hxp
5 天以前 256fb6df5072850105da4b381f8ce1896c168ac1
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBBillboard.py
@@ -22,14 +22,17 @@
import IpyGameDataPY
import DBDataMgr
import CommFunc
import DBComm
import json
import time
class BillboardData():
    ## 榜单数据
    
    def __init__(self, dbData=None):
        self.__dbData = DBStruct.tagDBBillboard() if not dbData else dbData
        self.__dataDict = DBComm.UserDataDict(self.__dbData, "UserData", "DataLen", True)
        return
    
    def GetType(self): return self.__dbData.BillboardType
@@ -72,17 +75,9 @@
    def SetCmpValue3(self, cmpValue3): self.__dbData.CmpValue3 = cmpValue3
    def GetTime(self): return self.__dbData.Time
    def SetTime(self, updTime): self.__dbData.Time = updTime
    def GetUserData(self): return self.__dbData.UserData
    def SetUserData(self, userData):
        if not isinstance(userData, str):
            if isinstance(userData, dict) or isinstance(userData, list):
                userData = json.dumps(userData, ensure_ascii=False)
            else:
                userData = ""
        userData = userData.replace(" ", "")
        self.__dbData.UserData = userData
        self.__dbData.DataLen = len(self.__dbData.UserData)
        return
    def GetUserDict(self): return self.__dataDict.GetData()
    def GetUserData(self): return self.__dataDict.ToString()
    def SetUserData(self, value): self.__dataDict.SetData(value)
    def GetBuffer(self): return self.__dbData.getBuffer()
    def Clear(self): return self.__dbData.clear()
    def Copy(self, setType=None):
@@ -110,6 +105,8 @@
        copyData.SetTime(self.GetTime())
        return copyData
    
TempBillData = BillboardData()
class Billboard():
    ## 某个排行榜类
    
@@ -120,21 +117,26 @@
        self.__billboardList = [] # [BillboardData, ...] 
        self.__idIndexDict = {} # {id:index, ...}
        self.__idOrderDict = {} # {id:名次, ...}
        self.__orderRuleList = None # 指定排名所需值规则列表 [[order, needCmpValue], ...]
        self.__sortDelay = False # 是否需要延迟排序
        self.__orderRuleList = None # 指定排名所需值规则列表 [[order, needCmpValue], ...]
        # 【层级模式】机器人填充数据模式,一般如果机器人数据量比较大的情况下实用该模式,如群英榜
        # 层级模式下,因为机器人数量一般比较大,比如1万,为了节约内存占用及遍历排序等效率,填充的机器人数据不插入实际的 __billboardList 里
        self.__orderRuleByLayer = False # 按固定层级模式,第1层即第1名,CmpValue直接使用名次值,方便排序用,由功能自行管理好CmpValue值
        self.__layerIDList = [] # 层级ID列表,顺序即排名,索引0为第1名,ID包含填充的机器人ID,初始的数据由功能按规则设置填充的机器人ID
        return
    
    def GetType(self): return self.__billboardType
    def GetGroupValue1(self): return self.__groupValue1
    def GetGroupValue2(self): return self.__groupValue2
    
    def ClearData(self):
    def ClearData(self, drName=""):
        if not self.__billboardList:
            return
        GameWorld.Log("Billboard ClearData billboardType=%s,groupValue1=%s,groupValue2=%s,dataCount=%s"
                      % (self.__billboardType, self.__groupValue1, self.__groupValue2, len(self.__billboardList)))
        if GameWorld.IsCrossServer():
            self.SaveDRData("Clear")
        GameWorld.Log("Billboard ClearData billboardType=%s,groupValue1=%s,groupValue2=%s,dataCount=%s,drName=%s"
                      % (self.__billboardType, self.__groupValue1, self.__groupValue2, len(self.__billboardList), drName))
        if drName or GameWorld.IsCrossServer():
            self.SaveDRData(drName if drName else "Clear")
        self.__billboardList = [] # [BillboardData, ...] 
        self.__idOrderDict = {} # {id:名次, ...}
        self.__idIndexDict = {}
