| #!/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  | 
|   | 
| Def_CrossBillboard_MaxDataCount = 100 # ¿ç·þ°ñµ¥Êý¾Ý×î´óÌõÊýÔݹ̶¨×î´óΪ100Ìõ£¬ÈçÓÐÐèÒªµ÷ÕûÐèÕë¶Ôʵ¼ÊÇé¿ö½øÐÐÆÀ¹À£¨ÈçÊý¾Ýͬ²½¡¢Í¬²½·â°üµÈ£©  | 
|       | 
| 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  | 
|       | 
|     # ±£´æÊý¾Ý ´æÊý¾Ý¿âºÍ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.__crossServerDataVer = 0 # Ö÷·þ°ñµ¥Êý¾Ý°æ±¾  | 
|         self.__clientServerDataVer = 0 # ×Ó·þ°ñµ¥Êý¾Ý°æ±¾  | 
|         self.__billboardList = [] # [tagDBCrossBillboard, ...]   | 
|         self.__idOrderDict = {} # {id:Ãû´Î, ...}  | 
|         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"   | 
|                       % (self.__billboardType, self.__groupValue1, self.__groupValue2))  | 
|         self.__billboardList = [] # [tagDBCrossBillboard, ...]   | 
|         self.__idOrderDict = {} # {id:Ãû´Î, ...}  | 
|           | 
|         self.UpdCrossServerDataVer(0)  | 
|         return  | 
|       | 
|     def SortData(self):  | 
|         self.__billboardList.sort(key=operator.attrgetter("CmpValue", "CmpValue2", "CmpValue3"), reverse=True)  | 
|         self.__idOrderDict = {} # ÅÅÐòºóÖØÖã¬Ï´βéѯʱ¸üв¢»º´æ  | 
|         self.UpdCrossServerDataVer()  | 
|         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()  | 
|         '''  | 
|         idOrderDict = self.GetIDOrderDict()  | 
|         if findID not in idOrderDict:  | 
|             return None  | 
|         order = idOrderDict[findID]  | 
|         return self.__billboardList[order - 1]  | 
|       | 
|     def SaveDRData(self):  | 
|         ## ¼Ç¼Á÷ÏòÊý¾Ý  | 
|         eventTypeName = "CrossBillboard_%s" % (self.__billboardType)  | 
|         drDict = {"BillboardType":self.__billboardType, "GroupValue1":self.__groupValue1, "GroupValue2":self.__groupValue2,   | 
|                   "DataCount":len(self.__billboardList)}  | 
|         DataRecordPack.SendEventPack(eventTypeName, drDict)  | 
|         for billboardData in self.__billboardList:  | 
|             dataDict = {"BillboardType":billboardData.BillboardType, "GroupValue1":billboardData.GroupValue1,   | 
|                         "GroupValue2":billboardData.GroupValue2, "Type2":billboardData.Type2,  | 
|                         "ID":billboardData.ID, "ID2":billboardData.ID2,  | 
|                         "Name1":billboardData.Name1, "Name2":billboardData.Name2,  | 
|                         "Value1":billboardData.Value1, "Value2":billboardData.Value2,  | 
|                         "CmpValue":billboardData.CmpValue, "CmpValue2":billboardData.CmpValue2,   | 
|                         "CmpValue3":billboardData.CmpValue3}  | 
|             DataRecordPack.SendEventPack(eventTypeName, dataDict)  | 
|         return  | 
|       | 
|     def GetBillboardDataList(self): return self.__billboardList  | 
|     def GetIDOrderDict(self):  | 
|         ## »ñÈ¡ID¶ÔÓ¦Ãû´Î×Öµä  | 
|         # @return: {ID:Ãû´Î, ...}  Ãû´Î´Ó1¿ªÊ¼  | 
|         if not self.__idOrderDict:  | 
|             for order, billboardData in enumerate(self.__billboardList, 1):  | 
|                 self.__idOrderDict[billboardData.ID] = order  | 
|         return self.__idOrderDict  | 
|       | 
|     def GetCount(self): return len(self.__billboardList)  | 
|     def GetMaxCount(self): return Def_CrossBillboard_MaxDataCount  | 
|       | 
|     def At(self, i): return self.__billboardList[i]  | 
|     def IsFull(self): return len(self.__billboardList) >= Def_CrossBillboard_MaxDataCount  | 
|       | 
|     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 = {}  | 
|             for i, syncData in enumerate(syncBillboardList):  | 
|                 ID, ID2, Name1, Name2, Type2, Value1, Value2, CmpValue, CmpValue2, CmpValue3 = 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.CmpValue = CmpValue  | 
|                 billboardData.CmpValue2 = CmpValue2  | 
|                 billboardData.CmpValue3 = CmpValue3  | 
|                   | 
|                 self.__idOrderDict[ID] = i + 1  | 
|                   | 
|             self.__clientServerDataVer = crossServerDataVer  | 
|               | 
|         return  | 
|   | 
| #// C0 04 ²é¿´¿ç·þÅÅÐаñ #tagCGViewCrossBillboard  | 
| #  | 
| #struct    tagCGViewCrossBillboard  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        Type;        //°ñµ¥ÀàÐÍ  | 
| #    BYTE        GroupValue1;    // ·Ö×éÖµ1  | 
| #    BYTE        GroupValue2;    // ·Ö×éÖµ2£¬Óë·Ö×éÖµ1×éºÏ¹éΪͬ×é°ñµ¥Êý¾Ý  | 
| #};  | 
| 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  | 
|       | 
|     if billboardType not in ShareDefine.CrossBillboardTypeList:  | 
|         return  | 
|       | 
|     billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|       | 
|     GameWorld.DebugLog("Íæ¼ÒÇëÇó²é¿´¿ç·þÅÅÐаñ: billboardType=%s,groupValue1=%s,groupValue2=%s" % (billboardType, groupValue1, groupValue2))  | 
|     if not billboardObj.CheckClientServerDataVer():  | 
|         SyncCrossBillboardToPlayer(curPlayer, billboardType, groupValue1, groupValue2, billboardObj.GetBillboardDataList())  | 
|         return  | 
|       | 
|     # ÇëÇó²éѯ¿ç·þ·þÎñÆ÷  | 
|     dataMsg = {"BillboardType":billboardType, "GroupValue1":groupValue1, "GroupValue2":groupValue2,  | 
|                "QueryData":{"EventName":"View", "PlayerID":playerID}}  | 
|     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=[], queryData={}):  | 
|     ## Í¬²½¿ç·þ°ñµ¥µ½×Ó·þ  | 
|     if not GameWorld.IsCrossServer():  | 
|         return  | 
|     billboardMgr = PyDataManager.GetCrossBillboardManager()  | 
|     billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)  | 
|     crossServerDataVer = billboardObj.GetCrossServerDataVer()  | 
|     msgData = {"BillboardType":billboardType, "GroupValue1":groupValue1, "GroupValue2":groupValue2,  | 
|                "QueryData":queryData, "CrossServerDataVer":crossServerDataVer}  | 
|       | 
|     # ÓвéѯÊý¾Ýʱ²Åͬ²½°ñµ¥Êý¾ÝÁÐ±í£¬·ñÔòֻͬ²½Êý¾Ý°æ±¾ºÅ  | 
|     if queryData:  | 
|         syncBillboardList = []  | 
|         billboardList = billboardObj.GetBillboardDataList()  | 
|         for billboardData in billboardList:  | 
|             ID = billboardData.ID  | 
|             ID2 = billboardData.ID2  | 
|             Name1 = billboardData.Name1  | 
|             Name2 = billboardData.Name2  | 
|             Type2 = billboardData.Type2  | 
|             Value1 = billboardData.Value1  | 
|             Value2 = billboardData.Value2  | 
|             CmpValue = billboardData.CmpValue  | 
|             CmpValue2 = billboardData.CmpValue2  | 
|             CmpValue3 = billboardData.CmpValue3  | 
|             syncBillboardList.append([ID, ID2, Name1, Name2, Type2, Value1, Value2, CmpValue, CmpValue2, CmpValue3])  | 
|         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":          | 
|         SyncCrossBillboardToPlayer(queryPlayer, billboardType, groupValue1, groupValue2, billboardObj.GetBillboardDataList())  | 
|     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):  | 
|     ## Í¬²½¸øÍæ¼Ò¿ç·þ°ñµ¥  | 
|     billboardInfo = ChPyNetSendPack.tagGCCrossBillboardInfo()  | 
|     billboardInfo.Type = billboardType  | 
|     billboardInfo.GroupValue1 = groupValue1  | 
|     billboardInfo.GroupValue2 = groupValue2  | 
|     billboardInfo.CrossBillboardDataList = []  | 
|     for billboardData in billboardList:  | 
|         billboardInfoData = ChPyNetSendPack.tagGCCrossBillboardData()  | 
|         billboardInfoData.ID = billboardData.ID  | 
|         billboardInfoData.Name1 = billboardData.Name1  | 
|         billboardInfoData.Name2 = billboardData.Name2  | 
|         billboardInfoData.Type2 = billboardData.Type2  | 
|         billboardInfoData.Value1 = billboardData.Value1  | 
|         billboardInfoData.Value2 = billboardData.Value2  | 
|         billboardInfoData.CmpValue = billboardData.CmpValue  | 
|         billboardInfoData.CmpValue2 = billboardData.CmpValue2  | 
|         billboardInfoData.CmpValue3 = billboardData.CmpValue3  | 
|         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"]  | 
|     cmpValue = billInfoDict["CmpValue"]  | 
|     cmpValue2 = billInfoDict["CmpValue2"]  | 
|     cmpValue3 = billInfoDict["CmpValue3"]  | 
|       | 
|     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 name1 == billboardData.Name1 and name2 == billboardData.Name2 \  | 
|             and type2 == billboardData.Type2 and id2 == billboardData.ID2:  | 
|             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"]  | 
|     cmpValue = billInfoDict["CmpValue"]  | 
|     cmpValue2 = billInfoDict["CmpValue2"]  | 
|     cmpValue3 = billInfoDict["CmpValue3"]  | 
|       | 
|     UpdCrossBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2,  | 
|                       cmpValue, cmpValue2, cmpValue3, groupValue2, id2)  | 
|     return  | 
|   | 
| def UpdCrossBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue,  | 
|                       cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0, autoSort=True):  | 
|     ''' ¸üпç·þÅÅÐаñ  | 
|     @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  | 
|     @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  | 
|               | 
|     # Ã»ÉèÖÃֵĬÈÏΪʱ¼ätime£¬ÏÈÉϰñµÄÅÅÇ°Ãæ  | 
|     if cmpValue3 == 0:  | 
|         # Ê±¼äȨֵ½öÔڱȽÏÖµ±ä¸üµÄÇé¿öϲŸüÐÂ, ·ÀÖ¹ÆäËû¸½ÊôÖµ¸üÐÂʱµ¼Ö±ȽÏÖµÏàͬµÄÍæ¼ÒÃû´Î¼ä»á±ä¶¯µÄÎÊÌâ  | 
|         if isNewData or billboardData.CmpValue != cmpValue or billboardData.CmpValue2 != cmpValue2:  | 
|             calcTime = GameWorld.ChangeTimeStrToNum("2090-01-01 00:00:00")  | 
|             cmpValue3 = max(0, calcTime - int(time.time())) # ±È½ÏÖµ3Èç¹ûûָ¶¨ÖµÔòĬÈϴ浱ǰ¸üеÄtime  | 
|         else:  | 
|             cmpValue3 = billboardData.CmpValue3  | 
|               | 
|     cmpValueChange = billboardData.CmpValue != cmpValue or billboardData.CmpValue2 != cmpValue2 or billboardData.CmpValue3 != cmpValue3  | 
|       | 
|     # ¸üÐÂËùÓÐÖµ  | 
|     billboardData.GroupValue1 = groupValue1  | 
|     billboardData.GroupValue2 = groupValue2  | 
|     billboardData.BillboardType = billboardType  | 
|     billboardData.ID = dataID  | 
|     billboardData.ID2 = id2  | 
|     billboardData.Name1 = "" if len(name1) > 33 else name1  | 
|     billboardData.Name2 = "" if len(name2) > 33 else name2  | 
|     billboardData.Type2 = type2  | 
|     billboardData.Value1 = value1  | 
|     billboardData.Value2 = value2  | 
|     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"   | 
|                        % (billboardType, groupValue1, groupValue2, dataID, isNewData, cmpValueChange,  | 
|                           type2, value1, value2, cmpValue, cmpValue2, cmpValue3), dataID)  | 
|       | 
|     if autoSort and cmpValueChange:  | 
|         billboardObj.SortData()  | 
|     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  | 
|   |