game_sync/worldsrv/tournament.go

1427 lines
45 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"math/rand"
"sort"
"strconv"
"sync"
"time"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/i18n"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/module"
"mongo.games.com/goserver/core/task"
"mongo.games.com/goserver/core/timer"
"mongo.games.com/game/common"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/tournament"
webapi_proto "mongo.games.com/game/protocol/webapi"
"mongo.games.com/game/srvdata"
"mongo.games.com/game/webapi"
)
const (
MatchTypeNormal = 1 // 锦标赛
MatchTypeChampion = 2 // 冠军赛
MatchTypeVIP = 3 // vip比赛
)
const (
MatchSwitchStart = 1 // 开启
MatchSwitchClose = 2 // 关闭
)
const (
MatchUseRobot = 0 // 使用机器人
MatchNotUserRobot = 1 // 关闭机器人
)
// tournament
var TournamentMgr = &Tournament{
GameMatchDateList: make(map[string]map[int32]*webapi_proto.GameMatchDate), //比赛配置
matches: make(map[int32]map[int32]*TmMatch),
signUpPlayers: make(map[string]map[int32]*SignInfo),
players: make(map[int32]map[int32]*PlayerMatchContext),
copyPlayers: make(map[int32]map[int32][]*PlayerMatchContext),
rankPlayers: make(map[int32]map[int32][]*PlayerMatchContext),
roundOverPlayerNum: make(map[int32]map[int32]int32),
finalPerRank: make(map[int32][]*PerRankInfo),
playerSignUpTime: make(map[int32]int64),
playerWaitStart: make(map[int32]int64),
singleSignupPlayers: make(map[int32]*SignupInfo),
singleFinalGrades: make(map[int32]map[int32]int32),
}
type Tournament struct {
GameMatchDateList map[string]map[int32]*webapi_proto.GameMatchDate // 比赛配置platform:比赛场配置id:比赛配置
matches map[int32]map[int32]*TmMatch // 开始比赛的数据比赛配置Id:比赛顺序序号:一场开始的比赛数据
signUpPlayers map[string]map[int32]*SignInfo // 报名的玩家 platform:比赛配置id:报名人
players map[int32]map[int32]*PlayerMatchContext // 比赛中玩家 比赛顺序序号:snid:玩家信息
copyPlayers map[int32]map[int32][]*PlayerMatchContext // 比赛玩家数据备份 比赛顺序序号:round:玩家信息
rankPlayers map[int32]map[int32][]*PlayerMatchContext //比赛玩家为了每轮积分排名用 比赛顺序序号,round
roundOverPlayerNum map[int32]map[int32]int32 // 完成比赛人数 比赛序号:轮次:人数
finalPerRank map[int32][]*PerRankInfo //本场比赛最后排名,每淘汰一位记录一位,最后记录决赛玩家
playerWaitStart map[int32]int64 // 等待时间 玩家Id:等待时长秒
singleFinalGrades map[int32]map[int32]int32 //使用机器人模式最后一轮分数
// UseRobot
playerSignUpTime map[int32]int64 //玩家报名时间 玩家Id:报名时间戳
singleSignupPlayers map[int32]*SignupInfo //报名的玩家玩家Id:报名信息
// UseRobot
}
type PerRankInfo struct {
Name string
SnId int32
RankId int32
Grade int32
}
type SignInfo struct {
signup map[int32]*TmPlayer //玩家Id
Platform string
MaxCnt int // 最大报名人数
}
type SignupInfo struct {
Platform string
Tmid int32
Snid int32
}
// 检查下数据是否合法(主要检查报名人数和晋级方式) n n|...|4|1
func (this *Tournament) checkData(cfg *webapi_proto.GameMatchDate) bool {
if cfg == nil {
return false
}
l := len(cfg.MatchPromotion)
if l < 2 {
return false
}
if cfg.MatchPromotion[0] != cfg.MatchNumebr { //第一位必须和报名人数相同
return false
}
if cfg.MatchPromotion[l-1] != 1 { //最后一位必须是1
return false
}
if cfg.MatchPromotion[l-2] != 4 { //倒数第二位必须是4
return false
}
for i, num := range cfg.MatchPromotion {
if i < l-1 { //除了最后一位
if num%4 != 0 { //必须是4的整倍数
return false
}
if num < cfg.MatchPromotion[i+1] { //必须递减
return false
}
}
}
return true
}
// UpdateData 更新配置
// init: 通知客户端配置变更
func (this *Tournament) UpdateData(init bool, cfgs *webapi_proto.GameMatchDateList) {
//logger.Logger.Trace("(this *Tournament) UpdateData:", cfgs)
if cfgs.Platform == "0" {
return
}
gmds := make(map[int32]*webapi_proto.GameMatchDate)
for _, v := range cfgs.List {
if this.checkData(v) {
gmds[v.Id] = v
} else {
logger.Logger.Error("GameMatchDate error: ", v)
}
}
oldgmds := this.GameMatchDateList[cfgs.Platform]
//旧配置关闭踢人 --旧配置关闭不影响已经开始的只取消报名未开始的
for _, v := range oldgmds {
gmd := gmds[v.Id]
if (gmd != nil && v.MatchSwitch == MatchSwitchStart && gmd.MatchSwitch != v.MatchSwitch) || //配置关闭
(gmd != nil && !this.IsTimeRange(gmd)) || //或者不在时间段内
(gmd != nil && v.UseRobot != gmd.UseRobot) || //或者匹配模式有修改
gmd == nil { //或者删除
signInfo := this.signUpPlayers[cfgs.Platform][v.Id]
if signInfo != nil && len(signInfo.signup) > 0 {
// 取消报名
this.CancelSignUpAll(cfgs.Platform, v.Id)
}
}
}
//新配置增加更新
for _, v := range gmds {
oldgmd := oldgmds[v.Id]
if oldgmd == nil || v.MatchSwitch == MatchSwitchStart {
if this.signUpPlayers[cfgs.Platform] == nil {
this.signUpPlayers[cfgs.Platform] = make(map[int32]*SignInfo)
}
this.signUpPlayers[cfgs.Platform][v.Id] = &SignInfo{
signup: make(map[int32]*TmPlayer),
Platform: cfgs.Platform,
MaxCnt: int(v.MatchNumebr),
}
}
if v.MatchSwitch == MatchSwitchClose || !this.IsTimeRange(v) {
this.CancelSignUpAll(cfgs.Platform, v.Id)
if v.MatchSwitch == MatchSwitchClose {
delete(this.signUpPlayers[cfgs.Platform], v.Id)
}
}
}
this.GameMatchDateList[cfgs.Platform] = gmds
if !init {
//todo 优化
for _, v := range PlayerMgrSington.playerOfPlatform[cfgs.Platform] {
//通知平台玩家数据更新
pack := TournamentMgr.GetSCTMInfosPack(cfgs.Platform, v.AppChannel)
proto.SetDefaults(pack)
logger.Logger.Trace("SCTMInfos++++++++++++:", pack)
v.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCTMInfos), pack)
}
}
}
// GetMatchInfo 比赛配置
func (this *Tournament) GetMatchInfo(platform string, tmId int32) *webapi_proto.GameMatchDate {
if list, ok := this.GameMatchDateList[platform]; ok {
if gmd, ok1 := list[tmId]; ok1 {
return gmd
}
}
return nil
}
// MatchSwitch 比赛开关
func (this *Tournament) MatchSwitch(platform string, tmId int32) bool {
info := this.GetMatchInfo(platform, tmId)
return info != nil && info.MatchSwitch == MatchSwitchStart
}
// IsUseRobot 是否用机器人
func (this *Tournament) IsUseRobot(platform string, tmId int32) bool {
info := this.GetMatchInfo(platform, tmId)
return info != nil && info.UseRobot == MatchUseRobot
}
// 周几
func getWeekNum(t time.Time) int {
strWeek := []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
week := t.Weekday()
for i, s := range strWeek {
if week.String() == s {
return i
}
}
return 0
}
// IsTimeRange 判断是否在比赛时间段内
// 在时间段内才能报名
func (this *Tournament) IsTimeRange(gmd *webapi_proto.GameMatchDate) bool {
if gmd != nil {
if gmd.MatchType == 2 { //冠军赛
tNow := time.Now()
switch gmd.MatchTimeType { // 0无时效 1重复时间段 2一次性时间段
case 0:
return true
case 1:
nowWeek := getWeekNum(tNow)
hms := int32(tNow.Hour()*10000 + tNow.Minute()*100 + tNow.Second())
if gmd.MatchTimeWeek != nil && len(gmd.MatchTimeWeek) > 0 {
for _, week := range gmd.MatchTimeWeek {
if nowWeek == int(week) {
if hms >= gmd.MatchTimeStartHMS && hms <= gmd.MatchTimeEndHMS {
return true
}
}
}
}
case 2:
if gmd.MatchTimeStamp != nil && len(gmd.MatchTimeStamp) > 1 {
startStamp := gmd.MatchTimeStamp[0]
endStamp := gmd.MatchTimeStamp[1]
if tNow.Unix() >= startStamp && tNow.Unix() <= endStamp {
return true
}
}
}
} else { //锦标赛没有时间限制
return true
}
}
return false
}
// IsOutTime 是否过期
func (this *Tournament) IsOutTime(gmd *webapi_proto.GameMatchDate) bool {
if gmd == nil || gmd.MatchSwitch != MatchSwitchStart {
return true
}
if gmd.MatchType == MatchTypeChampion { //冠军赛的一次性时间段才有过期可能
switch gmd.MatchTimeType { // 0无时效 1重复时间段 2一次性时间段
case 2:
tNow := time.Now()
if gmd.MatchTimeStamp != nil && len(gmd.MatchTimeStamp) > 1 {
endStamp := gmd.MatchTimeStamp[1]
if tNow.Unix() >= endStamp { //当前时间大于截止时间
return true
}
}
}
}
return false
}
// GetAllMatchInfo 比赛配置数据
func (this *Tournament) GetAllMatchInfo(platform string) map[int32]*webapi_proto.GameMatchDate {
if list, ok := this.GameMatchDateList[platform]; ok {
return list
}
return nil
}
// IsMatching 判断是否在比赛中
func (this *Tournament) IsMatching(snid int32) bool {
if this.players != nil {
for _, v := range this.players {
if v != nil {
for k := range v {
if k == snid {
return true
}
}
}
}
}
return false
}
// IsMatchWaiting 判断是否在匹配中
func (this *Tournament) IsMatchWaiting(platform string, snid int32) (bool, int32) {
// 未使用机器人
if this.signUpPlayers != nil && this.signUpPlayers[platform] != nil {
for tmid, info := range this.signUpPlayers[platform] {
if info.signup != nil {
for sid, _ := range info.signup {
if sid == snid {
return true, tmid
}
}
}
}
}
// 使用机器人了
if v, ok := this.singleSignupPlayers[snid]; ok {
return true, v.Tmid
}
return false, 0
}
// Quit 如果正在等待比赛,退赛
func (this *Tournament) Quit(platform string, snid int32) {
isWaiting, tmid := this.IsMatchWaiting(platform, snid)
if isWaiting {
this.CancelSignUp(platform, tmid, snid)
}
}
// signUpCost 报名
// tmId 比赛配置id
// cost true报名、false取消报名
// 报名费用 0成功 3道具不足 5金币不足 6钻石不足 7免费次数不足
func (this *Tournament) signUpCost(tmId int32, p *Player, cost bool) (bool, int32) {
logger.Logger.Trace("报名费用 signUpCost: ", tmId, " snid: ", p.SnId, " cost: ", cost)
if p == nil {
return false, int32(tournament.SignRaceCode_OPRC_NoItem)
}
gmd := this.GetMatchInfo(p.Platform, tmId)
if gmd != nil && !p.IsRob { //真人费用检测
if gmd.MatchType == MatchTypeVIP { //VIP比赛场
freeTimes := p.GetVIPPrivilege1() // VIP比赛场免费次数
logger.Logger.Trace("报名费用免费次数: freeTimes: ", freeTimes, " p.VipMatchTimes: ", p.VipMatchTimes)
if freeTimes > 0 {
if cost {
if p.VipMatchTimes < freeTimes { //参与次数<免费次数
p.VipMatchTimes++
} else {
logger.Logger.Trace("免费次数不足1")
return false, int32(tournament.SignRaceCode_OPRC_Free)
}
} else {
if p.VipMatchTimes > 0 {
p.VipMatchTimes--
} else {
p.VipMatchTimes = 0
}
}
} else {
logger.Logger.Trace("免费次数不足2")
return false, int32(tournament.SignRaceCode_OPRC_Free)
}
}
if gmd.SignupCostCoin > 0 {
logger.Logger.Trace("比赛场报名消耗金币", cost, gmd.SignupCostCoin)
if cost {
if p.Coin < gmd.SignupCostCoin { //金币不足
logger.Logger.Trace("金币不足")
return false, int32(tournament.SignRaceCode_OPRC_Coin)
} else {
p.AddCoin(-gmd.SignupCostCoin, 0, common.GainWay_MatchSignup, "system", gmd.MatchName+"-报名消耗")
}
} else {
p.AddCoin(gmd.SignupCostCoin, 0, common.GainWay_MatchSignup, "system", gmd.MatchName+"-报名退还")
}
}
if gmd.SignupCostDiamond > 0 {
logger.Logger.Trace("比赛场报名消耗钻石", cost, gmd.SignupCostDiamond)
if cost {
if p.Diamond < gmd.SignupCostDiamond { //钻石不足
logger.Logger.Trace("钻石不足")
return false, int32(tournament.SignRaceCode_OPRC_Diamond)
} else {
p.AddDiamond(-gmd.SignupCostDiamond, 0, common.GainWay_MatchSignup, "system", gmd.MatchName+"-报名消耗")
}
} else {
p.AddDiamond(gmd.SignupCostDiamond, 0, common.GainWay_MatchSignup, "system", gmd.MatchName+"-报名退还")
}
}
if gmd.SignupCostItem != nil && gmd.SignupCostItem.ItemNum > 0 {
//背包数据处理
logger.Logger.Trace("比赛场报名消耗道具", cost, gmd.SignupCostItem.ItemNum)
item := BagMgrSingleton.GetItem(p.SnId, gmd.SignupCostItem.ItemId)
if item != nil {
if cost {
if item.ItemNum < gmd.SignupCostItem.ItemNum {
logger.Logger.Trace("道具不足")
return false, int32(tournament.SignRaceCode_OPRC_NoItem)
} else {
BagMgrSingleton.SalePlayerItem(p, item, gmd.SignupCostItem.ItemNum)
//item.ItemNum -= gmd.SignupCostItem.ItemNum
//p.dirty = true
BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemConsume, item.ItemId, item.Name, gmd.SignupCostItem.ItemNum, gmd.MatchName+"-报名消耗")
//BagMgrSingleton.SyncBagData(p, item.ItemId)
}
} else {
BagMgrSingleton.SalePlayerItem(p, item, -gmd.SignupCostItem.ItemNum)
//item.ItemNum += gmd.SignupCostItem.ItemNum
//p.dirty = true
BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemObtain, item.ItemId, item.Name, gmd.SignupCostItem.ItemNum, gmd.MatchName+"-报名退还")
//BagMgrSingleton.SyncBagData(p, item.ItemId)
}
} else {
logger.Logger.Trace("道具不足")
return false, int32(tournament.SignRaceCode_OPRC_NoItem)
}
}
}
return true, 0
}
// SignUp 报名
// 0成功 1重复报名 2比赛没有开启 3道具不足 4不在报名时间段 5金币不足 6钻石不足 7免费次数不足
func (this *Tournament) SignUp(tmId int32, p *Player) (bool, int32) {
logger.Logger.Trace("(this *Tournament) SignUp:", tmId, p.SnId)
// 开启
info := this.GetMatchInfo(p.Platform, tmId)
if info == nil || info.GetMatchSwitch() == MatchSwitchClose {
return false, int32(tournament.SignRaceCode_OPRC_Close)
}
// 报名时间
if !TournamentMgr.IsTimeRange(info) {
return false, int32(tournament.SignRaceCode_OPRC_Time)
}
// 已报名
isWaiting, _ := TournamentMgr.IsMatchWaiting(p.Platform, p.SnId)
if TournamentMgr.IsMatching(p.SnId) || isWaiting {
return false, int32(tournament.SignRaceCode_OPRC_Repeat)
}
// 扣报名费
ok, code := this.signUpCost(tmId, p, true)
if !ok {
return false, code
}
var signInfo *SignInfo
gmd := this.GetMatchInfo(p.Platform, tmId)
if gmd == nil {
logger.Logger.Errorf("GetMatchInfo is nil. id=%v", tmId)
return false, int32(tournament.SignRaceCode_OPRC_Repeat)
}
if this.IsUseRobot(p.Platform, tmId) {
signupInfo := &SignupInfo{
Platform: p.Platform,
Tmid: tmId,
Snid: p.SnId,
}
this.singleSignupPlayers[p.SnId] = signupInfo
this.playerSignUpTime[p.SnId] = time.Now().Unix()
} else {
signInfo = &SignInfo{
signup: make(map[int32]*TmPlayer),
Platform: p.Platform,
MaxCnt: int(gmd.MatchNumebr),
}
var platform = p.Platform
gps := PlatformMgrSingleton.GetGameFree(p.Platform, gmd.GameFreeId)
if gps != nil && gps.GroupId != 0 {
for plt := range this.signUpPlayers {
gps2 := PlatformMgrSingleton.GetGameFree(plt, gmd.GameFreeId)
if gps.GroupId == gps2.GroupId {
platform = plt
break
}
}
}
if _, ok := this.signUpPlayers[platform][tmId]; !ok {
this.signUpPlayers[platform][tmId] = signInfo
} else {
signInfo = this.signUpPlayers[platform][tmId]
}
if _, ok := signInfo.signup[p.SnId]; !ok {
n := len(signInfo.signup) + 1
signInfo.signup[p.SnId] = &TmPlayer{SnId: p.SnId, seq: n}
logger.Logger.Trace("没使用机器人,真人 报名.............", n, " p.SnId: ", p.SnId)
} else {
return false, int32(tournament.SignRaceCode_OPRC_Repeat)
}
}
//(报名人数/20报名人数/10
minTime := gmd.MatchNumebr / 20
maxTime := gmd.MatchNumebr / 10
if gmd.MatchNumebr > 20 {
this.playerWaitStart[p.SnId] = int64(minTime + rand.Int31n(maxTime-minTime))
} else {
this.playerWaitStart[p.SnId] = 1
}
return true, 0
}
// CancelSignUp 取消玩家报名
func (this *Tournament) CancelSignUp(platform string, tmid, snid int32) {
delete(this.playerWaitStart, snid)
if this.signUpPlayers[platform] != nil && this.signUpPlayers[platform][tmid] != nil {
signInfo := this.signUpPlayers[platform][tmid]
if _, ok := signInfo.signup[snid]; ok {
p := PlayerMgrSington.GetPlayerBySnId(snid)
if p != nil && p.scene == nil {
//退费
this.signUpCost(tmid, p, false)
delete(this.signUpPlayers[platform][tmid].signup, snid)
//通知取消报名
pack := &tournament.SCSignRace{
OpCode: 1,
RetCode: 0,
}
proto.SetDefaults(pack)
logger.Logger.Trace("signUpPlayers: ", pack)
p.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCSignRace), pack)
return
}
}
}
if signupinfo, ok := this.singleSignupPlayers[snid]; ok {
p := PlayerMgrSington.GetPlayerBySnId(snid)
if p != nil && p.scene == nil {
//退费
this.signUpCost(signupinfo.Tmid, p, false)
delete(this.singleSignupPlayers, snid)
delete(this.playerSignUpTime, snid)
//通知取消报名
pack := &tournament.SCSignRace{
OpCode: 1,
RetCode: 0,
}
proto.SetDefaults(pack)
logger.Logger.Trace("singleSignupPlayers: ", pack)
p.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCSignRace), pack)
return
}
}
}
// CancelSignUpAll 取消所有报名
func (this *Tournament) CancelSignUpAll(platform string, tmId int32) {
if this.signUpPlayers[platform] != nil && this.signUpPlayers[platform][tmId] != nil {
for _, tmp := range this.signUpPlayers[platform][tmId].signup {
this.CancelSignUp(platform, tmId, tmp.SnId)
}
}
if this.singleSignupPlayers != nil {
for _, signupInfo := range this.singleSignupPlayers {
if signupInfo.Tmid == tmId {
this.CancelSignUp(signupInfo.Platform, tmId, signupInfo.Snid)
}
}
}
}
// CanStart 是否开赛
// 没有开机器人走这个判断
func (this *Tournament) CanStart(platform string, tmId int32) bool {
if this.signUpPlayers != nil && this.signUpPlayers[platform] != nil {
if signInfo, ok := this.signUpPlayers[platform][tmId]; ok {
matchInfo := this.GetMatchInfo(signInfo.Platform, tmId)
if matchInfo != nil {
n := 0
for _, v := range signInfo.signup {
p := PlayerMgrSington.GetPlayerBySnId(v.SnId)
if p == nil || p.scene != nil { //人不在或者在游戏内
this.CancelSignUp(platform, tmId, v.SnId)
break
}
n++
}
logger.Logger.Trace("TournamentMgr.CanStart: n: ", n, " matchInfo: ", matchInfo)
needNum := matchInfo.MatchNumebr / 4 * 4 //对4向下取整防止后台配置数据不是4的倍数
//所有人都准备好了
if needNum == int32(n) {
//人满 开始比赛
return true
}
}
}
}
return false
}
// Start 开赛
func (this *Tournament) Start(platform string, tmId int32) {
if this.signUpPlayers[platform] == nil {
this.signUpPlayers[platform] = make(map[int32]*SignInfo)
}
matchInfo := this.GetMatchInfo(platform, tmId)
signInfo := this.signUpPlayers[platform][tmId]
sortId := int32(time.Now().Nanosecond())
tm := &TmMatch{
TMId: tmId,
SortId: sortId,
gmd: matchInfo,
Platform: signInfo.Platform,
tmpUseRobot: matchInfo.UseRobot,
}
tm.gml = srvdata.MatchLevelMgr.Get(matchInfo.GameFreeId, matchInfo.MatchLevel)
tm.dbGameFree = srvdata.PBDB_GameFreeMgr.GetData(matchInfo.GameFreeId)
tm.CopyMap(signInfo.signup)
if this.matches[tmId] == nil {
this.matches[tmId] = make(map[int32]*TmMatch)
}
logger.Logger.Tracef("开赛:%+v, 难度:%v", tm, tm.gml)
// 开始比赛,清除报名数据
this.matches[tmId][sortId] = tm
tm.Start()
this.signUpPlayers[platform][tmId].signup = make(map[int32]*TmPlayer)
}
// NextRoundStartSingle 下一轮是否开始
func (this *Tournament) NextRoundStartSingle(sortId int32, mtp *PlayerMatchContext, matchRobotGrades map[int32]int32) {
logger.Logger.Tracef("================NextRoundStart_Single==========当前第 %v 轮============", mtp.round)
if _, ok := this.copyPlayers[sortId]; ok {
if _, ok1 := this.copyPlayers[sortId][mtp.round]; ok1 {
gmd := mtp.tm.gmd
//需要晋级的人数
promotionNum := gmd.MatchPromotion[mtp.round] // 晋级人数
if promotionNum != 1 { // 非决赛
if mtp.tm.robotGrades == nil || mtp.tm.robotGrades[int(mtp.round)] == nil {
mtp.tm.CreateRobotGrades(int(mtp.round))
}
if mtp.tm.robotGrades != nil && mtp.tm.robotGrades[int(mtp.round)] != nil {
robotGrades := mtp.tm.robotGrades[int(mtp.round)]
// 修改陪真人玩的机器人积分
if matchRobotGrades != nil {
logger.Logger.Trace("matchRobotGrades: ", matchRobotGrades)
for _, gradeInfo := range robotGrades {
if grade, ok := matchRobotGrades[gradeInfo.copySnid]; ok {
gradeInfo.grade = grade
}
}
}
//非决赛淘汰后开始配桌
logger.Logger.Trace("需要晋级的人数 promotionNum: ", promotionNum)
logger.Logger.Trace("非决赛开始淘汰晋级 grade: ", mtp.grade)
// 记录真人积分
findMe := false
for _, gradeinfo := range robotGrades {
if gradeinfo.copySnid == 0 {
gradeinfo.grade = mtp.grade
findMe = true
break
}
}
if !findMe {
gradeInfo := &TmGradeInfo{
grade: mtp.grade,
copySnid: 0,
}
robotGrades = append(robotGrades, gradeInfo) // 添加了真人数据
}
sort.Slice(robotGrades, func(i, j int) bool {
return robotGrades[i].grade > robotGrades[j].grade
})
for _, info := range robotGrades {
logger.Logger.Trace("Snid: ", info.copySnid, " grade: ", info.grade, " copyLv: ", info.copyLv, " copyRoleId: ", info.copyRoleId)
}
// 获取排名
index := int32(0) //晋级淘汰
for i, gradeinfo := range robotGrades {
if mtp.grade >= gradeinfo.grade {
index = int32(i) + 1
break
}
}
robotGrades = append(robotGrades[:promotionNum])
mtp.tm.robotGrades[int(mtp.round)] = robotGrades
if index == 0 { // 是最后一名
index = gmd.MatchPromotion[mtp.round-1]
}
if index <= promotionNum {
mtp.rank = index
this.sendPromotionInfo(mtp, sortId, JinJi, false, false) //晋级
mct := []*PlayerMatchContext{mtp}
finals := false
if mtp.round == int32(len(gmd.MatchPromotion)-2) {
finals = true
}
timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
MatchSceneMgrSingleton.NewRoundStart(mtp.tm, mct, finals, mtp.round+1)
return true
}), nil, time.Second*7, 1)
} else {
mtp.rank = index
pri := &PerRankInfo{
Name: mtp.p.Name,
SnId: mtp.p.SnId,
RankId: mtp.rank,
Grade: mtp.grade,
}
this.finalPerRank[sortId] = append(this.finalPerRank[sortId], pri)
this.sendPromotionInfo(mtp, sortId, TaoTai, true, false) //淘汰
}
}
} else {
// 比赛结束
// 修改陪真人玩的机器人积分
robotGrades := mtp.tm.robotGrades[int(mtp.round-1)]
if matchRobotGrades != nil {
logger.Logger.Trace("matchRobotGrades: ", matchRobotGrades)
for snid, grade := range matchRobotGrades {
logger.Logger.Trace("Snid: ", snid, " grade: ", grade)
}
for _, gradeInfo := range robotGrades {
if grade, ok := matchRobotGrades[gradeInfo.copySnid]; ok {
gradeInfo.grade = grade
}
}
}
// 记录真人积分
for _, gradeinfo := range robotGrades {
if gradeinfo.copySnid == 0 {
gradeinfo.grade = mtp.grade
break
}
}
sort.Slice(robotGrades, func(i, j int) bool {
return robotGrades[i].grade > robotGrades[j].grade
})
logger.Logger.Trace("robotGrades: ")
for _, info := range robotGrades {
logger.Logger.Trace("Snid: ", info.copySnid, " grade: ", info.grade, " copyLv: ", info.copyLv, " copyRoleId: ", info.copyRoleId)
}
// 获取真人名次
index := int32(0) //晋级淘汰
for i, gradeinfo := range robotGrades {
if mtp.grade >= gradeinfo.grade {
index = int32(i) + 1
break
}
}
if index == 0 {
index = gmd.MatchPromotion[mtp.round-1] //最后一名
}
mtp.rank = index
if this.finalPerRank[sortId] == nil {
this.finalPerRank[sortId] = []*PerRankInfo{}
}
pri := &PerRankInfo{
Name: mtp.p.Name,
SnId: mtp.p.SnId,
RankId: mtp.rank,
Grade: mtp.grade,
}
this.finalPerRank[sortId] = append(this.finalPerRank[sortId], pri) //把决赛的玩家记录在排行榜
outCode := TaoTai
if mtp.rank == 1 {
outCode = JinJi
}
this.sendPromotionInfo(mtp, sortId, outCode, true, true) //晋级
logger.Logger.Trace("比赛结束!!! ")
// 比赛结束
this.StopMatch(mtp.tm.TMId, sortId)
}
}
}
}
// 下一轮是否开始
func (this *Tournament) NextRoundStart(sortId int32, mtp *PlayerMatchContext) {
logger.Logger.Tracef("================NextRoundStart==========当前第 %v 轮============", mtp.round)
if _, ok := this.copyPlayers[sortId]; ok {
if mcs, ok1 := this.copyPlayers[sortId][mtp.round]; ok1 {
gmd := mtp.tm.gmd
//需要晋级的人数
promotionNum1 := gmd.MatchPromotion[mtp.round-1]
promotionNum := gmd.MatchPromotion[mtp.round]
//通知晋级信息0.晋级等待匹配 1.失败退出 2.等待判断是否晋级
pack := &tournament.SCPromotionInfo{}
if promotionNum != 1 {
n := int32(len(mcs))
//非决赛淘汰后开始配桌
logger.Logger.Trace("非决赛开始淘汰晋级")
outNum := promotionNum1 - promotionNum
//已经晋级的人数减去一桌之后 剩余人数还能够满足本轮淘汰
logger.Logger.Trace("n: ", n, " outNum: ", outNum)
if n-4 >= outNum {
//提前晋级的开始凑桌
MatchContextSlice(mcs).Sort(false)
//挑选出晋级的玩家
meIn := false //自己晋级
for k, v := range mcs {
if mtp.p.SnId == v.p.SnId {
meIn = true
}
logger.Logger.Trace("排序之后=========== ", k, v.p.SnId, v.round, v.seq, v.grade)
}
mct := []*PlayerMatchContext{}
finals := false
for i := 0; i < len(mcs)-int(outNum); i++ {
var mc PlayerMatchContext
mc = *mcs[i]
this.sendPromotionInfo(mcs[i], sortId, JinJi, false, false) //晋级
mc.rank = mcs[i].rank
mct = append(mct, &mc)
logger.Logger.Trace("======凑桌==========mc=================", mc)
if !finals && mc.round == int32(len(gmd.MatchPromotion)-2) {
finals = true
}
}
mcs = mcs[len(mct):]
this.copyPlayers[sortId][mtp.round] = this.copyPlayers[sortId][mtp.round][len(mct):]
willOut := false
if promotionNum1 == this.roundOverPlayerNum[sortId][mtp.round-1] {
//最后一个人打完了,确定要淘汰的人
willOut = true
} else {
if !meIn { //自己暂时没晋级
this.sendPromotionInfo(mtp, sortId, DaiDing, false, false) //待定
}
}
if this.finalPerRank[sortId] == nil {
this.finalPerRank[sortId] = []*PerRankInfo{}
}
isOver := false
for k, v := range this.copyPlayers[sortId][mtp.round] {
logger.Logger.Trace("凑桌之后剩余===2======== ", k, v.p.SnId, v.round, v.seq, v.grade)
if willOut {
this.sendPromotionInfo(v, sortId, TaoTai, true, false) //淘汰
//把淘汰的玩家记录在排行榜
pri := &PerRankInfo{
Name: v.p.Name,
SnId: v.p.SnId,
RankId: pack.RankId,
Grade: v.grade,
}
this.finalPerRank[sortId] = append(this.finalPerRank[sortId], pri)
//真人被淘汰,如果剩下的都是机器人,比赛解散
if !v.p.IsRob {
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(mtp.tm.TMId, sortId)
}
}
}
}
}
if !isOver {
timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
MatchSceneMgrSingleton.NewRoundStart(mtp.tm, mct, finals, mtp.round+1)
return true
}), nil, time.Second*7, 1)
}
} else {
this.sendPromotionInfo(mtp, sortId, DaiDing, false, false) //待定
}
} else {
if len(mcs) == 4 {
MatchContextSlice(mcs).Sort(true)
if this.finalPerRank[sortId] == nil {
this.finalPerRank[sortId] = []*PerRankInfo{}
}
for _, mc := range mcs {
pri := &PerRankInfo{
Name: mc.p.Name,
SnId: mc.p.SnId,
RankId: mc.rank,
Grade: mc.grade,
}
this.finalPerRank[sortId] = append(this.finalPerRank[sortId], pri) //把决赛的玩家记录在排行榜
outCode := TaoTai
if mc.rank == 1 {
outCode = JinJi
}
this.sendPromotionInfo(mc, sortId, outCode, true, true) //晋级
}
logger.Logger.Trace("比赛结束!!! ")
// 比赛结束
this.StopMatch(mtp.tm.TMId, sortId)
}
}
}
}
}
const (
JinJi = 0 // 晋级
TaoTai = 1 // 淘汰
DaiDing = 2 // 待定
)
// 发送晋级信息
// outCode 0晋级 1淘汰 2待定
// isOver 玩家比赛结束
// isFinals 比赛结束
func (this *Tournament) sendPromotionInfo(mc *PlayerMatchContext, sortId int32, outCode int, isOver, isFinals bool) {
if mc == nil {
return
}
rankId := mc.rank
if mc.tm.tmpUseRobot == MatchNotUserRobot { // 不使用机器人
rankId = this.getRank(sortId, mc.round, mc.p.SnId, isFinals)
mc.rank = rankId
}
//通知晋级信息0.晋级等待匹配 1.失败退出 2.等待判断是否晋级
pack := &tournament.SCPromotionInfo{}
pack.RetCode = int32(outCode)
pack.Round = mc.round
pack.RankId = rankId
pack.RoundCoin = 100 //暂时用不到先写死
pack.Record = mc.record
if mc.tm != nil {
pack.MatchId = mc.tm.TMId
}
if mc.tm != nil && mc.tm.gmd != nil {
pack.MatchPromotion = mc.tm.gmd.GetMatchPromotion()
pack.MatchName = mc.tm.gmd.GetMatchName()
if !mc.p.IsRob && isOver { //真人发奖
if mc.tm.gmd.Award != nil {
for _, award := range mc.tm.gmd.Award {
if rankId >= award.UpLimit && rankId <= award.DownLimit { //上下限是反的,我也是醉了
rankAward := &tournament.RankAward{
Coin: proto.Int64(award.Coin),
Diamond: proto.Int64(award.Diamond),
}
if award.ItemId != nil {
for _, info := range award.ItemId {
item := &tournament.ItemInfo{
ItemId: proto.Int32(info.ItemId),
ItemNum: proto.Int32(int32(info.ItemNum)),
Name: proto.String(info.Name),
}
rankAward.ItemInfo = append(rankAward.ItemInfo, item)
}
}
// test
//rankAward.ItemInfo = append(rankAward.ItemInfo, &tournament.ItemInfo{
// ItemId: 30003,
// ItemNum: 1,
// Name: "1元话费兑换码",
//})
// test
pack.RankAward = rankAward
}
}
}
}
}
sendFunc := func() {
outStr := "晋级"
switch outCode {
case 1:
outStr = "淘汰"
case 2:
outStr = "待定"
}
proto.SetDefaults(pack)
logger.Logger.Trace("sendPromotionInfo: ", outStr, " snid: ", mc.p.SnId, " pack: ", pack)
ok := mc.p.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCPromotionInfo), pack)
if ok && !mc.p.IsRob && isOver {
if pack.RankAward != nil {
if pack.RankAward.Coin != 0 { //金币
mc.p.AddCoin(pack.RankAward.Coin, 0, common.GainWay_MatchSystemSupply, "system", mc.tm.gmd.MatchName+"排名奖励")
}
if pack.RankAward.Diamond != 0 { //钻石
mc.p.AddDiamond(pack.RankAward.Diamond, 0, common.GainWay_MatchSystemSupply, "system", mc.tm.gmd.MatchName+"排名奖励")
}
if pack.RankAward.ItemInfo != nil {
for _, info := range pack.RankAward.ItemInfo {
if info.ItemNum <= 0 {
continue
}
item := &Item{
ItemId: info.ItemId,
ItemNum: int64(info.ItemNum),
}
BagMgrSingleton.AddJybBagInfo(mc.p, []*Item{item}, 0, common.GainWay_MatchSystemSupply, "system", mc.tm.gmd.MatchName+"排名奖励")
data := srvdata.PBDB_GameItemMgr.GetData(info.ItemId)
if data != nil {
// 背包变更记录
BagMgrSingleton.RecordItemLog(mc.p.Platform, mc.p.SnId, ItemObtain, item.ItemId, data.Name, item.ItemNum, mc.tm.gmd.MatchName+"排名奖励")
}
}
}
}
}
if isOver && mc.tm != nil { // 自己比赛结束
if !mc.p.IsRob {
this.CheckAddMatchSeasonLv(mc)
}
delete(this.players[sortId], mc.p.SnId)
}
}
// 获取兑换码奖品
var has bool
wg := new(sync.WaitGroup)
if pack.GetRankAward() != nil {
for _, v := range pack.GetRankAward().GetItemInfo() {
data := srvdata.PBDB_GameItemMgr.GetData(v.ItemId)
if data != nil && data.GetType() == common.ItemTypePhoneCode {
has = true
item := v // 并发需要复制
wg.Add(1)
// 兑换码奖品
var err error
var newMsg *model.Message
res := &webapi_proto.SAGetMatchAwardCode{}
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
// 获取兑换码
pack := &webapi_proto.ASGetMatchAwardCode{
Platform: mc.p.Platform,
Snid: mc.p.SnId,
ItemID: data.GetId(),
Money: data.GetNum(),
Tel: mc.p.Tel,
}
logger.Logger.Trace("GetMatchAwardCode ", pack)
var buff []byte
buff, err = webapi.APIGetMatchAwardCode(common.GetAppId(), pack)
if err != nil {
return err
}
if err = proto.Unmarshal(buff, res); err != nil {
return err
}
if res.GetCode() == "" || res.GetTag() != webapi_proto.TagCode_SUCCESS {
return nil
}
var params []string
for range []string{"zh", "vi", "en", "kh"} {
params = append(params, res.GetMoney(), res.GetCode()) // 金额,兑换码
}
// 发送邮件
title := i18n.Tr("languages", "MatchAwardTitle")
content := i18n.Tr("languages", "MatchAward", params)
newMsg = model.NewMessage("", 0, "", mc.p.SnId, model.MSGTYPE_RANK_REWARD,
title, content, 0, 0, model.MSGSTATE_UNREAD, time.Now().Unix(), 0, "", nil, mc.p.Platform, model.HallTienlen)
err := model.InsertMessage(mc.p.Platform, newMsg)
if err != nil {
logger.Logger.Errorf("发送邮件失败 snid:%v itemID:%v err:%v", mc.p.SnId, data.Id, err)
return err
}
return nil
}), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) {
defer wg.Done()
if err != nil || res.GetCode() == "" || res.GetTag() != webapi_proto.TagCode_SUCCESS {
logger.Logger.Errorf("获取兑换码失败 snid:%v itemID:%v res:%v err:%v", mc.p.SnId, data.Id, res, err)
return
}
item.Code = res.GetCode()
item.Msg = res.GetMoney()
p := PlayerMgrSington.GetPlayerBySnId(mc.p.SnId)
if p != nil {
p.AddMessage(newMsg)
}
}), fmt.Sprintf("RankAward%d", mc.p.SnId)).Start()
}
}
}
if !has {
sendFunc()
return
}
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
wg.Wait()
return nil
}), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) {
sendFunc()
})).Start()
}
// 更新段位
func (this *Tournament) CheckAddMatchSeasonLv(mc *PlayerMatchContext) {
if mc == nil {
return
}
platform := mc.p.Platform
if platform == DefaultPlatform {
return
}
rank := mc.rank
maxPlayerNum := mc.tm.gmd.MatchNumebr
upLine := maxPlayerNum * 33 / 100
downLine := maxPlayerNum * 67 / 100
snid := mc.p.SnId
ms := MatchSeasonMgrSington.GetMatchSeason(mc.p.SnId)
msid := MatchSeasonMgrSington.GetMatchSeasonId(platform)
if msid == nil {
MatchSeasonMgrSington.UpdateMatchSeasonId(platform)
}
if ms == nil {
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
ret, err := model.QueryMatchSeasonBySnid(platform, snid)
if err != nil {
return nil
}
return ret
}), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) {
var ret *model.MatchSeason
dirty := false
seasonId := int32(1)
if msid != nil {
seasonId = msid.SeasonId
}
if data == nil || data.(*model.MatchSeason) == nil {
player := PlayerMgrSington.GetPlayerBySnId(snid)
if player != nil {
ret = model.NewMatchSeason(player.Platform, snid, player.Name, seasonId, 1)
dirty = true
} else {
logger.Logger.Error("CSTMSeasonInfoHandler error: player == nil or msi == nil", snid)
}
} else {
ret = data.(*model.MatchSeason)
if ret.SeasonId < seasonId { //不同赛季段位继承
num := seasonId - ret.SeasonId
finalLv := ret.Lv
for i := 0; i < int(num); i++ { //继承几次
if i == int(num)-1 { //上个赛季
ret.LastLv = finalLv
}
finalLv = MatchSeasonMgrSington.MatchSeasonInherit(finalLv)
}
ret.Lv = finalLv
ret.SeasonId = seasonId
ret.IsAward = false
dirty = true
}
}
ms = MatchSeasonMgrSington.exchangeModel2Cache(ret)
ms.dirty = dirty
MatchSeasonMgrSington.SetMatchSeason(ms)
if rank <= upLine { //加分
MatchSeasonMgrSington.UpdateMatchSeasonLv(mc.p, 1, dirty)
} else if rank >= downLine && ms.Lv > 75 { //白银以上才触发减分
MatchSeasonMgrSington.UpdateMatchSeasonLv(mc.p, -1, dirty)
} else {
MatchSeasonMgrSington.UpdateMatchSeasonLv(mc.p, 0, dirty)
}
})).StartByFixExecutor("SnId:" + strconv.Itoa(int(snid)))
} else {
dirty := false
if ms.SeasonId < msid.SeasonId { //不同赛季段位继承
num := msid.SeasonId - ms.SeasonId
finalLv := ms.Lv
for i := 0; i < int(num); i++ { //继承几次
if i == int(num)-1 { //上个赛季
ms.LastLv = finalLv
}
finalLv = MatchSeasonMgrSington.MatchSeasonInherit(finalLv)
}
ms.Lv = finalLv
ms.SeasonId = msid.SeasonId
ms.IsAward = false
ms.UpdateTs = time.Now().Unix()
ms.dirty = true
dirty = true
MatchSeasonMgrSington.SetMatchSeason(ms)
}
if rank <= upLine { //加分
MatchSeasonMgrSington.UpdateMatchSeasonLv(mc.p, 1, dirty)
} else if rank >= downLine && ms.Lv > 75 { //白银以上才触发减分
MatchSeasonMgrSington.UpdateMatchSeasonLv(mc.p, -1, dirty)
} else {
MatchSeasonMgrSington.UpdateMatchSeasonLv(mc.p, 0, dirty)
}
}
}
// 比赛结束
func (this *Tournament) StopMatch(tmId, sortId int32) {
//房间清理
if this.matches[tmId] != nil && this.matches[tmId][sortId] != nil {
this.matches[tmId][sortId].Stop()
delete(this.matches[tmId], sortId)
}
//数据清理
delete(this.players, sortId)
delete(this.copyPlayers, sortId)
delete(this.rankPlayers, sortId)
delete(this.roundOverPlayerNum, sortId)
delete(this.finalPerRank, sortId)
}
func (this *Tournament) getRank(sortId, round, snid int32, isFinals bool) int32 {
if _, ok := this.rankPlayers[sortId]; ok {
if rps, ok1 := this.rankPlayers[sortId][round]; ok1 {
MatchContextSlice(rps).Sort(isFinals)
for _, rp := range rps {
if rp.p.SnId == snid {
return rp.rank
}
}
}
}
return 0
}
func (this *Tournament) isOut(sortId, snid int32) bool {
out := false
if this.finalPerRank[sortId] != nil {
for _, info := range this.finalPerRank[sortId] {
if info.SnId == snid {
out = true
}
}
}
return out
}
func (this *Tournament) GetTm(sortId int32) *TmMatch {
if this.matches != nil {
for _, sortTms := range this.matches {
for id, match := range sortTms {
if id == sortId {
return match
}
}
}
}
return nil
}
// 玩家比赛结束 更新积分
func (this *Tournament) UpdateMatchInfo(p *Player, sortId, grade, isWin int32, matchRobotGrades map[int32]int32) {
logger.Logger.Trace("=========== UpdateMatchInfo ==============")
logger.Logger.Tracef("UpdateMatchInfo: sortId:%v, grade:%v, isWin: %v, matchRobotGrades:%v", sortId, grade, isWin, matchRobotGrades)
if _, ok := this.players[sortId]; !ok {
this.players[sortId] = make(map[int32]*PlayerMatchContext)
}
if mtp, ok := this.players[sortId][p.SnId]; ok {
mtp.grade = grade
if this.roundOverPlayerNum[sortId] == nil {
this.roundOverPlayerNum[sortId] = make(map[int32]int32)
}
this.roundOverPlayerNum[sortId][mtp.round]++
if mtp.record == nil {
mtp.record = make(map[int32]int32)
}
mtp.record[isWin]++
//轮数增加
mtp.round++
mtp.gaming = false
if this.copyPlayers[sortId] == nil {
this.copyPlayers[sortId] = make(map[int32][]*PlayerMatchContext)
}
var mc PlayerMatchContext
mc = *mtp
this.copyPlayers[sortId][mtp.round] = append(this.copyPlayers[sortId][mtp.round], &mc)
if this.rankPlayers[sortId] == nil {
this.rankPlayers[sortId] = make(map[int32][]*PlayerMatchContext)
}
this.rankPlayers[sortId][mtp.round] = append(this.rankPlayers[sortId][mtp.round], &mc)
logger.Logger.Tracef("========snid(%v) grade(%v) ============", p.SnId, grade)
if mtp.tm.tmpUseRobot == MatchUseRobot { // 使用机器人
this.NextRoundStartSingle(sortId, mtp, matchRobotGrades)
} else {
this.NextRoundStart(sortId, mtp)
}
}
}
func (this *Tournament) CreatePlayerMatchContext(p *Player, m *TmMatch, seq int) *PlayerMatchContext {
ms := MatchSeasonMgrSington.GetMatchSeason(p.SnId)
var lv int32
if ms != nil {
lv = ms.Lv
}
roleId := int32(2000001)
if p.Roles != nil {
roleId = p.Roles.ModId
}
mc := NewMatchContext(p, m, 1000, p.SnId, lv, roleId, seq)
if mc != nil {
if this.players[m.SortId] == nil {
this.players[m.SortId] = make(map[int32]*PlayerMatchContext)
}
this.players[m.SortId][p.SnId] = mc
p.matchCtx = mc
return mc
}
return nil
}
// GetSCTMInfosPack 发送比赛配置数据
func (this *Tournament) GetSCTMInfosPack(platform, channelName string) *tournament.SCTMInfos {
pack := &tournament.SCTMInfos{}
matchInfo := this.GetAllMatchInfo(platform)
if matchInfo != nil {
for id, info := range matchInfo {
if info.MatchSwitch == 1 && !this.IsOutTime(info) && common.InMatchChannel(info.OnChannelName, channelName) {
tMInfo := &tournament.TMInfo{
Id: proto.Int32(id),
GameFreeId: info.GameFreeId,
MatchType: info.MatchType,
MatchName: info.MatchName,
MatchNumebr: info.MatchNumebr,
MatchSwitch: info.MatchSwitch,
SignupCostCoin: info.SignupCostCoin,
SignupCostDiamond: info.SignupCostDiamond,
MatchTimeType: info.MatchTimeType,
MatchTimeStartHMS: info.MatchTimeStartHMS,
MatchTimeEndHMS: info.MatchTimeEndHMS,
TitleURL: info.TitleURL,
AwardShow: info.AwardShow,
Rule: info.Rule,
SortId: info.SortId,
OnChannelName: info.OnChannelName,
}
if info.MatchTimeWeek != nil && len(info.MatchTimeWeek) > 0 {
for _, week := range info.MatchTimeWeek {
tMInfo.MatchTimeWeek = append(tMInfo.MatchTimeWeek, week)
}
}
if info.MatchTimeStamp != nil && len(info.MatchTimeStamp) > 0 {
for _, stamp := range info.MatchTimeStamp {
tMInfo.MatchTimeStamp = append(tMInfo.MatchTimeStamp, stamp)
}
}
if info.MatchPromotion != nil {
for _, mp := range info.MatchPromotion {
tMInfo.MatchPromotion = append(tMInfo.MatchPromotion, mp)
}
}
if info.Award != nil {
for _, award := range info.Award {
miAward := &tournament.MatchInfoAward{
Coin: award.Coin,
Diamond: award.Diamond,
UpLimit: award.UpLimit,
DownLimit: award.DownLimit,
}
if award.ItemId != nil {
for _, itemInfo := range award.ItemId {
a := &tournament.ItemInfo{
ItemId: itemInfo.ItemId,
ItemNum: int32(itemInfo.ItemNum),
Name: itemInfo.Name,
}
miAward.ItemInfo = append(miAward.ItemInfo, a)
}
}
tMInfo.Award = append(tMInfo.Award, miAward)
}
}
if info.SignupCostItem != nil && info.SignupCostItem.ItemNum > 0 {
signupCost := &tournament.ItemInfo{
ItemId: info.SignupCostItem.ItemId,
ItemNum: int32(info.SignupCostItem.ItemNum),
Name: info.SignupCostItem.Name,
}
tMInfo.SignupCostItem = signupCost
}
pack.TMInfo = append(pack.TMInfo, tMInfo)
}
}
}
return pack
}
func (this *Tournament) ModuleName() string {
return "Tournament"
}
// 初始化
func (this *Tournament) Init() {
logger.Logger.Trace("(this *Tournament) Init()")
}
func (this *Tournament) Update() {
// 使用机器人的情况
for snid, info := range this.singleSignupPlayers {
if this.playerSignUpTime[snid] != 0 {
matchInfo := this.GetMatchInfo(info.Platform, info.Tmid)
if matchInfo.MatchSwitch == MatchSwitchStart && !this.IsOutTime(matchInfo) && this.IsUseRobot(info.Platform, info.Tmid) {
needTime := this.playerWaitStart[snid]
if time.Now().Unix()-this.playerSignUpTime[snid] > needTime {
delete(this.singleSignupPlayers, snid)
delete(this.playerSignUpTime, snid)
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() {
}
func init() {
module.RegisteModule(TournamentMgr, time.Second, 0)
}