|
|
package validevents
|
|
|
|
|
|
import (
|
|
|
"joybuywork/internal/app"
|
|
|
"joybuywork/internal/config"
|
|
|
"joybuywork/internal/consts"
|
|
|
"joybuywork/internal/consts/ckey"
|
|
|
"joybuywork/internal/repository/cache"
|
|
|
"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/players"
|
|
|
"joybuywork/internal/service/provider/pusher"
|
|
|
"joybuywork/internal/service/queue/producer"
|
|
|
"joybuywork/internal/service/queue/types"
|
|
|
"joybuywork/internal/utils"
|
|
|
"joybuywork/internal/utils/lockdo"
|
|
|
"joybuywork/internal/utils/timez"
|
|
|
"joybuywork/internal/utils/verify"
|
|
|
"fmt"
|
|
|
"math/rand"
|
|
|
"strings"
|
|
|
"time"
|
|
|
|
|
|
"gorm.io/gen"
|
|
|
)
|
|
|
|
|
|
type condFinishOne struct {
|
|
|
condId int64 // 条件id
|
|
|
num int64 // 用户
|
|
|
userNum int64 // 完成人数
|
|
|
}
|
|
|
|
|
|
type condTotalOne struct {
|
|
|
condId int64 // 条件id
|
|
|
total float64 // 累计值
|
|
|
}
|
|
|
|
|
|
type event struct {
|
|
|
*base
|
|
|
|
|
|
tasks []*model.FissionCampaignTask // 校验完之后,剩下的用户可以完成的任务
|
|
|
|
|
|
taskDoneMap map[int64]int64
|
|
|
taskDayDoneMap map[int64]int64
|
|
|
taskWeekDoneMap map[int64]int64
|
|
|
|
|
|
condDoneMap map[int64]int64
|
|
|
condDayDoneMap map[int64]int64
|
|
|
condWeekDoneMap map[int64]int64
|
|
|
|
|
|
lvLimitMap map[int64][]string
|
|
|
preCondMap map[int32]struct{}
|
|
|
}
|
|
|
|
|
|
func (s *event) event(user *model.FissionUser, callbacks ...taskDoneCallback) (data eventData, err error) {
|
|
|
err = s.unlockReward(user, callbacks...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
conf, err := cache.NewCampaignTicket(s.Ctx).FindByMark(user.CampaignID, mtype.FissionCampaignTicketCustom)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if conf == nil || conf.Open == mtype.No {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
conds, userCondMap, err := s.getUserCondMap(user, false)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if len(conds) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
switch conf.BothType {
|
|
|
case mtype.FissionCampaignTicketBothTypeOne:
|
|
|
err = s.acceptCheckOne(user, conds)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
case mtype.FissionCampaignTicketBothTypeAll:
|
|
|
err = s.acceptCheckAll(user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果接收事件验证校验过后没有任务了,那么就不用去计算了
|
|
|
if len(s.tasks) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 过期数据处理
|
|
|
err = s.userCondExp(conds, userCondMap, conf.BothType)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
switch conf.BothType {
|
|
|
case mtype.FissionCampaignTicketBothTypeOne:
|
|
|
return s.one(user, conds, userCondMap, callbacks...)
|
|
|
case mtype.FissionCampaignTicketBothTypeAll:
|
|
|
return s.all(user, conds, userCondMap, callbacks...)
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 所有任务完成逻辑
|
|
|
func (s *event) all(user *model.FissionUser, allConds []*model.FissionCampaignCond, userCondMap map[int64]*model.FissionUserCond, callbacks ...taskDoneCallback) (data eventData, err error) {
|
|
|
var task *model.FissionCampaignTask
|
|
|
for _, v := range s.tasks {
|
|
|
if v.TaskMark == mtype.FissionCampaignTaskMarkCondAll {
|
|
|
task = v
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if task == nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 过滤被被限制了的事件
|
|
|
conds, err := s.condLimit(user, allConds, task)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 过滤到没有到没有可以完成的事件
|
|
|
if len(conds) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 接收到key对应的值
|
|
|
var valMap = make(map[string][]string)
|
|
|
for _, v := range s.Req.EventData {
|
|
|
valMap[v.EventKey] = append(valMap[v.EventKey], v.EventVal)
|
|
|
}
|
|
|
|
|
|
var condIdMap = make(map[int64]*model.FissionCampaignCond)
|
|
|
for _, v := range allConds {
|
|
|
condIdMap[v.ID] = v
|
|
|
}
|
|
|
|
|
|
var condTotal = make(map[int64]string) // 累计条件下的已累计的值
|
|
|
var condTotalFinishNumMap = make(map[int64]int64) // 累计条件下完成的次数
|
|
|
for _, v := range userCondMap {
|
|
|
cond := condIdMap[v.CondID]
|
|
|
if cond.IfCond == mtype.FissionCampaignCondIfCondTotal {
|
|
|
condTotal[cond.ID] = v.Total
|
|
|
condTotalFinishNumMap[cond.ID] = 0
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var userCondRecord []*model.FissionUserCondRecord
|
|
|
for _, cond := range conds {
|
|
|
|
|
|
if cond.Event != s.Req.Event {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
condCpnLimit, condDayLimit, condWeekLimit := s.condDoneMap[cond.ID], s.condDayDoneMap[cond.ID], s.condWeekDoneMap[cond.ID]
|
|
|
userCond := userCondMap[cond.ID]
|
|
|
total, num := userCond.Total, userCond.Num
|
|
|
var doneNum int64
|
|
|
for _, val := range valMap[cond.EventKey] {
|
|
|
|
|
|
// 任务被限制完成了
|
|
|
if s._beLimit(task, condCpnLimit, condDayLimit, condWeekLimit, user) {
|
|
|
break
|
|
|
}
|
|
|
|
|
|
switch cond.IfCond {
|
|
|
case mtype.FissionCampaignCondIfCondEq:
|
|
|
if cond.EventVal != val {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
condCpnLimit++
|
|
|
condDayLimit++
|
|
|
condWeekLimit++
|
|
|
doneNum = 1
|
|
|
case mtype.FissionCampaignCondIfCondGte:
|
|
|
if !utils.NumberStrCompareGte(val, cond.EventVal) {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
condCpnLimit++
|
|
|
condDayLimit++
|
|
|
condWeekLimit++
|
|
|
doneNum = 1
|
|
|
case mtype.FissionCampaignCondIfCondTotal:
|
|
|
total = utils.StrAdd(total, val)
|
|
|
|
|
|
// 计算一下完成的次数
|
|
|
doneRes := utils.CondTotalFinishNum(total, cond.EventVal, func(doneNum int32) bool {
|
|
|
condCpnLimit++
|
|
|
condDayLimit++
|
|
|
condWeekLimit++
|
|
|
return s._beTaskNumLimit(task, condCpnLimit, condDayLimit, condWeekLimit)
|
|
|
})
|
|
|
|
|
|
total = doneRes.Remain
|
|
|
doneNum = int64(doneRes.Num)
|
|
|
|
|
|
// 统计完成次数追加
|
|
|
condTotalFinishNumMap[cond.ID] += doneNum
|
|
|
|
|
|
// 累计总值
|
|
|
s._condTotal(cond.ID, val)
|
|
|
}
|
|
|
|
|
|
// 如果事件被消费了
|
|
|
if doneNum > 0 {
|
|
|
// 加一条记录
|
|
|
userCondRecord = append(userCondRecord, withdefault.FissionUserCondRecord(&model.FissionUserCondRecord{
|
|
|
CampaignID: user.CampaignID,
|
|
|
UserID: user.ID,
|
|
|
CondID: cond.ID,
|
|
|
Val: val,
|
|
|
IsUse: mtype.Yes,
|
|
|
BehaviorTime: s.Req.BehaviorTime,
|
|
|
}))
|
|
|
|
|
|
// 完成次数条件
|
|
|
for i := 0; i < int(doneNum); i++ {
|
|
|
s._condFinish(user, cond.ID, val, num == 0)
|
|
|
num++
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
userCondMap[cond.ID].Num += doneNum // 完成次数
|
|
|
userCondMap[cond.ID].CountNum += doneNum // 可以计算的完成次数
|
|
|
userCondMap[cond.ID].Total = total // 累计值
|
|
|
|
|
|
// 加限制值
|
|
|
err = s._addCondLimit(user, task, cond, doneNum)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 把有效的记录记录一下.
|
|
|
err = s._addUserCondRecord(user, userCondRecord, conds, task)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var fl int // 完成的次数
|
|
|
|
|
|
// 更新一下条件数据
|
|
|
defer func() {
|
|
|
m := s.GetDao().FissionUserCond
|
|
|
for _, v := range userCondMap {
|
|
|
_, _ = m.WithContext(s.Ctx).Where(m.ID.Eq(v.ID)).UpdateSimple(
|
|
|
m.Num.Value(v.Num),
|
|
|
m.CountNum.Value(v.CountNum-int64(fl)),
|
|
|
m.Total.Value(v.Total),
|
|
|
)
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
// 看看最小可计算数是谁,就是达标次数
|
|
|
for _, userCond := range userCondMap {
|
|
|
if userCond.CountNum == 0 {
|
|
|
fl = 0
|
|
|
break
|
|
|
}
|
|
|
|
|
|
if fl == 0 || fl > int(userCond.CountNum) {
|
|
|
fl = int(userCond.CountNum)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if fl == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
data.props = make(map[string]int32)
|
|
|
data.targetNum = int32(fl) // 达标数
|
|
|
|
|
|
var callbackTasks = make([]*model.FissionCampaignTask, 0, fl) // 要回调的任务
|
|
|
var addTaskRecord = make([]*model.FissionUserTaskRecord, 0, fl) // 任务记录
|
|
|
var rewardIds []int64 // 获得的奖品
|
|
|
var addTaskRewards []*model.FissionUserTaskReward // 待领取记录
|
|
|
for i := 0; i < fl; i++ {
|
|
|
|
|
|
record := withdefault.FissionUserTaskRecord(&model.FissionUserTaskRecord{
|
|
|
CreatedAt: s.Req.BehaviorTime,
|
|
|
CampaignID: user.CampaignID,
|
|
|
UserID: user.ID,
|
|
|
TaskID: task.ID,
|
|
|
IndicatorData: "[]",
|
|
|
Chance: task.Chance,
|
|
|
LimitProp: 0,
|
|
|
})
|
|
|
|
|
|
addTaskRecord = append(addTaskRecord, record)
|
|
|
callbackTasks = append(callbackTasks, task)
|
|
|
|
|
|
if task.AwardMode == mtype.FissionCampaignTaskAwardModeAuto {
|
|
|
switch task.PropMark {
|
|
|
case mtype.FissionCampaignRewardPropMarkReward:
|
|
|
data.props[task.PropMark] += 1
|
|
|
rewardIds = append(rewardIds, task.RewardID)
|
|
|
case mtype.FissionCampaignRewardPropMarkChance:
|
|
|
data.props[task.PropMark] += task.Chance
|
|
|
}
|
|
|
} else {
|
|
|
addTaskRewards = append(addTaskRewards, withdefault.FissionUserTaskReward(&model.FissionUserTaskReward{
|
|
|
UserID: user.ID,
|
|
|
CampaignID: user.CampaignID,
|
|
|
TaskID: task.ID,
|
|
|
ReceiveTime: 0,
|
|
|
TaskRecordID: record.ID,
|
|
|
}))
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
for _, callback := range callbacks {
|
|
|
err = callback(user, callbackTasks)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(addTaskRecord) > 0 {
|
|
|
err = s._addUserTaskRecord(addTaskRecord...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
for _, v := range addTaskRecord {
|
|
|
if s.reportType == mtype.FissionCampaignReportTypeNew {
|
|
|
s.MP().InApp(user).FinishTask(v.CreatedAt, v.TaskID)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
err = s._addTaskFinish(user, task, int64(fl))
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(rewardIds) > 0 {
|
|
|
_, err = s._taskReward(user, rewardIds)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(addTaskRewards) > 0 {
|
|
|
err = s.GetDao().FissionUserTaskReward.WithContext(s.Ctx).Create(addTaskRewards...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 任一任务完成
|
|
|
func (s *event) one(user *model.FissionUser, conds []*model.FissionCampaignCond, userCondMap map[int64]*model.FissionUserCond, callbacks ...taskDoneCallback) (data eventData, err error) {
|
|
|
// 接收到key对应的值
|
|
|
var valMap = make(map[string][]string)
|
|
|
for _, v := range s.Req.EventData {
|
|
|
valMap[v.EventKey] = append(valMap[v.EventKey], v.EventVal)
|
|
|
}
|
|
|
|
|
|
// 活动的条件数据
|
|
|
var condIdMap = make(map[int64]*model.FissionCampaignCond)
|
|
|
for _, v := range conds {
|
|
|
condIdMap[v.ID] = v
|
|
|
}
|
|
|
|
|
|
var condTotal = make(map[int64]string) // 累计条件下的已累计的值
|
|
|
for _, v := range userCondMap {
|
|
|
cond := condIdMap[v.CondID]
|
|
|
if cond.IfCond == mtype.FissionCampaignCondIfCondTotal {
|
|
|
condTotal[cond.ID] = v.Total
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionUserCond
|
|
|
cm := cmm.NewCMM(s.Ctx, s.GetDao())
|
|
|
var taskDoneMap = make(map[int64]int64) // 任务完成次数
|
|
|
var userCondRecord []*model.FissionUserCondRecord
|
|
|
// 可以完成的任务
|
|
|
for _, v := range s.tasks {
|
|
|
// 找到完成这个任务需要完成的条件
|
|
|
cond, ok := condIdMap[utils.FissionCampaignTaskMarkCondOneCondId(v.TaskMark)]
|
|
|
if !ok || !cm.EventCanTotal(cond, user.SubUserID, s.Req.AdsCondId, user.JoinAt, s.Req.BehaviorTime) { // 不存在,或者事件是验证目标类型不通过都不处理
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
cpnLimit, dayLimit, weekLimit := s.taskDoneMap[v.ID], s.taskDayDoneMap[v.ID], s.taskWeekDoneMap[v.ID]
|
|
|
userCond := userCondMap[cond.ID]
|
|
|
total, num := userCond.Total, userCond.Num
|
|
|
|
|
|
// 遍历接收到的key,计算任务完成的次数
|
|
|
for _, val := range valMap[cond.EventKey] {
|
|
|
|
|
|
// 任务被限制完成了
|
|
|
if s._beLimit(v, cpnLimit, dayLimit, weekLimit, user) {
|
|
|
break
|
|
|
}
|
|
|
|
|
|
var doneNum int64
|
|
|
switch cond.IfCond {
|
|
|
case mtype.FissionCampaignCondIfCondEq:
|
|
|
if cond.EventVal != val {
|
|
|
continue
|
|
|
}
|
|
|
cpnLimit++
|
|
|
dayLimit++
|
|
|
weekLimit++
|
|
|
doneNum = 1
|
|
|
case mtype.FissionCampaignCondIfCondGte:
|
|
|
if !utils.NumberStrCompareGte(val, cond.EventVal) {
|
|
|
continue
|
|
|
}
|
|
|
cpnLimit++
|
|
|
dayLimit++
|
|
|
weekLimit++
|
|
|
doneNum = 1
|
|
|
case mtype.FissionCampaignCondIfCondTotal:
|
|
|
total = utils.StrAdd(total, val)
|
|
|
|
|
|
// 计算一下完成的次数
|
|
|
doneRes := utils.CondTotalFinishNum(total, cond.EventVal, func(doneNum int32) bool {
|
|
|
cpnLimit++
|
|
|
dayLimit++
|
|
|
weekLimit++
|
|
|
return s._beTaskNumLimit(v, cpnLimit, dayLimit, weekLimit)
|
|
|
})
|
|
|
|
|
|
total = doneRes.Remain
|
|
|
doneNum = int64(doneRes.Num)
|
|
|
|
|
|
// 累计总值
|
|
|
s._condTotal(cond.ID, val)
|
|
|
}
|
|
|
|
|
|
// 如果事件被消费了
|
|
|
if doneNum > 0 {
|
|
|
// 加任务完成次数
|
|
|
taskDoneMap[v.ID] += doneNum
|
|
|
|
|
|
// 加一条记录
|
|
|
userCondRecord = append(userCondRecord, withdefault.FissionUserCondRecord(&model.FissionUserCondRecord{
|
|
|
CampaignID: user.CampaignID,
|
|
|
UserID: user.ID,
|
|
|
CondID: cond.ID,
|
|
|
Val: val,
|
|
|
IsUse: mtype.Yes,
|
|
|
BehaviorTime: s.Req.BehaviorTime,
|
|
|
}))
|
|
|
|
|
|
// 完成次数条件
|
|
|
for i := 0; i < int(doneNum); i++ {
|
|
|
s._condFinish(user, cond.ID, val, num == 0)
|
|
|
num++
|
|
|
switch num {
|
|
|
case 1:
|
|
|
err = s._invokePreCond(user, mtype.FissionCampaignTaskPreCondTask1)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
case 2:
|
|
|
err = s._invokePreCond(user, mtype.FissionCampaignTaskPreCondTask2)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 更新一下完成次数
|
|
|
switch cond.IfCond {
|
|
|
case mtype.FissionCampaignCondIfCondTotal:
|
|
|
// 更新一下累计值和完成次数
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(userCond.ID)).UpdateSimple(m.Num.Add(taskDoneMap[v.ID]), m.Total.Value(total))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
default:
|
|
|
// 更新一下用户条件的完成次数
|
|
|
if fNum := taskDoneMap[v.ID]; fNum > 0 {
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(userCond.ID)).UpdateSimple(m.Num.Add(fNum))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 把有效的记录记录一下.
|
|
|
err = s._addUserCondRecord(user, userCondRecord, conds, nil)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
data.props = make(map[string]int32)
|
|
|
|
|
|
// 完成任务
|
|
|
var rewardIds []int64
|
|
|
var callbackTasks []*model.FissionCampaignTask
|
|
|
var add []*model.FissionUserTaskRecord
|
|
|
var addTaskRewards []*model.FissionUserTaskReward // 待领取记录
|
|
|
for _, task := range s.tasks {
|
|
|
fNum := taskDoneMap[task.ID]
|
|
|
if fNum == 0 {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
err = s._addTaskFinish(user, task, fNum)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 达标数
|
|
|
data.targetNum += int32(fNum)
|
|
|
|
|
|
// 完成一次回调一次
|
|
|
for i := 0; i < int(fNum); i++ {
|
|
|
record := withdefault.FissionUserTaskRecord(&model.FissionUserTaskRecord{
|
|
|
CreatedAt: s.Req.BehaviorTime,
|
|
|
CampaignID: user.CampaignID,
|
|
|
UserID: user.ID,
|
|
|
TaskID: task.ID,
|
|
|
IndicatorData: "[]",
|
|
|
Chance: task.Chance,
|
|
|
LimitProp: 0,
|
|
|
})
|
|
|
|
|
|
add = append(add, record)
|
|
|
callbackTasks = append(callbackTasks, task)
|
|
|
|
|
|
if task.AwardMode == mtype.FissionCampaignTaskAwardModeAuto {
|
|
|
switch task.PropMark {
|
|
|
case mtype.FissionCampaignRewardPropMarkReward:
|
|
|
data.props[task.PropMark] += 1
|
|
|
rewardIds = append(rewardIds, task.RewardID)
|
|
|
case mtype.FissionCampaignRewardPropMarkChance:
|
|
|
data.props[task.PropMark] += task.Chance
|
|
|
players.AddTaskTip(s.Ctx, user.ID, mtype.FissionCampaignRewardPropMarkChance, task.Chance, 0)
|
|
|
case mtype.FissionCampaignRewardPropMarkPoint:
|
|
|
data.props[task.PropMark] += task.Chance
|
|
|
rewardIds = append(rewardIds, task.RewardID)
|
|
|
}
|
|
|
} else {
|
|
|
addTaskRewards = append(addTaskRewards, withdefault.FissionUserTaskReward(&model.FissionUserTaskReward{
|
|
|
UserID: user.ID,
|
|
|
CampaignID: user.CampaignID,
|
|
|
TaskID: task.ID,
|
|
|
ReceiveTime: 0,
|
|
|
TaskRecordID: record.ID,
|
|
|
}))
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(callbackTasks) > 0 {
|
|
|
for _, callback := range callbacks {
|
|
|
err = callback(user, callbackTasks)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(rewardIds) > 0 {
|
|
|
_, err = s._taskReward(user, rewardIds)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(add) > 0 {
|
|
|
err = s._addUserTaskRecord(add...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
for _, v := range add {
|
|
|
if s.reportType == mtype.FissionCampaignReportTypeNew {
|
|
|
s.MP().InApp(user).FinishTask(v.CreatedAt, v.TaskID)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(addTaskRewards) > 0 {
|
|
|
err = s.GetDao().FissionUserTaskReward.WithContext(s.Ctx).Create(addTaskRewards...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 获取用户对应条件完成状态hash表数据
|
|
|
func (s *event) getUserCondMap(user *model.FissionUser, unlockReward bool) (conds []*model.FissionCampaignCond, data map[int64]*model.FissionUserCond, err error) {
|
|
|
condM := s.GetDao().FissionCampaignCond
|
|
|
var wheres = []gen.Condition{
|
|
|
condM.CampaignID.Eq(user.CampaignID),
|
|
|
condM.IsDel.Eq(mtype.No),
|
|
|
}
|
|
|
|
|
|
if unlockReward {
|
|
|
wheres = append(wheres, condM.RewardID.Gt(0))
|
|
|
} else {
|
|
|
wheres = append(wheres, condM.RewardID.Eq(0))
|
|
|
}
|
|
|
|
|
|
conds, err = condM.WithContext(s.Ctx).Where(wheres...).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var condIds = make([]int64, 0, len(conds))
|
|
|
for _, cond := range conds {
|
|
|
condIds = append(condIds, cond.ID)
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionUserCond
|
|
|
list, err := m.WithContext(s.Ctx).Where(m.UserID.Eq(user.ID), m.CondID.In(condIds...)).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
data = make(map[int64]*model.FissionUserCond)
|
|
|
for _, v := range list {
|
|
|
data[v.CondID] = v
|
|
|
}
|
|
|
|
|
|
var add []*model.FissionUserCond
|
|
|
for _, condId := range condIds {
|
|
|
if _, ok := data[condId]; !ok {
|
|
|
add = append(add, withdefault.FissionUserCond(&model.FissionUserCond{
|
|
|
CampaignID: user.CampaignID,
|
|
|
UserID: user.ID,
|
|
|
CondID: condId,
|
|
|
Num: 0,
|
|
|
Total: "",
|
|
|
CountNum: 0,
|
|
|
}))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(add) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = m.WithContext(s.Ctx).Create(add...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
for _, v := range add {
|
|
|
data[v.CondID] = v
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 看看需不需要做一些过期处理
|
|
|
func (s *event) userCondExp(conds []*model.FissionCampaignCond, data map[int64]*model.FissionUserCond, bothType int8) (err error) {
|
|
|
if bothType == mtype.FissionCampaignTicketBothTypeAll {
|
|
|
task := s.tasks[0]
|
|
|
var start, end int64
|
|
|
if task.DayLimit > 0 {
|
|
|
_, start, end = timez.GMTStartAndEndTs(s.tOffset, s.Req.BehaviorTime)
|
|
|
} else if task.WeekLimit > 0 {
|
|
|
start, end = timez.GetWeekEnd(s.tOffset, int32(task.WeekNum))
|
|
|
}
|
|
|
|
|
|
if start == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var expId []int64
|
|
|
for _, cond := range conds {
|
|
|
if data[cond.ID].TotalExp < start {
|
|
|
data[cond.ID].TotalExp = end
|
|
|
data[cond.ID].Total = ""
|
|
|
data[cond.ID].CountNum = 0
|
|
|
expId = append(expId, data[cond.ID].ID)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(expId) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionUserCond
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.In(expId...)).UpdateSimple(
|
|
|
m.TotalExp.Value(end),
|
|
|
m.Total.Value(""),
|
|
|
m.CountNum.Value(0),
|
|
|
)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 完成任一任务
|
|
|
var taskMap = make(map[string]int64)
|
|
|
for _, cond := range conds {
|
|
|
taskMap[utils.FissionCampaignTaskMarkCondOneVal(cond.ID)] = cond.ID
|
|
|
}
|
|
|
|
|
|
for _, task := range s.tasks {
|
|
|
var start, end int64
|
|
|
if task.DayLimit > 0 {
|
|
|
_, start, end = timez.GMTStartAndEndTs(s.tOffset, s.Req.BehaviorTime)
|
|
|
} else if task.WeekLimit > 0 {
|
|
|
start, end = timez.GetWeekEnd(s.tOffset, int32(task.WeekNum))
|
|
|
}
|
|
|
|
|
|
if start == 0 {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
condId, ok := taskMap[task.TaskMark]
|
|
|
if ok && data[condId].TotalExp < start {
|
|
|
data[condId].TotalExp = end
|
|
|
data[condId].Total = ""
|
|
|
|
|
|
m := s.GetDao().FissionUserCond
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(data[condId].ID)).UpdateSimple(
|
|
|
m.TotalExp.Value(end),
|
|
|
m.Total.Value(""),
|
|
|
m.CountNum.Value(0),
|
|
|
)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 接收校验任一条件完成的事件
|
|
|
func (s *event) acceptCheckAll(user *model.FissionUser) (err error) {
|
|
|
m := s.GetDao().FissionCampaignTask
|
|
|
tasks, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(user.CampaignID), m.TaskMark.Eq(mtype.FissionCampaignTaskMarkCondAll), m.IsDel.Eq(mtype.No)).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return s.taskLimit(user, tasks)
|
|
|
}
|
|
|
|
|
|
// 接收校验任一条件完成的事件
|
|
|
func (s *event) acceptCheckOne(user *model.FissionUser, list []*model.FissionCampaignCond) (err error) {
|
|
|
var t = utils.Ternary[int32](s.Req.EventType == 0, mtype.FissionCampaignCondEventTypeCustom, s.Req.EventType)
|
|
|
|
|
|
var keys = make(map[string]struct{}, len(s.Req.EventData))
|
|
|
for _, v := range s.Req.EventData {
|
|
|
keys[fmt.Sprintf("%s_%s_%d", s.Req.Event, v.EventKey, t)] = struct{}{}
|
|
|
}
|
|
|
|
|
|
var conds []*model.FissionCampaignCond
|
|
|
for _, v := range list {
|
|
|
if _, ok := keys[fmt.Sprintf("%s_%s_%d", v.Event, v.EventKey, t)]; ok {
|
|
|
conds = append(conds, v)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var marks []string
|
|
|
for _, v := range conds {
|
|
|
marks = append(marks, utils.FissionCampaignTaskMarkCondOneVal(v.ID))
|
|
|
}
|
|
|
|
|
|
if len(marks) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionCampaignTask
|
|
|
tasks, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(user.CampaignID), m.TaskMark.In(marks...), m.IsDel.Eq(mtype.No)).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return s.taskLimit(user, tasks)
|
|
|
}
|
|
|
|
|
|
// 任务已经被限制
|
|
|
func (s *event) taskLimit(user *model.FissionUser, tasks []*model.FissionCampaignTask) (err error) {
|
|
|
var userId = user.ID
|
|
|
var preCond []int32
|
|
|
var levelLimit = make(map[int64][]int64)
|
|
|
for _, task := range tasks {
|
|
|
var fLimit bool
|
|
|
fLimit, err = s._fissionLimit(user, task)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if fLimit {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
if task.TaskLimit > 0 {
|
|
|
var num int64
|
|
|
num, err = s._cpnNum(userId, task.ID)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if num >= int64(task.TaskLimit) {
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if task.DayLimit > 0 {
|
|
|
var num int64
|
|
|
num, err = s._dayNum(userId, task.ID)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if num >= int64(task.DayLimit) {
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if task.WeekLimit > 0 {
|
|
|
var num int64
|
|
|
num, err = s._weekNum(userId, task.ID, int32(task.WeekNum))
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if num >= int64(task.WeekLimit) {
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if task.LevelLimit != "" {
|
|
|
levelLimit[task.ID] = task.GetLevelLimit()
|
|
|
}
|
|
|
|
|
|
if task.HasPre == mtype.Yes {
|
|
|
preCond = append(preCond, task.PreCond)
|
|
|
}
|
|
|
|
|
|
s.tasks = append(s.tasks, task)
|
|
|
}
|
|
|
|
|
|
err = s._levelLimit(levelLimit)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return s._preCond(userId, preCond)
|
|
|
}
|
|
|
|
|
|
func (s *event) _fissionLimit(user *model.FissionUser, task *model.FissionCampaignTask) (ok bool, err error) {
|
|
|
switch s.cpn.FissionID {
|
|
|
case consts.IdKeep:
|
|
|
var kg *players.KeepDog
|
|
|
kg, err = players.NewKeepDog(s.Ctx, user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return kg.TaskLimit(task)
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 用户等级限制
|
|
|
func (s *event) _levelLimit(taskLvIdMap map[int64][]int64) (err error) {
|
|
|
|
|
|
var titleMap = make(map[int64]string)
|
|
|
var ids []int64
|
|
|
for _, lvIds := range taskLvIdMap {
|
|
|
for _, lvId := range lvIds {
|
|
|
if _, ok := titleMap[lvId]; !ok {
|
|
|
titleMap[lvId] = ""
|
|
|
ids = append(ids, lvId)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
s.lvLimitMap = make(map[int64][]string)
|
|
|
|
|
|
if len(ids) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionUserLevel
|
|
|
list, err := m.WithContext(s.Ctx).Where(m.ID.In(ids...), m.DeletedAt.Eq(0)).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
for _, v := range list {
|
|
|
titleMap[v.ID] = v.Mark
|
|
|
}
|
|
|
|
|
|
for id, lvIds := range taskLvIdMap {
|
|
|
for _, lvId := range lvIds {
|
|
|
s.lvLimitMap[id] = append(s.lvLimitMap[id], titleMap[lvId])
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 前置任务
|
|
|
func (s *event) _preCond(userId int64, preCond []int32) (err error) {
|
|
|
s.preCondMap = make(map[int32]struct{}, len(preCond))
|
|
|
|
|
|
if len(preCond) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionUserPreCond
|
|
|
done, err := m.WithContext(s.Ctx).Select(m.PreCond).Where(m.UserID.Eq(userId), m.PreCond.In(preCond...), m.ExpiredAt.Gt(time.Now().Unix())).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
for _, v := range done {
|
|
|
s.preCondMap[v.PreCond] = struct{}{}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 活动内限制
|
|
|
func (s *event) _cpnNum(userId, taskId int64) (num int64, err error) {
|
|
|
num, err = s._taskFinishNum(userId, taskId)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if s.taskDoneMap == nil {
|
|
|
s.taskDoneMap = make(map[int64]int64)
|
|
|
}
|
|
|
|
|
|
s.taskDoneMap[taskId] = num
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 当天任务完成数
|
|
|
func (s *event) _dayNum(userId, taskId int64) (num int64, err error) {
|
|
|
day, start, end := timez.GMTStartAndEndTs(s.tOffset, s.Req.BehaviorTime)
|
|
|
|
|
|
key := ckey.FissionUserTaskDayLimit(day, userId, taskId)
|
|
|
num, err = lockdo.Int64(s.Ctx, key, func() (num int64, err error) {
|
|
|
m := s.GetDao().FissionUserTaskRecord
|
|
|
return m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(userId),
|
|
|
m.TaskID.Eq(taskId),
|
|
|
m.CreatedAt.Gte(start),
|
|
|
m.CreatedAt.Lte(end),
|
|
|
).Count()
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if s.taskDayDoneMap == nil {
|
|
|
s.taskDayDoneMap = make(map[int64]int64)
|
|
|
}
|
|
|
|
|
|
s.taskDayDoneMap[taskId] = num
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 周任务完成数
|
|
|
func (s *event) _weekNum(userId, taskId int64, weekNum int32) (num int64, err error) {
|
|
|
start, end := timez.GetWeekEnd(s.tOffset, weekNum)
|
|
|
|
|
|
key := ckey.FissionUserWeekLimit(start, userId, taskId)
|
|
|
num, err = lockdo.Int64(s.Ctx, key, func() (num int64, err error) {
|
|
|
m := s.GetDao().FissionUserTaskRecord
|
|
|
return m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(userId),
|
|
|
m.TaskID.Eq(taskId),
|
|
|
m.CreatedAt.Between(start, end),
|
|
|
).Count()
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if s.taskWeekDoneMap == nil {
|
|
|
s.taskWeekDoneMap = make(map[int64]int64)
|
|
|
}
|
|
|
|
|
|
s.taskWeekDoneMap[taskId] = num
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 判断是否被限制了
|
|
|
func (s *event) _beLimit(task *model.FissionCampaignTask, cpnLimit, dayLimit, weekLimit int64, user *model.FissionUser) bool {
|
|
|
|
|
|
// 用户等级限制
|
|
|
if task.LevelLimit != "" && s._beLevelLimit(task.ID, user.LevelMark) {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
// 语言限制
|
|
|
if lm := task.GetLangMarks(); len(lm) > 0 && !verify.InArray(user.LangMark, lm...) {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
// 有前置任务
|
|
|
if task.HasPre == mtype.Yes {
|
|
|
if _, ok := s.preCondMap[task.PreCond]; !ok {
|
|
|
return true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return s._beTaskNumLimit(task, cpnLimit, dayLimit, weekLimit)
|
|
|
}
|
|
|
|
|
|
// 任务可完成次数限制
|
|
|
func (s *event) _beTaskNumLimit(task *model.FissionCampaignTask, cpnLimit, dayLimit, weekLimit int64) bool {
|
|
|
// 活动限制
|
|
|
if task.TaskLimit > 0 && task.TaskLimit <= int32(cpnLimit) {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
// 每日限制
|
|
|
if task.DayLimit > 0 && task.DayLimit <= int32(dayLimit) {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
// 周限制
|
|
|
if task.WeekLimit > 0 && task.WeekLimit <= int32(weekLimit) {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
// 事件已经被限制
|
|
|
func (s *event) condLimit(user *model.FissionUser, conds []*model.FissionCampaignCond, task *model.FissionCampaignTask) (canDo []*model.FissionCampaignCond, err error) {
|
|
|
|
|
|
cm := cmm.NewCMM(s.Ctx, s.GetDao())
|
|
|
for _, cond := range conds {
|
|
|
if !cm.EventCanTotal(cond, user.SubUserID, s.Req.AdsCondId, user.JoinAt, s.Req.BehaviorTime) {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
if cond.IfCond == mtype.FissionCampaignCondIfCondTotal {
|
|
|
canDo = append(canDo, cond)
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
if task.TaskLimit > 0 {
|
|
|
var num int64
|
|
|
num, err = s._cpnCondDoneNum(user.ID, cond.ID)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
if num >= int64(task.TaskLimit) {
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if task.DayLimit > 0 {
|
|
|
var num int64
|
|
|
num, err = s._dayCondDoneNum(user.ID, cond.ID)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
if num >= int64(task.DayLimit) {
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if task.WeekLimit > 0 {
|
|
|
var num int64
|
|
|
num, err = s._weekCondDoneNum(user.ID, cond.ID, int32(task.WeekNum))
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
if num >= int64(task.WeekLimit) {
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
|
|
|
canDo = append(canDo, cond)
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 活动内限制
|
|
|
func (s *event) _cpnCondDoneNum(userId, condId int64) (num int64, err error) {
|
|
|
key := ckey.FissionUserCondCpnLimit(userId, condId)
|
|
|
num, err = lockdo.Int64(s.Ctx, key, func() (num int64, err error) {
|
|
|
m := s.GetDao().FissionUserCondRecord
|
|
|
return m.WithContext(s.Ctx).Where(m.UserID.Eq(userId), m.CondID.Eq(condId)).Count()
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if s.condDoneMap == nil {
|
|
|
s.condDoneMap = make(map[int64]int64)
|
|
|
}
|
|
|
|
|
|
s.condDoneMap[condId] = num
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 当天任务完成数
|
|
|
func (s *event) _dayCondDoneNum(userId, condId int64) (num int64, err error) {
|
|
|
day, start, end := timez.GMTStartAndEndTs(s.tOffset, s.Req.BehaviorTime)
|
|
|
|
|
|
key := ckey.FissionUserCondDayLimit(day, userId, condId)
|
|
|
num, err = lockdo.Int64(s.Ctx, key, func() (num int64, err error) {
|
|
|
m := s.GetDao().FissionUserCondRecord
|
|
|
return m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(userId),
|
|
|
m.CondID.Eq(condId),
|
|
|
m.BehaviorTime.Gte(start),
|
|
|
m.BehaviorTime.Lte(end),
|
|
|
).Count()
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if s.condDayDoneMap == nil {
|
|
|
s.condDayDoneMap = make(map[int64]int64)
|
|
|
}
|
|
|
|
|
|
s.condDayDoneMap[condId] = num
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 周任务完成数
|
|
|
func (s *event) _weekCondDoneNum(userId, condId int64, weekNum int32) (num int64, err error) {
|
|
|
start, end := timez.GetWeekEnd(s.tOffset, weekNum)
|
|
|
|
|
|
key := ckey.FissionUserCondWeekLimit(start, userId, condId)
|
|
|
num, err = lockdo.Int64(s.Ctx, key, func() (num int64, err error) {
|
|
|
m := s.GetDao().FissionUserCondRecord
|
|
|
return m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(userId),
|
|
|
m.CondID.Eq(condId),
|
|
|
m.BehaviorTime.Between(start, end),
|
|
|
).Count()
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if s.condWeekDoneMap == nil {
|
|
|
s.condWeekDoneMap = make(map[int64]int64)
|
|
|
}
|
|
|
|
|
|
s.condWeekDoneMap[condId] = num
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 同步限制数到缓存
|
|
|
func (s *event) _addCondLimit(user *model.FissionUser, task *model.FissionCampaignTask, cond *model.FissionCampaignCond, chance int64) (err error) {
|
|
|
if task.TaskLimit > 0 {
|
|
|
key := ckey.FissionUserCondCpnLimit(user.ID, cond.ID)
|
|
|
err = lockdo.ExistDo(s.Ctx, key, func(exist bool) (err error) {
|
|
|
if !exist {
|
|
|
var num int64
|
|
|
m := s.GetDao().FissionUserCondRecord
|
|
|
num, err = m.WithContext(s.Ctx).Where(m.UserID.Eq(user.ID), m.CondID.Eq(cond.ID)).Count()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
app.Redis.Cache.IncrBy(s.Ctx, key, num)
|
|
|
}
|
|
|
app.Redis.Cache.IncrBy(s.Ctx, key, chance)
|
|
|
app.Redis.Cache.Expire(s.Ctx, key, time.Duration(rand.Intn(60)+60)*time.Minute)
|
|
|
return
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if task.DayLimit > 0 {
|
|
|
day, start, end := timez.GMTStartAndEndTs(s.tOffset)
|
|
|
key := ckey.FissionUserCondDayLimit(day, user.ID, cond.ID)
|
|
|
err = lockdo.ExistDo(s.Ctx, key, func(exist bool) (err error) {
|
|
|
if !exist {
|
|
|
var num int64
|
|
|
m := s.GetDao().FissionUserCondRecord
|
|
|
num, err = m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(user.ID),
|
|
|
m.CondID.Eq(cond.ID),
|
|
|
m.CreatedAt.Gte(start),
|
|
|
m.CreatedAt.Lte(end),
|
|
|
).Count()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
app.Redis.Cache.IncrBy(s.Ctx, key, num)
|
|
|
}
|
|
|
app.Redis.Cache.IncrBy(s.Ctx, key, chance)
|
|
|
app.Redis.Cache.Expire(s.Ctx, key, time.Duration(rand.Intn(60)+60)*time.Minute)
|
|
|
return
|
|
|
})
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if task.WeekLimit > 0 {
|
|
|
start, end := timez.GetWeekEnd(s.tOffset, int32(task.WeekNum))
|
|
|
key := ckey.FissionUserCondWeekLimit(start, user.ID, cond.ID)
|
|
|
err = lockdo.ExistDo(s.Ctx, key, func(exist bool) (err error) {
|
|
|
if !exist {
|
|
|
var num int64
|
|
|
m := s.GetDao().FissionUserCondRecord
|
|
|
num, err = m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(user.ID),
|
|
|
m.CondID.Eq(cond.ID),
|
|
|
m.CreatedAt.Between(start, end),
|
|
|
).Count()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
app.Redis.Cache.IncrBy(s.Ctx, key, num)
|
|
|
}
|
|
|
app.Redis.Cache.IncrBy(s.Ctx, key, chance)
|
|
|
app.Redis.Cache.Expire(s.Ctx, key, time.Duration(rand.Intn(60)+60)*time.Minute)
|
|
|
return
|
|
|
})
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 是不是等级限制
|
|
|
func (s *event) _beLevelLimit(taskId int64, levelMark string) bool {
|
|
|
marks, ok := s.lvLimitMap[taskId]
|
|
|
if !ok { //没有证明没开限制
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
return !verify.OneInArray(marks, strings.Split(levelMark, ","))
|
|
|
}
|
|
|
|
|
|
// 用户事件的完成记录
|
|
|
func (s *event) _addUserCondRecord(user *model.FissionUser, userCondRecord []*model.FissionUserCondRecord, conds []*model.FissionCampaignCond, task *model.FissionCampaignTask) (err error) {
|
|
|
if len(userCondRecord) == 0 {
|
|
|
return
|
|
|
}
|
|
|
err = s.GetDao().FissionUserCondRecord.WithContext(s.Ctx).Create(userCondRecord...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var condMap = make(map[int64]*model.FissionCampaignCond, len(conds))
|
|
|
var openPush = make(map[int64]struct{})
|
|
|
var ids []int64
|
|
|
for _, cond := range conds {
|
|
|
ids = append(ids, cond.ID)
|
|
|
condMap[cond.ID] = cond
|
|
|
|
|
|
if cond.TriggetType == mtype.FissionCampaignCondTriggerTypeGlobal && cond.OpenPush == mtype.Yes {
|
|
|
openPush[cond.ID] = struct{}{}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var taskLotteryMap = make(map[int64]int32, len(s.tasks))
|
|
|
var taskDayLimitMap = make(map[int64]int32, len(s.tasks))
|
|
|
for _, v := range s.tasks {
|
|
|
taskLotteryMap[utils.FissionCampaignTaskMarkCondOneCondId(v.TaskMark)] = v.Chance
|
|
|
taskDayLimitMap[utils.FissionCampaignTaskMarkCondOneCondId(v.TaskMark)] = v.DayLimit
|
|
|
}
|
|
|
|
|
|
langTitle, err := provider.NewLangTitle(s.Ctx, s.cpn, user.LangMark)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
taskTitleMap, err := langTitle.GetCondTitle(ids...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
pageTitle, err := langTitle.GetPageTitle()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
push, _ := pusher.NewPusher(s.Ctx, s.cpn)
|
|
|
fc, _ := provider.NewFissionConfig(s.Ctx, push.GetProject())
|
|
|
|
|
|
for _, v := range userCondRecord {
|
|
|
if fc.Config().PushCampaignTask == mtype.Yes {
|
|
|
cond, ok := condMap[v.CondID]
|
|
|
if !ok {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
var lotteryNum int32
|
|
|
var dayLimit int32
|
|
|
if task != nil {
|
|
|
lotteryNum = task.Chance
|
|
|
dayLimit = task.DayLimit
|
|
|
} else {
|
|
|
lotteryNum = taskLotteryMap[v.CondID]
|
|
|
dayLimit = taskDayLimitMap[v.CondID]
|
|
|
}
|
|
|
|
|
|
producer.NewOplatformOther(s.Ctx).OpoCampaignCondOk(types.OpoCampaignCondOk{
|
|
|
ProjectId: s.cpn.ProjectID,
|
|
|
CampaignHashId: s.cpn.HashID,
|
|
|
CampaignTitle: s.cpn.Title,
|
|
|
UserId: user.SubUserID,
|
|
|
DeviceId: user.DeviceID,
|
|
|
TaskTitle: taskTitleMap[v.CondID],
|
|
|
PageTitle: pageTitle,
|
|
|
FissionIcon: fmt.Sprintf("%s/%s", config.Config.Upload.Host, consts.GetPushLogo(s.cpn.FissionID, int32(s.cpn.Target))),
|
|
|
CampaignUrl: push.GetChannelUrl(user.ChannelID),
|
|
|
MarkDesc: app.TalkMap.CompeteTask(utils.NotExistGetFirst[string](user.LangMark, s.cpn.GetLangMarks())),
|
|
|
Event: cond.Event,
|
|
|
EventKey: cond.EventKey,
|
|
|
LotteryNum: lotteryNum,
|
|
|
DayLimit: dayLimit,
|
|
|
}, producer.SetHeaderLang(user.LangMark))
|
|
|
}
|
|
|
|
|
|
if _, ok := openPush[v.CondID]; ok && push != nil {
|
|
|
_ = push.CompleteTask(user)
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 自动发放奖品
|
|
|
func (s *event) _taskReward(user *model.FissionUser, rewardIds []int64) (records []*award.RewardRes, err error) {
|
|
|
records, _, err = award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, user).RewardIdsBatch(rewardIds, true)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
for _, record := range records {
|
|
|
r := record.Record
|
|
|
players.AddTaskTip(s.Ctx, user.ID, r.PropMark, 0, r.ID)
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 触发前置任务
|
|
|
func (s *event) _invokePreCond(user *model.FissionUser, preCond int32) (err error) {
|
|
|
taskM := s.GetDao().FissionCampaignTask
|
|
|
task, err := taskM.WithContext(s.Ctx).Where(
|
|
|
taskM.CampaignID.Eq(user.CampaignID),
|
|
|
taskM.PreCond.Eq(preCond),
|
|
|
taskM.IsDel.Eq(mtype.No),
|
|
|
).Take()
|
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if task == nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionUserPreCond
|
|
|
err = m.WithContext(s.Ctx).Create(withdefault.FissionUserPreCond(&model.FissionUserPreCond{
|
|
|
CampaignID: user.CampaignID,
|
|
|
UserID: user.ID,
|
|
|
PreCond: task.PreCond,
|
|
|
ExpiredAt: time.Now().Add(time.Duration(task.ExpiredMin) * time.Minute).Unix(),
|
|
|
}))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
provider.NewFissionClue(s.Ctx, user.ID).SetPreCond(preCond, task.ExpiredMin)
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *event) unlockReward(user *model.FissionUser, callbacks ...taskDoneCallback) (err error) {
|
|
|
unlockConds, userCondMap, err := s.getUserCondMap(user, true)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
if len(unlockConds) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var unlockCond = make(map[int64]*model.FissionCampaignCond, len(unlockConds))
|
|
|
var rewardIds []int64
|
|
|
for _, cond := range unlockConds {
|
|
|
rewardIds = append(rewardIds, cond.RewardID)
|
|
|
unlockCond[cond.RewardID] = cond
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionUnlockReward
|
|
|
list, err := m.WithContext(s.Ctx).Where(
|
|
|
m.CampaignID.Eq(user.CampaignID),
|
|
|
m.UserID.Eq(user.ID),
|
|
|
m.RewardID.In(rewardIds...),
|
|
|
).Find()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
for _, v := range list {
|
|
|
_, ok := unlockCond[v.RewardID]
|
|
|
if ok {
|
|
|
delete(unlockCond, v.RewardID)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if len(unlockCond) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var conds []*model.FissionCampaignCond
|
|
|
for _, cond := range unlockConds {
|
|
|
conds = append(conds, cond)
|
|
|
}
|
|
|
|
|
|
err = s.acceptCheckOne(user, conds)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 如果接收事件验证校验过后没有任务了,那么就不用去计算了
|
|
|
if len(s.tasks) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
_, err = s.one(user, conds, userCondMap, callbacks...)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
s.tasks = nil
|
|
|
|
|
|
return
|
|
|
}
|