@@ -143,10 +145,15 @@
    def SortData(self):
        GameWorld.DebugLog("榜单排序: billboardType=%s,groupValue1=%s,groupValue2=%s,dataCount=%s" 
                      % (self.__billboardType, self.__groupValue1, self.__groupValue2, len(self.__billboardList)))
        self.__billboardList.sort(key=lambda b: (b.GetCmpValue(), b.GetCmpValue2(), b.GetCmpValue3(), -b.GetTime()), reverse=True)
        if self.__orderRuleByLayer:
            self.__billboardList.sort(key=lambda b: (-b.GetCmpValue(), -b.GetTime()), reverse=True)
        else:
            self.__billboardList.sort(key=lambda b: (b.GetCmpValue(), b.GetCmpValue2(), b.GetCmpValue3(), -b.GetTime()), reverse=True)
        self.__idOrderDict = {} # 排序后重置,下次查询时更新并缓存
        self.__idIndexDict = {}
        self.__sortDelay = False
        if self.__orderRuleByLayer:
            self.__fixAndFillLayer()
        return
    
    def SetSortDelay(self):
@@ -161,7 +168,7 @@
        if not self.__sortDelay:
            return
        self.SortData()
        return
        return True
    
    def AddNewBillboardData(self, dataID):
        newData = None
@@ -273,11 +280,65 @@
                        billboardIndex += 1
                for order, billboardData in enumerate(self.__billboardList, 1):
                    self.__idIndexDict[billboardData.GetID()] = order - 1
            # 按层级固定排位的
            elif self.__orderRuleByLayer:
                if not self.SortDelayDo():
                    self.__fixAndFillLayer()
            else:
                for order, billboardData in enumerate(self.__billboardList, 1):
                    self.__idOrderDict[billboardData.GetID()] = order
                    self.__idIndexDict[billboardData.GetID()] = order - 1
        return self.__idOrderDict
    def IsOrderRuleByLayer(self): return self.__orderRuleByLayer
    def SetOrderRuleByLayer(self, layerRobotIDList):
        '''设置排名规则为层级模式,即一个名次一个坑位层级,该模式支持机器人填充数据
        该模式下 CmpValue 固定为  MaxCount - 名次 + 1
        @param layerRobotIDList: 填充的机器人ID排名列表
        '''
        self.__orderRuleByLayer = True
        self.__layerIDList = layerRobotIDList
        self.SortData() # 强制排序处理
        return
    def SetLayerIDList(self, layerIDList): self.__layerIDList = layerIDList
    def GetLayerIDList(self): return self.__layerIDList
    def __fixAndFillLayer(self):
        ## 检查修正并填充满最终层级ID顺序
        maxCount = self.GetMaxCount()
        layerIDCnt = len(self.__layerIDList)
        if layerIDCnt < maxCount:
            self.__layerIDList.extend([0]*(maxCount-layerIDCnt)) # 先用0填充,确保长度一致
        # 先检查修正真实榜单数据的排名值,确保唯一
        orderIDDict = {}
        for index, billboardData in enumerate(self.__billboardList):
            dataID = billboardData.GetID()
            order = billboardData.GetCmpValue()
            if order > maxCount:
                # 超过的默认不上榜,后面的数据不再处理,外层的数据使用替换的模式,故理论上不会有多余的数据,这里暂做个防范
                break
            if order <= 0:
                # 没有名次数据的也不上榜,但先跳过继续处理后面的数据
                continue
            while 1 <= order <= maxCount:
                if order not in orderIDDict:
                    orderIDDict[order] = dataID
                    self.__idOrderDict[dataID] = order
                    self.__idIndexDict[dataID] = index
                    break
                # 重复的数据修正层级比较值,确保唯一
                order += 1
                billboardData.SetCmpValue(order)
        for index, layerID in enumerate(self.__layerIDList):
            order = index + 1
            dataID = layerID
            if order in orderIDDict:
                dataID = orderIDDict[order]
            self.__layerIDList[index] = dataID
        return
    
    def SetOrderRuleList(self, orderRuleList):
        ## 排名所需值规则列表
@@ -323,6 +384,10 @@
        self.__billboardDict = {} # 排行榜字典 {(billboardType, groupValue1, groupValue2):Billboard, ...}
        return
    
    def DelAllData(self):
        self.__billboardDict = {}
        return
    def GetBillboardGroupList(self, bType):
        ## 根据榜单类型获取该类型所有分组榜单信息
        ## @return: [(billboardType, groupValue1, groupValue2), ...]