package campaignuser import ( "joybuywork/internal/consts/ckey" "joybuywork/internal/plugins/jsonm" "joybuywork/internal/repository/cache" "joybuywork/internal/repository/model" "joybuywork/internal/repository/mtype" "joybuywork/internal/repository/withdefault" "joybuywork/internal/service/provider" "joybuywork/internal/service/provider/cachecurd" "joybuywork/internal/utils" "joybuywork/internal/utils/logic" "joybuywork/internal/utils/timez" "joybuywork/internal/utils/verify" pb "joybuywork/proto/go_proto/w_campaign_user" "joybuywork/proto/go_proto/workerr" "fmt" ) const ( childStatusWait = iota + 1 // 待完成 childStatusDone // 已完成 ) type Child struct { logic.Logic Req *pb.ChildReq Res *pb.ChildRes recordMap map[int32]int64 } func (s *Child) Run() error { return logic.Run(s) } func (s *Child) Exec() (err error) { cpn, user, err := s.user() if err != nil { return } return s.child(cpn, user) } func (s *Child) user() (cpn *model.FissionCampaign, user *model.FissionUser, err error) { cpn, err = cache.NewCampaign(s.Ctx).FindById(s.Req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } user, err = cache.NewFissionUser(s.Ctx, s.Req.GetCampaignId()).FindById(s.Req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } s.recordMap = make(map[int32]int64) return } func (s *Child) child(cpn *model.FissionCampaign, user *model.FissionUser) (err error) { m := s.GetDao().FissionCampaignChild list, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(cpn.ID)).Find() if err != nil { err = s.BE().MysqlError(err) return } tz := provider.NewCampaignTZ(s.Ctx, cpn, user.LangMark) for _, child := range list { switch child.Type { case mtype.FissionCampaignChildTypeBlind: err = s._blind(user, child, tz) if err != nil { return } case mtype.FissionCampaignChildTypeInvite: err = s._invite(user, child, tz) if err != nil { return } case mtype.FissionCampaignChildTypeSign: err = s._sign(user, child, tz) if err != nil { return } case mtype.FissionCampaignChildTypeLucky: err = s._lucky(user, child, tz) if err != nil { return } case mtype.FissionCampaignChildTypeTask: } } return s._setRecord(cpn.ProjectID, cpn.ID, user.LangMark) } func (s *Child) _lucky(user *model.FissionUser, child *model.FissionCampaignChild, tz *provider.CampaignTZ) (err error) { cpn, err := cache.NewCampaign(s.Ctx).FindById(child.ChildID) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.Status == mtype.FissionCampaignStatusCancel || cpn.IsDel == mtype.Yes { return } player, err := s._player(user, cpn) if err != nil { return } m := s.GetDao().FissionCampaignReward list, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(child.ChildID), m.IsDel.Eq(mtype.No)).Order(m.IsSuper.Desc(), m.ID).Find() if err != nil { err = s.BE().MysqlError(err) return } _, start, end := timez.GMTStartAndEndTs(tz.GetTz()) status := utils.Ternary[int32](verify.Inside(player.LastDone, start, end), childStatusDone, childStatusWait) var getRewardsIds = utils.SplitToInt64(player.LuckyReward, ",") var getMap = make(map[int64]struct{}, len(getRewardsIds)) for _, id := range getRewardsIds { getMap[id] = struct{}{} } s.Res.Lucky = &pb.ChildRes_Lucky{ Open: 1, Status: status, Rewards: s._reward(list, cpn.ProjectID, user.LangMark, getMap), ChildHashId: cpn.HashID, } if status == 2 { s.recordMap[mtype.FissionCampaignChildTypeLucky] = player.RecordID } return } func (s *Child) _sign(user *model.FissionUser, child *model.FissionCampaignChild, tz *provider.CampaignTZ) (err error) { cpn, err := cache.NewCampaign(s.Ctx).FindById(child.ChildID) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.Status == mtype.FissionCampaignStatusCancel || cpn.IsDel == mtype.Yes { return } player, err := s._player(user, cpn) if err != nil { return } m := s.GetDao().FissionCampaignReward list, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(child.ChildID), m.IsDel.Eq(mtype.No)).Order(m.SignDay).Find() if err != nil { err = s.BE().MysqlError(err) return } conf, err := cache.NewCampaignConfig(s.Ctx).FindByCampaignId(cpn.ID) if err != nil { err = s.BE().CacheError(err) return } _, start, end := timez.GMTStartAndEndTs(tz.GetTz()) var l int var status int32 = childStatusWait var getMap = make(map[int64]struct{}) if verify.Inside(player.LastDone, start, end) { // 今天已经签到了 status = childStatusDone signDay := player.SignDay if conf.PlayType == mtype.FissionCampaignConfigPlayTypeContinue { signDay = player.ContinueSign } l = int(signDay) % len(list) if l == 0 { l = len(list) } } else { // 今天没签到 signDay := player.SignDay if conf.PlayType == mtype.FissionCampaignConfigPlayTypeContinue { //连续签到,如果没连续签到,签到天数为0 signDay = utils.Ternary(verify.Inside(player.LastDone, start-86400, end-86400), player.ContinueSign, 0) } l = int(signDay) % len(list) } for i := 0; i < l; i++ { getMap[list[i].ID] = struct{}{} } s.Res.Sign = &pb.ChildRes_Sign{ Open: 1, Status: status, Rewards: s._reward(list, cpn.ProjectID, user.LangMark, getMap), Record: nil, RewardId: player.RewardID, ChildHashId: cpn.HashID, } if status == childStatusDone { s.recordMap[mtype.FissionCampaignChildTypeSign] = player.RecordID } return } func (s *Child) _invite(user *model.FissionUser, child *model.FissionCampaignChild, tz *provider.CampaignTZ) (err error) { cpn, err := cache.NewCampaign(s.Ctx).FindById(child.ChildID) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || !s._checkRun(cpn.TStart, 0, tz.GetTz()) || cpn.IsDel == mtype.Yes { return } player, err := s._player(user, cpn) if err != nil { return } m := s.GetDao().FissionCampaignReward list, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(child.ChildID), m.IsDel.Eq(mtype.No)).Order(m.Step).Find() if err != nil { err = s.BE().MysqlError(err) return } ranker, err := cachecurd.NewRanker(s.Ctx, ckey.FissionChildRank(cpn.ID), cachecurd.SetChildBuild(cpn.ID, cpn.ChildType)) if err != nil { err = s.BE().CacheError(err) return } rankList, err := ranker.GetRank(10) if err != nil { err = s.BE().CacheError(err) return } var status int32 = childStatusWait if player.RecordID > 0 || cpn.Status == mtype.FissionCampaignStatusCancel { status = childStatusDone } if player.RecordID > 0 { s.recordMap[mtype.FissionCampaignChildTypeInvite] = player.RecordID } s.Res.Invite = &pb.ChildRes_Invite{ Open: 1, Status: status, Start: cpn.TStart, End: cpn.TEnd, InviteNum: player.InviteNum, Rank: "", RankList: make([]*pb.ChildRes_RankOne, 10), ChildHashId: cpn.HashID, } rewards := s._reward(list, cpn.ProjectID, user.LangMark, nil) var userIds []int64 for _, member := range rankList { userIds = append(userIds, utils.StrToInt64(member.UserId)) } userMap, err := s._userMap(userIds) if err != nil { return } rankL := len(rankList) rewardL := len(list) var stepS = rewardL // 排行榜阶梯切割点 if rewardL > 4 { stepS = 10 } for i := 0; i < 10; i++ { var rankOne = &cachecurd.RankMember{} if i < rankL { rankOne = rankList[i] } one := &pb.ChildRes_RankOne{ SubUserId: userMap[utils.StrToInt64(rankOne.UserId)], InviteNum: int64(rankOne.Score), } var rewardOne = &pb.ChildRes_Reward{} if i < stepS { if i >= 4 { rewardOne = rewards[4] } else { rewardOne = rewards[i] } } one.RewardId = rewardOne.RewardId one.Title = rewardOne.Title one.Img = rewardOne.Img one.PropMark = rewardOne.PropMark one.RewardNum = rewardOne.RewardNum s.Res.Invite.RankList[i] = one } if player.InviteNum == 0 { return } var rank int64 rank, err = ranker.GetMemberRank(fmt.Sprint(player.UserID)) if err != nil { err = s.BE().CacheError(err) return } if rank > 9999 { s.Res.Invite.Rank = "10000+" } else { s.Res.Invite.Rank = fmt.Sprintf("%d", rank+1) } if status == childStatusDone { return } var between [][2]int64 for i := 0; i < rewardL; i++ { switch i { case 6: between = append(between, [2]int64{100, 9999}) case 5: between = append(between, [2]int64{10, 99}) case 4: between = append(between, [2]int64{4, 9}) default: between = append(between, [2]int64{int64(i), int64(i)}) } } for i, group := range between { if verify.Inside(rank, group[0], group[1]) { s.Res.Invite.Record = &pb.ChildRes_Record{ RewardId: rewards[i].RewardId, Title: rewards[i].Title, KvData: nil, Img: rewards[i].Img, PropMark: rewards[i].PropMark, RewardNum: rewards[i].RewardNum, IsSuper: rewards[i].IsSuper, } } } return } func (s *Child) _blind(user *model.FissionUser, child *model.FissionCampaignChild, tz *provider.CampaignTZ) (err error) { cpn, err := cache.NewCampaign(s.Ctx).FindById(child.ChildID) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.Status == mtype.FissionCampaignStatusCancel || cpn.IsDel == mtype.Yes { return } player, err := s._player(user, cpn) if err != nil { return } _, start, end := timez.GMTStartAndEndTs(tz.GetTz()) status := utils.Ternary[int32](verify.Inside(player.LastDone, start, end), childStatusDone, childStatusWait) s.Res.Blind = &pb.ChildRes_Blind{ Open: 1, Status: status, ChildHashId: cpn.HashID, } if status == childStatusDone { s.recordMap[mtype.FissionCampaignChildTypeBlind] = player.RecordID } return } func (s *Child) _setRecord(projectId, cpnId int64, langMark string) (err error) { if len(s.recordMap) == 0 { return } var recordIds []int64 for _, v := range s.recordMap { recordIds = append(recordIds, v) } m := s.GetDao().FissionRewardRecord.SubTable(cpnId) list, err := m.WithContext(s.Ctx).Where(m.ID.In(recordIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } var rewardIds, brid []int64 var bMap = make(map[int64]struct{}) var recordMap = make(map[int64]*model.FissionRewardRecord) var rewardMap = make(map[int64]*model.FissionCampaignReward) for _, v := range list { if _, ok := bMap[v.BaseRewardID]; !ok && v.BaseRewardID > 0 { bMap[v.BaseRewardID] = struct{}{} brid = append(brid, v.BaseRewardID) } recordMap[v.ID] = v if _, ok := rewardMap[v.RewardID]; !ok { rewardMap[v.RewardID] = nil rewardIds = append(rewardIds, v.RewardID) } } rewardM := s.GetDao().FissionCampaignReward rewards, err := rewardM.WithContext(s.Ctx).Where(rewardM.ID.In(rewardIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } for _, v := range rewards { rewardMap[v.ID] = v } preward, _ := provider.NewRewards(s.Ctx, projectId, brid...) for t, id := range s.recordMap { record, ok := recordMap[id] if !ok { continue } switch t { case mtype.FissionCampaignChildTypeBlind: s.Res.Blind.Record = s._record(record, preward, rewardMap, langMark) case mtype.FissionCampaignChildTypeInvite: s.Res.Invite.Record = s._record(record, preward, rewardMap, langMark) case mtype.FissionCampaignChildTypeSign: s.Res.Sign.Record = s._record(record, preward, rewardMap, langMark) case mtype.FissionCampaignChildTypeLucky: s.Res.Lucky.Record = s._record(record, preward, rewardMap, langMark) case mtype.FissionCampaignChildTypeTask: } } return } func (s *Child) _record(record *model.FissionRewardRecord, preward *provider.Rewards, rewardMap map[int64]*model.FissionCampaignReward, langMark string) *pb.ChildRes_Record { if record.PropMark == mtype.FissionCampaignRewardPropMarkChance { return &pb.ChildRes_Record{ Id: record.ID, HashId: record.HashID, RewardId: record.RewardID, PropMark: record.PropMark, RewardNum: record.RewardNum, IsSuper: int32(rewardMap[record.RewardID].IsSuper), } } info, _ := preward.InfoAutoLang(record.BaseRewardID, langMark) var kvData = make([]*pb.ChildRes_KV, 0, len(info.KvData)) for _, v := range info.KvData { kvData = append(kvData, &pb.ChildRes_KV{ Key: v.Key, Value: v.Value, IsShow: v.IsShow, }) } return &pb.ChildRes_Record{ Id: record.ID, HashId: record.HashID, RewardId: record.RewardID, Title: info.Title, KvData: kvData, Img: info.ImgUrl, Contact: info.Contact, OpenToUse: info.OpenToUse, WebUrl: info.WebUrl, AppParam: info.AppParam, DyRewardType: info.DyRewardType, CustomRewardVal: record.CustomRewardVal, PropMark: record.PropMark, RewardNum: record.RewardNum, IsSuper: int32(rewardMap[record.RewardID].IsSuper), PcParam: info.PcParam, ReceiveType: info.ReceiveType, } } func (s *Child) _player(user *model.FissionUser, cpn *model.FissionCampaign) (player *model.FissionChildUser, err error) { player, err = cache.NewFissionChildUser(s.Ctx).FindByUniqIdx(user.ID, cpn.ID, cache.WithNilSet(func() ([]byte, error) { info := withdefault.FissionChildUser(&model.FissionChildUser{ PCpnID: cpn.Pid, CampaignID: cpn.ID, UserID: user.ID, ParentID: user.ParentID, ChildType: cpn.ChildType, }) err = s.GetDao().FissionChildUser.WithContext(s.Ctx).Create(info) if err != nil { return nil, err } return jsonm.Marshal(info) })) if err != nil { err = s.BE().CacheError(err) return } return } func (s *Child) _reward(list []*model.FissionCampaignReward, projectId int64, langMark string, getMap map[int64]struct{}) (rewards []*pb.ChildRes_Reward) { var brid []int64 var bMap = make(map[int64]struct{}) for _, v := range list { if _, ok := bMap[v.RewardID]; !ok && v.RewardID > 0 { bMap[v.RewardID] = struct{}{} brid = append(brid, v.RewardID) } } var preward *provider.Rewards if len(brid) > 0 { preward, _ = provider.NewRewards(s.Ctx, projectId, brid...) } for _, v := range list { var isGet int32 if getMap != nil { if _, ok := getMap[v.ID]; ok { isGet = 1 } } switch v.PropMark { case mtype.FissionCampaignRewardPropMarkChance: rewards = append(rewards, &pb.ChildRes_Reward{ RewardId: v.ID, PropMark: v.PropMark, RewardNum: v.RewardNum, IsSuper: int32(v.IsSuper), IsGet: isGet, }) default: if preward == nil { continue } info := preward.AutoLang(v.RewardID, langMark) rewards = append(rewards, &pb.ChildRes_Reward{ RewardId: v.ID, Title: info.Title, Img: info.ImgUrl, PropMark: v.PropMark, RewardNum: v.RewardNum, IsSuper: int32(v.IsSuper), IsGet: isGet, }) } } return } func (s *Child) _userMap(userIds []int64) (data map[int64]string, err error) { data = make(map[int64]string, len(userIds)) if len(userIds) == 0 { return } m := s.GetDao().FissionUser list, err := m.WithContext(s.Ctx).Select(m.ID, m.SubUserID).Where(m.ID.In(userIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } for _, v := range list { data[v.ID] = v.SubUserID } return } func (s *Child) _checkRun(start, end int64, tOffset int32) bool { return timez.GMTInsideEndless(tOffset, start, end) }