123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 |
- package service
- import (
- "fmt"
- "sort"
- "strconv"
- "crazy-fox-backend-api/utils"
- "crazy-fox-backend-api/config"
- "crazy-fox-backend-api/model"
- "crazy-fox-backend-api/utils/uniqid"
- "github.com/dablelv/go-huge-util/conv"
- "github.com/jmoiron/sqlx/types"
- jsoniter "github.com/json-iterator/go"
- "github.com/pkg/errors"
- )
- type actRank struct{}
- // 展示数据处理
- func (This *actRank) handleActShow(confInfo *model.ActConfInfo) (types.JSONText, error) {
- rewardPro, err := This.formatRankRewardProShow(confInfo.RewardPro)
- if err != nil {
- return nil, errors.WithStack(err)
- }
- extraData, err := This.formatRankExtraDataShow(confInfo)
- if err != nil {
- return nil, errors.WithStack(err)
- }
- ExtraConf := model.ExtraConf{
- Reward: confInfo.Reward,
- ExtraReward: confInfo.ExtraReward,
- RewardConf: confInfo.RewardConf,
- RewardPro: rewardPro,
- ExtraData: extraData,
- }
- return jsoniter.Marshal(ExtraConf)
- }
- // 保存数据处理
- func (This *actRank) handleActSave(confInfo *model.ActConfInfo) error {
- var rewardMap model.ExtraConf
- var err error
- if err = jsoniter.Unmarshal(confInfo.ActShowConf, &rewardMap); err != nil {
- return errors.Wrap(err, "锦标赛Json解析失败")
- }
- // 格式化奖励数据
- if confInfo.RewardPro, err = This.formatRankRewardPro(rewardMap.RewardPro); err != nil {
- return errors.Wrap(err, "格式化奖励数据")
- }
- // 格式化收集积分配置
- if confInfo.RewardConf, err = This.formatRankRewardConf(confInfo.Type, rewardMap.RewardConf); err != nil {
- return errors.Wrap(err, "格式化收集积分配置")
- }
- // 格式化分房与机器人配置
- if confInfo.ExtraData, err = This.formatRankExtraData(confInfo.Type, rewardMap.ExtraData); err != nil {
- return errors.Wrap(err, "格式化分房与机器人配置")
- }
- return nil
- }
- // 分层数据处理
- func (This *actRank) handleActRewardSection(confInfo *model.ActConfInfo, maps ...map[string]any) error {
- var repoConfMap map[int64]model.RankRewardRepoConf
- if err := jsoniter.Unmarshal(confInfo.RewardPro, &repoConfMap); err != nil {
- return errors.Wrap(err, "锦标赛 rewardPro 解析失败")
- }
- conditionMap, rewardMap := maps[0], maps[1]
- for idx1, item1 := range repoConfMap {
- for idx2, item2 := range item1.Stages {
- for idx3, item3 := range item2.Stages {
- stageKey := fmt.Sprintf("%d_%d_%d", idx1, idx2, idx3)
- conditionMap[stageKey] = Activity.buildStageCondition(
- model.LvRange{LvStart: item1.Start, LvEnd: item1.End},
- model.SpinsRange{SpinsStart: item2.Start, SpinsEnd: item2.End},
- item3.SsGroup,
- )
- rewardMap[stageKey] = item3.Stages
- }
- }
- }
- return nil
- }
- // 导入数据处理
- func (This *actRank) handleActImport(detailInfo *model.ActDetailInfo, excelInfo [][][]string) (json types.JSONText, err error) {
- isProgress := false // 是否为有进度活动
- if utils.InSlice(detailInfo.Type, []string{config.ActRank, config.ActBuildRank}) {
- isProgress = true
- }
- sheetLen := utils.Ternary(isProgress, 8, 7)
- if len(excelInfo) != sheetLen {
- return json, errors.New("奖励配置异常")
- }
- isBuildRank := true // 是否为建筑锦标赛
- if utils.InSlice(detailInfo.Type, []string{config.ActRank, config.ActRank2}) {
- isBuildRank = false
- }
- sheet2Array := excelInfo[1]
- sheet3Array := excelInfo[2]
- sheet4Array := excelInfo[3]
- sheet5Array := excelInfo[4]
- sheet6Array := excelInfo[5]
- sheet7Array := excelInfo[6]
- extraConf := model.ExtraConf{}
- if isBuildRank {
- // 建筑锦标赛积分配置
- if extraConf.RewardConf, err = This.parseBuildRankScoreSheet(sheet2Array); err != nil {
- return json, errors.WithStack(err)
- }
- } else {
- // 锦标赛积分配置
- if extraConf.RewardConf, err = This.parseRankScoreSheet(sheet2Array); err != nil {
- return json, errors.WithStack(err)
- }
- }
- // 锦标赛房间配置
- if extraConf.ExtraData, err = This.parseRankExtraDataSheet(isBuildRank, sheet3Array, sheet4Array, sheet5Array); err != nil {
- return json, errors.WithStack(err)
- }
- // 锦标赛奖励配置
- rewardSheetArr := [][][]string{sheet6Array, sheet7Array}
- if isProgress {
- rewardSheetArr = append(rewardSheetArr, excelInfo[7])
- }
- if extraConf.RewardPro, err = This.parseRankRewardProSheet(rewardSheetArr); err != nil {
- return json, errors.WithStack(err)
- }
- if json, err = jsoniter.Marshal(extraConf); err != nil {
- return json, errors.Wrap(err, "锦标赛配置序列化失败")
- }
- return
- }
- func (This *actRank) formatRankRewardProShow(rewardPro types.JSONText) (types.JSONText, error) {
- var confMap map[int64]model.RankRewardRepoConf
- if err := jsoniter.Unmarshal(rewardPro, &confMap); err != nil {
- return nil, errors.Wrap(err, "锦标赛 rewardPro解析失败")
- }
- var rewardProArray []model.RankRewardShowConf
- for lvIdx, lvStages := range confMap {
- for spinIdx, spinsStages := range lvStages.Stages {
- for ssGroupIdx, ssGroupStages := range spinsStages.Stages {
- rewardProArray = append(rewardProArray, model.RankRewardShowConf{
- Idx: Activity.buildLayerOrderId(lvIdx, spinIdx, ssGroupIdx),
- LvRange: model.LvRange{LvStart: lvStages.Start, LvEnd: lvStages.End},
- SpinsRange: model.SpinsRange{SpinsStart: spinsStages.Start, SpinsEnd: spinsStages.End},
- SsGroup: ssGroupStages.SsGroup,
- RankRewardShow: model.RankRewardShow{
- Ranks: utils.MapValues(ssGroupStages.Stages.Ranks, true),
- Stages: utils.MapValues(ssGroupStages.Stages.Stages, true),
- },
- })
- }
- }
- }
- sort.SliceStable(rewardProArray, func(i, j int) bool { return rewardProArray[i].Idx < rewardProArray[j].Idx })
- return jsoniter.Marshal(rewardProArray)
- }
- func (This *actRank) formatRankExtraDataShow(confInfo *model.ActConfInfo) (types.JSONText, error) {
- var dataRepo model.RankExtraDataRepo
- if err := jsoniter.Unmarshal(confInfo.ExtraData, &dataRepo); err != nil {
- return nil, errors.Wrap(err, "锦标赛 extraData 解析失败")
- }
- dataShow := model.RankExtraDataShow{
- RankExtraData: dataRepo.RankExtraData,
- Robot: utils.MapValues(dataRepo.Robot, true),
- }
- // 锦标赛版本兼容
- if utils.InSlice(confInfo.Type, []string{config.ActRank, config.ActRank2}) {
- dataShow.RoomAllotConf = This.formatRankRoomAllotConf(dataRepo)
- }
- return jsoniter.Marshal(dataShow)
- }
- func (This *actRank) formatRankRoomAllotConf(dataRepo model.RankExtraDataRepo) (showConfArr []model.RankRoomAllotShowConf) {
- if utils.IsEmpty(dataRepo.RoomAllotConf) {
- allotStage := make([]model.RankRoomAllotStage, 0, len(dataRepo.SpinsSet))
- for i := 0; i < len(dataRepo.SpinsSet)-1; i++ {
- allotStage = append(allotStage, model.RankRoomAllotStage{
- SpinsRange: model.SpinsRange{
- SpinsStart: dataRepo.SpinsSet[i],
- SpinsEnd: dataRepo.SpinsSet[i+1] - 1,
- },
- RobotStop: dataRepo.SpinsSetSpins[i],
- })
- }
- dataRepo.RoomAllotConf = []model.RankRoomAllotRepoConf{
- {
- LvRange: model.LvRange{
- LvStart: 0,
- LvEnd: 999999999,
- },
- Stages: allotStage,
- },
- }
- }
- for _, item1 := range dataRepo.RoomAllotConf {
- for _, item2 := range item1.Stages {
- showConfArr = append(showConfArr, model.RankRoomAllotShowConf{
- LvRange: item1.LvRange,
- SpinsRange: item2.SpinsRange,
- RobotStop: item2.RobotStop,
- })
- }
- }
- return
- }
- // 格式化奖励数据
- func (This *actRank) formatRankRewardPro(rewardProJson types.JSONText) (types.JSONText, error) {
- var (
- err error
- rankRwdPro []model.RankRewardShowConf
- rankRwdProRepo = map[int64]model.RankRewardRepoConf{}
- unique = uniqid.GetUniqId()
- )
- defer uniqid.DelMapByUniqId(unique)
- if err = jsoniter.Unmarshal(rewardProJson, &rankRwdPro); err != nil {
- return nil, errors.Wrap(err, "锦标赛Json解析失败")
- }
- for _, one := range rankRwdPro {
- idxes := uniqid.GetStageIdx(unique, one.LvRange, one.SpinsRange, one.SsGroup)
- lvIdx, spinIdx, ssIdx := idxes[0], idxes[1], idxes[2]
- if _, Ok := rankRwdProRepo[lvIdx]; !Ok {
- rankRwdProRepo[lvIdx] = model.RankRewardRepoConf{
- StartEnd: model.StartEnd{Start: one.LvStart, End: one.LvEnd},
- Stages: map[int64]model.RankRewardSpinsStage{},
- }
- }
- if _, Ok := rankRwdProRepo[lvIdx].Stages[spinIdx]; !Ok {
- rankRwdProRepo[lvIdx].Stages[spinIdx] = model.RankRewardSpinsStage{
- StartEnd: model.StartEnd{Start: one.SpinsStart, End: one.SpinsEnd},
- Stages: map[int64]model.RankRewardSsGroupStage{},
- }
- }
- if _, Ok := rankRwdProRepo[lvIdx].Stages[spinIdx].Stages[ssIdx]; !Ok {
- rankRwdProRepo[lvIdx].Stages[spinIdx].Stages[ssIdx] = model.RankRewardSsGroupStage{
- SsGroup: one.SsGroup,
- Stages: model.RankRewardStage{
- Ranks: utils.Slice2Map(one.Ranks),
- Stages: utils.Slice2Map(one.Stages),
- },
- }
- }
- }
- return jsoniter.Marshal(rankRwdProRepo)
- }
- // 格式化收集积分配置
- func (This *actRank) formatRankRewardConf(actType string, rewardConfJson types.JSONText) (types.JSONText, error) {
- var rankRewardConf any
- switch actType {
- case config.ActRank, config.ActRank2:
- rankRewardConf = model.RankCollectConf{}
- case config.ActBuildRank, config.ActBuildRank2:
- rankRewardConf = model.BuildRankScoreConf{}
- default:
- return nil, errors.Wrap(nil, "活动类型异常:"+actType)
- }
- var err error
- if err = jsoniter.Unmarshal(rewardConfJson, &rankRewardConf); err != nil {
- return nil, errors.Wrap(err, "锦标赛Json解析失败")
- }
- return jsoniter.Marshal(rankRewardConf)
- }
- // 格式化分房与机器人配置
- func (This *actRank) formatRankExtraData(actType string, extraDataJson types.JSONText) (types.JSONText, error) {
- var dataShow model.RankExtraDataShow
- if err := jsoniter.Unmarshal(extraDataJson, &dataShow); err != nil {
- return nil, errors.Wrap(err, "锦标赛Json解析失败")
- }
- extraDataRepo := model.RankExtraDataRepo{
- RankExtraData: dataShow.RankExtraData,
- Robot: utils.Slice2Map(dataShow.Robot),
- RoomAllotConf: This.mapParseRankRoomAllotConf(dataShow.RoomAllotConf),
- }
- extraDataRepo.SetType = 2
- if utils.InSlice(actType, []string{config.ActRank, config.ActRank2}) {
- extraDataRepo.SetType = 10
- }
- return jsoniter.Marshal(extraDataRepo)
- }
- // 排名奖励
- func (This *actRank) parseRanksReward(sheet [][]string) (map[int64][]model.RankRanksReward, error) {
- var (
- err error
- rewardsMap = map[int64][]model.RankRanksReward{}
- )
- for i := 1; i < len(sheet); i++ {
- var (
- one = model.RankRanksReward{}
- id int64
- reward = make([]model.ExcelPrize, 6)
- )
- if err = utils.DestructAssign(sheet[i], &id, &one.RankPos, &reward); err != nil {
- return nil, errors.Wrap(err, fmt.Sprintf("第%d行 解析出错", i+1))
- }
- if one.Prize, err = Props.MultiParseActPrize(reward); err != nil {
- return nil, errors.WithStack(err)
- }
- rewardsMap[id] = append(rewardsMap[id], one)
- }
- return rewardsMap, nil
- }
- // 阶段奖励
- func (This *actRank) parseStagesReward(sheetInfo [][]string) (map[int64][]model.RankStageReward, error) {
- var (
- reward = model.RankStageReward{}
- err error
- mapIdx int64
- rewardsMap = map[int64][]model.RankStageReward{}
- )
- excelPrizes := make([]model.ExcelPrize, 6, 6)
- for i := 1; i < len(sheetInfo); i++ {
- if err := utils.DestructAssign(sheetInfo[i], &mapIdx, &reward.Stage, &reward.ProgressBarId, &reward.StepNum, &excelPrizes); err != nil {
- return nil, errors.Wrap(err, fmt.Sprintf("第%d行", i+1))
- }
- if reward.Prize, err = Props.MultiParseActPrize(excelPrizes); err != nil {
- return nil, err
- }
- rewardsMap[mapIdx] = append(rewardsMap[mapIdx], reward)
- }
- return rewardsMap, nil
- }
- // 锦标赛积分配置
- func (This *actRank) parseRankScoreSheet(sheet [][]string) (types.JSONText, error) {
- rewardConf := model.RankCollectConf{}
- for _, line := range sheet {
- var (
- tag string
- val int64
- )
- if err := utils.DestructAssign(line, &tag, &val); err != nil {
- return nil, errors.WithStack(err)
- }
- switch tag {
- case config.CollectTypeAttackSuccessImportText:
- rewardConf.AttackSuccess = val
- case config.CollectTypeAttackBreakImportText:
- rewardConf.AttackBreak = val
- case config.CollectTypeStealSuccessImportText:
- rewardConf.StealSuccess = val
- case config.CollectTypeStealBreakImportText:
- rewardConf.StealBreak = val
- case config.CollectTypeThreeHitImportText:
- rewardConf.ThreeHit = val
- }
- }
- return jsoniter.Marshal(rewardConf)
- }
- // 建筑锦标赛积分配置
- func (This *actRank) parseBuildRankScoreSheet(sheet [][]string) (types.JSONText, error) {
- rewardConf := model.BuildRankRewardConf{}
- if sheet[0][0] == config.BuildRankMinScoreImportText {
- rewardConf.MinScore = conv.ToAny[int64](sheet[0][1])
- }
- rewardConf.ActionConfig = make([]model.BuildRankScoreConf, 0, len(sheet))
- for i := 2; i < len(sheet); i++ {
- one := model.BuildRankScoreConf{}
- if err := utils.DestructAssign(sheet[i], &one.MinLv, &one.MaxLv, &one.SingleGet[0], &one.SingleGet[1]); err != nil {
- return nil, errors.WithStack(err)
- }
- rewardConf.ActionConfig = append(rewardConf.ActionConfig, one)
- }
- return jsoniter.Marshal(rewardConf)
- }
- // 锦标赛分房间配置
- func (This *actRank) parseRankExtraDataSheet(isBuildRank bool, allotSheet, robotSheet, limitSheet [][]string) (types.JSONText, error) {
- var err error
- extraData := model.RankExtraDataShow{}
- // 配置版本
- extraData.SetType = int64(utils.Ternary(isBuildRank, 2, 10))
- // 房间分配配置
- if isBuildRank {
- if extraData.UserLvSet, extraData.UserLvSetRobotStop, err = This.parseBuildRankRoomAllotSheet(allotSheet); err != nil {
- return nil, errors.WithStack(err)
- }
- } else {
- if extraData.RoomAllotConf, err = This.parseRankRoomAllotSheet(allotSheet); err != nil {
- return nil, errors.WithStack(err)
- }
- }
- // 机器人配置
- if extraData.Robot, err = This.parseRankRobotSheet(robotSheet); err != nil {
- return nil, errors.WithStack(err)
- }
- // 人数限制配置
- if extraData.RankLimit, err = This.parseRankLimitSheet(limitSheet); err != nil {
- return nil, errors.WithStack(err)
- }
- return jsoniter.Marshal(extraData)
- }
- // 房间分配配置
- func (This *actRank) parseRankRoomAllotSheet(sheet [][]string) ([]model.RankRoomAllotShowConf, error) {
- allotConfArr := make([]model.RankRoomAllotShowConf, 0, len(sheet))
- for i := 1; i < len(sheet); i++ {
- var one model.RankRoomAllotShowConf
- if err := utils.DestructAssign(sheet[i], &one.LvRange, &one.SpinsRange, &one.RobotStop); err != nil {
- return nil, errors.WithStack(err)
- }
- allotConfArr = append(allotConfArr, one)
- }
- return allotConfArr, nil
- }
- // 房间分配配置
- func (This *actRank) parseBuildRankRoomAllotSheet(sheet [][]string) ([]int64, []int64, error) {
- userArr := make([]int64, 0, len(sheet))
- robotArr := make([]int64, 0, len(sheet))
- for i := 1; i < len(sheet); i++ {
- var user, robot int64
- if err := utils.DestructAssign(sheet[i], &user, &robot); err != nil {
- return nil, nil, errors.WithStack(err)
- }
- userArr = append(userArr, user)
- robotArr = append(robotArr, robot)
- }
- return userArr, robotArr, nil
- }
- // 机器人配置
- func (This *actRank) parseRankRobotSheet(sheet [][]string) ([]model.RankRobot, error) {
- robotArr := make([]model.RankRobot, 0, len(sheet))
- for i := 1; i < len(sheet); i++ {
- var one model.RankRobot
- if err := utils.DestructAssign(sheet[i], &one.Id, &one.Pro, &one.Num, &one.Co1, &one.Co2); err != nil {
- return nil, errors.WithStack(err)
- }
- robotArr = append(robotArr, one)
- }
- return robotArr, nil
- }
- // 人数限制配置
- func (This *actRank) parseRankLimitSheet(sheet [][]string) ([]model.RankLimit, error) {
- limitArr := make([]model.RankLimit, 0, len(sheet))
- for i := 1; i < len(sheet); i++ {
- var one model.RankLimit
- if err := utils.DestructAssign(sheet[i], &one.Time, &one.Limit); err != nil {
- return nil, err
- }
- limitArr = append(limitArr, one)
- }
- return limitArr, nil
- }
- // 奖励配置
- func (This *actRank) parseRankRewardProSheet(sheetArr [][][]string) (types.JSONText, error) {
- if !utils.InSlice(len(sheetArr), []int{2, 3}) {
- return nil, errors.New("奖励配置异常")
- }
- var (
- rankRwdPro []model.RankRewardShowConf
- stagesMap []model.ThreeLayer
- rankRewards map[int64][]model.RankRanksReward
- stageRewards map[int64][]model.RankStageReward
- err error
- )
- if stagesMap, err = Activity.parseThreeLayerConf(sheetArr[0]); err != nil {
- return nil, errors.WithStack(err)
- }
- if rankRewards, err = This.parseRanksReward(sheetArr[1]); err != nil {
- return nil, errors.WithStack(err)
- }
- if len(sheetArr) == 3 {
- if stageRewards, err = This.parseStagesReward(sheetArr[2]); err != nil {
- return nil, errors.WithStack(err)
- }
- if len(stageRewards) == 0 {
- return nil, errors.New("未配置阶段奖励")
- }
- }
- rankRwdPro = make([]model.RankRewardShowConf, 0, len(stagesMap))
- for _, layer := range stagesMap {
- rankReward, Ok := rankRewards[layer.Id]
- if !Ok {
- return nil, errors.New(strconv.Itoa(int(layer.Id)) + ":未配置排行奖励")
- }
- rankRwdProItem := model.RankRewardShowConf{
- Idx: layer.Id,
- LvRange: layer.LvRange,
- SpinsRange: layer.SpinsRange,
- SsGroup: layer.SsGroup,
- RankRewardShow: model.RankRewardShow{Ranks: rankReward},
- }
- if len(stageRewards) > 0 {
- stageReward, Ok := stageRewards[layer.Id]
- if !Ok {
- return nil, errors.New(strconv.Itoa(int(layer.Id)) + ":未配置阶段奖励")
- }
- rankRwdProItem.Stages = stageReward
- }
- rankRwdPro = append(rankRwdPro, rankRwdProItem)
- }
- return jsoniter.Marshal(rankRwdPro)
- }
- // 房间分区配置解析
- func (This *actRank) mapParseRankRoomAllotConf(conf []model.RankRoomAllotShowConf) []model.RankRoomAllotRepoConf {
- var repoConfArr []model.RankRoomAllotRepoConf
- for _, one := range conf {
- sameLvRange := false
- for i, repoConf := range repoConfArr {
- if repoConf.LvRange == one.LvRange {
- repoConfArr[i].Stages = append(repoConfArr[i].Stages, model.RankRoomAllotStage{
- SpinsRange: one.SpinsRange,
- RobotStop: one.RobotStop,
- })
- sameLvRange = true
- break
- }
- }
- if !sameLvRange {
- repoConfArr = append(repoConfArr, model.RankRoomAllotRepoConf{
- LvRange: one.LvRange,
- Stages: []model.RankRoomAllotStage{
- {
- SpinsRange: one.SpinsRange,
- RobotStop: one.RobotStop,
- },
- },
- })
- }
- }
- return repoConfArr
- }
|