| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package PlayerCharm  | 
| #  | 
| # @todo:÷ÈÁ¦ÏµÍ³  | 
| # @author hxp  | 
| # @date 2021-11-17  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ÷ÈÁ¦ÏµÍ³  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2021-11-17 15:00"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import CommFunc  | 
| import ShareDefine  | 
| import PlayerControl  | 
| import ChPyNetSendPack  | 
| import PyGameDataStruct  | 
| import PlayerBillboard  | 
| import NetPackCommon  | 
| import PyDataManager  | 
| import PlayerSocial  | 
| import GameWorld  | 
|   | 
| import operator  | 
| import random  | 
| import time  | 
|   | 
| CharmValueRecTypeList = (  | 
| CharmValueRecType_Total, # ×Ü - 1  | 
| CharmValueRecType_Week, # ÖÜ - 2  | 
| CharmValueRecType_Day, # ÈÕ - 3  | 
| ) = range(1, 1 + 3)  | 
|       | 
| class DBPyCharmValueRecManager(object):  | 
|     ## ÷ÈÁ¦¹±Ï׼Ǽ¹ÜÀí  | 
|       | 
|     def __init__(self):  | 
|         self.charmValueRecDict = {} # ÷ÈÁ¦¹±Ï׼Ǽ×Öµä {playerID:{recType:{offerPlayerID:PyGameDataStruct.tagDBPyCharmValueRec, ...}, ...}}  | 
|         self.charmTotalDict = {} # ×Ü÷ÈÁ¦  {playerID:{recType:totalCharm, ...}, ...}  | 
|         self.charmSortListDict = {} # ÅÅÐòºóµÄ¹±Ï׼Ǽ {playerID:{recType:[PyGameDataStruct.tagDBPyCharmValueRec, ...], ...}}  | 
|         return  | 
|       | 
|     def ClearCharmByType(self, recType):  | 
|         for recTypeDict in self.charmValueRecDict.values():  | 
|             recTypeDict.pop(recType, None)  | 
|               | 
|         for recTypeDict in self.charmTotalDict.values():  | 
|             recTypeDict.pop(recType, None)  | 
|               | 
|         for recTypeDict in self.charmSortListDict.values():  | 
|             recTypeDict.pop(recType, None)  | 
|         return  | 
|       | 
|     # ±£´æÊý¾Ý ´æÊý¾Ý¿âºÍrealtimebackup  | 
|     def GetSaveData(self):  | 
|         savaData = ""  | 
|         cntData = ""  | 
|         cnt = 0  | 
|           | 
|         for recTypeDict in self.charmValueRecDict.values():  | 
|             for offerPlayerDict in recTypeDict.values():  | 
|                 for recData in offerPlayerDict.values():  | 
|                     cnt += 1  | 
|                     savaData += recData.getBuffer()  | 
|                   | 
|         GameWorld.Log("Save DBPyCharmValueRec 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 DBPyCharmValueRec count :%s" % cnt)  | 
|           | 
|         for _ in xrange(cnt):  | 
|             recData = PyGameDataStruct.tagDBPyCharmValueRec()  | 
|             recData.clear()  | 
|             pos += recData.readData(datas, pos, dataslen)  | 
|               | 
|             playerID = recData.PlayerID  | 
|             recType = recData.Type  | 
|             offerPlayerID = recData.OfferPlayerID  | 
|               | 
|             if playerID not in self.charmValueRecDict:  | 
|                 self.charmValueRecDict[playerID] = {}  | 
|             recTypeDataDict = self.charmValueRecDict[playerID]  | 
|             if recType not in recTypeDataDict:  | 
|                 recTypeDataDict[recType] = {}  | 
|             offerPlayerDict = recTypeDataDict[recType]  | 
|             offerPlayerDict[offerPlayerID] = recData  | 
|               | 
|             if playerID not in self.charmTotalDict:  | 
|                 self.charmTotalDict[playerID] = {}  | 
|             recTypeValueDict = self.charmTotalDict[playerID]  | 
|             recTypeValueDict[recType] = recTypeValueDict.get(recType, 0) + recData.CharmValue  | 
|               | 
|         return pos  | 
|       | 
| def DoOnWeek():  | 
|     PlayerBillboard.ClearBillboardByIndex(ShareDefine.Def_BT_CharmWeek)  | 
|     PyDataManager.GetDBPyCharmValueRecManager().ClearCharmByType(CharmValueRecType_Week)  | 
|     playerManager = GameWorld.GetPlayerManager()  | 
|     for i in xrange(playerManager.GetActivePlayerCount()):  | 
|         curPlayer = playerManager.GetActivePlayerAt(i)  | 
|         if not curPlayer or PlayerControl.GetIsTJG(curPlayer):  | 
|             continue  | 
|         Sync_PlayerCharmInfo(curPlayer)  | 
|     return  | 
|   | 
| def DoOnDay():  | 
|     PlayerBillboard.ClearBillboardByIndex(ShareDefine.Def_BT_CharmDay)  | 
|     PyDataManager.GetDBPyCharmValueRecManager().ClearCharmByType(CharmValueRecType_Day)  | 
|     playerManager = GameWorld.GetPlayerManager()  | 
|     for i in xrange(playerManager.GetActivePlayerCount()):  | 
|         curPlayer = playerManager.GetActivePlayerAt(i)  | 
|         if not curPlayer or PlayerControl.GetIsTJG(curPlayer):  | 
|             continue  | 
|         Sync_PlayerCharmInfo(curPlayer)  | 
|     return  | 
|   | 
| def OnPlayerLogin(curPlayer):  | 
|     Sync_PlayerCharmInfo(curPlayer)  | 
|     return  | 
|   | 
| def OnMixServerFirstLogin(curPlayer):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     charmValueRecMgr = PyDataManager.GetDBPyCharmValueRecManager()  | 
|     if playerID not in charmValueRecMgr.charmTotalDict:  | 
|         return  | 
|     recTypeValueDict = charmValueRecMgr.charmTotalDict.get(playerID, {})  | 
|     charmTotal = recTypeValueDict.get(CharmValueRecType_Total, 0)  | 
|     charmWeek = recTypeValueDict.get(CharmValueRecType_Week, 0)  | 
|     charmDay = recTypeValueDict.get(CharmValueRecType_Day, 0)  | 
|     GameWorld.Log("ºÏ·þÊ×µÇͬ²½÷ÈÁ¦°ñµ¥: charmTotal=%s,charmWeek=%s,charmDay=%s" % (charmTotal, charmWeek, charmDay), playerID)  | 
|     PlayerBillboard.UpdatePlayerBillboardEx(curPlayer, playerID, ShareDefine.Def_BT_CharmTotal, charmTotal)  | 
|     PlayerBillboard.UpdatePlayerBillboardEx(curPlayer, playerID, ShareDefine.Def_BT_CharmWeek, charmWeek)  | 
|     PlayerBillboard.UpdatePlayerBillboardEx(curPlayer, playerID, ShareDefine.Def_BT_CharmDay, charmDay)  | 
|     return  | 
|   | 
| def GetPlayerCharmOfferSortList(playerID, recType):  | 
|     ## »ñÈ¡ÅÅÐòºóµÄÍæ¼Ò÷ÈÁ¦¹±Ï×°ñ  | 
|       | 
|     charmValueRecMgr = PyDataManager.GetDBPyCharmValueRecManager()  | 
|     if playerID not in charmValueRecMgr.charmValueRecDict:  | 
|         return []  | 
|     recTypeDataDict = charmValueRecMgr.charmValueRecDict[playerID]  | 
|     if recType not in recTypeDataDict:  | 
|         return []  | 
|     offerPlayerDict = recTypeDataDict[recType]  | 
|       | 
|     if playerID not in charmValueRecMgr.charmSortListDict:  | 
|         charmValueRecMgr.charmSortListDict[playerID] = {}  | 
|     recTypeSortListDict = charmValueRecMgr.charmSortListDict[playerID]  | 
|     if recType not in recTypeSortListDict:  | 
|         # ÅÅÐò  | 
|         recDataList = offerPlayerDict.values()  | 
|         recDataList.sort(key=operator.attrgetter("CharmValue", "UpdTime"), reverse=True)  | 
|         recTypeSortListDict[recType] = recDataList  | 
|           | 
|     return recTypeSortListDict[recType]  | 
|   | 
| def AddCharm(curPlayer, playerID, offerPlayerID, addValue, isNotify=True):  | 
|     ''' Ìí¼Ó÷ÈÁ¦  | 
|     @param curPlayer: Ôö¼Ó÷ÈÁ¦µÄÍæ¼ÒʵÀý£¬¿ÉÄÜΪNone  | 
|     @param offerPlayerID: ÷ÈÁ¦¹±Ï×Íæ¼ÒID  | 
|     @param addValue: Ôö¼Ó÷ÈÁ¦Öµ  | 
|     '''  | 
|       | 
|     charmValueRecMgr = PyDataManager.GetDBPyCharmValueRecManager()  | 
|     if playerID not in charmValueRecMgr.charmValueRecDict:  | 
|         charmValueRecMgr.charmValueRecDict[playerID] = {}  | 
|     recTypeDataDict = charmValueRecMgr.charmValueRecDict[playerID]  | 
|       | 
|     if playerID not in charmValueRecMgr.charmTotalDict:  | 
|         charmValueRecMgr.charmTotalDict[playerID] = {}  | 
|     recTypeValueDict = charmValueRecMgr.charmTotalDict[playerID]  | 
|       | 
|     updTime = max(0, GameWorld.ChangeTimeStrToNum("2090-01-01 00:00:00") - int(time.time())) # ÓÃÓÚµ¹ÐòÅÅÐò  | 
|     for recType in CharmValueRecTypeList:  | 
|         if recType not in recTypeDataDict:  | 
|             recTypeDataDict[recType] = {}  | 
|         offerPlayerDict = recTypeDataDict[recType]  | 
|           | 
|         if offerPlayerID not in offerPlayerDict:  | 
|             offerPlayerDict[offerPlayerID] = PyGameDataStruct.tagDBPyCharmValueRec()  | 
|         recData = offerPlayerDict[offerPlayerID]  | 
|           | 
|         curValue = recData.CharmValue  | 
|         recData.PlayerID = playerID  | 
|         recData.Type = recType  | 
|         recData.OfferPlayerID = offerPlayerID  | 
|         recData.CharmValue += addValue  | 
|         recData.UpdTime = updTime  | 
|           | 
|         typeTotalValue = recTypeValueDict.get(recType, 0)  | 
|         recTypeValueDict[recType] = typeTotalValue + addValue  | 
|           | 
|         GameWorld.DebugLog("Ôö¼Ó÷ÈÁ¦¼Ç¼: playerID=%s,recType=%s,offerPlayerID=%s,addValue=%s,updValue=(%s-%s),updTime=%s,typeTotalValue=(%s-%s)"   | 
|                            % (playerID, recType, offerPlayerID, addValue, curValue, recData.CharmValue, updTime, typeTotalValue, recTypeValueDict[recType]), playerID)  | 
|           | 
|     # °ñµ¥  | 
|     charmTotal = recTypeValueDict.get(CharmValueRecType_Total, 0)  | 
|     charmWeek = recTypeValueDict.get(CharmValueRecType_Week, 0)  | 
|     charmDay = recTypeValueDict.get(CharmValueRecType_Day, 0)  | 
|     PlayerBillboard.UpdatePlayerBillboardEx(curPlayer, playerID, ShareDefine.Def_BT_CharmTotal, charmTotal)  | 
|     PlayerBillboard.UpdatePlayerBillboardEx(curPlayer, playerID, ShareDefine.Def_BT_CharmWeek, charmWeek)  | 
|     PlayerBillboard.UpdatePlayerBillboardEx(curPlayer, playerID, ShareDefine.Def_BT_CharmDay, charmDay)  | 
|       | 
|     charmValueRecMgr.charmSortListDict.pop(playerID, None) # Êý¾Ý±ä¸üÊ±ÒÆ³ý£¬Ï´ÎÓõ½Ê±ÔÙÖØÐÂÅÅÐòÉú³É  | 
|       | 
|     if not curPlayer:  | 
|         return  | 
|       | 
|     if not isNotify:  | 
|         return  | 
|       | 
|     PlayerControl.NotifyCode(curPlayer, "AddCharm", [addValue])  | 
|     Sync_PlayerCharmInfo(curPlayer)  | 
|     return  | 
|   | 
| def Sync_PlayerCharmInfo(curPlayer, isForce=False):  | 
|     ## Í¬²½÷ÈÁ¦ÐÅÏ¢  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     charmValueRecMgr = PyDataManager.GetDBPyCharmValueRecManager()  | 
|     if playerID not in charmValueRecMgr.charmTotalDict and not isForce:  | 
|         return  | 
|     recTypeValueDict = charmValueRecMgr.charmTotalDict.get(playerID, {})  | 
|     clientPack = ChPyNetSendPack.tagGCPlayerCharmValueInfo()  | 
|     clientPack.CharmValueTotal = recTypeValueDict.get(CharmValueRecType_Total, 0)  | 
|     clientPack.CharmValueWeek = recTypeValueDict.get(CharmValueRecType_Week, 0)  | 
|     clientPack.CharmValueDay = recTypeValueDict.get(CharmValueRecType_Day, 0)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  | 
|   | 
| #// B3 09 ÷ÈÁ¦¹±Ï×°ñ²é¿´ #tagCGCharmOfferBillboardQuery  | 
| #  | 
| #struct    tagCGCharmOfferBillboardQuery  | 
| #{  | 
| #    tagHead        Head;  | 
| #    DWORD        PlayerID;        // ÷ÈÁ¦Íæ¼ÒID  | 
| #    BYTE        QueryType;    // ²é¿´ÀàÐÍ£º 1-×ܰñ£¬2-Öܰñ£¬3-ÈÕ°ñ  | 
| #    BYTE        QueryCount;    // ²é¿´Ãû´ÎÊýÁ¿£¬×î´ó255  | 
| #};  | 
| def OnCharmOfferBillboardQuery(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     tagPlayerID = clientData.PlayerID  | 
|     queryType = clientData.QueryType  | 
|     queryCount = min(clientData.QueryCount, 255)  | 
|       | 
|     sortList = GetPlayerCharmOfferSortList(tagPlayerID, queryType)  | 
|     clientPack = ChPyNetSendPack.tagGCCharmOfferBillboardDataList()  | 
|     clientPack.PlayerID = tagPlayerID  | 
|     clientPack.QueryType = queryType  | 
|     clientPack.OfferBillboardDataList = []  | 
|     for i, recData in enumerate(sortList[:queryCount]):  | 
|         billboardData = ChPyNetSendPack.tagGCCharmOfferBillboardData()  | 
|         billboardData.OrderIndex = i  | 
|         billboardData.PlayerID = recData.OfferPlayerID  | 
|         billboardData.PlayerName = PlayerSocial.GetSocialPlayerName(billboardData.PlayerID)  | 
|         billboardData.NameLen = len(billboardData.PlayerName)  | 
|         billboardData.CharmValue = recData.CharmValue  | 
|         clientPack.OfferBillboardDataList.append(billboardData)  | 
|     clientPack.DataCount = len(clientPack.OfferBillboardDataList)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  | 
|   | 
| #// B3 19 ÌáÉý÷ÈÁ¦µÈ¼¶ #tagCGCharmLVUp  | 
| #  | 
| #struct    tagCGCharmLVUp  | 
| #{  | 
| #    tagHead        Head;  | 
| #};  | 
| def OnCharmLVUp(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)      | 
|     playerID = curPlayer.GetPlayerID()  | 
|           | 
|     totalCharm = 0  | 
|     charmValueRecMgr = PyDataManager.GetDBPyCharmValueRecManager()  | 
|     if playerID in charmValueRecMgr.charmTotalDict:  | 
|         recTypeValueDict = charmValueRecMgr.charmTotalDict.get(playerID, {})  | 
|         totalCharm = recTypeValueDict.get(CharmValueRecType_Total, 0)  | 
|           | 
|     PlayerControl.MapServer_QueryPlayer_DoLogic(curPlayer, "Charm", ["CharmLVUp", totalCharm], curPlayer.GetID())  | 
|     return  | 
|   | 
| def GMClearCharm():  | 
|     ## GMÇå¿Õ÷ÈÁ¦  | 
|     GameWorld.Log("GMÇå¿Õ÷ÈÁ¦")  | 
|     charmValueRecMgr = PyDataManager.GetDBPyCharmValueRecManager()  | 
|     charmValueRecMgr.charmValueRecDict = {}  | 
|     charmValueRecMgr.charmTotalDict = {}  | 
|     charmValueRecMgr.charmSortListDict = {}  | 
|     playerManager = GameWorld.GetPlayerManager()  | 
|     for i in xrange(playerManager.GetActivePlayerCount()):  | 
|         curPlayer = playerManager.GetActivePlayerAt(i)  | 
|         if not curPlayer or PlayerControl.GetIsTJG(curPlayer):  | 
|             continue  | 
|         Sync_PlayerCharmInfo(curPlayer, True)  | 
|     GameWorld.DebugAnswer(curPlayer, "GMÇå¿Õ÷ÈÁ¦OK")  | 
|     return  | 
|   | 
| def GMRandCharm(curPlayer, playerCount, offerCount, randA, randB):  | 
|     ## GMËæ»úÔö¼Ó÷ÈÁ¦Êý¾Ý  | 
|     GameWorld.Log("GMËæ»úÔö¼Ó÷ÈÁ¦Êý¾Ý: playerCount=%s,offerCount=%s,randA=%s,randB=%s" % (playerCount, offerCount, randA, randB))  | 
|     playerDict = {}  | 
|     playerManager = GameWorld.GetPlayerManager()  | 
|     for i in xrange(playerManager.GetActivePlayerCount()):  | 
|         player = playerManager.GetActivePlayerAt(i)  | 
|         if not player or PlayerControl.GetIsTJG(player):  | 
|             continue  | 
|         playerDict[player.GetPlayerID()] = player  | 
|           | 
|     playerCount = min(1000, playerCount)  | 
|     if len(playerDict) < playerCount:  | 
|         lackCount = playerCount - len(playerDict)  | 
|         for testPlayerID in xrange(1000, 1000 + lackCount):  | 
|             playerDict[testPlayerID] = None  | 
|               | 
|     for playerID, player in playerDict.items():  | 
|         for offerPlayerID in xrange(2000, 2000 + offerCount):  | 
|             addValue = random.randint(randA, randB)  | 
|             AddCharm(player, playerID, offerPlayerID, addValue, False)  | 
|         if player:  | 
|             Sync_PlayerCharmInfo(player)  | 
|               | 
|     GameWorld.DebugAnswer(curPlayer, "GMËæ»úÔö¼Ó÷ÈÁ¦Êý¾ÝOK")   | 
|     return  | 
|   |