island.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. package service
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "crazy-fox-backend-api/config"
  7. "crazy-fox-backend-api/model"
  8. "crazy-fox-backend-api/repo"
  9. "crazy-fox-backend-api/repo/okeys"
  10. "crazy-fox-backend-api/utils"
  11. jsoniter "github.com/json-iterator/go"
  12. "github.com/pkg/errors"
  13. "github.com/xuri/excelize/v2"
  14. )
  15. // islandService 岛屿模块服务
  16. type islandService struct{}
  17. func (This *islandService) BasicConf(req model.PageInfo) ([]model.TCoinConfig, int64) {
  18. return repo.SearchOnePage[model.TCoinConfig](req.Page, req.PageSize, "")
  19. }
  20. func (This *islandService) BasicConfEdit(req []model.TCoinConfig) error {
  21. if len(req) == 0 {
  22. return errors.New("配置列表为空")
  23. }
  24. if _, err := repo.Upsert(req); err != nil {
  25. return errors.WithStack(err)
  26. }
  27. cacheMap := make(map[string]model.TCoinConfig, len(req))
  28. for _, island := range req {
  29. cacheMap[strconv.FormatInt(island.LevelId, 10)] = island
  30. }
  31. // 更新缓存
  32. cache, err := This.buildIslandConfCache(cacheMap)
  33. if err != nil {
  34. return errors.WithStack(err)
  35. }
  36. repo.HMSetCache(okeys.LevelConf(), cache)
  37. return nil
  38. }
  39. func (This *islandService) buildIslandConfCache(confMap map[string]model.TCoinConfig) (cacheMap map[string]any, err error) {
  40. cacheMap = make(map[string]any, len(confMap))
  41. for s, conf := range confMap {
  42. one := model.IslandBasicCache{
  43. IslandBasic: conf.IslandBasic,
  44. MinMoney: conf.CoinConfig[0][0],
  45. MaxMoney: conf.CoinConfig[4][4],
  46. }
  47. one.CoinConfig, err = jsoniter.MarshalToString(conf.CoinConfig)
  48. if err != nil {
  49. return cacheMap, errors.WithStack(err)
  50. }
  51. one.Reward, err = jsoniter.MarshalToString(conf.Reward)
  52. if err != nil {
  53. return cacheMap, errors.WithStack(err)
  54. }
  55. for _, int64s := range conf.CoinConfig {
  56. for _, i3 := range int64s {
  57. one.SumMoney += i3
  58. }
  59. }
  60. cacheMap[s] = one
  61. }
  62. return cacheMap, err
  63. }
  64. func (This *islandService) handleBasicConfImport(excelInfo [][][]string) (err error) {
  65. if len(excelInfo) < 3 {
  66. return errors.New("工作表数量不匹配")
  67. }
  68. confArr, err := This.ParseSheet1(excelInfo[0])
  69. if err != nil {
  70. return errors.Wrap(err, "岛屿关卡多语言配置 工作表解析失败")
  71. }
  72. rewardMap, err := This.ParseSheet2(excelInfo[1])
  73. if err != nil {
  74. return errors.Wrap(err, "岛屿关卡奖励配置 工作表解析失败")
  75. }
  76. coinMap, err := This.ParseSheet3(excelInfo[2])
  77. if err != nil {
  78. return errors.Wrap(err, "岛屿关卡建造价格配置 工作表解析失败")
  79. }
  80. if err = This.packageConf(&confArr, rewardMap, coinMap); err != nil {
  81. return errors.Wrap(err, "岛屿关卡配置 拼装失败")
  82. }
  83. if err = This.BasicConfEdit(confArr); err != nil {
  84. return errors.Wrap(err, "岛屿关卡配置 更新失败")
  85. }
  86. return err
  87. }
  88. func (This *islandService) ParseSheet1(sheet [][]string) (confArr []model.TCoinConfig, err error) {
  89. confArr = make([]model.TCoinConfig, 0, len(sheet))
  90. for rowIdx := 1; rowIdx < len(sheet); rowIdx++ {
  91. var one model.TCoinConfig
  92. // 解析行配置
  93. if err = utils.DestructAssign(sheet[rowIdx], &one.LevelId, &one.IsLandLang); err != nil {
  94. return nil, errors.WithStack(err)
  95. }
  96. confArr = append(confArr, one)
  97. }
  98. return
  99. }
  100. func (This *islandService) ParseSheet2(sheet [][]string) (rewardMap map[int64][]model.PropPrize, err error) {
  101. prizes := make([]model.PropPrize, 0, 5)
  102. rewardMap = make(map[int64][]model.PropPrize, len(sheet))
  103. for rowIdx := 1; rowIdx < len(sheet); rowIdx++ {
  104. var (
  105. id int64
  106. rewardArr = make([]model.ExcelPrize, 5)
  107. )
  108. // 解析行配置
  109. if err = utils.DestructAssign(sheet[rowIdx], &id, &rewardArr); err != nil {
  110. return nil, errors.WithStack(err)
  111. }
  112. // 转换奖励格式
  113. if prizes, err = Props.MultiParsePropPrize(rewardArr); err != nil {
  114. return rewardMap, errors.WithStack(err)
  115. }
  116. rewardMap[id] = prizes
  117. }
  118. return rewardMap, err
  119. }
  120. func (This *islandService) ParseSheet3(sheet [][]string) (coinMap map[int64][5][5]int64, err error) {
  121. var curId int64
  122. var coin [5][5]int64
  123. coinMap = make(map[int64][5][5]int64, len(sheet))
  124. for rowIdx := 1; rowIdx < len(sheet); rowIdx++ {
  125. var (
  126. id int64
  127. ignore string
  128. )
  129. // 解析行配置
  130. if err = utils.DestructAssign(sheet[rowIdx], &id, &ignore, &coin[(rowIdx-1)%5]); err != nil {
  131. return coinMap, errors.WithStack(err)
  132. }
  133. if rowIdx%5 == 1 {
  134. curId = id
  135. }
  136. // 等级配置错误
  137. if id != curId {
  138. return coinMap, errors.New(fmt.Sprintf("第%d行,等级配置错误", rowIdx+1))
  139. }
  140. if rowIdx%5 == 0 {
  141. coinMap[id] = coin
  142. coin = [5][5]int64{}
  143. }
  144. }
  145. return coinMap, err
  146. }
  147. func (This *islandService) packageConf(confArr *[]model.TCoinConfig, rewardMap map[int64][]model.PropPrize, coinMap map[int64][5][5]int64) (err error) {
  148. var Ok bool
  149. for i := 0; i < len(*confArr); i++ {
  150. one := &(*confArr)[i]
  151. if one.Reward, Ok = rewardMap[one.LevelId]; !Ok {
  152. return errors.New(fmt.Sprintf("等级:%d,未配置奖励项", one.LevelId))
  153. }
  154. if one.CoinConfig, Ok = coinMap[one.LevelId]; !Ok {
  155. return errors.New(fmt.Sprintf("等级:%d,未配置建造价格项", one.LevelId))
  156. }
  157. one.PictureId = one.LevelId
  158. for _, prize := range one.Reward {
  159. switch prize.PropsId {
  160. case config.PropCoin:
  161. one.RewardCoin = prize.Num
  162. case config.PropSpin:
  163. one.RewardSpin = prize.Num
  164. }
  165. }
  166. }
  167. return
  168. }
  169. func (This *islandService) handleBasicConfExport(xlsx *excelize.File, fileName *string) (err error) {
  170. list := repo.Search[model.TCoinConfig]("")
  171. // 工作表1
  172. sheetName := "多语言配置"
  173. if err = xlsx.SetSheetName("Sheet1", sheetName); err != nil {
  174. return errors.WithStack(err)
  175. }
  176. if err = This.fillSheet1(xlsx, sheetName, list); err != nil {
  177. return err
  178. }
  179. // 工作表2
  180. sheetName = "奖励配置"
  181. if _, err = xlsx.NewSheet(sheetName); err != nil {
  182. return errors.WithStack(err)
  183. }
  184. if err = This.fillSheet2(xlsx, sheetName, list); err != nil {
  185. return err
  186. }
  187. // 工作表3
  188. sheetName = "建造价格配置"
  189. if _, err = xlsx.NewSheet(sheetName); err != nil {
  190. return errors.WithStack(err)
  191. }
  192. if err = This.fillSheet3(xlsx, sheetName, list); err != nil {
  193. return err
  194. }
  195. *fileName = "岛屿关卡基础配置"
  196. return err
  197. }
  198. func (This *islandService) fillSheet1(xlsx *excelize.File, sheetName string, list []model.TCoinConfig) (err error) {
  199. titles := []string{"关卡", "中文", "英文", "繁体", "法语", "德语", "西班牙语", "葡萄牙语", "泰语", "越南语", "挪威语", "印尼语",
  200. "罗马尼亚语", "马来西亚语", "意大利语", "波兰语"}
  201. if err = xlsx.SetSheetRow(sheetName, "A1", &titles); err != nil {
  202. return errors.WithStack(err)
  203. }
  204. for i, oneInfo := range list {
  205. rowSlice := utils.Destruct(oneInfo.LevelId, oneInfo.IsLandLang)
  206. if err = xlsx.SetSheetRow(sheetName, fmt.Sprintf("A%d", i+2), &rowSlice); err != nil {
  207. return errors.WithStack(err)
  208. }
  209. }
  210. return err
  211. }
  212. func (This *islandService) fillSheet2(xlsx *excelize.File, sheetName string, list []model.TCoinConfig) (err error) {
  213. titles := make([]string, 0, 5*3+1)
  214. titles = append(titles, "关卡")
  215. for i := 1; i <= 5; i++ {
  216. titles = append(titles, fmt.Sprintf("奖励%d", i), "是否固定值(非金币奖励均为固定值)", "数值(宝箱等部分奖励数量固定为1)")
  217. }
  218. if err = xlsx.SetSheetRow(sheetName, "A1", &titles); err != nil {
  219. return errors.WithStack(err)
  220. }
  221. var prizes []model.ExcelPrize
  222. for i, oneInfo := range list {
  223. prizes, err = Props.MultiParseExcelPrize(oneInfo.Reward)
  224. if err != nil {
  225. return errors.WithStack(err)
  226. }
  227. rowSlice := utils.Destruct(oneInfo.LevelId, prizes)
  228. if err = xlsx.SetSheetRow(sheetName, fmt.Sprintf("A%d", i+2), &rowSlice); err != nil {
  229. return errors.WithStack(err)
  230. }
  231. }
  232. return err
  233. }
  234. func (This *islandService) fillSheet3(xlsx *excelize.File, sheetName string, list []model.TCoinConfig) (err error) {
  235. titles := []string{"关卡ID", "物件", "1级", "2级", "3级", "4级", "5级"}
  236. if err = xlsx.SetSheetRow(sheetName, "A1", &titles); err != nil {
  237. return errors.WithStack(err)
  238. }
  239. buildName := []string{"建筑", "雕像", "风景", "生物", "科技"}
  240. rowId := 2
  241. for _, oneInfo := range list {
  242. for i2, int64s := range oneInfo.CoinConfig {
  243. rowSlice := []any{oneInfo.LevelId, buildName[i2], int64s[0], int64s[1], int64s[2], int64s[3], int64s[4]}
  244. if err = xlsx.SetSheetRow(sheetName, fmt.Sprintf("A%d", rowId), &rowSlice); err != nil {
  245. return errors.WithStack(err)
  246. }
  247. rowId++
  248. }
  249. }
  250. return err
  251. }
  252. func (This *islandService) ThemeConf(req model.PageInfo) ([]model.TMainBgConfig, int64) {
  253. list, total := repo.SearchOnePage[model.TMainBgConfig](req.Page, req.PageSize, "")
  254. for i := 0; i < len(list); i++ {
  255. list[i].Color1 = strings.ToUpper(list[i].Color1)
  256. list[i].Color2 = strings.ToUpper(list[i].Color2)
  257. }
  258. return list, total
  259. }
  260. func (This *islandService) ThemeConfEdit(req []model.TMainBgConfig) error {
  261. if len(req) == 0 {
  262. return errors.New("配置列表为空")
  263. }
  264. for i := 0; i < len(req); i++ {
  265. island := &req[i]
  266. island.Color1 = strings.ToUpper(island.Color1)
  267. island.Color2 = strings.ToUpper(island.Color2)
  268. }
  269. if _, err := repo.Upsert(req); err != nil {
  270. return errors.WithStack(err)
  271. }
  272. if err := This.updateThemeStatic(); err != nil {
  273. return errors.WithStack(err)
  274. }
  275. return nil
  276. }
  277. func (This *islandService) updateThemeStatic() (err error) {
  278. list := repo.Search[model.TMainBgConfig]("")
  279. if err = Config.SaveJson(list, "MainBgConfig"); err != nil {
  280. return errors.WithStack(err)
  281. }
  282. return
  283. }
  284. func (This *islandService) handleThemeImport(excelInfo [][][]string) (err error) {
  285. excelData := excelInfo[0]
  286. mulSpend := make([]model.TMainBgConfig, 0, len(excelData))
  287. for i := 1; i < len(excelData); i++ {
  288. var one model.TMainBgConfig
  289. if err = utils.DestructAssign(excelData[i], &one); err != nil {
  290. return errors.WithStack(err)
  291. }
  292. mulSpend = append(mulSpend, one)
  293. }
  294. if err = This.ThemeConfEdit(mulSpend); err != nil {
  295. return errors.WithStack(err)
  296. }
  297. return err
  298. }
  299. func (This *islandService) handleThemeExport(xlsx *excelize.File, fileName *string) (err error) {
  300. // 工作表1
  301. sheetName := "配置表"
  302. if err = xlsx.SetSheetName("Sheet1", sheetName); err != nil {
  303. return errors.WithStack(err)
  304. }
  305. titles := []string{"岛屿ID", "背景1", "背景1云朵色号", "背景2", "背景2云朵色号", "动画", "动画2"}
  306. if err = xlsx.SetSheetRow(sheetName, "A1", &titles); err != nil {
  307. return errors.WithStack(err)
  308. }
  309. list := repo.Search[model.TMainBgConfig]("")
  310. for i, oneInfo := range list {
  311. rowSlice := utils.Destruct(oneInfo)
  312. if err = xlsx.SetSheetRow(sheetName, fmt.Sprintf("A%d", i+2), &rowSlice); err != nil {
  313. return errors.WithStack(err)
  314. }
  315. }
  316. *fileName = "岛屿主题配置"
  317. return err
  318. }
  319. func (This *islandService) MaxLevelReward() (reward model.MaxIslandReward, err error) {
  320. content, err := Config.GetSystemConf(model.ItemTitle{Item: "Reward", Title: "maxLevel"})
  321. if err != nil {
  322. return reward, errors.WithStack(err)
  323. }
  324. if err = jsoniter.UnmarshalFromString(content, &reward); err != nil {
  325. return reward, errors.WithStack(err)
  326. }
  327. return
  328. }
  329. func (This *islandService) MaxLevelRewardEdit(req *model.MaxIslandReward) error {
  330. content, err := jsoniter.MarshalToString(req)
  331. if err != nil {
  332. return errors.WithStack(err)
  333. }
  334. sysConf := model.TSystemConfig{
  335. ItemTitle: model.ItemTitle{Item: "Reward", Title: "maxLevel"},
  336. Content: content,
  337. Memo: "最大关卡奖励",
  338. }
  339. if err = Config.UpdateSystemConf(sysConf); err != nil {
  340. return errors.WithStack(err)
  341. }
  342. return nil
  343. }