|
|
package players
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
"joybuywork/internal/app"
|
|
|
"joybuywork/internal/consts"
|
|
|
"joybuywork/internal/consts/ckey"
|
|
|
"joybuywork/internal/plugins/jsonm"
|
|
|
"joybuywork/internal/repository/cache"
|
|
|
"joybuywork/internal/repository/dao"
|
|
|
"joybuywork/internal/repository/dbcheck"
|
|
|
"joybuywork/internal/repository/model"
|
|
|
"joybuywork/internal/repository/mtype"
|
|
|
"joybuywork/internal/repository/withdefault"
|
|
|
"joybuywork/internal/service/cmm"
|
|
|
"joybuywork/internal/service/provider"
|
|
|
"joybuywork/internal/service/provider/award"
|
|
|
"joybuywork/internal/service/provider/cachecurd"
|
|
|
"joybuywork/internal/service/provider/fissionaction"
|
|
|
"joybuywork/internal/service/provider/stocks"
|
|
|
"joybuywork/internal/utils"
|
|
|
"joybuywork/internal/utils/timez"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
"strings"
|
|
|
"time"
|
|
|
|
|
|
"joybuywork/proto/go_proto/workerr"
|
|
|
|
|
|
"github.com/golang-module/carbon/v2"
|
|
|
"github.com/rs/xid"
|
|
|
"gorm.io/gen/field"
|
|
|
"gorm.io/gorm"
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
SignStatusOk = iota //签到成功
|
|
|
SignStatusFail //签到失败
|
|
|
SignStatusMissCard //补签卡不足
|
|
|
SignStatusDone //已签到
|
|
|
SignStatusCard //补签签到
|
|
|
SignStatusWait //活动未开启
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
SignWait = iota // 未签到
|
|
|
SignDone // 已签到
|
|
|
SignMiss // 漏签
|
|
|
)
|
|
|
|
|
|
type Status struct {
|
|
|
DirectNum int64 // 直接邀请人数
|
|
|
MaxContinue int32 // 最大连续签到
|
|
|
TodaySign int32 // 今天是否有签到
|
|
|
CycleDay int32 // 周期签到天数
|
|
|
}
|
|
|
|
|
|
// Sign 签到交互逻辑
|
|
|
type Sign struct {
|
|
|
Player
|
|
|
player *model.FissionSign
|
|
|
conf *model.FissionCampaignSign
|
|
|
|
|
|
upPlayer []field.AssignExpr
|
|
|
|
|
|
signDataKey string
|
|
|
|
|
|
cacheData *cachecurd.HMap
|
|
|
}
|
|
|
|
|
|
func NewSign(ctx context.Context, user *model.FissionUser, opts ...Option) (player *Sign, err error) {
|
|
|
player = &Sign{}
|
|
|
|
|
|
err = player.Init(ctx, user, consts.IdSignIn, opts...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = player.initPlayer()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
type SignReward struct {
|
|
|
RewardTitle string //奖品名称
|
|
|
RewardNum int32 //获得的奖品数量
|
|
|
ImgUrl string //奖品图片
|
|
|
RewardId int64 //奖品id
|
|
|
ReceiveType int32 //发放类型(0-无操作,1-系统发放,2-联系客服,3-客户端推送)
|
|
|
KvData []*mtype.KV //键值数据
|
|
|
Contact string //联系方式
|
|
|
}
|
|
|
|
|
|
// SignIn 签到
|
|
|
func (s *Sign) SignIn(signTime int64) (status int32, reward *SignReward, err error) {
|
|
|
defer func() {
|
|
|
s.AfterDo(err)
|
|
|
}()
|
|
|
tz := s.GetTz()
|
|
|
if !tz.IsRunning() {
|
|
|
status = SignStatusWait
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 今天的开始
|
|
|
today, _ := timez.GMTTimeStart(tz.GetTz())
|
|
|
|
|
|
// 提交上来的签到时间有这个可能是补签卡
|
|
|
submitDay, _ := timez.GMTTimeStart(tz.GetTz(), signTime)
|
|
|
|
|
|
s.Tran()
|
|
|
defer func() {
|
|
|
s.TranCommit(err)
|
|
|
}()
|
|
|
|
|
|
conf := s.GetConf()
|
|
|
if conf.SignType == mtype.FissionCampaignSignTypeCycle {
|
|
|
|
|
|
if signTime == 0 || today.Equal(submitDay) {
|
|
|
return s._cycleSign()
|
|
|
}
|
|
|
|
|
|
return s._cycleCardSign(submitDay)
|
|
|
}
|
|
|
|
|
|
// 下面的逻辑太老旧了,不想嵌套到里面 !!!
|
|
|
|
|
|
if today.Before(submitDay) { // 如果当前时间小于提交的时间,那就是未来的时间,未来时间不可以签到
|
|
|
status = SignStatusFail
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if signTime == 0 || today.Equal(submitDay) {
|
|
|
return s._todaySign(today)
|
|
|
}
|
|
|
|
|
|
return s._cardSign(submitDay)
|
|
|
}
|
|
|
|
|
|
// 周期补签卡签到
|
|
|
func (s *Sign) _cycleCardSign(signTime time.Time) (status int32, reward *SignReward, err error) {
|
|
|
s._cycleStart()
|
|
|
|
|
|
playerM := s.GetDao().FissionSign
|
|
|
player := s.GetPlayer()
|
|
|
|
|
|
if player.CardNum <= 0 {
|
|
|
status = SignStatusMissCard
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if player.CycleStart > signTime.Unix() || signTime.Unix() >= time.Now().Unix() {
|
|
|
status = SignStatusFail
|
|
|
return
|
|
|
}
|
|
|
|
|
|
status, signDay, err := s._sign(signTime, true)
|
|
|
if err != nil || status != SignStatusOk {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
cd, err := s._cycleData(false)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 签到的天更新
|
|
|
signStr, err := cd.Get(signCycleDay)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
if signStr == "" {
|
|
|
signStr = signDay.SignDate
|
|
|
} else {
|
|
|
signStr += consts.JoinComma + signDay.SignDate
|
|
|
}
|
|
|
|
|
|
s.AddOkDone(func() {
|
|
|
_ = cd.Set(signCycleDay, signStr)
|
|
|
})
|
|
|
|
|
|
continueNum, maxContinue, _, err := s._continueNum()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
s.AddOkDone(func() {
|
|
|
_ = cd.Set(signMaxContinue, fmt.Sprint(maxContinue))
|
|
|
_ = cd.Set(signContinueNum, fmt.Sprint(continueNum))
|
|
|
|
|
|
fissionaction.NewMarkPoint(s.Ctx).InApp(s.user).UseProp(time.Now().Unix(), consts.PropNameSignCard)
|
|
|
})
|
|
|
|
|
|
s.upPlayer = append(
|
|
|
s.upPlayer,
|
|
|
playerM.SignContinue.Value(continueNum),
|
|
|
playerM.MaxContinue.Value(maxContinue),
|
|
|
playerM.CardNum.Sub(1),
|
|
|
)
|
|
|
|
|
|
signDays := strings.Split(signStr, consts.JoinComma)
|
|
|
signNum := int32(len(signDays))
|
|
|
|
|
|
reward, recordIds, err := s._cycleReward(signNum, signDay)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._cyclePlayerSync(recordIds)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 周期签到
|
|
|
func (s *Sign) _cycleSign() (status int32, reward *SignReward, err error) {
|
|
|
s._cycleStart()
|
|
|
|
|
|
playerM := s.GetDao().FissionSign
|
|
|
player, tz := s.GetPlayer(), s.GetTz()
|
|
|
// 今天的开始
|
|
|
today, _ := timez.GMTTimeStart(tz.GetTz())
|
|
|
|
|
|
status, signDay, err := s._sign(today, false)
|
|
|
if err != nil || status != SignStatusOk {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if player.SignStart == 0 {
|
|
|
s.player.SignStart = today.Unix()
|
|
|
s.upPlayer = append(s.upPlayer, playerM.SignStart.Value(today.Unix()))
|
|
|
}
|
|
|
|
|
|
cd, err := s._cycleData(false)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
s.AddOkDone(func() {
|
|
|
// 下一次签到时间
|
|
|
err = cd.Set(signNextDay, fmt.Sprint(today.AddDate(0, 0, 1).Unix()))
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 最后签到时间
|
|
|
err = cd.Set(signLastDay, fmt.Sprint(today.Unix()))
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
})
|
|
|
|
|
|
// 签到的天更新
|
|
|
signStr, err := cd.Get(signCycleDay)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
if signStr == "" {
|
|
|
signStr = signDay.SignDate
|
|
|
} else {
|
|
|
signStr += consts.JoinComma + signDay.SignDate
|
|
|
}
|
|
|
|
|
|
s.AddOkDone(func() {
|
|
|
_ = cd.Set(signCycleDay, signStr)
|
|
|
})
|
|
|
|
|
|
// 连续签到数据
|
|
|
continueNum, _ := cd.GetInt64(signContinueNum)
|
|
|
s.AddOkDone(func() {
|
|
|
_, _ = cd.Incr(signContinueNum, 1)
|
|
|
})
|
|
|
|
|
|
continueNum += 1
|
|
|
maxContinue, _ := cd.GetInt64(signMaxContinue)
|
|
|
if continueNum > maxContinue {
|
|
|
maxContinue = continueNum
|
|
|
|
|
|
s.AddOkDone(func() {
|
|
|
_ = cd.Set(signMaxContinue, fmt.Sprint(maxContinue))
|
|
|
})
|
|
|
}
|
|
|
|
|
|
s.upPlayer = append(
|
|
|
s.upPlayer,
|
|
|
playerM.SignContinue.Value(int32(continueNum)),
|
|
|
playerM.MaxContinue.Value(int32(maxContinue)),
|
|
|
)
|
|
|
|
|
|
signDays := strings.Split(signStr, consts.JoinComma)
|
|
|
signNum := int32(len(signDays))
|
|
|
|
|
|
reward, recordIds, err := s._cycleReward(signNum, signDay)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._cyclePlayerSync(recordIds)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 周期奖品处理
|
|
|
func (s *Sign) _cycleReward(signNum int32, signDay *model.FissionSignDay) (reward *SignReward, recordIds []int64, err error) {
|
|
|
//当前签到是否有奖品
|
|
|
rewards, err := cmm.NewUserAppReward(s.Ctx).Get(s.GetDao(), s.user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var signReward *model.FissionCampaignReward
|
|
|
for _, v := range rewards {
|
|
|
if v.SignDay > signNum {
|
|
|
break
|
|
|
}
|
|
|
|
|
|
if v.SignDay == signNum {
|
|
|
signReward = v
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if signReward == nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
reward, recordIds, err = s._signReward(signDay, signReward)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 绑定数据
|
|
|
sdm := s.GetDao().FissionSignDay
|
|
|
_, err = sdm.WithContext(s.Ctx).Where(sdm.ID.Eq(signDay.ID)).UpdateSimple(sdm.RecordIds.Value(utils.Join(recordIds, consts.JoinComma)))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 周期用户更新数据同步
|
|
|
func (s *Sign) _cyclePlayerSync(recordIds []int64) (err error) {
|
|
|
playerM := s.GetDao().FissionSign
|
|
|
player := s.GetPlayer()
|
|
|
// 更新玩家数据
|
|
|
_, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple(s.upPlayer...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 更新统计数据
|
|
|
statM := s.GetDao().FissionUserStat
|
|
|
_, err = statM.WithContext(s.Ctx).Where(statM.UserID.Eq(player.UserID)).UpdateSimple(statM.SignNum.Add(1), statM.SignRewardNum.Add(int64(len(recordIds))))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
type SignBoard struct {
|
|
|
SignDate []*SignBoardOne //签到板信息
|
|
|
NowMouth string //当前月
|
|
|
CycleDate []*SignCycleDateOne
|
|
|
}
|
|
|
|
|
|
type SignCycleDateOne struct {
|
|
|
SignTime int64 //签到时间
|
|
|
SignIn int32 //签到类型(0-未签,1-已签,2-漏签)
|
|
|
NowDay bool //是否今天
|
|
|
RewardId int64 //奖品id,0即没有礼物
|
|
|
RewardTitle string //奖品图片
|
|
|
RewardImg string //奖品标题
|
|
|
IsSuper int32 //是否超级大奖 (0-否,1-是)
|
|
|
Y string //年
|
|
|
M string //月
|
|
|
D string //日
|
|
|
}
|
|
|
type SignBoardOne struct {
|
|
|
Y string //年
|
|
|
M string //月
|
|
|
D string //日
|
|
|
SignIn int32 //签到类型(0-未签,1-已签,2-漏签)
|
|
|
Ban bool //是否非签到日期
|
|
|
RewardId int64 //奖品id,0即没有礼物
|
|
|
Open bool //是否已经领奖
|
|
|
NowWeek bool //是否本周
|
|
|
NowDay bool //是否今天
|
|
|
LastMiss bool //是否最后一个漏签
|
|
|
NowMouth bool //是否本月
|
|
|
}
|
|
|
|
|
|
// SignBoard 签到版
|
|
|
func (s *Sign) SignBoard(pageType int32, nowMouth string) (signBoard *SignBoard, err error) {
|
|
|
defer func() {
|
|
|
s.AfterDo(err)
|
|
|
}()
|
|
|
conf := s.GetConf()
|
|
|
if conf.SignType == mtype.FissionCampaignSignTypeCycle {
|
|
|
return s._cycleSignBoard()
|
|
|
}
|
|
|
|
|
|
return s._normalSignBoard(pageType, nowMouth)
|
|
|
}
|
|
|
|
|
|
// 周期签到板
|
|
|
func (s *Sign) _cycleSignBoard() (signBoard *SignBoard, err error) {
|
|
|
s._cycleStart()
|
|
|
|
|
|
rewards, err := cmm.NewUserAppReward(s.Ctx).Get(s.GetDao(), s.user, s.GetDao().FissionCampaignReward.SignDay)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var rewardIds []int64
|
|
|
var dayReward = make(map[int32]*model.FissionCampaignReward)
|
|
|
for _, reward := range rewards {
|
|
|
dayReward[reward.SignDay] = reward
|
|
|
rewardIds = append(rewardIds, reward.RewardID)
|
|
|
}
|
|
|
|
|
|
prewards, err := provider.NewRewards(s.Ctx, s.cpn.ProjectID, rewardIds...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
player, conf, tz := s.GetPlayer(), s.GetConf(), s.GetTz()
|
|
|
|
|
|
today, _ := timez.GMTTimeStart(tz.GetTz())
|
|
|
cycleStart, _ := timez.GMTTimeStart(tz.GetTz(), player.CycleStart)
|
|
|
cpnEnd := s.GetTz().EndTime()
|
|
|
cd, err := s._cycleData(false)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
signDayStr, _ := cd.Get(signCycleDay)
|
|
|
var signDay []string
|
|
|
if signDayStr != "" {
|
|
|
signDay = strings.Split(signDayStr, consts.JoinComma)
|
|
|
}
|
|
|
|
|
|
var signMap = make(map[string]struct{})
|
|
|
for _, v := range signDay {
|
|
|
signMap[v] = struct{}{}
|
|
|
}
|
|
|
|
|
|
var signNum int32
|
|
|
var signDate = make([]*SignCycleDateOne, 0, int(conf.SignCycle))
|
|
|
for i := 0; i < int(conf.SignCycle); i++ {
|
|
|
one := &SignCycleDateOne{
|
|
|
SignTime: cycleStart.Unix(),
|
|
|
SignIn: 0,
|
|
|
NowDay: false,
|
|
|
RewardId: 0,
|
|
|
RewardTitle: "",
|
|
|
RewardImg: "",
|
|
|
IsSuper: 0,
|
|
|
Y: fmt.Sprint(cycleStart.Year()),
|
|
|
M: fmt.Sprint(int(cycleStart.Month())),
|
|
|
D: fmt.Sprint(cycleStart.Day()),
|
|
|
}
|
|
|
|
|
|
shortDate := cycleStart.Format(timez.ShortDateOnly)
|
|
|
|
|
|
if cycleStart.Before(today) {
|
|
|
if _, ok := signMap[shortDate]; ok {
|
|
|
one.SignIn = SignDone
|
|
|
signNum++
|
|
|
} else {
|
|
|
one.SignIn = SignMiss
|
|
|
}
|
|
|
} else {
|
|
|
signNum++
|
|
|
}
|
|
|
|
|
|
if cycleStart.Equal(today) {
|
|
|
one.NowDay = true
|
|
|
if _, ok := signMap[shortDate]; ok {
|
|
|
one.SignIn = SignDone
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if reward, ok := dayReward[signNum]; ok {
|
|
|
info := prewards.AutoLang(reward.RewardID, s.user.LangMark)
|
|
|
one.RewardId = reward.ID
|
|
|
one.IsSuper = int32(reward.IsSuper)
|
|
|
one.RewardTitle = info.Title
|
|
|
one.RewardImg = info.ImgUrl
|
|
|
delete(dayReward, signNum)
|
|
|
}
|
|
|
|
|
|
signDate = append(signDate, one)
|
|
|
cycleStart = cycleStart.AddDate(0, 0, 1)
|
|
|
if cycleStart.After(cpnEnd) {
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
|
|
|
signBoard = &SignBoard{CycleDate: signDate}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 看看要不要重制周期时间
|
|
|
func (s *Sign) _cycleStart() {
|
|
|
cd, err := s._cycleData(false)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
player, conf := s.GetPlayer(), s.GetConf()
|
|
|
|
|
|
dayStart := s._dayStart()
|
|
|
yesterdayStart := dayStart.AddDate(0, 0, -1)
|
|
|
var refresh bool
|
|
|
playerM := s.GetDao().FissionSign
|
|
|
if player.CycleStart == 0 {
|
|
|
s.player.CycleStart = dayStart.Unix()
|
|
|
s.upPlayer = append(s.upPlayer, playerM.CycleStart.Value(dayStart.Unix()))
|
|
|
|
|
|
s.AddOkDone(func() {
|
|
|
_ = cd.Set(signNextDay, fmt.Sprint(dayStart.Unix()))
|
|
|
})
|
|
|
|
|
|
} else if conf.RecycleType == mtype.FissionCampaignRecycleTypeContinue {
|
|
|
lastDay, _ := cd.GetInt64(signLastDay)
|
|
|
if lastDay < yesterdayStart.Unix() {
|
|
|
s.player.CycleStart = dayStart.Unix()
|
|
|
s.upPlayer = append(s.upPlayer, playerM.CycleStart.Value(dayStart.Unix()))
|
|
|
_ = cd.Clear()
|
|
|
refresh = true
|
|
|
}
|
|
|
} else if conf.RecycleType == mtype.FissionCampaignRecycleTypeCycle {
|
|
|
if (dayStart.Unix()-player.CycleStart)/consts.DaySec >= int64(conf.SignCycle) {
|
|
|
s.player.CycleStart = dayStart.Unix()
|
|
|
s.upPlayer = append(s.upPlayer, playerM.CycleStart.Value(dayStart.Unix()))
|
|
|
_ = cd.Clear()
|
|
|
refresh = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
_, err = s._cycleData(refresh)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func (s *Sign) _dayStart() time.Time {
|
|
|
tz := s.GetTz()
|
|
|
dayStart, _ := timez.GMTTimeStart(tz.GetTz())
|
|
|
cpnStart := tz.StarTime()
|
|
|
if dayStart.Before(cpnStart) {
|
|
|
dayStart = cpnStart
|
|
|
}
|
|
|
return dayStart
|
|
|
}
|
|
|
|
|
|
// GetSignCard 获得了签到卡
|
|
|
func (s *Sign) GetSignCard(num int32) (err error) {
|
|
|
player := s.GetPlayer()
|
|
|
|
|
|
m := s.GetDao().FissionSign
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.CardNum.Add(num))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
val, _ := jsonm.ToObjString(mtype.SignLogVal{CardNum: num})
|
|
|
|
|
|
err = s._addLog(withdefault.FissionSignLog(&model.FissionSignLog{
|
|
|
UserID: player.UserID,
|
|
|
CampaignID: player.CampaignID,
|
|
|
SignID: player.ID,
|
|
|
Type: mtype.FissionSignLogTypeSignCard,
|
|
|
Source: mtype.FissionSignLogSourceGetCard,
|
|
|
Val: val,
|
|
|
}))
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
s.appTrack().GetProp(time.Now().Unix(), consts.PropNameSignCard, num)
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// GetStatus 用户额外信息
|
|
|
func (s *Sign) GetStatus() (status Status, err error) {
|
|
|
player, conf, tz := s.GetPlayer(), s.GetConf(), s.GetTz()
|
|
|
|
|
|
statM := s.GetDao().FissionUserStat
|
|
|
stat, err := statM.WithContext(s.Ctx).Where(statM.UserID.Eq(player.UserID)).Take()
|
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if stat != nil {
|
|
|
status.DirectNum = stat.DirectNum
|
|
|
}
|
|
|
|
|
|
var maxContinue = player.MaxContinue
|
|
|
if player.NextStep > 0 {
|
|
|
maxContinue = 0
|
|
|
m := s.GetDao().FissionCampaignReward
|
|
|
if player.NextStep > 1 {
|
|
|
|
|
|
var reward *model.FissionCampaignReward
|
|
|
reward, err = m.WithContext(s.Ctx).Where(m.CampaignID.Eq(player.CampaignID), m.Step.Eq(player.NextStep-1)).Take()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if reward != nil {
|
|
|
maxContinue = reward.SignDay
|
|
|
}
|
|
|
} else if player.LoopNum > 0 {
|
|
|
var rewards []*model.FissionCampaignReward
|
|
|
rewards, err = cmm.NewCMM(s.Ctx, s.GetDao()).UserAppReward(s.user, m.Step)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
l := len(rewards)
|
|
|
maxContinue = rewards[l-1].SignDay
|
|
|
}
|
|
|
}
|
|
|
|
|
|
status.MaxContinue = maxContinue
|
|
|
|
|
|
today, _ := timez.GMTTimeStart(tz.GetTz())
|
|
|
exist, err := s._hasSign(today)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
status.TodaySign = utils.Ternary[int32](exist, 1, 0)
|
|
|
|
|
|
// 周期签到天数
|
|
|
if conf.SignType == mtype.FissionCampaignSignTypeCycle {
|
|
|
s._cycleStart()
|
|
|
|
|
|
cd, _ := s._cycleData(false)
|
|
|
cycleDay, _ := cd.Get(signCycleDay)
|
|
|
if cycleDay != "" {
|
|
|
status.CycleDay = int32(len(strings.Split(cycleDay, consts.JoinComma)))
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// GetConf 获取玩法配置
|
|
|
func (s *Sign) GetConf() *model.FissionCampaignSign {
|
|
|
if s.conf == nil {
|
|
|
s.conf, _ = cache.NewCampaignSign(s.Ctx).FindByCampaignId(s.user.CampaignID)
|
|
|
}
|
|
|
|
|
|
return s.conf
|
|
|
}
|
|
|
|
|
|
// GetPlayer 获取玩家基础数据
|
|
|
func (s *Sign) GetPlayer() *model.FissionSign {
|
|
|
return s.player
|
|
|
}
|
|
|
|
|
|
// 玩家
|
|
|
func (s *Sign) initPlayer() (err error) {
|
|
|
player, err := s._dbFirst()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
defer func() {
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
s.player = player
|
|
|
s.signDataKey = ckey.FissionSignData(player.ID)
|
|
|
}()
|
|
|
|
|
|
if player != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
player, err = s.firstOrCreate()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 创建玩家基础数据
|
|
|
func (s *Sign) firstOrCreate() (player *model.FissionSign, err error) {
|
|
|
lc := app.NewFollower(s.Ctx, ckey.FissionUserCreatePlayerOnce(s.user.ID)).Lock()
|
|
|
defer lc.Release()
|
|
|
if lc.Error() != nil {
|
|
|
err = lc.Error()
|
|
|
return
|
|
|
}
|
|
|
|
|
|
player, err = s._dbFirst()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if player != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return s.createPlayer()
|
|
|
}
|
|
|
|
|
|
// 数据库查询
|
|
|
func (s *Sign) _dbFirst() (*model.FissionSign, error) {
|
|
|
playerM := dao.FissionSign
|
|
|
player, err := playerM.WithContext(s.Ctx).Where(playerM.UserID.Eq(s.user.ID)).Take()
|
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
|
return nil, s.BE().MysqlError(err)
|
|
|
}
|
|
|
|
|
|
return player, nil
|
|
|
}
|
|
|
|
|
|
// 创建一个玩家
|
|
|
func (s *Sign) createPlayer() (player *model.FissionSign, err error) {
|
|
|
playerM := dao.FissionSign
|
|
|
player = withdefault.FissionSign(&model.FissionSign{
|
|
|
CampaignID: s.user.CampaignID,
|
|
|
UserID: s.user.ID,
|
|
|
})
|
|
|
|
|
|
err = playerM.WithContext(s.Ctx).Create(player)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *Sign) _addLog(logs ...*model.FissionSignLog) (err error) {
|
|
|
err = s.GetDao().FissionSignLog.WithContext(s.Ctx).Create(logs...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 连续签到数据
|
|
|
func (s *Sign) _continueNum() (continueNum, maxContinue int32, cycleDate []string, err error) {
|
|
|
player, tz := s.GetPlayer(), s.GetTz()
|
|
|
m := s.GetDao().FissionSignDay
|
|
|
list, err := m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(player.UserID),
|
|
|
).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
signMap := make(map[string]struct{})
|
|
|
for _, day := range list {
|
|
|
signMap[day.SignDate] = struct{}{}
|
|
|
}
|
|
|
|
|
|
var start = player.SignStart
|
|
|
if start == 0 {
|
|
|
start = time.Now().Unix()
|
|
|
}
|
|
|
|
|
|
sdn := timez.GMTCarbon(tz.GetTz()).Now()
|
|
|
sd := utils.BetweenDay(timez.GMTCarbon(tz.GetTz()).CreateFromTimestamp(start).StartOfDay(), sdn)
|
|
|
cycleStart, _ := timez.GMTTimeStart(tz.GetTz(), player.CycleStart)
|
|
|
cycle := cycleStart.Format(timez.ShortDateOnly)
|
|
|
|
|
|
for _, day := range sd {
|
|
|
_, ok := signMap[day]
|
|
|
|
|
|
if !ok {
|
|
|
continueNum = 0
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
if day >= cycle {
|
|
|
cycleDate = append(cycleDate, day)
|
|
|
}
|
|
|
|
|
|
continueNum++
|
|
|
|
|
|
if continueNum > maxContinue {
|
|
|
maxContinue = continueNum
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 获得奖品通用处理
|
|
|
func (s *Sign) _signReward(sign *model.FissionSignDay, rewards ...*model.FissionCampaignReward) (signReward *SignReward, recordId []int64, err error) {
|
|
|
if len(rewards) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var rewardIds []int64
|
|
|
var add []*award.RewardOne
|
|
|
for _, reward := range rewards {
|
|
|
rewardIds = append(rewardIds, reward.ID)
|
|
|
add = append(add, &award.RewardOne{
|
|
|
Reward: reward,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
records, async, err := award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, s.user).Batch(add, false)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
stock, err := stocks.NewCampaignReward(s.Ctx, rewardIds...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
player := s.GetPlayer()
|
|
|
var addLog []*model.FissionSignLog
|
|
|
for _, v := range records {
|
|
|
recordId = append(recordId, v.Record.ID)
|
|
|
|
|
|
val, _ := jsonm.MarshalToString(mtype.SignLogVal{
|
|
|
TOffset: s.GetTz().GetTz(),
|
|
|
SignDate: sign.SignDate,
|
|
|
RecordId: v.Record.ID,
|
|
|
RewardId: v.Record.RewardID,
|
|
|
})
|
|
|
addLog = append(addLog, withdefault.FissionSignLog(&model.FissionSignLog{
|
|
|
UserID: player.UserID,
|
|
|
CampaignID: player.CampaignID,
|
|
|
SignID: player.ID,
|
|
|
Type: mtype.FissionSignLogTypeGetReward,
|
|
|
Source: utils.Ternary[string](sign.SignType == mtype.FissionSignTypeRemedy, mtype.FissionSignLogSourceCardReward, mtype.FissionSignLogSourceSignReward),
|
|
|
Val: val,
|
|
|
}))
|
|
|
|
|
|
_ = stock.AddUseStock(1, v.Record.RewardID)
|
|
|
}
|
|
|
|
|
|
err = s._addLog(addLog...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
record, info := records[0].Record, records[0].Info
|
|
|
|
|
|
signReward = &SignReward{
|
|
|
RewardTitle: info.Title,
|
|
|
RewardNum: record.RewardNum,
|
|
|
ImgUrl: info.ImgUrl,
|
|
|
RewardId: record.RewardID,
|
|
|
ReceiveType: info.ReceiveType,
|
|
|
KvData: make([]*mtype.KV, 0, len(info.KvData)),
|
|
|
Contact: info.Contact,
|
|
|
}
|
|
|
|
|
|
for _, v := range info.KvData {
|
|
|
signReward.KvData = append(signReward.KvData, &mtype.KV{
|
|
|
Key: v.Key,
|
|
|
Value: v.Value,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
s.AddOkDone(async...)
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
const (
|
|
|
signNextDay = "next_day" // 下次签到日期
|
|
|
signLastDay = "last_day" // 最后签到日期
|
|
|
signContinueNum = "continue_num" // 连续签到天数
|
|
|
signMaxContinue = "max_continue" // 最大连续签到天数
|
|
|
signCycleDay = "cycle_day" // 周期内签到天
|
|
|
)
|
|
|
|
|
|
func (s *Sign) _cycleData(refresh bool) (data *cachecurd.HMap, err error) {
|
|
|
if s.cacheData != nil && !refresh {
|
|
|
return s.cacheData, nil
|
|
|
}
|
|
|
|
|
|
player, tz := s.GetPlayer(), s.GetTz()
|
|
|
dayStart, _ := timez.GMTTimeStart(tz.GetTz())
|
|
|
|
|
|
yesterdayStart := dayStart.AddDate(0, 0, -1)
|
|
|
|
|
|
data, err = cachecurd.NewHMap(s.Ctx, s.signDataKey, cachecurd.SetHMapExp(2*consts.TimeDay))
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
data, err = data.CustomBuild(func() ([]string, error) {
|
|
|
var values []string
|
|
|
today := dayStart.Format(timez.ShortDateOnly)
|
|
|
yesterday := yesterdayStart.Format(timez.ShortDateOnly)
|
|
|
m := s.GetDao().FissionSignDay
|
|
|
sign, err1 := m.WithContext(s.Ctx).Where(m.UserID.Eq(player.UserID), m.SignDate.In(today, yesterday)).Find()
|
|
|
if err1 != nil {
|
|
|
return nil, err1
|
|
|
}
|
|
|
|
|
|
var todaySign, yesterdaySign *model.FissionSignDay
|
|
|
for _, v := range sign {
|
|
|
if v.SignDate == today {
|
|
|
todaySign = v
|
|
|
} else if v.SignDate == yesterday {
|
|
|
yesterdaySign = v
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if todaySign == nil {
|
|
|
values = append(values, signNextDay, fmt.Sprint(dayStart.Unix()))
|
|
|
} else {
|
|
|
values = append(values, signNextDay, fmt.Sprint(dayStart.AddDate(0, 0, 1).Unix()))
|
|
|
}
|
|
|
|
|
|
if yesterdaySign == nil {
|
|
|
values = append(values, signLastDay, "0")
|
|
|
} else {
|
|
|
values = append(values, signLastDay, fmt.Sprint(yesterdayStart.Unix()))
|
|
|
}
|
|
|
|
|
|
// 连续签到天数
|
|
|
continueNum, maxContinue, cycleDate, err1 := s._continueNum()
|
|
|
if err1 != nil {
|
|
|
return nil, err1
|
|
|
}
|
|
|
values = append(values, signContinueNum, fmt.Sprint(continueNum), signMaxContinue, fmt.Sprint(maxContinue), signCycleDay, strings.Join(cycleDate, consts.JoinComma))
|
|
|
|
|
|
return values, nil
|
|
|
})
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
s.cacheData = data
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 是否已经签到了
|
|
|
func (s *Sign) _hasSign(today time.Time) (exist bool, err error) {
|
|
|
shortDay := today.Format(timez.ShortDateOnly)
|
|
|
player := s.GetPlayer()
|
|
|
|
|
|
key := ckey.FissionCampaignSignState(player.CampaignID, shortDay)
|
|
|
if app.Redis.Cache.HExists(s.Ctx, key, fmt.Sprint(player.UserID)).Val() {
|
|
|
exist = true
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionSignDay
|
|
|
sign, err := m.WithContext(s.Ctx).Where(m.UserID.Eq(player.UserID), m.SignDate.Eq(shortDay)).Take()
|
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return sign != nil, nil
|
|
|
}
|
|
|
|
|
|
// 签到某一天
|
|
|
func (s *Sign) _sign(signTime time.Time, useCard bool) (status int32, signDay *model.FissionSignDay, err error) {
|
|
|
shortDay := signTime.Format(timez.ShortDateOnly)
|
|
|
player, tz, conf := s.GetPlayer(), s.GetTz(), s.GetConf()
|
|
|
|
|
|
// 是否已经签到了
|
|
|
exist, err := s._hasSign(signTime)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
if exist {
|
|
|
status = SignStatusDone
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var value = xid.New().String()
|
|
|
var mapKey = fmt.Sprint(player.UserID)
|
|
|
var key = ckey.FissionCampaignSignState(player.CampaignID, shortDay)
|
|
|
// 预防一些错误,要回滚缓存
|
|
|
s.AddErrDone(func() {
|
|
|
v := app.Redis.Cache.HGet(s.Ctx, key, mapKey).Val()
|
|
|
if v == value {
|
|
|
app.Redis.Cache.HDel(s.Ctx, key, mapKey)
|
|
|
}
|
|
|
})
|
|
|
|
|
|
if !app.Redis.Cache.HSetNX(s.Ctx, key, mapKey, value).Val() {
|
|
|
status = SignStatusDone
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 延长缓存时间
|
|
|
app.Redis.Cache.ExpireAt(s.Ctx, key, signTime.AddDate(0, 0, 1))
|
|
|
|
|
|
// 签到记录
|
|
|
signDay = withdefault.FissionSignDay(&model.FissionSignDay{
|
|
|
UserID: player.UserID,
|
|
|
CampaignID: player.CampaignID,
|
|
|
SignDate: shortDay,
|
|
|
SignType: utils.Ternary[int8](useCard, mtype.FissionSignTypeOk, mtype.FissionSignTypeRemedy),
|
|
|
RecordIds: "",
|
|
|
})
|
|
|
|
|
|
if err = s.GetDao().FissionSignDay.WithContext(s.Ctx).Create(signDay); err != nil {
|
|
|
if errors.Is(err, gorm.ErrDuplicatedKey) {
|
|
|
status = SignStatusFail
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 加日志
|
|
|
if useCard {
|
|
|
val, _ := jsonm.ToObjString(mtype.SignLogVal{
|
|
|
TOffset: tz.GetTz(),
|
|
|
SignDate: shortDay,
|
|
|
CardNum: 1,
|
|
|
})
|
|
|
|
|
|
err = s._addLog(withdefault.FissionSignLog(&model.FissionSignLog{
|
|
|
UserID: player.UserID,
|
|
|
CampaignID: player.CampaignID,
|
|
|
SignID: player.ID,
|
|
|
Type: mtype.FissionSignLogTypeSignCard,
|
|
|
Source: mtype.FissionSignLogSourceUseCard,
|
|
|
Val: val,
|
|
|
}))
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
val, _ := jsonm.ToObjString(mtype.SignLogVal{
|
|
|
TOffset: tz.GetTz(),
|
|
|
SignDate: shortDay,
|
|
|
})
|
|
|
|
|
|
err = s._addLog(withdefault.FissionSignLog(&model.FissionSignLog{
|
|
|
UserID: player.UserID,
|
|
|
CampaignID: player.CampaignID,
|
|
|
SignID: player.ID,
|
|
|
Type: mtype.FissionSignLogTypeSign,
|
|
|
Source: utils.Ternary[string](conf.SignType == mtype.FissionCampaignSignTypeCycle, mtype.FissionSignLogSourceManualSign, mtype.FissionSignLogSourceAutoSign),
|
|
|
Val: val,
|
|
|
}))
|
|
|
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
s.AddOkDone(func() {
|
|
|
// 新版报表数据
|
|
|
if s.cpn.ReportType == mtype.FissionCampaignReportTypeNew {
|
|
|
fissionaction.NewMarkPoint(s.Ctx).InApp(s.user).Sign(time.Now().Unix(), tz.GetTz(), signTime.Format(timez.ShortDateOnly))
|
|
|
}
|
|
|
})
|
|
|
|
|
|
s.upPlayer = append(s.upPlayer, s.GetDao().FissionSign.SignDay.Add(1))
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 当天签到(旧)
|
|
|
func (s *Sign) _todaySign(today time.Time) (status int32, reward *SignReward, err error) {
|
|
|
status, signDay, err := s._sign(today, false)
|
|
|
if err != nil || status != SignStatusOk {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
reward, err = s._signOk(signDay)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 补签卡签到(旧)
|
|
|
func (s *Sign) _cardSign(signDate time.Time) (status int32, reward *SignReward, err error) {
|
|
|
player, tz := s.GetPlayer(), s.GetTz()
|
|
|
if player.CardNum == 0 {
|
|
|
status = SignStatusMissCard
|
|
|
return
|
|
|
}
|
|
|
|
|
|
shortDay := signDate.Format(timez.ShortDateOnly)
|
|
|
|
|
|
m := s.GetDao().FissionSignDay
|
|
|
sign, err := m.WithContext(s.Ctx).Where(m.UserID.Eq(player.UserID), m.SignDate.Eq(shortDay)).Take()
|
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if sign != nil {
|
|
|
status = SignStatusDone
|
|
|
return
|
|
|
}
|
|
|
|
|
|
signDay := withdefault.FissionSignDay(&model.FissionSignDay{
|
|
|
UserID: player.UserID,
|
|
|
CampaignID: player.CampaignID,
|
|
|
SignDate: shortDay,
|
|
|
SignType: mtype.FissionSignTypeOk,
|
|
|
RecordIds: "",
|
|
|
})
|
|
|
|
|
|
if err = m.WithContext(s.Ctx).Create(signDay); err != nil {
|
|
|
if errors.Is(err, gorm.ErrDuplicatedKey) {
|
|
|
status = SignStatusFail
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
status = SignStatusCard
|
|
|
|
|
|
playerM := s.GetDao().FissionSign
|
|
|
s.upPlayer = append(s.upPlayer, playerM.CardNum.Sub(1))
|
|
|
|
|
|
// 加日志
|
|
|
val, _ := jsonm.ToObjString(mtype.SignLogVal{
|
|
|
TOffset: tz.GetTz(),
|
|
|
SignDate: shortDay,
|
|
|
})
|
|
|
|
|
|
err = s._addLog(withdefault.FissionSignLog(&model.FissionSignLog{
|
|
|
UserID: player.UserID,
|
|
|
CampaignID: player.CampaignID,
|
|
|
SignID: player.ID,
|
|
|
Type: mtype.FissionSignLogTypeSignCard,
|
|
|
Source: mtype.FissionSignLogSourceUseCard,
|
|
|
Val: val,
|
|
|
}))
|
|
|
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
reward, err = s._signOk(signDay)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if s.cpn.ReportType == mtype.FissionCampaignReportTypeNew {
|
|
|
fissionaction.NewMarkPoint(s.Ctx).InApp(s.user).UseProp(time.Now().Unix(), consts.PropNameSignCard)
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 普通签到版(旧)
|
|
|
func (s *Sign) _normalSignBoard(pageType int32, nowMouth string) (signBoard *SignBoard, err error) {
|
|
|
cpn, conf, player, tz := s.cpn, s.conf, s.GetPlayer(), s.GetTz()
|
|
|
|
|
|
// 签到开始和结束时间
|
|
|
var now = timez.GMTCarbon(tz.GetTz()).Now()
|
|
|
var start carbon.Carbon
|
|
|
var end = timez.GMTCarbon(tz.GetTz()).CreateFromTimestamp(cpn.TEnd).EndOfDay()
|
|
|
if cpn.Status == mtype.FissionCampaignStatusWait {
|
|
|
start = timez.GMTCarbon(tz.GetTz()).CreateFromTimestamp(cpn.TStart)
|
|
|
} else if player.SignStart != 0 {
|
|
|
start = timez.GMTCarbon(tz.GetTz()).CreateFromTimestamp(player.SignStart)
|
|
|
} else {
|
|
|
start = now
|
|
|
}
|
|
|
|
|
|
start = start.StartOfDay()
|
|
|
|
|
|
// 奖品日期
|
|
|
dayReward, lastReward, err := s._dayReward(start, end, player.LoopNum)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 签到数据
|
|
|
signMap, rewardIdMap, openMap, lastMiss, err := s._dataMap(start, now, dayReward, lastReward)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 本周开始和周结束
|
|
|
wStart, wEnd := now.StartOfWeek(), now.EndOfWeek()
|
|
|
|
|
|
// 某个呀的签到板
|
|
|
var mStart carbon.Carbon
|
|
|
switch pageType {
|
|
|
case 1:
|
|
|
mStart = timez.GMTCarbon(tz.GetTz()).ParseByFormat(nowMouth, "Y-n").AddMonth()
|
|
|
case 2:
|
|
|
mStart = timez.GMTCarbon(tz.GetTz()).ParseByFormat(nowMouth, "Y-n").SubMonth()
|
|
|
}
|
|
|
|
|
|
if mStart.IsInvalid() {
|
|
|
mStart = now
|
|
|
}
|
|
|
|
|
|
// 完整月
|
|
|
mStart = mStart.StartOfMonth()
|
|
|
mEnd := mStart.EndOfMonth()
|
|
|
|
|
|
signBoard = &SignBoard{
|
|
|
SignDate: nil,
|
|
|
NowMouth: mStart.ToFormatString("Y-n"),
|
|
|
}
|
|
|
|
|
|
// 之前的时间
|
|
|
nw := mStart.Week()
|
|
|
for i := nw; i > 0; i-- {
|
|
|
s._appendSignDate(mStart.SubDays(i), start, end, wStart, wEnd, mStart, mEnd, rewardIdMap, signMap, openMap, conf.HasCard, lastMiss, signBoard)
|
|
|
}
|
|
|
|
|
|
begin := mStart
|
|
|
for {
|
|
|
if begin.Gte(mEnd) {
|
|
|
break
|
|
|
}
|
|
|
|
|
|
s._appendSignDate(begin, start, end, wStart, wEnd, mStart, mEnd, rewardIdMap, signMap, openMap, conf.HasCard, lastMiss, signBoard)
|
|
|
|
|
|
begin = begin.AddDay()
|
|
|
}
|
|
|
|
|
|
ew := begin.Week()
|
|
|
for i := 0; i < 7-ew; i++ {
|
|
|
s._appendSignDate(begin.AddDays(i), start, end, wStart, wEnd, mStart, mEnd, rewardIdMap, signMap, openMap, conf.HasCard, lastMiss, signBoard)
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 普通签到获得奖品逻辑(旧)
|
|
|
func (s *Sign) _normalReward(sign *model.FissionSignDay, totalNum int32) (signReward *SignReward, recordId []int64, err error) {
|
|
|
cm := cmm.NewCMM(s.Ctx, s.GetDao())
|
|
|
rewards, err := cm.UserAppReward(s.user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if len(rewards) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
reward := rewards[0]
|
|
|
num := totalNum / reward.SignDay
|
|
|
if num == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
player := s.GetPlayer()
|
|
|
m := s.GetDao().FissionRewardRecord.SubTable(player.ID)
|
|
|
count, err := m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(player.ID),
|
|
|
m.RewardID.Eq(reward.ID),
|
|
|
m.RewardType.Eq(mtype.FissionCampaignRewardTypeApp),
|
|
|
).Count()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
can := int64(num) - count
|
|
|
if can == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var addRewards []*model.FissionCampaignReward
|
|
|
for i := can; i > 0; i-- {
|
|
|
addRewards = append(addRewards, reward)
|
|
|
}
|
|
|
|
|
|
return s._signReward(sign, addRewards...)
|
|
|
}
|
|
|
|
|
|
// 阶梯签到获得奖品逻辑(旧)
|
|
|
func (s *Sign) _stepReward(sign *model.FissionSignDay, totalNum int32) (signReward *SignReward, recordId []int64, err error) {
|
|
|
cm := cmm.NewCMM(s.Ctx, s.GetDao())
|
|
|
rewards, err := cm.UserAppReward(s.user, s.GetDao().FissionCampaignReward.Step)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if len(rewards) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
player, conf := s.GetPlayer(), s.GetConf()
|
|
|
|
|
|
var stepMap = make(map[int32]*model.FissionCampaignReward)
|
|
|
for _, v := range rewards {
|
|
|
stepMap[v.Step] = v
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionRewardRecord.SubTable(player.CampaignID)
|
|
|
list, err := m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(player.UserID),
|
|
|
m.RewardType.Eq(mtype.FissionCampaignRewardTypeApp),
|
|
|
).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if conf.IsLoop == mtype.No {
|
|
|
|
|
|
for _, v := range list {
|
|
|
delete(stepMap, v.Step)
|
|
|
}
|
|
|
|
|
|
var addRewards []*model.FissionCampaignReward
|
|
|
for _, reward := range stepMap {
|
|
|
if totalNum < reward.SignDay {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
addRewards = append(addRewards, reward)
|
|
|
}
|
|
|
|
|
|
signReward, recordId, err = s._signReward(sign, addRewards...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
l := len(rewards)
|
|
|
lastReward := rewards[l-1]
|
|
|
|
|
|
signDay := 1 + player.SignDay - player.LoopNum*lastReward.SignDay
|
|
|
nextStep := player.NextStep
|
|
|
if nextStep == 0 {
|
|
|
nextStep = 1
|
|
|
}
|
|
|
if signDay < totalNum {
|
|
|
totalNum = signDay
|
|
|
}
|
|
|
|
|
|
var addLoopNum int32
|
|
|
var addRewards []*model.FissionCampaignReward
|
|
|
for {
|
|
|
|
|
|
stepReward := stepMap[nextStep]
|
|
|
if totalNum < stepReward.SignDay {
|
|
|
break
|
|
|
}
|
|
|
|
|
|
if stepReward.ID == lastReward.ID {
|
|
|
addLoopNum++
|
|
|
nextStep = 1
|
|
|
totalNum -= lastReward.SignDay
|
|
|
|
|
|
} else {
|
|
|
nextStep++
|
|
|
}
|
|
|
|
|
|
addRewards = append(addRewards, stepReward)
|
|
|
}
|
|
|
|
|
|
signReward, recordId, err = s._signReward(sign, addRewards...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
playerM := s.GetDao().FissionSign
|
|
|
s.upPlayer = append(s.upPlayer, playerM.LoopNum.Add(addLoopNum), playerM.NextStep.Value(nextStep))
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
type signState struct {
|
|
|
RewardId int64
|
|
|
SignDay int32
|
|
|
addDay int
|
|
|
}
|
|
|
|
|
|
// 签到板奖品分布(旧)
|
|
|
func (s *Sign) _dayReward(start, end carbon.Carbon, loopNum int32) (dayReward []*signState, lastReward *model.FissionCampaignReward, err error) {
|
|
|
conf := s.GetConf()
|
|
|
rewards, err := cmm.NewCMM(s.Ctx, s.GetDao()).UserAppReward(s.user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if len(rewards) == 0 {
|
|
|
err = workerr.NotFound("not found reward")
|
|
|
return
|
|
|
}
|
|
|
|
|
|
l := len(rewards)
|
|
|
lastReward = rewards[l-1]
|
|
|
|
|
|
// 非阶梯一个奖品,多次获得
|
|
|
if conf.SignType == mtype.FissionCampaignSignTypeNormal {
|
|
|
reward := rewards[0]
|
|
|
|
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if reward == nil {
|
|
|
err = workerr.NotFound("not found reward")
|
|
|
return
|
|
|
}
|
|
|
|
|
|
diff := start.DiffAbsInDays(end) + 1
|
|
|
|
|
|
times := int(diff / int64(reward.SignDay))
|
|
|
dayReward = make([]*signState, times)
|
|
|
for i := 0; i < times; i++ {
|
|
|
day := int32(i+1)*reward.SignDay - 1
|
|
|
dayReward[i] = &signState{
|
|
|
RewardId: reward.ID,
|
|
|
addDay: int(day),
|
|
|
SignDay: reward.SignDay,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 活动奖品,阶梯多奖品
|
|
|
|
|
|
// 不支持阶梯循环
|
|
|
if conf.IsLoop == mtype.No {
|
|
|
dayReward = make([]*signState, 0, len(rewards))
|
|
|
for _, v := range rewards {
|
|
|
dayReward = append(dayReward, &signState{
|
|
|
RewardId: v.ID,
|
|
|
addDay: int(v.SignDay - 1),
|
|
|
SignDay: v.SignDay,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
doLoop := int(loopNum + 1)
|
|
|
|
|
|
for i := 0; i < doLoop; i++ {
|
|
|
for _, v := range rewards {
|
|
|
dayReward = append(dayReward, &signState{
|
|
|
RewardId: v.ID,
|
|
|
addDay: int(v.SignDay-1) + int(lastReward.SignDay)*i,
|
|
|
SignDay: v.SignDay,
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 签到版基础数据(旧)
|
|
|
func (s *Sign) _dataMap(start, now carbon.Carbon, dayReward []*signState, lastReward *model.FissionCampaignReward,
|
|
|
) (signMap map[string]int8, rewardIdMap map[string]int64, openMap map[int64]int, lastMiss string, err error) {
|
|
|
|
|
|
player, conf, tz := s.GetPlayer(), s.GetConf(), s.GetTz()
|
|
|
|
|
|
// 签到的所有数据
|
|
|
sdm := s.GetDao().FissionSignDay
|
|
|
sd, err := sdm.WithContext(s.Ctx).
|
|
|
Select(sdm.SignDate, sdm.RecordIds).
|
|
|
Where(
|
|
|
sdm.UserID.Eq(player.UserID),
|
|
|
sdm.SignDate.Gte(start.ToShortDateString()),
|
|
|
sdm.SignDate.Lte(now.ToShortDateString()),
|
|
|
).Order(sdm.SignDate).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
sdMap := make(map[string][]int64)
|
|
|
for _, day := range sd {
|
|
|
sdMap[day.SignDate] = day.GetRecordIds()
|
|
|
}
|
|
|
|
|
|
rewardIdMap = make(map[string]int64)
|
|
|
var recordIds []int64
|
|
|
signMap = make(map[string]int8)
|
|
|
se := utils.BetweenDay(start, now)
|
|
|
for _, day := range se {
|
|
|
|
|
|
idv, ok := sdMap[day]
|
|
|
|
|
|
if ok {
|
|
|
if len(idv) > 0 {
|
|
|
recordIds = append(recordIds, idv...)
|
|
|
}
|
|
|
signMap[day] = mtype.FissionSignTypeOk
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
signMap[day] = mtype.FissionSignTypeMiss
|
|
|
lastMiss = day
|
|
|
missDay := timez.GMTCarbon(tz.GetTz()).ParseByFormat(day, "Ymd")
|
|
|
if conf.IsContinue == mtype.Yes {
|
|
|
var idx int32
|
|
|
for k, reward := range dayReward {
|
|
|
rewardDay := start.AddDays(reward.addDay)
|
|
|
if missDay.Gt(rewardDay) {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
switch conf.SignType {
|
|
|
case mtype.FissionCampaignSignTypeStep:
|
|
|
dayReward[k].addDay = int(missDay.AddDays(int(reward.SignDay)).DiffAbsInDays(start)) + int(idx*lastReward.SignDay)
|
|
|
if reward.RewardId == lastReward.ID {
|
|
|
idx++
|
|
|
}
|
|
|
case mtype.FissionCampaignSignTypeNormal:
|
|
|
idx++
|
|
|
dayReward[k].addDay = int(missDay.AddDays(int(idx * reward.SignDay)).DiffAbsInDays(start))
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
for k, reward := range dayReward {
|
|
|
if missDay.Gt(start.AddDays(reward.addDay)) {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
dayReward[k].addDay++
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
for _, state := range dayReward {
|
|
|
rewardIdMap[start.AddDays(state.addDay).ToShortDateString()] = state.RewardId
|
|
|
}
|
|
|
|
|
|
if len(recordIds) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 领奖数据
|
|
|
openMap = make(map[int64]int)
|
|
|
recordM := s.GetDao().FissionRewardRecord.SubTable(player.CampaignID)
|
|
|
records, err := recordM.WithContext(s.Ctx).Where(recordM.ID.In(recordIds...)).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
for _, record := range records {
|
|
|
openMap[record.RewardID]++
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 签到板追加数据(旧)
|
|
|
func (s *Sign) _appendSignDate(dt, start, end, wStart, wEnd, mStart, mEnd carbon.Carbon, rewardIdMap map[string]int64, signMap map[string]int8, openMap map[int64]int, hashCard int8, lastMiss string, res *SignBoard) {
|
|
|
dateStr := dt.ToShortDateString()
|
|
|
one := &SignBoardOne{
|
|
|
Y: fmt.Sprint(dt.Year()),
|
|
|
M: fmt.Sprint(dt.Month()),
|
|
|
D: fmt.Sprint(dt.Day()),
|
|
|
SignIn: 0,
|
|
|
Ban: dt.Lt(start) || dt.Gt(end),
|
|
|
RewardId: rewardIdMap[dateStr],
|
|
|
Open: false,
|
|
|
NowWeek: dt.Gte(wStart) && dt.Lte(wEnd),
|
|
|
NowDay: dt.IsToday(),
|
|
|
LastMiss: lastMiss != "" && lastMiss == dateStr,
|
|
|
NowMouth: dt.Gte(mStart) && dt.Lte(mEnd),
|
|
|
}
|
|
|
|
|
|
if st, ok := signMap[dateStr]; ok {
|
|
|
one.SignIn = utils.Ternary[int32](st == mtype.FissionSignTypeMiss, 2, 1)
|
|
|
one.Ban = !one.Ban && st == mtype.FissionSignTypeMiss && hashCard == mtype.No // 不能补签禁用
|
|
|
}
|
|
|
|
|
|
if open, ok := openMap[one.RewardId]; ok {
|
|
|
one.Open = open > 0
|
|
|
openMap[one.RewardId]--
|
|
|
}
|
|
|
|
|
|
res.SignDate = append(res.SignDate, one)
|
|
|
}
|
|
|
|
|
|
// 签到成功 (旧)
|
|
|
func (s *Sign) _signOk(signDay *model.FissionSignDay) (reward *SignReward, err error) {
|
|
|
continueNum, maxContinue, _, err := s._continueNum()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
player, conf := s.GetPlayer(), s.GetConf()
|
|
|
playerM := s.GetDao().FissionSign
|
|
|
|
|
|
s.upPlayer = append(s.upPlayer,
|
|
|
playerM.SignContinue.Value(continueNum),
|
|
|
playerM.MaxContinue.Value(maxContinue),
|
|
|
)
|
|
|
|
|
|
if player.SignStart == 0 {
|
|
|
s.upPlayer = append(s.upPlayer, playerM.SignStart.Value(time.Now().Unix()))
|
|
|
}
|
|
|
|
|
|
var totalNum = player.SignDay + 1
|
|
|
if conf.IsLoop == mtype.Yes {
|
|
|
totalNum = continueNum
|
|
|
} else if conf.IsContinue == mtype.Yes {
|
|
|
totalNum = maxContinue
|
|
|
}
|
|
|
|
|
|
var recordIds []int64
|
|
|
switch conf.SignType {
|
|
|
case mtype.FissionCampaignSignTypeNormal:
|
|
|
reward, recordIds, err = s._normalReward(signDay, totalNum)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
case mtype.FissionCampaignSignTypeStep:
|
|
|
reward, recordIds, err = s._stepReward(signDay, totalNum)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 绑定数据
|
|
|
if len(recordIds) > 0 {
|
|
|
sdm := s.GetDao().FissionSignDay
|
|
|
_, err = sdm.WithContext(s.Ctx).Where(sdm.ID.Eq(signDay.ID)).UpdateSimple(sdm.RecordIds.Value(utils.Join(recordIds, consts.JoinComma)))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 更新玩家数据
|
|
|
_, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple(s.upPlayer...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 更新统计数据
|
|
|
statM := s.GetDao().FissionUserStat
|
|
|
_, err = statM.WithContext(s.Ctx).Where(statM.UserID.Eq(player.UserID)).UpdateSimple(statM.SignNum.Add(1), statM.SignRewardNum.Add(int64(len(recordIds))))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|