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.
969 lines
22 KiB
Go
969 lines
22 KiB
Go
package players
|
|
|
|
import (
|
|
"context"
|
|
"joybuywork/internal/app"
|
|
"joybuywork/internal/consts"
|
|
"joybuywork/internal/consts/ckey"
|
|
"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/fissionaction"
|
|
"joybuywork/internal/service/queue/producer"
|
|
"joybuywork/internal/service/queue/types"
|
|
"joybuywork/internal/utils"
|
|
"joybuywork/internal/utils/lockdo"
|
|
"joybuywork/proto/go_proto/workerr"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"gits.branchcn.com/backend/microcode/plugins/derivative/lock"
|
|
"gorm.io/gen"
|
|
)
|
|
|
|
const (
|
|
chopHelpOk = iota
|
|
chopHelpLimit
|
|
chopHelpDone
|
|
)
|
|
|
|
type helperInfo struct {
|
|
ipAddress string // ip
|
|
os string // 系统
|
|
osVersion string // 系统版本
|
|
deviceModel string // 设备类型
|
|
webId string // 浏览器id
|
|
deviceID string // 设备号
|
|
actionTime int64 // 助力时间
|
|
helper *model.FissionUser // 用户数据
|
|
}
|
|
|
|
// Chop 现金转盘交互逻辑
|
|
type Chop struct {
|
|
Player
|
|
player *model.FissionChop
|
|
conf *model.FissionCampaignChop
|
|
|
|
chopHelpUserKey string
|
|
chopHelpUserRewardKey string
|
|
|
|
canSelectReward int32
|
|
oldPercent float64
|
|
}
|
|
|
|
func NewChop(ctx context.Context, user *model.FissionUser, opts ...Option) (player *Chop, err error) {
|
|
player = &Chop{}
|
|
|
|
err = player.Init(ctx, user, consts.IdChop, opts...)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = player.initPlayer()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// HelpClue 助力提醒
|
|
func (s *Chop) HelpClue() (isFix bool, old, add float64) {
|
|
player := s.GetPlayer()
|
|
help := provider.NewFissionClue(s.Ctx, player.UserID).GetChopHelp()
|
|
|
|
if help.ChopRewardId != player.ChopRewardID {
|
|
return
|
|
}
|
|
|
|
isFix = help.IsFix
|
|
old = help.OldPercent
|
|
add = help.AddPercent
|
|
|
|
return
|
|
}
|
|
|
|
// RegisterHelp 注册助力
|
|
func (s *Chop) RegisterHelp(actionTime int64, helper *model.FissionUser) (helpOk bool, err error) {
|
|
player := s.GetPlayer()
|
|
if player.ChopRewardID == 0 {
|
|
return
|
|
}
|
|
|
|
conf, userMark, helpMark := s.GetConf(), fmt.Sprint(helper.ID), mtype.FissionCampaignTicketHelpEventRegister
|
|
|
|
var canHelp bool
|
|
switch conf.HelpRule {
|
|
case mtype.FissionCampaignChopHelpRuleUniqReward:
|
|
canHelp, err = s.rewardCanHelp(helpMark, userMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
case mtype.FissionCampaignChopHelpRuleUniqUser:
|
|
canHelp, err = s.userCanHelp(helpMark, userMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
// 无需助力
|
|
if !canHelp {
|
|
return
|
|
}
|
|
|
|
// 任务数据
|
|
chopReward, task, err := s.getTask(mtype.FissionCampaignTaskTypeRegister)
|
|
if err != nil || task == nil {
|
|
return
|
|
}
|
|
|
|
// 助力处理
|
|
status, err := s._doHelp(chopReward, task, helpMark, userMark)
|
|
if err != nil || status != chopHelpOk {
|
|
return
|
|
}
|
|
|
|
info := &helperInfo{
|
|
actionTime: actionTime,
|
|
helper: helper,
|
|
}
|
|
|
|
err = s.helpOkNotify(info, chopReward, helpMark, task.Percent, types.HelpSourceRegister)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// InstallHelp 安装助力
|
|
func (s *Chop) InstallHelp(actionTime int64, helper *model.FissionUser) (helpOk bool, err error) {
|
|
player := s.GetPlayer()
|
|
if player.ChopRewardID == 0 {
|
|
return
|
|
}
|
|
|
|
conf, userMark, helpMark := s.GetConf(), fmt.Sprint(helper.ID), mtype.FissionCampaignTicketHelpEventInstall
|
|
|
|
var canHelp bool
|
|
switch conf.HelpRule {
|
|
case mtype.FissionCampaignChopHelpRuleUniqReward:
|
|
canHelp, err = s.rewardCanHelp(helpMark, userMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
case mtype.FissionCampaignChopHelpRuleUniqUser:
|
|
canHelp, err = s.userCanHelp(helpMark, userMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
// 无需助力
|
|
if !canHelp {
|
|
return
|
|
}
|
|
|
|
// 任务数据
|
|
chopReward, task, err := s.getTask(mtype.FissionCampaignTaskTypeInstall)
|
|
if err != nil || task == nil {
|
|
return
|
|
}
|
|
|
|
// 助力处理
|
|
status, err := s._doHelp(chopReward, task, helpMark, userMark)
|
|
if err != nil || status != chopHelpOk {
|
|
return
|
|
}
|
|
|
|
info := &helperInfo{
|
|
actionTime: actionTime,
|
|
helper: helper,
|
|
}
|
|
err = s.helpOkNotify(info, chopReward, helpMark, task.Percent, types.HelpSourceInstall)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// OpenHelp 打开助力
|
|
func (s *Chop) OpenHelp(actionTime int64, helper *model.FissionUser) (helpOk bool, err error) {
|
|
player := s.GetPlayer()
|
|
if player.ChopRewardID == 0 {
|
|
return
|
|
}
|
|
|
|
conf, userMark, helpMark := s.GetConf(), fmt.Sprint(helper.ID), mtype.FissionCampaignTicketHelpEventOpen
|
|
|
|
var canHelp bool
|
|
switch conf.HelpRule {
|
|
case mtype.FissionCampaignChopHelpRuleUniqReward:
|
|
canHelp, err = s.rewardCanHelp(helpMark, userMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
case mtype.FissionCampaignChopHelpRuleUniqUser:
|
|
canHelp, err = s.userCanHelp(helpMark, userMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
// 无需助力
|
|
if !canHelp {
|
|
return
|
|
}
|
|
|
|
// 任务数据
|
|
chopReward, task, err := s.getTask(mtype.FissionCampaignTaskTypeOpen)
|
|
if err != nil || task == nil {
|
|
return
|
|
}
|
|
|
|
// 助力处理
|
|
status, err := s._doHelp(chopReward, task, helpMark, userMark)
|
|
if err != nil || status != chopHelpOk {
|
|
return
|
|
}
|
|
|
|
info := &helperInfo{
|
|
actionTime: actionTime,
|
|
helper: helper,
|
|
}
|
|
|
|
err = s.helpOkNotify(info, chopReward, helpMark, task.Percent, types.HelpSourceOpen)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// ClickHelp 点击助力
|
|
func (s *Chop) ClickHelp(actionTime int64, userMark, IpAddress, os, osVersion, deviceModel, deviceId, webId string) (helpOk bool, err error) {
|
|
player := s.GetPlayer()
|
|
if player.ChopRewardID == 0 {
|
|
return
|
|
}
|
|
|
|
conf, helpMark := s.GetConf(), mtype.FissionCampaignTicketHelpEventClick
|
|
|
|
var canHelp bool
|
|
|
|
switch conf.HelpRule {
|
|
case mtype.FissionCampaignChopHelpRuleUniqReward:
|
|
canHelp, err = s.rewardCanHelp(helpMark, userMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
case mtype.FissionCampaignChopHelpRuleUniqUser:
|
|
canHelp, err = s.userCanHelp(helpMark, userMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
// 无需助力
|
|
if !canHelp {
|
|
return
|
|
}
|
|
|
|
// 任务数据
|
|
chopReward, task, err := s.getTask(mtype.FissionCampaignTaskTypeClick)
|
|
if err != nil || task == nil {
|
|
return
|
|
}
|
|
|
|
// 助力处理
|
|
status, err := s._doHelp(chopReward, task, helpMark, userMark)
|
|
if err != nil || status != chopHelpOk {
|
|
return
|
|
}
|
|
|
|
helper := &helperInfo{
|
|
ipAddress: IpAddress,
|
|
os: os,
|
|
osVersion: osVersion,
|
|
deviceModel: deviceModel,
|
|
deviceID: deviceId,
|
|
webId: webId,
|
|
actionTime: actionTime,
|
|
}
|
|
|
|
err = s.helpOkNotify(helper, chopReward, helpMark, task.Percent, types.HelpSourceClick)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// Reselect 重选奖品
|
|
func (s *Chop) Reselect() (err error) {
|
|
player := s.GetPlayer()
|
|
if player.ChopRewardID == 0 {
|
|
return
|
|
}
|
|
|
|
canSelect, err := s.ExistSelectReward()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if !canSelect {
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionChop
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.ChopRewardID.Value(0))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// SelectReward 选择奖品
|
|
func (s *Chop) SelectReward(rewardId int64) (err error) {
|
|
player := s.GetPlayer()
|
|
|
|
if player.ChopRewardID > 0 {
|
|
err = s.BE().VerifyError("reward selected")
|
|
return
|
|
}
|
|
|
|
rewardM := s.GetDao().FissionCampaignReward
|
|
reward, err := rewardM.WithContext(s.Ctx).Where(rewardM.ID.Eq(rewardId)).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
if reward == nil {
|
|
err = workerr.NotFound("not found reward")
|
|
return
|
|
}
|
|
|
|
chopRewardM := s.GetDao().FissionChopReward
|
|
|
|
if reward.HasRule == mtype.Yes {
|
|
ruleM := s.GetDao().FissionCampaignRewardRule
|
|
var rule *model.FissionCampaignRewardRule
|
|
rule, err = ruleM.WithContext(s.Ctx).Where(ruleM.RewardID.Eq(reward.ID)).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
var count int64
|
|
count, err = chopRewardM.WithContext(s.Ctx).Where(
|
|
chopRewardM.UserID.Eq(player.UserID),
|
|
chopRewardM.RewardID.Eq(reward.ID),
|
|
).Count()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
if count >= int64(rule.CampaignLimit) {
|
|
err = s.BE().VerifyError("reward limit")
|
|
return
|
|
}
|
|
}
|
|
|
|
chopReward := withdefault.FissionChopReward(&model.FissionChopReward{
|
|
UserID: player.UserID,
|
|
CampaignID: player.CampaignID,
|
|
RewardID: reward.ID,
|
|
InitPercent: reward.InitPercent,
|
|
Percent: reward.InitPercent,
|
|
RecordID: 0,
|
|
})
|
|
|
|
if err = chopRewardM.WithContext(s.Ctx).Create(chopReward); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionChop
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.ChopRewardID.Value(chopReward.ID))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
// 选择奖品埋点
|
|
fissionaction.NewMarkPoint(s.Ctx).InApp(s.user).SelectReward(time.Now().Unix(), reward.ID)
|
|
|
|
// 有初始助力,要推送一下消息
|
|
if reward.InitPercent > 0 {
|
|
provider.NewFissionClue(s.Ctx, s.user.ID).ChopHelp(chopReward.ID, 0, reward.InitPercent, true)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// ExistSelectReward 是否存在可选择的奖品
|
|
func (s *Chop) ExistSelectReward() (exist bool, err error) {
|
|
if s.canSelectReward != 0 {
|
|
return s.canSelectReward == 1, nil
|
|
}
|
|
|
|
exist, err = s._existSelectReward()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if exist {
|
|
s.canSelectReward = 1
|
|
} else {
|
|
s.canSelectReward = -1
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 是否选择奖品
|
|
func (s *Chop) _existSelectReward() (exist bool, err error) {
|
|
rewards, err := cmm.NewCMM(s.Ctx, s.GetDao()).UserAppReward(s.user)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var limitIds []int64
|
|
for _, reward := range rewards {
|
|
if reward.HasRule == mtype.Yes {
|
|
limitIds = append(limitIds, reward.ID)
|
|
}
|
|
}
|
|
|
|
if len(limitIds) == 0 {
|
|
return true, nil
|
|
}
|
|
|
|
ruleM := s.GetDao().FissionCampaignRewardRule
|
|
rules, err := ruleM.WithContext(s.Ctx).Where(ruleM.CampaignID.Eq(s.user.CampaignID), ruleM.RewardID.In(limitIds...)).Find()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
var ruleMap = make(map[int64]*model.FissionCampaignRewardRule, len(rules))
|
|
for _, rule := range rules {
|
|
ruleMap[rule.RewardID] = rule
|
|
}
|
|
|
|
type rewardGet struct {
|
|
RewardId int64 `json:"reward_id"`
|
|
Num int32 `json:"num"`
|
|
}
|
|
|
|
var gets []*rewardGet
|
|
chopRewardM := s.GetDao().FissionChopReward
|
|
err = chopRewardM.WithContext(s.Ctx).
|
|
Select(chopRewardM.ID.Count().As("num"), chopRewardM.RewardID).
|
|
Where(chopRewardM.UserID.Eq(s.user.ID), chopRewardM.RecordID.Gt(0)).
|
|
Group(chopRewardM.RewardID).
|
|
Scan(&gets)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
var filterMap = make(map[int64]struct{})
|
|
for _, v := range gets {
|
|
if rule, ok := ruleMap[v.RewardId]; ok && rule.CampaignLimit <= v.Num {
|
|
filterMap[v.RewardId] = struct{}{}
|
|
}
|
|
}
|
|
|
|
return len(rewards) > len(filterMap), nil
|
|
}
|
|
|
|
// GetConf 获取玩法配置
|
|
func (s *Chop) GetConf() *model.FissionCampaignChop {
|
|
if s.conf == nil {
|
|
s.conf, _ = cache.NewCampaignChop(s.Ctx).FindByCampaignId(s.user.CampaignID)
|
|
}
|
|
|
|
return s.conf
|
|
}
|
|
|
|
// RefreshView 刷新预览用户
|
|
func (s *Chop) RefreshView() (err error) {
|
|
if !s.IsView() {
|
|
err = s.BE().VerifyError("非预览用户无法重新体验")
|
|
return
|
|
}
|
|
|
|
player := s.GetPlayer()
|
|
|
|
m := s.GetDao().FissionChop
|
|
_, err = m.WithContext(s.Ctx).Where(m.UserID.Eq(player.UserID)).Delete()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
app.Redis.Cache.Del(s.Ctx, s.chopHelpUserRewardKey, s.chopHelpUserKey)
|
|
|
|
helpM := s.GetDao().FissionChopHelp
|
|
_, err = helpM.WithContext(s.Ctx).Where(helpM.UserID.Eq(player.UserID)).Delete()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
chopRewardM := s.GetDao().FissionChopReward
|
|
_, err = chopRewardM.WithContext(s.Ctx).Where(chopRewardM.UserID.Eq(player.UserID)).Delete()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// GetPlayer 获取玩家基础数据
|
|
func (s *Chop) GetPlayer() *model.FissionChop {
|
|
return s.player
|
|
}
|
|
|
|
// 玩家
|
|
func (s *Chop) initPlayer() (err error) {
|
|
player, err := s._dbFirst()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
s.player = player
|
|
s.chopHelpUserKey = ckey.FissionChopHelpUser(player.UserID)
|
|
s.chopHelpUserRewardKey = ckey.FissionChopHelpUserReward(player.ChopRewardID)
|
|
}()
|
|
|
|
if player != nil {
|
|
return
|
|
}
|
|
|
|
player, err = s.firstOrCreate()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 创建玩家基础数据
|
|
func (s *Chop) firstOrCreate() (player *model.FissionChop, 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 *Chop) createPlayer() (player *model.FissionChop, err error) {
|
|
playerM := dao.FissionChop
|
|
player = withdefault.FissionChop(&model.FissionChop{
|
|
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 *Chop) _dbFirst() (*model.FissionChop, error) {
|
|
playerM := dao.FissionChop
|
|
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 *Chop) userCanHelp(mark string, uniqMark string) (canHelp bool, err error) {
|
|
player, key := s.GetPlayer(), s.chopHelpUserKey
|
|
|
|
// 这个人给它上级助力过事件了,就不能再助力了
|
|
yes, err := app.Redis.Cache.HSetNX(s.Ctx,
|
|
key,
|
|
fmt.Sprintf("%s_%s", mark, uniqMark),
|
|
1,
|
|
).Result()
|
|
if err != nil {
|
|
err = s.BE().RedisError(err)
|
|
return
|
|
}
|
|
|
|
if !yes {
|
|
return
|
|
}
|
|
|
|
// 设置成功就给一个过期时间
|
|
app.Redis.Cache.Expire(s.Ctx, key, consts.TimeDay)
|
|
|
|
// 再查数据库看看是不是真的,怕只是缓存过期
|
|
helpM := s.GetDao().FissionChopHelp
|
|
help, err := helpM.WithContext(s.Ctx).
|
|
Where(
|
|
helpM.CampaignID.Eq(player.CampaignID),
|
|
helpM.Mark.Eq(mark),
|
|
helpM.UserMark.Eq(uniqMark),
|
|
).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
if help != nil {
|
|
return
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// 奖品唯一助力
|
|
func (s *Chop) rewardCanHelp(mark string, uniqMark string) (canHelp bool, err error) {
|
|
player, key := s.GetPlayer(), s.chopHelpUserRewardKey
|
|
|
|
// 这个人给它上级助力过事件了,就不能再助力了
|
|
yes, err := app.Redis.Cache.HSetNX(s.Ctx,
|
|
key,
|
|
fmt.Sprintf("%s_%s", mark, uniqMark),
|
|
1,
|
|
).Result()
|
|
if err != nil {
|
|
err = s.BE().RedisError(err)
|
|
return
|
|
}
|
|
|
|
if !yes {
|
|
return
|
|
}
|
|
app.Redis.Cache.Expire(s.Ctx, key, consts.TimeDay)
|
|
|
|
// 再查数据库看看助力过没有
|
|
helpM := s.GetDao().FissionChopHelp
|
|
help, err := helpM.WithContext(s.Ctx).
|
|
Where(
|
|
helpM.ChopRewardID.Eq(player.ChopRewardID),
|
|
helpM.Mark.Eq(mark),
|
|
helpM.UserMark.Eq(uniqMark),
|
|
).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
if help != nil {
|
|
return
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (s *Chop) getTask(taskType int8) (chopReward *model.FissionChopReward, task *model.FissionCampaignTask, err error) {
|
|
player := s.GetPlayer()
|
|
|
|
chopRewardM := s.GetDao().FissionChopReward
|
|
chopReward, err = chopRewardM.WithContext(s.Ctx).Where(chopRewardM.ID.Eq(player.ChopRewardID)).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
// 没找到,或者助力完成
|
|
if chopReward == nil || chopReward.RecordID > 0 {
|
|
return
|
|
}
|
|
|
|
taskM := s.GetDao().FissionCampaignTask
|
|
task, err = taskM.WithContext(s.Ctx).Where(
|
|
taskM.CampaignID.Eq(player.CampaignID),
|
|
taskM.TaskType.Eq(taskType),
|
|
taskM.TaskMark.Eq(utils.FissionCampaignTaskMarkRewardOneVal(chopReward.RewardID)),
|
|
).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
s.oldPercent = chopReward.Percent
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Chop) _doHelp(chopReward *model.FissionChopReward, task *model.FissionCampaignTask, helpMark, userMark string) (status int8, err error) {
|
|
// 计算助力进度
|
|
percent, err := s._helpPercent(chopReward, task, helpMark)
|
|
if err != nil { // 有错误,或者被限制了
|
|
return
|
|
}
|
|
|
|
if percent == 0 {
|
|
status = chopHelpLimit
|
|
return
|
|
}
|
|
|
|
if percent < 100 {
|
|
err = s._chopHelpOk(chopReward, task, helpMark, userMark, percent)
|
|
return
|
|
}
|
|
|
|
// 发奖要锁住,防止并发发奖
|
|
lc := app.NewRedisLock(s.Ctx, ckey.FissionChopHelpOnce(chopReward.ID), lock.SetExpire(10*time.Second))
|
|
if !lc.SoftLock() {
|
|
return
|
|
}
|
|
defer lc.Release()
|
|
|
|
// 重新找一遍,看看是不是没绑定奖励
|
|
chopRewardM := s.GetDao().FissionChopReward
|
|
chopReward, err = chopRewardM.WithContext(s.Ctx).Where(chopRewardM.ID.Eq(chopReward.ID)).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
if chopReward.RecordID > 0 {
|
|
status = chopHelpDone
|
|
return
|
|
}
|
|
|
|
err = s._chopHelpOk(chopReward, task, helpMark, userMark, 100)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Chop) _helpPercent(chopReward *model.FissionChopReward, task *model.FissionCampaignTask, helpMark string) (percent float64, err error) {
|
|
// 有限制的助力
|
|
if task.PercentLimit != 0 {
|
|
key := ckey.FissionChopHelpMarkPercent(chopReward.ID, helpMark)
|
|
|
|
s._createPercentCache(chopReward.ID, key, helpMark, 0)
|
|
|
|
num := app.Redis.Cache.IncrByFloat(s.Ctx, key, task.Percent).Val()
|
|
// 超过限制不能助力
|
|
if num > task.PercentLimit {
|
|
return
|
|
}
|
|
}
|
|
|
|
// 提高助力进度
|
|
key := ckey.FissionChopHelpPercent(chopReward.ID)
|
|
s._createPercentCache(chopReward.ID, key, "", chopReward.InitPercent)
|
|
percent = app.Redis.Cache.IncrByFloat(s.Ctx, key, task.Percent).Val()
|
|
return
|
|
}
|
|
|
|
// 创建缓存进度
|
|
func (s *Chop) _createPercentCache(chopRewardId int64, key, mark string, initPercent float64) {
|
|
_ = lockdo.ExistDo(s.Ctx, key, func(exist bool) (err error) {
|
|
if exist {
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionChopHelp
|
|
var cond = []gen.Condition{
|
|
m.ChopRewardID.Eq(chopRewardId),
|
|
}
|
|
if mark != "" {
|
|
cond = append(cond, m.Mark.Eq(mark))
|
|
}
|
|
|
|
var num struct {
|
|
Percent float64
|
|
}
|
|
|
|
err = m.WithContext(s.Ctx).Select(m.Percent.Sum().As("percent")).Where(cond...).Scan(&num)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
app.Redis.Cache.IncrByFloat(s.Ctx, key, num.Percent+initPercent)
|
|
app.Redis.Cache.Expire(s.Ctx, key, consts.TimeDay)
|
|
return
|
|
})
|
|
}
|
|
|
|
// 助力成功
|
|
func (s *Chop) _chopHelpOk(chopReward *model.FissionChopReward, task *model.FissionCampaignTask, helpMark, userMark string, percent float64) (err error) {
|
|
user := s.user
|
|
m := s.GetDao().FissionChopHelp
|
|
err = m.WithContext(s.Ctx).Create(withdefault.FissionChopHelp(&model.FissionChopHelp{
|
|
UserID: chopReward.UserID,
|
|
CampaignID: chopReward.CampaignID,
|
|
ChopRewardID: chopReward.ID,
|
|
Mark: helpMark,
|
|
Percent: task.Percent,
|
|
UserMark: userMark,
|
|
}))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
chopRewardM := s.GetDao().FissionChopReward
|
|
if percent != 100 {
|
|
_, err = chopRewardM.WithContext(s.Ctx).Where(chopRewardM.ID.Eq(chopReward.ID)).UpdateSimple(chopRewardM.Percent.Add(task.Percent))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
rewardM := s.GetDao().FissionCampaignReward
|
|
reward, err := rewardM.WithContext(s.Ctx).Where(rewardM.ID.Eq(chopReward.RewardID)).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
ok, err := award.NewAwardIssVerify(s.Ctx, user, reward).DeductStock().IsOK()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var opts []award.RecordOption
|
|
if !ok {
|
|
opts = append(opts, award.RewardRecordStatus(
|
|
mtype.FissionRewardRecordStatusFail,
|
|
mtype.FissionRewardRecordFailTypeCli,
|
|
mtype.FissionRewardRecordFailTypeCliLackMsg,
|
|
))
|
|
}
|
|
|
|
record, _, _, err := award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, user).One(reward, true, opts...)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
_, err = chopRewardM.WithContext(s.Ctx).Where(chopRewardM.ID.Eq(chopReward.ID)).UpdateSimple(
|
|
chopRewardM.Percent.Value(100),
|
|
chopRewardM.RecordID.Value(record.ID),
|
|
)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 一些助力回调处理
|
|
func (s *Chop) helpOkNotify(info *helperInfo, chopReward *model.FissionChopReward, helpMark string, percent float64, source int32) (err error) {
|
|
beHelper, cpn := s.user, s.cpn
|
|
// 助力次数 + 1
|
|
statM := s.GetDao().FissionUserStat
|
|
_, err = statM.WithContext(s.Ctx).Where(statM.UserID.Eq(beHelper.ID)).UpdateSimple(statM.HelpNum.Add(1))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
// 如果是点击事件 info 为nil
|
|
var subUserId, subDeviceId string
|
|
if source == types.HelpSourceClick {
|
|
// 平台
|
|
platform, dm := strings.ToLower(info.os), strings.ToLower(info.deviceModel)
|
|
if platform == "macos" {
|
|
platform = consts.PlatformIOS
|
|
}
|
|
|
|
if platform == consts.PlatformIOS && dm == consts.PlatformIPad {
|
|
platform = consts.PlatformIPad
|
|
}
|
|
|
|
subDeviceId = info.deviceID
|
|
|
|
fissionaction.NewMarkPoint(s.Ctx).OutApp(
|
|
beHelper.CampaignID,
|
|
beHelper.ChannelID,
|
|
beHelper.ID,
|
|
info.webId,
|
|
platform,
|
|
beHelper.LangMark,
|
|
).Help(
|
|
info.actionTime,
|
|
helpMark,
|
|
chopReward.RewardID,
|
|
info.ipAddress,
|
|
info.os,
|
|
info.osVersion,
|
|
info.deviceModel,
|
|
)
|
|
|
|
} else {
|
|
subUserId = info.helper.SubUserID
|
|
subDeviceId = info.helper.DeviceID
|
|
fissionaction.NewMarkPoint(s.Ctx).InApp(info.helper).Help(info.actionTime, helpMark, chopReward.RewardID)
|
|
}
|
|
|
|
langTitle, err := provider.NewLangTitle(s.Ctx, s.cpn, beHelper.LangMark)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
pageTitle, err := langTitle.GetPageTitle()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 助力通知
|
|
producer.NewOplatformOther(s.Ctx).OpoCampaignHelpOk(types.OpoCampaignHelpOk{
|
|
ProjectId: cpn.ProjectID,
|
|
CampaignHashId: cpn.HashID,
|
|
CampaignTitle: cpn.Title,
|
|
PageTitle: pageTitle,
|
|
HelperUserId: subUserId,
|
|
HelperDeviceId: subDeviceId,
|
|
BeHelperUserId: beHelper.SubUserID,
|
|
BeHelperDeviceId: beHelper.DeviceID,
|
|
Source: source,
|
|
}, producer.SetHeaderLang(beHelper.LangMark))
|
|
|
|
provider.NewFissionClue(s.Ctx, beHelper.ID).ChopHelp(chopReward.ID, s.oldPercent, percent, false)
|
|
|
|
return
|
|
}
|