diff --git a/service/roomrank/consts.go b/service/roomrank/consts.go index 0112881..8724ebd 100644 --- a/service/roomrank/consts.go +++ b/service/roomrank/consts.go @@ -4,5 +4,6 @@ const ( UserClassMin = 1 // 最小评级 UserClassMax = 5 // 最大评级 - RoomCloseSecond = 180 // 房间关闭时间 + RoomCloseSecond = 180 // 房间关闭时间 + RoomResetRobotSecond = 300 // 改变机器人分数并重新排序的间隔时间 ) diff --git a/service/roomrank/dto-room.go b/service/roomrank/dto-room.go index ce05049..d40fce7 100644 --- a/service/roomrank/dto-room.go +++ b/service/roomrank/dto-room.go @@ -19,7 +19,9 @@ type Room struct { Details *RoomDetails `gorm:"-"` // 详情 DetailsText string `gorm:"comment:详情封装"` - Closed bool `gorm:"comment:房间已关闭"` + Closed bool `gorm:"comment:房间已关闭"` + ResetRobotTime int64 `gorm:"comment:上次刷新机器人时间"` + HasSettle bool `gorm:"comment:是否结算"` CreateTime int64 `gorm:"comment:创建时间戳"` UpdateTime int64 `gorm:"comment:修改时间戳"` @@ -38,7 +40,7 @@ type RoomPlayer struct { Uid int64 // 玩家唯一ID Score int64 // 玩家排行分数 JoinTime int64 // 加入时间 - UserType int // 用户类型 + UserType int // 用户类型 -1=原生配置机器人 RobotConfigId int // 0=玩家 } @@ -111,3 +113,30 @@ func (d *Room) GetPlayerTypeCount(userType int) int { return p.UserType == userType }) } + +/* 排名规则 降序 +- 如果是玩家之间的分数相同,则先达到该分数的玩家排名靠前 +- 如果是机器人之间的分数相同,则按照计算的处理先后顺序进行排序,或者随机排序,因为不重要 +- 如果是玩家和机器人之间的分数相同,则玩家排名永远高于机器人排名 +*/ + +func (d *RoomDetails) Len() int { + return len(d.Players) +} +func (d *RoomDetails) Less(i, j int) bool { + if d.Players[i].Score != d.Players[j].Score { + return d.Players[i].Score > d.Players[j].Score + } + // 如果是玩家和机器人之间的分数相同,则玩家排名永远高于机器人排名 + if d.Players[i].RobotConfigId != d.Players[j].RobotConfigId { + return d.Players[i].RobotConfigId < d.Players[j].RobotConfigId + } + // 如果是玩家之间的分数相同,则先达到该分数的玩家排名靠前 + if d.Players[i].RobotConfigId == 0 && d.Players[j].RobotConfigId == 0 { + return d.Players[i].JoinTime > d.Players[j].JoinTime + } + return d.Players[i].Score > d.Players[j].Score +} +func (d *RoomDetails) Swap(i, j int) { + d.Players[i], d.Players[j] = d.Players[j], d.Players[i] +} diff --git a/service/roomrank/handle.go b/service/roomrank/handle.go index 44208c7..3fb8d99 100644 --- a/service/roomrank/handle.go +++ b/service/roomrank/handle.go @@ -41,17 +41,21 @@ func HandleInfo(req *models.ReqRoomRankInfo) (code string, rsp models.RspRoomRan // 尝试判断结算 hasSettle := TrySettle(gameId, player, config) + if hasSettle { + SavePlayer(gameId, player) + rsp.RoomRankInfo = GetInfo(player, config) + return + } + // 尝试加入房间 room, hasRoom := TryGetRoom(gameId, player, config, playerLevel) - if hasSettle || hasRoom { - SavePlayer(gameId, player) - } if hasRoom { + TryReSort(room, config) + + SavePlayer(gameId, player) SaveRoom(gameId, room) } - rsp.RoomRankInfo = GetInfo(player, config) - return } diff --git a/service/roomrank/logic.go b/service/roomrank/logic.go index 9d73bde..cd51470 100644 --- a/service/roomrank/logic.go +++ b/service/roomrank/logic.go @@ -30,6 +30,7 @@ func TrySettle(gameId string, player *Player, config *confroomrank.ActivityConfi if !hasConfActivity { return } + TrySettleRoom(gameId, room, confActivity) // 设置玩家奖励等数据 hasChange = true player.SettleHas = true diff --git a/service/roomrank/room.go b/service/roomrank/room.go index b20bc04..b0015eb 100644 --- a/service/roomrank/room.go +++ b/service/roomrank/room.go @@ -5,6 +5,9 @@ import ( "apigame/service-common/svmysql" "apigame/util/util-lx/lxalilog" "apigame/util/util-lx/lxtime" + "math" + "math/rand/v2" + "sort" ) func tryInitTable(gameId string, room *Room) { @@ -50,6 +53,7 @@ func CreateRoom(gameId string, activityId int64, roomConfigId int) (room *Room, room.ActivityId = activityId room.ConfigId = roomConfigId room.Closed = false + room.HasSettle = false room.CreateTime = lxtime.NowUninx() details := new(RoomDetails) details.Players = make([]*RoomPlayer, 0) @@ -135,6 +139,10 @@ func TryGetRoom(gameId string, player *Player, config *confroomrank.ActivityConf roomCreate, hasCreate := CreateRoom(gameId, config.Id, roomConfigId) if hasCreate { room = roomCreate + + // 配置原生机器人 + JoinInitRobot(room, roomConfig) + PlayerJoinRoom(room, player) hasRoom = hasCreate } @@ -181,3 +189,96 @@ func GetTypeCanJoinCount(room *Room, roomConfig confroomrank.RoomConfig, userTyp } return maxCount - room.GetPlayerTypeCount(userType) } + +// JoinInitRobot 配置原生机器人 +func JoinInitRobot(room *Room, roomConfig confroomrank.RoomConfig) { + for i := 0; i < len(roomConfig.InitRobot); i++ { + pair := roomConfig.InitRobot[i] + robotConfigId := pair[0] + robotCount := pair[1] + for i := 0; i < robotCount; i++ { + roomPlayer := NewRoomRobot(robotConfigId, -1) + room.Details.Players = append(room.Details.Players, roomPlayer) + } + } +} + +// TrySettleRoom 尝试结算房间 +func TrySettleRoom(gameId string, room *Room, confActivity *confroomrank.ActivityConfig) { + if room.HasSettle { + return + } + // 机器人最终算分 + for i := 0; i < len(room.Details.Players); i++ { + roomPlayer := room.Details.Players[i] + if roomPlayer.RobotConfigId == 0 { + continue + } + confRobot, hasConfRobot := confActivity.Robot[roomPlayer.RobotConfigId] + if hasConfRobot { + roomPlayer.Score = GetRobotScoreMax(&confRobot) + } + } + + sort.Sort(room.Details) + room.HasSettle = true + SaveRoom(gameId, room) +} + +// TryResetRobot 尝试改变机器人分数并重新排序 +func TryResetRobot(room *Room, config *confroomrank.ActivityConfig) { + secNow := lxtime.NowUninx() + if secNow < room.ResetRobotTime+RoomResetRobotSecond { + return + } + // 机器人即时算分 + for i := 0; i < len(room.Details.Players); i++ { + roomPlayer := room.Details.Players[i] + if roomPlayer.RobotConfigId == 0 { + continue + } + confRobot, hasConfRobot := config.Robot[roomPlayer.RobotConfigId] + if hasConfRobot { + roomPlayer.Score = GetRobotScoreCurrent(config, &confRobot, secNow) + } + } +} + +// TryReSort 尝试重新排序 +func TryReSort(room *Room, config *confroomrank.ActivityConfig) { + TryResetRobot(room, config) + sort.Sort(room.Details) +} + +// GetRobotScoreCurrent 从机器人配置里得到实时得分 +func GetRobotScoreCurrent(config *confroomrank.ActivityConfig, confRobot *confroomrank.RobotConfig, secNow int64) int64 { + percent := float64(0) + if config.EndTime <= config.StartTime { + percent = 0 + } else if secNow <= config.StartTime { + percent = 0 + } else if secNow >= config.EndTime { + percent = 100 + } else { + percent = float64(secNow-config.StartTime) * 100 / float64(config.EndTime-config.StartTime) + } + + score := (float64(confRobot.TotalScore-confRobot.MinScore) * + float64(100-confRobot.TotalRate+rand.IntN(confRobot.TotalRate*2)) / 100) * percent / 100 + result := int64(confRobot.MinScore) + int64(math.Ceil(score)) + if result < int64(confRobot.MinScore) { + result = int64(confRobot.MinScore) + } + return result +} + +// GetRobotScoreMax 从机器人配置里得到最高分 +func GetRobotScoreMax(confRobot *confroomrank.RobotConfig) int64 { + score := float64(confRobot.TotalScore-confRobot.MinScore) * + float64(100-confRobot.TotalRate+rand.IntN(confRobot.TotalRate*2)) / float64(100) + result := int64(confRobot.MinScore) + int64(math.Ceil(score)) + if result < int64(confRobot.MinScore) { + result = int64(confRobot.MinScore) + } + return result +} -- libgit2 0.21.0