| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package PlayerRecData  | 
| #  | 
| # @todo:Íæ¼Ò¼Ç¼  | 
| # @author hxp  | 
| # @date 2024-07-02  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: Íæ¼Ò¼Ç¼£¬Çø±ðÓëͨÓüǼ£¬Í¨ÓüǼ×Ö·û³¤¶È¼Ç¼ÓÐÏÞ£¬ÇÒÕë¶ÔÍæ¼ÒµÄ¼Ç¼²éÕÒÿ´ÎÐèÒª±éÀú£¬Ð§Âʲ»¸ß  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2024-07-02 16:30"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import ChConfig  | 
| import ShareDefine  | 
| import PyDataManager  | 
| import PyGameDataStruct  | 
| import ChPyNetSendPack  | 
| import NetPackCommon  | 
| import GameWorld  | 
| import CommFunc  | 
|   | 
| import time  | 
|   | 
| class PlayerRecData():  | 
|       | 
|     def __init__(self, dbRecData=None):  | 
|         if not dbRecData:  | 
|             dbRecData = PyGameDataStruct.tagDBPlayerRecData()  | 
|         self.dbRecData = dbRecData  | 
|         self.evalUserData = None  | 
|         return  | 
|     def clear(self):  | 
|         self.dbRecData.clear()  | 
|         self.evalUserData = None  | 
|         return  | 
|     def GetPlayerID(self): return self.dbRecData.PlayerID  | 
|     def SetPlayerID(self, playerID): self.dbRecData.PlayerID = playerID  | 
|     def GetRecType(self): return self.dbRecData.RecType  | 
|     def SetRecType(self, recType): self.dbRecData.RecType = recType  | 
|     def GetTime(self): return self.dbRecData.Time  | 
|     def SetTime(self, sTime): self.dbRecData.Time = sTime  | 
|     def GetValue1(self): return self.dbRecData.Value1  | 
|     def SetValue1(self, value1): self.dbRecData.Value1 = value1  | 
|     def GetValue2(self): return self.dbRecData.Value2  | 
|     def SetValue2(self, value2): self.dbRecData.Value2 = value2  | 
|     def GetValue3(self): return self.dbRecData.Value3  | 
|     def SetValue3(self, value3): self.dbRecData.Value3 = value3  | 
|     def GetValue4(self): return self.dbRecData.Value4  | 
|     def SetValue4(self, value4): self.dbRecData.Value4 = value4  | 
|     def GetValue5(self): return self.dbRecData.Value5  | 
|     def SetValue5(self, value5): self.dbRecData.Value5 = value5  | 
|     def GetValue6(self): return self.dbRecData.Value6  | 
|     def SetValue6(self, value6): self.dbRecData.Value6 = value6  | 
|     def GetValue7(self): return self.dbRecData.Value7  | 
|     def SetValue7(self, value7): self.dbRecData.Value7 = value7  | 
|     def GetValue8(self): return self.dbRecData.Value8  | 
|     def SetValue8(self, value8): self.dbRecData.Value8 = value8  | 
|     def GetUserData(self): return self.dbRecData.UserData  | 
|     def SetUserData(self, userData):  | 
|         if type(userData) != str:  | 
|             userData = str(userData)  | 
|         self.dbRecData.UserData = userData.replace(" ", "")  | 
|         self.dbRecData.UserDataLen = len(self.dbRecData.UserData)  | 
|         if self.evalUserData != None:  | 
|             self.evalUserData = None  | 
|         return  | 
|     def GetEvalUserData(self, defValue={}):  | 
|         if self.evalUserData == None:  | 
|             try:  | 
|                 self.evalUserData = eval(self.dbRecData.UserData)  | 
|             except:  | 
|                 self.evalUserData = defValue  | 
|         return self.evalUserData  | 
|     def SetEvalUserData(self, eValue):  | 
|         self.evalUserData = eValue  | 
|         return  | 
|       | 
|     def IsMatchValue(self, valueList):  | 
|         # ¼ì²é¼Ç¼ֵÁбíÊÇ·ñÅäÖøüǼ  | 
|         # @param valueList: [value1, value2, ...] valueΪNoneʱ²»ÅжϸÃÖµ  | 
|         if not valueList:  | 
|             return False  | 
|         for i, value in enumerate(valueList, 1):  | 
|             if value == None:  | 
|                 continue  | 
|             if not hasattr(self, "GetValue%s" % i):  | 
|                 continue  | 
|             curValue = getattr(self, "GetValue%s" % i)()  | 
|             if curValue != value:  | 
|                 return False  | 
|         return True  | 
|       | 
|     def GetString(self):  | 
|         return {"PlayerID":self.GetPlayerID(), "RecType":self.GetRecType(), "Time":self.GetTime(),   | 
|                 "Value1":self.GetValue1(), "Value2":self.GetValue2(), "Value3":self.GetValue3(), "Value4":self.GetValue4(),  | 
|                 "Value5":self.GetValue5(), "Value6":self.GetValue6(), "Value7":self.GetValue7(), "Value8":self.GetValue8(),   | 
|                 "UserData":self.GetUserData()  | 
|                 }  | 
|     def SetAttr(self, attrDict, isClear=False):  | 
|         if isClear:  | 
|             self.clear()  | 
|         for k, v in attrDict.items():  | 
|             if hasattr(self, "Set%s" % k):  | 
|                 getattr(self, "Set%s" % k, v)(v)  | 
|         return  | 
|       | 
| class DBPlayerRecDataManager():  | 
|     ## Íæ¼Ò¼Ç¼¹ÜÀí  | 
|       | 
|     def __init__(self):  | 
|         self.Clear()  | 
|         return  | 
|       | 
|     def Clear(self):  | 
|         self.recTypeDict = {} # {recType:{playerID:[PlayerRecData, ...], ...}}  | 
|         return  | 
|       | 
|     def DelRecDataByType(self, recType):  | 
|         ## É¾³ýij¸ö¼Ç¼ÀàÐÍËùÓÐÍæ¼Ò¼Ç¼  | 
|         recDict = self.recTypeDict.pop(recType, {})  | 
|         delCount = 0  | 
|         for recList in recDict.values():  | 
|             delCount += len(recList)  | 
|         GameWorld.DebugLog("ɾ³ýËùÓÐÍæ¼ÒÖ¸¶¨¼Ç¼ÀàÐÍ: recType=%s,delCount=%s" % (recType, delCount))  | 
|         return delCount  | 
|       | 
|     def DelRecDataByTypePlayer(self, recType, delPlayerID):  | 
|         ## É¾³ýÍæ¼Òij¸öÀàÐͼǼ  | 
|         if recType not in self.recTypeDict:  | 
|             return 0  | 
|         playerRecDataDict = self.recTypeDict[recType]  | 
|         recDataList = playerRecDataDict.pop(delPlayerID, None)  | 
|         delCount = len(recDataList) if recDataList else 0  | 
|         GameWorld.DebugLog("ɾ³ýij¸öÍæ¼ÒÖ¸¶¨¼Ç¼ÀàÐÍ: recType=%s,delPlayerID=%s,delCount=%s" % (recType, delPlayerID, delCount))  | 
|         return delCount  | 
|       | 
|     def DelRecDataByTypeValue(self, recType, valueList, delPlayerID=None):  | 
|         ## É¾³ýij¸ö¼Ç¼ÀàÐÍÆ¥ÅäValueÖµÁбíµÄ¼Ç¼  | 
|         # @param valueList: [value1, value2, ...] valueΪNoneʱ²»ÅжϸÃÖµ  | 
|         # @param delPlayerID: ¿ÉÖ¸¶¨Ö»É¾³ýij¸öÍæ¼ÒµÄ¼Ç¼  | 
|           | 
|         if not valueList:  | 
|             return 0  | 
|         if recType not in self.recTypeDict:  | 
|             return 0  | 
|         delCountTotal = 0  | 
|         recDict = self.recTypeDict[recType]  | 
|         for playerID, recDataList in recDict.items():  | 
|             if delPlayerID and playerID != delPlayerID:  | 
|                 continue  | 
|             delCount = 0  | 
|             for recData in recDataList[::-1]: # µ¹Ðò´¦Àíɾ³ý  | 
|                 if recData.IsMatchValue(valueList):  | 
|                     recDataList.remove(recData)  | 
|                     delCount += 1  | 
|                       | 
|             if delCount:  | 
|                 delCountTotal += delCount  | 
|                 GameWorld.DebugLog("ɾ³ýij¸ö¼Ç¼ÀàÐÍËùÓÐValue1Æ¥ÅäÖµµÄ¼Ç¼: recType=%s,valueList=%s,delPlayerID=%s,delCount=%s"   | 
|                                    % (recType, valueList, playerID, delCount))  | 
|         return delCountTotal  | 
|       | 
|     def DelRecData(self, recData):  | 
|         ## É¾³ýÖ¸¶¨¼Ç¼  | 
|         playerID = recData.GetPlayerID()  | 
|         recType = recData.GetRecType()  | 
|         if recType not in self.recTypeDict:  | 
|             return 0  | 
|         playerRecDataDict = self.recTypeDict[recType]  | 
|         if playerID not in playerRecDataDict:  | 
|             return 0  | 
|         playerRecDataList = playerRecDataDict[playerID]  | 
|         if recData in playerRecDataList:  | 
|             playerRecDataList.remove(recData)  | 
|         return 1  | 
|       | 
|     def AddPlayerRecData(self, recType, playerID):  | 
|         ## Ìí¼ÓÍæ¼Ò¼Ç¼  | 
|         recData = PlayerRecData()  | 
|         recData.clear()  | 
|         recData.SetPlayerID(playerID)  | 
|         recData.SetRecType(recType)  | 
|         recData.SetTime(int(time.time()))  | 
|         self.__AddRecData(recData)  | 
|         return recData  | 
|       | 
|     def AddPlayerRecDataByDict(self, attrDict):  | 
|         ## Ò»°ãÊÇ¿ç·þͬ²½¹ýÀ´Êý¾ÝÌí¼ÓÓà  | 
|         recData = PlayerRecData()  | 
|         recData.SetAttr(attrDict, True)  | 
|         self.__AddRecData(recData)  | 
|         return recData  | 
|       | 
|     def __AddRecData(self, recData):  | 
|         playerID = recData.GetPlayerID()  | 
|         recType = recData.GetRecType()  | 
|         if recType not in self.recTypeDict:  | 
|             self.recTypeDict[recType] = {}  | 
|         playerRecDataDict = self.recTypeDict[recType]  | 
|         if playerID not in playerRecDataDict:  | 
|             playerRecDataDict[playerID] = []  | 
|         playerRecDataList = playerRecDataDict[playerID]  | 
|         playerRecDataList.append(recData)  | 
|         return  | 
|       | 
|     def GetPlayerRecDataFirst(self, recType, playerID):  | 
|         ## »ñÈ¡Íæ¼Ò¼Ç¼ÀàÐͶÔÓ¦µÄµÚÒ»Ìõ¼Ç¼£¬ÊÊÓÃÓÚ½öÐèÒ»ÌõµÄ¼Ç¼ÀàÐÍ  | 
|         recDataList = self.GetPlayerRecDataList(recType, playerID)  | 
|         if recDataList:  | 
|             recData = recDataList[0]  | 
|         else:  | 
|             recData = self.AddPlayerRecData(recType, playerID)  | 
|         return recData  | 
|   | 
|     def GetPlayerRecData(self, recType, playerID, valueList):  | 
|         ## »ñÈ¡Íæ¼Ò¼Ç¼ÀàÐͶÔÓ¦µÄijÌõ¼Ç¼  | 
|         # @param valueList: [value1, value2, ...] valueΪNoneʱ²»ÅжϸÃÖµ  | 
|         recDataList = self.GetPlayerRecDataList(recType, playerID)  | 
|         if not recDataList:  | 
|             return  | 
|         for recData in recDataList:  | 
|             if recData.IsMatchValue(valueList):  | 
|                 return recData    | 
|         return  | 
|       | 
|     def GetPlayerRecDataList(self, recType, playerID):  | 
|         ## »ñÈ¡Íæ¼Ò¼Ç¼ÀàÐͶÔÓ¦¼Ç¼Áбí [recData, ...]  | 
|         if recType not in self.recTypeDict:  | 
|             self.recTypeDict[recType] = {}  | 
|         playerRecDataDict = self.recTypeDict[recType]  | 
|         if playerID not in playerRecDataDict:  | 
|             playerRecDataDict[playerID] = []  | 
|         playerRecDataList = playerRecDataDict[playerID]  | 
|         return playerRecDataList  | 
|       | 
|     def GetPlayerRecDataDict(self, recType):  | 
|         ## »ñÈ¡¼Ç¼ÀàÐͶÔÓ¦ËùÓÐÍæ¼ÒµÄ¼Ç¼×Öµä {playerID:[recData, ...], ...}  | 
|         if recType not in self.recTypeDict:  | 
|             return {}  | 
|         return self.recTypeDict[recType]  | 
|       | 
|     def SortRecDataList(self, recDataList):  | 
|         recDataList.sort(key=lambda r: (r.GetTime()), reverse=False)  | 
|         return  | 
|       | 
|     # ±£´æÊý¾Ý ´æÊý¾Ý¿âºÍrealtimebackup  | 
|     def GetSaveData(self):  | 
|         savaData = ""  | 
|         cntData = ""  | 
|         cnt = 0  | 
|           | 
|         for playerRecDataDict in self.recTypeDict.values():  | 
|             for recDataList in playerRecDataDict.values():  | 
|                 for recData in recDataList:  | 
|                     cnt += 1  | 
|                     if recData.evalUserData != None:  | 
|                         recData.SetUserData(recData.evalUserData)  | 
|                     savaData += recData.dbRecData.getBuffer()  | 
|                       | 
|         GameWorld.Log("Save DBPlayerRecData 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 DBPlayerRecData count :%s" % cnt)  | 
|           | 
|         self.Clear()  | 
|           | 
|         for _ in xrange(cnt):  | 
|             recData = PyGameDataStruct.tagDBPlayerRecData()  | 
|             recData.clear()  | 
|             pos += recData.readData(datas, pos, dataslen)  | 
|               | 
|             self.__AddRecData(PlayerRecData(recData))  | 
|               | 
|         return pos  | 
|       | 
| PlayerRecDataTemp = PlayerRecData()  | 
|   | 
| def OnPlayerLogin(curPlayer):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     playerRecMgr = PyDataManager.GetDBPlayerRecDataManager()  | 
|     for recType in ChConfig.Def_PlayerRecLoginNotifyList:  | 
|         recDataList = playerRecMgr.GetPlayerRecDataList(recType, playerID)  | 
|         if not recDataList:  | 
|             continue  | 
|         SyncPlayerRecInfo(curPlayer, recType, recDataList)  | 
|     return  | 
|   | 
| def MapServer_AddPlayerRec(curPlayer, recType, valueList, userData="", notifyType=0):  | 
|     '''  | 
|     @todo: Ìí¼ÓÍæ¼Ò¼Ç¼  | 
|     @param recType: Í¨ÓüǼÀàÐÍ, ¶ÔÓ¦ ShareDefine.Def_PlayerRecTypeList  | 
|     @param valueList: ÊýÖµÁбí[value1, value2, ...], °´Ë³Ðò, Ö§³Övalue1 ~ value8  | 
|     @param userData: ×Ô¶¨Òå×Ö·ûÐÅÏ¢  | 
|     @param notifyType: 0-²»Í¨Öª; 1-֪ͨµ¥Ìõ; 2-֪ͨȫ²¿  | 
|     '''  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     if recType not in ShareDefine.Def_PlayerRecTypeList:  | 
|         GameWorld.ErrLog("Íæ¼Ò¼Ç¼ÀàÐÍ´íÎó: recType=%s" % recType, playerID)  | 
|         return  | 
|       | 
|     playerRecMgr = PyDataManager.GetDBPlayerRecDataManager()  | 
|     recDataList = playerRecMgr.GetPlayerRecDataList(recType, playerID)  | 
|     if recDataList and len(recDataList) >= ChConfig.Def_PlayerRecCountDict.get(recType, 50):  | 
|         playerRecMgr.SortRecDataList(recDataList)  | 
|         recDataList.pop(0) # É¾³ýµÚÒ»¸ö  | 
|           | 
|     recData = playerRecMgr.AddPlayerRecData(recType, playerID)  | 
|       | 
|     for num, value in enumerate(valueList, 1):  | 
|         if num > 8:  | 
|             break  | 
|         getattr(recData, "SetValue%s" % num)(min(ChConfig.Def_UpperLimit_DWord, value))  | 
|           | 
|     if userData:  | 
|         recData.SetUserData(userData)  | 
|           | 
|     if notifyType == 1:  | 
|         SyncPlayerRecInfo(curPlayer, recType, [recData])  | 
|     elif notifyType == 2:  | 
|         SyncPlayerRecInfo(curPlayer, recType, recDataList)  | 
|           | 
|     return recData  | 
|   | 
| def SyncPlayerRecInfo(curPlayer, recType, recDataList):  | 
|     if not recDataList:  | 
|         return  | 
|       | 
|     playerRecList = []  | 
|     for recData in recDataList:  | 
|         if not recData:  | 
|             continue  | 
|         rec = ChPyNetSendPack.tagGCPlayerRec()  | 
|         rec.Time = recData.GetTime()  | 
|         rec.Value1 = recData.GetValue1()  | 
|         rec.Value2 = recData.GetValue2()  | 
|         rec.Value3 = recData.GetValue3()  | 
|         rec.Value4 = recData.GetValue4()  | 
|         rec.Value5 = recData.GetValue5()  | 
|         rec.Value6 = recData.GetValue6()  | 
|         rec.Value7 = recData.GetValue7()  | 
|         rec.Value8 = recData.GetValue8()  | 
|         rec.UserData = recData.GetUserData()  | 
|         rec.UserDataLen = len(rec.UserData)  | 
|         playerRecList.append(rec)  | 
|           | 
|     clientPack = ChPyNetSendPack.tagGCPlayerRecInfo()  | 
|     clientPack.Clear()  | 
|     clientPack.Type = recType  | 
|     clientPack.PlayerRecList = playerRecList  | 
|     clientPack.Count = len(clientPack.PlayerRecList)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  |