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 }