#!/usr/bin/python # -*- coding: GBK -*- #------------------------------------------------------------------------------- # ##@package DB.StructData.DBBillboard # # @todo:DBÅÅÐаñ # @author hxp # @date 2025-05-16 # @version 1.0 # # ÏêϸÃèÊö: DBÅÅÐаñ # #------------------------------------------------------------------------------- #"""Version = 2025-05-16 12:00""" #------------------------------------------------------------------------------- import DBStruct import GameWorld import ShareDefine import DataRecordPack import IpyGameDataPY import DBDataMgr import CommFunc import json class BillboardData(): ## °ñµ¥Êý¾Ý def __init__(self, dbData=None): self.__dbData = DBStruct.tagDBBillboard() if not dbData else dbData return def GetType(self): return self.__dbData.BillboardType def SetType(self, bType): self.__dbData.BillboardType = bType def GetGroupValue1(self): return self.__dbData.GroupValue1 def SetGroupValue1(self, groupValue1): self.__dbData.GroupValue1 = groupValue1 def GetGroupValue2(self): return self.__dbData.GroupValue2 def SetGroupValue2(self, groupValue2): self.__dbData.GroupValue2 = groupValue2 def GetID(self): return self.__dbData.ID def SetID(self, dataID): self.__dbData.ID = dataID def GetID2(self): return self.__dbData.ID2 def SetID2(self, id2): self.__dbData.ID2 = id2 def GetName1(self): return self.__dbData.Name1 def SetName1(self, name): self.__dbData.Name1 = name def GetName2(self): return self.__dbData.Name2 def SetName2(self, name2): self.__dbData.Name2 = name2 def GetType2(self): return self.__dbData.Type2 def SetType2(self, type2): self.__dbData.Type2 = type2 def GetValue1(self): return self.__dbData.Value1 def SetValue1(self, value1): self.__dbData.Value1 = value1 def GetValue2(self): return self.__dbData.Value2 def SetValue2(self, value2): self.__dbData.Value2 = value2 def GetValue3(self): return self.__dbData.Value3 def SetValue3(self, value3): self.__dbData.Value3 = value3 def GetValue4(self): return self.__dbData.Value4 def SetValue4(self, value4): self.__dbData.Value4 = value4 def GetValue5(self): return self.__dbData.Value5 def SetValue5(self, value5): self.__dbData.Value5 = value5 def GetValue6(self): return self.__dbData.Value6 def SetValue6(self, value6): self.__dbData.Value6 = value6 def GetValue7(self): return self.__dbData.Value7 def SetValue7(self, value7): self.__dbData.Value7 = value7 def GetValue8(self): return self.__dbData.Value8 def SetValue8(self, value8): self.__dbData.Value8 = value8 def GetCmpValue(self): return self.__dbData.CmpValue def SetCmpValue(self, cmpValue): self.__dbData.CmpValue = cmpValue def GetCmpValue2(self): return self.__dbData.CmpValue2 def SetCmpValue2(self, cmpValue2): self.__dbData.CmpValue2 = cmpValue2 def GetCmpValue3(self): return self.__dbData.CmpValue3 def SetCmpValue3(self, cmpValue3): self.__dbData.CmpValue3 = cmpValue3 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 GetBuffer(self): return self.__dbData.getBuffer() def Clear(self): return self.__dbData.clear() def Copy(self, setType=None): copyData = BillboardData() copyData.SetType(setType if setType != None else self.GetType()) copyData.SetGroupValue1(self.GetGroupValue1()) copyData.SetGroupValue2(self.GetGroupValue2()) copyData.SetID(self.GetID()) copyData.SetID2(self.GetID2()) copyData.SetName1(self.GetName1()) copyData.SetName2(self.GetName2()) copyData.SetType2(self.GetType2()) copyData.SetValue1(self.GetValue1()) copyData.SetValue2(self.GetValue2()) copyData.SetValue3(self.GetValue3()) copyData.SetValue4(self.GetValue4()) copyData.SetValue5(self.GetValue5()) copyData.SetValue6(self.GetValue6()) copyData.SetValue7(self.GetValue7()) copyData.SetValue8(self.GetValue8()) copyData.SetUserData(self.GetUserData()) copyData.SetCmpValue(self.GetCmpValue()) copyData.SetCmpValue2(self.GetCmpValue2()) copyData.SetCmpValue3(self.GetCmpValue3()) return copyData class Billboard(): ## ij¸öÅÅÐаñÀà def __init__(self, billboardType=0, groupValue1=0, groupValue2=0): self.__billboardType = billboardType self.__groupValue1 = groupValue1 self.__groupValue2 = groupValue2 self.__billboardList = [] # [BillboardData, ...] self.__idIndexDict = {} # {id:index, ...} self.__idOrderDict = {} # {id:Ãû´Î, ...} self.__orderRuleList = None # Ö¸¶¨ÅÅÃûËùÐèÖµ¹æÔòÁбí [[order, needCmpValue], ...] self.__sortDelay = False # ÊÇ·ñÐèÒªÑÓ³ÙÅÅÐò return def GetType(self): return self.__billboardType def GetGroupValue1(self): return self.__groupValue1 def GetGroupValue2(self): return self.__groupValue2 def ClearData(self): 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") self.__billboardList = [] # [BillboardData, ...] self.__idOrderDict = {} # {id:Ãû´Î, ...} self.__idIndexDict = {} return 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()), reverse=True) self.__idOrderDict = {} # ÅÅÐòºóÖØÖã¬Ï´βéѯʱ¸üв¢»º´æ self.__idIndexDict = {} self.__sortDelay = False return def SetSortDelay(self): ## ÉèÖÃÑÓ³ÙÅÅÐò GameWorld.DebugLog("°ñµ¥ÉèÖÃÑÓ³ÙÅÅÐò: billboardType=%s,groupValue1=%s,groupValue2=%s,dataCount=%s" % (self.__billboardType, self.__groupValue1, self.__groupValue2, len(self.__billboardList))) self.__sortDelay = True return def SortDelayDo(self): ## ÑÓ³ÙÅÅÐòÖ´ÐÐÅÅÐò if not self.__sortDelay: return self.SortData() return def AddNewBillboardData(self): newData = None if self.IsFull(): return newData newData = BillboardData() newData.SetType(self.__billboardType) newData.SetGroupValue1(self.__groupValue1) newData.SetGroupValue2(self.__groupValue2) self.AddBillboardData(newData) return newData def AddBillboardData(self, billboardData): ## Ìí¼Ó°ñµ¥Êý¾Ýµ½¸Ã°ñ # @param billboardData: BillboardData # @return: ÊÇ·ñ³É¹¦ if self.IsFull(): return False self.__billboardList.append(billboardData) self.__idIndexDict[billboardData.GetID()] = len(self.__billboardList) - 1 self.__sortDelay = True # __idOrderDict ²»´¦Àí£¬µÈÏ´ÎÅÅÐòºó×Ô¶¯´¦Àí£¬ËùÒÔÐÂÌí¼ÓµÄÊý¾Ý¿ÉÄÜÕÒ²»µ½¶ÔÓ¦Ãû´Î£¬µ«ÊÇÄÜÕÒµ½¶ÔÓ¦Ë÷Òý¼°Êý¾Ý return True def FindByID(self, findID): ''' ¸ù¾ÝID²éѯ°ñµ¥Êý¾Ý @param findID: ²éÕÒµÄID @return: None or BillboardData ''' billData = None self.GetIDOrderDict() if findID not in self.__idIndexDict: return billData idIndex = self.__idIndexDict[findID] if idIndex >= len(self.__billboardList): return billData billData = self.__billboardList[idIndex] if not billData and False: billData = BillboardData() # ²»»áÖ´Ðе½£¬Ö»ÎªÁË.³ö´úÂëÌáʾ return billData def IndexOfByID(self, findID): ''' ¸ù¾ÝID²éѯËùÔÚ°ñµ¥Ë÷Òý @param findID: ²éÕÒµÄID @return: -1 or >=0 ''' self.GetIDOrderDict() if findID not in self.__idIndexDict: return -1 idIndex = self.__idIndexDict[findID] return idIndex def SaveDRData(self, eventName="", addDataDict={}): ## ¼Ç¼Á÷ÏòÊý¾Ý self.SortDelayDo() dataCount = len(self.__billboardList) if not dataCount: return idOrderDict = self.GetIDOrderDict() serverTime = GameWorld.GetServerTime() timeStr = "%02d%02d%02d%s" % (serverTime.hour, serverTime.minute, serverTime.second, str(serverTime.microsecond)[:3]) eventTypeStr = "Billboard_%s_%s_%s_%s_%s" % (self.__billboardType, self.__groupValue1, self.__groupValue2, eventName, timeStr) dataDict = {"BillboardType":self.__billboardType, "DataCount":dataCount, "addDataDict":addDataDict, "GroupValue1":self.__groupValue1, "GroupValue2":self.__groupValue2} DataRecordPack.SendEventPack(eventTypeStr, dataDict) for index, bData in enumerate(self.__billboardList): rank = idOrderDict.get(bData.GetID(), index + 1) dataDict = {"Type2":bData.GetType2(), "Rank":rank, "Index":index, "ID":bData.GetID(), "ID2":bData.GetID2(), "Name1":bData.GetName1(), "Name2":bData.GetName2(), "Value1":bData.GetValue1(), "Value2":bData.GetValue2(), "Value3":bData.GetValue3(), "Value4":bData.GetValue4(), "Value5":bData.GetValue5(), "Value6":bData.GetValue6(), "Value7":bData.GetValue7(), "Value8":bData.GetValue8(), "CmpValue":bData.GetCmpValue(), "CmpValue2":bData.GetCmpValue2(), "CmpValue3":bData.GetCmpValue3(), "UserData":bData.GetUserData()} DataRecordPack.SendEventPack(eventTypeStr, dataDict) return def GetBillboardDataList(self): return self.__billboardList def GetIDOrderDict(self): ## »ñÈ¡ID¶ÔÓ¦Ãû´Î×Öµä # @return: {ID:Ãû´Î, ...} Ãû´Î´Ó1¿ªÊ¼ if not self.__idOrderDict or not self.__idIndexDict: self.__idOrderDict = {} self.__idIndexDict = {} if self.__orderRuleList: billboardDataCount = self.GetCount() rankPre = 0 billboardIndex = 0 for rank, needCmpValue in self.__orderRuleList: orderCountTotal = rank - rankPre # ½±ÀøÃû´ÎÊýÁ¿ rankPre = rank for index in xrange(billboardIndex, billboardDataCount): if orderCountTotal <= 0: break billboardData = self.At(index) if billboardData.GetCmpValue() < needCmpValue: break orderReal = rank - orderCountTotal + 1 self.__idOrderDict[billboardData.GetID()] = orderReal orderCountTotal -= 1 billboardIndex += 1 for order, billboardData in enumerate(self.__billboardList, 1): self.__idIndexDict[billboardData.GetID()] = order - 1 else: for order, billboardData in enumerate(self.__billboardList, 1): self.__idOrderDict[billboardData.GetID()] = order self.__idIndexDict[billboardData.GetID()] = order - 1 return self.__idOrderDict def SetOrderRuleList(self, orderRuleList): ## ÅÅÃûËùÐèÖµ¹æÔòÁбí # @param orderRuleList: ÅÅÃûËùÐèÖµ¹æÔòÁбí [[order, needCmpValue], ...] self.__orderRuleList = orderRuleList self.__idOrderDict = {} # ÉèÖúóÐèÖØÖ㬿ÉÄÜÅäÖùæÔò±ä»¯Á˵¼ÖÂʵ¼ÊÅÅÃû¿ÉÄܱ仯 self.__idIndexDict = {} GameWorld.Log("ÉèÖÃÅÅÃûËùÐèÖµ¹æÔòÁбí: billboardType=%s,groupValue1=%s,groupValue2=%s, %s" % (self.__billboardType, self.__groupValue1, self.__groupValue2, orderRuleList)) return def GetCount(self): return len(self.__billboardList) def GetMaxCount(self): maxCountDict = IpyGameDataPY.GetFuncEvalCfg("BillboardSet", 2, {}) return maxCountDict.get(self.__billboardType, 100) def At(self, index): billData = self.__billboardList[index] if not billData and False: billData = BillboardData() # ²»»áÖ´Ðе½£¬Ö»ÎªÁË.³ö´úÂëÌáʾ return billData def IsFull(self): return len(self.__billboardList) >= self.GetMaxCount() def DeleteByIndex(self, index): if index >= len(self.__billboardList): return self.__billboardList.pop(index) self.__idOrderDict = {} self.__idIndexDict = {} return def DeleteByID(self, dataID): index = self.IndexOfByID(dataID) if index >= 0: self.DeleteByIndex(index) return class BillboardMgr(): ## ÅÅÐаñ¹ÜÀí def __init__(self): self.__billboardDict = {} # ÅÅÐаñ×Öµä {(billboardType, groupValue1, groupValue2):Billboard, ...} return def GetBillboardGroupList(self, bType): ## ¸ù¾Ý°ñµ¥ÀàÐÍ»ñÈ¡¸ÃÀàÐÍËùÓзÖ×é°ñµ¥ÐÅÏ¢ ## @return: [(billboardType, groupValue1, groupValue2), ...] groupList = [] for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys(): if bType == billboardType: groupList.append((billboardType, groupValue1, groupValue2)) return groupList def GetBillboard(self, billboardType, groupValue1=0, groupValue2=0): ''' »ñÈ¡ÅÅÐаñ @param billboardType: ÅÅÐаñÀàÐÍ @param groupValue1: ·Ö×éÖµ1 @param groupValue2: ·Ö×éÖµ2£¬Óë·Ö×éÖµ1×éºÏ¹éΪͬ×é°ñµ¥Êý¾Ý @return: Billboard ''' key = (billboardType, groupValue1, groupValue2) if key in self.__billboardDict: billboardObj = self.__billboardDict[key] else: billboardObj = Billboard(billboardType, groupValue1, groupValue2) self.__billboardDict[key] = billboardObj return billboardObj def RemoveBillboard(self, billboardType): ## ÒÆ³ýij¸öÀàÐ͵İñµ¥ËùÓÐÊý¾Ý for key in self.__billboardDict.keys(): if key[0] == billboardType: self.__billboardDict.pop(key) return def ClearBillboard(self, billboardType, groupValue1=None, groupValue2=None): '''Çå³ýij¸öÀàÐ͵İñµ¥ËùÓÐÊý¾Ý£¬¿ÉÖ¸¶¨¹ýÂËgroupValue£¬ÓÐÁ÷Ïò¼Ç¼ @param groupValue1: ²»ÎªNoneʱÑéÖ¤ groupValue1 ÊÇ·ñÏàͬ @param groupValue2: ²»ÎªNoneʱÑéÖ¤ groupValue2 ÊÇ·ñÏàͬ Èç¹ûgroupValue1 groupValue2 ¶¼´«ÈëNone£¬Ï൱ÓÚÇå¿Õ billboardType ÀàÐ͵ÄËùÓаñµ¥Êý¾Ý ''' clearList = [] for bType, gValue1, gValue2 in self.__billboardDict.keys(): if bType != billboardType: continue if groupValue1 != None and groupValue1 != gValue1: continue if groupValue2 != None and groupValue2 != gValue2: continue key = (bType, gValue1, gValue2) clearList.append(key) for bType, gValue1, gValue2 in clearList: self.GetBillboard(bType, gValue1, gValue2).ClearData() return def CopyBillboard(self, fromBillboardType, toBillboardType, groupValue1=None, groupValue2=None): '''½«Ä³¸öÀàÐ͵İñµ¥ÍêÈ«¿½±´µ½ÆäËû°ñµ¥ - Ò»°ãÓÃÓÚ±¸·Ý¡¢×ªÒÆÊý¾Ý @param fromBillboardType: Ô´°ñµ¥ÀàÐÍ @param toBillboardType: Ä¿±ê°ñµ¥ÀàÐÍ @param groupValue1: ĬÈÏΪNone-¿½±´¸ÃÀàÐÍËùÓаñµ¥£¬´óÓÚµÈÓÚ0ʱ-½ö¿½±´¸ÃÀàÐÍϵÄÖ¸¶¨°ñµ¥ @param groupValue2: ĬÈÏΪNone-¿½±´¸ÃÀàÐÍËùÓаñµ¥£¬´óÓÚµÈÓÚ0ʱ-½ö¿½±´¸ÃÀàÐÍϵÄÖ¸¶¨°ñµ¥ ''' if groupValue1 == None: self.RemoveBillboard(toBillboardType) # ĬÈÏÇå¿ÕÄ¿±ê°ñµ¥ groupList = self.GetBillboardGroupList(fromBillboardType) else: groupValue2 = groupValue2 if groupValue2 != None else 0 groupList = [fromBillboardType, groupValue1, groupValue2] for billboardType, groupValue1, groupValue2 in groupList: frbillboardObj = self.GetBillboard(billboardType, groupValue1, groupValue2) toBillboardObj = self.GetBillboard(toBillboardType, groupValue1, groupValue2) GameWorld.Log("CopyBillboard: billboardType=%s,toBillboardType=%s,groupValue1=%s,groupValue2=%s" % (billboardType, toBillboardType, groupValue1, groupValue2)) toBillboardObj.ClearData() for index in range(frbillboardObj.GetCount()): frbillboardData = frbillboardObj.At(index) toBillboardObj.AddBillboardData(frbillboardData.Copy(toBillboardType)) return # ±£´æÊý¾Ý ´æÊý¾Ý¿âºÍrealtimebackup def GetSaveData(self): savaData = "" cntData = "" cnt = 0 for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys(): billboardObj = self.GetBillboard(billboardType, groupValue1, groupValue2) for i in xrange(billboardObj.GetCount()): billboardData = billboardObj.At(i) cnt += 1 savaData += billboardData.GetBuffer() GameWorld.Log("Save DBBillboard count :%s len=%s" % (cnt, len(savaData))) return CommFunc.WriteDWORD(cntData, cnt) + savaData # ´ÓÊý¾Ý¿âÔØÈëÊý¾Ý def LoadPyGameData(self, datas, pos, dataslen): if pos >= dataslen: return cnt, pos = CommFunc.ReadDWORD(datas, pos) GameWorld.Log("Load DBBillboard count :%s" % cnt) for _ in xrange(cnt): dbData = DBStruct.tagDBBillboard() dbData.clear() pos += dbData.readData(datas, pos, dataslen) billboardType, groupValue1, groupValue2 = dbData.BillboardType, dbData.GroupValue1, dbData.GroupValue2 billboardObj = self.GetBillboard(billboardType, groupValue1, groupValue2) billboardObj.AddBillboardData(BillboardData(dbData)) # ÅÅÐò for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys(): billboardObj = self.GetBillboard(billboardType, groupValue1, groupValue2) billboardObj.SortData() return pos def OnMinute(): ## ÿ·ÖÖÓÑÓ³ÙÅÅÐò billboardMgr = DBDataMgr.GetBillboardMgr() for billboardType in ShareDefine.BillboardTypeAllList: groupList = billboardMgr.GetBillboardGroupList(billboardType) for billboardType, groupValue1, groupValue2 in groupList: billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2) billboardObj.SortDelayDo() return