| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package CrossLuckyCloudBuy  | 
| #  | 
| # @todo:ÐÒÔËÔÆ¹º  | 
| # @author hxp  | 
| # @date 2021-10-21  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ÐÒÔËÔÆ¹º  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2021-10-21 17:00"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import GameWorld  | 
| import ShareDefine  | 
| import CrossRealmMsg  | 
| import PlayerControl  | 
| import DataRecordPack  | 
| import PlayerCompensation  | 
| import CrossActionControl  | 
| import ChPyNetSendPack  | 
| import IpyGameDataPY  | 
| import NetPackCommon  | 
| import PyGameData  | 
| import ChConfig  | 
|   | 
| import operator  | 
| import random  | 
| import math  | 
| import time  | 
|   | 
| Def_RecType_LuckyCloudBuyNum = ShareDefine.Def_UniversalGameRecType_LuckyCloudBuyNum  | 
| '''  | 
| ÐÒÔËÔÆ¹º¹ºÂòºÅÂë¼Ç¼  | 
| ShareDefine.Def_UniversalGameRecType_LuckyCloudBuyNum  | 
| time:idTime             °ó¶¨µÄÂִαêʶID£¬¶ÔÓ¦¿ª½±¼Ç¼µÄtimeÖµ  | 
| value1:zoneID        ·ÖÇøID  | 
| value2:roundNum        ½ñÈÕµÚ¼¸ÂÖ  | 
| value3:playerID        Íæ¼ÒID  | 
| value4:buyNum          ¹ºÂòºÅÂë  | 
| value5:buyTime         ¹ºÂòʱ¼ä  | 
|   | 
| StrValue1:playerName    Íæ¼ÒÃû  | 
| StrValue3:accID        Íæ¼ÒÕ˺Š | 
| '''  | 
|   | 
| Def_RecType_LuckyCloudBuyLottery = ShareDefine.Def_UniversalGameRecType_LuckyCloudBuyLottery  | 
| '''  | 
| ÐÒÔËÔÆ¹º¿ª½±¼Ç¼  | 
| ShareDefine.Def_UniversalGameRecType_LuckyCloudBuyLottery  | 
| time:idTime                ´´½¨Ê±¼ä£¨Ò²×÷Ϊ±¾ÂÖΨһ±êʶID£¬ÓÃÉú³Éʱ¼ätimeÖµ×÷ΪΨһID£©  | 
| value1:cfgID*100+zoneID        ÅäÖÃID*100 + ·ÖÇøID  | 
| value2:roundNum          ½ñÈÕµÚ¼¸ÂÖ  | 
| value3:luckyPlayerID     Öн±Íæ¼ÒID  | 
| value4:lotteryNum         ¿ª½±ºÅÂë  | 
| value5:lotteryTime       ¿ª½±Ê±¼ä  | 
|   | 
| StrValue1:luckyPlayerName    Öн±Íæ¼ÒÃû  | 
| StrValue3:lotteryInfo        ·ÖÇøÐÅÏ¢|´ó½±ÐÅÏ¢|Öн±Íæ¼ÒÕ˺Š | 
| '''  | 
|   | 
| class LuckyCloudBuyNum():  | 
|     ''' ÐÒÔËÔÆ¹º¹ºÂòºÅÂë¼Ç¼  | 
|     '''  | 
|     def __init__(self):  | 
|         self.idTime = 0  | 
|         self.zoneID = 0  | 
|         self.roundNum = 0  | 
|         self.playerID = 0  | 
|         self.buyNum = 0  | 
|         self.buyTime = 0  | 
|           | 
|         self.playerName = ""  | 
|         self.accID = ""  | 
|         return  | 
|       | 
|     def GetString(self):  | 
|         return {"idTime":self.idTime, "zoneID":self.zoneID, "roundNum":self.roundNum, "playerID":self.playerID,   | 
|                 "buyNum":self.buyNum, "buyTime":self.buyTime, "playerName":self.playerName, "accID":self.accID}  | 
|           | 
|     def SetAttrByDict(self, attrDict):  | 
|         for k, v in attrDict.items():  | 
|             setattr(self, k, v)  | 
|         return  | 
|       | 
| class LuckyCloudBuyLottery():  | 
|     ''' ÐÒÔËÔÆ¹º¿ª½±¼Ç¼  | 
|     '''  | 
|     def __init__(self):  | 
|         self.idTime = 0  | 
|         self.cfgID = 0  | 
|         self.zoneID = 0  | 
|         self.roundNum = 0  | 
|         self.luckyPlayerID = 0  | 
|         self.lotteryNum = 0  | 
|         self.lotteryTime = 0  | 
|           | 
|         self.luckyPlayerName = ""  | 
|         self.serverIDRangeList = [] # ·ÖÇøÐÅÏ¢  | 
|         self.superItemInfo = [] # ´ó½±ÐÅÏ¢  | 
|         self.luckyPlayerAccID = "" # Öн±Íæ¼ÒÕ˺Š | 
|         return  | 
|       | 
|     def GetString(self):  | 
|         return {"idTime":self.idTime, "cfgID":self.cfgID, "zoneID":self.zoneID, "roundNum":self.roundNum, "luckyPlayerID":self.luckyPlayerID,   | 
|                 "lotteryNum":self.lotteryNum, "lotteryTime":self.lotteryTime, "luckyPlayerName":self.luckyPlayerName,   | 
|                 "serverIDRangeList":self.serverIDRangeList, "superItemInfo":self.superItemInfo, "luckyPlayerAccID":self.luckyPlayerAccID}  | 
|           | 
|     def SetAttrByDict(self, attrDict):  | 
|         for k, v in attrDict.items():  | 
|             setattr(self, k, v)  | 
|         return  | 
|           | 
| def OnServerStart():  | 
|       | 
|     if not GameWorld.IsCrossServer():  | 
|         return  | 
|       | 
|     PyGameData.g_luckyCloudBuyNumDict = {}  | 
|     PyGameData.g_luckyCloudBuyLotteryDict = {}  | 
|       | 
|     universalRecMgr = GameWorld.GetUniversalRecMgr()  | 
|     recDataList = universalRecMgr.GetTypeList(Def_RecType_LuckyCloudBuyNum)  | 
|     GameWorld.Log("¼ÓÔØÐÒÔËÔÆ¹º¹ºÂò¼Ç¼! %s" % recDataList.Count())  | 
|       | 
|     for index in xrange(recDataList.Count()):  | 
|         recData = recDataList.At(index)  | 
|         zoneID = recData.GetValue1()  | 
|           | 
|         buyRec = LuckyCloudBuyNum()  | 
|         buyRec.idTime = int(recData.GetTime())  | 
|         buyRec.zoneID = zoneID  | 
|         buyRec.roundNum = recData.GetValue2()  | 
|         buyRec.playerID = recData.GetValue3()  | 
|         buyRec.buyNum = recData.GetValue4()  | 
|         buyRec.buyTime = recData.GetValue5()  | 
|           | 
|         buyRec.playerName = recData.GetStrValue1()  | 
|         buyRec.accID = recData.GetStrValue3()  | 
|           | 
|         if zoneID not in PyGameData.g_luckyCloudBuyNumDict:  | 
|             PyGameData.g_luckyCloudBuyNumDict[zoneID] = []  | 
|         buyRecList = PyGameData.g_luckyCloudBuyNumDict[zoneID]  | 
|         buyRecList.append(buyRec)  | 
|           | 
|     for zoneID, buyRecList in PyGameData.g_luckyCloudBuyNumDict.items():  | 
|         buyRecList.sort(key=operator.attrgetter("idTime"))  | 
|         GameWorld.Log("    ÐÒÔËÔÆ¹º·ÖÇø¹ºÂò¼Ç¼! zoneID=%s, count=%s" % (zoneID, len(buyRecList)))  | 
|           | 
|     recDataList = universalRecMgr.GetTypeList(Def_RecType_LuckyCloudBuyLottery)  | 
|     GameWorld.Log("¼ÓÔØÐÒÔËÔÆ¹º¿ª½±¼Ç¼! %s" % recDataList.Count())  | 
|       | 
|     for index in xrange(recDataList.Count()):  | 
|         recData = recDataList.At(index)  | 
|         value1 = recData.GetValue1()  | 
|         cfgID, zoneID = value1 / 100, value1 % 100  | 
|         lotteryRec = LuckyCloudBuyLottery()  | 
|         lotteryRec.idTime = int(recData.GetTime())  | 
|         lotteryRec.cfgID = cfgID  | 
|         lotteryRec.zoneID = zoneID  | 
|         lotteryRec.roundNum = recData.GetValue2()  | 
|         lotteryRec.luckyPlayerID = recData.GetValue3()  | 
|         lotteryRec.lotteryNum = recData.GetValue4()  | 
|         lotteryRec.lotteryTime = recData.GetValue5()  | 
|           | 
|         lotteryRec.luckyPlayerName = recData.GetStrValue1()  | 
|         strValue3 = recData.GetStrValue3()  | 
|         lotteryRec.serverIDRangeList, lotteryRec.superItemInfo, lotteryRec.luckyPlayerAccID = [], [], ""  | 
|         if strValue3:  | 
|             serverIDStr, superItemStr, accID = strValue3.split("|")  | 
|             lotteryRec.serverIDRangeList = eval(serverIDStr) if (serverIDStr.startswith("[") and serverIDStr.endswith("]")) else []  | 
|             lotteryRec.superItemInfo = eval(superItemStr) if (superItemStr.startswith("[") and superItemStr.endswith("]")) else []  | 
|             lotteryRec.luckyPlayerAccID = accID  | 
|               | 
|         if zoneID not in PyGameData.g_luckyCloudBuyLotteryDict:  | 
|             PyGameData.g_luckyCloudBuyLotteryDict[zoneID] = []  | 
|         lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict[zoneID]  | 
|         lotteryRecList.append(lotteryRec)  | 
|           | 
|     for zoneID, lotteryRecList in PyGameData.g_luckyCloudBuyLotteryDict.items():  | 
|         lotteryRecList.sort(key=operator.attrgetter("idTime"))  | 
|         GameWorld.Log("    ÐÒÔËÔÆ¹º·ÖÇø¿ª½±¼Ç¼! zoneID=%s, count=%s" % (zoneID, len(lotteryRecList)))  | 
|           | 
|     return  | 
|   | 
| def OnServerClose():  | 
|       | 
|     if not GameWorld.IsCrossServer():  | 
|         return  | 
|       | 
|     universalRecMgr = GameWorld.GetUniversalRecMgr()  | 
|           | 
|     GameWorld.Log("±£´æÐÒÔËÔÆ¹º¹ºÂò¼Ç¼!")  | 
|     universalRecMgr.Delete(Def_RecType_LuckyCloudBuyNum)  | 
|     recDataList = universalRecMgr.GetTypeList(Def_RecType_LuckyCloudBuyNum)  | 
|     for zoneID, buyRecList in PyGameData.g_luckyCloudBuyNumDict.items():  | 
|         GameWorld.Log("    ±£´æÐÒÔËÔÆ¹º¹ºÂò¼Ç¼! zoneID=%s, count=%s" % (zoneID, len(buyRecList)))  | 
|         for buyRec in buyRecList:  | 
|             recData = recDataList.AddRec()  | 
|             recData.SetTime(buyRec.idTime)  | 
|             recData.SetValue1(buyRec.zoneID)  | 
|             recData.SetValue2(buyRec.roundNum)  | 
|             recData.SetValue3(buyRec.playerID)  | 
|             recData.SetValue4(buyRec.buyNum)  | 
|             recData.SetValue5(buyRec.buyTime)  | 
|               | 
|             recData.SetStrValue1(buyRec.playerName)  | 
|             recData.SetStrValue3(buyRec.accID)  | 
|               | 
|               | 
|     GameWorld.Log("±£´æÐÒÔËÔÆ¹º¿ª½±¼Ç¼!")  | 
|     universalRecMgr.Delete(Def_RecType_LuckyCloudBuyLottery)  | 
|     recDataList = universalRecMgr.GetTypeList(Def_RecType_LuckyCloudBuyLottery)  | 
|     for zoneID, lotteryRecList in PyGameData.g_luckyCloudBuyLotteryDict.items():  | 
|         GameWorld.Log("    ±£´æÐÒÔËÔÆ¹º¿ª½±¼Ç¼! zoneID=%s, count=%s" % (zoneID, len(lotteryRecList)))  | 
|         for lotteryRec in lotteryRecList:  | 
|             recData = recDataList.AddRec()  | 
|             recData.SetTime(lotteryRec.idTime)  | 
|             recData.SetValue1(lotteryRec.cfgID * 100 + lotteryRec.zoneID)  | 
|             recData.SetValue2(lotteryRec.roundNum)  | 
|             recData.SetValue3(lotteryRec.luckyPlayerID)  | 
|             recData.SetValue4(lotteryRec.lotteryNum)  | 
|             recData.SetValue5(lotteryRec.lotteryTime)  | 
|               | 
|             recData.SetStrValue1(lotteryRec.luckyPlayerName)  | 
|             recData.SetStrValue3("%s|%s|%s" % (str(lotteryRec.serverIDRangeList).replace(" ", ""),   | 
|                                                str(lotteryRec.superItemInfo).replace(" ", ""),   | 
|                                                lotteryRec.luckyPlayerAccID))  | 
|               | 
|     return  | 
|   | 
| def OnPlayerLogin(curPlayer):  | 
|     if GameWorld.IsCrossServer():  | 
|         return  | 
|       | 
|     Sync_LuckyCloudBuyRoundInfo(curPlayer)  | 
|     __LoginNotifyMapCloudBuyNumInfo(curPlayer)  | 
|     return  | 
|   | 
| def DoOnDay():  | 
|       | 
|     # Çå³ý¹ýÆÚµÄ¿ª½±¼Ç¼£¬¹ºÂò¼Ç¼½ö±£Áô±¾ÆÚ  | 
|     crossServerTime = GameWorld.ChangeTimeStrToNum(GameWorld.GetCrossServerTimeStr())  | 
|     MaxTime = 3 * 24 * 3600 # ×î´ó±£Áô½ü3Ìì¼Ç¼  | 
|     for zoneID, lotteryRecList in PyGameData.g_luckyCloudBuyLotteryDict.items():  | 
|         doCount = len(lotteryRecList)  | 
|         GameWorld.DebugLog("¼ì²éÐÒÔËÔÆ¹º·ÖÇø¿ª½±¼Ç¼ÊÇ·ñ³¬Ê±! zoneID=%s,doCount=%s" % (zoneID, doCount))  | 
|         while lotteryRecList and doCount > 0:  | 
|             doCount -= 1  | 
|             lotteryRec = lotteryRecList[0]  | 
|             passTime = crossServerTime - lotteryRec.lotteryTime  | 
|             if not lotteryRec.lotteryNum or not lotteryRec.lotteryTime or passTime < MaxTime:  | 
|                 GameWorld.DebugLog("    Î´¿ª½±»òÔÚ±£Áôʱ¼äÄÚ! lotteryNum=%s,crossServerTime=%s(%s),lotteryTime=%s(%s),passTime=%s < %s"   | 
|                                    % (lotteryRec.lotteryNum, crossServerTime, GameWorld.ChangeTimeNumToStr(crossServerTime),   | 
|                                       lotteryRec.lotteryTime, GameWorld.ChangeTimeNumToStr(lotteryRec.lotteryTime), passTime, MaxTime))  | 
|                 break  | 
|             lotteryRec = lotteryRecList.pop(0)  | 
|             GameWorld.DebugLog("    Ôƹº¿ª½±¼Ç¼³¬Ê±£¬É¾³ý! lotteryNum=%s,crossServerTime=%s(%s),lotteryTime=%s(%s),passTime=%s >= %s"   | 
|                                    % (lotteryRec.lotteryNum, crossServerTime, GameWorld.ChangeTimeNumToStr(crossServerTime),   | 
|                                       lotteryRec.lotteryTime, GameWorld.ChangeTimeNumToStr(lotteryRec.lotteryTime), passTime, MaxTime))  | 
|               | 
|     if not GameWorld.IsCrossServer():  | 
|         return  | 
|       | 
|     maxBuyCount = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 2)  | 
|     doLotteryBuyCountPer = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 3)  | 
|     doLotteryBuyCount = int(math.ceil(maxBuyCount * doLotteryBuyCountPer / 100.0))  | 
|       | 
|     zoneLotteryInfo = {}  | 
|     for zoneID, lotteryRecList in PyGameData.g_luckyCloudBuyLotteryDict.items():  | 
|         if not lotteryRecList:  | 
|             continue  | 
|         lastLotteryRec = lotteryRecList[-1] # È¡×îºóÒ»¸öΪ×îÐÂÒ»ÆÚ  | 
|         cfgID = lastLotteryRec.cfgID  | 
|         if lastLotteryRec.lotteryNum:  | 
|             GameWorld.Log("OnDayÒÑ¿ª½±½øÈëÐÂÒ»ÌìµÚÒ»ÂÖ£¡ cfgID=%s,zoneID=%s" % (cfgID, zoneID))  | 
|             DoStartNewRoundLuckyCloudBuy(cfgID, 1)  | 
|             continue  | 
|         buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])  | 
|         buyCount = len(buyRecList)  | 
|         if len(buyRecList) >= doLotteryBuyCount:  | 
|             GameWorld.Log("OnDay먦½±µ«¹ºÂò·ÝÊý³¬¹ý¿ª½±±£µ×·ÝÊý£¡ cfgID=%s,zoneID=%s,buyCount=%s >= %s" % (cfgID, zoneID, buyCount, doLotteryBuyCount))  | 
|             DoLuckyCloudBuyLottery(lastLotteryRec, True, "OnDay")  | 
|             continue  | 
|           | 
|         GameWorld.Log("ÒѹºÂò·ÝÊý²»×㿪½±±£µ×·ÝÊý£¬ÖØÖÃΪÐÂÒ»ÌìµÄµÚÒ»ÂÖ£¡ cfgID=%s,zoneID=%s,buyCount=%s < %s" % (cfgID, zoneID, buyCount, doLotteryBuyCount))  | 
|         lastLotteryRec.roundNum = 1  | 
|         dataDict = {"Type":"ResetRound"}  | 
|         dataDict.update(lastLotteryRec.GetString())  | 
|         DataRecordPack.SendEventPack("LuckyCloudBuyLottery", dataDict)  | 
|         zoneLotteryInfo[zoneID] = [lastLotteryRec.GetString()]  | 
|           | 
|     # ¹ã²¥×Ó·þÂÖ´ÎÐÅÏ¢±ä¸ü  | 
|     if zoneLotteryInfo:  | 
|         dataMsg = {"syncType":"Update", "zoneLotteryInfo":zoneLotteryInfo}  | 
|         CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg)  | 
|     return  | 
|   | 
| def DoLuckyCloudBuyLottery(lotteryRec, resetRound=False, sign=""):  | 
|     ## Ôƹº¿ª½±  | 
|       | 
|     idTime = lotteryRec.idTime  | 
|     cfgID = lotteryRec.cfgID  | 
|     zoneID = lotteryRec.zoneID  | 
|     roundNum = lotteryRec.roundNum  | 
|       | 
|     lotteryDateStr = GameWorld.ChangeTimeNumToStr(idTime, ChConfig.TYPE_Time_YmdFormat)  | 
|     GameWorld.Log("ÐÒÔËÔÆ¹º¿ª½±: idTime=%s(%s),cfgID=%s,zoneID=%s,roundNum=%s,resetRound=%s,sign=%s"   | 
|                   % (idTime, lotteryDateStr, cfgID, zoneID, roundNum, resetRound, sign))  | 
|       | 
|     todayLuckyPlayerCountInfo = {} # µ±ÈÕÖн±Íæ¼ÒÖн±´ÎÊýÐÅÏ¢ {playerID:count, ...}  | 
|     lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])  | 
|     for lotRec in lotteryRecList[-roundNum:]:  | 
|         if lotRec.luckyPlayerID:  | 
|             todayLuckyPlayerCountInfo[lotRec.luckyPlayerID] = todayLuckyPlayerCountInfo.get(lotRec.luckyPlayerID, 0) + 1  | 
|               | 
|     GameWorld.Log("    µ±ÈÕÒÑÖн±Íæ¼Ò´ÎÊýÐÅÏ¢: %s" % todayLuckyPlayerCountInfo)  | 
|       | 
|     # ¿ª½±  | 
|     playerNumListDict = {}  | 
|     baseWeight = 100  | 
|     randList = []  | 
|     maxRate = 0  | 
|     luckyCountLimit, luckyWeightReducePer = IpyGameDataPY.GetFuncEvalCfg("LuckyCloudBuySet", 4)  | 
|     buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])      | 
|     for buyRec in buyRecList:  | 
|         if buyRec.idTime != idTime:  | 
|             GameWorld.ErrLog("    ·Ç±¾ÂÖ¹ºÂòµÄºÅÂ룡 idTime=%s, buyRecInfo=%s" % (idTime, buyRec.GetString()))  | 
|             continue  | 
|         playerID = buyRec.playerID  | 
|         luckyCount = todayLuckyPlayerCountInfo.get(playerID, 0)  | 
|         if luckyCount >= luckyCountLimit:  | 
|             weight = max(1, int(baseWeight * (100 - luckyWeightReducePer) / 100.0))  | 
|             #GameWorld.Log("    Íæ¼Òµ±ÈÕÖн±´ÎÊý³¬¹ýÖ¸¶¨´ÎÊý£¬Öн±È¨ÖؽµµÍ! playerID=%s, luckyCount(%s) >= %s, weight=%s"   | 
|             #              % (playerID, luckyCount, luckyCountLimit, weight))  | 
|         else:  | 
|             weight = baseWeight  | 
|         maxRate += weight  | 
|         randList.append([maxRate, buyRec])  | 
|           | 
|         # Í³¼ÆÍæ¼ÒËùÓкÅÂë  | 
|         if playerID not in playerNumListDict:  | 
|             playerNumListDict[playerID] = []  | 
|         playerNumList = playerNumListDict[playerID]  | 
|         playerNumList.append(buyRec.buyNum)  | 
|           | 
|     GameWorld.Log("    ±¾ÂÖ¿ª½±±ýͼÁбíÐÅÏ¢: buyCount=%s,randListLen=%s,maxRate=%s" % (len(buyRecList), len(randList), maxRate))  | 
|     luckyBuyRec = GameWorld.GetResultByRandomList(randList)  | 
|     if luckyBuyRec:  | 
|         GameWorld.Log("    ÐÒÔËÖн±ºÅÂë¼Ç¼: lotteryNum=%s, %s" % (luckyBuyRec.buyNum, luckyBuyRec.GetString()))  | 
|         lotteryRec.luckyPlayerID = luckyBuyRec.playerID  | 
|         lotteryRec.luckyPlayerName = luckyBuyRec.playerName  | 
|         lotteryRec.luckyPlayerAccID = luckyBuyRec.accID  | 
|         lotteryRec.lotteryNum = luckyBuyRec.buyNum  | 
|           | 
|     else:  | 
|         GameWorld.ErrLog("    ÔƹºÎÞÈ˹ºÂò»ò¿ª½±Òì³£! cfgID=%s,zoneID=%s" % (cfgID, zoneID))  | 
|         maxBuyCount = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 2)  | 
|         lotteryRec.lotteryNum = random.randint(1, maxBuyCount)  | 
|         GameWorld.Log("    Ëæ»úÖн±ºÅÂë! lotteryNum=%s" % lotteryRec.lotteryNum)  | 
|           | 
|     lotteryRec.lotteryTime = int(time.time())  | 
|       | 
|     # ·¢Óʼþ  | 
|     for playerID, buyNumList in playerNumListDict.items():  | 
|         if playerID == lotteryRec.luckyPlayerID:  | 
|             addItemList = [lotteryRec.superItemInfo[:3]] if len(lotteryRec.superItemInfo) >= 3 else []  | 
|             PlayerCompensation.SendMailByKey("LuckyCloudBuyWin", [playerID], addItemList, [lotteryRec.lotteryNum], crossMail=True)  | 
|         else:  | 
|             buyNums = GetMailBuyNums(buyNumList)  | 
|             PlayerCompensation.SendMailByKey("LuckyCloudBuyFail", [playerID], [], [lotteryRec.lotteryNum, buyNums], crossMail=True)  | 
|               | 
|     dataDict = {"Type":"Lottery"}  | 
|     dataDict.update(lotteryRec.GetString())  | 
|     DataRecordPack.SendEventPack("LuckyCloudBuyLottery", dataDict)  | 
|       | 
|     # ¹ã²¥×Ó·þ¿ª½±ÐÅÏ¢  | 
|     zoneLotteryInfo = {zoneID:[lotteryRec.GetString()]}  | 
|     dataMsg = {"syncType":"Update", "zoneLotteryInfo":zoneLotteryInfo}  | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg)  | 
|           | 
|     actInfoDict = CrossActionControl.GetCrossActInfoByCfgID(ShareDefine.CrossActName_LuckyCloudBuy, cfgID)  | 
|     if not actInfoDict or not actInfoDict[ShareDefine.ActKey_State]:  | 
|         GameWorld.Log("    ²»ÔڻÖÐÁË£¬²»¿ªÏÂÒ»ÂÖ! cfgID=%s" % cfgID)  | 
|         return  | 
|           | 
|     if roundNum >= IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 1):  | 
|         GameWorld.Log("    µ±ÈÕÒÑ´ïÿÈÕÔÆ¹ºÂÖÊýÉÏÏÞ£¬²»¿ªÏÂÒ»ÂÖ! roundNum=%s" % roundNum)  | 
|         return  | 
|       | 
|     nextRoundNum = 1 if resetRound else (roundNum + 1)  | 
|     GameWorld.Log("ÐÒÔËÔÆ¹º¿ªÆôÏÂÒ»ÂÖ! cfgID=%s,zoneID=%s,roundNum=%s,resetRound=%s,nextRoundNum=%s"   | 
|                   % (cfgID, zoneID, roundNum, resetRound, nextRoundNum))  | 
|     # ¿ªÊ¼ÏÂÒ»ÂÖ  | 
|     return DoStartNewRoundLuckyCloudBuy(cfgID, nextRoundNum)  | 
|   | 
| def GetMailBuyNums(buyNumList):  | 
|     buyNumList.sort()  | 
|     buyNums = "" # ÐÎÈç 1-3¡¢5-7¡¢10¡¢20¡¢100¡¢200-205  | 
|     startNum, lastNum = None, None  | 
|     sign = "¡¢".decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())  | 
|     for i, num in enumerate(buyNumList):  | 
|         if num - 1 == lastNum:  | 
|             lastNum = num  | 
|             if not buyNums.endswith("-"):  | 
|                 buyNums += "-"  | 
|                   | 
|             if i == len(buyNumList) - 1:  | 
|                 buyNums += str(num)  | 
|             continue  | 
|           | 
|         if startNum != lastNum:  | 
|             buyNums += str(lastNum)  | 
|               | 
|         if buyNums:  | 
|             buyNums += sign  | 
|               | 
|         buyNums += str(num)  | 
|           | 
|         startNum = num  | 
|         lastNum = num  | 
|           | 
|     return buyNums  | 
|   | 
| def OnLuckyCloudBuyReset(ipyData, state):  | 
|     ## ÔƹºÖØÖà  | 
|     cfgID = ipyData.GetCfgID()  | 
|     zoneID = ipyData.GetZoneID()  | 
|       | 
|     startNewLottery = False  | 
|     lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])  | 
|     lastLotteryRec = None if not lotteryRecList else lotteryRecList[-1]  | 
|     if lastLotteryRec and not lastLotteryRec.lotteryNum:  | 
|         GameWorld.Log("ÐÒÔËÔÆ¹ºÖØÖ㬵±Ç°ÂÖ´Î먦½±£¬Ö±½Ó¿ª½±! cfgID=%s,zoneID=%s" % (lastLotteryRec.cfgID, zoneID))  | 
|         startNewLottery = DoLuckyCloudBuyLottery(lastLotteryRec, True, "Reset")  | 
|       | 
|     if state and not startNewLottery:  | 
|         GameWorld.Log("ÐÒÔËÔÆ¹ºÖØÖ㬵±Ç°Ã»ÓÐ먦½±µÄÂִΣ¬Ö±½Ó¿ªÆôÐÂÒ»ÂÖ! cfgID=%s,zoneID=%s" % (cfgID, zoneID))  | 
|         DoStartNewRoundLuckyCloudBuy(cfgID, 1)  | 
|           | 
|     return  | 
|   | 
| def DoStartNewRoundLuckyCloudBuy(cfgID, roundNum):  | 
|     # ¿ªÆôÐÂÒ»ÂÖÔÆ¹º  | 
|       | 
|     actInfoDict = CrossActionControl.GetCrossActInfoByCfgID(ShareDefine.CrossActName_LuckyCloudBuy, cfgID)  | 
|     if not actInfoDict or not actInfoDict[ShareDefine.ActKey_State]:  | 
|         GameWorld.ErrLog("ÐÒÔËÔÆ¹º·Ç»î¶¯ÖУ¬ÎÞ·¨¿ªÆô! cfgID=%s, roundNum=%s" % (cfgID, roundNum))  | 
|         return  | 
|       | 
|     actIpyData = IpyGameDataPY.GetIpyGameData("CrossActLuckyCloudBuy", cfgID)  | 
|     if not actIpyData:  | 
|         return  | 
|     zoneID = actIpyData.GetZoneID()  | 
|     serverIDRangeList = actIpyData.GetServerIDRangeList()  | 
|     templateIDList = actIpyData.GetTemplateIDList()  | 
|     if not templateIDList:  | 
|         return  | 
|       | 
|     dayIndex = actInfoDict.get(ShareDefine.ActKey_DayIndex, 0)  | 
|     templateID = templateIDList[dayIndex] if len(templateIDList) > dayIndex else templateIDList[-1]  | 
|     templateIpyData = IpyGameDataPY.GetIpyGameData("CrossActLuckyCloudBuyTemplate", templateID)  | 
|     if not templateIpyData:  | 
|         return  | 
|       | 
|     superItemWeightInfo = templateIpyData.GetSuperItemWeightInfo()  | 
|     superItemInfo = GameWorld.GetResultByWeightList(superItemWeightInfo)  | 
|     if not superItemInfo or len(superItemInfo) < 3:  | 
|         GameWorld.ErrLog("ÐÒÔËÔÆ¹ºÉú³É´ó½±Ê§°Ü! zoneID=%s,roundNum=%s,superItemInfo=%s" % (zoneID, roundNum, superItemInfo))  | 
|         return  | 
|       | 
|     lotteryRec = LuckyCloudBuyLottery()  | 
|     lotteryRec.idTime = int(time.time())  | 
|     lotteryRec.cfgID = cfgID  | 
|     lotteryRec.zoneID = zoneID  | 
|     lotteryRec.roundNum = roundNum  | 
|       | 
|     lotteryRec.serverIDRangeList = serverIDRangeList  | 
|     lotteryRec.superItemInfo = superItemInfo  | 
|       | 
|     if zoneID not in PyGameData.g_luckyCloudBuyLotteryDict:  | 
|         PyGameData.g_luckyCloudBuyLotteryDict[zoneID] = []  | 
|     lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict[zoneID]  | 
|     lotteryRecList.append(lotteryRec)  | 
|       | 
|     PyGameData.g_luckyCloudBuyNumDict[zoneID] = [] # ÐÂÒ»ÂÖÇé¿ö¹ºÂò¼Ç¼  | 
|       | 
|     dataDict = {"Type":"NewRound"}  | 
|     dataDict.update(lotteryRec.GetString())  | 
|     DataRecordPack.SendEventPack("LuckyCloudBuyLottery", dataDict)  | 
|       | 
|     # ¹ã²¥×Ó·þ¿ª½±ÐÅÏ¢  | 
|     zoneLotteryInfo = {zoneID:[lotteryRec.GetString()]}  | 
|     dataMsg = {"syncType":"New", "zoneLotteryInfo":zoneLotteryInfo}  | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg)  | 
|     return True  | 
|   | 
| def Sync_LuckyCloudBuyDataToClientServer(tick, serverGroupID=0):  | 
|     GameWorld.Log("ͬ²½¸ø×Ó·þ¶ÔÓ¦µÄÐÒÔËÔÆ¹ºÐÅÏ¢: syncServerGroupID=%s" % (serverGroupID))  | 
|       | 
|     # ¿ª½±¼Ç¼  | 
|     zoneLotteryInfo = {}  | 
|     for zoneID, lotteryRecList in PyGameData.g_luckyCloudBuyLotteryDict.items():  | 
|         zoneLotteryList = []  | 
|         for lotteryRec in lotteryRecList:  | 
|             zoneLotteryList.append(lotteryRec.GetString())  | 
|         zoneLotteryInfo[zoneID] = zoneLotteryList  | 
|           | 
|     dataMsg = {"syncType":"All", "zoneLotteryInfo":zoneLotteryInfo}  | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg)  | 
|       | 
|     # ¹ºÂò¼Ç¼  | 
|     for zoneID in PyGameData.g_luckyCloudBuyLotteryDict.keys():  | 
|         zoneBuyNumList = []  | 
|         buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])  | 
|         for buyRec in buyRecList:  | 
|             zoneBuyNumList.append(buyRec.GetString())  | 
|               | 
|         dataMsg = {"syncType":"All", "zoneID":zoneID, "zoneBuyNumList":zoneBuyNumList}  | 
|         CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyNum, dataMsg)  | 
|           | 
|     return  | 
|   | 
| def CrossServerMsg_LuckyCloudBuyLottery(msgData):  | 
|     ## ×Ó·þÊÕµ½¿ª½±¼Ç¼֪ͨ  | 
|       | 
|     syncType = msgData["syncType"] # All New Update  | 
|     zoneLotteryInfo = msgData["zoneLotteryInfo"]  | 
|       | 
|     serverGroupID = GameWorld.GetServerGroupID()  | 
|     serverZoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)  | 
|     syncMapLotteryRec = None # ÓÐÐèҪͬ²½µØÍ¼µÄ£¬¼´Óб¾·ÖÇøµÄÊý¾Ýͬ²½  | 
|     GameWorld.Log("ÊÕµ½·ÖÇøÔÆ¹º¿ª½±¼Ç¼ͬ²½ÐÅÏ¢: syncType=%s,serverZoneID=%s,zoneCount=%s" % (syncType, serverZoneID, len(zoneLotteryInfo)))  | 
|       | 
|     if syncType == "All":  | 
|         PyGameData.g_luckyCloudBuyLotteryDict = {}  | 
|           | 
|     for zoneID, zoneLotteryList in zoneLotteryInfo.items():  | 
|         if zoneID not in PyGameData.g_luckyCloudBuyLotteryDict:  | 
|             PyGameData.g_luckyCloudBuyLotteryDict[zoneID] = []  | 
|         lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict[zoneID]  | 
|         GameWorld.Log("    ·ÖÇøÔÆ¹º¿ª½±¼Ç¼ͬ²½ÐÅÏ¢: syncType=%s,zoneID=%s,count=%s" % (syncType, zoneID, zoneLotteryList))  | 
|         for attrDict in zoneLotteryList:  | 
|             if syncType in ["All", "New"]:  | 
|                 lotteryRec = LuckyCloudBuyLottery()  | 
|                 lotteryRec.SetAttrByDict(attrDict)  | 
|                 lotteryRecList.append(lotteryRec)  | 
|                 if zoneID == serverZoneID:  | 
|                     syncMapLotteryRec = lotteryRec  | 
|                       | 
|                 # ±¾·ÖÇøÐÂÂÖ´Î  | 
|                 if syncType == "New" and zoneID == serverZoneID:  | 
|                     GameWorld.Log("        ±¾·þ·ÖÇøÐÂÔöÔÆ¹º¿ª½±¼Ç¼ÐÅÏ¢: idTime=%s" % lotteryRec.idTime)  | 
|                     PyGameData.g_luckyCloudBuyNumDict[zoneID] = []  | 
|                     if len(lotteryRec.superItemInfo) >= 2:  | 
|                         superItemID, superItemCount = lotteryRec.superItemInfo[0], lotteryRec.superItemInfo[1]  | 
|                         PlayerControl.WorldNotify(0, "LuckyCloudBuyOpen", [superItemID, superItemCount])  | 
|                       | 
|             elif syncType == "Update":  | 
|                 for lotteryRec in lotteryRecList[::-1]: # Ò»°ãÊÇ×îºóÒ»¸ö±ØÃüÖÐ  | 
|                     if lotteryRec.idTime == attrDict["idTime"] and lotteryRec.zoneID == attrDict["zoneID"]:  | 
|                         lotteryRec.SetAttrByDict(attrDict)  | 
|                         GameWorld.Log("    ¸üÐÂÔÆ¹º¿ª½±¼Ç¼ÐÅÏ¢: idTime=%s" % lotteryRec.idTime)  | 
|                           | 
|                         if zoneID != serverZoneID:  | 
|                             break  | 
|                           | 
|                         syncMapLotteryRec = lotteryRec  | 
|                           | 
|                         # ±¾·ÖÇø¿ª½±¼Ç¼ͬ²½  | 
|                         if lotteryRec.lotteryNum:  | 
|                             GameWorld.Log("        ±¾·þ·ÖÇø¸üÐÂÔÆ¹º¿ª½±¼Ç¼ÐÅÏ¢: idTime=%s" % lotteryRec.idTime)  | 
|                             if len(lotteryRec.superItemInfo) >= 2:  | 
|                                 superItemID, superItemCount = lotteryRec.superItemInfo[0], lotteryRec.superItemInfo[1]  | 
|                                 PlayerControl.WorldNotify(0, "LuckyCloudBuyClose", [lotteryRec.lotteryNum, lotteryRec.luckyPlayerName, superItemID, superItemCount])  | 
|                                   | 
|                         break  | 
|                       | 
|     # Í¨ÖªµØÍ¼  | 
|     if syncMapLotteryRec:  | 
|         Sync_LuckyCloudBuyRoundInfo(None)  | 
|         GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_LuckyCloudBuyInfo, syncMapLotteryRec.GetString())  | 
|           | 
|     return  | 
|   | 
| def OnMapServerInitOK():  | 
|     # Í¨ÖªµØÍ¼·þÎñÆ÷״̬  | 
|       | 
|     if GameWorld.IsCrossServer():  | 
|         return  | 
|       | 
|     serverGroupID = GameWorld.GetServerGroupID()  | 
|     zoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)  | 
|     if not zoneID:  | 
|         return  | 
|       | 
|     lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])  | 
|     lastLotteryRec = None if not lotteryRecList else lotteryRecList[-1]  | 
|     sendMsg = {} if not lastLotteryRec else lastLotteryRec.GetString()  | 
|       | 
|     GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_LuckyCloudBuyInfo, sendMsg)  | 
|     return  | 
|   | 
| def ClientServerMsg_LuckyCloudBuy(serverGroupID, msgData):  | 
|     ## ÊÕµ½×Ó·þÇëÇóÐÒÔËÔÆ¹º¹ºÂò  | 
|       | 
|     zoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)  | 
|     if not zoneID:  | 
|         return  | 
|       | 
|     accID = msgData["accID"]  | 
|     playerID = msgData["playerID"]  | 
|     playerName = msgData["playerName"]  | 
|     buyCount = msgData["buyCount"]  | 
|     roundID = msgData["roundID"]  | 
|       | 
|     lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])  | 
|     if not lotteryRecList:  | 
|         return  | 
|     lotteryRec = lotteryRecList[-1]  | 
|       | 
|     if roundID != lotteryRec.idTime or zoneID != lotteryRec.zoneID:  | 
|         GameWorld.ErrLog("ÐÒÔËÔÆ¹º¹ºÂòÒì³££¡½±³ØÂÖ´ÎÐÅÏ¢²»Ò»Ö£¡ roundID=%s,zoneID=%s, lotteryRec idTime=%s,zoneID=%s"  | 
|                           % (roundID, zoneID, lotteryRec.idTime, lotteryRec.zoneID))  | 
|         PlayerControl.CrossNotifyCode(serverGroupID, playerID, "LuckyCloudBuyError")  | 
|         return  | 
|       | 
|     if lotteryRec.lotteryNum:  | 
|         GameWorld.ErrLog("ÐÒÔËÔÆ¹º¹ºÂòÒì³££¡ÒÑ¿ª½±£¬ÎÞ·¨ÔÙ¹ºÂò£¡ roundID=%s,zoneID=%s, lotteryNum=%s"  | 
|                           % (roundID, zoneID, lotteryRec.lotteryNum))  | 
|         PlayerControl.CrossNotifyCode(serverGroupID, playerID, "LuckyCloudBuyError")  | 
|         return  | 
|       | 
|     buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])  | 
|     maxBuyCount = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 2)  | 
|     remainCount = max(0, maxBuyCount - len(buyRecList))  | 
|       | 
|     if remainCount < buyCount:  | 
|         GameWorld.ErrLog("ÐÒÔËÔÆ¹º¹ºÂòÒì³££¡Ê£Óà¿É¹ºÂòµÄ·ÝÊý²»×㣡 remainCount=%s < buyCount=%s" % (remainCount, buyCount))  | 
|         PlayerControl.CrossNotifyCode(serverGroupID, playerID, "LuckyCloudBuyError")  | 
|         return  | 
|       | 
|     preBuyRec = None if not buyRecList else buyRecList[-1]  | 
|     startNum = 1 if not preBuyRec else (preBuyRec.buyNum + 1)  | 
|     buyNumList = range(startNum, startNum + buyCount)  | 
|       | 
|     zoneBuyNumList = []  | 
|     for buyNum in buyNumList:  | 
|         buyRec = LuckyCloudBuyNum()  | 
|         buyRec.idTime = roundID  | 
|         buyRec.zoneID = zoneID  | 
|         buyRec.roundNum = lotteryRec.roundNum  | 
|         buyRec.playerID = playerID  | 
|         buyRec.buyNum = buyNum  | 
|         buyRec.buyTime = int(time.time())  | 
|           | 
|         buyRec.playerName = playerName  | 
|         buyRec.accID = accID  | 
|           | 
|         if zoneID not in PyGameData.g_luckyCloudBuyNumDict:  | 
|             PyGameData.g_luckyCloudBuyNumDict[zoneID] = []  | 
|         buyRecList = PyGameData.g_luckyCloudBuyNumDict[zoneID]  | 
|         buyRecList.append(buyRec)  | 
|           | 
|         zoneBuyNumList.append(buyRec.GetString())  | 
|               | 
|     dataDict = {"PlayerID":playerID, "AccID":accID, "zoneID":zoneID, "roundID":roundID, "roundNum":lotteryRec.roundNum,   | 
|                 "buyNumList":buyNumList, "buyCount":buyCount, "remainCount":(remainCount - buyCount)}  | 
|     DataRecordPack.SendEventPack("LuckyCloudBuyNum", dataDict)  | 
|       | 
|     # Í¨Öª×Ó·þ  | 
|     dataMsg = {"syncType":"New", "zoneID":zoneID, "zoneBuyNumList":zoneBuyNumList, "buyPlayer":[serverGroupID, playerID, roundID, buyCount]}  | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyNum, dataMsg)  | 
|       | 
|     # ½áË㿪½±  | 
|     if remainCount == buyCount:  | 
|         DoLuckyCloudBuyLottery(lotteryRec, False, "SoldOut")  | 
|           | 
|     return  | 
|   | 
| def DoGMLuckyCloudBuy(serverGroupID, buyCount):  | 
|     GameWorld.Log("GMÌí¼ÓÔÆ¹º¼Ç¼! serverGroupID=%s,buyCount=%s" % (serverGroupID, buyCount))  | 
|       | 
|     zoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)  | 
|     if not zoneID:  | 
|         return  | 
|       | 
|     lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])  | 
|     if not lotteryRecList:  | 
|         return  | 
|     lotteryRec = lotteryRecList[-1]  | 
|       | 
|     buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])  | 
|     maxBuyCount = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 2)  | 
|     remainCount = max(0, maxBuyCount - len(buyRecList))  | 
|     buyCount = min(buyCount, remainCount)  | 
|     if buyCount <= 0:  | 
|         GameWorld.ErrLog("GMÐÒÔËÔÆ¹º¹ºÂòÒì³££¡Ê£Óà¿É¹ºÂòµÄ·ÝÊý²»×㣡zoneID=%s,buyCount=%s" % (zoneID, buyCount))  | 
|         return  | 
|       | 
|     preBuyRec = None if not buyRecList else buyRecList[-1]  | 
|     startNum = 1 if not preBuyRec else (preBuyRec.buyNum + 1)  | 
|     buyNumList = range(startNum, startNum + buyCount)  | 
|     buyPlayerID = random.choice([1001, 1002, 1003]) # Ëæ»úѡһ¸öGM²âÊÔplayerID  | 
|       | 
|     zoneBuyNumList = []  | 
|     for buyNum in buyNumList:  | 
|         buyRec = LuckyCloudBuyNum()  | 
|         buyRec.idTime = lotteryRec.idTime  | 
|         buyRec.zoneID = zoneID  | 
|         buyRec.roundNum = lotteryRec.roundNum  | 
|         buyRec.playerID = buyPlayerID  | 
|         buyRec.buyNum = buyNum  | 
|         buyRec.buyTime = int(time.time())  | 
|           | 
|         buyRec.playerName = "[s%s]playerName_%s" % (serverGroupID, buyPlayerID)  | 
|         buyRec.accID = "accID_%s@test@s%s" % (buyPlayerID, serverGroupID)  | 
|           | 
|         if zoneID not in PyGameData.g_luckyCloudBuyNumDict:  | 
|             PyGameData.g_luckyCloudBuyNumDict[zoneID] = []  | 
|         buyRecList = PyGameData.g_luckyCloudBuyNumDict[zoneID]  | 
|         buyRecList.append(buyRec)  | 
|           | 
|         zoneBuyNumList.append(buyRec.GetString())  | 
|           | 
|     # Í¨Öª×Ó·þ  | 
|     dataMsg = {"syncType":"New", "zoneID":zoneID, "zoneBuyNumList":zoneBuyNumList}  | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyNum, dataMsg)  | 
|       | 
|     # ½áË㿪½±  | 
|     if remainCount == buyCount:  | 
|         DoLuckyCloudBuyLottery(lotteryRec, False, "SoldOut")  | 
|     return  | 
|   | 
| def CrossServerMsg_LuckyCloudBuyNum(msgData):  | 
|     ## ×Ó·þÊÕµ½¹ºÂò¼Ç¼֪ͨ  | 
|       | 
|     syncType = msgData["syncType"] # All New  | 
|     zoneID = msgData["zoneID"]  | 
|     zoneBuyNumList = msgData["zoneBuyNumList"]  | 
|       | 
|     curServerGroupID = GameWorld.GetServerGroupID()  | 
|     actInfo = CrossActionControl.GetCrossActInfoByServerGroupID(ShareDefine.CrossActName_LuckyCloudBuy, curServerGroupID)  | 
|     if not actInfo:  | 
|         return  | 
|     state = actInfo.get(ShareDefine.ActKey_State)  | 
|     ipyDataInfo = actInfo.get(ShareDefine.ActKey_IpyDataInfo)  | 
|     if not state or not ipyDataInfo:  | 
|         return  | 
|     serverZoneID = ipyDataInfo.get("ZoneID")  | 
|     if zoneID != serverZoneID:  | 
|         GameWorld.DebugLog("²»ÊDZ¾·þÎñÆ÷·ÖÇøµÄÔÆ¹º¼Ç¼²»´¦Àí! curServerGroupID=%s,serverZoneID(%s) != zoneID(%s)"   | 
|                            % (curServerGroupID, serverZoneID, zoneID))  | 
|         return  | 
|       | 
|     if syncType == "All":  | 
|         PyGameData.g_luckyCloudBuyNumDict = {}  | 
|           | 
|     if zoneID not in PyGameData.g_luckyCloudBuyNumDict:  | 
|         PyGameData.g_luckyCloudBuyNumDict[zoneID] = []  | 
|     buyRecList = PyGameData.g_luckyCloudBuyNumDict[zoneID]  | 
|       | 
|     syncRecList = []  | 
|     for attrDict in zoneBuyNumList:  | 
|         buyRec = LuckyCloudBuyNum()  | 
|         buyRec.SetAttrByDict(attrDict)  | 
|         buyRecList.append(buyRec)  | 
|         if syncType == "New":  | 
|             syncRecList.append(buyRec)  | 
|               | 
|     if syncRecList:  | 
|         Sync_LuckyCloudBuyNumRecInfo(None, syncRecList)  | 
|           | 
|     buyPlayer = msgData.get("buyPlayer")  | 
|     if not buyPlayer:  | 
|         return  | 
|     serverGroupID, playerID, roundID, buyCount = buyPlayer  | 
|     if serverGroupID != curServerGroupID:  | 
|         return  | 
|       | 
|     templateIDList = ipyDataInfo.get("TemplateIDList")  | 
|     if not templateIDList:  | 
|         return  | 
|       | 
|     dayIndex = actInfo.get(ShareDefine.ActKey_DayIndex, 0)  | 
|     templateID = templateIDList[dayIndex] if len(templateIDList) > dayIndex else templateIDList[-1]  | 
|     templateIpyData = IpyGameDataPY.GetIpyGameData("CrossActLuckyCloudBuyTemplate", templateID)  | 
|     if not templateIpyData:  | 
|         return  | 
|     baseAwardInfo = templateIpyData.GetBaseAwardInfo()  | 
|     randAwardWeightInfo = templateIpyData.GetRandAwardWeightInfo()  | 
|       | 
|     awardItemDict = {}  | 
|     for _ in xrange(buyCount):  | 
|         awardItemInfo = []  | 
|         awardItemInfo += baseAwardInfo  | 
|         randItemInfo = GameWorld.GetResultByWeightList(randAwardWeightInfo)  | 
|         if randItemInfo:  | 
|             awardItemInfo += [randItemInfo]  | 
|               | 
|         for itemID, itemCount, isBind in awardItemInfo:  | 
|             if itemID not in awardItemDict:  | 
|                 awardItemDict[itemID] = [itemCount, isBind]  | 
|             else:  | 
|                 awardItemDict[itemID] = [awardItemDict[itemID][0] + itemCount, isBind]  | 
|                   | 
|     awardItemList = []  | 
|     for itemID in awardItemDict.keys():  | 
|         itemCount, isBind = awardItemDict[itemID]  | 
|         awardItemList.append([itemID, itemCount, isBind])  | 
|           | 
|     player = GameWorld.GetPlayerManager().FindPlayerByID(playerID)  | 
|     if not player:  | 
|         GameWorld.Log("Íæ¼Ò²»ÔÚÏßÏÈ»º´æ£¬Íæ¼ÒÉÏÏߺóÔÙͬ²½Ôƹº! roundID=%s,buyCount=%s,awardItemList=%s"   | 
|                       % (roundID, buyCount, awardItemList), playerID)  | 
|         PyGameData.g_unNotifyCloudBuyNumDict[playerID] = [roundID, buyCount, awardItemList]  | 
|         return  | 
|       | 
|     mapID = player.GetRealMapID()  | 
|     sysMsg = str(["LuckyCloudBuyNum", roundID, buyCount, awardItemList])  | 
|     player.MapServer_QueryPlayerResult(0, 0, "LuckyCloudBuy", sysMsg, len(sysMsg))  | 
|     GameWorld.Log("֪ͨµØÍ¼¿ç·þÔÆ¹º¹ºÂò½áËã: roundID=%s,buyCount=%s,mapID=%s" % (roundID, buyCount, mapID), playerID)  | 
|     return  | 
|   | 
| def __LoginNotifyMapCloudBuyNumInfo(curPlayer):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     if playerID not in PyGameData.g_unNotifyCloudBuyNumDict:  | 
|         return  | 
|     roundID, buyCount, awardItemList = PyGameData.g_unNotifyCloudBuyNumDict.pop(playerID)  | 
|       | 
|     mapID = curPlayer.GetRealMapID()  | 
|     sysMsg = str(["LuckyCloudBuyNum", roundID, buyCount, awardItemList])  | 
|     curPlayer.MapServer_QueryPlayerResult(0, 0, "LuckyCloudBuy", sysMsg, len(sysMsg))  | 
|     GameWorld.Log("ÉÏÏß²¹Í¨ÖªµØÍ¼¿ç·þÔÆ¹º¹ºÂò½áËã: roundID=%s,buyCount=%s,mapID=%s" % (roundID, buyCount, mapID), playerID)  | 
|     return  | 
|   | 
| #// C0 05 ²éѯÐÒÔËÔÆ¹º¹ºÂòºÅÂë¼Ç¼ #tagCGQueryLuckyCloudBuyNumRec  | 
| #  | 
| #struct    tagCGQueryLuckyCloudBuyNumRec  | 
| #{  | 
| #    tagHead        Head;  | 
| #};  | 
| def OnQueryLuckyCloudBuyNumRec(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     if GameWorld.IsCrossServer():  | 
|         return  | 
|     Sync_LuckyCloudBuyNumRecInfo(curPlayer)  | 
|     return  | 
|   | 
| #// C0 06 ²éѯÐÒÔËÔÆ¹º¿ª½±¼Ç¼ #tagCGQueryLuckyCloudBuyLotteryRec  | 
| #  | 
| #struct    tagCGQueryLuckyCloudBuyLotteryRec  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        ZoneID;    //²éѯ·ÖÇøID  | 
| #};  | 
| def OnQueryLuckyCloudBuyLotteryRec(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     if GameWorld.IsCrossServer():  | 
|         return  | 
|     zoneID = clientData.ZoneID  | 
|     Sync_LuckyCloudBuyLotteryRecInfo(curPlayer, zoneID)  | 
|     return  | 
|   | 
| def Sync_LuckyCloudBuyRoundInfo(curPlayer):  | 
|     ## Í¨Öª»î¶¯ÖеÄÔÆ¹º»î¶¯ÐÅÏ¢  | 
|     serverGroupID = GameWorld.GetServerGroupID()  | 
|     actInfo = CrossActionControl.GetCrossActInfoByServerGroupID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)  | 
|     if not actInfo:  | 
|         return  | 
|     state = actInfo.get(ShareDefine.ActKey_State)  | 
|     ipyDataInfo = actInfo.get(ShareDefine.ActKey_IpyDataInfo)  | 
|     if not state or not ipyDataInfo:  | 
|         return  | 
|     zoneID = ipyDataInfo.get("ZoneID")  | 
|     if not zoneID:  | 
|         return  | 
|       | 
|     templateIDList = ipyDataInfo.get("TemplateIDList")  | 
|     if not templateIDList:  | 
|         return  | 
|       | 
|     dayIndex = actInfo.get(ShareDefine.ActKey_DayIndex, 0)  | 
|     templateID = templateIDList[dayIndex] if len(templateIDList) > dayIndex else templateIDList[-1]  | 
|     templateIpyData = IpyGameDataPY.GetIpyGameData("CrossActLuckyCloudBuyTemplate", templateID)  | 
|     if not templateIpyData:  | 
|         return  | 
|     baseAwardInfo = templateIpyData.GetBaseAwardInfo()  | 
|     randAwardWeightInfo = templateIpyData.GetRandAwardWeightInfo()  | 
|       | 
|     lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])  | 
|     lotteryRec = None if not lotteryRecList else lotteryRecList[-1] # È¡×îÐÂÒ»ÆÚµÄ  | 
|     if not lotteryRec:  | 
|         return  | 
|       | 
|     superItemInfo = lotteryRec.superItemInfo + [0, 0, 0, 0, 0]  | 
|     superItemID, superItemCount, _, moneyType, moneyValue = superItemInfo[:5]  | 
|     clientPack = ChPyNetSendPack.tagGCLuckyCloudBuyRoundInfo()  | 
|     clientPack.ZoneID = zoneID  | 
|     clientPack.StartDate = ipyDataInfo.get("StartDate", "")  | 
|     clientPack.EndtDate = ipyDataInfo.get("EndDate", "")  | 
|     clientPack.LVLimit = ipyDataInfo.get("LVLimit", 0)  | 
|     clientPack.RoundID = lotteryRec.idTime  | 
|     clientPack.RoundNum = lotteryRec.roundNum  | 
|     clientPack.SuperItemID = superItemID  | 
|     clientPack.SuperItemCount = superItemCount  | 
|     clientPack.SuperItemMoneyType = moneyType  | 
|     clientPack.SuperItemMoneyValue = moneyValue  | 
|     clientPack.BaseItemList = []  | 
|     for itemID, itemCount, isBind in baseAwardInfo:  | 
|         item = ChPyNetSendPack.tagGCLuckyCloudBuyRoundItem()  | 
|         item.ItemID = itemID  | 
|         item.ItemCount = itemCount  | 
|         item.IsBind = isBind  | 
|         clientPack.BaseItemList.append(item)  | 
|     clientPack.BaseItemCount = len(clientPack.BaseItemList)  | 
|       | 
|     clientPack.RandItemList = []  | 
|     for _, itemID, itemCount, isBind in randAwardWeightInfo:  | 
|         item = ChPyNetSendPack.tagGCLuckyCloudBuyRoundItem()  | 
|         item.ItemID = itemID  | 
|         item.ItemCount = itemCount  | 
|         item.IsBind = isBind  | 
|         clientPack.RandItemList.append(item)  | 
|     clientPack.RandItemCount = len(clientPack.RandItemList)  | 
|       | 
|     if not curPlayer:  | 
|         playerManager = GameWorld.GetPlayerManager()  | 
|         for i in xrange(playerManager.GetActivePlayerCount()):  | 
|             curPlayer = playerManager.GetActivePlayerAt(i)  | 
|             if curPlayer == None:  | 
|                 continue  | 
|             if PlayerControl.GetIsTJG(curPlayer):  | 
|                 continue  | 
|             NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     else:  | 
|         if PlayerControl.GetIsTJG(curPlayer):  | 
|             return  | 
|         NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|           | 
|     return  | 
|   | 
| def Sync_LuckyCloudBuyNumRecInfo(curPlayer, syncRecList=None):  | 
|     ## Í¨Öª»î¶¯ÖеÄÔÆ¹º»î¶¯¹ºÂò¼Ç¼ÐÅÏ¢  | 
|       | 
|     serverGroupID = GameWorld.GetServerGroupID()  | 
|     zoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)  | 
|     buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])  | 
|           | 
|     if syncRecList == None:  | 
|         lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])  | 
|         lotteryRec = None if not lotteryRecList else lotteryRecList[-1] # È¡×îÐÂÒ»ÆÚµÄ  | 
|         if not lotteryRec:  | 
|             return  | 
|         syncRecList = buyRecList[-50:]  | 
|           | 
|     maxBuyCount = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 2)  | 
|           | 
|     clientPack = ChPyNetSendPack.tagGCLuckyCloudBuyNumRecInfo()  | 
|     clientPack.RemainCount = max(0, maxBuyCount - len(buyRecList))  | 
|     clientPack.BuyNumRecList = []  | 
|     for buyRec in syncRecList:  | 
|         buyNumInfo = ChPyNetSendPack.tagGCLuckyCloudBuyNumRec()  | 
|         buyNumInfo.PlayerName = buyRec.playerName  | 
|         buyNumInfo.NameLen = len(buyNumInfo.PlayerName)  | 
|         buyNumInfo.BuyNum = buyRec.buyNum  | 
|         clientPack.BuyNumRecList.append(buyNumInfo)  | 
|           | 
|     clientPack.Count = len(clientPack.BuyNumRecList)  | 
|           | 
|     if not curPlayer:  | 
|         playerManager = GameWorld.GetPlayerManager()  | 
|         for i in xrange(playerManager.GetActivePlayerCount()):  | 
|             curPlayer = playerManager.GetActivePlayerAt(i)  | 
|             if curPlayer == None:  | 
|                 continue  | 
|             if PlayerControl.GetIsTJG(curPlayer):  | 
|                 continue  | 
|             NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     else:  | 
|         if PlayerControl.GetIsTJG(curPlayer):  | 
|             return  | 
|         NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  | 
|   | 
| def Sync_LuckyCloudBuyLotteryRecInfo(curPlayer, zoneID, syncRec=None):  | 
|     ## Í¨ÖªÔƹº»î¶¯·ÖÇøÀúÊ·¿ª½±ÐÅÏ¢  | 
|       | 
|     if syncRec == None:          | 
|         lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])  | 
|     else:  | 
|         lotteryRecList = [syncRec]  | 
|           | 
|     clientPack = ChPyNetSendPack.tagGCLuckyCloudBuyLotteryRecInfo()  | 
|     clientPack.ZoneIDList = PyGameData.g_luckyCloudBuyLotteryDict.keys()  | 
|     clientPack.ZoneCount = len(clientPack.ZoneIDList)  | 
|     clientPack.ZoneID = zoneID  | 
|     clientPack.LotteryRecList = []  | 
|     for lotteryRec in lotteryRecList:  | 
|         if not lotteryRec.lotteryNum:  | 
|             # Î´¿ª½±µÄÔݲ»Í¬²½  | 
|             continue  | 
|         lotteryInfo = ChPyNetSendPack.tagGCLuckyCloudBuyLotteryRec()  | 
|         lotteryInfo.SuperItemID = lotteryRec.superItemInfo[0] if len(lotteryRec.superItemInfo) > 0 else 0  | 
|         lotteryInfo.SuperItemCount = lotteryRec.superItemInfo[1] if len(lotteryRec.superItemInfo) > 1 else 0  | 
|         lotteryInfo.PlayerName = lotteryRec.luckyPlayerName  | 
|         lotteryInfo.NameLen = len(lotteryInfo.PlayerName)  | 
|         lotteryInfo.LotteryNum = lotteryRec.lotteryNum  | 
|         lotteryInfo.LotteryTime = lotteryRec.lotteryTime  | 
|         clientPack.LotteryRecList.append(lotteryInfo)  | 
|           | 
|     clientPack.Count = len(clientPack.LotteryRecList)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  |