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.
567 lines
14 KiB
Go
567 lines
14 KiB
Go
package campaignuser
|
|
|
|
import (
|
|
"joybuywork/internal/consts"
|
|
"joybuywork/internal/repository/cache"
|
|
"joybuywork/internal/repository/model"
|
|
"joybuywork/internal/repository/mtype"
|
|
"joybuywork/internal/repository/withdefault"
|
|
"joybuywork/internal/service/provider"
|
|
"joybuywork/internal/service/provider/award"
|
|
"joybuywork/internal/service/provider/fissionaction"
|
|
"joybuywork/internal/service/provider/players"
|
|
"joybuywork/internal/service/provider/stocks"
|
|
"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"
|
|
"strings"
|
|
"time"
|
|
|
|
"gits.branchcn.com/backend/microcode/plugins/lucky"
|
|
"gorm.io/gen/field"
|
|
)
|
|
|
|
const (
|
|
childActiveStatusWait = 1
|
|
childActiveStatusLack = 2
|
|
childActiveStatusSame = 3
|
|
)
|
|
|
|
type ChildActive struct {
|
|
logic.Logic
|
|
Req *pb.ChildActiveReq
|
|
Res *pb.ChildActiveRes
|
|
|
|
recordMap map[int32]int64
|
|
|
|
childUserUp []field.AssignExpr
|
|
}
|
|
|
|
func (s *ChildActive) Run() error {
|
|
return logic.Run(s)
|
|
}
|
|
|
|
func (s *ChildActive) Exec() (err error) {
|
|
cpn, user, err := s.user()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
reward, player, err := s.active(cpn, user)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if reward == nil {
|
|
s.Res.Status = childActiveStatusWait
|
|
return
|
|
}
|
|
|
|
return s.getReward(cpn, user, reward, player)
|
|
}
|
|
|
|
func (s *ChildActive) 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 *ChildActive) active(cpn *model.FissionCampaign, user *model.FissionUser) (reward *model.FissionCampaignReward, player *model.FissionChildUser, err error) {
|
|
relate, err := cache.NewCampaignChild(s.Ctx).FindByUniqIdx(cpn.ID, int8(s.Req.GetChildType()))
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if relate == nil {
|
|
err = workerr.NotFound("not found child")
|
|
return
|
|
}
|
|
|
|
child, err := cache.NewCampaign(s.Ctx).FindById(relate.ChildID)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if child == nil {
|
|
err = workerr.NotFound("not found child")
|
|
return
|
|
}
|
|
|
|
player, err = cache.NewFissionChildUser(s.Ctx).FindByUniqIdx(user.ID, child.ID)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if player == nil {
|
|
err = workerr.NotFound("not found player")
|
|
return
|
|
}
|
|
|
|
switch s.Req.GetChildType() {
|
|
case mtype.FissionCampaignChildTypeInvite:
|
|
if player.RecordID > 0 {
|
|
err = s.done(cpn.ProjectID, cpn.ID, player.RecordID, user.LangMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
case mtype.FissionCampaignChildTypeSign:
|
|
reward, err = s._sign(cpn, user, player)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return
|
|
case mtype.FissionCampaignChildTypeBlind:
|
|
reward, err = s._lottery(cpn, user, player)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return
|
|
case mtype.FissionCampaignChildTypeLucky:
|
|
reward, err = s._lucky(cpn, user, player)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return
|
|
case mtype.FissionCampaignChildTypeTask:
|
|
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *ChildActive) _sign(cpn *model.FissionCampaign, user *model.FissionUser, player *model.FissionChildUser) (reward *model.FissionCampaignReward, err error) {
|
|
tz := provider.NewCampaignTZ(s.Ctx, cpn, user.LangMark)
|
|
|
|
_, start, end := timez.GMTStartAndEndTs(tz.GetTz())
|
|
if verify.Inside(player.LastDone, start, end) {
|
|
err = s.done(cpn.ProjectID, cpn.ID, player.RecordID, user.LangMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
//如果是预览用户,随机返回一个奖品
|
|
if user.IsView == mtype.Yes {
|
|
m := s.GetDao().FissionCampaignReward
|
|
reward, err = m.WithContext(s.Ctx).Where(m.CampaignID.Eq(player.CampaignID), m.SignDay.Eq(1), m.IsDel.Eq(mtype.No)).Take()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionCampaignReward
|
|
list, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(player.CampaignID), m.IsDel.Eq(mtype.No)).Order(m.SignDay).Find()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
var l = len(list)
|
|
|
|
conf, err := cache.NewCampaignConfig(s.Ctx).FindByCampaignId(player.CampaignID)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
playerM := s.GetDao().FissionChildUser
|
|
s.childUserUp = append(s.childUserUp, playerM.SignDay.Add(1))
|
|
if player.JoinTime == 0 {
|
|
s.childUserUp = append(s.childUserUp, playerM.JoinTime.Value(time.Now().Unix()))
|
|
}
|
|
|
|
var idx int
|
|
switch conf.PlayType {
|
|
case mtype.FissionCampaignConfigPlayTypeSign:
|
|
idx = int(player.SignDay) % l
|
|
case mtype.FissionCampaignConfigPlayTypeContinue:
|
|
var continueSign = player.ContinueSign + 1
|
|
if !verify.Inside(player.LastDone, start-86400, end-86400) {
|
|
continueSign = 1
|
|
}
|
|
|
|
s.childUserUp = append(s.childUserUp, playerM.ContinueSign.Value(continueSign))
|
|
|
|
idx = int(continueSign-1) % l
|
|
default:
|
|
return
|
|
}
|
|
|
|
reward = list[idx]
|
|
|
|
s.AddAfterRun(func() (err error) {
|
|
|
|
fissionaction.NewMarkPoint(s.Ctx).InApp(user).JoinChild(time.Now().Unix(), player.CampaignID, player.ChildType)
|
|
fissionaction.NewMarkPoint(s.Ctx).Child(player, user).ChildSign(time.Now().Unix())
|
|
|
|
return
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
func (s *ChildActive) _lucky(cpn *model.FissionCampaign, user *model.FissionUser, player *model.FissionChildUser) (reward *model.FissionCampaignReward, err error) {
|
|
reward, err = s._lottery(cpn, user, player)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if reward == nil {
|
|
return
|
|
}
|
|
|
|
var luckyReward = player.LuckyReward
|
|
if reward.IsSuper == mtype.Yes {
|
|
luckyReward = ""
|
|
} else {
|
|
luckyReward = strings.Trim(fmt.Sprintf("%s,%d", luckyReward, reward.ID), ",")
|
|
}
|
|
|
|
s.childUserUp = append(s.childUserUp, s.GetDao().FissionChildUser.LuckyReward.Value(luckyReward))
|
|
|
|
return
|
|
}
|
|
|
|
// 抽奖
|
|
func (s *ChildActive) _lottery(cpn *model.FissionCampaign, user *model.FissionUser, player *model.FissionChildUser) (reward *model.FissionCampaignReward, err error) {
|
|
tz := provider.NewCampaignTZ(s.Ctx, cpn, user.LangMark)
|
|
|
|
_, start, end := timez.GMTStartAndEndTs(tz.GetTz())
|
|
if verify.Inside[int64](player.LastDone, start, end) {
|
|
err = s.done(cpn.ProjectID, cpn.ID, player.RecordID, user.LangMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
conf, err := cache.NewCampaignConfig(s.Ctx).FindByCampaignId(player.CampaignID)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionCampaignReward
|
|
rewards, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(player.CampaignID), m.IsDel.Eq(mtype.No)).Find()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
//如果是预览用户,随机返回一个奖品
|
|
if user.IsView == mtype.Yes {
|
|
var dataMap = make(map[int64]*model.FissionCampaignReward)
|
|
for _, v := range rewards {
|
|
if v.Odds == 0 && conf.PlayType == mtype.FissionCampaignConfigPlayTypeRate {
|
|
continue
|
|
}
|
|
dataMap[v.ID] = v
|
|
}
|
|
|
|
for _, v := range dataMap {
|
|
reward = v
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
s.AddAfterRun(func() (err error) {
|
|
|
|
fissionaction.NewMarkPoint(s.Ctx).InApp(user).JoinChild(time.Now().Unix(), player.CampaignID, player.ChildType)
|
|
fissionaction.NewMarkPoint(s.Ctx).Child(player, user).ChildLottery(time.Now().Unix())
|
|
|
|
return
|
|
})
|
|
|
|
if player.JoinTime == 0 {
|
|
s.childUserUp = append(s.childUserUp, s.GetDao().FissionChildUser.JoinTime.Value(time.Now().Unix()))
|
|
}
|
|
|
|
var ids []int64
|
|
for _, v := range rewards {
|
|
if v.PropMark == mtype.FissionCampaignRewardPropMarkChance {
|
|
continue
|
|
}
|
|
ids = append(ids, v.ID)
|
|
}
|
|
|
|
stock, err := stocks.NewCampaignReward(s.Ctx, ids...)
|
|
if err != nil {
|
|
return
|
|
}
|
|
useStockMap, _ := stock.AllUseStock()
|
|
|
|
var filterMap = make(map[int64]struct{})
|
|
for _, id := range player.GetLuckyReward() {
|
|
filterMap[id] = struct{}{}
|
|
}
|
|
|
|
var hasReward bool
|
|
var rewardMap = make(map[int64]*model.FissionCampaignReward)
|
|
for _, v := range rewards {
|
|
|
|
if v.PropMark == mtype.FissionCampaignRewardPropMarkReward && int64(v.Stock) <= useStockMap[v.ID] {
|
|
continue
|
|
}
|
|
|
|
if _, ok := filterMap[v.ID]; ok {
|
|
continue
|
|
}
|
|
|
|
oddo := v.Odds
|
|
if conf.PlayType == mtype.FissionCampaignConfigPlayTypeRand {
|
|
oddo = 1
|
|
}
|
|
|
|
v.Odds = oddo
|
|
|
|
rewardMap[v.ID] = v
|
|
hasReward = true
|
|
}
|
|
|
|
//奖品都发完了
|
|
if !hasReward {
|
|
s.Res.Status = childActiveStatusLack
|
|
return
|
|
}
|
|
|
|
//获取到了奖品
|
|
for {
|
|
//构建抽奖机
|
|
machine := s.lotteryMachine(rewardMap)
|
|
|
|
//抽奖
|
|
lcy, _ := machine.Lottery()
|
|
|
|
getReward, ok := rewardMap[lcy.Int64()]
|
|
if !ok {
|
|
s.Res.Status = childActiveStatusLack
|
|
return
|
|
}
|
|
|
|
if getReward.PropMark == mtype.FissionCampaignRewardPropMarkChance {
|
|
reward = getReward
|
|
return
|
|
}
|
|
|
|
//中奖了
|
|
var check bool
|
|
check, err = award.NewAwardIssVerify(s.Ctx, user, getReward).DeductStock().RuleFilter().IsOK()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
//扣除库存成功
|
|
if check {
|
|
reward = getReward
|
|
return
|
|
}
|
|
|
|
//这个奖品这个人不能中了
|
|
delete(rewardMap, lcy.Int64())
|
|
}
|
|
}
|
|
|
|
// 抽奖机
|
|
func (s *ChildActive) lotteryMachine(selection map[int64]*model.FissionCampaignReward) *lucky.Discrete {
|
|
var prize []lucky.Reward
|
|
for _, v := range selection {
|
|
prize = append(prize, lucky.Reward{
|
|
Share: int(v.Odds),
|
|
Mark: v.ID,
|
|
})
|
|
}
|
|
|
|
return lucky.NewDiscrete(s.Ctx, prize)
|
|
}
|
|
|
|
func (s *ChildActive) _rsp(reward *model.FissionCampaignReward, info provider.RewardAutoLang, record *model.FissionRewardRecord) {
|
|
s.AddAfterRun(func() (err error) {
|
|
|
|
res := &pb.ChildActiveRes_Record{
|
|
RewardId: reward.ID,
|
|
PropMark: reward.PropMark,
|
|
RewardNum: reward.RewardNum,
|
|
IsSuper: int32(reward.IsSuper),
|
|
Title: info.Title,
|
|
KvData: make([]*pb.ChildActiveRes_KV, 0, len(info.KvData)),
|
|
Img: info.ImgUrl,
|
|
Contact: info.Contact,
|
|
OpenToUse: info.OpenToUse,
|
|
WebUrl: info.WebUrl,
|
|
AppParam: info.AppParam,
|
|
DyRewardType: info.DyRewardType,
|
|
Id: 0,
|
|
HashId: "",
|
|
CustomRewardVal: "",
|
|
PcParam: info.PcParam,
|
|
ReceiveType: info.ReceiveType,
|
|
}
|
|
|
|
for _, v := range info.KvData {
|
|
res.KvData = append(res.KvData, &pb.ChildActiveRes_KV{
|
|
Key: v.Key,
|
|
Value: v.Value,
|
|
IsShow: v.IsShow,
|
|
})
|
|
}
|
|
|
|
if record != nil {
|
|
res.Id = record.ID
|
|
res.HashId = record.HashID
|
|
res.CustomRewardVal = record.CustomRewardVal
|
|
res.PropMark = record.PropMark
|
|
res.RewardNum = record.RewardNum
|
|
}
|
|
|
|
s.Res.Record = res
|
|
|
|
return
|
|
})
|
|
}
|
|
|
|
func (s *ChildActive) getReward(cpn *model.FissionCampaign, user *model.FissionUser, reward *model.FissionCampaignReward, player *model.FissionChildUser) (err error) {
|
|
if user.IsView == mtype.Yes {
|
|
preward, _ := provider.NewRewards(s.Ctx, cpn.ProjectID, reward.RewardID)
|
|
info, _ := preward.InfoAutoLang(reward.RewardID, user.LangMark)
|
|
|
|
// 设置返回的数据
|
|
s._rsp(reward, info, nil)
|
|
return
|
|
}
|
|
|
|
if reward.PropMark == mtype.FissionCampaignRewardPropMarkChance {
|
|
switch cpn.FissionID {
|
|
case consts.IdKeep:
|
|
err = s._keepChance(user, reward)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
record, info, _, err := award.NewAwardReward(s.Ctx, s.GetDao(), cpn.ProjectID, user).One(reward, true, award.RewardRecordChildId(player.CampaignID))
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionChildUser
|
|
var up = s.childUserUp
|
|
up = append(up, m.LastDone.Value(record.CreatedAt), m.RewardID.Value(record.RewardID), m.RecordID.Value(record.ID))
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(up...)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
var recordSource string
|
|
switch player.ChildType {
|
|
case mtype.FissionCampaignChildTypeLucky:
|
|
recordSource = mtype.FissionChildUserRecordSourceLucky
|
|
case mtype.FissionCampaignChildTypeBlind:
|
|
recordSource = mtype.FissionChildUserRecordSourceBlind
|
|
case mtype.FissionCampaignChildTypeSign:
|
|
recordSource = mtype.FissionChildUserRecordSourceSign
|
|
case mtype.FissionCampaignChildTypeInvite:
|
|
case mtype.FissionCampaignChildTypeTask:
|
|
}
|
|
|
|
if recordSource != "" {
|
|
err = s.GetDao().FissionChildUserRecord.WithContext(s.Ctx).Create(withdefault.FissionChildUserRecord(&model.FissionChildUserRecord{
|
|
PCpnID: player.PCpnID,
|
|
CampaignID: player.CampaignID,
|
|
UserID: player.UserID,
|
|
PlayerID: player.ID,
|
|
ChildType: player.ChildType,
|
|
Mark: recordSource,
|
|
RecordID: record.ID,
|
|
}))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
s.AddAfterRun(func() (err error) {
|
|
return cache.NewFissionChildUser(s.Ctx).Clear(player)
|
|
})
|
|
|
|
// 返回数据
|
|
s._rsp(reward, info, record)
|
|
|
|
fissionaction.NewMarkPoint(s.Ctx).Child(player, user).ChildGetReward(time.Now().Unix(), record.RewardID, record.ID, record.RewardType)
|
|
|
|
return
|
|
}
|
|
|
|
func (s *ChildActive) _keepChance(user *model.FissionUser, reward *model.FissionCampaignReward) (err error) {
|
|
keepDog, err := players.NewKeepDog(s.Ctx, user)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return keepDog.ChildActive(reward.RewardNum, int8(s.Req.GetChildType()))
|
|
}
|
|
|
|
func (s *ChildActive) done(projectId, cpnId, recordId int64, langMark string) (err error) {
|
|
m := s.GetDao().FissionRewardRecord.SubTable(cpnId)
|
|
record, err := m.WithContext(s.Ctx).Where(m.ID.Eq(recordId)).Take()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
preward, err := provider.NewRewards(s.Ctx, projectId, record.BaseRewardID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
rewardM := s.GetDao().FissionCampaignReward
|
|
reward, err := rewardM.WithContext(s.Ctx).Where(rewardM.ID.Eq(record.RewardID)).Take()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
info, _ := preward.InfoAutoLang(reward.RewardID, langMark)
|
|
|
|
s._rsp(reward, info, record)
|
|
|
|
s.Res.Status = childActiveStatusSame
|
|
|
|
return
|
|
}
|