| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package GameRecData  | 
| #  | 
| # @todo:ͨÓüǼ±íР | 
| # @author hxp  | 
| # @date 2024-09-04  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: Í¨ÓüǼ±íУ¬ÔͨÓüǼ×Ö·û³¤¶È¼Ç¼ÓÐÏÞ£¬ÇÒÕë¶Ôij¸ö¼Ç¼ÀàÐÍϵÄ×ÓÀàÐͲéÕÒÿ´ÎÐèÒª±éÀú£¬Ð§Âʲ»¸ß  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2024-09-04 16:30"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import GameWorld  | 
| import PyGameDataStruct  | 
| import ShareDefine  | 
| import CommFunc  | 
|   | 
| import time  | 
|   | 
| class GameRecData():  | 
|       | 
|     def __init__(self, dbRecData=None):  | 
|         if not dbRecData:  | 
|             dbRecData = PyGameDataStruct.tagDBGameRec()  | 
|         self.dbRecData = dbRecData  | 
|         self.__userDataDict = None  | 
|         self.__userDataChange = False  | 
|         return  | 
|     def clear(self):  | 
|         self.dbRecData.clear()  | 
|         self.__userDataDict = None  | 
|         self.__userDataChange = False  | 
|         return  | 
|     def GetRecType(self): return self.dbRecData.RecType  | 
|     def SetRecType(self, recType): self.dbRecData.RecType = recType  | 
|     def GetRecID(self): return self.dbRecData.RecID  | 
|     def SetRecID(self, recID): self.dbRecData.RecID = recID  | 
|     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 __GetUserDataDict(self):  | 
|         if self.__userDataDict == None:  | 
|             try:  | 
|                 self.__userDataDict = eval(self.dbRecData.UserData)  | 
|             except:  | 
|                 self.__userDataDict = {}  | 
|         return self.__userDataDict  | 
|     def GetUserDataByKey(self, key, defaultValue=None):  | 
|         userDataDict = self.__GetUserDataDict()  | 
|         if key in userDataDict:  | 
|             return userDataDict[key]  | 
|         return defaultValue  | 
|     def SetUserDataByKey(self, key, value):  | 
|         userDataDict = self.__GetUserDataDict()  | 
|         userDataDict[key] = value  | 
|         self.__userDataChange = True  | 
|         return  | 
|     def GetUserData(self):  | 
|         if self.__userDataChange:  | 
|             self.SaveUserData()  | 
|         return self.dbRecData.UserData  | 
|     def SetUserData(self, userData):  | 
|         ## Ö§³ÖÖ±½Ó±£´æÈÎÒâ¸ñʽÊý¾Ý£¬»òÕß°´×ֵ䷽ʽ¶ÁÈ¡kvÖµ  | 
|         if type(userData) != str:  | 
|             userData = str(userData)  | 
|         self.dbRecData.UserData = userData.replace(" ", "")  | 
|         self.dbRecData.UserDataLen = len(self.dbRecData.UserData)  | 
|         self.__userDataDict = None  | 
|         self.__userDataChange = False  | 
|         return  | 
|     def SaveUserData(self):  | 
|         if self.__userDataChange:  | 
|             self.SetUserData(self.__userDataDict)  | 
|         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 {"RecID":self.GetRecID(), "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(),   | 
|                 "UserDataDict":self.__GetUserDataDict()  | 
|                 }  | 
|     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)  | 
|             elif k == "UserDataDict":  | 
|                 self.__userDataDict = v  | 
|         return  | 
|       | 
| class DBGameRecDataManager():  | 
|     ## Í¨ÓüǼ¹ÜÀí  | 
|       | 
|     def __init__(self):  | 
|         self.Clear()  | 
|         return  | 
|       | 
|     def Clear(self):  | 
|         self.recTypeDict = {} # {recType:{recID:[GameRecData, ...], ...}}  | 
|         self.recValueIndexDict = {} # {recType:{recID:{indexKey:[GameRecData, ...], ...}, ...}, ...}  | 
|         return  | 
|       | 
|     def DelGameRecDataByType(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))  | 
|         self.recValueIndexDict.pop(recType, {})  | 
|         return delCount  | 
|       | 
|     def DelGameRecDataByTypeID(self, recType, delRecID):  | 
|         ## É¾³ýij¸öÀàÐͶÔÓ¦µÄID¼Ç¼  | 
|         if recType not in self.recTypeDict:  | 
|             return 0  | 
|         recDataDict = self.recTypeDict[recType]  | 
|         recDataList = recDataDict.pop(delRecID, None)  | 
|         delCount = len(recDataList) if recDataList else 0  | 
|         GameWorld.DebugLog("ɾ³ýÖ¸¶¨ÐÂͨÓüǼÀàÐÍij¸ö¼Ç¼IDËùÓмǼ: recType=%s,delRecID=%s,delCount=%s" % (recType, delRecID, delCount))  | 
|         if recType in self.recValueIndexDict:  | 
|             recIndexDataDict = self.recValueIndexDict[recType]  | 
|             recIndexDataDict.pop(delRecID, None)  | 
|         return delCount  | 
|       | 
|     def DelGameRecDataByTypeValue(self, recType, valueList, delRecID=None):  | 
|         ## É¾³ýij¸ö¼Ç¼ÀàÐÍÆ¥ÅäValueÖµÁбíµÄ¼Ç¼  | 
|         # @param valueList: [value1, value2, ...] valueΪNoneʱ²»ÅжϸÃÖµ  | 
|         # @param delRecID: ¿ÉÖ¸¶¨Ö»É¾³ý¼Ç¼IDµÄ¼Ç¼  | 
|           | 
|         if not valueList:  | 
|             return 0  | 
|         if recType not in self.recTypeDict:  | 
|             return 0  | 
|         delCountTotal = 0  | 
|         recDict = self.recTypeDict[recType]  | 
|         for recID, recDataList in recDict.items():  | 
|             if delRecID and recID != delRecID:  | 
|                 continue  | 
|             delCount = 0  | 
|             for recData in recDataList[::-1]: # µ¹Ðò´¦Àíɾ³ý  | 
|                 if recData.IsMatchValue(valueList):  | 
|                     delCount += self.DelGameRecData(recData)  | 
|                       | 
|             if delCount:  | 
|                 delCountTotal += delCount  | 
|                 GameWorld.DebugLog("ɾ³ýij¸öÐÂͨÓüǼÀàÐÍËùÓÐValue1Æ¥ÅäÖµµÄ¼Ç¼: recType=%s,valueList=%s,delRecID=%s,delCount=%s"   | 
|                                    % (recType, valueList, recID, delCount))  | 
|         return delCountTotal  | 
|       | 
|     def DelGameRecData(self, recData):  | 
|         ## É¾³ýÖ¸¶¨¼Ç¼  | 
|         recID = recData.GetRecID()  | 
|         recType = recData.GetRecType()  | 
|         if recType not in self.recTypeDict:  | 
|             return 0  | 
|         recDataDict = self.recTypeDict[recType]  | 
|         if recID not in recDataDict:  | 
|             return 0  | 
|         recDataList = recDataDict[recID]  | 
|         if recData in recDataList:  | 
|             recDataList.remove(recData)  | 
|               | 
|         keyStr = self.__GetValueIndexKey(recData)  | 
|         if keyStr:  | 
|             recIndexDataDict = self.recValueIndexDict.get(recType, {})  | 
|             valueIndexDict = recIndexDataDict.get(recID, {})  | 
|             recIndexDataList = valueIndexDict.get(keyStr, [])  | 
|             if recData in recIndexDataList:  | 
|                 recIndexDataList.remove(recData)  | 
|         return 1  | 
|       | 
|     def AddGameRecData(self, recType, recID, valueSetList=None, maxCount=0):  | 
|         '''Ìí¼Ó¼Ç¼  | 
|         @param recType: ¼Ç¼ÀàÐÍ  | 
|         @param recID: ¼Ç¼ÀàÐͶÔÓ¦µÄ×ÓID£¬±ÈÈç¿ÉÒÔÊÇÍæ¼ÒID»òÕ߯äËû×Ô¶¨µÄID£¬¸ÃIDÔÚͬ¸ö¼Ç¼ÀàÐÍÖÐΨһ£¬²»Í¬¼Ç¼ÀàÐÍ¿ÉÖØ¸´  | 
|         @param valueList: [value1, value2, ...] ÉèÖõÄValueÖµÁÐ±í  | 
|         @param maxCount: Ã¿ÖּǼID×î´ó¿É±£´æ¼Ç¼ÌõÊý£¬Ä¬ÈÏ0²»ÏÞÖÆ  | 
|         '''  | 
|         recData = GameRecData()  | 
|         recData.clear()  | 
|         recData.SetRecType(recType)  | 
|         recData.SetRecID(recID)  | 
|         recData.SetTime(int(time.time()))  | 
|         if valueSetList:  | 
|             for num, v in enumerate(valueSetList, 1):  | 
|                 if not hasattr(recData, "SetValue%s" % num):  | 
|                     continue  | 
|                 getattr(recData, "SetValue%s" % num)(v)  | 
|         recDataList = self.__AddGameRecData(recData)  | 
|           | 
|         doCount = len(recDataList)  | 
|         while maxCount and len(recDataList) > maxCount and doCount > 0:  | 
|             GameWorld.DebugLog("³¬¹ý¼Ç¼ÉÏÏÞɾ³ý¼Ç¼: recType=%s,recID=%s,recCount=%s,maxCount=%s" % (recType, recID, len(recDataList), maxCount))  | 
|             doCount -= 1  | 
|             self.DelGameRecData(recDataList[0]) # ³¬¹ý×î´óÉÏÏÞ£¬É¾³ýµÚÒ»¸ö  | 
|               | 
|         return recData  | 
|       | 
|     def AddGameRecDataByDict(self, attrDict):  | 
|         ## Ò»°ãÊÇ¿ç·þͬ²½¹ýÀ´Êý¾ÝÌí¼ÓÓà  | 
|         recData = GameRecData()  | 
|         recData.SetAttr(attrDict, True)  | 
|         self.__AddGameRecData(recData)  | 
|         return recData  | 
|       | 
|     def __AddGameRecData(self, recData):  | 
|         recID = recData.GetRecID()  | 
|         recType = recData.GetRecType()  | 
|         if recType not in self.recTypeDict:  | 
|             self.recTypeDict[recType] = {}  | 
|         recDataDict = self.recTypeDict[recType]  | 
|         if recID not in recDataDict:  | 
|             recDataDict[recID] = []  | 
|         recDataList = recDataDict[recID]  | 
|         recDataList.append(recData)  | 
|           | 
|         keyStr = self.__GetValueIndexKey(recData)  | 
|         if keyStr:  | 
|             if recType not in self.recValueIndexDict:  | 
|                 self.recValueIndexDict[recType] = {}  | 
|             recIndexDataDict = self.recValueIndexDict[recType]  | 
|             if recID not in recIndexDataDict:  | 
|                 recIndexDataDict[recID] = {}  | 
|             valueIndexDict = recIndexDataDict[recID]  | 
|             if keyStr not in valueIndexDict:  | 
|                 valueIndexDict[keyStr] = []  | 
|             recIndexDataList = valueIndexDict[keyStr]  | 
|             recIndexDataList.append(recData)  | 
|         return recDataList  | 
|       | 
|     def __GetValueIndexKey(self, recData):  | 
|         ## »ñÈ¡¼Ç¼¶ÔÏó¶ÔÓ¦×ÖµäkeyÖµ£¬Ä¬ÈÏʹÓÃvalue1  | 
|         recType = recData.GetRecType()  | 
|         if recType not in ShareDefine.Def_GameRecValueKeyDict:  | 
|             return  | 
|         valueNumList = ShareDefine.Def_GameRecValueKeyDict[recType]  | 
|         if not valueNumList:  | 
|             valueNumList = [1]  | 
|         keyStr = ""  | 
|         for num in valueNumList:  | 
|             if not hasattr(recData, "GetValue%s" % num):  | 
|                 return  | 
|             if keyStr:  | 
|                 keyStr += "_"  | 
|             keyStr += str(getattr(recData, "GetValue%s" % num)())  | 
|         return keyStr  | 
|       | 
|     def GetGameRecDataMatch(self, recType, recID, valueList, findone=False):  | 
|         '''»ñÈ¡¼Ç¼ÀàÐͶÔÓ¦µÄÆ¥ÅävalueÖµ¼Ç¼  | 
|         @param recType: ¼Ç¼ÀàÐÍ  | 
|         @param recID: ¼Ç¼ÀàÐͶÔÓ¦µÄ×ÓID  | 
|         @param valueList: [value1, value2, ...] valueΪNoneʱ²»ÅжϸÃÖµ  | 
|         @param findone: ÊÇ·ñֻƥÅäÒ»ÌõÂú×ãµÄ¼Ç¼  | 
|         @return: recData or [recData, ...] or None  | 
|         '''  | 
|           | 
|         # ÓÐÅäÖÃvalueË÷ÒýkeyµÄ£¬Ö±½Ó¿ìËÙ»ñÈ¡  | 
|         if recType in ShareDefine.Def_GameRecValueKeyDict:  | 
|             if recType not in self.recValueIndexDict:  | 
|                 return  | 
|             recIndexDataDict = self.recValueIndexDict[recType]  | 
|             if recID not in recIndexDataDict:  | 
|                 return  | 
|             valueIndexDict = recIndexDataDict[recID]  | 
|             keyStr = ""  | 
|             for v in valueList:  | 
|                 if keyStr:  | 
|                     keyStr += "_"  | 
|                 keyStr += str(v)  | 
|             if keyStr not in valueIndexDict:  | 
|                 return  | 
|             recIndexDataList = valueIndexDict[keyStr]  | 
|             if not recIndexDataList:  | 
|                 return  | 
|             return recIndexDataList[0] if findone else recIndexDataList  | 
|           | 
|         # Ã»ÓеÄÔò±éÀúÆ¥Åä  | 
|         recDataList = self.GetGameRecDataList(recType, recID)  | 
|         if not recDataList:  | 
|             return  | 
|         matchRecDataList = []  | 
|         for recData in recDataList:  | 
|             if not recData.IsMatchValue(valueList):  | 
|                 continue  | 
|             if findone:  | 
|                 return recData  | 
|             matchRecDataList.append(recData)  | 
|         return matchRecDataList  | 
|       | 
|     def GetGameRecDataList(self, recType, recID):  | 
|         ## »ñÈ¡¼Ç¼ÀàÐͶÔÓ¦¼Ç¼Áбí [recData, ...]  | 
|         if recType not in self.recTypeDict:  | 
|             self.recTypeDict[recType] = {}  | 
|         recDataDict = self.recTypeDict[recType]  | 
|         if recID not in recDataDict:  | 
|             recDataDict[recID] = []  | 
|         recDataList = recDataDict[recID]  | 
|         return recDataList  | 
|       | 
|     def GetGameRecDataDict(self, recType):  | 
|         ## »ñÈ¡¼Ç¼ÀàÐͶÔÓ¦ËùÓмǼ×Öµä {recID:[recData, ...], ...}  | 
|         if recType not in self.recTypeDict:  | 
|             return {}  | 
|         return self.recTypeDict[recType]  | 
|       | 
|     def SortGameRecDataList(self, recDataList):  | 
|         recDataList.sort(key=lambda r: (r.GetTime()), reverse=False)  | 
|         return  | 
|       | 
|     # ±£´æÊý¾Ý ´æÊý¾Ý¿âºÍrealtimebackup  | 
|     def GetSaveData(self):  | 
|         savaData = ""  | 
|         cntData = ""  | 
|         cnt = 0  | 
|           | 
|         for recDataDict in self.recTypeDict.values():  | 
|             for recDataList in recDataDict.values():  | 
|                 for recData in recDataList:  | 
|                     cnt += 1  | 
|                     recData.SaveUserData()  | 
|                     savaData += recData.dbRecData.getBuffer()  | 
|                       | 
|         GameWorld.Log("Save DBGameRec 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 DBGameRec count :%s" % cnt)  | 
|           | 
|         self.Clear()  | 
|           | 
|         for _ in xrange(cnt):  | 
|             recData = PyGameDataStruct.tagDBGameRec()  | 
|             recData.clear()  | 
|             pos += recData.readData(datas, pos, dataslen)  | 
|               | 
|             self.__AddGameRecData(GameRecData(recData))  | 
|               | 
|         # °´Ê±¼äÉýÐòÅÅÐòÏ  | 
|         for recDataDict in self.recTypeDict.values():  | 
|             for recDataList in recDataDict.values():  | 
|                 recDataList.sort(key=lambda d: (d.GetTime()))  | 
|         return pos  | 
|       | 
| GameRecDataTemp = GameRecData()  | 
|   | 
|   |