package roomrank import ( "apigame/configs/confroomrank" "apigame/service-common/svcommon" "apigame/service-common/svmysql" "apigame/util/util-lx/lxalilog" "apigame/util/util-lx/lxtime" "math" "math/rand" "sort" "time" ) func tryInitRoom(gameId string, room *Room) { svmysql.InitTable(room, gameId, false) } // SaveRoom 存储数据 func SaveRoom(gameId string, room *Room) { tryInitRoom(gameId, room) room.UpdateTime = lxtime.NowUninx() room.Encode() err := svmysql.Save(room, gameId) if err != nil { lxalilog.Errors(err, "roomrank.SaveRoom error", gameId, room.Id, room.ActivityId) return } } // LoadRoom 获取数据 func LoadRoom(gameId string, topType int, activityId int64, roomUid int64) (room *Room, has bool) { room = &Room{Id: roomUid, TopType: topType, ActivityId: activityId} if roomUid == 0 { has = false return } tryInitRoom(gameId, room) var err error has, err = svmysql.First(room, gameId) if err != nil { lxalilog.Errors(err, "roomrank.LoadRoom error", gameId, roomUid, activityId) return } room.Decode() return } func CreateRoom(gameId string, topType int, config *confroomrank.ActivityConfig, roomConfigId int, activityTime int64) (room *Room, has bool) { room = new(Room) room.TopType = topType room.ActivityId = config.Id room.ConfigId = roomConfigId room.Closed = false room.HasSettle = false room.CreateTime = lxtime.NowUninx() room.ActivityTime = activityTime details := new(RoomDetails) details.Players = make([]*RoomPlayer, 0) details.IndexNames = make([]int, 0) details.IndexAvatars = make([]int, 0) room.Details = details err := svmysql.Save(room, gameId) if err != nil { has = false } else { has = true } return } // FindRoom 查找 func FindRoom(gameId string, topType int, activityId int64, roomConfigId int, activityTime int64) (rooms []*Room, has bool) { roomDemo := &Room{TopType: topType, ActivityId: activityId, ActivityTime: activityTime} tryInitRoom(gameId, roomDemo) info := roomDemo.MysqlInfo(gameId) info.DbMysql = info.DbMysql.Where("config_id = ? AND activity_time = ? AND closed = false", roomConfigId, activityTime) has, _ = svmysql.Find(&rooms, info) for _, room := range rooms { room.Decode() } return } // TryGetRoom 尝试获取房间 func TryGetRoom(gameId string, topType int, player *Player, config *confroomrank.ActivityConfig) (room *Room, hasRoom bool) { hasRoom = false // 查找玩家所在的房间 room, hasRoom = LoadRoom(gameId, topType, config.Id, player.RoomUid) if hasRoom { if confRoom, hasConfRoom := config.Room[room.ConfigId]; hasConfRoom { TryCloseRoom(gameId, room, config, confRoom) } return } return } // TryFindRoom 尝试获取房间 func TryFindRoom(gameId string, topType int, player *Player, config *confroomrank.ActivityConfig, playerLevel int, activityTime int64) (room *Room, hasRoom bool, firstJoin bool) { // 根据等级和分数范围查找合适的房间配置ID roomConfigId := 0 roomConfig := confroomrank.RoomConfig{} for _, i2 := range config.Room { if playerLevel >= i2.Levels[0] && playerLevel <= i2.Levels[1] && player.UserClass == i2.UserClass { roomConfigId = i2.Id roomConfig = i2 } } if roomConfigId == 0 { lxalilog.Errors("TryGetRoom find roomConfigId error", playerLevel, player.UserClass) return } // 数据库查找合适条件的房间列表 rooms, has := FindRoom(gameId, topType, config.Id, roomConfigId, activityTime) if has { for i := 0; i < len(rooms); i++ { roomTemp := rooms[i] TryCloseRoom(gameId, roomTemp, config, roomConfig) if roomTemp.Closed { continue } // 可容纳玩家类型数量 canJoinCount := GetTypeCanJoinCount(roomTemp, roomConfig, player.UserType) if canJoinCount > 0 { room = roomTemp hasRoom = true break } } } if hasRoom { // 如果有 就加入 PlayerJoinRoom(room, player) firstJoin = true } else { // 如果没有合适条件的房间 创建一个 roomCreate, hasCreate := CreateRoom(gameId, topType, config, roomConfigId, activityTime) if hasCreate { room = roomCreate room.Details.IndexNames = svcommon.GetIndexNames(gameId, roomConfig.TotalPlayer) room.Details.IndexAvatars = svcommon.GetIndexAvatars(gameId, roomConfig.TotalPlayer) // 配置原生机器人 JoinInitRobot(gameId, room, roomConfig) PlayerJoinRoom(room, player) firstJoin = true hasRoom = hasCreate } } return } func PlayerJoinRoom(room *Room, player *Player) { roomPlayer := NewRoomPlayer(player) room.Details.Players = append(room.Details.Players, roomPlayer) player.RoomUid = room.Id } // TryCloseRoom 尝试关闭房间 func TryCloseRoom(gameId string, room *Room, config *confroomrank.ActivityConfig, roomConfig confroomrank.RoomConfig) { if room.Closed { return } secNow := lxtime.NowUninx() if secNow > room.CreateTime+RoomCloseSecond { room.Closed = true // 根据缺口自动填充机器人 for i := 0; i < len(roomConfig.PlayerTypeCount); i++ { pair := roomConfig.PlayerTypeCount[i] userType := pair[0] canJoinCount := pair[1] - room.GetPlayerTypeCount(userType) robotConfigId := roomConfig.AutoRobot[i] for i := 0; i < canJoinCount; i++ { roomPlayer := NewRoomRobot(gameId, room, robotConfigId, userType) room.Details.Players = append(room.Details.Players, roomPlayer) } } // 如果总数还不足 用默认的第一类来填充 { canJoinCount := roomConfig.TotalPlayer - len(room.Details.Players) if canJoinCount > 0 && len(roomConfig.AutoRobot) > 0 { userType := roomConfig.PlayerTypeCount[0][0] robotConfigId := roomConfig.AutoRobot[0] for i := 0; i < canJoinCount; i++ { roomPlayer := NewRoomRobot(gameId, room, robotConfigId, userType) room.Details.Players = append(room.Details.Players, roomPlayer) } } } // 填充完之后要排序计算 TryResetRobot(room, config, true) TryReSort(room, config) SaveRoom(gameId, room) } } // GetTypeCanJoinCount 房间获取某种类型玩家可加入数量 func GetTypeCanJoinCount(room *Room, roomConfig confroomrank.RoomConfig, userType int) int { maxCount := 0 for i := 0; i < len(roomConfig.PlayerTypeCount); i++ { pair := roomConfig.PlayerTypeCount[i] if pair[0] == userType { maxCount = pair[1] break } } return maxCount - room.GetPlayerTypeCount(userType) } // JoinInitRobot 配置原生机器人 func JoinInitRobot(gameId string, 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(gameId, room, robotConfigId, -1) room.Details.Players = append(room.Details.Players, roomPlayer) } } } // TrySettleRoom 尝试结算房间 func TrySettleRoom(gameId string, room *Room, config *confroomrank.ActivityConfig) { // 已经结算过的不结算 if room.HasSettle { return } // 活动切换或者时间到 触发结算 needSettle := false if room.ActivityId != config.Id { needSettle = true } else { dateEnd := GetTimeEnd(room.ActivityTime, config.ReleaseTime) dtNow := lxtime.NowUninx() if dtNow >= dateEnd.Unix() { needSettle = true } } if !needSettle { return } percent := float64(0) dateEnd := GetTimeEnd(room.ActivityTime, config.ReleaseTime) secTotal := 24 * 60 * 60 dtEnd := dateEnd.Unix() if dtEnd > config.EndTime { dtEnd = config.EndTime } dtCreate := room.CreateTime if dtEnd <= dtCreate { percent = 0 } else { percent = float64(dtEnd-dtCreate) * 100 / float64(secTotal) // 如果 结算时间-创建时间 小于8小时 根据这个房间存在时间进行衰减 if dtEnd-dtCreate < int64(time.Hour*8) { percent = percent * float64(dtEnd-dtCreate) / float64(time.Hour*8) } } // 机器人最终算分 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, percent) if roomPlayer.Score < int64(confRobot.MinScore) { roomPlayer.Score = int64(confRobot.MinScore) } } } sort.Sort(room.Details) room.HasSettle = true SaveRoom(gameId, room) } // TryResetRobot 尝试改变机器人分数并重新排序 func TryResetRobot(room *Room, config *confroomrank.ActivityConfig, force bool) { secNow := lxtime.NowUninx() if !force && secNow < room.ResetRobotTime+RoomResetRobotSecond { return } room.ResetRobotTime = secNow percent := float64(0) dateEnd := GetTimeEnd(room.ActivityTime, config.ReleaseTime) secTotal := 24 * 60 * 60 dtEnd := dateEnd.Unix() if dtEnd > config.EndTime { dtEnd = config.EndTime } dtCreate := room.CreateTime if dtEnd <= dtCreate { percent = 0 } else if secNow <= dtCreate { percent = 0 } else if secNow >= dtEnd { percent = 100 } else { percent = float64(secNow-dtCreate) * 100 / float64(secTotal) } // 机器人即时算分 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, percent) } } } // TryReSort 尝试重新排序 func TryReSort(room *Room, config *confroomrank.ActivityConfig) { TryResetRobot(room, config, false) sort.Sort(room.Details) } // GetRobotScoreCurrent 从机器人配置里得到实时得分 func GetRobotScoreCurrent(config *confroomrank.ActivityConfig, confRobot *confroomrank.RobotConfig, percent float64) int64 { score := (float64(confRobot.TotalScore-int(config.OpenScore)) * float64(100-confRobot.Range+rand.Intn(confRobot.Range*2)) / 100) * percent / 100 result := config.OpenScore + int64(math.Ceil(score)) if result < config.OpenScore { result = config.OpenScore } return result }