| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #  | 
| #  | 
| ##@package PlayerCompensation.py  | 
| #  | 
| # @todo:Óʼþ¹ÜÀí£¨²¹³¥£©  | 
| #        1. È«·þÓʼþÒ»¸öGUIDÒ»·âÓʼþ£¬ÓÐʱ¼äÏÞÖÆ£¬½ÓÊÕÓʼþµÄ³ÖÐøÊ±¼äºÍÑÓ³Ùɾ³ýʱ¼äµã(¿É½ÓÊÕºóµÄXÌìɾ³ýÓʼþ)  | 
| #           ±íʾÈç¹ûÈ«·þÓʼþÒѾ֪ͨ¹ýij¸öÍæ¼Ò£¬ÄÇô¶ÔÓÚ¸ÃÍæ¼Ò£¬¼´Ê¹Óʼþ¹ýÆÚÍæ¼ÒûÓÐÖ÷¶¯É¾³ýÓʼþ£¬Ò²Ó¦¸Ã֪ͨ¸ÃÍæ¼Ò  | 
| #        2. ¸öÈËÓʼþÒ»¸öGUID¿ÉÒÔÊǸöÈË»òÕß¶àÈËÓʼþ£¬µ«ÊǶàÈËÓʼþ²»Ö§³ÖÅäÖÿÉÁìÈ¡µÄ³ÖÐøÊ±¼ä£¬ÈôÒªÖ§³ÖÐèÐÞ¸ÄÁìÈ¡¼Ç¼Âß¼  | 
| #        3. ¸öÈËÓʼþ°´ÀàÐÍ·Ö²»Í¬µÄ¿É±£´æÊýÁ¿£¬Íæ¼Ò²»¸ÐÖª  | 
| #        4. ¹ØÓÚÓʼþ·¢¼þÈË ±êÌ⠺͠ÕýÎÄ£¬Èç¹ûÊÇÄ£°å»òÕß×éºÏÐÅÏ¢À࣬¶¼Ó¦¸ÃÓÉǰ¶Ë×éÖ¯Íê³É£¬ºó¶Ëֻȡģ°å±êʶ  | 
| #        5. ¿ÉÁìÈ¡¼´ÒÑ֪ͨ¹ýÍæ¼Ò¸Ã·âÓʼþ£¬ÐèÒªÔÚÓʼþ·¢ÉúʱºÍÉÏÏßʱÉèÖÃ״̬  | 
| #  | 
| # @author alee  | 
| # @date 2017-08-11 20:00  | 
| # @version 1.1  | 
| # @note:  | 
| # @change: "2018-08-10 12:00" hxp È«·þÓʼþÔö¼ÓÉý¼¶ºóÊÇ·ñ¿ÉÁìȡѡÏîÉèÖã¬Ôö¼ÓÓʼþ²éѯ¡¢Í¨¹ýÉóºË¡¢É¾³ý¹¦ÄÜ£»  | 
| #------------------------------------------------------------------------------   | 
| #"""Version = 2018-08-10 12:00"""  | 
| #------------------------------------------------------------------------------   | 
| import GameWorld  | 
| import ChConfig  | 
| import ShareDefine  | 
| import IPY_GameServer  | 
| import ChGameToMapPyPack  | 
| import NetPackCommon  | 
| import CommFunc  | 
| import ChPyNetSendPack  | 
| import PyGameDataStruct  | 
| import CrossRealmMsg  | 
| import DataRecordPack  | 
| import ReadChConfig  | 
| import PlayerDBOper  | 
| import EventReport  | 
| import IpyGameDataPY  | 
| import PlayerControl  | 
| import PyDataManager  | 
| import PyGameData  | 
| import datetime  | 
| import uuid  | 
| import math  | 
| import json  | 
| #Áìȡ״̬  ¸öλÊý±êʶ £¨¿ÉÁìÈ¡¼´ÒÑ֪ͨ¹ýÍæ¼Ò¸Ã·âÓʼþ£¬ÐèÒªÔÚÓʼþ·¢ÉúʱºÍÉÏÏßʱÉèÖÃ״̬  | 
| #0 Î´Í¨Öª£¬1 ²»¿ÉÁìÈ¡£¬ 2 ¿ÉÁìÈ¡£¬ 3 ÒÑÁìÈ¡£¬4 ÒÑɾ³ý  | 
| (  | 
| Unknown_State,  | 
| Disable_State,  | 
| Enable_State,  | 
| Yet_State,  | 
| Del_State  | 
| ) = range(5)  | 
|   | 
| CheckState_OK = 0 # ÒÑÉóºË  | 
| CheckState_No = 1 # Î´ÉóºË  | 
|   | 
| LimitLVType_Not = 0 # Éý¼¶Âú×ãÁìÈ¡µÈ¼¶ºó²»¿ÉÁì  | 
| LimitLVType_Can = 1 # Éý¼¶Âú×ãÁìÈ¡µÈ¼¶ºó¿ÉÁì  | 
|   | 
| #Áìȡ״̬  Ê®Î»Êý±êʶ  | 
| (  | 
| Read_State_No,  # Óʼþδ¶Á  | 
| Read_State_Yes  # ÓʼþÒѶÁ  | 
| ) = range(2)  | 
|   | 
| #Áìȡ״̬  | 
| (  | 
| Entire_CompensationType,    #È«·þ  | 
| Personal_CompensationType,  #¸öÈË  | 
| Unknow_CompensationType     #δ֪  | 
| ) = range(3)  | 
|   | 
| Def_RequestState = "CompensationRequestState"  | 
|   | 
| #==================================================================================================  | 
| class CrossPersonalCompensationManager(object):  | 
|     ## ¿ç·þÓʼþ¹ÜÀí£¬×¢Òâ¸ÃÀàÖ»´¦ÀíÊý¾ÝÂß¼£¬¹¦ÄÜÏà¹ØÂß¼²»ÒªÐ´ÔÚ¸ÃÀ࣬²»È»ÖضÁ½Å±¾²»»áÉúЧ  | 
|       | 
|     def __init__(self):  | 
|         self.playerMailDict = {} # Íæ¼Ò²¹³¥Áбí {playerID:{GUID:tagDBCrossPersonalCompensation, ...}, ...}  | 
|         return  | 
|       | 
|     # ±£´æÊý¾Ý ´æÊý¾Ý¿âºÍrealtimebackup  | 
|     def GetSaveData(self):  | 
|         savaData = ""  | 
|         cntData = ""  | 
|         cnt = 0  | 
|         for mailDict in self.playerMailDict.values():  | 
|             for mailObj in mailDict.values():  | 
|                 cnt += 1  | 
|                 savaData += mailObj.getBuffer()  | 
|                   | 
|         GameWorld.Log("Save DBCrossPersonalCompensation 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 DBCrossPersonalCompensation count :%s" % cnt)  | 
|           | 
|         for _ in xrange(cnt):  | 
|             mailObj = PyGameDataStruct.tagDBCrossPersonalCompensation()  | 
|             mailObj.clear()  | 
|             pos += mailObj.readData(datas, pos, dataslen)  | 
|               | 
|             playerID = mailObj.PlayerID  | 
|             guid = mailObj.GUID  | 
|             if playerID not in self.playerMailDict:  | 
|                 self.playerMailDict[playerID] = {}  | 
|             mailDict = self.playerMailDict[playerID]  | 
|             mailDict[guid] = mailObj  | 
|               | 
|         return pos  | 
|       | 
| def Sync_CrossMailPlayerIDToClientServer(serverGroupID=0):  | 
|     ''' Í¬²½Óпç·þÓʼþµÄÍæ¼ÒIDµ½×Ó·þ  | 
|     @param serverGroupID: Îª0ʱͬ²½ËùÓÐ×Ó·þ  | 
|     '''  | 
|     crossMailMgr = PyDataManager.GetCrossPersonalCompensationManager()  | 
|     addMailPlayerIDList = crossMailMgr.playerMailDict.keys()  | 
|     if not addMailPlayerIDList:  | 
|         return  | 
|     # Í¬²½×Ó·þÎñÆ÷  | 
|     serverGroupIDList = [serverGroupID] if serverGroupID else []  | 
|     dataMsg = {"IDType":"Add", "PlayerIDList":addMailPlayerIDList}  | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_MailPlayerIDList, dataMsg, serverGroupIDList)  | 
|     return  | 
|   | 
| def CrossServerMsg_MailPlayerIDList(dataMsg):  | 
|     ## ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½Óпç·þÓʼþµÄÍæ¼ÒIDÁÐ±í  | 
|     idType = dataMsg["IDType"]  | 
|     playerIDList = dataMsg["PlayerIDList"]  | 
|     for playerID in playerIDList:  | 
|         if idType == "Del":  | 
|             if playerID in PyGameData.g_crossMailPlayerDict:  | 
|                 PyGameData.g_crossMailPlayerDict.pop(playerID)  | 
|             continue  | 
|           | 
|         if idType == "Add":  | 
|             if playerID in PyGameData.g_crossMailPlayerDict:  | 
|                 continue  | 
|             PyGameData.g_crossMailPlayerDict[playerID] = 0  | 
|               | 
|             player = GameWorld.GetPlayerManager().FindPlayerByID(playerID)  | 
|             if not player or not player.GetInitOK():  | 
|                 continue  | 
|             RequestToGetCrossMail(player)  | 
|               | 
|     return  | 
|   | 
| def RequestToGetCrossMail(curPlayer):  | 
|     ## ÇëÇóͬ²½¿ç·þÓʼþÄÚÈÝ  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     if playerID not in PyGameData.g_crossMailPlayerDict:  | 
|         return  | 
|     lastTick = PyGameData.g_crossMailPlayerDict[playerID]  | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     if tick - lastTick <= 30000:  | 
|         return  | 
|     PyGameData.g_crossMailPlayerDict[playerID] = tick  | 
|     dataMsg = {"CMD":"Get", "PlayerID":playerID}  | 
|     CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_MailContent, dataMsg)  | 
|     return  | 
|   | 
| def ClientServerMsg_MailContent(serverGroupID, msgData, tick):  | 
|     ## ÊÕµ½×Ó·þÍæ¼ÒÇëÇóͬ²½¿ç·þÓʼþ  | 
|       | 
|     GameWorld.Log("ÊÕµ½×Ó·þÍæ¼Òͬ²½¸öÈËÓʼþÃüÁî: serverGroupID=%s, %s" % (serverGroupID, msgData))  | 
|       | 
|     reqCMD = msgData["CMD"]  | 
|     playerID = msgData["PlayerID"]  | 
|     guidList = msgData.get("GuidList", [])  | 
|     crossMailMgr = PyDataManager.GetCrossPersonalCompensationManager()  | 
|     if playerID not in crossMailMgr.playerMailDict:  | 
|         return  | 
|     playerMailDict = crossMailMgr.playerMailDict[playerID]  | 
|       | 
|     if reqCMD == "Get":  | 
|         SyncTickAttrKey = "SyncTick"  | 
|         getMailList = []  | 
|         for guid, mailObj in playerMailDict.items():  | 
|             if hasattr(mailObj, SyncTickAttrKey):  | 
|                 getTick = getattr(mailObj, SyncTickAttrKey)  | 
|                 if tick - getTick <= 30000:  | 
|                     GameWorld.DebugLog("¶Ìʱ¼äÄÚÖØ¸´ÇëÇóÁìÈ¡µÄÓʼþ²»Í¬²½£¬·ÀÖ¹ÖØ¸´·¢·Å! GUID=%s" % guid)  | 
|                     continue  | 
|             setattr(mailObj, SyncTickAttrKey, tick)  | 
|             crossMailDict = {"PlayerID":mailObj.PlayerID, "GUID":mailObj.GUID, "LimitTime":mailObj.LimitTime,  | 
|                              "Text":mailObj.Text, "ItemInfo":mailObj.ItemInfo, "Detail":mailObj.Detail,  | 
|                              "Gold":mailObj.Gold, "GoldPaper":mailObj.GoldPaper, "Silver":mailObj.Silver,  | 
|                              "MoneySource":mailObj.MoneySource  | 
|                              }  | 
|             getMailList.append(crossMailDict)  | 
|               | 
|         if getMailList:  | 
|             CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_MailContent, getMailList, [serverGroupID])  | 
|               | 
|     elif reqCMD == "GetOK":  | 
|           | 
|         for guid in guidList:  | 
|             playerMailDict.pop(guid, None)  | 
|             DataRecordPack.DR_GiveCompensationSuccess(playerID, guid)  | 
|               | 
|         if not playerMailDict:  | 
|             crossMailMgr.playerMailDict.pop(playerID, None)  | 
|             dataMsg = {"IDType":"Del", "PlayerIDList":[playerID]}  | 
|             CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_MailPlayerIDList, dataMsg, [serverGroupID])  | 
|               | 
|     return  | 
|   | 
| def CrossServerMsg_MailContent(getMailList):  | 
|     ## ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄ´ý·¢ËÍÓʼþÄÚÈÝ  | 
|       | 
|     playerGetGUIDInfo = {}  | 
|     for mailDict in getMailList:  | 
|         GUID = mailDict.get("GUID", "")  | 
|         playerID = mailDict.get("PlayerID", 0)  | 
|         if not GUID or not playerID:  | 
|             continue  | 
|           | 
|         GameWorld.Log("ÊÕµ½¿ç·þ¸öÈËÓʼþÄÚÈÝ£º%s" % mailDict, playerID)  | 
|           | 
|         addItemDictList = eval(mailDict.get("ItemInfo", "[]"))  | 
|         LimitTime = mailDict.get("LimitTime", "")  | 
|         Text = mailDict.get("Text", "")  | 
|         gold = GameWorld.ToIntDef(mailDict.get("Gold"))  | 
|         goldPaper = GameWorld.ToIntDef(mailDict.get("GoldPaper"))  | 
|         silver = GameWorld.ToIntDef(mailDict.get("Silver"))  | 
|         moneySource = GameWorld.ToIntDef(mailDict.get("MoneySource"), ChConfig.Def_GiveMoney_Mail)  | 
|         detail = mailDict.get("Detail", "")  | 
|           | 
|         AddPersonalItem(GUID, addItemDictList, [playerID], LimitTime, Text, gold, goldPaper, silver, detail, moneySource)  | 
|           | 
|         if playerID not in playerGetGUIDInfo:  | 
|             playerGetGUIDInfo[playerID] = []  | 
|         guidList = playerGetGUIDInfo[playerID]  | 
|         guidList.append(GUID)  | 
|           | 
|     for playerID, guidList in playerGetGUIDInfo.items():  | 
|         dataMsg = {"CMD":"GetOK", "PlayerID":playerID, "GuidList":guidList}  | 
|         CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_MailContent, dataMsg)  | 
|           | 
|     return  | 
|   | 
| def __AddPlayerCrossMail(addItemDictList, PlayerIDList, LimitTime, Text, gold, goldPaper, silver, detail, moneySource):  | 
|     ## Ìí¼Ó¿ç·þÍæ¼Ò¸öÈ˲¹³¥Óʼþ  | 
|       | 
|     addMailPlayerIDList = []  | 
|     crossMailMgr = PyDataManager.GetCrossPersonalCompensationManager()  | 
|     for playerID in PlayerIDList:  | 
|         GUID = str(uuid.uuid1()) # ÓÉÓÚ¿ç·þÓʼþÓÉÿ¸öÍæ¼Ò¶À×Ôͬ²½¸öÈËÓʼþ£¬ËùÒÔ²åÈëʱÿ¸öÈ˵ÄÓʼþµ¥¶ÀGUID£¬·ÀÖ¹ÅúÁ¿·¢ËÍͬÄÚÈÝÓʼþÊ±ÖØ¸´²åÈë½±ÀøÎïÆ·  | 
|         mailObj = PyGameDataStruct.tagDBCrossPersonalCompensation()  | 
|         mailObj.PlayerID = playerID  | 
|         mailObj.GUID = GUID  | 
|         mailObj.LimitTime = LimitTime  | 
|         mailObj.Text = Text  | 
|         mailObj.TextLen = len(mailObj.Text)  | 
|         mailObj.Gold = gold  | 
|         mailObj.GoldPaper = goldPaper  | 
|         mailObj.Silver = silver  | 
|         mailObj.ItemInfo = json.dumps(addItemDictList, ensure_ascii=False)  | 
|         mailObj.ItemLen = len(mailObj.ItemInfo)  | 
|         mailObj.Detail = detail  | 
|         mailObj.DetailLen = len(mailObj.Detail)  | 
|         mailObj.MoneySource = moneySource  | 
|           | 
|         if playerID not in crossMailMgr.playerMailDict:  | 
|             crossMailMgr.playerMailDict[playerID] = {}  | 
|             addMailPlayerIDList.append(playerID)  | 
|         playerMailDict = crossMailMgr.playerMailDict[playerID]  | 
|         playerMailDict[GUID] = mailObj  | 
|           | 
|         #Ìí¼ÓÁ÷Ïò  | 
|         addDict = {"LimitTime":LimitTime, "Text":Text, "Gold":gold, "GoldPaper":goldPaper, "Silver":silver,   | 
|                    "ItemListLen":len(addItemDictList), "Detail":detail, "MoneySource":moneySource, "CrossMail":True}  | 
|         DataRecordPack.DR_AddPersonalCompensation(PlayerIDList, GUID, addItemDictList, addDict)  | 
|       | 
|     if addMailPlayerIDList:  | 
|         dataMsg = {"IDType":"Add", "PlayerIDList":addMailPlayerIDList}  | 
|         CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_MailPlayerIDList, dataMsg)  | 
|           | 
|     return  | 
|   | 
| #==================================================================================================  | 
| ## ¸ù¾ÝÎïÆ·ÐÅÏ¢×ֵ䣬Éú³É²¹³¥ÎïÆ·ÊµÀý£¬ÓÃÓÚGM¹¤¾ßÌí¼Ó²¹³¥  | 
| #  @param curItemDict   | 
| #  @return IpyCompensationItem  | 
| def MakeCompensationItem(curItemDict):  | 
|     if not __checkMailItemDict(curItemDict):  | 
|         return  | 
|     curItemData = IPY_GameServer.IpyCompensationItem()  | 
|     #curItemData.GUID = curItemDict['GUID']  | 
|     curItemData.ItemID = curItemDict['ItemID']  | 
|     curItemData.Count = curItemDict['Count']  | 
|     #curItemData.IsBind = curItemDict.get('IsBind',0)  | 
|     curItemData.IsBind = curItemDict.get('IsAuctionItem',0)  | 
|     curItemData.UserData = curItemDict.get('UserData', '')  | 
|     return curItemData  | 
|   | 
| #  ´Ë´¦»õ±ÒplayerIDList·¢·Åͳһ£¬Èç¸ù¾ÝÍæ¼Ò²»Í¬¶ø±ä£¬ÔòÓ¦ÐèÐÞ¸Ä  | 
| ## ¹¦ÄÜ·¢·ÅÎïÆ·²¹³¥/½±ÀøÓʼþ  | 
| #  @param addItemList [(itemID, itemCnt, ÊÇ·ñÅÄÆ·), {»òÎïÆ·ÐÅÏ¢×Öµä}, ...]  | 
| #  @return GUID  | 
| def SendPersonalItemMailEx(title, content, getDays, playerIDList, addItemList, gold = 0, goldPaper = 0, silver = 0,   | 
|                            detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):  | 
|     limitTime = str(GameWorld.GetDatetimeByDiffDays(getDays))  | 
|     limitTime = limitTime.split(".")[0]  | 
|     return SendPersonalItemMail(title, content, limitTime, playerIDList, addItemList, gold, goldPaper, silver, detail, moneySource, crossMail)  | 
|       | 
| def SendPersonalItemMailBatch(batchMailInfoList):  | 
|     ## ÅúÁ¿·¢ËÍÓʼþ  | 
|     mailTypeKey, batchPlayerIDList, batchAddItemList, batchParamList, batchGold, batchGoldPaper, batchSilver, batchDetail, moneySource, crossMail = batchMailInfoList  | 
|       | 
|     lenPlayerID = len(batchPlayerIDList)  | 
|     lenItem = len(batchAddItemList)  | 
|     lenParam = len(batchParamList)  | 
|     lenGold = len(batchGold)  | 
|     lenGoldPaper = len(batchGoldPaper)  | 
|     lenSilver = len(batchSilver)  | 
|     lenDetail = len(batchDetail)  | 
|       | 
|     title = ""  | 
|     getDays = 30  | 
|     limitTime = str(GameWorld.GetDatetimeByDiffDays(getDays))  | 
|     limitTime = limitTime.split(".")[0]  | 
|       | 
|     for i, playerIDList in enumerate(batchPlayerIDList):  | 
|         if not playerIDList:  | 
|             continue  | 
|         addItemList = batchAddItemList[i] if lenItem == lenPlayerID else []  | 
|         paramList = batchParamList[i] if lenParam == lenPlayerID else []  | 
|         gold = batchGold[i] if lenGold == lenPlayerID else 0  | 
|         goldPaper = batchGoldPaper[i] if lenGoldPaper == lenPlayerID else 0  | 
|         silver = batchSilver[i] if lenSilver == lenPlayerID else 0  | 
|         detail = batchDetail[i] if lenDetail == lenPlayerID else ""  | 
|         content = "<MailTemplate>%s</MailTemplate>%s" % (mailTypeKey, str(paramList))  | 
|         SendPersonalItemMail(title, content, limitTime, playerIDList, addItemList, gold, goldPaper, silver, detail=detail, moneySource=moneySource, crossMail=crossMail)  | 
|           | 
|     return  | 
|   | 
| def SendMailByKey(mailTypeKey, playerIDList, addItemList, paramList=[], gold=0, goldPaper=0, silver=0,   | 
|                   detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):  | 
|     if not mailTypeKey:  | 
|         mailTypeKey = ShareDefine.DefaultLackSpaceMailType  | 
|     GameWorld.DebugLog("SendMailByKey %s, playerIDList=%s, addItemList=%s, paramList=%s, gold=%s, goldPaper=%s, silver=%s, moneySource=%s"   | 
|                        % (mailTypeKey, playerIDList, addItemList, paramList, gold, goldPaper, silver, moneySource))  | 
|     title = ""  | 
|     content = "<MailTemplate>%s</MailTemplate>%s" % (mailTypeKey, json.dumps(paramList, ensure_ascii=False))  | 
|     return SendPersonalItemMailEx(title, content, 30, playerIDList, addItemList, gold, goldPaper, silver, detail, moneySource, crossMail)  | 
|   | 
| def CrossServerMsg_SendMail(msgData):  | 
|     ## ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄ·¢ËÍÓʼþ  | 
|     mailTypeKey = msgData["MailTypeKey"]  | 
|     playerIDList = msgData["Player"]  | 
|     addItemList = msgData.get("Item", [])  | 
|     paramList = msgData.get("Param", [])  | 
|     SendMailByKey(mailTypeKey, playerIDList, addItemList, paramList)  | 
|     return  | 
|   | 
| def __checkMailItemIDCount(itemID, itemCount, isAuctionItem):  | 
|     ## ¼ì²éÊÇ·ñºÏ·¨µÄÓʼþÎïÆ·ID Count Êý¾Ý  | 
|     if not (isinstance(itemID, int) or isinstance(itemID, long)):  | 
|         return  | 
|     if not (isinstance(itemCount, int) or isinstance(itemCount, long)):  | 
|         return  | 
|     if not (isinstance(isAuctionItem, int) or isinstance(isAuctionItem, long) or isinstance(isAuctionItem, bool)):  | 
|         return  | 
|     if itemID > ShareDefine.Def_UpperLimit_DWord or itemCount > ShareDefine.Def_UpperLimit_DWord or isAuctionItem > 255:  | 
|         return  | 
|     return True  | 
|   | 
| def __checkMailItemDict(curItemDict):  | 
|     ## ¼ì²éÊÇ·ñºÏ·¨µÄÓʼþÎïÆ·dictÐÅÏ¢  {"ItemID":xxx, "Count":xxx, "IsAuctionItem":xxx}  | 
|     if not isinstance(curItemDict, dict):  | 
|         return  | 
|     if "ItemID" not in curItemDict or "Count" not in curItemDict:  | 
|         return  | 
|     itemID = curItemDict["ItemID"]  | 
|     itemCount = curItemDict["Count"]  | 
|     isAuctionItem = curItemDict.get("IsAuctionItem", 0)  | 
|     if not __checkMailItemIDCount(itemID, itemCount, isAuctionItem):  | 
|         return  | 
|     return curItemDict  | 
|   | 
| def __checkMailItemList(addItemList):  | 
|     ## ¼ì²éÊÇ·ñºÏ·¨µÄÓʼþÎïÆ·ÁÐ±í  | 
|     addItemDictList = []  | 
|     for itemInfo in addItemList:  | 
|         if isinstance(itemInfo, dict):  | 
|             if not __checkMailItemDict(itemInfo):  | 
|                 return False, []  | 
|             addItemDictList.append(itemInfo)  | 
|             continue  | 
|           | 
|         if (isinstance(itemInfo, list) or isinstance(itemInfo, tuple)) and (len(itemInfo) == 3 or len(itemInfo) == 2):  | 
|             itemID, itemCount = itemInfo[:2]  | 
|             isAuctionItem = itemInfo[2] if len(itemInfo) > 2 else 0  | 
|             if not __checkMailItemIDCount(itemID, itemCount, isAuctionItem):  | 
|                 return False, []  | 
|             addItemDict = {}  | 
|             addItemDict['ItemID'] = itemID  | 
|             addItemDict['Count'] = itemCount  | 
|             addItemDict['IsAuctionItem'] = isAuctionItem  | 
|             addItemDictList.append(addItemDict)  | 
|         else:  | 
|             return False, []  | 
|     return True, addItemDictList  | 
|   | 
| #  ´Ë´¦»õ±ÒplayerIDList·¢·Åͳһ£¬Èç¸ù¾ÝÍæ¼Ò²»Í¬¶ø±ä£¬ÔòÓ¦ÐèÐÞ¸Ä  | 
| ## ¹¦ÄÜ·¢·ÅÎïÆ·²¹³¥/½±ÀøÓʼþ  | 
| #  @param addItemList [(itemID, itemCnt, ÊÇ·ñÅÄÆ·), {»òÎïÆ·ÐÅÏ¢×Öµä}, ...]  | 
| #  @return GUID  | 
| #  @remarks addItemListÖ§³Öappend×Öµä  | 
| def SendPersonalItemMail(title, content, limitTime, playerIDList, addItemList, gold = 0, goldPaper = 0, silver = 0,   | 
|                          detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False, mailType=0):  | 
|     if not playerIDList:  | 
|         return ""  | 
|       | 
|     #if not addItemList:  | 
|     #    return ""  | 
|   | 
|     curServerTime = GameWorld.GetCurrentDataTimeStr()  | 
|     # µ±Ç°Ê±¼äÒѾ³¬¹ýÁìȡʱ¼ä  | 
|     if not curServerTime or curServerTime >= limitTime:  | 
|         GameWorld.DebugLog("¹¦ÄÜ·¢·ÅÎïÆ·²¹³¥/½±ÀøÓʼþ£¬Áìȡʱ¼äÒѳ¬Ê±£¬Ä¬Èϲ»Ìí¼Ó£¡LimitTime=%s" % limitTime)  | 
|         return ""  | 
|     isOK, addItemDictList = __checkMailItemList(addItemList)  | 
|     if not isOK:  | 
|         GameWorld.ErrLog("·¢Ë͸öÈËÓʼþ´íÎó: title=%s,content=%s,playerIDList=%s,addItemList=%s,gold=%s,goldPaper=%s,silver=%s,detail=%s,moneySource=%s,crossMail=%s"   | 
|                          % (title, content, playerIDList, addItemList, gold, goldPaper, silver, detail, moneySource, crossMail))  | 
|         return  | 
|       | 
|     gold = min(gold, ShareDefine.Def_UpperLimit_DWord)  | 
|     goldPaper = min(goldPaper, ShareDefine.Def_UpperLimit_DWord)  | 
|     silver = min(silver, ShareDefine.Def_UpperLimit_DWord)  | 
|       | 
|     perMailItemCnt = IpyGameDataPY.GetFuncCfg("MailMaxItemCnt")  | 
|     mailCnt = max(1, int(math.ceil(len(addItemDictList)/float(perMailItemCnt)))) # Ò»·âÓʼþ×î¶à5¸öÎïÆ·  | 
|     for i in xrange(mailCnt):  | 
|         if i != 0:  | 
|             gold, goldPaper, silver = 0, 0, 0 # ²ð·Öºó·ÇµÚÒ»·âµÄÓʼþ»õ±Ò¹éÁ㣬·ÀÖ¹ÖØ¸´¸ø»õ±Ò½±Àø  | 
|         startIndex = i*perMailItemCnt  | 
|         GUID = str(uuid.uuid1())  | 
|         AddPersonalItem(GUID, addItemDictList[startIndex:startIndex + perMailItemCnt], playerIDList,   | 
|                                            limitTime, GetMailText(title, content, mailType),  | 
|                                            gold, goldPaper, silver, detail, moneySource, crossMail)  | 
|     return GUID  | 
|   | 
| ## ·¢ËÍ´¿ÎÄ×Ö¸öÈ˲¹³¥  | 
| #  @param limitTime ¿ÉÒÔ´«¿Õ  | 
| #  @return None  | 
| def SendPersonalAsTextMail(PlayerID, title, content, limitTime, mailType=0):  | 
|     if GameWorld.IsCrossServer():  | 
|         return  | 
|     GUID = str(uuid.uuid1())  | 
|     PyAddPersonalCompensation(GUID, PlayerID, GameWorld.GetCurrentDataTimeStr(), limitTime,   | 
|                               GetMailText(title, content, mailType))  | 
|     return  | 
|   | 
| def GetMailText(title, content, mailType=0, sender=ChConfig.Def_Mail_SenderSys):  | 
|     ## »ñÈ¡Óʼþ×ֶΠText ÄÚÈÝ  | 
|     return "%s<$_$>%s<$_$>%s<$_$>%s" % (sender, title, content, mailType)  | 
|   | 
| def GetEntireCompensationInfo(checkState, limitLVType, limitLV):  | 
|     return checkState * 1000000 + limitLVType * 100000 + limitLV  | 
| def ParseEntireCompensationInfo(mailInfo):  | 
|     limitLV = mailInfo % 100000  | 
|     checkState = mailInfo / 1000000  | 
|     limitLVType = (mailInfo - checkState * 1000000) / 100000  | 
|     return checkState, limitLVType, limitLV  | 
|   | 
| def QueryCompensationPersonalInfo(playerID):  | 
|     '''¸öÈ˲¹³¥Óʼþ²éѯ  | 
|     '''  | 
|           | 
|     retList = []  | 
|     compensationMgr = GameWorld.GetCompensationMgr()  | 
|       | 
|     tempSign = "<MailTemplate>"  | 
|     tempSignEnd = "</MailTemplate>"  | 
|     curPersonalCount = compensationMgr.GetPersonalCompensationCount(playerID)  | 
|     GameWorld.DebugLog("QueryCompensationPersonalInfo %s" % curPersonalCount)  | 
|     for i in xrange(curPersonalCount):  | 
|         compensation = compensationMgr.PersonalCompensationAt(playerID, i)  | 
|           | 
|         contentList = compensation.Text.split("<$_$>")  | 
|         if len(contentList) < 3:  | 
|             continue  | 
|         sender, title, content = contentList[:3]  | 
|         mailType = GameWorld.ToIntDef(contentList[3]) if len(contentList) > 3 else 0  | 
|           | 
|         if tempSign in content and tempSignEnd in content:  | 
|             title = content[content.index(tempSign) + len(tempSign):content.index(tempSignEnd)]  | 
|             content = ""  | 
|               | 
|         GUID = compensation.GUID  | 
|         itemList = []  | 
|         curGUIDItemCount = compensationMgr.FindItemCount(GUID)  | 
|         for i in xrange(curGUIDItemCount):  | 
|             curItem = compensationMgr.FindItemAt(GUID, i)  | 
|             itemID = curItem.ItemID  | 
|             if not itemID:  | 
|                 continue  | 
|             itemList.append([itemID, curItem.Count, curItem.IsBind, curItem.UserData])  | 
|               | 
|         recState = compensationMgr.FindPlayerRecState(playerID, GUID)  | 
|           | 
|         infoDict = {"GUID":GUID, "Gold":compensation.Gold, "GoldPaper":compensation.GoldPaper, "Silver":compensation.Silver,  | 
|                     "Sender":sender, "Title":title, "Content":content, "RecState":recState, "MailType":mailType,  | 
|                     "CreateTime":compensation.CreateTime, "LimitTime":compensation.LimitTime, "ItemList":itemList}  | 
|           | 
|         retList.append(infoDict)  | 
|           | 
|     return retList  | 
|   | 
| def QueryCompensationInfo(fromDate, toDate, guid, searchTitle, searchContent, searchState=None, maxCount=10):  | 
|     '''È«·þ²¹³¥Óʼþ²éѯ  | 
|     '''  | 
|       | 
|     compensationMgr = GameWorld.GetCompensationMgr()  | 
|     retList = []  | 
|     if guid:  | 
|         infoDict = __GetQueryCompensationInfoDict(compensationMgr, compensationMgr.FindEntireCompensation(guid), "", "", searchTitle, searchContent, searchState)  | 
|         if infoDict:  | 
|             retList.append(infoDict)  | 
|         return retList  | 
|       | 
|     if fromDate:  | 
|         fromDate = "%s 00:00:00" % fromDate  | 
|     if toDate:  | 
|         toDate = "%s 23:59:59" % toDate  | 
|           | 
|     entireCnt = compensationMgr.GetEntireCompensationCount()  | 
|     for i in xrange(entireCnt):  | 
|         compensation = compensationMgr.AtEntireCompensation(i)  | 
|                       | 
|         infoDict = __GetQueryCompensationInfoDict(compensationMgr, compensation, fromDate, toDate, searchTitle, searchContent, searchState)  | 
|         if not infoDict:  | 
|             continue  | 
|           | 
|         retList.append(infoDict)  | 
|         if len(retList) >= maxCount:  | 
|             break  | 
|           | 
|     return retList  | 
|   | 
| def __GetQueryCompensationInfoDict(compensationMgr, compensation, fromDate, toDate, searchTitle, searchContent, searchState):  | 
|     if not compensation or not compensation.GUID:  | 
|         return  | 
|       | 
|     if fromDate and compensation.CreateTime < fromDate:  | 
|         return  | 
|       | 
|     if toDate and compensation.CreateTime > toDate:  | 
|         return  | 
|       | 
|     contentList = compensation.Text.split("<$_$>")  | 
|     if len(contentList) < 3:  | 
|         return  | 
|     sender, title, content = contentList[:3]  | 
|     mailType = GameWorld.ToIntDef(contentList[3]) if len(contentList) > 3 else 0  | 
|       | 
|     if searchTitle and searchTitle not in title:  | 
|         return  | 
|       | 
|     if searchContent and searchContent not in content:  | 
|         return  | 
|       | 
|     checkState, limitLVType, limitLV = ParseEntireCompensationInfo(compensation.PlayerLV)  | 
|     if searchState != None and searchState != checkState:  | 
|         return  | 
|       | 
|     GUID = compensation.GUID  | 
|     itemList = []  | 
|     curGUIDItemCount = compensationMgr.FindItemCount(GUID)  | 
|     for i in xrange(curGUIDItemCount):  | 
|         curItem = GameWorld.GetCompensationMgr().FindItemAt(GUID, i)  | 
|         itemID = curItem.ItemID  | 
|         if not itemID:  | 
|             continue  | 
|         itemList.append([itemID, curItem.Count, curItem.IsBind, curItem.UserData])  | 
|           | 
|     compensationDict = {"GUID":GUID, "CheckState":checkState, "LimitLVType":limitLVType, "LimitLV":limitLV, "MailType":mailType,  | 
|                         "Gold":compensation.Gold, "GoldPaper":compensation.GoldPaper, "Silver":compensation.Silver,  | 
|                         "PlayerJob":compensation.PlayerJob, "Sender":sender, "Title":title, "Content":content, "OnlyServerID":compensation.ServerID,  | 
|                         "CreateTime":compensation.CreateTime, "LimitTime":compensation.LimitTime, "ItemList":itemList}  | 
|     return compensationDict  | 
|   | 
| def EntireCompensationOper(operGUIDList, operation):  | 
|     '''È«·þÓʼþ²Ù×÷¹ÜÀí  | 
|     @param operGUIDList: ´ý²Ù×÷µÄÓʼþGUIDÁÐ±í  | 
|     @param operation: 1-ͨ¹ý£»2-ɾ³ý  | 
|     '''  | 
|       | 
|     okGUIDList = []  | 
|     successGUIDList = []  | 
|     compensationMgr = GameWorld.GetCompensationMgr()  | 
|     for GUID in operGUIDList:  | 
|         compensation = compensationMgr.FindEntireCompensation(GUID)  | 
|         if not compensation or compensation.GUID != GUID:  | 
|             continue  | 
|           | 
|         # É¾³ý  | 
|         if operation == 2:  | 
|             compensationMgr.DeleteEntireCompensation(GUID)  | 
|             compensationMgr.DeleteCompensationItem(GUID)  | 
|             compensationMgr.DeleteRecByGUID(GUID)  | 
|             GameWorld.Log("ɾ³ýÈ«·þÓʼþ: GUID=%s" % GUID)  | 
|             DataRecordPack.DR_EntireCompensation(GUID, "Delete")  | 
|               | 
|         # Í¨¹ý  | 
|         elif operation == 1:  | 
|             mailInfo = compensation.PlayerLV  | 
|             checkState, limitLVType, limitLV = ParseEntireCompensationInfo(mailInfo)  | 
|             updMailInfo = GetEntireCompensationInfo(CheckState_OK, limitLVType, limitLV)  | 
|             compensationMgr.SetEntireCompensationPlayerLV(GUID, updMailInfo)  | 
|             GameWorld.Log("È«·þÓʼþÉóºËͨ¹ý: GUID=%s,mailInfo=%s,checkState=%s,updMailInfo=%s"   | 
|                           % (GUID, mailInfo, checkState, updMailInfo))  | 
|             if checkState != CheckState_OK:  | 
|                 okGUIDList.append(GUID)  | 
|                 DataRecordPack.DR_EntireCompensation(GUID, "CheckOK")  | 
|         else:  | 
|             continue  | 
|         successGUIDList.append(GUID)  | 
|           | 
|     playerManager = GameWorld.GetPlayerManager()  | 
|     for i in xrange(playerManager.GetActivePlayerCount()):  | 
|         player = playerManager.GetActivePlayerAt(i)  | 
|         if player == None or not player.GetInitOK() or PlayerControl.GetIsTJG(player):  | 
|             continue  | 
|         #¹ã²¥ÔÚÏßÍæ¼Ò  | 
|         notifyList = []  | 
|         for GUID in okGUIDList:  | 
|             compensationType, curEntireRequire = CheckRequestCompensation(player, GUID, False)  | 
|             if compensationType == Unknow_CompensationType:  | 
|                 continue  | 
|             Text, gold, goldPaper, silver = curEntireRequire.Text, curEntireRequire.Gold, curEntireRequire.GoldPaper, curEntireRequire.Silver  | 
|             createTime = curEntireRequire.CreateTime  | 
|             notifyList.append((GUID, Text, createTime, gold, goldPaper, silver))  | 
|               | 
|         #GameWorld.DebugLog("¹ã²¥ÔÚÏßÍæ¼ÒÈ«·þÓʼþ: %s" % str(notifyList), player.GetPlayerID())  | 
|         if notifyList:  | 
|             SyncQueryCompensationResult(player, notifyList)  | 
|               | 
|     return successGUIDList  | 
|   | 
| def SendEntireMail(mailTypeKey, getDays, limitLV, limitLVType, addItemList=[], paramList=[], \  | 
|                    gold=0, goldPaper=0, silver=0, detail="", moneySource=ChConfig.Def_GiveMoney_Mail, GUID="", mailType=0):  | 
|     ''' ·¢ËÍÈ«·þÓʼþ  | 
|     @param mailTypeKey: ÓʼþÄ£°åkey  | 
|     @param getDays: ÓÐЧÌìÊý  | 
|     @param limitLV: ÁìÈ¡×îµÍµÈ¼¶ÏÞÖÆ  | 
|     @param limitLVType: µÈ¼¶²»×ãµÄÉý¼¶ºóÊÇ·ñ¿ÉÁì 0-²»¿É£¬1-¿ÉÒÔ  | 
|     '''  | 
|       | 
|     if not mailTypeKey or getDays <= 0:  | 
|         return  | 
|       | 
|     isOK, addItemDictList = __checkMailItemList(addItemList)  | 
|     if not isOK:  | 
|         GameWorld.ErrLog("·¢ËÍÈ«·þÓʼþ´íÎó: mailTypeKey=%s,addItemList=%s,paramList=%s,gold=%s,goldPaper=%s,silver=%s,detail=%s,moneySource=%s"   | 
|                      % (mailTypeKey, addItemList, paramList, gold, goldPaper, silver, detail, moneySource))  | 
|         return  | 
|       | 
|     gold = min(gold, ShareDefine.Def_UpperLimit_DWord)  | 
|     goldPaper = min(goldPaper, ShareDefine.Def_UpperLimit_DWord)  | 
|     silver = min(silver, ShareDefine.Def_UpperLimit_DWord)  | 
|       | 
|     if not GUID:  | 
|         GUID = str(uuid.uuid1())  | 
|           | 
|     limitTime = str(GameWorld.GetDatetimeByDiffDays(getDays))  | 
|     limitTime = limitTime.split(".")[0]  | 
|       | 
|     sender = ChConfig.Def_Mail_SenderSys  | 
|     title = ""  | 
|     content = "<MailTemplate>%s</MailTemplate>%s" % (mailTypeKey, json.dumps(paramList, ensure_ascii=False))  | 
|       | 
|     checkState = 0 # ÓʼþÉóºË״̬£¬Îª¼æÈÝÀÏÓʼþ£¬Ä¬ÈÏ0-ÒÑÉóºË£¬1-δÉóºË  | 
|     mailInfo = GetEntireCompensationInfo(checkState, limitLVType, limitLV)  | 
|     PlayerJob = 127 # Ä¬ÈÏȫְҵ¿ÉÁì  | 
|     serverID = 0 # Ä¬ÈÏËùÓзþÎñÆ÷ID  | 
|       | 
|     AddEntireItem(GUID, addItemDictList, limitTime, mailInfo, PlayerJob, GetMailText(title, content, mailType, sender),   | 
|                   gold, goldPaper, silver, detail, serverID)  | 
|     return  | 
|   | 
| ## Ìí¼ÓÈ«·þ²¹³¥  | 
| #  @param addItemDictList, LimitTime, mailInfo, PlayerJob,  Text   | 
| #  @return None  | 
| def AddEntireItem(GUID, addItemDictList, LimitTime, mailInfo, PlayerJob, Text,  | 
|                   gold = 0, goldPaper = 0, silver = 0, detail="", serverID=0):  | 
|     '''  | 
|     @param mailInfo: GetEntireCompensationInfo µÄ·µ»ØÖµ, Ä¿Ç°ÔÝ´æ×ֶΠPlayerLV ÖÐ  | 
|     '''  | 
|     if GameWorld.IsCrossServer():  | 
|         return  | 
|     #GameWorld.DebugLog("Compensation### AddEntireItem GUID:%s ItemDict:\n%s "%(GUID, addItemDictList))  | 
|       | 
|     #Ìí¼Ó²¹³¥°üµÄËùÓÐÎïÆ·  | 
|     for addItemDict in addItemDictList:  | 
|         curItemData = MakeCompensationItem(addItemDict)  | 
|         if not curItemData:  | 
|             return  | 
|         GameWorld.GetCompensationMgr().AddCompensationItem(GUID, curItemData)  | 
|           | 
|     createTime = GameWorld.GetCurrentDataTimeStr()  | 
|       | 
|     #Ìí¼ÓÈ«·þÁìÈ¡²¹³¥Ìõ¼þ  | 
|     gold = min(gold, ShareDefine.Def_UpperLimit_DWord)  | 
|     goldPaper = min(goldPaper, ShareDefine.Def_UpperLimit_DWord)  | 
|     silver = min(silver, ShareDefine.Def_UpperLimit_DWord)  | 
|     GameWorld.GetCompensationMgr().AddEntireCompensationItem(GUID, createTime, LimitTime, mailInfo,   | 
|                                                              PlayerJob, Text, gold, goldPaper, silver, serverID)  | 
|     checkState, limitLVType, limitLV = ParseEntireCompensationInfo(mailInfo)  | 
|     addDict = {"LimitTime":LimitTime, "LimitLV":limitLV, "LimitLVType":limitLVType, "CheckState":checkState, "PlayerJob":PlayerJob, "Text":Text,   | 
|                "Gold":gold, "GoldPaper":goldPaper, "Silver":silver, "ItemList":addItemDictList, "Detail":detail}  | 
|     #Ìí¼ÓÁ÷Ïò  | 
|     eventName = "Add" if checkState == CheckState_OK else "AddToCheck"  | 
|     DataRecordPack.DR_EntireCompensation(GUID, eventName, addDict)  | 
|     __WriteSendMailOKEvent(GUID, addItemDictList, LimitTime, Text, None, mailInfo, PlayerJob)  | 
|       | 
|     testAccIDList = ReadChConfig.GetEvalChConfig("TestAccID")  | 
|     playerManager = GameWorld.GetPlayerManager()  | 
|     for i in xrange(playerManager.GetActivePlayerCount()):  | 
|         player = playerManager.GetActivePlayerAt(i)  | 
|         if player == None or not player.GetInitOK() or PlayerControl.GetIsTJG(player):  | 
|             continue  | 
|         if checkState == CheckState_No:  | 
|             playerAccID = GameWorld.GetPlatformAccID(player.GetAccID())  | 
|             if playerAccID not in testAccIDList:  | 
|                 continue  | 
|                   | 
|         #¹ã²¥ÔÚÏßÍæ¼Ò  | 
|         compensationType, curEntireRequire = CheckRequestCompensation(player, GUID, False)  | 
|         if compensationType == Unknow_CompensationType:  | 
|             continue  | 
|         Text, gold, goldPaper, silver = curEntireRequire.Text, curEntireRequire.Gold, curEntireRequire.GoldPaper, curEntireRequire.Silver  | 
|         #GameWorld.Log("#¹ã²¥ÔÚÏßÍæ¼Ò%s"%player.GetPlayerID())  | 
|         SyncQueryCompensationResult(player, [(GUID, Text, createTime, gold, goldPaper, silver)])  | 
|     return  | 
|   | 
| # ¼ì²éÓʼþÊÇ·ñÒÑ´ïµ½±£´æÉÏÏÞ£¬È糬¹ýÔòÏÈɾ³ý¾ÉÓʼþ  | 
| # @param LimitTime ²ÎÊý¿É´«¿Õ£¬¸öÈËÓʼþ²»ÏÞÖÆÁìÈ¡ÆÚÏÞ£¬Ö»ÏÞÖÆ±£´æÊýÁ¿£¬   | 
| def PyAddPersonalCompensation(GUID, PlayerID, CreateTime, LimitTime, Text, gold = 0, goldPaper = 0, silver = 0, moneySource=ChConfig.Def_GiveMoney_Mail):  | 
|     curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(PlayerID)  | 
|     totalCount = GameWorld.GetCompensationMgr().GetPersonalCompensationCount(PlayerID)  | 
|     #´ýÖ§³Öpy¶Á±í  | 
|     maxMailCount = IpyGameDataPY.GetFuncCfg("MailDefaultCount")  | 
|     delCount = totalCount - maxMailCount + 1  | 
|     GameWorld.DebugLog("ÐÂÔö¸öÈËÓʼþ: totalCount=%s,maxMailCount=%s" % (totalCount, maxMailCount), PlayerID)  | 
|     if delCount > 0:  | 
|         GameWorld.Log("¸öÈËÓʼþ´ïµ½ÉÏÏÞ£¬ÐèҪɾ³ý£¡delCount=%s" % (delCount), PlayerID)  | 
|         delGUIDList = GetPlayerDelMailGUIDList(PlayerID)  | 
|         #ÏÈÈ¡µÃҪɾ³ýµÄGUID  | 
|         delGUIDs = []  | 
|         for _ in xrange(delCount):  | 
|             if not delGUIDList:  | 
|                 break  | 
|             delGUID = delGUIDList.pop(0)  | 
|             curIpyPersonalData = GameWorld.GetCompensationMgr().FindPersonalCompensation(PlayerID, delGUID)  | 
|             if curIpyPersonalData.GUID == delGUID:  | 
|                 delGUIDs.append(curIpyPersonalData.GUID)  | 
|               | 
|         for guid in delGUIDs:  | 
|             ClearPersonalCompensation(PlayerID, guid, "MaxCountLimiit")  | 
|             GameWorld.Log("    DeletePersonalCompensation GUID = %s" % guid, PlayerID)  | 
|               | 
|             if curPlayer:  | 
|                 NotifyCompensationResult(curPlayer, guid, 1)  | 
|             #δ²¹Á÷Ïò  | 
|               | 
|     #´Ë´¦Ã»ÓÐÏ·¢Í¨Öª  | 
|     mailType = moneySource - ChConfig.Def_GiveMoney_Unknown # typeÀàÐÍΪbyte£¬´æÖµÊ±ÐèÒª´¦ÀíÏ  | 
|     gold = min(gold, ShareDefine.Def_UpperLimit_DWord)  | 
|     goldPaper = min(goldPaper, ShareDefine.Def_UpperLimit_DWord)  | 
|     silver = min(silver, ShareDefine.Def_UpperLimit_DWord)  | 
|     GameWorld.GetCompensationMgr().AddPersonalCompensation(GUID, PlayerID, CreateTime,  | 
|                                                            LimitTime, Text, mailType, gold, goldPaper, silver)  | 
|     if PlayerID in PyGameData.g_playerDelMailGUIDDict:  | 
|         guidList = PyGameData.g_playerDelMailGUIDDict[PlayerID]  | 
|         guidList.append(GUID)  | 
|     return  | 
|   | 
| def GetPlayerDelMailGUIDList(playerID):  | 
|     ## »ñÈ¡´ýɾ³ýµÄ¸öÈËÓʼþGUIDÁÐ±í  | 
|     if playerID not in PyGameData.g_playerDelMailGUIDDict:  | 
|           | 
|         timeGUIDList = []  | 
|         curPersonalCount = GameWorld.GetCompensationMgr().GetPersonalCompensationCount(playerID)  | 
|         for i in xrange(curPersonalCount):  | 
|             curMail = GameWorld.GetCompensationMgr().PersonalCompensationAt(playerID, i)  | 
|             timeGUIDList.append([curMail.CreateTime, curMail.GUID])  | 
|               | 
|         timeGUIDList.sort() # °´´´½¨Ê±¼äÉýÐòÅÅÐò  | 
|         delGUIDList = []  | 
|         for _, guid in timeGUIDList:  | 
|             if guid not in delGUIDList:  | 
|                 delGUIDList.append(guid)  | 
|         PyGameData.g_playerDelMailGUIDDict[playerID] = delGUIDList  | 
|           | 
|     return PyGameData.g_playerDelMailGUIDDict[playerID]  | 
|   | 
| #  ´Ë´¦»õ±ÒplayerIDList·¢·Åͳһ£¬Èç¸ù¾ÝÍæ¼Ò²»Í¬¶ø±ä£¬ÔòÓ¦ÐèÐÞ¸Ä  | 
| ## Ìí¼Ó¸öÈ˲¹³¥  | 
| #  @param addItemDict, PlayerIDList, LimitTime, Text   | 
| #  @return None  | 
| def AddPersonalItem(GUID, addItemDictList, PlayerIDList, LimitTime, Text, gold = 0, goldPaper = 0, silver = 0,   | 
|                     detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):  | 
|     if GameWorld.IsCrossServer():  | 
|         if crossMail:  | 
|             __AddPlayerCrossMail(addItemDictList, PlayerIDList, LimitTime, Text, gold, goldPaper, silver, detail, moneySource)  | 
|         return  | 
|     GameWorld.DebugLog("Compensation### AddPersonalItem GUID:%s ItemDict:\n%s "%(GUID, addItemDictList))  | 
|       | 
|     #Ìí¼Ó²¹³¥°üµÄËùÓÐÎïÆ·  | 
|     for addItemDict in addItemDictList:  | 
|         curItemData = MakeCompensationItem(addItemDict)  | 
|         if not curItemData:  | 
|             return  | 
|         GameWorld.GetCompensationMgr().AddCompensationItem(GUID, curItemData)  | 
|           | 
|     #offlinePlayerIDList = []  | 
|     onlinePlayerInfo = {}  | 
|     #ÅúÁ¿Ìí¼ÓÍæ¼Ò¸öÈ˲¹³¥ÁìÈ¡±í  | 
|     createTime = GameWorld.GetCurrentDataTimeStr()  | 
|     for PlayerID in PlayerIDList:  | 
|         PyAddPersonalCompensation(GUID, PlayerID, createTime, LimitTime, Text, gold, goldPaper, silver, moneySource)  | 
|         # Õë¶Ô¸öÈ˲¹³¥£¬Èç¹ûÊÇÔÚÏßÍæ¼Ò£¬ÔòÁ¢¼´ÍÆË͸ø¿Í»§¶Ë  | 
|         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(PlayerID)  | 
|         if curPlayer:  | 
|             SyncQueryCompensationResult(curPlayer, [(GUID, Text, createTime, gold, goldPaper, silver)])  | 
|             onlinePlayerInfo[curPlayer.GetAccID()] = [curPlayer.GetName(), curPlayer.GetLV()]  | 
|     #===========================================================================  | 
|     #    else:  | 
|     #        offlinePlayerIDList.append(PlayerID)  | 
|     #          | 
|     # if offlinePlayerIDList:  | 
|     #    PlayerDBOper.FindDBOper(PlayerDBOper.Table_DBPlayer, {"PlayerID":{"$in":offlinePlayerIDList}},  | 
|     #                            {"PlayerID":1, "AccID":1, "PlayerName":1, "LV":1, "_id":0},  | 
|     #                            FindDBResult_SendMail, [GUID, addItemDictList, createTime, Text])  | 
|     # if onlinePlayerInfo:  | 
|     #    __WriteSendMailOKEvent(GUID, addItemDictList, createTime, Text, onlinePlayerInfo)  | 
|     #===========================================================================  | 
|       | 
|     #Ìí¼ÓÁ÷Ïò  | 
|     addDict = {"LimitTime":LimitTime, "Text":Text, "Gold":gold, "GoldPaper":goldPaper, "Silver":silver,   | 
|                "ItemListLen":len(addItemDictList), "Detail":detail, "MoneySource":moneySource}  | 
|     DataRecordPack.DR_AddPersonalCompensation(PlayerIDList, GUID, addItemDictList, addDict)  | 
|     return  | 
|   | 
| def FindDBResult_SendMail(resultSetList, extendValueList):  | 
|     if not resultSetList:  | 
|         return  | 
|       | 
|     playerInfoDict = {}  | 
|     GUID, addItemDictList, LimitTime, Text = extendValueList  | 
|     GameWorld.Log("ÓʼþÀëÏßÍæ¼ÒDBÐÅÏ¢: GUID=%s, %s" % (GUID, str(resultSetList)))  | 
|     for resultDict in resultSetList:  | 
|         playerInfoDict[resultDict["AccID"]] = [resultDict["PlayerName"], resultDict["LV"]]  | 
|           | 
|     __WriteSendMailOKEvent(GUID, addItemDictList, LimitTime, Text, playerInfoDict)  | 
|     return  | 
|   | 
| ## Í¨ÖªµØÍ¼Óʼþ·¢ËÍOK  | 
| def __WriteSendMailOKEvent(GUID, addItemDictList, LimitTime, Text, playerInfoDict={}, playerLV=0, playerJob=0):  | 
| #===============================================================================  | 
| #    eventName = "SendMail"  | 
| #    #%s<$_$>%s  | 
| #    sender, title, content = Text.split("<$_$>")  | 
| #   | 
| #    #<MailTemplate>Ä£°å±àºÅ</MailTemplate>[%s,%s]  | 
| #    if "</MailTemplate>" in content:  | 
| #        mailContentList = content.split("</MailTemplate>")  | 
| #        mailTemplateNO = GameWorld.ToIntDef(mailContentList[0][14:], None)  | 
| #        EventMailInfo = ReadChConfig.GetEvalChConfig("EventMailInfo")  | 
| #        if mailTemplateNO not in EventMailInfo:  | 
| #            return  | 
| #        title, content = EventMailInfo[mailTemplateNO]  | 
| #          | 
| #        mailParamStr = mailContentList[1]  | 
| #        mailParamStr = mailParamStr.replace(" ", "")  | 
| #        if mailParamStr.startswith("[") and mailParamStr.endswith("]") and len(mailParamStr) > 2:  | 
| #            content = content % tuple(eval(mailParamStr))  | 
| #              | 
| #    itemInfo = "ÎïÆ·:"  | 
| #    for addItemDict in addItemDictList:  | 
| #        itemName = "%s" % addItemDict['ItemID']  | 
| #        if addItemDict.get('IsBind',0):  | 
| #            itemName += "(°ó)"  | 
| #        itemInfo += " %s*%s" % (itemName, addItemDict['Count'])  | 
| #          | 
| #    # È«·þ  | 
| #    if not playerInfoDict:  | 
| #        comments = "%s: %s ÓÐЧÆÚ:%s, ÏÞÖÆµÈ¼¶:%s,Ö°Òµ:%s; %s; %s" % (title, GUID, LimitTime, playerLV, playerJob, itemInfo, content)  | 
| #        customEvent = EventReport.custom_events()  | 
| #        customEvent.account_id = "ServerAccount"  | 
| #        customEvent.event_name = eventName  | 
| #        customEvent.session_id = "ServerSession"  | 
| #        customEvent.account_name = customEvent.account_id  | 
| #        customEvent.comments = CommFunc.GetStrCutoff(comments, 255)  | 
| #        EventReport.WriteEvent(customEvent)  | 
| #    else:  | 
| #        comments = "%s: %s ÓÐЧÆÚ:%s, %s; %s" % (title, GUID, LimitTime, itemInfo, content)  | 
| #        comments = CommFunc.GetStrCutoff(comments, 255)  | 
| #        for accID, playerInfo in playerInfoDict.items():  | 
| #            playerName, playerLV = playerInfo  | 
| #            customEvent = EventReport.custom_events()  | 
| #            customEvent.SetEventAgentInfo(GameWorld.GetPlayerPlatform(accID))  | 
| #            customEvent.account_id = GameWorld.GetPlatformAccID(accID)  | 
| #            customEvent.event_name = eventName  | 
| #            customEvent.session_id = "GameServerPlayerSession"  | 
| #              | 
| #            customEvent.account_name = customEvent.account_id  | 
| #            customEvent.chr_name = playerName  | 
| #            customEvent.comments = comments  | 
| #            EventReport.WriteEvent(customEvent)  | 
| #===============================================================================  | 
|     return  | 
|   | 
|   | 
| ##A9 A1 ²éÑ¯Íæ¼Ò²¹³¥#tagCGQueryCompensation  | 
| #  @param index, clientData, tick   | 
| #  @return None  | 
| def OnQueryPlayerCompensation(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     NotifyPlayerCompensation(curPlayer)  | 
|   | 
|   | 
| # ÌáÈ¡½ÓÊÕÓʼþÏ·¢  | 
| def NotifyPlayerCompensation(curPlayer):  | 
|     RequestToGetCrossMail(curPlayer)  | 
|     notifyList = SeekPlayerCompensation(curPlayer)  | 
|     SyncQueryCompensationResult(curPlayer, notifyList)  | 
|     return  | 
|   | 
| # É¾³ý¸öÈËÓʼþ±í ×´Ì¬±í£¬Í¬Ò»¸öGUID ¿ÉÒÔ¶àÈËÁìÈ¡£¬²»ÄÜͬʱɾ³ýÎïÆ·  | 
| def ClearPersonalCompensation(curPlayerID, curGUID, eventName=""):  | 
|     GameWorld.GetCompensationMgr().DeletePersonalCompensation(curPlayerID, curGUID)  | 
|     GameWorld.GetCompensationMgr().DeletePlayerCompensationRec(curPlayerID, curGUID)  | 
|       | 
|     #´æÔÚ¶àÈËÓʼþµÄÇé¿ö£¬¹Êɾ³ýÎïÆ·Ðè¼ì²éÊÇ·ñ×îºóÒ»¸öÁìÈ¡Õ߲ſÉɾ³ý  | 
|     if GameWorld.GetCompensationMgr().GetPersonalCountByGUID(curGUID) == 0:  | 
|         GameWorld.GetCompensationMgr().DeleteCompensationItem(curGUID)  | 
|           | 
|     if curPlayerID in PyGameData.g_playerDelMailGUIDDict:  | 
|         guidList = PyGameData.g_playerDelMailGUIDDict[curPlayerID]  | 
|         if curGUID in guidList:  | 
|             guidList.remove(curGUID)  | 
|     if eventName:  | 
|         # ÓÐÌØÊâ²Ù×÷ɾ³ýµÄ²Å¼Ç¼£¬³£¹æÁìȡɾ³ýµÄĬÈÏÎÞeventName£¬²»¼Ç¼  | 
|         DataRecordPack.DR_DelPersonalCompensation(curPlayerID, curGUID, eventName)  | 
|     return  | 
|   | 
| # ÉèÖÃÁìȡ״̬  | 
| def SetPrizeState(curPlayerID, GUID, prizeState, readState):  | 
|     state = readState*10 + prizeState  | 
|     GameWorld.GetCompensationMgr().AddPlayerRec(curPlayerID, GUID, state)  | 
|     return  | 
|   | 
| def GetPrizeGetState(curPlayerID, GUID):  | 
|     ## »ñÈ¡Áìȡ״̬  | 
|     return GameWorld.GetCompensationMgr().FindPlayerRecState(curPlayerID, GUID) % 10  | 
|   | 
| ##²éÕÒÍæ¼Ò¿ÉÁìÈ¡µÄ²¹³¥ÁÐ±í  | 
| #  @param curPlayer   | 
| #  @return None  | 
| def SeekPlayerCompensation(curPlayer):  | 
|     curPlayerID = curPlayer.GetID()  | 
|     curTime = datetime.datetime.today()  | 
|   | 
|     allList = [] #²¹³¥ÎïÆ·±í [(GUID,TEXT),(GUID,TEXT),...]  | 
|     #¸öÈ˲¹³¥  | 
|     curPersonalCount = GameWorld.GetCompensationMgr().GetPersonalCompensationCount(curPlayerID)  | 
|     for i in xrange(curPersonalCount):  | 
|         curIpyPersonalData = GameWorld.GetCompensationMgr().PersonalCompensationAt(curPlayerID, i)  | 
|   | 
|         #¿ÉÒÔÓõĽ±Àø  | 
|         allList.append((curIpyPersonalData.GUID, curIpyPersonalData.Text, curIpyPersonalData.CreateTime,  | 
|                         curIpyPersonalData.Gold, curIpyPersonalData.GoldPaper, curIpyPersonalData.Silver))  | 
|       | 
|     #È«·þ²¹³¥      | 
|     curEntireCount = GameWorld.GetCompensationMgr().GetEntireCompensationCount()  | 
|     curJob = curPlayer.GetJob()  | 
|     curLV = curPlayer.GetLV()  | 
|     isTestAccID = GameWorld.GetPlatformAccID(curPlayer.GetAccID()) in ReadChConfig.GetEvalChConfig("TestAccID")  | 
|     for i in xrange(curEntireCount - 1, -1, -1):  | 
|         curRequire = GameWorld.GetCompensationMgr().AtEntireCompensation(i)  | 
|           | 
|         checkState, limitLVType, limitLV = ParseEntireCompensationInfo(curRequire.PlayerLV)  | 
|         if checkState == CheckState_No:  | 
|             if not isTestAccID:  | 
|                 #δÉóºËµÄÓʼþ²»´¦Àí  | 
|                 continue  | 
|               | 
|         #»ñÈ¡¼Ç¼  | 
|         states = GameWorld.GetCompensationMgr().FindPlayerRecState(curPlayerID, curRequire.GUID)  | 
|         readState = states/10    # ¿É¶Á         | 
|         curState = states%10    # Áìȡ״̬  | 
|         if curState in (Disable_State, Del_State):  | 
|             #²»¿ÉÁì »ò ÒÑÁì  | 
|             #GameWorld.DebugLog("¸ÃÍæ¼Òµ±Ç°È«·þÓʼþ״̬²»Ï·¢: curState=%s,GUID=%s" % (curState, curRequire.GUID), curPlayerID)  | 
|             continue  | 
|           | 
|         limitTime = datetime.datetime.strptime(curRequire.LimitTime, ChConfig.TYPE_Time_Format)  | 
|         if limitTime < curTime and curState == Unknown_State:  | 
|             #δ֪ͨ¹ýµÄÓʼþ³¬Ê±£¬²Å¿ÉÉèÖóɲ»¿ÉÁìÈ¡  | 
|             SetPrizeState(curPlayerID, curRequire.GUID, Disable_State, readState)  | 
|             continue  | 
|           | 
|         if limitLVType == LimitLVType_Not and curPlayer.GetCreateRoleTime() > curRequire.CreateTime:  | 
|             #GameWorld.DebugLog("Éý¼¶ºó²»¿ÉÁìÈ¡µÄÓʼþ·¢ËÍʱ¼äºó´´½ÇµÄÍæ¼ÒĬÈϲ»¿ÉÁìÈ¡! CreateRoleTime=%s > %s" % (curPlayer.GetCreateRoleTime(), curRequire.CreateTime))  | 
|             SetPrizeState(curPlayerID, curRequire.GUID, Disable_State, readState)  | 
|             continue  | 
|   | 
|         if limitLV > curLV:  | 
|             #µÈ¼¶²»×ã  | 
|             if limitLVType == LimitLVType_Not:  | 
|                 SetPrizeState(curPlayerID, curRequire.GUID, Disable_State, readState)  | 
|             continue  | 
|         if curRequire.PlayerJob not in (-1, 127):  | 
|             curJob = curPlayer.GetJob()  | 
|             #ÓÐÖ°ÒµÏÞÖÆ  | 
|             if (curRequire.PlayerJob&pow(2,curJob)) == 0:  | 
|                 SetPrizeState(curPlayerID, curRequire.GUID, Disable_State, readState)  | 
|                 continue  | 
|               | 
|         if curRequire.ServerID and curRequire.ServerID != GameWorld.GetPlayerServerID(curPlayer):  | 
|             # Ö¸¶¨·þÎñÆ÷Óʼþ  | 
|             SetPrizeState(curPlayerID, curRequire.GUID, Disable_State, readState)  | 
|             continue  | 
|           | 
|         #¿ÉÒÔÓõĽ±Àø  | 
|         if Enable_State != curState and curState != Yet_State:  | 
|             SetPrizeState(curPlayerID, curRequire.GUID, Enable_State, readState)  | 
|         allList.append((curRequire.GUID, curRequire.Text, curRequire.CreateTime,  | 
|                         curRequire.Gold, curRequire.GoldPaper, curRequire.Silver))  | 
|   | 
|     return allList  | 
|   | 
| ##·¢ËÍ¿ÉÁìÈ¡½±Àø²éѯ½á¹û  | 
| #  @param curPlayer, notifyList   | 
| #  @return None  | 
| def SyncQueryCompensationResult(curPlayer, notifyList):  | 
|     sendPack = ChPyNetSendPack.tagGCQueryCompensationResult()  | 
|     sendPack.Clear()  | 
|     for GUID, Text, CreateTime, gold, goldPaper, silver in notifyList:  | 
|         curGUIDItemCount = GameWorld.GetCompensationMgr().FindItemCount(GUID)  | 
|         subPack = ChPyNetSendPack.tagGCCompensationPack()  | 
|         subPack.GUID = GUID  | 
|         subPack.CreateTime = CreateTime  | 
|         subPack.Text = Text  | 
|         subPack.TextLen = len(Text)  | 
|         subPack.Gold = gold  | 
|         subPack.GoldPaper = goldPaper  | 
|         subPack.Silver = silver   | 
|         resState = GameWorld.GetCompensationMgr().FindPlayerRecState(curPlayer.GetPlayerID(), GUID)  | 
|         if resState % 10 == Yet_State:  | 
|             subPack.IsRead = Yet_State # ÒÑÁìÈ¡  | 
|         else:  | 
|             subPack.IsRead = resState / 10 # ÊÇ·ñÒѶÁ  | 
|         for index in xrange(curGUIDItemCount):  | 
|             curItem = GameWorld.GetCompensationMgr().FindItemAt(GUID, index)  | 
|             subPackItem = ChPyNetSendPack.tagGCCompensationItem()  | 
|             subPackItem.ItemID = curItem.ItemID  | 
|             subPackItem.Count = curItem.Count  | 
|             subPackItem.IsBind = curItem.IsBind  | 
|             subPackItem.UserData = curItem.UserData  | 
|             subPackItem.UserDataLen = len(curItem.UserData)  | 
|             subPack.Items.append(subPackItem)  | 
|         subPack.Count = len(subPack.Items)  | 
|         sendPack.PackList.append(subPack)  | 
|     sendPack.Count = len(sendPack.PackList)  | 
|     NetPackCommon.SendFakePack(curPlayer, sendPack)  | 
|     return  | 
|   | 
| def SyncQueryCompensationResultByGUID(curPlayer, notifyGUIDList):  | 
|     curPlayerID = curPlayer.GetPlayerID()  | 
|     notifyList = []  | 
|     compensationMgr = GameWorld.GetCompensationMgr()  | 
|     for GUID in notifyGUIDList:  | 
|         findCompensation = compensationMgr.FindPersonalCompensation(curPlayerID, GUID)  | 
|         if findCompensation.PlayerID != curPlayerID:  | 
|             findCompensation = compensationMgr.FindEntireCompensation(GUID)  | 
|             if findCompensation.GUID != GUID:  | 
|                 # ÕÒ²»µ½Óʼþ  | 
|                 continue  | 
|         notifyList.append((findCompensation.GUID, findCompensation.Text, findCompensation.CreateTime,   | 
|                            findCompensation.Gold, findCompensation.GoldPaper, findCompensation.Silver))  | 
|     if not notifyList:  | 
|         return  | 
|     SyncQueryCompensationResult(curPlayer, notifyList)  | 
|     return  | 
|   | 
| ##03 03 Íæ¼ÒÇëÇóÁìÈ¡²¹³¥#tagMGRequestCompensation  | 
| #  @param routeIndex, mapID, curPackData, tick  | 
| #  @return None  | 
| def OnMGRequestCompensation(routeIndex, mapID, curPackData, tick):  | 
|     global g_PlayerRequestStateDict  | 
|     GameWorld.DebugLog("Compensation### OnMGRequestCompensation in")  | 
|     myPlayerID = curPackData.PlayerID      | 
|     curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(myPlayerID)  | 
|     if not curPlayer:  | 
|         return  | 
|     if curPlayer.GetDictByKey(Def_RequestState):#УÑéËø  | 
|         GameWorld.DebugLog("Compensation### already request")  | 
|         return  | 
|       | 
|     curPlayer.SetDict(Def_RequestState, 1)#¼ÓËø  | 
|       | 
|     GUID = curPackData.GUID  | 
|     GameWorld.DebugLog("Compensation### OnMGRequestCompensation myPlayerID %s GUID %s"%(myPlayerID, GUID))  | 
|       | 
|     compensationType, curEntireRequire = CheckRequestCompensation(curPlayer, GUID)   | 
|     if compensationType == Unknow_CompensationType or not curEntireRequire:  | 
|         #Áìȡʧ°Ü  | 
|         curPlayer.SetDict(Def_RequestState, 0)#½âËø  | 
|         GameWorld.DebugLog("Compensation### OnMGRequestCompensation no found")  | 
|         return  | 
|     #УÑé±³°üÊ£Óà¿Õ¼äÊÇ·ñ×ã¹»  | 
|     #===========================================================================  | 
|     # curCUIDItemCount = GameWorld.GetCompensationMgr().FindItemCount(GUID)  | 
|     # if curPackData.PackSpaceCount < curCUIDItemCount:  | 
|     #    curPlayer.SetDict(Def_RequestState, 0)#½âËø  | 
|     #    GameWorld.DebugLog("Compensation### OnMGRequestCompensation no enough space")  | 
|     #    return  | 
|     #===========================================================================  | 
|     #·¢Ë͵½MapServer¸øÓè½±Àø  | 
|     SendGMRequestCompensationResult(routeIndex, mapID, curPlayer, GUID, compensationType, curEntireRequire)  | 
|     GameWorld.DebugLog("Compensation### OnMGRequestCompensation out")  | 
|       | 
| ##ÇëÇóÁìÈ¡ÎïÆ·  | 
| #  @param curPlayer, GUID   | 
| #  @return CompensationType ²¹³¥ÀàÐÍ  | 
| def CheckRequestCompensation(curPlayer, GUID, isPersonnal = True):  | 
|     curPlayerID = curPlayer.GetID()  | 
|       | 
|     states = GameWorld.GetCompensationMgr().FindPlayerRecState(curPlayerID, GUID)  | 
|     readState = states/10    # ¿É¶Á         | 
|     curState = states%10    # Áìȡ״̬  | 
|       | 
|     if curState in (Disable_State, Yet_State, Del_State):  | 
|         #²»¿ÉÁì »ò ÒÑÁì  | 
|         #GameWorld.DebugLog("µ±Ç°Óʼþ²»¿ÉÁìÈ¡»òÒÑÁì: states=%s,curState=%s,GUID=%s" % (states, curState, GUID), curPlayerID)  | 
|         return Unknow_CompensationType, None  | 
|       | 
|     if isPersonnal:  | 
|         #ÔÚ¸öÈ˲¹³¥ÖÐ  | 
|         curPersonalCompensation = GameWorld.GetCompensationMgr().FindPersonalCompensation(curPlayerID, GUID)  | 
|         if curPersonalCompensation.PlayerID == curPlayerID:  | 
|             #·µ»Ø²¹³¥ÀàÐÍ  | 
|             return Personal_CompensationType, curPersonalCompensation  | 
|           | 
|     #---------  | 
|     #ÔÚÈ«·þ²¹³¥ÖÐ  | 
|     curEntireRequire = GameWorld.GetCompensationMgr().FindEntireCompensation(GUID)  | 
|     if curEntireRequire.GUID != GUID:  | 
|         #²»ÔÙÈ«·þ²¹³¥ÖУ¬É¾³ý¼Ç¼  | 
|         GameWorld.GetCompensationMgr().DeletePlayerCompensationRec(curPlayerID, GUID)  | 
|         return Unknow_CompensationType, None  | 
|       | 
|     checkState, limitLVType, limitLV = ParseEntireCompensationInfo(curEntireRequire.PlayerLV)  | 
|     if checkState == CheckState_No:  | 
|         isTestAccID = GameWorld.GetPlatformAccID(curPlayer.GetAccID()) in ReadChConfig.GetEvalChConfig("TestAccID")  | 
|         if not isTestAccID:  | 
|             #δÉóºËµÄÓʼþ²»´¦Àí  | 
|             return Unknow_CompensationType, None  | 
|           | 
|     #δ֪ͨ¹ý£¬ÇÒÒѳ¬Ê±  | 
|     limitTime = datetime.datetime.strptime(curEntireRequire.LimitTime, ChConfig.TYPE_Time_Format)  | 
|     curTime = datetime.datetime.today()  | 
|     if limitTime < curTime and Unknown_State == curState:  | 
|         #³¬Ê±£¬ÉèÖóɲ»¿ÉÁìÈ¡  | 
|         SetPrizeState(curPlayerID, GUID, Disable_State, readState)  | 
|         return Unknow_CompensationType, None  | 
|   | 
|     if Enable_State == curState:  | 
|         #¿ÉÁìÈ¡ÇÒδ³¬Ê±£¬·µ»ØÎïÆ·ÐÅÏ¢  | 
|         return Entire_CompensationType, curEntireRequire  | 
|       | 
|     curLV = curPlayer.GetLV()  | 
|     if limitLV > curLV:  | 
|         #µÈ¼¶²»×ã  | 
|         if limitLVType == LimitLVType_Not:  | 
|             SetPrizeState(curPlayerID, GUID, Disable_State, readState)  | 
|         return Unknow_CompensationType, None  | 
|     curJob = curPlayer.GetJob()  | 
|     if curEntireRequire.PlayerJob not in (-1, 127):  | 
|         #ÓÐÖ°ÒµÏÞÖÆ  | 
|         if (curEntireRequire.PlayerJob&pow(2,curJob)) == 0:  | 
|             SetPrizeState(curPlayerID, GUID, Disable_State, readState)  | 
|             return Unknow_CompensationType, None  | 
|       | 
|     if curEntireRequire.ServerID and curEntireRequire.ServerID != GameWorld.GetPlayerServerID(curPlayer):  | 
|         # Ö¸¶¨·þÎñÆ÷Óʼþ  | 
|         SetPrizeState(curPlayerID, GUID, Disable_State, readState)  | 
|         return Unknow_CompensationType, None  | 
|        | 
|     #¿ÉÒÔÓõĽ±Àø  | 
|     SetPrizeState(curPlayerID, GUID, Enable_State, readState)  | 
|     #·µ»ØÎïÆ·ÐÅÏ¢     | 
|     return Entire_CompensationType, curEntireRequire  | 
|   | 
| ##·¢ËÍ·â°ü 03 02 Íæ¼ÒÁìÈ¡²¹³¥½á¹û#tagGMRequestCompensationResult  | 
| #  @param routeIndex, mapID, curPlayer, curItem  | 
| #  @return None  | 
| def SendGMRequestCompensationResult(routeIndex, mapID, curPlayer, GUID, compensationType, curEntireRequire):  | 
|       | 
|     Text, gold, goldPaper, silver, createTime = curEntireRequire.Text, curEntireRequire.Gold, \  | 
|         curEntireRequire.GoldPaper, curEntireRequire.Silver, curEntireRequire.CreateTime  | 
|     # È«·þÓʼþûÓРType ×Ö¶Î  | 
|     moneySource = curEntireRequire.Type if compensationType == Personal_CompensationType else 0  | 
|       | 
|     sendPack = ChGameToMapPyPack.tagGMRequestCompensationResult()   | 
|     sendPack.PlayerID = curPlayer.GetID()  | 
|     sendPack.CompensationType = compensationType  | 
|     sendPack.GUID = GUID  | 
|     sendPack.CreateTime = createTime  | 
|     sendPack.Text = Text  | 
|     sendPack.TextLen = len(Text)  | 
|     sendPack.Gold = gold  | 
|     sendPack.GoldPaper = goldPaper  | 
|     sendPack.Silver = silver  | 
|     sendPack.MoneySource = moneySource  | 
|     curGUIDItemCount = GameWorld.GetCompensationMgr().FindItemCount(GUID)  | 
|       | 
|     for i in xrange(curGUIDItemCount):  | 
|         curItem = GameWorld.GetCompensationMgr().FindItemAt(GUID, i)  | 
|         subPackItem = ChGameToMapPyPack.tagGMCompensationItem()  | 
|         subPackItem.ItemID = curItem.ItemID  | 
|         subPackItem.Count = curItem.Count  | 
|         subPackItem.IsBind = curItem.IsBind  | 
|         subPackItem.UserData = curItem.UserData  | 
|         subPackItem.UserDataLen = len(curItem.UserData)  | 
|         sendPack.Items.append(subPackItem)  | 
|     sendPack.Count = len(sendPack.Items)  | 
|     NetPackCommon.SendPyPackToMapServer(routeIndex, mapID, sendPack)   | 
|     return  | 
|   | 
|   | 
| ##03 04 Íæ¼ÒÁìÈ¡²¹³¥ÎïÆ··¢·Å½á¹û#tagMGGiveCompensationResult  | 
| #  @param routeIndex, mapID, curPackData, tick  | 
| #  @return None  | 
| def OnMGGiveCompensationResult(routeIndex, mapID, curPackData, tick):  | 
|       | 
|     myPlayerID = curPackData.PlayerID  | 
|     curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(myPlayerID)  | 
|     if not curPlayer:  | 
|         return  | 
|     GUID = curPackData.GUID  | 
|     CompensationType = curPackData.CompensationType  | 
|     curPlayer.SetDict(Def_RequestState, 0)#½âËø  | 
|     if curPackData.Result:  | 
|         GiveCompensationSuccess(curPlayer, GUID, CompensationType)  | 
|     return  | 
|   | 
|   | 
|   | 
| ##Íæ¼ÒÁìÈ¡²¹³¥ÎïÆ··¢·Å³É¹¦  | 
| #  @param curPlayer, GUID  | 
| #  @return None  | 
| def GiveCompensationSuccess(curPlayer, GUID, CompensationType, isDel=False):  | 
|     curPlayerID = curPlayer.GetID()  | 
|     SetPrizeState(curPlayerID, GUID, Yet_State, Read_State_Yes) # ÉèÖÃΪÒÑÁìÈ¡  | 
|     #Á÷Ïò¼Ç¼  | 
|     DataRecordPack.DR_GiveCompensationSuccess(curPlayerID, GUID)  | 
|     if not isDel:  | 
|         SyncQueryCompensationResultByGUID(curPlayer, [GUID])  | 
|         return  | 
|       | 
|     NotifyCompensationResult(curPlayer, GUID, 1)  | 
|       | 
|     #È«·þ½±ÀøÁìÈ¡¼Ç¼±ä¸üΪÒÑÁìÈ¡  | 
|     if CompensationType == Entire_CompensationType:  | 
|         SetPrizeState(curPlayerID, GUID, Del_State, Read_State_Yes)  | 
|         return  | 
|     #¸öÈ˽±ÀøÁìÈ¡ÌõĿִÐÐɾ³ý  | 
|     if CompensationType == Personal_CompensationType:  | 
|         ClearPersonalCompensation(curPlayerID, GUID)  | 
|         return  | 
|       | 
|     return  | 
|   | 
| ##ÇåÀí³¬Ê±È«·þ²¹³¥, È«·þÓʼþ·ÖÁ½²¿´¦Àí£º1. Óʼþ½ÓÊÕµÄÓÐЧʱ¼ä£¬ºǫ́ÉèÖã¬2. Óʼþɾ³ýʱ¼äΪ½ÓÊÕÓÐЧʱ¼äÔÙÑÓ³¤30Ìì  | 
| #  @param None  | 
| #  @return None  | 
| def ClearUpEntireCompensation():  | 
|     #УÑé¹ýÆÚ²¹³¥  | 
|     curTime = datetime.datetime.today()  | 
|     needClearGUIDList = []  | 
|     entireCnt = GameWorld.GetCompensationMgr().GetEntireCompensationCount()  | 
|     for i in xrange(entireCnt):  | 
|         curEntireRequire = GameWorld.GetCompensationMgr().AtEntireCompensation(i)  | 
|         # ³¬¹ý½ÓÊÕÓʼþ30ÌìÔòÍêȫɾ³ý´ËÓʼþ  | 
|         limitTime = datetime.datetime.strptime(curEntireRequire.LimitTime, ChConfig.TYPE_Time_Format) + datetime.timedelta(days = 30)  | 
|         if limitTime < curTime:  | 
|             needClearGUIDList.append(curEntireRequire.GUID)  | 
|               | 
|     #ɾ³ý¹ýÆÚ²¹³¥ÐÅÏ¢£¬ Ã»ÓÐÖ÷¶¯Í¨ÖªÔÚÏßÍæ¼Ò  | 
|     for GUID in needClearGUIDList:  | 
|         #ɾ³ýÁìÈ¡Ìõ¼þ  | 
|         GameWorld.GetCompensationMgr().DeleteEntireCompensation(GUID)  | 
|         #ɾ³ý¹ýÆÚÎïÆ·  | 
|         GameWorld.GetCompensationMgr().DeleteCompensationItem(GUID)  | 
|         #Çå³ýÁìȡ״̬¼Ç¼¾Í  | 
|         GameWorld.GetCompensationMgr().DeleteRecByGUID(GUID)  | 
|     return  | 
|   | 
|   | 
| ##ÇåÀí³¬Ê±30ÌìµÄ¸öÈËÓʼþ, ·ñÔòÁ÷Ê§Íæ¼ÒÔÚ²»¶ÏºÏ·þÇé¿öÏÂÊý¾Ý»áÀÛ»ý  | 
| # ¸öÈËÓʼþÔÝÎÞ¹ýÆÚʱ¼äÉ趨£¬Ö»ÓÐ30ÌìÇåÀíÂß¼,ÒÔ´´½¨Ê±¼äΪ׼  | 
| #  @param None  | 
| #  @return None  | 
| def ClearUpPersonalCompensation():  | 
|     #УÑé¹ýÆÚ²¹³¥  | 
|     tempSign = "<MailTemplate>"  | 
|     tempSignEnd = "</MailTemplate>"  | 
|     curTime = datetime.datetime.today()  | 
|     needClearGUIDList = []  | 
|     allCnt = GameWorld.GetCompensationMgr().GetAllPersonalCompensationCount()  | 
|     for i in xrange(allCnt):  | 
|         curMail = GameWorld.GetCompensationMgr().AtAllPersonalCompensation(i)  | 
|           | 
|         mailText = curMail.Text  | 
|         # Í¨ÖªÀàÄ£°åÓʼþ£¬¹ýÌì¿ÉÖ±½Óɾ³ý  | 
|         if tempSign in mailText and tempSignEnd in mailText and CheckCanDelCompensation(curMail, curMail.GUID, curMail.PlayerID):  | 
|             tempKey = mailText[mailText.index(tempSign) + len(tempSign):mailText.index(tempSignEnd)]  | 
|             notClearMailKeyList = IpyGameDataPY.GetFuncEvalCfg("MailSet", 1)  | 
|             if tempKey not in notClearMailKeyList:  | 
|                 #GameWorld.DebugLog("¹ýÌìɾ³ýÎÞ¸½¼þ֪ͨÀàÓʼþÄ£°å! tempKey=%s %s, %s" % (tempKey, curMail.PlayerID, curMail.GUID))  | 
|                 needClearGUIDList.append([curMail.PlayerID, curMail.GUID])  | 
|                 player = GameWorld.GetPlayerManager().FindPlayerByID(curMail.PlayerID)  | 
|                 if player and player.GetInitOK():  | 
|                     NotifyCompensationResult(player, curMail.GUID, 1)  | 
|                 continue  | 
|           | 
|         # ³¬¹ý½ÓÊÕÓʼþ30ÌìÔòÍêȫɾ³ý´ËÓʼþ  | 
|         limitTime = datetime.datetime.strptime(curMail.CreateTime, ChConfig.TYPE_Time_Format) + datetime.timedelta(days = 30)  | 
|         if limitTime < curTime:  | 
|             needClearGUIDList.append([curMail.PlayerID, curMail.GUID])  | 
|       | 
|     GameWorld.Log("ClearUpPersonalCompensation count=%s"%len(needClearGUIDList))  | 
|           | 
|     #ɾ³ý¹ýÆÚ²¹³¥ÐÅÏ¢£¬ Ã»ÓÐÖ÷¶¯Í¨ÖªÔÚÏßÍæ¼Ò  | 
|     for playerID, GUID in needClearGUIDList:  | 
|         ClearPersonalCompensation(playerID, GUID, "Timeout")  | 
|     return  | 
|   | 
| ## ÇåÀí³¬Ê±²¹³¥, ¸öÈËÓʼþÔÚ³¬¹ýÉÏÏÞºó²Å»á×Ô¶¯É¾³ý  | 
| #  @param None  | 
| #  @return None  | 
| def ClearUpTimeOutCompensation():  | 
|       | 
|     ClearUpPersonalCompensation()  | 
|     ClearUpEntireCompensation()  | 
|     return  | 
|   | 
|   | 
| #===============================================================================  | 
| # //A9 A6 ÉèÖÃÓʼþ£¨²¹³¥£©ÒѶÁ״̬ #tagCGReadCompensation  | 
| #   | 
| # struct    tagCGReadCompensation  | 
| # {  | 
| #    tagHead        Head;  | 
| #    char        GUID[40];  | 
| #    BYTE        IsRead;        //ÉèÖÃÓʼþ£¨²¹³¥£©ÊÇ·ñÒѶÁ 1¶ÁÈ¡  | 
| # };  | 
| #===============================================================================  | 
| def OnReadCompensation(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|       | 
|     GUID = clientData.GUID  | 
|     curPlayerID = curPlayer.GetID()  | 
|       | 
|     #ÔÚ¸öÈ˲¹³¥ÖÐ  | 
|     curPersonalCompensation = GameWorld.GetCompensationMgr().FindPersonalCompensation(curPlayerID, GUID)  | 
|     if curPersonalCompensation.PlayerID != curPlayerID:  | 
|         curEntireRequire = GameWorld.GetCompensationMgr().FindEntireCompensation(GUID)  | 
|         if curEntireRequire.GUID != GUID:  | 
|             #GameWorld.DebugLog("ÕÒ²»µ½ÓʼþGUID:%s"%GUID)  | 
|             # ÕÒ²»µ½Óʼþ  | 
|             return  | 
|     curState = GameWorld.GetCompensationMgr().FindPlayerRecState(curPlayerID, GUID)  | 
|     if curState/10 >= Read_State_Yes:  | 
|         # ÒѶÁ  | 
|         #GameWorld.DebugLog("ÒѶÁGUID:%s"%GUID)  | 
|         return  | 
|     curState = Read_State_Yes*10 + curState%10  | 
|     GameWorld.GetCompensationMgr().AddPlayerRec(curPlayerID, GUID, curState)  | 
|     #GameWorld.DebugLog("ÒѶÁcurState:%s"%curState)  | 
|     return  | 
|   | 
| #===============================================================================  | 
| # //A9 A7 É¾³ýÓʼþ£¨²¹³¥£© #tagCGDelCompensation  | 
| #   | 
| # struct    tagCGDelCompensation  | 
| # {  | 
| #    tagHead        Head;  | 
| #    char        GUID[40];  | 
| # };  | 
| #===============================================================================  | 
| def OnDelCompensation(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     GUID = clientData.GUID  | 
|     curPlayerID = curPlayer.GetID()  | 
|       | 
|     #ÔÚ¸öÈ˲¹³¥ÖÐ  | 
|     curPersonalCompensation = GameWorld.GetCompensationMgr().FindPersonalCompensation(curPlayerID, GUID)  | 
|     if curPersonalCompensation.PlayerID == curPlayerID:  | 
|         if not CheckCanDelCompensation(curPersonalCompensation, GUID, curPlayerID):  | 
|             #Óи½¼þ²»¿Éɾ³ý  | 
|             GameWorld.DebugLog("¸Ã¸öÈËÓʼþ²»¿Éɾ³ý: %s" % GUID, curPlayerID)  | 
|             NotifyCompensationResult(curPlayer, GUID, 0)  | 
|             return  | 
|           | 
|         ClearPersonalCompensation(curPlayerID, GUID, "ClientDel")  | 
|         NotifyCompensationResult(curPlayer, GUID, 1)  | 
|         #GameWorld.DebugLog("¸öÈ˲¹³¥ÖÐOnDelCompensation:%s"%GUID)  | 
|         return  | 
|       | 
|     curEntireRequire = GameWorld.GetCompensationMgr().FindEntireCompensation(GUID)  | 
|     if curEntireRequire.GUID != GUID:  | 
|         # ÕÒ²»µ½Óʼþ  | 
|         NotifyCompensationResult(curPlayer, GUID, 0)  | 
|         #GameWorld.DebugLog("ÕÒ²»µ½ÓʼþOnDelCompensation:%s"%GUID)  | 
|         return  | 
|       | 
|     #È«·þÓʼþ  | 
|     curEntireRequire = GameWorld.GetCompensationMgr().FindEntireCompensation(GUID)  | 
|     if curEntireRequire.GUID == GUID:  | 
|         if not CheckCanDelCompensation(curEntireRequire, GUID, curPlayerID):  | 
|             #Óи½¼þ²»¿Éɾ³ý  | 
|             GameWorld.DebugLog("¸ÃÈ«·þÓʼþ²»¿Éɾ³ý: %s" % GUID, curPlayerID)  | 
|             NotifyCompensationResult(curPlayer, GUID, 0)  | 
|             return  | 
|           | 
|         SetPrizeState(curPlayerID, GUID, Del_State, GameWorld.GetCompensationMgr().FindPlayerRecState(curPlayerID, GUID)/10)  | 
|         NotifyCompensationResult(curPlayer, GUID, 1)  | 
|         #GameWorld.DebugLog("È«·þÓʼþOnDelCompensation:%s"%GUID)  | 
|         return  | 
|   | 
|     NotifyCompensationResult(curPlayer, GUID, 0)  | 
|          | 
| # Óи½¼þµÄÇé¿öÍæ¼Ò²»¿ÉÖ÷¶¯É¾³ýÓʼþ£¬±ÜÃâÎó²Ù×÷£»ÏµÍ³¿Éɾ³ý²»Óõ÷ÓÃ´Ë½Ó¿Ú  | 
| def CheckCanDelCompensation(mailObj, GUID, playerID=0):  | 
|     if playerID:  | 
|         if GetPrizeGetState(playerID, GUID) == Yet_State:  | 
|             #GameWorld.DebugLog("ÒÑÁìÈ¡µÄÓʼþ¿Éɾ³ý: %s" % GUID, playerID)  | 
|             return True  | 
|           | 
|     if mailObj.Gold or mailObj.GoldPaper or mailObj.Silver:  | 
|         # Óи½¼Ó»õ±Ò²»¿Éɾ³ý  | 
|         return False  | 
|       | 
|     if GameWorld.GetCompensationMgr().FindItemCount(GUID):  | 
|         # Óи½¼þÎïÆ·²»¿Éɾ³ý  | 
|         return False  | 
|     return True  | 
|           | 
| # Óʼþɾ³ýÇé¿ö     | 
| def NotifyCompensationResult(curPlayer, GUID, result):      | 
|     sendMCPack = ChPyNetSendPack.tagGCDelCompensationResult()  | 
|     sendMCPack.GUID = GUID  | 
|     sendMCPack.Result = result  | 
|     NetPackCommon.SendFakePack(curPlayer, sendMCPack)  | 
|       | 
|      |