|
|
|
@ -84,16 +84,18 @@ type PlayerRoundInfo struct {
|
|
|
|
|
|
|
|
|
|
type Tournament struct {
|
|
|
|
|
common.BaseClockSinker
|
|
|
|
|
TypeList map[string]*webapiproto.GameMatchType // 比赛类型列表 平台id:比赛类型列表
|
|
|
|
|
GameMatchDateList map[string]map[int32]*webapiproto.GameMatchDate // 比赛配置,platform:比赛场配置id:比赛配置
|
|
|
|
|
singleSignupPlayers map[int32]*SignupInfo // 开启机器人时,报名的玩家,玩家Id:报名信息
|
|
|
|
|
signupPlayers map[string]map[int32]*SignInfo // 报名的玩家 platform:比赛配置id:报名人
|
|
|
|
|
playerWaitStart map[int32]int64 // 等待时间 玩家Id:等待时长秒
|
|
|
|
|
matches map[int32]map[int64]*TmMatch // 开始比赛的数据,比赛配置Id:比赛顺序序号:一场开始的比赛数据
|
|
|
|
|
players map[int64]map[int32]*PlayerMatchContext // 比赛中玩家 比赛顺序序号:玩家id:玩家信息
|
|
|
|
|
roundPlayers map[int64]map[int32]*PlayerRoundInfo // 每轮比赛数据备份 比赛顺序序号:第几轮
|
|
|
|
|
finalPerRank map[int64][]*PerRankInfo // 本场比赛排名,每淘汰一位记录一位,最后记录决赛玩家 比赛顺序序号
|
|
|
|
|
MatchAwardNum map[string]map[int32]int32 // 比赛配置Id:比赛奖励次數
|
|
|
|
|
TypeList map[string]*webapiproto.GameMatchType // 平台id:比赛类型列表
|
|
|
|
|
GameMatchDateList map[string]map[int32]*webapiproto.GameMatchDate // 平台id:比赛场配置id:比赛配置
|
|
|
|
|
|
|
|
|
|
singleSignupPlayers map[int32]*SignupInfo // 玩家Id:报名信息; 使用机器人时的报名信息
|
|
|
|
|
signupPlayers map[string]map[int32]*SignInfo // 平台id:比赛配置id:报名信息; 不使用机器人时的报名信息
|
|
|
|
|
MatchAwardNum map[string]map[int32]int32 // 平台id:比赛配置Id:发第一名奖励次数
|
|
|
|
|
|
|
|
|
|
playerWaitStart map[int32]int64 // 玩家Id:等待时长秒; 玩家报名后等待比赛开始
|
|
|
|
|
matches map[int32]map[int64]*TmMatch // 比赛配置Id:比赛顺序序号:开始的比赛数据
|
|
|
|
|
players map[int64]map[int32]*PlayerMatchContext // 比赛顺序序号:玩家id:玩家信息
|
|
|
|
|
roundPlayers map[int64]map[int32]*PlayerRoundInfo // 比赛顺序序号:第几轮:结算记录
|
|
|
|
|
finalPerRank map[int64][]*PerRankInfo // 比赛顺序序号:本场比赛排名,每淘汰一位记录一位,最后记录决赛玩家
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewTournament() *Tournament {
|
|
|
|
@ -111,6 +113,61 @@ func NewTournament() *Tournament {
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) ModuleName() string {
|
|
|
|
|
return "Tournament"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) Init() {
|
|
|
|
|
logger.Logger.Trace("Tournament Init")
|
|
|
|
|
for _, v := range PlatformMgrSingleton.GetPlatforms() {
|
|
|
|
|
if v == nil || v.IdStr == "0" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
ret, err := model.GetMatchAward(v.IdStr)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Logger.Warnf("GetMatchAward error %v", err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if this.MatchAwardNum == nil {
|
|
|
|
|
this.MatchAwardNum = make(map[string]map[int32]int32)
|
|
|
|
|
}
|
|
|
|
|
this.MatchAwardNum[v.IdStr] = ret.Award
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) Update() {
|
|
|
|
|
// 使用机器人的情况
|
|
|
|
|
for snId, info := range this.singleSignupPlayers {
|
|
|
|
|
if info == nil || info.Ts <= 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
matchInfo := this.GetMatchInfo(info.Platform, info.TmId, 0)
|
|
|
|
|
if this.IsMatchOn(matchInfo) && !this.IsOutTime(matchInfo) && this.IsRobotOn(matchInfo) {
|
|
|
|
|
needTime := this.playerWaitStart[snId]
|
|
|
|
|
if time.Now().Unix()-info.Ts > needTime {
|
|
|
|
|
signInfo := &SignInfo{
|
|
|
|
|
signup: make(map[int32]*TmPlayer),
|
|
|
|
|
Platform: info.Platform,
|
|
|
|
|
MaxCnt: int(matchInfo.MatchNumebr),
|
|
|
|
|
}
|
|
|
|
|
seq := rand.Intn(int(matchInfo.MatchNumebr)) + 1
|
|
|
|
|
signInfo.signup[snId] = &TmPlayer{SnId: snId, seq: seq}
|
|
|
|
|
this.signupPlayers[info.Platform][info.TmId] = signInfo
|
|
|
|
|
|
|
|
|
|
//倒计时结束 开始比赛
|
|
|
|
|
this.Start(info.Platform, info.TmId)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.CancelSignUpAll(info.Platform, info.TmId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) Shutdown() {
|
|
|
|
|
this.SaveMatchAward()
|
|
|
|
|
module.UnregisteModule(this)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查下数据是否合法(主要检查报名人数和晋级方式) n n|...|4|1
|
|
|
|
|
func (this *Tournament) checkData(cfg *webapiproto.GameMatchDate) bool {
|
|
|
|
|
if cfg == nil {
|
|
|
|
@ -486,8 +543,8 @@ func (this *Tournament) GetAllMatchInfo(platform string) map[int32]*webapiproto.
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsMatching 判断是否在比赛中
|
|
|
|
|
func (this *Tournament) IsMatching(snId int32) bool {
|
|
|
|
|
// IsGaming 判断是否在比赛中
|
|
|
|
|
func (this *Tournament) IsGaming(snId int32) bool {
|
|
|
|
|
if this.players != nil {
|
|
|
|
|
for _, v := range this.players {
|
|
|
|
|
if v != nil {
|
|
|
|
@ -666,7 +723,7 @@ func (this *Tournament) SignUp(tmId int32, p *Player) (bool, int32) {
|
|
|
|
|
}
|
|
|
|
|
// 已报名
|
|
|
|
|
isWaiting, _ := this.IsMatchWaiting(p.Platform, p.SnId)
|
|
|
|
|
if this.IsMatching(p.SnId) || isWaiting {
|
|
|
|
|
if this.IsGaming(p.SnId) || isWaiting {
|
|
|
|
|
return false, int32(tournament.SignRaceCode_OPRC_Repeat)
|
|
|
|
|
}
|
|
|
|
|
if this.GetMatchAwardNum(p.Platform, tmId) <= 0 {
|
|
|
|
@ -783,7 +840,7 @@ func (this *Tournament) CancelSignUpAll(platform string, tmId int32) {
|
|
|
|
|
func (this *Tournament) Quit(platform string, snid int32) {
|
|
|
|
|
logger.Logger.Tracef("TournamentMgr.Quit: snId:%d", snid)
|
|
|
|
|
isWaiting, tmid := this.IsMatchWaiting(platform, snid)
|
|
|
|
|
if isWaiting && !this.IsMatching(snid) {
|
|
|
|
|
if isWaiting && !this.IsGaming(snid) {
|
|
|
|
|
this.CancelSignUp(platform, tmid, snid)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -861,6 +918,7 @@ func (this *Tournament) Start(platform string, tmId int32) {
|
|
|
|
|
// 开始比赛,清除报名数据
|
|
|
|
|
for _, v := range signInfo.signup {
|
|
|
|
|
delete(this.singleSignupPlayers, v.SnId)
|
|
|
|
|
delete(this.playerWaitStart, v.SnId)
|
|
|
|
|
TaskSubjectSingleton.Touch(common.TaskTypeJoinMatch, &TaskData{
|
|
|
|
|
SnId: v.SnId,
|
|
|
|
|
GameID: int(tm.dbGameFree.GetGameId()),
|
|
|
|
@ -880,9 +938,10 @@ func (this *Tournament) Start(platform string, tmId int32) {
|
|
|
|
|
// StopMatch 比赛结束
|
|
|
|
|
func (this *Tournament) StopMatch(tmId int32, sortId int64) {
|
|
|
|
|
logger.Logger.Tracef("StopMatch:%v, %v", tmId, sortId)
|
|
|
|
|
var tm *TmMatch
|
|
|
|
|
//房间清理
|
|
|
|
|
if this.matches[tmId] != nil && this.matches[tmId][sortId] != nil {
|
|
|
|
|
tm := this.matches[tmId][sortId]
|
|
|
|
|
tm = this.matches[tmId][sortId]
|
|
|
|
|
matchLog := this.MakeMatchLog(tm.Platform, tmId, sortId)
|
|
|
|
|
this.saveMatchLog(matchLog)
|
|
|
|
|
tm.Stop()
|
|
|
|
@ -1030,6 +1089,25 @@ func (this *Tournament) GetRank(sortId int64, snid int32) int32 {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) stopMatch(matchId int32, sortId int64) (isOver bool) {
|
|
|
|
|
if this.players[sortId] != nil {
|
|
|
|
|
hasReal := false
|
|
|
|
|
for snId, context := range this.players[sortId] {
|
|
|
|
|
if !context.p.IsRob && !this.isOut(sortId, snId) { // 有真人没有淘汰
|
|
|
|
|
hasReal = true
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//没有真人比赛解散
|
|
|
|
|
if !hasReal {
|
|
|
|
|
isOver = true
|
|
|
|
|
logger.Logger.Trace("没有真人比赛解散")
|
|
|
|
|
this.StopMatch(matchId, sortId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UpdateMatchInfo 玩家比赛结束 更新积分
|
|
|
|
|
func (this *Tournament) UpdateMatchInfo(p *Player, sortId int64, grade, isWin int32, matchRobotGrades map[int32]int32) {
|
|
|
|
|
logger.Logger.Tracef("UpdateMatchInfo: sortId:%v, grade:%v, isWin: %v, matchRobotGrades:%v", sortId, grade, isWin, matchRobotGrades)
|
|
|
|
@ -1083,25 +1161,6 @@ func (this *Tournament) UpdateMatchInfo(p *Player, sortId int64, grade, isWin in
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) stopMatch(matchId int32, sortId int64) (isOver bool) {
|
|
|
|
|
if this.players[sortId] != nil {
|
|
|
|
|
hasReal := false
|
|
|
|
|
for snId, context := range this.players[sortId] {
|
|
|
|
|
if !context.p.IsRob && !this.isOut(sortId, snId) { // 有真人没有淘汰
|
|
|
|
|
hasReal = true
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//没有真人比赛解散
|
|
|
|
|
if !hasReal {
|
|
|
|
|
isOver = true
|
|
|
|
|
logger.Logger.Trace("没有真人比赛解散")
|
|
|
|
|
this.StopMatch(matchId, sortId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NextRoundStartSingle 下一轮是否开始
|
|
|
|
|
// 开启机器人时使用
|
|
|
|
|
func (this *Tournament) NextRoundStartSingle(sortId int64, playerCtx *PlayerMatchContext, matchRobotGrades map[int32]int32) {
|
|
|
|
@ -1283,6 +1342,7 @@ func (this *Tournament) NextRoundStart(sortId int64, playerCtx *PlayerMatchConte
|
|
|
|
|
willOut = true
|
|
|
|
|
} else {
|
|
|
|
|
if !meIn { //自己暂时没晋级
|
|
|
|
|
logger.Logger.Tracef("待定 %+v", info.players)
|
|
|
|
|
this.sendPromotionInfo(playerCtx, sortId, DaiDing, false, false) //待定
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1307,23 +1367,23 @@ func (this *Tournament) NextRoundStart(sortId int64, playerCtx *PlayerMatchConte
|
|
|
|
|
}), nil, time.Second*7, 1)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.sendPromotionInfo(playerCtx, sortId, DaiDing, false, false) //待定
|
|
|
|
|
// 待定
|
|
|
|
|
logger.Logger.Tracef("待定 %+v", info.players)
|
|
|
|
|
this.sendPromotionInfo(playerCtx, sortId, DaiDing, false, false)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if len(info.players) == 4 {
|
|
|
|
|
MatchContextSlice(info.players).Sort(true)
|
|
|
|
|
for _, mc := range info.players {
|
|
|
|
|
outCode := TaoTai
|
|
|
|
|
if mc.rank == 1 {
|
|
|
|
|
outCode = JinJi
|
|
|
|
|
}
|
|
|
|
|
this.sendPromotionInfo(mc, sortId, outCode, true, true) //晋级
|
|
|
|
|
MatchContextSlice(info.players).Sort(true)
|
|
|
|
|
for _, mc := range info.players {
|
|
|
|
|
outCode := TaoTai
|
|
|
|
|
if mc.rank == 1 {
|
|
|
|
|
outCode = JinJi
|
|
|
|
|
}
|
|
|
|
|
logger.Logger.Trace("比赛结束!!! ")
|
|
|
|
|
|
|
|
|
|
// 比赛结束
|
|
|
|
|
this.StopMatch(playerCtx.tm.TMId, sortId)
|
|
|
|
|
this.sendPromotionInfo(mc, sortId, outCode, true, true) //晋级
|
|
|
|
|
}
|
|
|
|
|
logger.Logger.Trace("比赛结束!!! ")
|
|
|
|
|
|
|
|
|
|
// 比赛结束
|
|
|
|
|
this.StopMatch(playerCtx.tm.TMId, sortId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1877,7 +1937,7 @@ func (this *Tournament) MakeMatchLog(platform string, tmId int32, sortId int64)
|
|
|
|
|
matchLog.MatchName = gameMatchDate.MatchName
|
|
|
|
|
matchLog.Platform = platform
|
|
|
|
|
matchLog.GameFreeId = gameMatchDate.GameFreeId
|
|
|
|
|
matchLog.StartTime = time.Unix(this.matches[tmId][sortId].StartTime, 0)
|
|
|
|
|
matchLog.StartTime = this.matches[tmId][sortId].StartTime
|
|
|
|
|
matchLog.EndTime = time.Now()
|
|
|
|
|
matchLog.SortId = sortId
|
|
|
|
|
return matchLog
|
|
|
|
@ -1898,84 +1958,6 @@ func (this *Tournament) saveMatchLog(matchLog *model.MatchLog) {
|
|
|
|
|
})).StartByFixExecutor("saveMatchLogTask")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) ModuleName() string {
|
|
|
|
|
return "Tournament"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) Init() {
|
|
|
|
|
logger.Logger.Trace("Tournament Init")
|
|
|
|
|
for _, v := range PlatformMgrSingleton.GetPlatforms() {
|
|
|
|
|
if v == nil || v.IdStr == "0" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
ret, err := model.GetMatchAward(v.IdStr)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Logger.Warnf("GetMatchAward error %v", err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if this.MatchAwardNum == nil {
|
|
|
|
|
this.MatchAwardNum = make(map[string]map[int32]int32)
|
|
|
|
|
}
|
|
|
|
|
this.MatchAwardNum[v.IdStr] = ret.Award
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) Update() {
|
|
|
|
|
// 使用机器人的情况
|
|
|
|
|
for snId, info := range this.singleSignupPlayers {
|
|
|
|
|
if info == nil || info.Ts <= 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
matchInfo := this.GetMatchInfo(info.Platform, info.TmId, 0)
|
|
|
|
|
if this.IsMatchOn(matchInfo) && !this.IsOutTime(matchInfo) && this.IsRobotOn(matchInfo) {
|
|
|
|
|
needTime := this.playerWaitStart[snId]
|
|
|
|
|
if time.Now().Unix()-info.Ts > needTime {
|
|
|
|
|
signInfo := &SignInfo{
|
|
|
|
|
signup: make(map[int32]*TmPlayer),
|
|
|
|
|
Platform: info.Platform,
|
|
|
|
|
MaxCnt: int(matchInfo.MatchNumebr),
|
|
|
|
|
}
|
|
|
|
|
seq := rand.Intn(int(matchInfo.MatchNumebr)) + 1
|
|
|
|
|
signInfo.signup[snId] = &TmPlayer{SnId: snId, seq: seq}
|
|
|
|
|
this.signupPlayers[info.Platform][info.TmId] = signInfo
|
|
|
|
|
|
|
|
|
|
//倒计时结束 开始比赛
|
|
|
|
|
this.Start(info.Platform, info.TmId)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.CancelSignUpAll(info.Platform, info.TmId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 防止内存泄露
|
|
|
|
|
now := time.Now().Unix()
|
|
|
|
|
for _, v := range this.matches {
|
|
|
|
|
for _, vv := range v {
|
|
|
|
|
if vv != nil && now-vv.StartTime > int64(time.Hour.Seconds()*5) {
|
|
|
|
|
for _, p := range vv.TmPlayer {
|
|
|
|
|
this.ForceQuit(vv.Platform, p.SnId)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) OnDayTimer() {
|
|
|
|
|
for k := range this.MatchAwardNum {
|
|
|
|
|
this.MatchAwardNum[k] = make(map[int32]int32)
|
|
|
|
|
}
|
|
|
|
|
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
|
|
|
|
this.SaveMatchAward()
|
|
|
|
|
return nil
|
|
|
|
|
}), nil, "save_match_award_times").Start()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) Shutdown() {
|
|
|
|
|
this.SaveMatchAward()
|
|
|
|
|
module.UnregisteModule(this)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) SaveMatchAward() {
|
|
|
|
|
if this.MatchAwardNum == nil {
|
|
|
|
|
return
|
|
|
|
@ -2047,11 +2029,44 @@ func (this *Tournament) FixMatchTimeStamp(d *webapiproto.GameMatchDate) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) OnHourTimer() {
|
|
|
|
|
now := time.Now()
|
|
|
|
|
for _, v := range this.GameMatchDateList {
|
|
|
|
|
for _, vv := range v {
|
|
|
|
|
this.FixMatchTimeStamp(vv)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 防止异常情况卡房间
|
|
|
|
|
for _, v := range this.matches {
|
|
|
|
|
for _, vv := range v {
|
|
|
|
|
if vv != nil && (now.Sub(vv.RoundTime).Hours() >= 1 || now.Sub(vv.StartTime).Hours() > 5) {
|
|
|
|
|
logger.Logger.Errorf("比赛异常 %v", vv)
|
|
|
|
|
this.StopMatch(vv.TMId, vv.SortId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for sortId := range this.players {
|
|
|
|
|
for _, tm := range this.matches {
|
|
|
|
|
if _, ok := tm[sortId]; !ok {
|
|
|
|
|
for _, v := range this.players[sortId] {
|
|
|
|
|
if v != nil {
|
|
|
|
|
logger.Logger.Errorf("比赛异常 %v", v.tm)
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
this.StopMatch(0, sortId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *Tournament) OnDayTimer() {
|
|
|
|
|
for k := range this.MatchAwardNum {
|
|
|
|
|
this.MatchAwardNum[k] = make(map[int32]int32)
|
|
|
|
|
}
|
|
|
|
|
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
|
|
|
|
this.SaveMatchAward()
|
|
|
|
|
return nil
|
|
|
|
|
}), nil, "save_match_award_times").Start()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetMatchAwardNum 剩余奖励数量
|
|
|
|
@ -2080,6 +2095,7 @@ func (this *Tournament) GetMatchAwardNum(platform string, id int32) int32 {
|
|
|
|
|
return num
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetRound 获取当前轮次
|
|
|
|
|
func (this *Tournament) GetRound(sortId int64) int32 {
|
|
|
|
|
d, ok := this.roundPlayers[sortId]
|
|
|
|
|
if !ok || d == nil {
|
|
|
|
|