using System;  
 | 
using System.Collections.Generic;  
 | 
using UnityEngine;  
 | 
  
 | 
// 支持分页查询排行榜, 本服/跨服统一使用 参考QueryRankByPage  新封包 DTCA130_tagMCViewBillboardRet  
 | 
public class RankModel : GameSystemManager<RankModel>  
 | 
{  
 | 
    public event Action<int> onRankRefresh;  
 | 
    //public event Action<int> onMyRankRefresh;  
 | 
      
 | 
    //排行榜滚动显示的最大数量 类型  
 | 
    Dictionary<int, int> ranksShowMaxCnt = new Dictionary<int, int>();  
 | 
  
 | 
    //分页查询  
 | 
    Dictionary<int, int> queryRankCD = new Dictionary<int, int>(); //首次查询CD,不影响后续的分页查询  
 | 
    //分页查询 排名索引按字段存储 1代表第一名  
 | 
    Dictionary<int, Dictionary<int, RankData>> m_RankPageDatas = new Dictionary<int, Dictionary<int, RankData>>();    
 | 
    //类型:ID -排名索引,通过ID进行排重删除 不同名次 同ID的数据  
 | 
    Dictionary<int, Dictionary<int, int>> m_RankIDToIndex = new Dictionary<int, Dictionary<int, int>>();  
 | 
  
 | 
    //监听排行榜显示名次,用于分页查询,第一页查询由外部触发  
 | 
    //使用场景 如界面排行榜滚动的时候每次查询30个排名名额,在显示大于m*30 +20名时,监听下一页,查询m+1页  
 | 
    int pageCnt = 20; //每页查询条数  
 | 
    int queryPointNum = 12;  //查询点  
 | 
    int queryPageCD = 60; //内部查询点CD 避免不断上下滑动的时候过于频繁查询,外部使用重新打开的时候可以重置CD  
 | 
    Dictionary<int, float> queryPageTimes = new Dictionary<int, float>(); //查询页CD  
 | 
    Dictionary<int, int> ranksServerMaxCnt = new Dictionary<int, int>();    //服务器排行榜当前总数量(动态变化),分页查询的时候过滤用  
 | 
  
 | 
  
 | 
  
 | 
    public override void Init()  
 | 
    {  
 | 
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize;  
 | 
        ParseConfig();  
 | 
    }  
 | 
  
 | 
    public void OnBeforePlayerDataInitialize()  
 | 
    {  
 | 
        m_RankPageDatas.Clear();  
 | 
        m_RankIDToIndex.Clear();  
 | 
        queryRankCD.Clear();  
 | 
    }  
 | 
  
 | 
    void ParseConfig()  
 | 
    {  
 | 
        var config = FuncConfigConfig.Get("BillboardSet");  
 | 
        ranksShowMaxCnt = ConfigParse.ParseIntDict(config.Numerical3);  
 | 
    }  
 | 
  
 | 
    public int GetRankShowMaxCnt(int type)  
 | 
    {  
 | 
        if (ranksShowMaxCnt.ContainsKey(type))  
 | 
        {  
 | 
            return ranksShowMaxCnt[type];  
 | 
        }  
 | 
        return 100;  
 | 
    }  
 | 
  
 | 
    public override void Release()  
 | 
    {  
 | 
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize;  
 | 
    }  
 | 
  
 | 
  
 | 
    void ReSetRankDataEx(RankData data, HA130_tagMCViewBillboardRet.tagMCViewBillboardData serverData, int type)  
 | 
    {  
 | 
        data.id = serverData.ID;  
 | 
        data.id2 = (int)serverData.ID2;  
 | 
        data.name1 = serverData.Name1.Trim().Replace("\0", "");  
 | 
        data.name2 = serverData.Name2.Trim().Replace("\0", "");  
 | 
        data.subType = serverData.Type2;  
 | 
        data.value1 = serverData.Value1;  
 | 
        data.value2 = serverData.Value2;  
 | 
        data.value3 = serverData.Value3;  
 | 
        data.value4 = serverData.Value4;  
 | 
        data.value5 = serverData.Value5;  
 | 
        data.value6 = serverData.Value6;  
 | 
        data.value7 = serverData.Value7;  
 | 
        data.value8 = serverData.Value8;  
 | 
        data.cmpValue = serverData.CmpValue;  
 | 
        data.cmpValue2 = serverData.CmpValue2;  
 | 
        data.cmpValue3 = serverData.CmpValue3;  
 | 
        data.userData = serverData.UserData;  
 | 
        data.rank = serverData.Rank;  
 | 
        data.type = type;  
 | 
        data.index = serverData.Index;  
 | 
    }  
 | 
  
 | 
  
 | 
    #region 分页查询  
 | 
  
 | 
  
 | 
    //!!!本服分页查询使用说明  
 | 
    //1. QueryRankByPage:先查询第一页,startIndex = 0, count = 30, 在第一页查询前可以选择初始化ResetQueryParam  
 | 
    //2. ListenRankPage:一般在滚动条OnRefreshCell监听排行榜显示名次,用于分页查询  
 | 
    //  
 | 
    //  startIndex 和 count 配对,与watchID无关联  
 | 
    //  watchID;    //查看指定ID名次前后,查询范围服务端已固定,如果只要查指定目标,count可以设置1减少附加信息  
 | 
    public void QueryRankByPage(int type, int startIndex = 0, int count = 20, int watchID = 0, bool forceQuery = false, int groupValue1 = 0, int groupValue2 = 0)  
 | 
    {  
 | 
        if (queryRankCD.ContainsKey(type) && !forceQuery)  
 | 
        {  
 | 
            if (Time.time - queryRankCD[type] < 2f)  
 | 
            {  
 | 
                return;  
 | 
            }  
 | 
        }  
 | 
  
 | 
        var pak = new CA130_tagCMViewBillboard();  
 | 
        pak.Type = (byte)type;  
 | 
        pak.GroupValue1 = (byte)groupValue1;  
 | 
        pak.GroupValue2 = (uint)groupValue2;  
 | 
        pak.StartIndex = (ushort)startIndex;  //排名从0开始  
 | 
        pak.ViewCnt = (byte)count;  
 | 
        pak.ViewID = (uint)watchID;  
 | 
  
 | 
        GameNetSystem.Instance.SendInfo(pak);  
 | 
        queryRankCD[type] = (int)Time.time;  
 | 
    }  
 | 
  
 | 
  
 | 
    public void ListenRankPage(int type, int index, int groupValue1 = 0, int groupValue2 = 0)  
 | 
    {  
 | 
        int page = index / pageCnt;  
 | 
        if (index > page * pageCnt + queryPointNum)  
 | 
        {  
 | 
            if (queryPageTimes.ContainsKey(page) && Time.realtimeSinceStartup - queryPageTimes[page] < queryPageCD)  
 | 
                return;  
 | 
            if (ranksServerMaxCnt.ContainsKey(type))  
 | 
            {   
 | 
                if(index >= ranksServerMaxCnt[type])  
 | 
                {  
 | 
                    //超过服务器已上榜的总数量,比如总榜单是100名,当前只有8名玩家上榜,往下滚动就不再查询  
 | 
                    return;  
 | 
                }  
 | 
            }  
 | 
            Debug.LogFormat("分页查询:{0} - {1}", index, page);  
 | 
            QueryRankByPage(type, pageCnt * (page + 1), pageCnt, 0, true, groupValue1, groupValue2);  
 | 
            queryPageTimes[page] = Time.realtimeSinceStartup;  
 | 
        }  
 | 
    }  
 | 
  
 | 
    public void ResetQueryParam()  
 | 
    {  
 | 
        pageCnt = 20;  
 | 
        queryPointNum = 12;  
 | 
        queryPageCD = 60;  
 | 
        queryPageTimes.Clear();  
 | 
    }  
 | 
  
 | 
    public void SetQueryParm(int pageCnt, int queryPointNum, int queryPageCD)  
 | 
    {  
 | 
        this.pageCnt = pageCnt;  
 | 
        this.queryPointNum = queryPointNum;  
 | 
        this.queryPageCD = queryPageCD;  
 | 
        queryPageTimes.Clear();  
 | 
    }  
 | 
  
 | 
  
 | 
  
 | 
    //跨服排行榜信息  
 | 
    void ReSetRankData(RankData data, HA130_tagMCViewBillboardRet.tagMCViewBillboardData serverData, int type)  
 | 
    {  
 | 
        data.id = serverData.ID;  
 | 
        data.id2 = (int)serverData.ID2;  
 | 
        data.name1 = serverData.Name1.Replace("\0", "");  
 | 
        data.name2 = serverData.Name2.Replace("\0", "");  
 | 
        data.subType = serverData.Type2;  
 | 
        data.value1 = serverData.Value1;  
 | 
        data.value2 = serverData.Value2;  
 | 
        data.value3 = serverData.Value3;  
 | 
        data.value4 = serverData.Value4;  
 | 
        data.value5 = serverData.Value5;  
 | 
        data.value6 = serverData.Value6;  
 | 
        data.value7 = serverData.Value7;  
 | 
        data.value8 = serverData.Value8;  
 | 
        data.cmpValue = serverData.CmpValue;  
 | 
        data.cmpValue2 = serverData.CmpValue2;  
 | 
        data.cmpValue3 = serverData.CmpValue3;  
 | 
        data.userData = serverData.UserData;  
 | 
        data.rank = serverData.Rank;  
 | 
        data.index = serverData.Index;  
 | 
        data.type = type;   //与服务端一致的跨服排行榜类型,外部自行处理不同分组分赛季等情况  
 | 
    }  
 | 
  
 | 
    //查询本服/跨服排行榜  
 | 
    public void ReceiveRankPagePackage(HA130_tagMCViewBillboardRet package)  
 | 
    {  
 | 
        int rankType = package.Type;  
 | 
        //部分跨服排行榜同一个榜存在分组分区的情况 //赛区3位+赛季3位+排行榜类型3位  
 | 
        if (rankType == 165)    //CrossServerOneVsOneRewardModel.rankType  
 | 
        {  
 | 
            rankType = (int)package.GroupValue1 * 1000000 + (int)package.GroupValue2 * 1000 + rankType;  
 | 
        }  
 | 
  
 | 
        if (!m_RankPageDatas.ContainsKey(rankType))  
 | 
        {  
 | 
            m_RankPageDatas.Add(rankType, new Dictionary<int, RankData>());  
 | 
        }  
 | 
  
 | 
        //同ID排重删除  
 | 
        if (!m_RankIDToIndex.ContainsKey(rankType))  
 | 
        {  
 | 
            m_RankIDToIndex.Add(rankType, new Dictionary<int, int>());  
 | 
        }  
 | 
  
 | 
        if (!ranksServerMaxCnt.ContainsKey(rankType))  
 | 
        {   
 | 
            ranksServerMaxCnt.Add(rankType, package.DataTotal);  
 | 
        }  
 | 
        ranksServerMaxCnt[rankType] = package.DataTotal;  
 | 
  
 | 
        for (int i = 0; i < package.PageDataCnt; i++)  
 | 
        {  
 | 
            int id = (int)package.PageDataList[i].ID;  
 | 
            int orderIndex = (int)package.PageDataList[i].Rank;  
 | 
            if (!m_RankIDToIndex[rankType].ContainsKey(id))  
 | 
            {  
 | 
                m_RankIDToIndex[rankType][id] = orderIndex;  
 | 
            }  
 | 
            else if (m_RankIDToIndex[rankType][id] != orderIndex)  
 | 
            {  
 | 
                m_RankPageDatas[rankType].Remove(m_RankIDToIndex[rankType][id]);  
 | 
                m_RankIDToIndex[rankType][id] = orderIndex;  
 | 
            }  
 | 
        }  
 | 
  
 | 
  
 | 
  
 | 
        for (int i = 0; i < package.PageDataCnt; i++)  
 | 
        {  
 | 
            int orderIndex = (int)package.PageDataList[i].Rank;  
 | 
            if (!m_RankPageDatas[rankType].ContainsKey(orderIndex))  
 | 
            {  
 | 
                m_RankPageDatas[rankType][orderIndex] = new RankData();  
 | 
            }  
 | 
            ReSetRankDataEx(m_RankPageDatas[rankType][orderIndex], package.PageDataList[i], rankType);  
 | 
        }  
 | 
  
 | 
        if (package.ViewID != 0)  
 | 
        {  
 | 
            //查询指定目标排名  
 | 
            for (int i = 0; i < package.ViewIDDataCnt; i++)  
 | 
            {  
 | 
                int id = (int)package.ViewIDDataList[i].ID;  
 | 
                int orderIndex = (int)package.ViewIDDataList[i].Rank;  
 | 
                if (!m_RankIDToIndex[rankType].ContainsKey(id))  
 | 
                {  
 | 
                    m_RankIDToIndex[rankType][id] = orderIndex;  
 | 
                }  
 | 
                else if (m_RankIDToIndex[rankType][id] != orderIndex)  
 | 
                {  
 | 
                    m_RankPageDatas[rankType].Remove(m_RankIDToIndex[rankType][id]);  
 | 
                    m_RankIDToIndex[rankType][id] = orderIndex;  
 | 
                }  
 | 
            }  
 | 
  
 | 
  
 | 
            for (int i = 0; i < package.ViewIDDataCnt; i++)  
 | 
            {  
 | 
                int orderIndex = (int)package.ViewIDDataList[i].Rank;  
 | 
                if (!m_RankPageDatas[rankType].ContainsKey(orderIndex))  
 | 
                {  
 | 
                    m_RankPageDatas[rankType][orderIndex] = new RankData();  
 | 
                }  
 | 
                ReSetRankData(m_RankPageDatas[rankType][orderIndex], package.ViewIDDataList[i], package.Type);  
 | 
            }  
 | 
            //onMyRankRefresh?.Invoke(package.Type);    同时查询没有单独返回数据,暂时不要这个事件  
 | 
        }  
 | 
  
 | 
        onRankRefresh?.Invoke(package.Type);  
 | 
  
 | 
  
 | 
    }  
 | 
  
 | 
    //排名从1 开始  
 | 
    //如果是跨服排行榜 类型可能因跨服功能不同 由分组分赛季等情况组合  
 | 
    public Dictionary<int, RankData> GetRankPageDatas(int type)  
 | 
    {  
 | 
        Dictionary<int, RankData> datas = null;  
 | 
        if (m_RankPageDatas.TryGetValue(type, out datas))  
 | 
        {  
 | 
            return datas;  
 | 
        }  
 | 
        return null;  
 | 
    }  
 | 
  
 | 
    //查询指定目标排名的数据  
 | 
    public RankData GetRankDataByRank(int type, int rank)  
 | 
    {  
 | 
        Dictionary<int, RankData> rankDatas = null;  
 | 
        RankData rankData = null;  
 | 
        if (m_RankPageDatas.TryGetValue(type, out rankDatas))  
 | 
        {  
 | 
            rankDatas.TryGetValue(rank, out rankData);  
 | 
        }  
 | 
        return rankData;  
 | 
    }  
 | 
  
 | 
  
 | 
    ////如果是跨服排行榜 类型可能因跨服功能不同 由分组分赛季等情况组合  
 | 
    public RankData GetMyRank(int type)  
 | 
    {  
 | 
        var playerId = PlayerDatas.Instance.baseData.PlayerID;  
 | 
        Dictionary<int, RankData> rankDatas = null;  
 | 
        if (m_RankPageDatas.TryGetValue(type, out rankDatas))  
 | 
        {  
 | 
            foreach (var item in rankDatas.Values)  
 | 
            {  
 | 
                if (item.id == playerId)  
 | 
                {  
 | 
                    return item;  
 | 
                }  
 | 
            }  
 | 
        }  
 | 
        return null;  
 | 
    }  
 | 
  
 | 
    public RankData GetRankByID(int type, int queryID)  
 | 
    {  
 | 
        Dictionary<int, RankData> rankDatas = null;  
 | 
        if (m_RankPageDatas.TryGetValue(type, out rankDatas))  
 | 
        {  
 | 
            foreach (var item in rankDatas.Values)  
 | 
            {  
 | 
                if (item.id == queryID)  
 | 
                {  
 | 
                    return item;  
 | 
                }  
 | 
            }  
 | 
        }  
 | 
        return null;  
 | 
    }  
 | 
    #endregion  
 | 
}  
 | 
  
 | 
