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" "gits.branchcn.com/backend/joybuywork/proto/go_proto/workerr" ) // Ballot 幸运上上签交互逻辑 type Ballot struct { Player player *model.FissionBallot conf *model.FissionCampaignBallot fissionPlayerSetInitOnceKey string } func NewBallot(ctx context.Context, user *model.FissionUser, opts ...Option) (player *Ballot, err error) { player = &Ballot{} err = player.Init(ctx, user, consts.IdBallot, opts...) if err != nil { return } err = player.initPlayer() if err != nil { return } return } // Lottery 抽奖 func (s *Ballot) Lottery() (reward *model.FissionCampaignReward, info provider.RewardAutoLang, record *model.FissionRewardRecord, err error) { player := s.GetPlayer() if player.Chance <= 0 { err = workerr.CChanceNoneError return } rewards, err := cmm.NewCMM(s.Ctx, s.GetDao()).UserAppReward(s.user) if err != nil { return } var rewardMap = make(map[int64]*model.FissionCampaignReward) for _, v := range rewards { rewardMap[v.ID] = v } for _, v := range rewardMap { reward = v break } record, info, _, err = award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, s.user).One(reward, true) if err != nil { return } // 抽奖数减1 playerM := s.GetDao().FissionBallot _, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple(playerM.Chance.Sub(1)) if err != nil { err = s.BE().MysqlError(err) return } val, _ := jsonm.MarshalToString(mtype.LotteryLogVal{ Chance: 1, RewardId: record.RewardID, RecordId: record.ID, }) log := withdefault.FissionBallotLog(&model.FissionBallotLog{ UserID: player.UserID, CampaignID: player.CampaignID, BallotID: player.ID, Type: mtype.LotteryFissionTypeDecr, Source: mtype.FissionLogSourceLottery, Val: val, }) err = s._addLog(log) if err != nil { return } return } // Sign 签到 func (s *Ballot) Sign() (err error) { player, conf := s.GetPlayer(), s.GetConf() if conf.DayChance == 0 { return } signOk, lastSign := s._lastSign(player.LastSign) if !signOk { return } playerM := s.GetDao().FissionBallot _, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple( playerM.Chance.Add(conf.DayChance), playerM.DayChance.Add(conf.DayChance), playerM.LastSign.Value(lastSign), ) if err != nil { return s.BE().MysqlError(err) } val, _ := jsonm.MarshalToString(mtype.LotteryLogVal{ Chance: conf.DayChance, }) log := withdefault.FissionBallotLog(&model.FissionBallotLog{ UserID: player.UserID, CampaignID: player.CampaignID, BallotID: player.ID, Type: mtype.LotteryFissionTypeAdd, Source: mtype.FissionLogSourceSign, Val: val, }) err = s._addLog(log) if err != nil { return } s.player.Chance = player.Chance + conf.DayChance return } // SetInit 获得初始次数 func (s *Ballot) SetInit() (err error) { player, conf := s.GetPlayer(), s.GetConf() if player.SetInit == mtype.Yes || conf.InitChance == 0 { return } key := s.fissionPlayerSetInitOnceKey if !app.NewRedisLock(s.Ctx, key).SoftLock() { return } m := s.GetDao().FissionBallot _, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.SetInit.Value(mtype.Yes), m.Chance.Add(conf.InitChance)) if err != nil { err = s.BE().MysqlError(err) return } val, _ := jsonm.MarshalToString(mtype.LotteryLogVal{ Chance: conf.InitChance, }) log := withdefault.FissionBallotLog(&model.FissionBallotLog{ UserID: player.UserID, CampaignID: player.CampaignID, BallotID: player.ID, Type: mtype.LotteryFissionTypeAdd, Source: mtype.FissionLogSourceInit, Val: val, }) err = s._addLog(log) if err != nil { return } s.player.Chance += conf.InitChance return } // GetConf 获取玩法配置 func (s *Ballot) GetConf() *model.FissionCampaignBallot { if s.conf == nil { s.conf, _ = cache.NewCampaignBallot(s.Ctx).FindByCampaignId(s.user.CampaignID) } return s.conf } // GetPlayer 获取玩家基础数据 func (s *Ballot) GetPlayer() *model.FissionBallot { return s.player } // 玩家 func (s *Ballot) initPlayer() (err error) { player, err := s._dbFirst() if err != nil { return } defer func() { if err != nil { return } s.player = player s.fissionPlayerSetInitOnceKey = ckey.FissionPlayerSetInitOnce(player.UserID) }() if player != nil { return } player, err = s.firstOrCreate() if err != nil { return } return } // 创建玩家基础数据 func (s *Ballot) firstOrCreate() (player *model.FissionBallot, 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 *Ballot) _dbFirst() (*model.FissionBallot, error) { playerM := dao.FissionBallot 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 *Ballot) createPlayer() (player *model.FissionBallot, err error) { playerM := dao.FissionBallot player = withdefault.FissionBallot(&model.FissionBallot{ 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 *Ballot) _addLog(logs ...*model.FissionBallotLog) (err error) { err = s.GetDao().FissionBallotLog.WithContext(s.Ctx).Create(logs...) if err != nil { err = s.BE().MysqlError(err) return } return }