| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package CrossBillboard  | 
| #  | 
| # @todo:¿ç·þÅÅÐаñ  | 
| # @author hxp  | 
| # @date 2020-01-13  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ¿ç·þÅÅÐаñ  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2020-01-13 17:00"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import CommFunc  | 
| import ShareDefine  | 
| import CrossRealmMsg  | 
| import PyGameDataStruct  | 
| import ChPyNetSendPack  | 
| import DataRecordPack  | 
| import NetPackCommon  | 
| import PyDataManager  | 
| import GameWorld  | 
|   | 
| import operator  | 
| import time  | 
|   | 
| class CrossBillboardManager(object):  | 
|     ## ¿ç·þÅÅÐаñ¹ÜÀí£¬×¢Òâ¸ÃÀàÖ»´¦ÀíÊý¾ÝÂß¼£¬¹¦ÄÜÏà¹ØÂß¼²»ÒªÐ´ÔÚ¸ÃÀ࣬²»È»ÖضÁ½Å±¾²»»áÉúЧ  | 
|       | 
|     def __init__(self):  | 
|         self.__billboardDict = {} # ÅÅÐаñ×Öµä {(billboardType, groupValue1, groupValue2):CrossBillboard, ...}  | 
|         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 GetCrossBillboard(self, billboardType, groupValue1, groupValue2=0):  | 
|         ''' »ñÈ¡¿ç·þÅÅÐаñ  | 
|         @param billboardType: ÅÅÐаñÀàÐÍ  | 
|         @param groupValue1: ·Ö×éÖµ1  | 
|         @param groupValue2: ·Ö×éÖµ2£¬Óë·Ö×éÖµ1×éºÏ¹éΪͬ×é°ñµ¥Êý¾Ý  | 
|         @return: CrossBillboard  | 
|         '''  | 
|         key = (billboardType, groupValue1, groupValue2)  | 
|         if key in self.__billboardDict:  | 
|             billboardObj = self.__billboardDict[key]  | 
|         else:  | 
|             billboardObj = CrossBillboard(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  | 
|       | 
|     # ±£´æÊý¾Ý ´æÊý¾Ý¿âºÍrealtimebackup  | 
|     def GetSaveData(self):  | 
|         savaData = ""  | 
|         cntData = ""  | 
|         cnt = 0  | 
|         for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys():  | 
|             billboardObj = self.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|             for i in xrange(billboardObj.GetCount()):  | 
|                 billboardData = billboardObj.At(i)  | 
|                 cnt += 1  | 
|                 savaData += billboardData.getBuffer()  | 
|                   | 
|         GameWorld.Log("Save DBCrossBillboard count :%s len=%s" % (cnt, len(savaData)))  | 
|         return CommFunc.WriteDWORD(cntData, cnt) + savaData  | 
|       | 
|     # ´ÓÊý¾Ý¿âÔØÈëÊý¾Ý  | 
|     def LoadPyGameData(self, datas, pos, dataslen):  | 
|         cnt, pos = CommFunc.ReadDWORD(datas, pos)  | 
|         GameWorld.Log("Load DBCrossBillboard count :%s" % cnt)  | 
|           | 
|         for _ in xrange(cnt):  | 
|             billboardData = PyGameDataStruct.tagDBCrossBillboard()  | 
|             billboardData.clear()  | 
|             pos += billboardData.readData(datas, pos, dataslen)  | 
|               | 
|             billboardType, groupValue1, groupValue2 = billboardData.BillboardType, billboardData.GroupValue1, billboardData.GroupValue2  | 
|             billboardObj = self.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|             billboardObj.AddBillboardData(billboardData)  | 
|               | 
|         # ÅÅÐò  | 
|         for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys():  | 
|             billboardObj = self.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|             billboardObj.SortData()  | 
|               | 
|         return pos  | 
|       | 
| class CrossBillboard(object):  | 
|     ''' ¶ÔÓ¦¾ßÌåÀàÐÍÅÅÐаñÂß¼Àà  | 
|     '''  | 
|       | 
|     def __init__(self, billboardType, groupValue1=0, groupValue2=0):  | 
|         self.__billboardType = billboardType  | 
|         self.__groupValue1 = groupValue1  | 
|         self.__groupValue2 = groupValue2  | 
|         self.__maxCount = ShareDefine.CrossBillboard_MaxDataCount.get(billboardType, 100)  | 
|         self.__crossServerDataVer = 0 # Ö÷·þ°ñµ¥Êý¾Ý°æ±¾  | 
|         self.__clientServerDataVer = 0 # ×Ó·þ°ñµ¥Êý¾Ý°æ±¾  | 
|         self.__billboardList = [] # [tagDBCrossBillboard, ...]   | 
|         self.__idIndexDict = {} # {id:index, ...}  | 
|         self.__idOrderDict = {} # {id:Ãû´Î, ...}  | 
|         self.__orderRuleList = None  | 
|         self.__sortDelay = False # ÊÇ·ñÐèÒªÑÓ³ÙÅÅÐò  | 
|         return  | 
|       | 
|     def GetBillboardType(self): return self.__billboardType  | 
|     def GetGroupValue1(self): return self.__groupValue1  | 
|     def GetGroupValue2(self): return self.__groupValue2  | 
|       | 
|     def ClearData(self):  | 
|         GameWorld.Log("CrossBillboard 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 = [] # [tagDBCrossBillboard, ...]   | 
|         self.__idOrderDict = {} # {id:Ãû´Î, ...}  | 
|         self.__idIndexDict = {}  | 
|           | 
|         self.UpdCrossServerDataVer(0)  | 
|         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=operator.attrgetter("CmpValue", "CmpValue2", "CmpValue3"), reverse=True)  | 
|         self.__idOrderDict = {} # ÅÅÐòºóÖØÖã¬Ï´βéѯʱ¸üв¢»º´æ  | 
|         self.__idIndexDict = {}  | 
|         self.__sortDelay = False  | 
|         self.UpdCrossServerDataVer()  | 
|         return  | 
|       | 
|     def SetDelaySort(self):  | 
|         ## ÉèÖÃÑÓ³ÙÅÅÐò  | 
|         GameWorld.DebugLog("¿ç·þ°ñµ¥ÉèÖÃÑÓ³ÙÅÅÐò: billboardType=%s,groupValue1=%s,groupValue2=%s,dataCount=%s"   | 
|                       % (self.__billboardType, self.__groupValue1, self.__groupValue2, len(self.__billboardList)))  | 
|         self.__sortDelay = True  | 
|         self.UpdCrossServerDataVer()  | 
|         return  | 
|       | 
|     def DoDelaySort(self):  | 
|         ## ÑÓ³ÙÅÅÐò  | 
|         if not self.__sortDelay:  | 
|             return  | 
|         self.SortData()  | 
|         return  | 
|       | 
|     def AddBillboardData(self, billboardData):  | 
|         ## Ìí¼Ó°ñµ¥Êý¾Ýµ½¸Ã°ñ  | 
|         # @param billboardData: PyGameDataStruct.tagDBCrossBillboard()  | 
|         # @return: ÊÇ·ñ³É¹¦  | 
|         if self.IsFull():  | 
|             return False  | 
|         self.__billboardList.append(billboardData)  | 
|         return True  | 
|       | 
|     def FindByID(self, findID):  | 
|         ''' ¸ù¾ÝID²éѯ°ñµ¥Êý¾Ý  | 
|         @param findID: ²éÕÒµÄID  | 
|         @return: None or PyGameDataStruct.tagDBCrossBillboard()  | 
|         '''  | 
|         self.GetIDOrderDict()  | 
|         if findID not in self.__idIndexDict:  | 
|             return None  | 
|         idIndex = self.__idIndexDict[findID]  | 
|         if idIndex >= len(self.__billboardList):  | 
|             return None  | 
|         return self.__billboardList[idIndex]  | 
|       | 
|     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.DoDelaySort()  | 
|         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, billboardData in enumerate(self.__billboardList):  | 
|             rank = idOrderDict.get(billboardData.ID, index + 1)  | 
|             dataDict = {"Type2":billboardData.Type2, "Rank":rank, "Index":index,  | 
|                         "ID":billboardData.ID, "ID2":billboardData.ID2,    | 
|                         "Name1":billboardData.Name1, "Name2":billboardData.Name2,  | 
|                         "Value1":billboardData.Value1, "Value2":billboardData.Value2,  | 
|                         "Value3":billboardData.Value3, "Value4":billboardData.Value4,  | 
|                         "Value5":billboardData.Value5, "Value6":billboardData.Value6,  | 
|                         "Value7":billboardData.Value7, "Value8":billboardData.Value8,  | 
|                         "CmpValue":billboardData.CmpValue, "CmpValue2":billboardData.CmpValue2,   | 
|                         "CmpValue3":billboardData.CmpValue3, "UserData":billboardData.UserData}  | 
|             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.CmpValue < needCmpValue:  | 
|                             break  | 
|                         orderReal = rank - orderCountTotal + 1  | 
|                         self.__idOrderDict[billboardData.ID] = orderReal  | 
|                         orderCountTotal -= 1  | 
|                         billboardIndex += 1  | 
|                 for order, billboardData in enumerate(self.__billboardList, 1):  | 
|                     self.__idIndexDict[billboardData.ID] = order - 1  | 
|             else:  | 
|                 for order, billboardData in enumerate(self.__billboardList, 1):  | 
|                     self.__idOrderDict[billboardData.ID] = order  | 
|                     self.__idIndexDict[billboardData.ID] = 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): return self.__maxCount  | 
|       | 
|     def At(self, i): return self.__billboardList[i]  | 
|     def IsFull(self): return len(self.__billboardList) >= self.__maxCount  | 
|       | 
|     def UpdCrossServerDataVer(self, version=None):  | 
|         ## ¸üпç·þ°ñµ¥Êý¾Ý°æ±¾ºÅ£¬ÓÃÓÚ¿ç·þÖ÷·þ¡¢×Ó·þÑéÖ¤Êý¾Ý°æ±¾£¬Í¬²½°ñµ¥Êý¾ÝÓà  | 
|         if not GameWorld.IsCrossServer():  | 
|             return  | 
|         if version == None:  | 
|             version = int(time.time())  | 
|         self.__crossServerDataVer = version  | 
|         #SyncCrossBillboardToClientServer(self.__billboardType, self.__groupValue1, self.__groupValue2)  | 
|         return  | 
|     def GetCrossServerDataVer(self): return self.__crossServerDataVer  | 
|       | 
|     def CheckClientServerDataVer(self):  | 
|         ## ¼ì²é×Ó·þ°ñµ¥Êý¾Ý°æ±¾ÊÇ·ñÐèҪͬ²½  | 
|         # @return: ÊÇ·ñÐèÒªÏò¿ç·þÖ÷·þͬ²½×îÐÂÊý¾Ý  | 
|         return self.__clientServerDataVer == 0 or self.__clientServerDataVer != self.__crossServerDataVer  | 
|       | 
|     def UpdClientServerBillboard(self, crossServerDataVer, syncBillboardList=None):  | 
|         ## ¸üб¾·þµÄ¿ç·þ°ñµ¥Êý¾Ý  | 
|           | 
|         # ¸üпç·þÊý¾Ý°æ±¾  | 
|         self.__crossServerDataVer = crossServerDataVer  | 
|         # ÌØÊâ°æ±¾0´ú±íÇå³ýÊý¾Ý  | 
|         if crossServerDataVer == 0:  | 
|             self.ClearData()  | 
|               | 
|         # ¸üÐÂÊý¾Ý  | 
|         if syncBillboardList != None:  | 
|             self.__billboardList = self.__billboardList[:len(syncBillboardList)] # Ö±½ÓÓñ¾·þÒÔºóµÄÅÅÐÐÊý¾ÝʵÀýclearºó¸²¸Ç¸üУ¬²»×ãµÄ´´½¨ÐÂʵÀý  | 
|             self.__idOrderDict = {}  | 
|             self.__idIndexDict = {}  | 
|             for i, syncData in enumerate(syncBillboardList):  | 
|                 ID, ID2, Name1, Name2, Type2, Value1, Value2, CmpValue, CmpValue2, CmpValue3, Value3, Value4, Value5, Value6, Value7, Value8, UserData = syncData  | 
|                 if i < len(self.__billboardList):  | 
|                     billboardData = self.__billboardList[i]  | 
|                     billboardData.clear()  | 
|                 else:  | 
|                     billboardData = PyGameDataStruct.tagDBCrossBillboard()  | 
|                     self.__billboardList.append(billboardData)  | 
|                       | 
|                 billboardData.GroupValue1 = self.__groupValue1  | 
|                 billboardData.GroupValue2 = self.__groupValue2  | 
|                 billboardData.BillboardType = self.__billboardType  | 
|                 billboardData.ID = ID  | 
|                 billboardData.ID2 = ID2  | 
|                 billboardData.Name1 = Name1  | 
|                 billboardData.Name2 = Name2  | 
|                 billboardData.Type2 = Type2  | 
|                 billboardData.Value1 = Value1  | 
|                 billboardData.Value2 = Value2  | 
|                 billboardData.Value3 = Value3  | 
|                 billboardData.Value4 = Value4  | 
|                 billboardData.Value5 = Value5  | 
|                 billboardData.Value6 = Value6  | 
|                 billboardData.Value7 = Value7  | 
|                 billboardData.Value8 = Value8  | 
|                 billboardData.UserData = UserData  | 
|                 billboardData.DataLen = len(billboardData.UserData)  | 
|                 billboardData.CmpValue = CmpValue  | 
|                 billboardData.CmpValue2 = CmpValue2  | 
|                 billboardData.CmpValue3 = CmpValue3  | 
|                   | 
|                 self.__idOrderDict[ID] = i + 1  | 
|                 self.__idIndexDict[ID] = i  | 
|                   | 
|             self.__clientServerDataVer = crossServerDataVer  | 
|               | 
|         return  | 
|   | 
| def CopyBillboardOnDay():  | 
|     billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     for billboardType in ShareDefine.CrossBillboardTypeList:  | 
|         if billboardType in [ShareDefine.Def_CBT_BossTrialSubmitBak, ShareDefine.Def_CBT_BossTrialSubmitFamilyBak]:  | 
|             continue  | 
|         groupList = billboardMgr.GetBillboardGroupList(billboardType)  | 
|         for billboardType, groupValue1, groupValue2 in groupList:  | 
|             billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|             billboardObj.SaveDRData("OnDay")  | 
|     return  | 
|   | 
| def OnMinuteProcess():  | 
|     billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     for billboardType in ShareDefine.CrossBillboardTypeList:  | 
|         groupList = billboardMgr.GetBillboardGroupList(billboardType)  | 
|         for billboardType, groupValue1, groupValue2 in groupList:  | 
|             billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|             billboardObj.DoDelaySort()  | 
|     return  | 
|   | 
| def CopyBillboard(fromBillboardType, toBillboardType):  | 
|     ## ½«Ä³¸öÀàÐ͵İñµ¥ÍêÈ«¿½±´µ½ÆäËû°ñµ¥ - Ò»°ãÓÃÓÚ±¸·Ý¡¢×ªÒÆÊý¾Ý  | 
|       | 
|     billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     billboardMgr.RemoveBillboard(toBillboardType) # Ä¬ÈÏÇå¿ÕÄ¿±ê°ñµ¥  | 
|       | 
|     groupList = billboardMgr.GetBillboardGroupList(fromBillboardType)  | 
|     for billboardType, groupValue1, groupValue2 in groupList:  | 
|         frbillboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|         toBillboardObj = billboardMgr.GetCrossBillboard(toBillboardType, groupValue1, groupValue2)  | 
|         GameWorld.Log("CopyCrossBillboard: billboardType=%s,toBillboardType=%s,groupValue1=%s,groupValue2=%s"   | 
|                       % (billboardType, toBillboardType, groupValue1, groupValue2))  | 
|         for frbillboardData in frbillboardObj.GetBillboardDataList():  | 
|             tobillboardData = PyGameDataStruct.tagDBCrossBillboard()  | 
|             tobillboardData.GroupValue1 = groupValue1  | 
|             tobillboardData.GroupValue2 = groupValue2  | 
|             tobillboardData.BillboardType = toBillboardType  | 
|             tobillboardData.ID = frbillboardData.ID  | 
|             tobillboardData.ID2 = frbillboardData.ID2  | 
|             tobillboardData.Name1 = frbillboardData.Name1  | 
|             tobillboardData.Name2 = frbillboardData.Name2  | 
|             tobillboardData.Type2 = frbillboardData.Type2  | 
|             tobillboardData.Value1 = frbillboardData.Value1  | 
|             tobillboardData.Value2 = frbillboardData.Value2  | 
|             tobillboardData.Value3 = frbillboardData.Value3  | 
|             tobillboardData.Value4 = frbillboardData.Value4  | 
|             tobillboardData.Value5 = frbillboardData.Value5  | 
|             tobillboardData.Value6 = frbillboardData.Value6  | 
|             tobillboardData.Value7 = frbillboardData.Value7  | 
|             tobillboardData.Value8 = frbillboardData.Value8  | 
|             tobillboardData.UserData = frbillboardData.UserData  | 
|             tobillboardData.DataLen = len(tobillboardData.UserData)  | 
|             tobillboardData.CmpValue = frbillboardData.CmpValue  | 
|             tobillboardData.CmpValue2 = frbillboardData.CmpValue2  | 
|             tobillboardData.CmpValue3 = frbillboardData.CmpValue3  | 
|             toBillboardObj.AddBillboardData(tobillboardData)  | 
|               | 
|     return  | 
|   | 
| def CopyBillboardEx(fromBillboardType, toBillboardType, groupValue1, groupValue2=0):  | 
|     ## ½«Ä³¸öÀàÐ͵İñµ¥ÍêÈ«¿½±´µ½ÆäËû°ñµ¥ - Ò»°ãÓÃÓÚ±¸·Ý¡¢×ªÒÆÊý¾Ý  | 
|       | 
|     billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     frbillboardObj = billboardMgr.GetCrossBillboard(fromBillboardType, groupValue1, groupValue2)  | 
|     toBillboardObj = billboardMgr.GetCrossBillboard(toBillboardType, groupValue1, groupValue2)  | 
|     toBillboardObj.ClearData()  | 
|     GameWorld.Log("CopyBillboardEx: fromBillboardType=%s,toBillboardType=%s,groupValue1=%s,groupValue2=%s"   | 
|                   % (fromBillboardType, toBillboardType, groupValue1, groupValue2))  | 
|     for frbillboardData in frbillboardObj.GetBillboardDataList():  | 
|         tobillboardData = PyGameDataStruct.tagDBCrossBillboard()  | 
|         tobillboardData.GroupValue1 = groupValue1  | 
|         tobillboardData.GroupValue2 = groupValue2  | 
|         tobillboardData.BillboardType = toBillboardType  | 
|         tobillboardData.ID = frbillboardData.ID  | 
|         tobillboardData.ID2 = frbillboardData.ID2  | 
|         tobillboardData.Name1 = frbillboardData.Name1  | 
|         tobillboardData.Name2 = frbillboardData.Name2  | 
|         tobillboardData.Type2 = frbillboardData.Type2  | 
|         tobillboardData.Value1 = frbillboardData.Value1  | 
|         tobillboardData.Value2 = frbillboardData.Value2  | 
|         tobillboardData.Value3 = frbillboardData.Value3  | 
|         tobillboardData.Value4 = frbillboardData.Value4  | 
|         tobillboardData.Value5 = frbillboardData.Value5  | 
|         tobillboardData.Value6 = frbillboardData.Value6  | 
|         tobillboardData.Value7 = frbillboardData.Value7  | 
|         tobillboardData.Value8 = frbillboardData.Value8  | 
|         tobillboardData.UserData = frbillboardData.UserData  | 
|         tobillboardData.DataLen = len(tobillboardData.UserData)  | 
|         tobillboardData.CmpValue = frbillboardData.CmpValue  | 
|         tobillboardData.CmpValue2 = frbillboardData.CmpValue2  | 
|         tobillboardData.CmpValue3 = frbillboardData.CmpValue3  | 
|         toBillboardObj.AddBillboardData(tobillboardData)  | 
|           | 
|     return  | 
|   | 
| #// C0 04 ²é¿´¿ç·þÅÅÐаñ #tagCGViewCrossBillboard  | 
| #  | 
| #struct    tagCGViewCrossBillboard  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        Type;        //°ñµ¥ÀàÐÍ  | 
| #    BYTE        GroupValue1;    // ·Ö×éÖµ1  | 
| #    BYTE        GroupValue2;    // ·Ö×éÖµ2£¬Óë·Ö×éÖµ1×éºÏ¹éΪͬ×é°ñµ¥Êý¾Ý  | 
| #    DWORD        StartIndex;    //²é¿´µÄÆðʼÃû´ÎË÷Òý£¬ Ä¬ÈÏ0  | 
| #    BYTE        WatchCnt;    //²é¿´ÌõÊý£¬Ä¬ÈÏ20£¬×î´ó²»³¬¹ý100  | 
| #    DWORD        WatchID;        //²é¿´Ö¸¶¨IDÃû´Îǰºó£¬ÈçÍæ¼ÒID¡¢¼Ò×åIDµÈ  | 
| #};  | 
| def OnViewCrossBillboard(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     if GameWorld.IsCrossServer():  | 
|         return  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     billboardType, groupValue1, groupValue2 = clientData.Type, clientData.GroupValue1, clientData.GroupValue2  | 
|     startIndex = clientData.StartIndex  | 
|     watchCnt = clientData.WatchCnt  | 
|     watchID = clientData.WatchID  | 
|       | 
|     if billboardType not in ShareDefine.CrossBillboardTypeList:  | 
|         return  | 
|       | 
|     # Ö§³Ö·ÖÒ³²éѯ£¬¸ÄΪֱ½Ó²é¿ç·þ·þÎñÆ÷  | 
|       | 
|     GameWorld.DebugLog("Íæ¼ÒÇëÇó²é¿´¿ç·þÅÅÐаñ: billboardType=%s,groupValue1=%s,groupValue2=%s" % (billboardType, groupValue1, groupValue2))  | 
|       | 
|     # ÇëÇó²éѯ¿ç·þ·þÎñÆ÷  | 
|     dataMsg = {"BillboardType":billboardType, "GroupValue1":groupValue1, "GroupValue2":groupValue2,  | 
|                "QueryData":{"EventName":"View", "PlayerID":playerID, "StartIndex":startIndex, "WatchCnt":watchCnt, "WatchID":watchID}}  | 
|     CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_QueryBillboard, dataMsg)  | 
|     return  | 
|   | 
| def ClientServerMsg_QueryBillboard(serverGroupID, msgData):  | 
|     ## ÊÕµ½×Ó·þÇëÇó²éѯÅÅÐаñÐÅÏ¢  | 
|     billboardType = msgData["BillboardType"]  | 
|     groupValue1 = msgData["GroupValue1"]  | 
|     groupValue2 = msgData["GroupValue2"]  | 
|     queryData = msgData.get("QueryData", {}) # ÔÊý¾Ý·µ»Ø×Ó·þ  | 
|     SyncCrossBillboardToClientServer(billboardType, groupValue1, groupValue2, [serverGroupID], queryData)  | 
|     return  | 
|   | 
| def SyncCrossBillboardToClientServer(billboardType, groupValue1, groupValue2, serverGroupIDList=None, queryData=None):  | 
|     ## Í¬²½¿ç·þ°ñµ¥µ½×Ó·þ  | 
|     if not GameWorld.IsCrossServer():  | 
|         return  | 
|     if serverGroupIDList == None:  | 
|         serverGroupIDList = []  | 
|     if queryData == None:  | 
|         queryData = {}  | 
|     billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|     billboardObj.DoDelaySort()  | 
|     idOrderDict = billboardObj.GetIDOrderDict()  | 
|     crossServerDataVer = billboardObj.GetCrossServerDataVer()  | 
|     msgData = {"BillboardType":billboardType, "GroupValue1":groupValue1, "GroupValue2":groupValue2,  | 
|                "QueryData":queryData, "CrossServerDataVer":crossServerDataVer}  | 
|       | 
|     # ÓвéѯÊý¾Ýʱ²Åͬ²½°ñµ¥Êý¾ÝÁÐ±í£¬·ñÔòֻͬ²½Êý¾Ý°æ±¾ºÅ  | 
|     if queryData:  | 
|         #playerID = queryData.get("PlayerID", 0)  | 
|         startIndex = queryData.get("StartIndex", 0)  | 
|         watchCnt = queryData.get("WatchCnt", 0)  | 
|         watchID = queryData.get("WatchID", 0)  | 
|           | 
|         count = billboardObj.GetCount()  | 
|         endIndex = 0  | 
|         # ²é¿´×Ô¼ºÇ°ºóÃû´Î  | 
|         if watchID:  | 
|             playerIndex = billboardObj.IndexOfByID(watchID)  | 
|             if playerIndex != -1:  | 
|                 # Ç°5ºó4£¬Ê×β²¹×ã10Ìõ¼Ç¼  | 
|                 endIndex = min(playerIndex + 5, count)  | 
|                 startIndex = max(0, endIndex - 10)  | 
|                 endIndex = min(endIndex + (10 - (endIndex - startIndex)), count)  | 
|             else:  | 
|                 startIndex = 0  | 
|                   | 
|         # Ö¸¶¨Ë÷Òý·ÖÒ³²é¿´  | 
|         else:  | 
|             startIndex = max(startIndex, 0)  | 
|             startIndex = min(startIndex, count)  | 
|             watchCnt = 20 if not watchCnt else min(watchCnt, 100) # Ä¬ÈÏ20£¬×î¶à100  | 
|             endIndex = min(startIndex + watchCnt, count)  | 
|               | 
|         syncBillboardList = []  | 
|         for index in xrange(startIndex, endIndex):  | 
|               | 
|             if startIndex < 0 or index >= count:  | 
|                 break  | 
|               | 
|             billboardData = billboardObj.At(index)  | 
|               | 
|             ID = billboardData.ID  | 
|             ID2 = billboardData.ID2  | 
|             Name1 = billboardData.Name1  | 
|             Name2 = billboardData.Name2  | 
|             Type2 = billboardData.Type2  | 
|             Value1 = billboardData.Value1  | 
|             Value2 = billboardData.Value2  | 
|             Value3 = billboardData.Value3  | 
|             Value4 = billboardData.Value4  | 
|             Value5 = billboardData.Value5  | 
|             Value6 = billboardData.Value6  | 
|             Value7 = billboardData.Value7  | 
|             Value8 = billboardData.Value8  | 
|             UserData = billboardData.UserData  | 
|             CmpValue = billboardData.CmpValue  | 
|             CmpValue2 = billboardData.CmpValue2  | 
|             CmpValue3 = billboardData.CmpValue3  | 
|             orderIndex = idOrderDict.get(ID, index + 1) - 1  | 
|             syncBillboardList.append([orderIndex, ID, ID2, Name1, Name2, Type2, Value1, Value2, CmpValue, CmpValue2, CmpValue3, Value3, Value4, Value5, Value6, Value7, Value8, UserData])  | 
|         msgData["BillboardDataList"] = syncBillboardList  | 
|           | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_SyncBillboard, msgData, serverGroupIDList)  | 
|     return  | 
|   | 
| def CrossServerMsg_SyncBillboard(msgData, tick):  | 
|     ## ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄÅÅÐаñÐÅÏ¢  | 
|     billboardType = msgData["BillboardType"]  | 
|     groupValue1 = msgData["GroupValue1"]  | 
|     groupValue2 = msgData["GroupValue2"]  | 
|     crossServerDataVer = msgData["CrossServerDataVer"]  | 
|     syncBillboardList = msgData.get("BillboardDataList")  | 
|     GameWorld.DebugLog("ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄÅÅÐаñÐÅÏ¢: billboardType=%s,groupValue1=%s,groupValue2=%s,crossServerDataVer=%s"   | 
|                        % (billboardType, groupValue1, groupValue2, crossServerDataVer))  | 
|       | 
|     #billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     #billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|     #billboardObj.UpdClientServerBillboard(crossServerDataVer, syncBillboardList)  | 
|       | 
|     queryData = msgData.get("QueryData")  | 
|     if not queryData:  | 
|         return  | 
|       | 
|     eventName = queryData.get("EventName")  | 
|     #eventData = queryData.get("EventData")  | 
|     queryPlayerID = queryData.get("PlayerID", 0)  | 
|     if not eventName or not queryPlayerID:  | 
|         return  | 
|       | 
|     queryPlayer = GameWorld.GetPlayerManager().FindPlayerByID(queryPlayerID)  | 
|     if not queryPlayer:  | 
|         return  | 
|       | 
|     if eventName == "View":          | 
|         watchID = queryData.get("WatchID", 0)  | 
|         SyncCrossBillboardToPlayer(queryPlayer, billboardType, groupValue1, groupValue2, syncBillboardList, watchID)  | 
|     #else:  | 
|     #    idOrderDict = billboardObj.GetIDOrderDict()  | 
|     #    order = idOrderDict.get(queryPlayerID, 0)  | 
|     #    sysMsg = str([billboardType, groupValue1, groupValue2, eventName, eventData, order])  | 
|     #    queryPlayer.MapServer_QueryPlayerResult(0, 0, "CrossBillboardOrder", sysMsg, len(sysMsg))  | 
|           | 
|     return  | 
|   | 
| def SyncCrossBillboardToPlayer(curPlayer, billboardType, groupValue1, groupValue2, billboardList, watchID):  | 
|     ## Í¬²½¸øÍæ¼Ò¿ç·þ°ñµ¥  | 
|     billboardInfo = ChPyNetSendPack.tagGCCrossBillboardInfo()  | 
|     billboardInfo.Type = billboardType  | 
|     billboardInfo.GroupValue1 = groupValue1  | 
|     billboardInfo.GroupValue2 = groupValue2  | 
|     billboardInfo.WatchID = watchID  | 
|     billboardInfo.CrossBillboardDataList = []  | 
|     for dataInfo in billboardList:  | 
|         orderIndex, ID, ID2, Name1, Name2, Type2, Value1, Value2, CmpValue, CmpValue2, CmpValue3, Value3, Value4, Value5, Value6, Value7, Value8, UserData = dataInfo  | 
|         billboardInfoData = ChPyNetSendPack.tagGCCrossBillboardData()  | 
|         billboardInfoData.OrderIndex = orderIndex  | 
|         billboardInfoData.ID = ID  | 
|         billboardInfoData.ID2 = ID2  | 
|         billboardInfoData.Name1 = Name1  | 
|         billboardInfoData.Name2 = Name2  | 
|         billboardInfoData.Type2 = Type2  | 
|         billboardInfoData.Value1 = Value1  | 
|         billboardInfoData.Value2 = Value2  | 
|         billboardInfoData.Value3 = Value3  | 
|         billboardInfoData.Value4 = Value4  | 
|         billboardInfoData.Value5 = Value5  | 
|         billboardInfoData.Value6 = Value6  | 
|         billboardInfoData.Value7 = Value7  | 
|         billboardInfoData.Value8 = Value8  | 
|         billboardInfoData.CmpValue = CmpValue  | 
|         billboardInfoData.CmpValue2 = CmpValue2  | 
|         billboardInfoData.CmpValue3 = CmpValue3  | 
|         billboardInfoData.UserData = UserData  | 
|         billboardInfoData.DataLen = len(billboardInfoData.UserData)  | 
|         billboardInfo.CrossBillboardDataList.append(billboardInfoData)  | 
|     billboardInfo.BillboardCount = len(billboardInfo.CrossBillboardDataList)  | 
|     NetPackCommon.SendFakePack(curPlayer, billboardInfo)  | 
|     return  | 
|   | 
| def MapServer_UpdateCrossBillboard(billInfoDict):  | 
|     '''µØÍ¼¸üпç·þÅÅÐаñ, Í¨Óà  | 
|     {"Type":bType, "GroupValue1":groupValue1, "Type2":type2, "ID":dataID, "ID2":id2, "Name1":name1, "Name2":name2,  | 
|     "Value1":value1, "Value2":value2, "CmpValue":cmpValue, "CmpValue2":cmpValue2, "CmpValue3":cmpValue3,  | 
|     "GroupValue2":groupValue2}  | 
|     '''  | 
|       | 
|     if GameWorld.IsCrossServer():  | 
|         # Ö»ÓÐ×Ó·þÎñÆ÷Äܵ÷Óà  | 
|         return  | 
|     GameWorld.DebugLog("×Ó·þµØÍ¼¸üпç·þ°ñµ¥Êý¾Ý! %s" % billInfoDict)  | 
|       | 
|     billboardType = billInfoDict["Type"]  | 
|     if billboardType not in ShareDefine.CrossBillboardTypeList:  | 
|         return  | 
|     groupValue1 = billInfoDict["GroupValue1"]  | 
|     groupValue2 = billInfoDict["GroupValue2"]  | 
|     dataID = billInfoDict["ID"]  | 
|     if not groupValue1 or not dataID:  | 
|         return  | 
|       | 
|     type2 = billInfoDict["Type2"]  | 
|     id2 = billInfoDict["ID2"]  | 
|     name1 = billInfoDict["Name1"]  | 
|     name2 = billInfoDict["Name2"]  | 
|     value1 = billInfoDict["Value1"]  | 
|     value2 = billInfoDict["Value2"]  | 
|     value3 = billInfoDict.get("Value3", 0)  | 
|     value4 = billInfoDict.get("Value4", 0)  | 
|     value5 = billInfoDict.get("Value5", 0)  | 
|     value6 = billInfoDict.get("Value6", 0)  | 
|     value7 = billInfoDict.get("Value7", 0)  | 
|     value8 = billInfoDict.get("Value8", 0)  | 
|     cmpValue = billInfoDict["CmpValue"]  | 
|     cmpValue2 = billInfoDict["CmpValue2"]  | 
|     cmpValue3 = billInfoDict["CmpValue3"]  | 
|     userData = billInfoDict.get("UserData", "")  | 
|       | 
|     billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|     billboardData = billboardObj.FindByID(dataID)  | 
|     if billboardData:  | 
|         if cmpValue == billboardData.CmpValue and cmpValue2 == billboardData.CmpValue2 \  | 
|             and (not cmpValue3 or cmpValue3 == billboardData.CmpValue3) \  | 
|             and value1 == billboardData.Value1 and value2 == billboardData.Value2 \  | 
|             and value3 == billboardData.Value3 and value4 == billboardData.Value4 \  | 
|             and value5 == billboardData.Value5 and value6 == billboardData.Value6 \  | 
|             and value7 == billboardData.Value7 and value8 == billboardData.Value8 \  | 
|             and name1 == billboardData.Name1 and name2 == billboardData.Name2 \  | 
|             and type2 == billboardData.Type2 and id2 == billboardData.ID2 and userData == billboardData.UserData:  | 
|             GameWorld.DebugLog("    °ñµ¥ÖµÏàͬ£¬²»Í¬²½¿ç·þ·þÎñÆ÷! ")  | 
|             return  | 
|           | 
|     elif billboardObj.IsFull():  | 
|         lastBillBoardData = __CmpLastBillboardData(cmpValue, cmpValue2, cmpValue3, billboardObj)  | 
|         if not lastBillBoardData:  | 
|             GameWorld.DebugLog("    °ñµ¥Öµ²»³¬¹ý×îºóÒ»Ãû£¬²»Í¬²½¿ç·þ·þÎñÆ÷! ")  | 
|             return  | 
|           | 
|     else:  | 
|         GameWorld.DebugLog("    ±¾·þûÓÐÔÚ°ñÉÏ!")  | 
|           | 
|     # Í¬²½¿ç·þ·þÎñÆ÷  | 
|     CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_UpdateBillboard, billInfoDict)  | 
|     return  | 
|   | 
| def ClientServerMsg_UpdateBillboard(serverGroupID, billInfoDict):  | 
|     GameWorld.Log("ÊÕµ½×Ó·þ¸üпç·þ°ñµ¥Êý¾Ý! serverGroupID=%s, %s" % (serverGroupID, billInfoDict))  | 
|       | 
|     billboardType = billInfoDict["Type"]  | 
|     if billboardType not in ShareDefine.CrossBillboardTypeList:  | 
|         return  | 
|     groupValue1 = billInfoDict["GroupValue1"]  | 
|     groupValue2 = billInfoDict["GroupValue2"]  | 
|       | 
|     type2 = billInfoDict["Type2"]  | 
|     dataID = billInfoDict["ID"]  | 
|     id2 = billInfoDict["ID2"]  | 
|     name1 = billInfoDict["Name1"]  | 
|     name2 = billInfoDict["Name2"]  | 
|     value1 = billInfoDict["Value1"]  | 
|     value2 = billInfoDict["Value2"]  | 
|     value3 = billInfoDict.get("Value3", 0)  | 
|     value4 = billInfoDict.get("Value4", 0)  | 
|     value5 = billInfoDict.get("Value5", 0)  | 
|     value6 = billInfoDict.get("Value6", 0)  | 
|     value7 = billInfoDict.get("Value7", 0)  | 
|     value8 = billInfoDict.get("Value8", 0)  | 
|     cmpValue = billInfoDict["CmpValue"]  | 
|     cmpValue2 = billInfoDict["CmpValue2"]  | 
|     cmpValue3 = billInfoDict["CmpValue3"]  | 
|     userData = billInfoDict.get("UserData", "")  | 
|     kwargs = {"value3":value3, "value4":value4, "value5":value5, "value6":value6, "value7":value7, "value8":value8, "userData":userData}  | 
|       | 
|     UpdCrossBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2,  | 
|                       cmpValue, cmpValue2, cmpValue3, groupValue2, id2, **kwargs)  | 
|     return  | 
|   | 
| def UpdCrossBillboardFamily(bType, groupValue1, familyBillInfo, cmpValue, cmpValue2=0, autoSort=True):  | 
|     ## ¸üпç·þÏÉÃ˰ñµ¥  | 
|     if not familyBillInfo:  | 
|         return  | 
|     if "id" not in familyBillInfo:  | 
|         return  | 
|     familyID = familyBillInfo["id"]  | 
|     familyName = familyBillInfo["name"]  | 
|     id2 = familyBillInfo["id2"]  | 
|     name2 = familyBillInfo["name2"]  | 
|     value1 = familyBillInfo["value1"]  | 
|     value2 = familyBillInfo["value2"]  | 
|     value3 = familyBillInfo["value3"]  | 
|     value4 = familyBillInfo["value4"]  | 
|     value5 = familyBillInfo["value5"]  | 
|     type2 = 0  | 
|       | 
|     UpdCrossBillboard(bType, groupValue1, familyID, familyName, name2, type2, value1, value2, cmpValue, cmpValue2,   | 
|                       id2=id2, autoSort=autoSort, value3=value3, value4=value4, value5=value5)  | 
|     return  | 
|   | 
| def UpdCrossBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue,  | 
|                       cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0, autoSort=True, noSortAndSync=False,  | 
|                       **kwargs):  | 
|     ''' ¸üпç·þÅÅÐаñ  | 
|     @param billboardType: ÅÅÐаñË÷ÒýÀàÐÍ£¬Í¬¸ö°ñµ¥ÀàÐÍ¿ÉÒÔÓжà¸ö·Ö×é°ñµ¥Êý¾Ý£¬¶ÀÁ¢ÅÅÐò  | 
|     @param groupValue1: °ñµ¥·Ö×é1  | 
|     @param dataID: °ñµ¥Î¨Ò»Êý¾ÝID£¬ÈçÍæ¼ÒIDµÈ  | 
|     @param name1: ÏÔʾÃû³Æ1£¬²»Ó°ÏìÅÅÐò  | 
|     @param name2: ÏÔʾÃû³Æ2£¬²»Ó°ÏìÅÅÐò  | 
|     @param type2: °ñµ¥Êý¾ÝÀàÐÍ2£¬×Ô¶¨Ò壬һ°ãΪְҵµÈ¶þ¼¶·ÖÀ࣬²»Ó°ÏìÅÅÐò  | 
|     @param value1: ÏÔʾֵ1£¬²»Ó°ÏìÅÅÐò  | 
|     @param value2: ÏÔʾֵ2£¬²»Ó°ÏìÅÅÐò  | 
|     @param cmpValue: ±È½ÏÖµ1  | 
|     @param cmpValue2: ±È½ÏÖµ2  | 
|     @param cmpValue3: ±È½ÏÖµ3£¬Ã»É趨µÄ»°Ä¬ÈÏΪʱ¼ä´Á±È½ÏÖµ  | 
|     @param groupValue1: °ñµ¥·Ö×é2  | 
|     @param id2: À©Õ¹Êý¾ÝID2  | 
|     @param autoSort: ÊÇ·ñÅÅÐò£¬Ä¬ÈÏTrue  | 
|     @param noSortAndSync: ²»ÅÅÐò¼°Í¬²½×Ó·þ£¬Ä¬ÈÏFalse; Ò»°ãÓÃÓÚÅúÁ¿¸üÐÂÊý¾ÝʱÉèÖÃΪTrue£¬¼õÉÙÅÅÐò¼°Í¬²½ÆµÂÊ£¬µ«ÊÇÒ»¶¨ÒªÔÚÉèÖÃÍêÊý¾Ý»ò×îºóÒ»ÌõÊý¾ÝºóÊÖ¶¯µ÷ÓÃÒ»´ÎÅÅÐòSortData  | 
|     @return: ÊÇ·ñÉϰñ¸üаñµ¥  | 
|     '''  | 
|     if not GameWorld.IsCrossServer():  | 
|         # Ö»Óпç·þ·þÎñÆ÷Äܵ÷Óà  | 
|         return  | 
|     if not groupValue1 or not dataID:  | 
|         return  | 
|     billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|     billboardData = billboardObj.FindByID(dataID)  | 
|     isNewData = False  | 
|     if not billboardData:  | 
|         isNewData = True  | 
|         if billboardObj.IsFull():  | 
|             # Óë×îºóÒ»Ãû¶Ô±È  | 
|             lastBillBoardData = __CmpLastBillboardData(cmpValue, cmpValue2, cmpValue3, billboardObj)  | 
|             if not lastBillBoardData:  | 
|                 GameWorld.DebugLog("    °ñµ¥Öµ²»³¬¹ý×îºóÒ»Ãû£¬²»Éϰñ! ")  | 
|                 return  | 
|             billboardData = lastBillBoardData  | 
|             billboardData.clear()  | 
|         else:  | 
|             billboardData = PyGameDataStruct.tagDBCrossBillboard()  | 
|             if not billboardObj.AddBillboardData(billboardData):  | 
|                 return  | 
|               | 
|     cmpValueChange = isNewData or billboardData.CmpValue != cmpValue or billboardData.CmpValue2 != cmpValue2 or (cmpValue3 and billboardData.CmpValue3 != cmpValue3)  | 
|     # Ã»ÉèÖÃֵĬÈÏΪʱ¼ätime£¬ÏÈÉϰñµÄÅÅÇ°Ãæ  | 
|     if cmpValue3 == 0:  | 
|         # Ê±¼äȨֵ½öÔڱȽÏÖµ±ä¸üµÄÇé¿öϲŸüÐÂ, ·ÀÖ¹ÆäËû¸½ÊôÖµ¸üÐÂʱµ¼Ö±ȽÏÖµÏàͬµÄÍæ¼ÒÃû´Î¼ä»á±ä¶¯µÄÎÊÌâ  | 
|         if cmpValueChange:  | 
|             calcTime = GameWorld.ChangeTimeStrToNum("2090-01-01 00:00:00")  | 
|             cmpValue3 = max(0, calcTime - int(time.time())) # ±È½ÏÖµ3Èç¹ûûָ¶¨ÖµÔòĬÈϴ浱ǰ¸üеÄtime  | 
|         else:  | 
|             cmpValue3 = billboardData.CmpValue3  | 
|               | 
|     # ¸üÐÂËùÓÐÖµ  | 
|     billboardData.GroupValue1 = groupValue1  | 
|     billboardData.GroupValue2 = groupValue2  | 
|     billboardData.BillboardType = billboardType  | 
|     billboardData.ID = dataID  | 
|     billboardData.ID2 = id2  | 
|     billboardData.SetName1(name1)  | 
|     billboardData.SetName2(name2)  | 
|     billboardData.Type2 = type2  | 
|     billboardData.Value1 = value1  | 
|     billboardData.Value2 = value2  | 
|     billboardData.Value3 = kwargs.get("value3", 0)  | 
|     billboardData.Value4 = kwargs.get("value4", 0)  | 
|     billboardData.Value5 = kwargs.get("value5", 0)  | 
|     billboardData.Value6 = kwargs.get("value6", 0)  | 
|     billboardData.Value7 = kwargs.get("value7", 0)  | 
|     billboardData.Value8 = kwargs.get("value8", 0)  | 
|     billboardData.UserData = kwargs.get("userData", "")      | 
|     billboardData.DataLen = len(billboardData.UserData)      | 
|     billboardData.CmpValue = cmpValue  | 
|     billboardData.CmpValue2 = cmpValue2  | 
|     billboardData.CmpValue3 = cmpValue3  | 
|       | 
|     GameWorld.DebugLog("¸üпç·þÅÅÐаñÖµ: billboardType=%s,groupValue1=%s,groupValue2=%s,dataID=%s,isNewData=%s,cmpValueChange=%s,type2=%s,value1=%s,value2=%s,cmpValue=%s,cmpValue2=%s,cmpValue3=%s,%s"   | 
|                        % (billboardType, groupValue1, groupValue2, dataID, isNewData, cmpValueChange,  | 
|                           type2, value1, value2, cmpValue, cmpValue2, cmpValue3, kwargs), dataID)  | 
|     if noSortAndSync:  | 
|         return True  | 
|       | 
|     # ÐÂÊý¾Ý¿ÉÄܵ¼Ö°ñµ¥IDÔö¼õ£¬Ç¿ÖÆÅÅÐòÒ»´Î  | 
|     if isNewData:  | 
|         billboardObj.SortData()  | 
|     elif cmpValueChange:  | 
|         if autoSort:  | 
|             billboardObj.SortData()  | 
|         else:  | 
|             billboardObj.SetDelaySort()  | 
|     else:  | 
|         billboardObj.UpdCrossServerDataVer()  | 
|     return True  | 
|   | 
| def __CmpLastBillboardData(cmpValue, cmpValue2, cmpValue3, billboardObj):  | 
|     ## ±È½ÏÊÇ·ñ³¬¹ý×îºóÒ»Ãû  | 
|     # @return: ³¬¹ýÔò·µ»Ø×îºóÒ»ÃûÊý¾ÝʵÀý£¬·ñÔò·µ»ØNone  | 
|     if not billboardObj.GetCount():  | 
|         return  | 
|     lastBillBoardData = billboardObj.At(billboardObj.GetCount() - 1)  | 
|     if cmpValue < lastBillBoardData.CmpValue:  | 
|         #ÎÞ·¨Éϰñ  | 
|         return  | 
|     elif cmpValue == lastBillBoardData.CmpValue:   | 
|         if cmpValue2 < lastBillBoardData.CmpValue2:  | 
|             return  | 
|         elif cmpValue2 == lastBillBoardData.CmpValue2:  | 
|             if cmpValue3 <= lastBillBoardData.CmpValue3:  | 
|                 return  | 
|     return lastBillBoardData  | 
|   |