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" "joybuywork/internal/service/provider/projectuser" "joybuywork/internal/utils" "joybuywork/internal/utils/timez" "joybuywork/internal/utils/verify" "math" "strconv" "time" "gits.branchcn.com/backend/microcode/plugins/derivative/lock" "gorm.io/gen/field" ) const ( voteOk = iota voteEnd // 非投票时间无法投票 voteLack // 投票机会不足 votePointLack // 积分不足 voteLimit // 投票已达最大次数 voteFail // 投票失败 voteNotSameTeam // 不能投同队伍 ) type Vs struct { Player player *model.FissionV conf *model.FissionCampaignV fissionPlayerSetInitOnceKey string } func NewVs(ctx context.Context, user *model.FissionUser, opts ...Option) (player *Vs, err error) { player = &Vs{} err = player.Init(ctx, user, consts.IdVs, opts...) if err != nil { return } err = player.initPlayer() if err != nil { return } return } func (s *Vs) Exchange(item *model.RedeemMallItem) (err error) { player := s.GetPlayer() val, _ := jsonm.MarshalToString(mtype.VsLogVal{ PointsNum: item.CoinNum, MallId: item.MallID, MallItemId: item.ID, }) log := withdefault.FissionVsLog(&model.FissionVsLog{ UserID: player.UserID, CampaignID: player.CampaignID, VsID: player.ID, Type: mtype.FissionVsLogTypeExchange, Source: mtype.FissionLogSourceExchange, Val: val, }) err = s._addLog(log) if err != nil { return } vsM := s.GetDao().FissionV _, err = vsM.WithContext(s.Ctx).Where(vsM.ID.Eq(player.ID)).UpdateSimple(vsM.CoinUse.Add(item.CoinNum)) if err != nil { err = s.BE().MysqlError(err) return } return } func (s *Vs) FirstVisit() (rewards []*EventReward, err error) { ok, rewards, err := s.eventOk(mtype.FissionCampaignEventMarkFirstVisit) if err != nil || !ok { return } player := s.GetPlayer() var chance int32 var point int32 var logs = make([]*model.FissionVsLog, 0, len(rewards)) for _, v := range rewards { var val string var t int8 switch v.PropMark { case mtype.FissionCampaignRewardPropMarkPoint: t = mtype.FissionVsLogTypeAddPoint val, _ = jsonm.ToObjString(mtype.VsLogVal{ PointsNum: v.Chance, }) point += v.Chance case mtype.FissionCampaignRewardPropMarkReward: t = mtype.FissionVsLogTypeReward val, _ = jsonm.ToObjString(mtype.VsLogVal{ RewardId: v.Reward.Record.RewardID, RecordId: v.Reward.Record.ID, }) case mtype.FissionCampaignRewardPropMarkChance: t = mtype.FissionVsLogTypeAddVote val, _ = jsonm.ToObjString(mtype.VsLogVal{ Chance: v.Chance, }) chance++ } logs = append(logs, withdefault.FissionVsLog(&model.FissionVsLog{ UserID: player.UserID, CampaignID: player.CampaignID, VsID: player.ID, Type: t, Source: mtype.FissionLogSourceFirstVisit, Val: val, })) } err = s._addLog(logs...) if err != nil { return } if chance > 0 || point > 0 { m := s.GetDao().FissionV _, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.Chance.Add(chance), m.CoinGet.Add(point)) if err != nil { err = s.BE().MysqlError(err) return } } return } func (s *Vs) TipReward() (err error) { player := s.GetPlayer() var ids []int64 m := s.GetDao().FissionVsVoteSettlement err = m.WithContext(s.Ctx).Select(m.ID).Where(m.VsID.Eq(player.ID), m.TipAt.Eq(0)).Pluck(m.ID, &ids) if err != nil { err = s.BE().MysqlError(err) return } if len(ids) == 0 { return } _, err = m.WithContext(s.Ctx).Where(m.ID.In(ids...)).UpdateColumnSimple(m.TipAt.Value(time.Now().Unix())) if err != nil { err = s.BE().MysqlError(err) return } return } func (s *Vs) SettlementReward(settlement *model.FissionVsVoteSettlement) (rewards []*Reward, err error) { player := s.GetPlayer() if settlement.AcceptAt > 0 { if settlement.TipAt > 0 { return } m := s.GetDao().FissionRewardRecord records, err1 := m.WithContext(s.Ctx).Where(m.ID.In(settlement.GetRecordIds()...)).Find() if err1 != nil { err1 = s.BE().MysqlError(err1) return } var brMap = make(map[int64]struct{}) var brIds []int64 for _, record := range records { if _, ok := brMap[record.BaseRewardID]; !ok && record.BaseRewardID > 0 { brIds = append(brIds, record.BaseRewardID) } } preward, err1 := provider.NewRewards(s.Ctx, s.cpn.ProjectID, brIds...) if err1 != nil { err = err1 return } rewards = make([]*Reward, 0, len(records)) for _, record := range records { switch record.PropMark { case mtype.FissionCampaignRewardPropMarkReward: info, _ := preward.InfoAutoLang(record.BaseRewardID, s.user.LangMark) rewards = append(rewards, &Reward{ Id: record.RewardID, PropMark: record.PropMark, Title: info.Title, Img: info.ImgUrl, KvData: info.KvData, ReceiveType: info.ReceiveType, Contact: info.Contact, OpenToUse: info.OpenToUse, WebUrl: info.WebUrl, AppParam: info.AppParam, PcParam: info.PcParam, PropNum: record.RewardNum, RewardHashId: record.HashID, }) case mtype.FissionCampaignRewardPropMarkPoint: rewards = append(rewards, &Reward{ Id: record.RewardID, PropMark: record.PropMark, Title: record.Title, Img: record.ImgURL, PropNum: record.RewardNum, RewardHashId: record.HashID, }) } } return } lc := app.NewRedisLock(s.Ctx, ckey.FissionVoteAcceptOnce(settlement.ID), lock.SetExpire(10*time.Second)) defer lc.Release() if !lc.SoftLock() { return } m := s.GetDao().FissionVsVote vote, err := m.WithContext(s.Ctx).Where(m.ID.Eq(settlement.VoteID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if vote == nil { return } scheduleM := s.GetDao().FissionCampaignVsSchedule schedule, err := scheduleM.WithContext(s.Ctx).Where(scheduleM.ID.Eq(vote.ScheduleID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if schedule == nil { return } rewardM := s.GetDao().FissionCampaignReward reward, err := rewardM.WithContext(s.Ctx).Where(rewardM.ID.Eq(schedule.RewardID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if reward == nil { return } odds, _ := strconv.ParseFloat(settlement.Odds, 64) if reward.PropMark == mtype.FissionCampaignTaskPropMarkPoint && odds != 1 { rewardNum := int32(math.Floor(float64(reward.RewardNum) * odds)) reward.RewardNum = rewardNum } var num = vote.FreeVote + vote.PointVote var accepts = make([]*model.FissionCampaignReward, 0) for i := 0; i < int(num); i++ { accepts = append(accepts, reward) } res, _, err := award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, s.user).DeductStockBatch(accepts, true) if err != nil { return } var coinGet int32 var recordIds []int64 rewards = make([]*Reward, 0, len(res)) for _, v := range res { record := v.Record info := v.Info rewards = append(rewards, &Reward{ Id: record.RewardID, PropMark: record.PropMark, Title: info.Title, Img: info.ImgUrl, KvData: info.KvData, ReceiveType: info.ReceiveType, Contact: info.Contact, OpenToUse: info.OpenToUse, WebUrl: info.WebUrl, AppParam: info.AppParam, PcParam: info.PcParam, PropNum: record.RewardNum, RewardHashId: record.HashID, }) recordIds = append(recordIds, record.ID) if s.GetConf().ClaimType != mtype.FissionCampaignVsClaimTypeAuto { s.appTrack().VsAcceptReward(record.CreatedAt, schedule.ID, record.RewardID, record.ID) } if record.PropMark == mtype.FissionCampaignRewardPropMarkPoint { coinGet += record.RewardNum } } idStr, _ := jsonm.ToSliceString(recordIds) sltM := s.GetDao().FissionVsVoteSettlement _, err = sltM.WithContext(s.Ctx).Where(sltM.ID.Eq(settlement.ID)).UpdateColumnSimple( sltM.AcceptAt.Value(time.Now().Unix()), sltM.RecordIds.Value(idStr), ) if err != nil { err = s.BE().MysqlError(err) return } if coinGet > 0 { playerM := s.GetDao().FissionV _, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateColumnSimple(playerM.CoinGet.Add(coinGet)) if err != nil { err = s.BE().MysqlError(err) return } } val, _ := jsonm.MarshalToString(mtype.VsLogVal{ RewardId: reward.ID, ScheduleId: settlement.ScheduleID, Odds: settlement.Odds, Num: num, }) log := withdefault.FissionVsLog(&model.FissionVsLog{ UserID: player.UserID, CampaignID: player.CampaignID, VsID: player.ID, Type: mtype.FissionVsLogTypeSettlement, Source: mtype.FissionLogSourceSettlement, Val: val, }) err = s._addLog(log) if err != nil { return } return } // ReceiveReward 手动领取奖励 func (s *Vs) ReceiveReward(taskRewards ...*model.FissionUserTaskReward) (chance int32, reward *award.RewardRes, err error) { err = s._receiveReward(taskRewards, func(tasks []*model.FissionCampaignTask, records []*award.RewardRes) error { chance, err = s.taskFinish(tasks, false) if err != nil { return err } if len(records) == 0 { return nil } reward = records[0] return nil }) if err != nil { return } return } // FinishTask 完成任务 func (s *Vs) FinishTask(tasks ...*model.FissionCampaignTask) (err error) { _, err = s.taskFinish(tasks, true) if err != nil { return } return } // 完成任务 func (s *Vs) taskFinish(tasks []*model.FissionCampaignTask, checkManual bool) (chance int32, err error) { player := s.GetPlayer() var coinGet int32 var logs []*model.FissionVsLog for _, task := range tasks { if checkManual && task.AwardMode == mtype.FissionCampaignTaskAwardModeManual { continue } var val string var t int8 switch task.PropMark { case mtype.FissionCampaignTaskPropMarkChance: chance += task.Chance val, _ = jsonm.MarshalToString(mtype.VsLogVal{ TaskId: task.ID, Chance: task.Chance, }) t = mtype.FissionVsLogTypeAddVote case mtype.FissionCampaignTaskPropMarkPoint: val, _ = jsonm.MarshalToString(mtype.VsLogVal{ TaskId: task.ID, PointsNum: task.Chance, }) t = mtype.FissionVsLogTypeAddPoint coinGet += task.Chance case mtype.FissionCampaignTaskPropMarkReward: val, _ = jsonm.MarshalToString(mtype.VsLogVal{ TaskId: task.ID, RewardId: task.RewardID, }) t = mtype.FissionVsLogTypeReward } log := withdefault.FissionVsLog(&model.FissionVsLog{ UserID: player.UserID, CampaignID: player.CampaignID, VsID: player.ID, Type: t, Source: "", Val: val, }) switch task.TaskType { case mtype.FissionCampaignTaskTypeRegister: log.Source = mtype.FissionLogSourceRegister case mtype.FissionCampaignTaskTypeInstall: log.Source = mtype.FissionLogSourceInstall case mtype.FissionCampaignTaskTypeCondAll: log.Source = utils.Ternary[string](task.AwardMode == mtype.FissionCampaignTaskAwardModeManual, mtype.FissionLogSourceManualCondAll, mtype.FissionLogSourceCondAll) case mtype.FissionCampaignTaskTypeCondOne: log.Source = utils.Ternary[string](task.AwardMode == mtype.FissionCampaignTaskAwardModeManual, mtype.FissionLogSourceManualCondOne, mtype.FissionLogSourceCondOne) } logs = append(logs, log) } if chance > 0 || coinGet > 0 { m := s.GetDao().FissionV _, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.Chance.Add(chance), m.CoinGet.Add(coinGet)) if err != nil { return } } err = s._addLog(logs...) if err != nil { return } return } func (s *Vs) Vote(scheduleId, teamId int64) (status int32, err error) { s.Tran() defer func() { s.TranCommit(err) }() player, conf := s.GetPlayer(), s.GetConf() scheduleM := s.GetDao().FissionCampaignVsSchedule schedule, err := scheduleM.WithContext(s.Ctx).Where(scheduleM.ID.Eq(scheduleId)).Take() if err != nil { err = s.BE().MysqlError(err) return } if schedule.GetStatus() != mtype.FissionCampaignVsScheduleStatusVote { return voteEnd, nil } var winType int8 = mtype.FissionCampaignVsScheduleWinTypeWin if teamId == 0 { if !verify.InArray[string](mtype.FissionCampaignVsScheduleOtherVoteDraw, schedule.GetOtherVote()...) { return voteFail, nil } winType = mtype.FissionCampaignVsScheduleWinTypeDraw } m := s.GetDao().FissionVsVote vote, err := m.WithContext(s.Ctx).Where(m.VsID.Eq(player.ID), m.ScheduleID.Eq(scheduleId)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if vote == nil { vote = withdefault.FissionVsVote(&model.FissionVsVote{ CampaignID: player.CampaignID, UserID: player.UserID, VsID: player.ID, ScheduleID: scheduleId, WinType: winType, WinTeamID: teamId, IsWin: 0, }) err = m.WithContext(s.Ctx).Create(vote) if err != nil { err = s.BE().MysqlError(err) return } defer func() { if status != voteOk { _, _ = m.WithContext(s.Ctx).Delete(vote) } }() } if vote.WinType != winType || vote.WinTeamID != teamId || (teamId > 0 && !verify.InArray[int64](teamId, schedule.GetVsTeamIds()...)) { return voteNotSameTeam, nil } if vote.FreeVote+vote.PointVote >= conf.EachLimitNum { return voteLimit, nil } if player.Chance > 0 { val, _ := jsonm.MarshalToString(mtype.VsLogVal{ Chance: 1, ScheduleId: scheduleId, WinType: winType, WinTeamId: teamId, }) log := withdefault.FissionVsLog(&model.FissionVsLog{ UserID: player.UserID, CampaignID: player.CampaignID, VsID: player.ID, Type: mtype.FissionVsLogTypeVote, Source: mtype.FissionLogSourceVote, Val: val, }) err = s._addLog(log) if err != nil { return } vsM := s.GetDao().FissionV _, err = vsM.WithContext(s.Ctx).Where(vsM.ID.Eq(player.ID)).UpdateSimple(vsM.Chance.Sub(1)) if err != nil { err = s.BE().MysqlError(err) return } _, err = m.WithContext(s.Ctx).Where(m.ID.Eq(vote.ID)).UpdateColumnSimple(m.FreeVote.Add(1)) if err != nil { err = s.BE().MysqlError(err) return } err = s._voteAdd() if err != nil { return } s.appTrack().VsVote(time.Now().Unix(), scheduleId, int32(winType), teamId) return voteOk, nil } if conf.OpenPoint == mtype.No { return voteLack, nil } pu, err := projectuser.NewProjectUser(s.Ctx, projectuser.WithInit(s.cpn.ProjectID, s.user.SubUserID), projectuser.WithDao(s.GetDao()), ) if err != nil { return } ok, err := pu.Deduct(mtype.ProjectUserCoinUseSourceCampaign, mtype.ProjectUserCoinDerVote, player.CampaignID, conf.PointsNum) if err != nil { return } if !ok { s.Rollback("项目用户积分不足") return voteLack, nil } val, _ := jsonm.MarshalToString(mtype.VsLogVal{ Chance: 1, ScheduleId: scheduleId, WinType: winType, WinTeamId: teamId, PointsNum: conf.PointsNum, }) log := withdefault.FissionVsLog(&model.FissionVsLog{ UserID: player.UserID, CampaignID: player.CampaignID, VsID: player.ID, Type: mtype.FissionVsLogTypeVote, Source: mtype.FissionLogSourceVote, Val: val, }) err = s._addLog(log) if err != nil { return } vsM := s.GetDao().FissionV _, err = vsM.WithContext(s.Ctx).Where(vsM.ID.Eq(player.ID)).UpdateSimple(vsM.CoinUse.Add(conf.PointsNum)) if err != nil { err = s.BE().MysqlError(err) return } _, err = m.WithContext(s.Ctx).Where(m.ID.Eq(vote.ID)).UpdateColumnSimple(m.PointVote.Add(1)) if err != nil { err = s.BE().MysqlError(err) return } err = s._voteAdd() if err != nil { return } s.appTrack().PointsUse(time.Now().Unix(), conf.PointsNum) s.appTrack().VsVote(time.Now().Unix(), scheduleId, int32(winType), teamId) return voteOk, nil } type Schedule struct { Id int64 Desc string VsImg string VsDate string VsTz int32 VoteCountdown int64 Status int32 OpenOdds int32 OddsLeft string OddsRight string OddsDraw string WinType int32 WinTeamId int64 Scores []*Score OtherVote []string Teams []*Team UserVote *UserVote Reward *Reward Votes []*Vote } type Score struct { TeamId int64 Score string } type UserVote struct { UserWinType int32 UserWinTeamId int64 IsWin bool VoteNum int32 } type Team struct { Id int64 Name string LogoImg string Score string } type Reward struct { Id int64 PropMark string Title string Img string KvData []*mtype.RewardKV ReceiveType int32 Contact string //联系方式 OpenToUse int32 //开启去使用(0-否,1-是) WebUrl string //Web端的跳转地址 AppParam string //App端的跳转参数 PcParam string //pc端的跳转参数 PropNum int32 RewardHashId string //领取的用户奖品hash_id } type Vote struct { WinType int32 `json:"win_type"` WinTeamId int64 `json:"win_team_id"` Num int64 `json:"num"` } func (s *Vs) Schedules(tabType int32) (list []*Schedule, err error) { player, conf := s.GetPlayer(), s.GetConf() teamM := s.GetDao().FissionCampaignVsTeam teams, err := teamM.WithContext(s.Ctx).Where(teamM.CampaignID.Eq(s.user.CampaignID)).Find() if err != nil { err = s.BE().MysqlError(err) return } var teamMap = make(map[int64]*model.FissionCampaignVsTeam, len(teams)) for _, v := range teams { teamMap[v.ID] = v } voteM := s.GetDao().FissionVsVote votes, err := voteM.WithContext(s.Ctx).Where( voteM.CampaignID.Eq(s.user.CampaignID), voteM.VsID.Eq(player.ID), ).Find() if err != nil { err = s.BE().MysqlError(err) return } var voteMap = make(map[int64]*model.FissionVsVote, len(votes)) for _, v := range votes { voteMap[v.ScheduleID] = v } scheduleM := s.GetDao().FissionCampaignVsSchedule schedules, err := scheduleM.WithContext(s.Ctx).Where( scheduleM.CampaignID.Eq(player.CampaignID), scheduleM.VsAt.Gt(0), ).Order(scheduleM.VsAt.Asc()).Find() if err != nil { err = s.BE().MysqlError(err) return } var rewardIds []int64 for _, v := range schedules { rewardIds = append(rewardIds, v.RewardID) } rewardM := s.GetDao().FissionCampaignReward rewards, err := rewardM.WithContext(s.Ctx).Where(rewardM.ID.In(rewardIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } var hasPoint bool var brdIds []int64 var brdMap = make(map[int64]struct{}) for _, v := range rewards { if _, ok := brdMap[v.RewardID]; !ok && v.RewardID > 0 { brdIds = append(brdIds, v.RewardID) } if v.PropMark == mtype.FissionCampaignRewardPropMarkPoint { hasPoint = true } } preward, err := provider.NewRewards(s.Ctx, s.cpn.ProjectID, brdIds...) if err != nil { return } var title, imgUrl string if hasPoint { title, imgUrl, _, err = cmm.NewCMM(s.Ctx, s.GetDao()).GetCoinInfo(s.cpn.ProjectID, s.user.LangMark) if err != nil { return } } var rewardMap = make(map[int64]*Reward, len(rewards)) for _, reward := range rewards { one := &Reward{ Id: reward.ID, PropMark: reward.PropMark, Title: title, Img: imgUrl, KvData: nil, ReceiveType: 0, Contact: "", OpenToUse: 0, WebUrl: "", AppParam: "", PcParam: "", PropNum: reward.RewardNum, } if reward.PropMark == mtype.FissionCampaignRewardPropMarkReward { info, _ := preward.InfoAutoLang(reward.RewardID, s.user.LangMark) one.Title = info.Title one.Img = info.ImgUrl one.KvData = info.KvData one.ReceiveType = info.ReceiveType one.Contact = info.Contact one.OpenToUse = info.OpenToUse one.WebUrl = info.WebUrl one.AppParam = info.AppParam one.PcParam = info.PcParam } rewardMap[reward.ID] = one } var scheduleLang = make(map[int64]*mtype.VsSchedulePkTeam) if verify.InArray[string](s.user.LangMark, s.cpn.GetLangMarks()[1:]...) { var lang *model.FissionCampaignLang lang, err = cache.NewCampaignLang(s.Ctx).FindByCampaignId(player.CampaignID, s.user.LangMark) if err != nil { err = s.BE().CacheError(err) return } for _, v := range lang.GetVs() { for _, pk := range v.PkTeams { scheduleLang[pk.Id] = pk } } } var fn = func(v *model.FissionCampaignVsSchedule) { slt := v.GetSettlement() scoreMap := make(map[int64]string, len(slt.Scores)) for _, v := range slt.Scores { scoreMap[v.TeamId] = v.Score } one := &Schedule{ Id: v.ID, Desc: v.Desc, VsImg: v.VsImg, VsDate: timez.GMTTime(conf.VsTz, v.VsAt).Format(timez.PointYmdHi), VsTz: conf.VsTz, VoteCountdown: v.VoteEnd - time.Now().Unix(), Status: v.GetStatus(), OpenOdds: int32(v.OpenOdds), OddsLeft: v.OddsLeft, OddsRight: v.OddsRight, OddsDraw: v.OddsDraw, WinType: slt.WinType, WinTeamId: slt.WinTeamId, Scores: make([]*Score, 0, len(slt.Scores)), OtherVote: v.GetOtherVote(), Teams: make([]*Team, 0, len(v.GetVsTeamIds())), UserVote: nil, Reward: rewardMap[v.RewardID], Votes: nil, } for _, v := range slt.Scores { one.Scores = append(one.Scores, &Score{ TeamId: v.TeamId, Score: v.Score, }) } if vote, ok := voteMap[v.ID]; ok { one.UserVote = &UserVote{ UserWinType: int32(vote.WinType), UserWinTeamId: vote.WinTeamID, IsWin: vote.IsWin == mtype.Yes, VoteNum: vote.FreeVote + vote.PointVote, } } for _, teamId := range v.GetVsTeamIds() { two := &Team{ Id: teamId, } if team, ok := teamMap[teamId]; ok { two.Name = team.Name two.LogoImg = team.LogoImg two.Score = scoreMap[teamId] } one.Teams = append(one.Teams, two) } if lang, ok := scheduleLang[v.ID]; ok && lang != nil { one.Desc = lang.Desc one.VsImg = lang.VsImg for i, v := range lang.Teams { if v.Id > 0 { one.Teams[i].Name = v.Name one.Teams[i].LogoImg = v.LogoImg } } } one.Votes, err = s._voteNum(v.ID) if err != nil { return } list = append(list, one) } for _, v := range schedules { if tabType == 1 && !verify.InArray[int32](v.GetStatus(), mtype.FissionCampaignVsScheduleStatusVote, mtype.FissionCampaignVsScheduleStatusRunning) { continue } _, ok := voteMap[v.ID] if tabType == 3 && !ok { continue } fn(v) } if len(list) > 0 || tabType != 1 { return } l := len(schedules) for i := l; i > 0; i-- { one := schedules[i-1] if one.IsSettlement == mtype.Yes { fn(one) break } } return } // SetInit 获得初始次数 func (s *Vs) 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().FissionV _, 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.VsLogVal{ Chance: conf.InitChance, }) log := withdefault.FissionVsLog(&model.FissionVsLog{ UserID: player.UserID, CampaignID: player.CampaignID, VsID: player.ID, Type: mtype.FissionVsLogTypeAddVote, Source: mtype.FissionLogSourceInit, Val: val, }) err = s._addLog(log) if err != nil { return } s.player.Chance += conf.InitChance return } // GetConf 获取玩法配置 func (s *Vs) GetConf() *model.FissionCampaignV { if s.conf == nil { s.conf, _ = cache.NewCampaignVs(s.Ctx).FindByCampaignId(s.user.CampaignID) } return s.conf } // GetPlayer 获取玩家基础数据 func (s *Vs) GetPlayer() *model.FissionV { return s.player } // 玩家 func (s *Vs) 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 *Vs) firstOrCreate() (player *model.FissionV, 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 *Vs) _dbFirst() (*model.FissionV, error) { playerM := dao.FissionV 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 *Vs) createPlayer() (player *model.FissionV, err error) { playerM := dao.FissionV player = withdefault.FissionVs(&model.FissionV{ 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 *Vs) _addLog(logs ...*model.FissionVsLog) (err error) { err = s.GetDao().FissionVsLog.WithContext(s.Ctx).Create(logs...) if err != nil { err = s.BE().MysqlError(err) return } return } func (s *Vs) _voteNum(scheduleId int64) (votes []*Vote, err error) { m := s.GetDao().FissionVsVote voteNumField := field.NewUnsafeFieldRaw("free_vote + point_vote") err = m.WithContext(s.Ctx). Select(m.WinType, m.WinTeamID, voteNumField.Sum().As("num")). Where(m.ScheduleID.Eq(scheduleId)). Group(m.WinType, m.WinTeamID). Scan(&votes) if err != nil { err = s.BE().MysqlError(err) return } return } func (s *Vs) _voteAdd() (err error) { m := s.GetDao().FissionV _, err = m.WithContext(s.Ctx).Where(m.ID.Eq(s.GetPlayer().ID)).UpdateSimple(m.VoteNum.Add(1)) if err != nil { err = s.BE().MysqlError(err) return } s.player.VoteNum++ return }