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.

322 lines
7.1 KiB
Go

package campaignuser
import (
"joybuywork/internal/repository/dbcheck"
"joybuywork/internal/repository/finder"
"joybuywork/internal/repository/model"
"joybuywork/internal/repository/mtype"
"joybuywork/internal/repository/withdefault"
"joybuywork/internal/service/cmm"
"joybuywork/internal/service/provider/award"
"joybuywork/internal/service/provider/fissionaction"
"joybuywork/internal/utils/logic"
pb "joybuywork/proto/go_proto/w_campaign_user"
"joybuywork/proto/go_proto/workerr"
"fmt"
"time"
"github.com/golang-module/carbon/v2"
"gorm.io/gen/field"
)
const (
feedFailTypeNone = iota //0-饲养成功
feedFailTypeLack //1-道具不足
feedFailTypeMax //2-不能继续升级
feedFailTypeDie //3-生命体死亡
)
const (
feedHasRewardNone = iota
feedHasRewardOk
feedHasRewardLack
)
type Feed struct {
logic.Logic
Req *pb.FeedReq
Res *pb.FeedRes
growRecords []*model.FissionGrowRecord
}
func (s *Feed) Run() error {
return logic.Run(s)
}
func (s *Feed) Exec() (err error) {
player, conf, err := s.player()
if err != nil || s.Res.FailType != feedFailTypeNone {
return
}
err = s.feed(player, conf)
if err != nil || s.Res.FailType != feedFailTypeNone {
return
}
return s.growRecord()
}
func (s *Feed) player() (player *model.FissionGrow, conf *model.FissionCampaignGrow, err error) {
playerM := s.GetDao().FissionGrow
player, err = playerM.WithContext(s.Ctx).Where(playerM.UserID.Eq(s.Req.GetUserId())).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if player == nil {
err = workerr.NotFound("not found player")
return
}
if player.GrowNum < s.Req.GetNum() {
s.Res.FailType = feedFailTypeLack
return
}
confM := s.GetDao().FissionCampaignGrow
conf, err = confM.WithContext(s.Ctx).Where(confM.CampaignID.Eq(player.CampaignID)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if conf == nil {
err = workerr.NotFound("not found grow conf")
return
}
return
}
func (s *Feed) feed(player *model.FissionGrow, conf *model.FissionCampaignGrow) (err error) {
lifeM := s.GetDao().FissionGrowLife
life, err := lifeM.WithContext(s.Ctx).Where(lifeM.UserID.Eq(player.UserID), lifeM.IsGrow.Eq(mtype.Yes)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if life == nil {
err = workerr.NotFound("not found life")
return
}
if life.IsDie == mtype.Yes {
s.Res.FailType = feedFailTypeDie
return
}
//查找生命体剩余阶段
stepM := s.GetDao().FissionCampaignGrowStep
steps, err := stepM.WithContext(s.Ctx).Where(stepM.CampaignID.Eq(player.CampaignID), stepM.Step.Gt(life.Step)).Order(stepM.Step).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
if len(steps) == 0 {
s.Res.FailType = feedFailTypeMax
return
}
s._setGrowRecord(player, mtype.FissionGrowRecordFeed, []*mtype.GrowVarData{{
Key: "{{num}}",
Value: fmt.Sprint(s.Req.GetNum()),
}})
//喂了养料之后当前的阶段
var num = life.Num + s.Req.GetNum()
var step *model.FissionCampaignGrowStep
for _, v := range steps {
if v.Num <= num {
step = v
break
}
}
var lifeUp = []field.AssignExpr{
lifeM.DieTime.Value(carbon.Now().AddHours(int(conf.DieHour)).Timestamp()),
}
defer func() {
if err != nil {
return
}
_, err = lifeM.WithContext(s.Ctx).Where(lifeM.ID.Eq(life.ID)).UpdateSimple(lifeUp...)
if err != nil {
err = s.BE().MysqlError(err)
return
}
}()
//养料具体使用
var useNum = s.Req.GetNum()
if step != nil {
//升级只消耗到达下一级别的养料
lifeUp = append(lifeUp, lifeM.Step.Value(step.Step), lifeM.Num.Value(0))
useNum = step.Num - life.Num
} else {
//不升级
lifeUp = append(lifeUp, lifeM.Num.Add(s.Req.GetNum()))
}
playerM := s.GetDao().FissionGrow
_, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple(playerM.GrowNum.Sub(useNum))
if err != nil {
err = s.BE().MysqlError(err)
return
}
s.Res.Step = life.Step
// 没升级
if step == nil {
return
}
s.Res.UpStep = step.Step
s.Res.LvUp = true
// 升级了,但是不是最后一级
if step.Step != steps[len(steps)-1].Step {
s._setGrowRecord(player, mtype.FissionGrowRecordLvUp, nil)
return
}
// 最后一级直接领奖
record, err := s._reward(player)
if err != nil {
return
}
lifeUp = append(lifeUp, lifeM.RecordID.Value(record.ID))
return
}
func (s *Feed) _reward(player *model.FissionGrow) (record *model.FissionRewardRecord, err error) {
cpn, err := finder.Campaign(s.Ctx, player.CampaignID)
if err != nil {
err = s.BE().CacheError(err)
return
}
user, err := finder.FissionUser(s.Ctx, cpn.ID, player.UserID)
if err != nil {
err = s.BE().CacheError(err)
return
}
cm := cmm.NewCMM(s.Ctx, s.GetDao())
rewards, err := cm.UserAppReward(user)
if err != nil {
return
}
if len(rewards) == 0 {
return
}
reward := rewards[0]
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, info, async, err := award.NewAwardReward(s.Ctx, s.GetDao(), cpn.ProjectID, user).One(reward, false, opts...)
if err != nil {
return
}
s.AddAfterRun(func() (err error) {
s.Res.RewardTitle = record.Title
s.Res.RewardUrl = record.ImgURL
s.Res.RewardId = reward.ID
s.Res.Contact = info.Contact
s.Res.ReceiveType = info.ReceiveType
if info.ReceiveType == mtype.RewardReceiveTypeClient {
s.Res.KvData = make([]*pb.FeedRes_KV, 0, len(info.KvData))
for _, v := range info.KvData {
s.Res.KvData = append(s.Res.KvData, &pb.FeedRes_KV{
Key: v.Key,
Value: v.Value,
})
}
}
if !ok {
s.Res.HasReward = feedHasRewardLack
return
}
s.Res.HasReward = feedHasRewardOk
for _, do := range async {
do()
}
return
})
statM := s.GetDao().FissionUserStat
_, err = statM.WithContext(s.Ctx).Where(statM.UserID.Eq(player.UserID)).UpdateSimple(statM.GrowRewardNum.Add(1))
if err != nil {
err = s.BE().MysqlError(err)
return
}
s._setGrowRecord(player, mtype.FissionGrowRecordGetReward, []*mtype.GrowVarData{{
Key: "{{reward_title}}",
Value: record.Title,
IdMark: reward.ID,
}})
s.AddAfterRun(func() (err error) {
fissionaction.NewMarkPoint(s.Ctx).InApp(user).GrowOk(time.Now().Unix(), reward.ID, record.ID)
return
})
return
}
func (s *Feed) _setGrowRecord(player *model.FissionGrow, mark string, varData []*mtype.GrowVarData) {
feedRecord := withdefault.FissionGrowRecord(&model.FissionGrowRecord{
UserID: player.UserID,
CampaignID: player.CampaignID,
Mark: mark,
VarData: "",
})
feedRecord.SetVarData(varData)
s.growRecords = append(s.growRecords, feedRecord)
}
func (s *Feed) growRecord() (err error) {
if len(s.growRecords) == 0 {
return
}
recordM := s.GetDao().FissionGrowRecord
err = recordM.WithContext(s.Ctx).Create(s.growRecords...)
if err != nil {
err = s.BE().MysqlError(err)
return
}
return
}