pet_home_server/src/server/game/champship_mgr.go
2026-04-19 00:02:03 -04:00

1073 lines
30 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 game
import (
"fmt"
"maps"
"math"
avatarCfg "server/conf/avatar"
champshipCfg "server/conf/champship"
faceCfg "server/conf/face"
randnameCfg "server/conf/randname"
"server/db"
"server/game/mod/activity"
"server/game/mod/friend"
"server/game/mod/msg"
GoUtil "server/game_util"
proto "server/msg"
"sort"
"sync"
"time"
"gitea.bywaystudios.com/pet_home/leaf/log"
)
const (
RANK_PLAYER_ROBOT = 2
)
type ChampshipMgr struct {
*ServerMod
}
type ChampshipData struct {
mu sync.RWMutex
AutoId int
RobotId int
Rank map[int][]*ChampshipRank // 锦标赛排行榜
PreRank map[int][]*ChampshipRank // 锦标赛排行榜 备份
Pool map[int]*GroupInfo // 锦标赛未分配玩家
GroupInfo map[int]int // 锦标赛分组信息
PreGroupInfo map[int]int // 锦标赛分组信息 备份
Robot map[int]*ChampshipRobot // 机器人
PreRobot map[int]*ChampshipRobot // 机器人 备份
ZeroTime int64
Version int
Aid int // 当前活动ID
}
type ChampshipRank struct {
Uid int
Score float64
Time int64
Type int
Rank int
}
type ChampshipRobot struct {
Max float64
Type int
Name string
Avatar int
Face int
Level int
GroupId int
Time int64
Score float64
PerScore float64
Playroom map[int]int
DressSet map[int]int
FurSet int
ActLog *friend.ActLogInfo
PetName string
}
type GroupInfo struct {
Uid int
Score float64
Time int64
N int
H int
}
type CRank struct {
Uid int
Score float64
N int
H int
}
func (c *ChampshipMgr) Init() {
c.key = CHAMPSHIP_MGR_KEY
c.data = &ChampshipData{
Rank: make(map[int][]*ChampshipRank, 0),
PreRank: make(map[int][]*ChampshipRank, 0),
Pool: make(map[int]*GroupInfo, 0),
GroupInfo: make(map[int]int),
PreGroupInfo: make(map[int]int),
Robot: make(map[int]*ChampshipRobot, 0),
PreRobot: make(map[int]*ChampshipRobot, 0),
}
// 注册处理函数
c.init()
c.version()
now := GoUtil.Now()
zeroTime := GoUtil.ZeroTimestamp()
if c.getData().ZeroTime != zeroTime {
c.ZeroUpdate()
} else {
c.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() {
c.ZeroUpdate()
})
}
remain := now - zeroTime
remain1 := 1800 - remain%1800
c.mDispatr.AfterFunc(time.Duration(remain1)*time.Second, func() { // 30分钟后重新分组
c.group()
})
c.mDispatr.AfterFunc(time.Duration(60)*time.Second, func() {
c.ai()
})
}
func (c *ChampshipMgr) version() {
if c.data.(*ChampshipData).Version == 0 {
c.data.(*ChampshipData).Version = 1
for _, v := range c.data.(*ChampshipData).Rank {
sortChampionshipRank(v)
for _, info := range v {
if info.Type != RANK_PLAYER_ROBOT {
c.SetRankCache(info.Uid)
}
}
}
for _, v := range c.data.(*ChampshipData).PreRank {
sortChampionshipRank(v)
for _, info := range v {
if info.Type != RANK_PLAYER_ROBOT {
c.SetRankCache(info.Uid)
}
}
}
}
}
func sortChampionshipRank(rankList []*ChampshipRank) {
rank := 1
lastRank := 1
lastScore := 0.0
for _, v := range rankList {
if v.Score == lastScore {
v.Rank = lastRank
} else {
v.Rank = rank
lastRank = rank
lastScore = v.Score
}
rank++
}
}
// 每天零点30分通知所有在线玩家领取奖励
func (c *ChampshipMgr) ZeroNotifyAll() (interface{}, error) {
NotifyAllPlayerMsg(&msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
HandleType: msg.HANDLE_MOD_PLAYER_MSG,
End: GoUtil.Now() + onehour,
})
c.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration()+1800)*time.Second, func() {
c.ZeroNotifyAll()
})
return nil, nil
}
func (c *ChampshipMgr) ZeroUpdate() (interface{}, error) {
log.Debug("ChampshipMgr ZeroUpdate")
data := c.getData()
data.mu.Lock()
activityCfg := G_GameLogicPtr.ActivityMgr.GetActivityListByType(activity.ACT_TYPE_CHAMPION)
// 如果活动ID没有变化说明没有新的活动不需要重置数据
if activityCfg.AId != 0 && activityCfg.AId == data.Aid {
log.Debug("championship zero update not init by aid %d", data.Aid)
data.mu.Unlock()
return nil, nil
}
log.Debug("championship zero update by aid %d", activityCfg.AId)
data.Aid = activityCfg.AId
data.ZeroTime = GoUtil.ZeroTimestamp()
// 深拷贝 map避免多个协程持有同一个 map 引用导致并发读写
oldRank := make(map[int][]*ChampshipRank, len(data.Rank))
maps.Copy(oldRank, data.Rank)
oldRobot := make(map[int]*ChampshipRobot, len(data.Robot))
for k, v := range data.Robot {
oldRobot[k] = v
}
oldGroupInfo := make(map[int]int, len(data.GroupInfo))
for k, v := range data.GroupInfo {
oldGroupInfo[k] = v
}
data.PreRank = oldRank
data.PreRobot = oldRobot
data.PreGroupInfo = oldGroupInfo
data.AutoId = 0
data.RobotId = 1
data.Robot = make(map[int]*ChampshipRobot, 0)
data.Rank = make(map[int][]*ChampshipRank, 0)
data.GroupInfo = make(map[int]int, 0)
c.update = true
// 0点更新排行榜缓存
for k := range data.PreGroupInfo {
c.SetRankCache(k)
}
data.mu.Unlock()
timeDuration := GoUtil.NextZeroTimestampDuration()
if timeDuration <= 0 {
log.Error("championship zero update error")
timeDuration = 24 * 3600
}
c.mDispatr.AfterFunc(time.Duration(timeDuration)*time.Second, func() {
c.ZeroUpdate()
})
c.mDispatr.AfterFunc(time.Duration(timeDuration+1800)*time.Second, func() {
c.ZeroNotifyAll()
})
// 在锁外通知玩家,避免在持有锁时调用外部函数
go c.NotifyPlayer()
return nil, nil
}
func (c *ChampshipMgr) NotifyPlayer() {
data := c.getData()
data.mu.RLock()
// 深拷贝需要通知的数据,避免在锁外访问 map
notifyList := make([]struct {
Uid int
Rank int
}, 0)
for _, v := range data.PreRank {
for i := 0; i < 3 && i < len(v); i++ {
if v[i].Type == RANK_PLAYER_ROBOT {
continue
}
notifyList = append(notifyList, struct {
Uid int
Rank int
}{Uid: v[i].Uid, Rank: i + 1})
}
}
data.mu.RUnlock()
// 在锁外通知,避免持锁时间过长
for _, item := range notifyList {
NotifyChampshipResult(item.Uid, item.Rank)
}
}
func (c *ChampshipMgr) ai() (interface{}, error) {
ChampshipData := c.getData()
ChampshipData.mu.Lock()
defer ChampshipData.mu.Unlock()
now := GoUtil.Now()
uids := make(map[int]struct{})
for k, v := range ChampshipData.Rank {
notify := make(map[int]int)
for e, r := range v {
if r.Type == RANK_PLAYER_ROBOT {
AddScore := 0.0
Robot := ChampshipData.Robot[r.Uid]
if Robot == nil {
continue
}
if Robot.Type == 2 && Robot.Time+60 < now {
AddScore = Robot.PerScore
Robot.Time = now
}
if Robot.Type == 3 && Robot.Time+1800 < now {
AddScore = Robot.PerScore
Robot.Time = now
}
r.Score += AddScore
r.Score = math.Round(r.Score)
} else {
notify[r.Uid] = e
}
}
sort.Slice(v, func(i, j int) bool { // 排序 从大到小 数值相等按时间排序
if v[i].Score > v[j].Score {
return true
} else if v[i].Score == v[j].Score {
return v[i].Time < v[j].Time
}
return false
})
sortChampionshipRank(v)
for e, r := range v {
if r.Type == RANK_PLAYER_ROBOT {
continue
}
if notify[r.Uid] != e {
c.SetRankCache(r.Uid)
uids[r.Uid] = struct{}{}
}
}
ChampshipData.Rank[k] = v
}
// 在锁外通知玩家,避免在持锁时启动 goroutine 访问可能被并发修改的数据
for uid := range uids {
go NotifyPlayer(uid, &msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
End: now + onehour,
})
}
c.mDispatr.AfterFunc(time.Duration(60)*time.Second, func() {
c.ai()
})
return nil, nil
}
func (c *ChampshipMgr) GetPreRankMsg(uid int) *proto.ResChampshipPreRank {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
groupId := ChampshipData.PreGroupInfo[uid]
if groupId == 0 {
return &proto.ResChampshipPreRank{}
}
RankList, ok := ChampshipData.PreRank[groupId]
if !ok {
return &proto.ResChampshipPreRank{}
}
myRank := 0
myScore := 0.0
RL := make(map[int32]*proto.ResPlayerRank, 0)
for k, v := range RankList {
if v.Uid == uid {
myRank = v.Rank
myScore = v.Score
}
if v.Type == RANK_PLAYER_ROBOT {
robot := ChampshipData.PreRobot[v.Uid]
if robot == nil {
continue
}
last := &proto.ActLog{}
if robot.ActLog != nil {
last = &proto.ActLog{
Type: int32(robot.ActLog.Type),
Time: robot.ActLog.Time,
Param: robot.ActLog.Param,
}
}
RL[int32(k+1)] = &proto.ResPlayerRank{
Uid: int64(v.Uid),
Score: float32(v.Score),
Name: robot.Name,
Avatar: int32(robot.Avatar),
Face: int32(robot.Face),
Level: int32(robot.Level),
Type: int32(v.Type),
PlayroomSet: GoUtil.MapIntToInt32(robot.Playroom),
DressSet: GoUtil.MapIntToInt32(robot.DressSet),
FurSet: int32(robot.FurSet),
PetName: robot.PetName,
Last: last,
Rank: int32(v.Rank),
}
} else {
simplePlayer := G_GameLogicPtr.GetSimplePlayerByUid(v.Uid)
if simplePlayer == nil {
continue
}
last := &proto.ActLog{}
if simplePlayer.ActLog != nil {
last = &proto.ActLog{
Type: int32(simplePlayer.ActLog.Type),
Time: simplePlayer.ActLog.Time,
Param: simplePlayer.ActLog.Param,
}
}
RL[int32(k+1)] = &proto.ResPlayerRank{
Uid: int64(v.Uid),
Score: float32(v.Score),
Name: simplePlayer.Name,
Avatar: int32(simplePlayer.Avatar),
Face: int32(simplePlayer.Face),
Level: int32(simplePlayer.Level),
Type: int32(v.Type),
PlayroomSet: GoUtil.MapIntToInt32(simplePlayer.Playroom),
DressSet: GoUtil.MapIntToInt32(simplePlayer.DressSet),
FurSet: int32(simplePlayer.PetFur),
PetName: simplePlayer.PetName,
Last: last,
Rank: int32(v.Rank),
}
}
}
return &proto.ResChampshipPreRank{
MyRank: int32(myRank),
MyScore: float32(myScore),
RankList: RL,
}
}
// TODO 待优化
func (c *ChampshipMgr) GetRankMsg(uid int) *proto.ResChampshipRank {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
groupId := ChampshipData.GroupInfo[uid]
if groupId == 0 {
return &proto.ResChampshipRank{}
}
rankList, ok := ChampshipData.Rank[groupId]
if !ok {
return &proto.ResChampshipRank{}
}
myRank := 0
myScore := 0.0
RL := make(map[int32]*proto.ResPlayerRank, 0)
for k, v := range rankList {
if v.Uid == uid {
myRank = v.Rank
myScore = v.Score
}
if v.Type == RANK_PLAYER_ROBOT {
robot := ChampshipData.Robot[v.Uid]
if robot == nil {
continue
}
last := &proto.ActLog{}
if robot.ActLog != nil {
last = &proto.ActLog{
Type: int32(robot.ActLog.Type),
Time: robot.ActLog.Time,
Param: robot.ActLog.Param,
}
}
RL[int32(k+1)] = &proto.ResPlayerRank{
Uid: int64(v.Uid),
Score: float32(v.Score),
Name: robot.Name,
Avatar: int32(robot.Avatar),
Face: int32(robot.Face),
Level: int32(robot.Level),
Type: int32(v.Type),
PlayroomSet: GoUtil.MapIntToInt32(robot.Playroom),
DressSet: GoUtil.MapIntToInt32(robot.DressSet),
FurSet: int32(robot.FurSet),
PetName: robot.PetName,
Last: last,
Rank: int32(v.Rank),
}
} else {
simplePlayer := G_GameLogicPtr.GetSimplePlayerByUid(v.Uid)
if simplePlayer == nil {
continue
}
last := &proto.ActLog{}
if simplePlayer.ActLog != nil {
last = &proto.ActLog{
Type: int32(simplePlayer.ActLog.Type),
Time: simplePlayer.ActLog.Time,
Param: simplePlayer.ActLog.Param,
}
}
RL[int32(k+1)] = &proto.ResPlayerRank{
Uid: int64(v.Uid),
Score: float32(v.Score),
Name: simplePlayer.Name,
Avatar: int32(simplePlayer.Avatar),
Face: int32(simplePlayer.Face),
Level: int32(simplePlayer.Level),
Type: int32(v.Type),
PlayroomSet: GoUtil.MapIntToInt32(simplePlayer.Playroom),
DressSet: GoUtil.MapIntToInt32(simplePlayer.DressSet),
FurSet: int32(simplePlayer.PetFur),
PetName: simplePlayer.PetName,
Last: last,
Rank: int32(v.Rank),
}
}
}
return &proto.ResChampshipRank{
MyRank: int32(myRank),
MyScore: float32(myScore),
RankList: RL,
}
}
// 分组
func (c *ChampshipMgr) group() (interface{}, error) {
c.mDispatr.AfterFunc(time.Duration(1800)*time.Second, func() { // 30分钟后重新分组
c.group()
})
ChampshipData := c.getData()
ChampshipData.mu.Lock()
defer ChampshipData.mu.Unlock()
log.Debug("ChampshipMgr group, player num:%d", len(ChampshipData.Pool))
if len(ChampshipData.Pool) == 0 { // 未分配玩家池为空
return nil, nil
}
total, err := db.RedisZCard(RANK_USER)
if err != nil {
total = 10000
}
total = min(total, 10000)
g := make(map[int][]int, 0)
list, err := db.RedisZRevRangeWithScores(RANK_USER, 0, total)
if err != nil {
log.Debug("redis zrevrange failed, err:%v\n", err)
}
uids := make([]int, 0, len(list))
for _, v := range list {
uids = append(uids, GoUtil.Int(v.Member))
}
for k, v := range ChampshipData.Pool { // step 1:根据数值分配玩家
x := 0
n := champshipCfg.GetGroupId(v.N)
h := champshipCfg.GetGroupId(v.H)
if n < h {
x = min(max(n-1, h-2), 1)
} else {
x = n
}
x = max(x, 1)
_, ok := g[x]
if !ok {
g[x] = make([]int, 0)
}
g[x] = append(g[x], k)
}
for i := 11; i > 0; i-- {
if len(g[i]) == 0 {
continue
}
// 少于10个的元素合并到下一组
if len(g[i]) < 10 && i > 1 {
g[i-1] = append(g[i-1], g[i]...)
continue
}
// 不被10整除的元素分到下一组
if len(g[i])%10 != 0 && i > 1 {
remainder := len(g[i]) % 10
g[i-1] = append(g[i-1], g[i][len(g[i])-remainder:]...)
g[i] = g[i][:len(g[i])-remainder]
}
ChampshipData.AutoId++
startId := ChampshipData.AutoId
for j := 0; j < len(g[i]); j++ {
if len(ChampshipData.Rank[ChampshipData.AutoId]) >= 10 {
log.Error("championship error: more than 10 players in a group")
}
ChampshipData.GroupInfo[g[i][j]] = ChampshipData.AutoId
userData := ChampshipData.Pool[g[i][j]]
ChampshipData.Rank[ChampshipData.AutoId] = append(ChampshipData.Rank[ChampshipData.AutoId], &ChampshipRank{
Uid: userData.Uid,
Score: userData.Score,
Time: userData.Time,
})
//log.Debug("group AutoId:%d, Uid:%d, Score:%.2f, Time:%d", ChampshipData.AutoId, userData.Uid, userData.Score, userData.Time)
if len(ChampshipData.Rank[ChampshipData.AutoId]) >= 10 && j != len(g[i])-1 {
ChampshipData.AutoId++
}
}
for j := startId; j <= ChampshipData.AutoId; j++ { // 填充机器人
if len(ChampshipData.Rank[j]) >= 30 || len(ChampshipData.Rank[j]) == 0 {
log.Error("championship error: more than 30 players in a group or no player in a group")
continue
}
robotNum := 30 - len(ChampshipData.Rank[j])
//log.Debug("group AutoId:%d, player num:%d, need robot num:%d", j, len(ChampshipData.Rank[j]), robotNum)
robotList := CreateRobotList(i, robotNum, j)
for i := 0; i < robotNum; i++ {
go FormatRobotInfo(robotList[i], i+1, uids)
}
for _, v := range robotList {
ChampshipData.Robot[ChampshipData.RobotId] = v
ChampshipData.Rank[j] = append(ChampshipData.Rank[j], &ChampshipRank{
Uid: ChampshipData.RobotId,
Score: math.Round(v.Score),
Time: v.Time,
Type: RANK_PLAYER_ROBOT,
})
ChampshipData.RobotId++
}
sort.Slice(ChampshipData.Rank[j], func(x, y int) bool { // 排序 从大到小 数值相等按时间排序
if ChampshipData.Rank[j][x].Score > ChampshipData.Rank[j][y].Score {
return true
}
return false
})
sortChampionshipRank(ChampshipData.Rank[j])
}
}
// 收集需要通知的玩家
notifyList := make([]int, 0, len(ChampshipData.Pool))
for k := range ChampshipData.Pool {
go c.SetRankCache(k) // SetRankCache 使用 unsafe 方法,在持有锁时是安全的
notifyList = append(notifyList, k)
}
c.getData().Pool = make(map[int]*GroupInfo) // 清空未分配池
// 在锁外通知玩家,避免在持有锁时调用外部函数
for _, uid := range notifyList {
go NotifyPlayer(uid, &msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
End: GoUtil.Now() + onehour,
})
}
return nil, nil
}
// 获取分组ID
func (c *ChampshipMgr) getGroupId(uid int) int {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
groupId, ok := ChampshipData.GroupInfo[uid]
if ok {
return groupId
}
return 0
}
// 进去榜单
func (c *ChampshipMgr) inRank(m *msg.Msg) (interface{}, error) {
data := m.Extra.(CRank)
// 在加锁前获取 GroupId避免在持有写锁时调用会获取读锁的 getGroupId 导致死锁
groupId := c.getGroupId(data.Uid)
ChampshipData := c.getData()
ChampshipData.mu.Lock()
defer ChampshipData.mu.Unlock()
// 再次检查 GroupId因为可能在等待锁期间被其他协程修改
if currentGroupId, ok := ChampshipData.GroupInfo[data.Uid]; ok {
groupId = currentGroupId
}
if groupId == 0 {
ChampshipData.Pool[data.Uid] = &GroupInfo{
Uid: data.Uid,
Score: data.Score,
Time: GoUtil.Now(),
N: data.N,
H: data.H,
}
return nil, nil
}
rankList, ok := ChampshipData.Rank[groupId]
if !ok {
ChampshipData.Rank[groupId] = make([]*ChampshipRank, 0)
}
inRank := false
notify := make(map[int]int)
for k, v := range rankList {
notify[v.Uid] = k
if v.Uid == data.Uid {
if v.Score < data.Score {
v.Score = data.Score
v.Time = GoUtil.Now()
inRank = true
} else {
return nil, nil
}
}
}
if !inRank {
rankList = append(rankList, &ChampshipRank{
Uid: data.Uid,
Score: data.Score,
Time: GoUtil.Now(),
})
}
sort.Slice(rankList, func(i, j int) bool { // 排序 从大到小 数值相等按时间排序
if rankList[i].Score > rankList[j].Score {
return true
} else if rankList[i].Score == rankList[j].Score {
return rankList[i].Time < rankList[j].Time
}
return false
})
// 重新排序 相同分数排名相同
sortChampionshipRank(rankList)
ChampshipData.Rank[groupId] = rankList
// 收集需要通知的玩家
notifyList := make([]int, 0)
for k, v := range rankList {
if notify[v.Uid] != k && v.Type != RANK_PLAYER_ROBOT {
c.SetRankCache(v.Uid)
notifyList = append(notifyList, v.Uid)
}
}
// 在锁外通知玩家
for _, uid := range notifyList {
go NotifyPlayer(uid, &msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
End: GoUtil.Now() + onehour,
})
}
c.SetRankCache(data.Uid)
return nil, nil
}
func (c *ChampshipMgr) getMyRank(uid int) int {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
groupId := ChampshipData.GroupInfo[uid]
if groupId == 0 {
return 0
}
rankList, ok := ChampshipData.Rank[groupId]
if !ok {
return 0
}
for _, v := range rankList {
if v.Uid == uid {
return v.Rank
}
}
return 0
}
func (c *ChampshipMgr) unsafe_getMyRank(uid int) int {
ChampshipData := c.getData()
groupId := ChampshipData.GroupInfo[uid]
if groupId == 0 {
return 0
}
rankList, ok := ChampshipData.Rank[groupId]
if !ok {
return 0
}
for _, v := range rankList {
if v.Uid == uid {
return v.Rank
}
}
return 0
}
func (c *ChampshipMgr) getLastMyRank(uid int) int {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
groupId := ChampshipData.PreGroupInfo[uid]
if groupId == 0 {
return 0
}
rankList, ok := ChampshipData.PreRank[groupId]
if !ok {
return 0
}
for _, v := range rankList {
if v.Uid == uid {
return v.Rank
}
}
return 0
}
func (c *ChampshipMgr) unsafe_getLastMyRank(uid int) int {
ChampshipData := c.getData()
groupId := ChampshipData.PreGroupInfo[uid]
if groupId == 0 {
return 0
}
rankList, ok := ChampshipData.PreRank[groupId]
if !ok {
return 0
}
for _, v := range rankList {
if v.Uid == uid {
return v.Rank
}
}
return 0
}
func (c *ChampshipMgr) getData() *ChampshipData {
return c.data.(*ChampshipData)
}
func CreateRobotList(G, num, groupId int) []*ChampshipRobot {
r := make([]*ChampshipRobot, 0)
switch G {
case 1:
r = append(r, CreateRobot(float64(GoUtil.RandNum(12181, 21680)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(7531, 12180)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(4631, 7530)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(2781, 4630)), groupId))
for i := 0; i < 6; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(1731, 2780)), groupId))
}
for i := 0; i < 5; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(241, 580)), groupId))
}
Last := num - len(r)
for i := 0; i < Last; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(20, 240)), groupId))
}
case 2:
r = append(r, CreateRobot(float64(GoUtil.RandNum(12181, 21680)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(7531, 12180)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(4631, 7530)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(2781, 4630)), groupId))
for i := 0; i < 6; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(1731, 2780)), groupId))
}
n := num - 10
for i := 0; i < int(float64(n)*0.1); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(241, 580)), groupId))
}
Last := num - len(r)
for i := 0; i < Last; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(20, 240)), groupId))
}
case 3:
r = append(r, CreateRobot(float64(GoUtil.RandNum(12181, 21680)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(7531, 12180)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(4631, 7530)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(2781, 4630)), groupId))
for i := 0; i < 6; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(1731, 2780)), groupId))
}
n := num - 10
for i := 0; i < int(float64(n)*0.05); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(581, 1730)), groupId))
}
for i := 0; i < int(float64(n)*0.15); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(241, 580)), groupId))
}
Last := num - len(r)
for i := 0; i < Last; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(20, 240)), groupId))
}
case 4:
r = append(r, CreateRobot(float64(GoUtil.RandNum(12181, 21680)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(7531, 12180)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(4631, 7530)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(2781, 4630)), groupId))
n := num - 4
for i := 0; i < int(float64(n)*0.35); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(1731, 2780)), groupId))
}
for i := 0; i < int(float64(n)*0.1); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(581, 1730)), groupId))
}
for i := 0; i < int(float64(n)*0.1); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(241, 580)), groupId))
}
Last := num - len(r)
for i := 0; i < Last; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(20, 240)), groupId))
}
case 5:
r = append(r, CreateRobot(float64(GoUtil.RandNum(12181, 21680)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(7531, 12180)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(4631, 7530)), groupId))
n := num - 3
for i := 0; i < int(float64(n)*0.05); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(2781, 4630)), groupId))
}
for i := 0; i < int(float64(n)*0.3); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(1731, 2780)), groupId))
}
for i := 0; i < int(float64(n)*0.1); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(581, 1730)), groupId))
}
for i := 0; i < int(float64(n)*0.2); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(241, 580)), groupId))
}
Last := num - len(r)
for i := 0; i < Last; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(20, 240)), groupId))
}
case 6:
r = append(r, CreateRobot(float64(GoUtil.RandNum(12181, 21680)), groupId))
r = append(r, CreateRobot(float64(GoUtil.RandNum(7531, 12180)), groupId))
n := num - 2
for i := 0; i < int(float64(n)*0.05); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(4631, 7530)), groupId))
}
for i := 0; i < int(float64(n)*0.05); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(2781, 4630)), groupId))
}
for i := 0; i < int(float64(n)*0.3); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(1731, 2780)), groupId))
}
for i := 0; i < int(float64(n)*0.1); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(581, 1730)), groupId))
}
for i := 0; i < int(float64(n)*0.25); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(241, 580)), groupId))
}
Last := num - len(r)
for i := 0; i < Last; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(20, 240)), groupId))
}
case 7:
r = append(r, CreateRobot(float64(GoUtil.RandNum(12181, 21680)), groupId))
n := num - 1
for i := 0; i < int(float64(n)*0.05); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(7531, 12180)), groupId))
}
for i := 0; i < int(float64(n)*0.05); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(4631, 7530)), groupId))
}
for i := 0; i < int(float64(n)*0.1); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(2781, 4630)), groupId))
}
for i := 0; i < int(float64(n)*0.3); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(1731, 2780)), groupId))
}
for i := 0; i < int(float64(n)*0.1); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(581, 1730)), groupId))
}
for i := 0; i < int(float64(n)*0.2); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(241, 580)), groupId))
}
Last := num - len(r)
for i := 0; i < Last; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(20, 240)), groupId))
}
case 8, 9, 10, 11:
M10 := GoUtil.RandMap(map[int]int{0: 98, 1: 2})
if M10 == 1 {
r = append(r, CreateRobot(float64(GoUtil.RandNum(35131, 64980)), groupId))
}
n := num
for i := 0; i < int(float64(n)*0.05); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(12181, 21680)), groupId))
}
for i := 0; i < int(float64(n)*0.05); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(7531, 12180)), groupId))
}
for i := 0; i < int(float64(n)*0.05); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(4631, 7530)), groupId))
}
for i := 0; i < int(float64(n)*0.1); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(2781, 4630)), groupId))
}
for i := 0; i < int(float64(n)*0.3); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(1731, 2780)), groupId))
}
for i := 0; i < int(float64(n)*0.15); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(581, 1730)), groupId))
}
for i := 0; i < int(float64(n)*0.2); i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(241, 580)), groupId))
}
Last := num - len(r)
for i := 0; i < Last; i++ {
r = append(r, CreateRobot(float64(GoUtil.RandNum(20, 240)), groupId))
}
}
return r
}
func CreateRobot(M float64, groupId int) *ChampshipRobot {
rType := GoUtil.RandMap(map[int]int{1: 25, 2: 50, 3: 25})
score := M / 10
perScore := 0.0
if rType == 2 {
perScore = math.Round((M/10*0.34)/(float64(GoUtil.NextZeroTimestampDuration())/60)*100) / 100
score = M / 10 * 0.66
}
if rType == 3 {
perScore = math.Round((M/10*0.34)/(float64(GoUtil.NextZeroTimestampDuration())/1800)*100) / 100
score = 2
}
return &ChampshipRobot{
Max: M / 10,
Type: rType,
Name: randnameCfg.GetRandName(),
PetName: randnameCfg.GetRandName(),
Avatar: avatarCfg.GetRandInitId(),
Face: faceCfg.GetRandInitId(),
Level: GoUtil.RandNum(1, 10),
GroupId: groupId,
Time: GoUtil.Now(),
Score: score,
PerScore: perScore,
}
}
func FormatRobotInfo(robot *ChampshipRobot, index int, uids []int) {
x := int(len(uids)) / 30
if index > int(x) {
index = int(x)
}
start := max(int64((index-1)*x), 0)
end := max(int64(index*x-1), 0)
rindex := GoUtil.RandNum(int(start), int(end))
if rindex >= len(uids) {
rindex = len(uids) - 1
}
uid := uids[rindex]
playerSimpleData := G_GameLogicPtr.GetSimplePlayerByUid(uid)
if playerSimpleData == nil {
return
}
robot.Level = playerSimpleData.Level
robot.Avatar = playerSimpleData.Avatar
robot.Face = playerSimpleData.Face
robot.Playroom = playerSimpleData.Playroom
robot.DressSet = playerSimpleData.DressSet
robot.FurSet = playerSimpleData.PetFur
robot.ActLog = playerSimpleData.ActLog
robot.PetName = playerSimpleData.PetName
}
func (c *ChampshipMgr) SetRankCache(uid int) {
preRank := c.unsafe_getLastMyRank(uid)
rank := c.unsafe_getMyRank(uid)
preGroupId := c.getData().PreGroupInfo[uid]
groupId := c.getData().GroupInfo[uid]
key := fmt.Sprintf("champship_rank_cache_%d", uid)
log.Debug("SetRankCache key:%s; data:%s", key, fmt.Sprintf("%d_%d_%d_%d", preRank, rank, preGroupId, groupId))
db.RedisSetKey(key, fmt.Sprintf("%d_%d_%d_%d", preRank, rank, preGroupId, groupId), time.Second*172800)
}
func (c *ChampshipMgr) Debug() {
ChampshipData := c.getData()
ChampshipData.Pool = make(map[int]*GroupInfo)
ChampshipData.Rank = make(map[int][]*ChampshipRank)
for i := 1; i <= 1000; i++ {
ChampshipData.Pool[i+10000] = &GroupInfo{
Uid: i + 10000,
Score: float64(GoUtil.RandNum(20, 21680)),
Time: GoUtil.Now(),
N: GoUtil.RandNum(1, 99),
H: GoUtil.RandNum(1, 99),
}
}
c.group()
var i int
for _, v := range ChampshipData.Rank {
for _, v1 := range v {
if v1.Type == 0 {
i++
}
}
}
log.Debug("Debug player num:%d", i)
}
func GetRankCache(uid int) (int, int, int, int) {
key := fmt.Sprintf("champship_rank_cache_%d", uid)
data, err := db.RedisGetKey(key)
if err != nil || data == "" {
return 0, 0, 0, 0
}
var preRank, rank, preGroupId, groupId int
fmt.Sscanf(data, "%d_%d_%d_%d", &preRank, &rank, &preGroupId, &groupId)
return preRank, rank, preGroupId, groupId
}