package game import ( "fmt" "server/GoUtil" "server/conf" "server/db" "server/game/mod/msg" "sort" "strconv" ) const ( RANK_TIME_SORT = 3000000000 ) type RankMgr struct { *ServerMod } type RankData struct { List map[int][]*Rank // 玩家排行榜 Champship map[int][]*Rank // 锦标赛排行榜 BackData map[int][]*Rank // 玩家排行榜 备份 } type RankInfo struct { List []*Rank MyRank int MyScore float64 } const ( RANK_TYPE_USER = 1 // 玩家排行榜 RANK_TYPE_GLOBAL = 2 // 全球排行榜 RANK_USER = "rank_user" // redis玩家排行榜 RANK_COUNTRY_USER = "rank_country_user" // redis国家排行榜 ) type Rank struct { Uid int Score float64 Time int64 } type RankMsg struct { Uid int Score float64 RankType int } func (r *RankMgr) Init() { r.key = RANK_MGR_KEY r.data = &RankData{ List: make(map[int][]*Rank, 0), } // 注册处理函数 r.init() r.RegisterHandler(msg.HANDLE_TYPE_RANK, r.inRank) r.RegisterHandler(msg.HANDLE_TYPE_RANK_INFO, r.getRankInfo) r.RegisterHandler(msg.SERVER_ZERO_UPDATE, r.ZeroUpdate) r.version() } func (r *RankMgr) version() error { RedisKey := fmt.Sprintf("%s_%s", RANK_COUNTRY_USER, conf.Server.CountryCode) RedisList, _ := db.RedisZRevRangeWithScores(RedisKey, 0, 100) if len(RedisList) > 0 { return nil } rankList := r.getRank(RANK_TYPE_USER) if len(rankList) == 0 { return nil } for _, v := range rankList { Uid := strconv.Itoa(v.Uid) db.RedisZAdd(RedisKey, Uid, v.Score) } return nil } func (r *RankMgr) getData() *RankData { return r.data.(*RankData) } // 零点更新 重置榜单 func (r *RankMgr) ZeroUpdate(m *msg.Msg) (interface{}, error) { return nil, nil } // 获取榜单数据 func (r *RankMgr) getRank(RankType int) []*Rank { if v, ok := r.getData().List[RankType]; ok { len := min(100, len(v)) return v[:len] } return []*Rank{} } func (r *RankMgr) getAllRank(RankType int) []*Rank { if v, ok := r.getData().List[RankType]; ok { return v } return []*Rank{} } func (r *RankMgr) getMyRank(Uid, RankType int) (int, float64) { if d, ok := r.getData().List[RankType]; ok { for k, v := range d { if v.Uid == Uid { return k + 1, v.Score } } } return 0, 0.0 } // 设置榜单数据 func (r *RankMgr) setRank(RankType int, data []*Rank) { r.getData().List[RankType] = data } // 获取排行榜信息 func (r *RankMgr) getRankInfo(m *msg.Msg) (interface{}, error) { data := m.Extra.(RankMsg) // 全球排行榜 if data.RankType == RANK_TYPE_GLOBAL { return r.getRedisRankInfo(m) } // 国家排行榜 if data.RankType == RANK_TYPE_USER { return r.getRedisCountryRankInfo(m) } rankList := r.getRank(data.RankType) MyRank, MyScore := r.getMyRank(m.From, data.RankType) return &RankInfo{ List: rankList, MyRank: MyRank, MyScore: MyScore, }, nil } func (r *RankMgr) getRedisCountryRankInfo(m *msg.Msg) (interface{}, error) { RedisKey := fmt.Sprintf("%s_%s", RANK_COUNTRY_USER, conf.Server.CountryCode) RedisList, err := db.RedisZRevRangeWithScores(RedisKey, 0, 100) if err != nil { return &RankInfo{}, nil } sort.Slice(RedisList, func(i, j int) bool { // 排序 从大到小 return RedisList[i].Score > RedisList[j].Score }) rankList := make([]*Rank, 0) for _, v := range RedisList { rankList = append(rankList, &Rank{ Uid: GoUtil.Int(v.Member), Score: v.Score, Time: GoUtil.Now(), }) } MyRank, MyScore, _ := db.RedisZRankWithScores(RANK_USER, strconv.Itoa(m.From)) return &RankInfo{ List: rankList, MyRank: int(MyRank), MyScore: MyScore, }, nil } func (r *RankMgr) getRedisRankInfo(m *msg.Msg) (interface{}, error) { RedisList, err := db.RedisZRevRangeWithScores(RANK_USER, 0, 100) if err != nil { return &RankInfo{}, nil } sort.Slice(RedisList, func(i, j int) bool { // 排序 从大到小 return RedisList[i].Score > RedisList[j].Score }) rankList := make([]*Rank, 0) for _, v := range RedisList { rankList = append(rankList, &Rank{ Uid: GoUtil.Int(v.Member), Score: v.Score, Time: GoUtil.Now(), }) } MyRank, MyScore, _ := db.RedisZRankWithScores(RANK_USER, strconv.Itoa(m.From)) return &RankInfo{ List: rankList, MyRank: int(MyRank), MyScore: MyScore, }, nil } // 进入排行榜 func (r *RankMgr) inRank(m *msg.Msg) (interface{}, error) { data := m.Extra.(RankMsg) rankList := r.getRank(data.RankType) inRank := false for _, v := range rankList { if v.Uid == data.Uid { if v.Score < data.Score { v.Score = data.Score v.Time = m.SendT inRank = true break } return nil, nil } } if !inRank { rankList = append(rankList, &Rank{Uid: data.Uid, Score: data.Score, Time: m.SendT}) } 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 }) r.setRank(data.RankType, rankList) if data.RankType == RANK_TYPE_USER { // 全球玩家排行榜 Uid := strconv.Itoa(data.Uid) TimeSort := fmt.Sprintf("0.%d", RANK_TIME_SORT-GoUtil.Now()) TimeSortF, _ := strconv.ParseFloat(TimeSort, 64) db.RedisZAdd(RANK_USER, Uid, data.Score+TimeSortF) // 地区玩家排行榜 RedisKey := fmt.Sprintf("%s_%s", RANK_COUNTRY_USER, conf.Server.CountryCode) db.RedisZAdd(RedisKey, Uid, data.Score+TimeSortF) } r.update = true return nil, nil } func (r *RankMgr) ClearRank(RankType int) { // if RankType == RANK_TYPE_GLOBAL { // db.RedisDel(RANK_USER) // return // } r.setRank(RankType, []*Rank{}) }