// 默认情况,各个榜可能有所变化  
 | 
// 玩家个人榜  
 | 
// ID            -             玩家ID  
 | 
// Name1    -             玩家名  
 | 
// Name2    -             游戏账号  
 | 
// Type2      -             职业  
 | 
// Value1     -             官职  
 | 
// Value2     -             称号ID  
 | 
// Value3     -             头像  
 | 
// Value4     -             头像框  
 | 
// Value5     -             主角形象  
 | 
// cmpValue     比较值亿  
 | 
// cmpValue2    比较值小于亿  
 | 
// cmpValue3    时间戳  
 | 
// ---------------------------------------  
 | 
// 仙盟榜  
 | 
// ID            -             仙盟ID  
 | 
// ID2          -             盟主ID  
 | 
// Name1    -             仙盟名  
 | 
// Name2    -             盟主名  
 | 
// Value1     -             总战力,整除亿部分  
 | 
// Value2     -             总战力,求余亿部分  
 | 
// Value3     -             徽章  
 | 
// Value4     -             仙盟等级  
 | 
// Value5     -             仙盟ServerID  
 | 
  
 | 
  
 | 
public class RankData  
 | 
{  
 | 
    public int type;    //排行榜类型  
 | 
    public int subType;  
 | 
    public uint id;  
 | 
    public int id2;  
 | 
    public string name1;  
 | 
    public string name2;  
 | 
    public uint value1;  
 | 
    public uint value2;  
 | 
    public uint value3;  
 | 
    public uint value4;  
 | 
    public uint value5;  
 | 
    public uint value6;  
 | 
    public uint value7;  
 | 
    public uint value8;  
 | 
    public uint cmpValue;  
 | 
    public uint cmpValue2;  
 | 
    public uint cmpValue3;  
 | 
    public string userData;  
 | 
    public int rank;   // 排名从1开始,代表第1名  
 | 
    public int index;    //数据在榜单列表中的索引,从0开始 非排名 分页查询会用到   
 | 
}  
 | 
  
 |