You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

643 lines
15 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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)
}