| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package CrossActionControl  | 
| #  | 
| # @todo:¿ç·þ»î¶¯×Ü¿ª¹ØÂß¼  | 
| # @author hxp  | 
| # @date 2020-01-13  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ¿ç·þ»î¶¯×Ü¿ª¹ØÂß¼  | 
| #          ¿ç·þ»î¶¯µÄʱ¼äÒÔ¿ç·þ·þÎñÆ÷Ϊ׼£¬ËùÓеÄ״̬¿ØÖÆÓÉ¿ç·þ·þÎñÆ÷¿ØÖƲ¢¹ã²¥×Ó·þÎñÆ÷  | 
| #          ×Ó·þ½ö×ö¾ßÌå»î¶¯Âß¼  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2020-01-13 17:00"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import GameWorld  | 
| import ShareDefine  | 
| import PlayerControl  | 
| import IpyGameDataPY  | 
| import CrossActCTGBillboard  | 
| import CrossRealmMsg  | 
| import PyGameData  | 
| import ChConfig  | 
|   | 
| import datetime  | 
| import time  | 
|   | 
| (  | 
| CrossAct_ReloadSign, # ÐÅÏ¢ÖØÔØ±ê¼Ç  | 
| CrossAct_TodayInfo, # µ±ÈյĻÐÅÏ¢  | 
| CrossAct_CfgIDInfo, # ´¦ÀíµÄcfgIDÐÅÏ¢  | 
| ) = range(3)  | 
|   | 
| def OnPlayerLogin(curPlayer):  | 
|     return  | 
|   | 
| def OnServerClose():  | 
|     if not GameWorld.IsCrossServer():  | 
|         return  | 
|           | 
|     GameWorld.GetUniversalRecMgr().Delete(ShareDefine.Def_UniversalGameRecType_CrossActInfo)  | 
|       | 
|     if not PyGameData.g_crossActInfoDict:  | 
|         return  | 
|     GameWorld.Log("±£´æ¿ç·þÔËÓª»î¶¯ÐÅϢͨÓüǼ: ")  | 
|       | 
|     # ±£´æ»î¶¯ÖÐµÄ  | 
|     recDataList = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossActInfo)  | 
|     for actName, actInfoDict in PyGameData.g_crossActInfoDict.items():  | 
|         for cfgID, actInfo in actInfoDict.items():  | 
|             if not actInfo.get(ShareDefine.ActKey_State):  | 
|                 # ·Ç»î¶¯Öеģ¬ÒѾ½áËã¹ýÁË£¬²»ÐèÒª´æ´¢  | 
|                 continue  | 
|             state = actInfo.get(ShareDefine.ActKey_State, 0)  | 
|             actID = actInfo.get(ShareDefine.ActKey_ID, 0)  | 
|             templateID = actInfo.get(ShareDefine.ActKey_TemplateID, 0)  | 
|             serverIDRangeList = actInfo.get(ShareDefine.ActKey_ServerIDRangeList, "")  | 
|             recData = recDataList.AddRec()  | 
|             recData.SetStrValue1(actName)  | 
|             recData.SetStrValue3(str(serverIDRangeList))  | 
|             recData.SetValue1(cfgID)  | 
|             recData.SetValue2(state)  | 
|             recData.SetValue3(actID)  | 
|             recData.SetValue4(templateID)  | 
|             GameWorld.Log("    actName=%s,cfgID=%s,state=%s,actID=%s,templateID=%s,serverIDRangeList=%s"   | 
|                           % (actName, cfgID, state, actID, templateID, serverIDRangeList))  | 
|               | 
|     return  | 
|   | 
| def GetCrossActZoneID(actName, serverGroupID):  | 
|     ## »ñÈ¡×Ó·þIDËùÊô¿ç·þ»î¶¯·ÖÇø£¬ ¿ç·þ¡¢×Ó·þͨÓà  | 
|     actInfoDict = GetCrossActInfoByServerGroupID(actName, serverGroupID)  | 
|     if not actInfoDict:  | 
|         return  | 
|     cfgID = actInfoDict.get(ShareDefine.ActKey_CfgID)  | 
|     ipyDataInfo = actInfoDict.get(ShareDefine.ActKey_IpyDataInfo)  | 
|     if not ipyDataInfo:  | 
|         GameWorld.ErrLog("ActKey_IpyDataInfoΪ¿Õ, ÕÒ²»µ½¿ç·þ»î¶¯ËùÊô·ÖÇø! actName=%s, serverGroupID=%s, cfgID=%s"   | 
|                          % (actName, serverGroupID, cfgID))  | 
|         return  | 
|     return ipyDataInfo.get("ZoneID")  | 
|   | 
| def GetCrossActInfoByServerGroupID(actName, serverGroupID):  | 
|     '''»ñÈ¡×Ó·þIDËùÊô¿ç·þ»î¶¯ÐÅÏ¢£¬ ¿ç·þ¡¢×Ó·þͨÓà  | 
|         @param serverGroupID: ·þÎñÆ÷ID»ò·þÎñÆ÷·ÖID  | 
|                                 ¿ç·þ»î¶¯±íÅäÖõÄÊÇ·þÎñÆ÷ID£¬¶ø×Ó·þºÏ·þºóÒÔÖ÷·þµÄ·þÎñÆ÷ID×÷Ϊ·þÎñÆ÷×éID£¬ËùÒÔÁ½ÖÖ·þÎñÆ÷IDÔڴ˺¯ÊýÖÐͨÓà  | 
|         @return: None or ActKey_IpyDataInfo  | 
|     '''  | 
|       | 
|     crossActInfoDict = PyGameData.g_crossActInfoDict  | 
|     if crossActInfoDict and actName in crossActInfoDict:  | 
|         curActInfoDict = crossActInfoDict[actName]  | 
|           | 
|         for actInfoDict in curActInfoDict.values():  | 
|             if not actInfoDict.get(ShareDefine.ActKey_State, 0):  | 
|                 continue  | 
|             serverIDRangeList = actInfoDict.get(ShareDefine.ActKey_ServerIDRangeList)  | 
|             if not serverIDRangeList:  | 
|                 continue  | 
|               | 
|             for groupInfo in serverIDRangeList:  | 
|                 if (isinstance(groupInfo, int) and serverGroupID == groupInfo) \  | 
|                     or ((isinstance(groupInfo, tuple) or isinstance(groupInfo, list)) \  | 
|                         and len(groupInfo) == 2 and groupInfo[0] <= serverGroupID <= groupInfo[1]):  | 
|                     return actInfoDict  | 
|                   | 
|     GameWorld.DebugLog("ÕÒ²»µ½·þÎñÆ÷×éID¶ÔÓ¦¿ç·þ»î¶¯·ÖÇø! actName=%s, serverGroupID=%s" % (actName, serverGroupID))  | 
|     return  | 
|   | 
| def GetCrossActInfoByCfgID(actName, cfgID):  | 
|     crossActInfoDict = GetCrossActInfoDict()  | 
|     if actName not in crossActInfoDict:  | 
|         return  | 
|     curActInfoDict = crossActInfoDict[actName]  | 
|     if cfgID not in curActInfoDict:  | 
|         return  | 
|     return curActInfoDict[cfgID]  | 
|   | 
| def GetCrossActInfoDict():  | 
|     if PyGameData.g_crossActInfoDict == None:  | 
|         PyGameData.g_crossActInfoDict = {}  | 
|           | 
|         # ÏȼÓÔØÍ¨ÓüǼ´æ´¢ÖеĻÐÅÏ¢  | 
|         recDataList = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossActInfo)  | 
|         GameWorld.Log("¼ÓÔØÍ¨ÓüǼÖеĿç·þÔËÓª»î¶¯ÐÅÏ¢: %s" % recDataList.Count())  | 
|         for index in xrange(recDataList.Count()):  | 
|             recData = recDataList.At(index)  | 
|             actName = recData.GetStrValue1()  | 
|             strValue3 = recData.GetStrValue3()  | 
|             serverIDRangeList = eval(strValue3) if strValue3 else []  | 
|             cfgID = recData.GetValue1()  | 
|             state = recData.GetValue2()  | 
|             actID = recData.GetValue3()  | 
|             templateID = recData.GetValue4()  | 
|             if not state:  | 
|                 continue  | 
|             if actName not in PyGameData.g_crossActInfoDict:  | 
|                 PyGameData.g_crossActInfoDict[actName] = {}  | 
|             actInfoDict = PyGameData.g_crossActInfoDict[actName]  | 
|             # »î¶¯ID¡¢×´Ì¬¡¢Ä£°åÐÅÏ¢µ¥¶À´æ´¢£¬ÖØÖûÅжÏÓà  | 
|             dbInfo = {ShareDefine.ActKey_ID:actID, ShareDefine.ActKey_State:state, ShareDefine.ActKey_TemplateID:templateID,   | 
|                       ShareDefine.ActKey_CfgID:cfgID, ShareDefine.ActKey_ServerIDRangeList:serverIDRangeList}  | 
|             actInfo = {}  | 
|             actInfo.update(dbInfo)  | 
|             actInfo[ShareDefine.ActKey_DBInfo] = dbInfo  | 
|             actInfoDict[cfgID] = actInfo  | 
|               | 
|             GameWorld.Log("    actName=%s,cfgID=%s, %s" % (actName, cfgID, actInfoDict))  | 
|               | 
|     return PyGameData.g_crossActInfoDict  | 
|   | 
| def __GetParseIpyDataList(ipyDataMgr, actName, actInfoDict):  | 
|     ## »ñÈ¡ÐèÒª´¦ÀíµÄºÏ·¨·Ö×é»î¶¯ÅäÖÃÁÐ±í£¬ÒѾÔڻÖеıØÐëÒª´¦Àí  | 
|       | 
|     groupNameList = [] # È·±£·Ö×é˳Ðò  | 
|     groupInfo = {}  | 
|     actCfgCount = getattr(ipyDataMgr, "Get%sCount" % actName)()  | 
|     for cfgIndex in xrange(actCfgCount):  | 
|         ipyData = getattr(ipyDataMgr, "Get%sByIndex" % actName)(cfgIndex)  | 
|         actGroupName = ipyData.GetActGroupName()  | 
|         if actGroupName not in groupInfo:  | 
|             groupInfo[actGroupName] = []  | 
|             groupNameList.append(actGroupName)  | 
|         groupIpyDataList = groupInfo[actGroupName]  | 
|         groupIpyDataList.append(ipyData)  | 
|           | 
|     parseIpyDataList = []  | 
|     for actGroupName in groupNameList:  | 
|         groupIpyDataList = groupInfo[actGroupName]  | 
|         allOpen = False  | 
|         cfgIDList = []  | 
|         allServerIDRangeList = []  | 
|         for ipyData in groupIpyDataList:  | 
|             cfgID = ipyData.GetCfgID()  | 
|             cfgIDList.append(cfgID)  | 
|             serverIDRangeList = ipyData.GetServerIDRangeList()  | 
|               | 
|             if cfgID in actInfoDict and actInfoDict[cfgID]:  | 
|                 actInfo = actInfoDict[cfgID]  | 
|                 # ÒѾÔڻÖеļǼ±ØÐëÒª´¦Àí  | 
|                 parseIpyDataList.append(ipyData)  | 
|                 if actName in ShareDefine.CrossActLockServerGroupIDList:  | 
|                     serverIDRangeList = actInfo[ShareDefine.ActKey_ServerIDRangeList]  | 
|                     GameWorld.Log("    Ê¹ÓÃÒѾÔڻÖеļǼµÄÇø·þ·Ö×é: cfgID=%s,serverIDRangeList=%s"   | 
|                                   % (cfgID, serverIDRangeList))  | 
|                       | 
|             # Ã»ÅäÖõÄÈ«·þ¿ª·Å  | 
|             if not serverIDRangeList:  | 
|                 allOpen = True  | 
|             else:  | 
|                 allServerIDRangeList.extend(serverIDRangeList)  | 
|                   | 
|         if allOpen and len(groupIpyDataList) > 1:  | 
|             GameWorld.ErrLog("    Í¬×é»î¶¯·þÎñÆ÷IDÅäÖÃÒì³££¬ÓÐÈ«·þ¿ª·ÅµÄ£¬Ö»ÄÜÅäÖÃ1Ìõ£¬²»´¦Àí! actGroupName=%s,cfgIDList=%s" % (actGroupName, cfgIDList))  | 
|             continue  | 
|           | 
|         errorServerIDList = []  | 
|         for i in xrange(len(allServerIDRangeList)):  | 
|             checkIDA, checkIDB = allServerIDRangeList[i]  | 
|             for j in xrange(i):  | 
|                 serverIDA, serverIDB = allServerIDRangeList[j]  | 
|                 if serverIDA <= checkIDA <= serverIDB:  | 
|                     errorServerIDList.append(checkIDA)  | 
|                       | 
|                 if serverIDA <= checkIDB <= serverIDB:  | 
|                     errorServerIDList.append(checkIDB)  | 
|                       | 
|         if errorServerIDList:  | 
|             GameWorld.ErrLog("    Í¬×é»î¶¯·þÎñÆ÷IDÅäÖÃÒì³££¬Óн»²æ£¬²»´¦Àí! actGroupName=%s,cfgIDList=%s,errorServerIDList=%s"   | 
|                              % (actGroupName, cfgIDList, errorServerIDList))  | 
|             continue  | 
|           | 
|         for ipyData in groupIpyDataList:  | 
|             cfgID = ipyData.GetCfgID()  | 
|             if cfgID in actInfoDict and actInfoDict[cfgID]:  | 
|                 continue  | 
|             parseIpyDataList.append(ipyData)  | 
|               | 
|     return parseIpyDataList  | 
|   | 
| def __GetCrossActInfo(isRefreshState=True):  | 
|     # @return: isReload, CrossActInfo  | 
|       | 
|     key = "CrossActInfo"  | 
|     CrossActInfo = IpyGameDataPY.GetConfigEx(key)  | 
|     serverTime = GameWorld.GetServerTime()  | 
|     curDateStr = "%d-%d-%d" % (serverTime.year, serverTime.month, serverTime.day)  | 
|     curHour = serverTime.hour  | 
|     reloadSignHour = 0 if curHour < 5 else 5  | 
|     reloadSign = "%s %s" % (curDateStr, reloadSignHour)  | 
|     if CrossActInfo and CrossActInfo[CrossAct_ReloadSign] == reloadSign:  | 
|         #GameWorld.DebugLog("ÒѾ¼ÓÔØ¹ý±¾ÈÕ¿ç·þÔËÓª»î¶¯´¦ÀíÐÅÏ¢£¡reloadSign=%s" % reloadSign)  | 
|         return False, CrossActInfo  | 
|       | 
|     # ÒòΪºóÃæµÄʱ¼äÅж϶¼ÊǾ«È·µ½·ÖµÄ£¬¶ø´¦Àí´ËÂß¼µÄʱºò¿ÉÄܲ»ÊÇ0Ã룬ËùÒÔÕâÀïµÄdatetimeÈ¡µ±Ç°Ê±¼ä¾«È·µ½·ÖµÄ  | 
|     curDateTimeStr = "%s %02d:%02d:00" % (curDateStr, serverTime.hour, serverTime.minute)  | 
|     curDateTime = datetime.datetime.strptime(curDateTimeStr, ChConfig.TYPE_Time_Format)  | 
|       | 
|     actTimeInfoDict = {}  | 
|     actCfgIDInfoDict = {}  | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|       | 
|     GameWorld.Log("=============================================================")  | 
|     GameWorld.Log("¼ÓÔØ±¾ÈÕ¿ç·þÔËÓª»î¶¯ÐÅÏ¢: %s, reloadSign=%s =====" % (curDateTime, reloadSign))  | 
|     crossActInfoDict = GetCrossActInfoDict()  | 
|     GameWorld.Log("    crossActInfoDict=%s" % crossActInfoDict)  | 
|       | 
|     for actName in ShareDefine.CrossActNameList:  | 
|           | 
|         # È¡³ö±¾»î¶¯ËùÊô±¾·þIDµÄËùÓÐÅäÖà  | 
|         GameWorld.Log("¼ÓÔØ¿ç·þÔËÓª»î¶¯: actName=%s" % (actName))  | 
|           | 
|         if not hasattr(ipyDataMgr, "Get%sCount" % actName):  | 
|             GameWorld.ErrLog("    Ã»Óиÿç·þÔËÓª»î¶¯ÀàÐͶÔÓ¦»î¶¯Ê±¼ä±í! actName=%s" % actName)  | 
|             continue  | 
|           | 
|         curActInfoDict = crossActInfoDict.get(actName, {})  | 
|           | 
|         # ÑéÖ¤·þÎñÆ÷ID²»Öظ´µÄÅäÖà  | 
|         parseIpyDataList = __GetParseIpyDataList(ipyDataMgr, actName, curActInfoDict)  | 
|         for ipyData in parseIpyDataList:  | 
|             cfgID = ipyData.GetCfgID()  | 
|             actGroupName = ipyData.GetActGroupName()  | 
|             startDateStr = ipyData.GetStartDate()  | 
|             endDateStr = ipyData.GetEndDate()  | 
|             GameWorld.Log("    cfgID=%s,actGroupName==%s,startDateStr=%s,endDateStr=%s,curDateTime=%s" % (cfgID, actGroupName, startDateStr, endDateStr, curDateTime))  | 
|             if not startDateStr:  | 
|                 startDateStr = curDateStr  | 
|                 GameWorld.Log("        ¿ªÊ¼ÈÕÆÚΪ¿Õ£¬Ä¬ÈÏÿÌ죬½ñÈÕΪ: startDateStr=%s" % startDateStr)  | 
|             if not endDateStr:  | 
|                 endDateStr = curDateStr  | 
|                 GameWorld.Log("        ½áÊøÈÕÆÚΪ¿Õ£¬Ä¬ÈÏÿÌ죬½ñÈÕΪ: endDateStr=%s" % endDateStr)  | 
|                   | 
|             actByWeek = (startDateStr.startswith("W") and endDateStr.startswith("W")) # °´ÖÜx¿ª  | 
|             if actByWeek:  | 
|                 startDateStr, endDateStr = GameWorld.GetOperationActionDateStr(ipyData)  | 
|                 GameWorld.Log("        ÐÇÆÚXת»¯ÎªÈÕÆÚ: %s ~ %s" % (startDateStr, endDateStr))  | 
|                   | 
|             if hasattr(ipyData, "GetStartTimeList") and hasattr(ipyData, "GetEndTimeList"):  | 
|                 startHMStrList = ipyData.GetStartTimeList()  | 
|                 endHMStrList = ipyData.GetEndTimeList()  | 
|             else:  | 
|                 startHMStrList = []  | 
|                 endHMStrList = []  | 
|                   | 
|             notifyInfoDictStart = ipyData.GetNotifyInfoStart() if hasattr(ipyData, "GetNotifyInfoStart") else {}  | 
|             notifyInfoDictEnd = ipyData.GetNotifyInfoEnd() if hasattr(ipyData, "GetNotifyInfoEnd") else {}  | 
|             notifyInfoLoopInfo = ipyData.GetNotifyInfoLoop() if hasattr(ipyData, "GetNotifyInfoLoop") else [] # [Ñ»··ÖÖÓ, ¹ã²¥key, [¹ã²¥²ÎÊýÁбí¿ÉÑ¡]]  | 
|               | 
|             if len(startHMStrList) != len(endHMStrList):  | 
|                 GameWorld.ErrLog("        »î¶¯ÅäÖÿªÊ¼¼°½áÊøÊ±¼ä¸öÊý²»Æ¥Åä! actName=%s,cfgID=%s,startHMStrList=%s,endHMStrList=%s"   | 
|                                  % (actName, cfgID, startHMStrList, endHMStrList))  | 
|                   | 
|             resetType = 0 if not hasattr(ipyData, "GetResetType") else ipyData.GetResetType() # ÖØÖÃÀàÐÍ£¬0-0µãÖØÖã»1-5µãÖØÖà  | 
|             if resetType == 1:  | 
|                 startDayDate = datetime.datetime.strptime("%s 05:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)  | 
|                 endDayDate = datetime.datetime.strptime("%s 05:00:00" % (endDateStr), ChConfig.TYPE_Time_Format) # ½áÊøÈÕÆÚ5µã  | 
|             elif resetType == 2:  | 
|                 startDayDate = datetime.datetime.strptime("%s 05:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)  | 
|                 endDayDate = datetime.datetime.strptime("%s 00:00:00" % (endDateStr), ChConfig.TYPE_Time_Format) + datetime.timedelta(days=1) # ½áÊøÈÕÆÚ¸ôÌì0µã  | 
|             else:  | 
|                 startDayDate = datetime.datetime.strptime("%s 00:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)  | 
|                 endDayDate = datetime.datetime.strptime("%s 00:00:00" % (endDateStr), ChConfig.TYPE_Time_Format) + datetime.timedelta(days=1) # ½áÊøÈÕÆÚ¸ôÌì0µã  | 
|                   | 
|             GameWorld.Log("        resetType=%s,startDayDate=%s,endDayDate=%s,startHMStrList=%s,endHMStrList=%s"   | 
|                           % (resetType, startDayDate, endDayDate, startHMStrList, endHMStrList))  | 
|               | 
|             if curDateTime < startDayDate or curDateTime >= endDayDate:  | 
|                 isActTime = False  | 
|                 if cfgID not in curActInfoDict or not curActInfoDict[cfgID]:  | 
|                     GameWorld.Log("        ·Ç»î¶¯Ê±¼ä£¡²»´¦Àí£¡")  | 
|                     continue  | 
|             else:  | 
|                 isActTime = True  | 
|                   | 
|             GameWorld.Log("        ÐèÒª´¦ÀíµÄ¿ç·þÔËÓª»î¶¯ÐÅÏ¢: cfgID=%s,isActTime=%s" % (cfgID, isActTime))  | 
|               | 
|             startList = [] # [startDateTime, ...]  | 
|             endList = [] # [endDateTime, ...]  | 
|             startNotifyDict = {} # {notifyDateTime:notifyInfo, ...}  | 
|             endNotifyDict = {} # {notifyDateTime:notifyInfo, ...}  | 
|             loopNotifyDict = {} # {notifyDateTime:notifyInfo, ...}  | 
|             notifyDict = {}  | 
|               | 
|             # Ã»ÅäÖÃʱ·ÖµÄ´ú±íÈ«Ìì  | 
|             if not startHMStrList:  | 
|                 startDateTime = startDayDate  | 
|                 endDateTime = endDayDate  | 
|                   | 
|                 startList.append(startDateTime)  | 
|                 endList.append(endDateTime)  | 
|                   | 
|             # Ã¿Ì찴ʱ¶Î¿ªÆôµÄ£¬Ö§³Ö¶àʱ¶Î  | 
|             else:  | 
|                 for hmIndex, startHMStr in enumerate(startHMStrList):  | 
|                     if hmIndex >= len(endHMStrList):  | 
|                         break  | 
|                     endHMStr = endHMStrList[hmIndex]  | 
|                     # Ã¿Ì쿪µÄ, Êµ¼Ê¿ª¹ØÊ±¼äֻȡ½ñÌìµÄÈÕÆÚ£» ÕâÀïÓиöÎÊÌ⣬ȫ·þ¹ã²¥µÄʱ¼ä²»ÊǽñÌìµÄ, Ôݲ»×öÖ§³Ö£¬Ö®ºóÕæÓÐÕâÖÖÐèÇóÔÙ˵  | 
|                     startTimeStr = "%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, startHMStr)  | 
|                     endTimeStr = "%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, endHMStr)  | 
|                     startDateTime = datetime.datetime.strptime(startTimeStr, ChConfig.TYPE_Time_Format)  | 
|                     endDateTime = datetime.datetime.strptime(endTimeStr, ChConfig.TYPE_Time_Format)  | 
|                       | 
|                     startList.append(startDateTime)  | 
|                     endList.append(endDateTime)  | 
|                       | 
|             GameWorld.Log("        startList=%s" % (startList))  | 
|             GameWorld.Log("        end  List=%s" % (endList))  | 
|               | 
|             for dtIndex, startDateTime in enumerate(startList):  | 
|                 endDateTime = endList[dtIndex]  | 
|                 # ¹ã²¥ - Ïà¶Ôʵ¼Ê¿ªÊ¼Ê±¼ä  | 
|                 for notifyMinute, notifyInfo in notifyInfoDictStart.items():  | 
|                     notifyDateTime = startDateTime + datetime.timedelta(minutes=notifyMinute)  | 
|                     if notifyDateTime.year == curDateTime.year and notifyDateTime.month == curDateTime.month and notifyDateTime.day == curDateTime.day:  | 
|                         startNotifyDict[notifyDateTime] = notifyInfo  | 
|                           | 
|                 # ¹ã²¥ - Ïà¶Ôʵ¼Ê½áÊøÊ±¼ä  | 
|                 for notifyMinute, notifyInfo in notifyInfoDictEnd.items():  | 
|                     notifyDateTime = endDateTime + datetime.timedelta(minutes=notifyMinute)  | 
|                     if notifyDateTime.year == curDateTime.year and notifyDateTime.month == curDateTime.month and notifyDateTime.day == curDateTime.day:  | 
|                         endNotifyDict[notifyDateTime] = notifyInfo  | 
|                           | 
|                 # ¹ã²¥ - Ñ»·¹ã²¥  | 
|                 if notifyInfoLoopInfo and len(notifyInfoLoopInfo) >= 2:  | 
|                     loopMinutes, loopNotifyKey = notifyInfoLoopInfo[:2]  | 
|                     loopNotifyParamList = notifyInfoLoopInfo[2] if len(notifyInfoLoopInfo) > 2 else []  | 
|                     notifyInfo = [loopNotifyKey, loopNotifyParamList] # Ñ»·¹ã²¥µÄĬÈÏÎÞ²ÎÊý  | 
|                     loopCount, loopMaxCount = 0, 100  | 
|                     while loopMinutes and loopNotifyKey and loopCount < loopMaxCount:  | 
|                         loopCount += 1  | 
|                         notifyDateTime = curDateTime + datetime.timedelta(minutes=loopMinutes * loopCount)  | 
|                         if notifyDateTime >= endDateTime:  | 
|                             break  | 
|                         if notifyDateTime.year == curDateTime.year and notifyDateTime.month == curDateTime.month and notifyDateTime.day == curDateTime.day:  | 
|                             loopNotifyDict[notifyDateTime] = notifyInfo  | 
|                               | 
|             if startNotifyDict or endNotifyDict or loopNotifyDict:  | 
|                 GameWorld.Log("        startNotifyDict: %s, %s" % (len(startNotifyDict.keys()), sorted(startNotifyDict.keys())))  | 
|                 GameWorld.Log("        end  NotifyDict: %s, %s" % (len(endNotifyDict.keys()), sorted(endNotifyDict.keys())))  | 
|                 GameWorld.Log("        loop NotifyDict: %s, %s" % (len(loopNotifyDict.keys()), sorted(loopNotifyDict.keys())))  | 
|                 notifyDict.update(startNotifyDict)  | 
|                 notifyDict.update(endNotifyDict)  | 
|                 notifyDict.update(loopNotifyDict)  | 
|                   | 
|             if actName not in actTimeInfoDict:  | 
|                 actTimeInfoDict[actName] = {}  | 
|             actTimeInfoDict[actName][cfgID] = [ipyData, startList, endList, notifyDict]  | 
|             if actName not in actCfgIDInfoDict:  | 
|                 actCfgIDInfoDict[actName] = [[], []]  | 
|             endCfgIDList, actCfgIDList = actCfgIDInfoDict[actName]  | 
|               | 
|             if actName not in crossActInfoDict:  | 
|                 crossActInfoDict[actName] = {}  | 
|             curActInfoDict = crossActInfoDict[actName]  | 
|             if cfgID not in curActInfoDict:  | 
|                 curActInfoDict[cfgID] = {}  | 
|             curCfgActInfoDict = curActInfoDict[cfgID]  | 
|               | 
|             # ipyData »î¶¯Ê±¼ä±íÐÅÏ¢ÓÉ¿ç·þ·þÎñÆ÷ͬ²½×Ó·þ£¬»î¶¯ÄÚÈÝÈ¡×Ó·þ×Ô¼ºµÄ  | 
|             ipyDataDict = {}  | 
|             for k, v in ipyData.__dict__.items():  | 
|                 if k in ["NotifyInfoStart", "NotifyInfoEnd", "NotifyInfoLoop", "ServerIDRangeList"]:  | 
|                     continue  | 
|                 ipyDataDict[k] = v  | 
|             ipyDataDict.update({"StartDate":startDateStr, "EndDate":endDateStr})  | 
|             GameWorld.Log("        ipyDataDict=%s" % ipyDataDict)  | 
|               | 
|             curCfgActInfoDict.update({ShareDefine.ActKey_CfgID:cfgID, ShareDefine.ActKey_IpyDataInfo:ipyDataDict})  | 
|             if ShareDefine.ActKey_ServerIDRangeList not in curCfgActInfoDict or actName not in ShareDefine.CrossActLockServerGroupIDList:  | 
|                 # Ã»ÓеϰÔòʹÓÃÅäÖÃÖе쬷ÀÖ¹ÅäÖÃÐ޸ĵ¼Ö·þÎñÆ÷ID·ÖÇø±ä¶¯ÒýÆðµÄ»î¶¯Êý¾ÝÒì³££¬³ý·Çºǫ́¹¤¾ßÇ¿ÖÆÐÞ¸Ä  | 
|                 curCfgActInfoDict[ShareDefine.ActKey_ServerIDRangeList] = ipyData.GetServerIDRangeList()  | 
|                   | 
|             actID, dayIndex, templateID = 0, 0, 0  | 
|             if isActTime:  | 
|                 ''' ×¢£º ¼ì²éÊÇ·ñÒѾ´æÔڻÖеķÖ×飬ÓеĻ°Ç¿Öƽ«ÆäÖÃΪ½áËã״̬£¬ÓÐÇÒ½öÓÐÒ»¸ö»î¶¯ÖеÄ×飬ºóÃæµÄÇ¿ÖÆ¸²¸ÇÇ°ÃæµÄ  | 
|                 parseIpyDataList  È·±£Í¬Ò»»î¶¯×éÃûµÄserverID²»»áÖØ¸´  | 
|                                         ÕâÀï½øÒ»²½È·±£²»Í¬»î¶¯×éÃûµÄ²»»áͬʱ¿ªÆô»î¶¯£¬ÓÐÇÒ½öÓÐÒ»¸ö»î¶¯ÖеĻ×é  | 
|                 '''  | 
|                 for befIpyData in parseIpyDataList:  | 
|                     befCfgID = befIpyData.GetCfgID()  | 
|                     befActGroupName = befIpyData.GetActGroupName()  | 
|                     if befActGroupName == actGroupName:  | 
|                         break  | 
|                     if befCfgID not in actCfgIDList:  | 
|                         continue  | 
|                     actCfgIDList.remove(befCfgID)  | 
|                     if befCfgID in curActInfoDict:  | 
|                         befCfgActInfoDict = curActInfoDict[befCfgID]  | 
|                         befCfgActInfoDict[ShareDefine.ActKey_ID] = 0 # »î¶¯IDÇ¿ÖÆÖÃΪ0  | 
|                           | 
|                     if befCfgID in endCfgIDList:  | 
|                         continue  | 
|                     endCfgIDList.append(befCfgID)  | 
|                     GameWorld.Log("        Ç°Ãæ´æÔڻµÄ·Ö×飬ÔòÇ¿ÖÆ½áÊø»î¶¯£¡ befCfgID=%s,befActGroupName=%s" % (befCfgID, befActGroupName))  | 
|                 if cfgID not in actCfgIDList:  | 
|                     actCfgIDList.append(cfgID)  | 
|                       | 
|                 dayIndex = (curDateTime - startDayDate).days  | 
|                 actIDDateTime = startDayDate  | 
|                 isDayReset = 0 if not hasattr(ipyData, "GetIsDayReset") else ipyData.GetIsDayReset()  | 
|                 # °´Ê±¶Î¿ªµÄĬÈÏÿÌìÖØÖà  | 
|                 if isDayReset or (startHMStrList and endHMStrList):  | 
|                     actIDDateTime += datetime.timedelta(days=dayIndex)  | 
|                 actID = int(time.mktime(actIDDateTime.timetuple())) # Ä¬ÈÏÈ¡¿ªÊ¼Ê±¼äµãµÄtimeÖµ×÷Ϊ»î¶¯ID  | 
|                 GameWorld.Log("        isDayReset=%s,actIDDateTime=%s,actID=%s" % (isDayReset, actIDDateTime, actID))  | 
|                   | 
|                 # Ä£°åID  | 
|                 if hasattr(ipyData, "TemplateIDList"):  | 
|                     templateIDList = ipyData.GetTemplateIDList()  | 
|                     templateID = templateIDList[-1] if dayIndex >= len(templateIDList) else templateIDList[dayIndex]  | 
|                       | 
|                     # ÆäËûÌØÊâÄ£°åID»ñÈ¡´¦Àí£¬ÓÐÐèÒªµÄµ¥¶À´¦Àí¼´¿É£¬¸ù¾Ý»î¶¯¹æÔò×ÔÐÐÀ©Õ¹...    | 
|             else:  | 
|                 if cfgID not in endCfgIDList:  | 
|                     endCfgIDList.append(cfgID)  | 
|                       | 
|             curCfgActInfoDict.update({ShareDefine.ActKey_ID:actID, ShareDefine.ActKey_TemplateID:templateID,   | 
|                                       ShareDefine.ActKey_DayIndex:dayIndex})  | 
|               | 
|     CrossActInfo = IpyGameDataPY.SetConfigEx(key, [reloadSign, actTimeInfoDict, actCfgIDInfoDict])  | 
|       | 
|     GameWorld.Log("±¾ÈÕ¿ç·þÔËÓª»î¶¯ÐÅÏ¢¼ÓÔØÍê±Ï!reloadSign=%s,isRefreshState=%s" % (reloadSign, isRefreshState))  | 
|     GameWorld.Log("    actTimeInfoDict=%s" % actTimeInfoDict)  | 
|     GameWorld.Log("    actCfgIDInfoDict=%s" % actCfgIDInfoDict)  | 
|     GameWorld.Log("    crossActInfoDict=%s" % crossActInfoDict)  | 
|     GameWorld.Log("=============================================================")  | 
|     if isRefreshState:  | 
|         Dispose_CrossActState(True)  | 
|           | 
|     return True, CrossActInfo  | 
|   | 
| def Dispose_CrossActState(reloadRefresh=False):  | 
|       | 
|     isReload, CrossActInfo = __GetCrossActInfo(False) # ÕâÀï±ØÐë´«False  | 
|     isReload = isReload or reloadRefresh  | 
|     actTimeInfoDict = CrossActInfo[CrossAct_TodayInfo]  | 
|     actCfgIDInfoDict = CrossActInfo[CrossAct_CfgIDInfo]  | 
|       | 
|     crossActInfoDict = GetCrossActInfoDict()  | 
|       | 
|     # ÕâÀïʱ¼äÐ辫ȷµ½·ÖÖÓ£¬²»È»ºóÃæµÄ±È½Ï»áÆ¥Åä²»µ½  | 
|     curDateTime = GameWorld.GetServerTime()  | 
|     curDateTime = datetime.datetime.strptime("%d-%d-%d %d:%d:00" % (curDateTime.year, curDateTime.month, curDateTime.day,  | 
|                                                                     curDateTime.hour, curDateTime.minute), ChConfig.TYPE_Time_Format)  | 
|     actChangeList = []  | 
|     actStateChangeList = []  | 
|     sysnCrossActInfoDict = {}  | 
|     for actName in ShareDefine.CrossActNameList:  | 
|         if actName not in actTimeInfoDict or actName not in crossActInfoDict or actName not in actCfgIDInfoDict:  | 
|             continue  | 
|                   | 
|         timeInfoDict = actTimeInfoDict[actName]  | 
|         endCfgIDList, actCfgIDList = actCfgIDInfoDict[actName]  | 
|         # ¿ÉÄÜÒ»ÌõcfgID´¦Àí½áÊø£¬ÁíÒ»ÌõcfgID´¦Àí¿ªÊ¼£¬Ò²¿ÉÄÜͬһÌõcfgID¼´½áÊøÍ¬Ê±ÓÖ¿ªÊ¼£¨ÈçÿÌìÖØÖõģ©  | 
|         cfgIDList = endCfgIDList + actCfgIDList  | 
|         for cfgID in cfgIDList:  | 
|             if cfgID not in timeInfoDict:  | 
|                 continue  | 
|             ipyData, startList, endList, notifyDict = timeInfoDict[cfgID]  | 
|               | 
|             isEnd = True  | 
|             state = 0 # Ä¬ÈÏ¹Ø±Õ  | 
|             cfgID = ipyData.GetCfgID()  | 
|             groupName = ipyData.GetActGroupName()  | 
|             zoneID = ipyData.GetZoneID()  | 
|               | 
|             if cfgID not in crossActInfoDict[actName]:  | 
|                 crossActInfoDict[actName][cfgID] = {}  | 
|             actInfoDict = crossActInfoDict[actName][cfgID]  | 
|               | 
|             # ×´Ì¬  | 
|             if cfgID not in endCfgIDList:  | 
|                 for dIndex, startDateTime in enumerate(startList):  | 
|                     endDateTime = endList[dIndex]  | 
|                     if startDateTime <= curDateTime < endDateTime:  | 
|                         state = dIndex + 1 # Ò²ÊÇ´ú±íµÚ¼¸¸öʱ¼ä¶Î  | 
|                         break  | 
|                 if endList:  | 
|                     isEnd = (curDateTime >= endList[-1])  | 
|                       | 
|             serverIDRangeList = actInfoDict.get(ShareDefine.ActKey_ServerIDRangeList)  | 
|             # È«·þ¹ã²¥ÌáʾÐÅÏ¢  | 
|             if curDateTime in notifyDict:  | 
|                 if serverIDRangeList != None:  | 
|                     notifyKey, paramList = notifyDict[curDateTime]  | 
|                     country = 0  | 
|                     serverGroupIDList = []  | 
|                     crossNotifyList = []  | 
|                     crossNotifyList.append([ShareDefine.CrossNotify_CrossAct, [country, notifyKey, paramList], serverIDRangeList])  | 
|                     PlayerControl.CrossNotifyEx(serverGroupIDList, crossNotifyList)  | 
|                   | 
|             dbInfo = actInfoDict.get(ShareDefine.ActKey_DBInfo, {})  | 
|             dbState = dbInfo.get(ShareDefine.ActKey_State, 0)  | 
|             dbCfgID = dbInfo.get(ShareDefine.ActKey_CfgID, 0)  | 
|             dbActID = dbInfo.get(ShareDefine.ActKey_ID, 0)  | 
|             dbTemplateID = dbInfo.get(ShareDefine.ActKey_TemplateID, 0)  | 
|             dbServerIDRangeList = dbInfo.get(ShareDefine.ActKey_ServerIDRangeList, None)  | 
|               | 
|             forceReset = False  | 
|             if dbCfgID == cfgID and dbServerIDRangeList != serverIDRangeList:  | 
|                 forceReset = True  | 
|                   | 
|             actID = actInfoDict.get(ShareDefine.ActKey_ID, 0)  | 
|             templateID = actInfoDict.get(ShareDefine.ActKey_TemplateID, 0)  | 
|             if not isReload and dbState == state and dbActID == actID and not forceReset:  | 
|                 #ÒѾÊÇÕâ¸ö״̬ÁË  | 
|                 continue  | 
|             GameWorld.Log("¿ç·þÔËÓª»î¶¯×´Ì¬: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,dbState=%s -> state=%s,isEnd=%s, dbActID=%s -> actID=%s,forceReset=%s"   | 
|                           % (actName, cfgID, groupName, zoneID, dbState, state, isEnd, dbActID, actID, forceReset))  | 
|               | 
|             # ¸üÐÂ״̬  | 
|             actInfoDict[ShareDefine.ActKey_State] = state  | 
|             dbInfo = {ShareDefine.ActKey_ID:actID, ShareDefine.ActKey_State:state, ShareDefine.ActKey_TemplateID:templateID,   | 
|                       ShareDefine.ActKey_CfgID:cfgID, ShareDefine.ActKey_ServerIDRangeList:serverIDRangeList}  | 
|             actInfoDict[ShareDefine.ActKey_DBInfo] = dbInfo  | 
|             #GameWorld.Log("    »î¶¯×´Ì¬Í¬²½ÐÅÏ¢: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,actInfoDict=%s" % (actName, cfgID, groupName, zoneID, actInfoDict))  | 
|             if actName not in sysnCrossActInfoDict:  | 
|                 sysnCrossActInfoDict[actName] = {}  | 
|             sysnCrossActInfoDict[actName][cfgID] = actInfoDict  | 
|               | 
|             if dbActID != actID or forceReset:  | 
|                 GameWorld.Log("    »î¶¯ID±ä¸ü: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,dbActID=%s -> actID=%s,forceReset=%s,dbTemplateID=%s"   | 
|                               % (actName, cfgID, groupName, zoneID, dbActID, actID, forceReset, dbTemplateID))  | 
|                   | 
|                 if actName == ShareDefine.CrossActName_CTGBillboard:  | 
|                     CrossActCTGBillboard.OnActIDChange(cfgID, dbTemplateID, state)  | 
|                       | 
|                 else:  | 
|                     actChangeList.append([actName, ipyData, state, cfgID, groupName, zoneID, dbActID, actID, forceReset, dbTemplateID])  | 
|                       | 
|                 # »î¶¯ID±ä¸üÇ¿ÖÆÊÓΪ״̬±ä¸ü£¬·Àֹά»¤Ç°ºó״̬һÑù£¬µ«Æäʵ»î¶¯IDÒѾ²»Í¬µÄÇé¿ö»áµ¼ÖÂÎÞ·¨´¥·¢×´Ì¬±ä¸ü  | 
|                 actIDChange = True  | 
|                 actStateChangeList.append([actName, ipyData, dbState, state, cfgID, groupName, zoneID, actIDChange, dbTemplateID])  | 
|                   | 
|             elif dbState != state:  | 
|                 actIDChange = False  | 
|                 GameWorld.Log("    »î¶¯×´Ì¬±ä¸ü: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,dbState=%s -> state=%s,actIDChange=%s,dbTemplateID=%s"   | 
|                               % (actName, cfgID, groupName, zoneID, dbState, state, actIDChange, dbTemplateID))  | 
|                 actStateChangeList.append([actName, ipyData, dbState, state, cfgID, groupName, zoneID, actIDChange, dbTemplateID])  | 
|                   | 
|             # ·Ç»î¶¯ÖеĴ¦ÀíÍê¹Ø±Õºó£¬×îºóɾ³ý  | 
|             if not state and isEnd:  | 
|                 del crossActInfoDict[actName][cfgID]  | 
|                 if not crossActInfoDict[actName]:  | 
|                     del crossActInfoDict[actName]  | 
|                 GameWorld.Log("    ÒƳý½áÊøµÄ»î¶¯: actName=%s,cfgID=%s,crossActInfoDict=%s" % (actName, cfgID, crossActInfoDict))  | 
|                   | 
|     # Í¬²½×Ó·þÎñÆ÷  | 
|     if sysnCrossActInfoDict:  | 
|         serverGroupIDList = []  | 
|         CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossActInfo, sysnCrossActInfoDict, serverGroupIDList)  | 
|       | 
|     # ÐèÒªµÈ»î¶¯µÈͬ²½µ½×Ó·þºó²Å´¦ÀíÒÔÏÂÂß¼£¬²»È»¿ÉÄܵ¼ÖÂ×Ó·þûÓлʱ¼äÃ÷ϸÒýÆð»î¶¯Òì³£  | 
|     for changeInfo in actChangeList:  | 
|         actName, ipyData, state, cfgID, groupName, zoneID, dbActID, actID, forceReset, dbTemplateID = changeInfo  | 
|         GameWorld.Log("    »î¶¯ID±ä¸ü: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,dbActID=%s -> actID=%s,forceReset=%s,dbTemplateID=%s"   | 
|                       % (actName, cfgID, groupName, zoneID, dbActID, actID, forceReset, dbTemplateID))  | 
|           | 
|         if actName == ShareDefine.CrossActName_AllRecharge:  | 
|             import CrossActAllRecharge  | 
|             CrossActAllRecharge.OnActIDChange(ipyData, state)  | 
|               | 
|     for changeInfo in actStateChangeList:  | 
|         actName, ipyData, dbState, state, cfgID, groupName, zoneID, actIDChange, dbTemplateID = changeInfo  | 
|         GameWorld.Log("    »î¶¯×´Ì¬±ä¸ü: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,dbState=%s -> state=%s,actIDChange=%s,dbTemplateID=%s"   | 
|                       % (actName, cfgID, groupName, zoneID, dbState, state, actIDChange, dbTemplateID))  | 
|           | 
|         if actName == ShareDefine.CrossActName_LuckyCloudBuy:  | 
|             import CrossLuckyCloudBuy  | 
|             CrossLuckyCloudBuy.OnLuckyCloudBuyStateChange(ipyData, actIDChange, state)  | 
|               | 
|     return  | 
|   | 
| def Sync_CrossActInfoToClientServer(serverGroupID=0):  | 
|     ''' Í¬²½¿ç·þÔËÓª»î¶¯ÐÅÏ¢µ½×Ó·þÎñÆ÷  | 
|     @param serverGroupID: Îª0ʱͬ²½ËùÓÐ×Ó·þ  | 
|     '''  | 
|       | 
|     isReload, _ = __GetCrossActInfo()  | 
|     if isReload:  | 
|         # Èç¹ûÊÇÖØ¶ÁµÄ£¬ÔòÔÚÄÚ²ãÒѾͬ²½ÁË£¬´Ë´¦²»Öظ´Í¬²½  | 
|         return  | 
|       | 
|     # Í¬²½×Ó·þÎñÆ÷  | 
|     sysnCrossActInfoDict = GetCrossActInfoDict()  | 
|     serverGroupIDList = [serverGroupID] if serverGroupID else []  | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossActInfo, sysnCrossActInfoDict, serverGroupIDList)  | 
|     return  | 
|   | 
| ## ================================================================================================  | 
|   | 
| def CrossServerMsg_CrossActInfo(sysnCrossActInfoDict):  | 
|     ## ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄ¿ç·þÔËÓª»î¶¯×´Ì¬  | 
|       | 
|     GameWorld.Log("===== ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄ¿ç·þÔËÓª»î¶¯×´Ì¬: %s" % sysnCrossActInfoDict)  | 
|     if PyGameData.g_crossActInfoDict == None or not sysnCrossActInfoDict:  | 
|         PyGameData.g_crossActInfoDict = {}  | 
|           | 
|     for actName, syncActInfoDict in sysnCrossActInfoDict.items():  | 
|         for cfgID, syncActInfo in syncActInfoDict.items():  | 
|             if actName not in PyGameData.g_crossActInfoDict:  | 
|                 PyGameData.g_crossActInfoDict[actName] = {}  | 
|             actInfoDict = PyGameData.g_crossActInfoDict[actName]  | 
|             actInfoDict[cfgID] = syncActInfo  | 
|               | 
|         if actName == ShareDefine.CrossActName_LuckyCloudBuy:  | 
|             import CrossLuckyCloudBuy  | 
|             CrossLuckyCloudBuy.Sync_LuckyCloudBuyRoundInfo(None)  | 
|               | 
|         GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossActInfo % actName, syncActInfoDict)  | 
|           | 
|     # É¾³ý·Ç»î¶¯ÖÐµÄ  | 
|     for actName, actInfoDict in PyGameData.g_crossActInfoDict.items():  | 
|         for cfgID, actInfo in actInfoDict.items():  | 
|             if not actInfo.get(ShareDefine.ActKey_State, 0):  | 
|                 del PyGameData.g_crossActInfoDict[actName][cfgID]  | 
|                   | 
|     return  | 
|   | 
| def GetPlayerCrossActInfo(curPlayer, actName):  | 
|     ## »ñÈ¡¿ç·þÍæ¼Ò¶ÔÓ¦µÄ¿ç·þ»î¶¯ÐÅÏ¢  | 
|     if PyGameData.g_crossActInfoDict == None:  | 
|         return {}  | 
|     actInfoDict = PyGameData.g_crossActInfoDict.get(actName, {})  | 
|     if not actInfoDict:  | 
|         return {}  | 
|     playerServerID = GameWorld.GetPlayerServerID(curPlayer)  | 
|     for actInfo in actInfoDict.values():  | 
|         if not actInfo.get(ShareDefine.ActKey_State, 0):  | 
|             continue  | 
|         if ShareDefine.ActKey_ServerIDRangeList not in actInfo:  | 
|             continue  | 
|         serverIDRangeList = actInfo[ShareDefine.ActKey_ServerIDRangeList]  | 
|         if not serverIDRangeList:  | 
|             # È«·þ¿ªÆô  | 
|             return actInfo  | 
|         for serverIDA, serverIDB in serverIDRangeList:  | 
|             if serverIDA <= playerServerID <= serverIDB:  | 
|                 return actInfo  | 
|     return {}  | 
|   | 
| def SendMapServerCrossActionState():  | 
|     # µØÍ¼Æô¶¯³É¹¦Ê±Í¨Öª¿ç·þ»î¶¯Ïà¹Ø×´Ì¬  - ±¾·þµØÍ¼£¬¿ç·þµØÍ¼²»ÐèҪ֪ͨ  | 
|       | 
|     if PyGameData.g_crossActInfoDict == None:  | 
|         return  | 
|       | 
|     sysnCrossActInfoDict = PyGameData.g_crossActInfoDict  | 
|     for actName in ShareDefine.CrossActNameList:  | 
|         actInfoDict = sysnCrossActInfoDict.get(actName, {})  | 
|         GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossActInfo % actName, actInfoDict)  | 
|           | 
|     return  | 
|   | 
| ## ================================================================================================  | 
|   | 
| def __GetTodayCrossDailyActionInfo():  | 
|     # »ñÈ¡±¾ÈÕ´ý´¦ÀíµÄÈÕ³£»î¶¯ÐÅÏ¢  | 
|     key = "TodayCrossDailyActionInfo"  | 
|     curTime = int(time.time())  | 
|     curDateStr = GameWorld.ChangeTimeNumToStr(curTime, ChConfig.TYPE_Time_YmdFormat) # µ±ÌìÈÕÆÚ  | 
|     loadSign = curDateStr  | 
|     TodayDailyActionInfo = IpyGameDataPY.GetConfigEx(key)  | 
|     if TodayDailyActionInfo and TodayDailyActionInfo[0] == loadSign:  | 
|         GameWorld.DebugLog("ÒѾ¼ÓÔØ¹ý±¾ÈÕ¿ç·þÈÕ³£»î¶¯´¦ÀíÐÅÏ¢£¡loadSign=%s" % loadSign)  | 
|         return TodayDailyActionInfo[1]  | 
|       | 
|     todayActionInfo = []  | 
|       | 
|     dayTime = GameWorld.GetServerTime()  | 
|     weekDay = str(dayTime.weekday() + 1) # ¸ñʽΪjson, µ±Ç°ÐÇÆÚ¼¸, 1´ú±íÐÇÆÚ1  | 
|       | 
|     GameWorld.Log("===== ¼ÓÔØ½ñÌì¿ç·þÈÕ³£»î¶¯ÐÅÏ¢ =====")  | 
|     GameWorld.Log("µ±Ç°ÐÇÆÚ%s" % weekDay)  | 
|       | 
|     dailyTimeInfoList = []  | 
|       | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|     for i in xrange(ipyDataMgr.GetCrossDailyActionCount()):  | 
|         dailyIpyData = ipyDataMgr.GetCrossDailyActionByIndex(i)  | 
|         dailyID = dailyIpyData.GetDailyID()  | 
|           | 
|         openTimeDict = dailyIpyData.GetOpenTimeDict()  | 
|         # Ã»ÓÐʱ¼ä¿ØÖƵ쬴ú±íÓÀ¾Ã¿ª·Å  | 
|         if not openTimeDict:  | 
|             todayActionInfo.append([dailyID])  | 
|             GameWorld.Log("    Ôö¼Ó±¾ÈÕ³£¿ª¿ç·þÈÕ³£»î¶¯ÐÅÏ¢: dailyID=%s" % dailyID)  | 
|             continue  | 
|           | 
|         #Èç¹ûÐÇÆÚkeyÖдæÔÚ "0" ´ú±íÿÈÕ¶¼¿ªÆô  | 
|         if "0" not in openTimeDict and weekDay not in openTimeDict:  | 
|             GameWorld.Log("    ²»ÊÇ¿ç·þÈÕ³£»î¶¯¿ªÆôÐÇÆÚ: dailyID=%s,openWeekLimit=%s" % (dailyID, openTimeDict.keys()))  | 
|             continue  | 
|         openTimeList = openTimeDict["0"] if "0" in openTimeDict else openTimeDict[weekDay]  | 
|         dailyTimeInfoList.append([openTimeList, dailyIpyData])  | 
|           | 
|     GameWorld.Log("    -----------------------")  | 
|     for openTimeList, ipyData in dailyTimeInfoList:  | 
|         dailyID = ipyData.GetDailyID()  | 
|         notifyInfoDict = ipyData.GetNotifyInfo()  | 
|           | 
|         openList = [] # [(ʱ,·Ö), ...]  | 
|         overList = [] # [(ʱ,·Ö), ...]  | 
|         goonStateDict = {} # {״̬:[(aDateTime, bDateTime)], ...}  | 
|         notifyDict = {} # {(ʱ,·Ö):[notifyKey, [²ÎÊý]], ...}  | 
|         OpenState = 1 # ¶¨Ò忪Æô״̬Ϊ1  | 
|           | 
|         for hour, minute in openTimeList:    | 
|             openTimeStr = "%s %02d:%02d:%02d" % (curDateStr, hour, minute, 0)  | 
|               | 
|             # ¾«È·¿ªÆôʱ¼ä  | 
|             openDateTime = datetime.datetime.strptime(openTimeStr, ChConfig.TYPE_Time_Format)  | 
|             openList.append((openDateTime.hour, openDateTime.minute))  | 
|               | 
|             # ¾«È·¹Ø±Õʱ¼ä  | 
|             overDateTime = openDateTime + datetime.timedelta(minutes=ipyData.GetDuration())  | 
|             overList.append((overDateTime.hour, overDateTime.minute))  | 
|               | 
|             # goon ¿ªÆô״̬  | 
|             openStateTimeList = goonStateDict.get(OpenState, [])  | 
|             openStateTimeList.append((openDateTime, overDateTime))  | 
|             goonStateDict[OpenState] = openStateTimeList  | 
|               | 
|             # goon ÆäËû״̬£¬´ýÀ©Õ¹  | 
|             # ...  | 
|               | 
|             # ¹ã²¥  | 
|             for notifyMinute, notifyInfo in notifyInfoDict.items():  | 
|                 notifyDateTime = openDateTime + datetime.timedelta(minutes=notifyMinute)  | 
|                 notifyDict[(notifyDateTime.hour, notifyDateTime.minute)] = notifyInfo  | 
|                   | 
|         todayActionInfo.append([dailyID, openList, overList, goonStateDict, notifyDict])  | 
|         GameWorld.Log("    Ôö¼Ó±¾ÈÕ¿ç·þÈÕ³£»î¶¯ÐÅÏ¢: dailyID=%s,openList=%s,overList=%s,goonStateDict=%s,notifyDict=%s"   | 
|                       % (dailyID, openList, overList, goonStateDict, notifyDict))  | 
|           | 
|     TodayDailyActionInfo = IpyGameDataPY.SetConfigEx(key, [loadSign, todayActionInfo])  | 
|     GameWorld.Log("±¾ÈÕ¿ç·þÈÕ³£»î¶¯ÐÅÏ¢¼ÓÔØÍê±Ï! loadSign=%s" % loadSign)  | 
|     GameWorld.Log("=============================================================")  | 
|     return TodayDailyActionInfo[1]  | 
|   | 
| def Dispose_CrossDailyActionState():  | 
|     # ¿ç·þÈÕ³£»î¶¯×´Ì¬±ä¸ü¼ì²é´¦Àí  | 
|       | 
|     todayDailyActionInfo = __GetTodayCrossDailyActionInfo()  | 
|     if not todayDailyActionInfo:  | 
|         return  | 
|       | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     dayTime = GameWorld.GetServerTime()  | 
|     curHourMinute = (dayTime.hour, dayTime.minute)  | 
|       | 
|     sysnCrossDailyActionStateDict = {}  | 
|       | 
|     for actionInfo in todayDailyActionInfo:  | 
|         dailyActionID = actionInfo[0]  | 
|         state = 0 # Ä¬ÈÏ¹Ø±Õ  | 
|           | 
|         # ³¤¶ÈΪ1µÄ´ú±í³£¿ªµÄ»î¶¯  | 
|         if len(actionInfo) == 1:  | 
|             state = 1  | 
|         else:  | 
|             #openList = [] # [(ʱ,·Ö), ...]  | 
|             #overList = [] # [(ʱ,·Ö), ...]  | 
|             #goonStateDict = {} # {״̬:[(aDateTime, bDateTime)], ...}  | 
|             #notifyDict = {} # {(ʱ,·Ö):[notifyKey, [²ÎÊý]], ...}  | 
|             openList, overList, goonStateDict, notifyDict = actionInfo[1:]  | 
|               | 
|             # ¾«È·Æ¥Å俪Æô  | 
|             if curHourMinute in openList:  | 
|                 state = 1  | 
|             # ¾«È·Æ¥Å乨±Õ  | 
|             elif curHourMinute in overList:  | 
|                 state = 0  | 
|             # goon ×´Ì¬  | 
|             else:  | 
|                 for goonState, openStateTimeList in goonStateDict.items():  | 
|                     for dateTimeInfo in openStateTimeList:  | 
|                         if dateTimeInfo[0] < dayTime < dateTimeInfo[1]:  | 
|                             state = goonState  | 
|                             break  | 
|                           | 
|             # È«·þ¹ã²¥ÌáʾÐÅÏ¢  | 
|             if curHourMinute in notifyDict:  | 
|                 notifyKey, paramList = notifyDict[curHourMinute]  | 
|                 serverGroupIDList = []  | 
|                 PlayerControl.WorldNotifyCross(serverGroupIDList, 0, notifyKey, paramList)  | 
|                   | 
|         dictName = ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % dailyActionID  | 
|         beforeState = gameWorld.GetDictByKey(dictName)  | 
|         if beforeState == state:  | 
|             #ÒѾÊÇÕâ¸ö״̬ÁË  | 
|             continue  | 
|           | 
|         if state:  | 
|             if dailyActionID == ShareDefine.CrossDailyActionID_YaomoBoss:  | 
|                 GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_ActionBossRebornSign % dailyActionID, int(time.time()))  | 
|                   | 
|         sysnCrossDailyActionStateDict[dailyActionID] = state  | 
|         #֪ͨMapserver,ÉèÖÃ×Öµä  | 
|         GameWorld.SendMapServerMsgEx(dictName, state)  | 
|         #¸üÐÂ×ÖµäÖµ  | 
|         gameWorld.SetDict(dictName, state)  | 
|         GameWorld.Log("¿ç·þÈÕ³£»î¶¯×´Ì¬±ä¸ü: dailyActionID=%s,state=%s,dictName=%s" % (dailyActionID, state, dictName))  | 
|           | 
|     # Í¬²½×Ó·þÎñÆ÷  | 
|     if sysnCrossDailyActionStateDict:  | 
|         serverGroupIDList = []  | 
|         CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossDailyActionState, sysnCrossDailyActionStateDict, serverGroupIDList)  | 
|           | 
|     return  | 
|   | 
| def SendMapServerCrossDailyActionState():  | 
|     # µØÍ¼Æô¶¯³É¹¦Ê±Í¨Öª±¾ÈÕ½øÐÐÖеÄÈÕ³£»î¶¯×´Ì¬  | 
|       | 
|     todayDailyActionInfo = __GetTodayCrossDailyActionInfo()  | 
|     if not todayDailyActionInfo:  | 
|         return  | 
|       | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     for actionInfo in todayDailyActionInfo:  | 
|         dailyActionID = actionInfo[0]  | 
|         dictName = ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % dailyActionID   | 
|         state = gameWorld.GetDictByKey(dictName)  | 
|         if state:  | 
|             GameWorld.SendMapServerMsgEx(dictName, state)  | 
|               | 
|     return  | 
|   | 
| def CrossServerMsg_CrossDailyActionState(msgData):  | 
|       | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     for dailyActionID, state in msgData.items():  | 
|         dictName = ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % dailyActionID  | 
|         #֪ͨMapserver,ÉèÖÃ×Öµä  | 
|         GameWorld.SendMapServerMsgEx(dictName, state)  | 
|         #¸üÐÂ×ÖµäÖµ  | 
|         gameWorld.SetDict(dictName, state)  | 
|         GameWorld.Log("ÊÕµ½¿ç·þÈÕ³£»î¶¯×´Ì¬±ä¸ü: dailyActionID=%s,state=%s,dictName=%s" % (dailyActionID, state, dictName))  | 
|           | 
|     return  | 
|   |