| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #---------------------------------------------------------------------  | 
| #  | 
| #---------------------------------------------------------------------  | 
| ##@package GameWorld  | 
| # @todo: ³£Óú¯Êý¶¨Òå  | 
| #  | 
| # @author: eggxp  | 
| # @date 2010-03-31  | 
| # @version 2.4  | 
| #  | 
| # @change: "2012-12-21 11:00" jiang ÐÂÔöº¯ÊýÍæ¼Òʱ¼ä¼ä¸ôRefurbishPlayerTick  | 
| # @change: "2013-01-18 18:45" hyx Ôö¼Ó»ñÈ¡Íæ¼ÒÇø·þÃûµÄ½Ó¿Ú  | 
| # @change: "2013-03-20 18:00" Alee Ìí¼ÓDEBUGÊä³öº¯ÊýDebugLog  | 
| # @change: "2013-09-10 20:10" Alee º¯ÊýDebugLog¸ÄÓÃGetDebugLevel²ÅÓÐЧ  | 
| # @change: "2014-05-16 10:30" xmnathan Ôö¼Ó½»Ò×Ëù¹ÜÀíÆ÷½Ó¿Ú  | 
| # @change: "2014-09-22 10:00" xmnathan Ôö¼ÓGM¹¤¾ß²¹³¥¹ÜÀíÆ÷½Ó¿Ú  | 
| # @change: "2015-01-14 00:30" hxp Ôö¼Ó·þÎñÆ÷Æ½Ì¨Çø·þID»ñÈ¡  | 
| # @change: "2015-01-14 20:30" hxp Ôö¼ÓCanHappenº¯Êý  | 
| # @change: "2015-06-08 20:30" hxp Ôö¼Ó»ñÈ¡channelCode  | 
| # @change: "2015-10-22 23:00" hxp Ôö¼Ó»ñÈ¡×Ó·þserverID  | 
| # @change: "2016-03-28 17:00" hxp Ôö¼Ó´´½Ç¸ÄÃûGetPlayerFullName  | 
| # @change: "2016-07-18 19:00" hxp Ôö¼Ó»ñȡƽ̨Õ˺Š | 
| #---------------------------------------------------------------------  | 
| #"""Version = 2016-07-18 19:00"""  | 
| #---------------------------------------------------------------------  | 
| import IPY_GameServer  | 
| import LogUI  | 
| import ChConfig  | 
| import IpyGameDataPY  | 
| import PyGameData  | 
| import ReadChConfig  | 
| import PlayerDBGSEvent  | 
| import ConfigParser  | 
| import GameConfig  | 
| import ShareDefine  | 
| import CommFunc  | 
| import datetime  | 
| import os  | 
| import math  | 
| import sys  | 
| import time  | 
| import random  | 
| import copy  | 
| import urllib  | 
| #import psyco  | 
| #---------------------------------------------------------------------  | 
| GameWorldData = IPY_GameServer.IPY_GameWorld()  | 
| #---------------------------------------------------------------------  | 
|   | 
| ServerRootPath = "" # ·þÎñÆ÷¸ù·¾¶  | 
| MergeServerID = 0 # ±¾×Ó·þµÄ¿ç·þID  | 
|   | 
| #---------------------------------------------------------------------  | 
|   | 
| ## º¯Êýµ÷Óà  | 
| #  @param curCallObj ÊµÀý£¨¿ÉÄÜÊÇij¸öÎļþÃû£©   | 
| #  @param callName ÊµÀýµÄij¸öÊôÐÔ  | 
| #  @return ÊôÐÔ  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def ParseNameGetObj(curCallObj, callName):  | 
|     callList = callName.split(".")  | 
|     if len(callList) <= 1:  | 
|         return None  | 
|       | 
|     for curCallName in callList:  | 
|         if hasattr(curCallObj, curCallName) != True:  | 
|             #ÎÞ´ËÊôÐÔ  | 
|             return None  | 
|           | 
|         curCallObj = getattr(curCallObj, curCallName)  | 
|           | 
|     return curCallObj  | 
|   | 
| ## Íⲿµ÷ÓõĻñÈ¡ÊôÐÔ£¬ÇÒÊÇ¿ÉÒÔcallµÄ  | 
| #  @param curCallObj ÊµÀý£¨¿ÉÄÜÊÇij¸öÎļþÃû£©   | 
| #  @param callName ÊµÀýµÄij¸öÊôÐÔ  | 
| #  @return ¿ÉÒÔcallµÄÊôÐÔ  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetExecFunc(curCallObj, callName):  | 
|     curCallObj = ParseNameGetObj(curCallObj, callName)  | 
|       | 
|     if curCallObj == None:  | 
|         return None  | 
|           | 
|     if callable(curCallObj) != True:  | 
|         #²»¿Éµ÷Óà  | 
|         return None  | 
|       | 
|     return curCallObj  | 
|   | 
| ##¸¡µãÊýÏòÉÏÈ¡Õû  | 
| # @param x ÊäÈëµÄÊý  | 
| # @return ·µ»ØÖµ, ÏòÉÏÈ¡ÕûºóµÄÖµ  | 
| # @remarks ¸¡µãÊýÏòÉÏÈ¡Õû  | 
| def GetFloatUpper(x):  | 
|     return int(math.ceil(x))  | 
|   | 
| ## ÏòÉÏÈ¡Õû(²ÎÊý -> Öµ,³ýÊý)  | 
| #  @param x Öµ  | 
| #  @param div ³ýÊý  | 
| #  @return int  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetIntUpper(x, div):  | 
|     return int(math.ceil(x / float(div)))  | 
|   | 
| ## ×Ö·û´®×ª»»ÎªÕûÐÍ, Èç¹û²»ÄÜת»», ·µ»ØÄ¬ÈÏÖµ  | 
| #  @param input ×Ö·û´®  | 
| #  @param defValue Ä¬ÈÏÖµ  | 
| #  @return int or Ä¬ÈÏÖµ   | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def ToIntDef(input, defValue = 0):  | 
|     try:  | 
|         result = int(input)  | 
|         return result  | 
|   | 
|     except ValueError:  | 
|         return defValue  | 
|       | 
| ## ÅжÏ2¸ö¶ÔÏóÊÇ·ñͬ¹ú¼®   | 
| #  @param srcObj Æðµã¶ÔÏó   | 
| #  @param desObj Ä¿±ê¶ÔÏó   | 
| #  @return True or False  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def IsSameCountry(srcObj, desObj):  | 
|     #ͬ¹ú¼®  | 
|     if srcObj.GetCountry() == desObj.GetCountry() :  | 
|         return True  | 
|     #Ò»ÈËÊÇÐÂÊÖ,ͬ¹ú¼®  | 
|     if srcObj.GetCountry() == 1 or desObj.GetCountry() == 1 :  | 
|         return True  | 
|     return False  | 
|   | 
| ## ¼ì²éÊÇ·ñÊÇGM  | 
| #  @param curPlayer   | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def IsGM(curPlayer):  | 
|     #0:²»ÊÇGM 90:ÄÚ²¿²âÊÔ  | 
|     if curPlayer.GetGMLevel() in [0 , 90]:  | 
|         return  | 
|       | 
|     return True   | 
|   | 
| ## »ñµÃµ±Ç°ÏµÍ³Ê±¼ä  | 
| #  @param   | 
| #  @return µ±Ç°Ê±¼ä  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetCurrentDataTimeStr():  | 
|     curTimeStr = str(GetServerTime())  | 
|     curTimeStr = curTimeStr.split(".")[0]  | 
|     return curTimeStr  | 
|   | 
| ## »ñµÃϵͳʱ¼ä(²ÎÊý -> Ê±¼äÁбí)  | 
| #  @param timeStr Ê±¼äÁÐ±í  | 
| #  @return Ê±¼ädatetime¸ñʽ  | 
| #  @remarks »ñµÃϵͳʱ¼ä(²ÎÊý -> Ê±¼äÁбí)  | 
| def GetDateTimeByStr(timeStr):  | 
|     timeStr = timeStr.strip().split(".")[0]  | 
|     try:  | 
|         return  datetime.datetime.strptime(timeStr, ChConfig.TYPE_Time_Format)  | 
|     except BaseException , e :  | 
|         Log("%s : %s"%(e, timeStr))  | 
|         return  | 
|   | 
|     return  | 
|   | 
| ## »ñµÃÖ¸¶¨µÄʱ¼ä¸ñʽ  | 
| #  @param timeStr Ê±¼äÁÐ±í  | 
| #  @param timeFormat Ö¸¶¨µÄת»»¸ñʽ  | 
| #  @return Ê±¼ädatetime¸ñʽ  | 
| #  @remarks »ñµÃÖ¸¶¨µÄʱ¼ä¸ñʽ  | 
| def GetDateTimeByFormatStr(timeStr, timeFormat):  | 
|     timeStr = timeStr.strip().split(".")[0]  | 
|     try:  | 
|         return  datetime.datetime.strptime(timeStr, timeFormat)  | 
|     except BaseException , e :  | 
|         Log("%s : %s"%(e, timeStr))  | 
|         return  | 
|   | 
|     return  | 
| #######################################################################  | 
| ## »ñÈ¡GameWorldEventManager  | 
| #  @param   | 
| #  @return GameWorldEventManager  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetGameWorldEventManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetGameWorldEventManager()  | 
|   | 
| ## »ñÈ¡GameWorld  | 
| #  @param   | 
| #  @return GameWorld  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetGameWorld():  | 
|     global GameWorldData  | 
|     return GameWorldData  | 
|   | 
| ## »ñÈ¡PlayerManager  | 
| #  @param   | 
| #  @return PlayerManager  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetPlayerManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetPlayerManager()  | 
|   | 
| ## »ñÈ¡TeamManager  | 
| #  @param   | 
| #  @return TeamManager  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetTeamManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetTeamManager()  | 
|   | 
| ## »ñÈ¡TruckMananger  | 
| #  @param   | 
| #  @return TruckMananger  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetTruckMananger():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetTruckManager()  | 
|   | 
| ## »ñÈ¡FamilyManager  | 
| #  @param   | 
| #  @return FamilyManager  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetFamilyManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetFamilyManager()  | 
|   | 
| ## »ñÈ¡Billboard  | 
| #  @param   | 
| #  @return Billboard  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetBillboard():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetBillboardManager()  | 
|   | 
|   | 
| ## »ñÈ¡MailManager  | 
| #  @param   | 
| #  @return MailManager  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetMailManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetAllMailList()  | 
|   | 
| ## »ñÈ¡¼Ò×å¿Æ¼¼¹ÜÀíÆ÷  | 
| #  @param   | 
| #  @return FamilyTechManager  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetFamilyTechManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetFamilyTechMgr()  | 
|   | 
| ## »ñÈ¡¾º¼¼³¡¹ÜÀíÆ÷  | 
| #  @param   | 
| #  @return FamilyTechManager  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetVSRoomManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetVSRoomMgr()  | 
|   | 
| ## »ñÈ¡½±³Í±í¹ÜÀíÆ÷  | 
| #  @param   | 
| #  @return VsRewardMgr  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetVsRewardManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetVsRewardMgr()  | 
|   | 
|   | 
| ## »ñÈ¡°ï»áÐÐΪ¹ÜÀíÆ÷  | 
| #  @param   | 
| #  @return VsRewardMgr  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetFamilyActionManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetFamilyActionMgr()  | 
|   | 
| ## »ñÈ¡¸±±¾Í¨¹Ø¼Ç¼¹ÜÀíÆ÷  | 
| #  @param   | 
| #  @return VsRewardMgr  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetFBPassRecManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetFBPassRecMgr()  | 
|   | 
| ## »ñÈ¡Íæ¼ÒÐÅϢͨÓüǼ¹ÜÀíÆ÷  | 
| #  @param   | 
| #  @return VsRewardMgr  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetUniversalRecMgr():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetUniversalRecMgr()  | 
|   | 
| ## ½»Ò×Ëù¹ÜÀíÆ÷  | 
| #  @param   | 
| #  @return BourseManager  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetBourseManager():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetBourseManager()  | 
|   | 
| ## GM¹¤¾ß²¹³¥¹ÜÀíÆ÷  | 
| #  @param   | 
| #  @return HightLadderMgr  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetCompensationMgr():  | 
|     global GameWorldData  | 
|     return GameWorldData.GetCompensationMgr()  | 
|   | 
| #######################################################################  | 
| ## ÖØÐ¼ÓÔØ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks   | 
| def DoReload(tick):  | 
|     if __GetPsycoIsOpen():  | 
|         #Psyco¿ªÆô  | 
|         PsycoReload(tick)  | 
|         return  | 
|   | 
|     #Psyco¹Ø±Õ  | 
|     __DoReload(tick)  | 
|     return  | 
|   | 
| ## ÖØÐ¼ÓÔØ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks   | 
| def __DoReload(tick):  | 
|     for name, reloadPath in sys.modules.items():  | 
|         try:  | 
|             if GetGameWorld().GetDictByKey("Reload") == 1 and name in ["PyGameData"]:  | 
|                 DebugLog("²»ÖضÁ %s"%name)  | 
|                 continue  | 
|             reload(reloadPath)  | 
|         except Exception:  | 
|             continue  | 
|     GetGameWorld().SetDict("Reload", 1)  | 
|     Log("Reload Begin : time = %s"%GetCurrentDataTimeStr())  | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ## Õý³£ÈÕ¼Ç  | 
| #  @param msg ÐÅÏ¢  | 
| #  @param playerID Íæ¼ÒID  | 
| #  @param par   | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def Log(msg , playerID = 0, par = 0):  | 
|     LogUI.Msg('%s\t%s\t%s'%(par, playerID, msg))  | 
|     return  | 
|   | 
| ## Òì³£ÈÕ¼Ç  | 
| #  @param msg ÐÅÏ¢  | 
| #  @param playerID Íæ¼ÒID  | 
| #  @param par   | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def ErrLog(msg, playerID = 0, par = 0):  | 
|     LogUI.Msg('%s\t%s\t###Error:%s'%(par, playerID, msg))  | 
|     return  | 
|   | 
| ##DEBUGµ÷ÊÔÊä³öÐÅÏ¢  | 
| # @param msg ÏûÏ¢  | 
| # @param playerID Íæ¼ÒID  | 
| # @param par ÏûÏ¢²ÎÊý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def DebugLog(msg, playerID = 0, par = 0):  | 
|     if not GetGameWorld().GetDebugLevel():  | 
|         return  | 
|       | 
|     LogUI.Msg('%s\t%s\tPyDebug:%s'%(par, playerID, msg))  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃµ±Ç°·þÎñÆ÷¿ç·þID  | 
| # @param ÎÞ  | 
| # @return  | 
| def GetMergeServerID():  | 
|     global MergeServerID  | 
|       | 
|     if not MergeServerID:  | 
|         rootPath = ChConfig.GetServerRootPath()  | 
|         mergeServerIniFile = rootPath + "\\ZoneServerGroup\\rungate\\InterfaceServer\\MultiServerWarProxyServer\\Config\\config.ini"  | 
|         if not os.path.isfile(mergeServerIniFile):  | 
|             ErrLog('ÎÞ·¨ÕÒµ½Îļþ = %s'%(mergeServerIniFile))  | 
|             raise Exception('ÎÞ·¨ÕÒµ½Îļþ = %s'%(mergeServerIniFile))  | 
|           | 
|         mergeServerIni = ConfigParser.ConfigParser()  | 
|         mergeServerIni.read(mergeServerIniFile)  | 
|           | 
|         section, option = "Config", "ServerID"  | 
|         if not mergeServerIni.has_option(section, option):  | 
|             ErrLog("%s ÕÒ²»µ½ÅäÖÃ: section=%s,option=%s" % (mergeServerIniFile, section, option))  | 
|             return 0  | 
|           | 
|         MergeServerID = ToIntDef(mergeServerIni.get(section, option))  | 
|         Log("¶ÁÈ¡ MergeServerID=%s" % MergeServerID)  | 
|           | 
|     return MergeServerID  | 
|   | 
| ## »ñµÃµ±Ç°·þÎñÆ÷µÄ°æ±¾ºÅ  | 
| #  @param   | 
| #  @return ServerVersion  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetServerVersion():  | 
|     return GetGameWorld().GetServerVersion()  | 
|   | 
| def GetServerGroupID():  | 
|     ## ·þÎñÆ÷×éID£¬±ØÐëΨһ£¬´ú±íÕą̂ÎïÀí·þÎñÆ÷  | 
|     return ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "GroupID"), 0)  | 
|   | 
| def GetPlatformServerNum(platform):  | 
|     # »ñÈ¡·þÎñÆ÷µÄƽ̨±àºÅ  | 
|     platformNumDict = ReadChConfig.GetDBEvalChConfig("DBPlatformNum")  | 
|     #===========================================================================  | 
|     # if platform not in platformNumDict:  | 
|     #    ErrLog("DBPlatformNumûÓÐÅäÖø÷þÎñÆ÷ƽ̨Ëù¶ÔÓ¦µÄ±àºÅ£¡platfrom=%s" % platform)  | 
|     #    raise Exception("DBPlatformNumûÓÐÅäÖø÷þÎñÆ÷ƽ̨Ëù¶ÔÓ¦µÄ±àºÅ£¡platfrom=%s" % platform)  | 
|     #===========================================================================  | 
|     return platformNumDict.get(platform, 0)  | 
|   | 
| ##»ñµÃµ±Ç°·þÎñÆ÷ƽ̨  | 
| # @param ÎÞ  | 
| # @return  | 
| def GetPlatform():  | 
|     return ReadChConfig.GetPyMongoConfig("platform", "PlatformName")  | 
|   | 
| #===============================================================================  | 
| # ##»ñµÃµ±Ç°·þÎñÆ÷ID  | 
| # # @param ÎÞ  | 
| # # @return  | 
| # def GetServerID():  | 
| #    return ToIntDef(GetServerSID()[1:], 0)  | 
| #===============================================================================  | 
|   | 
| #===============================================================================  | 
| # def GetServerSID():  | 
| #    ##»ñµÃµ±Ç°·þÎñÆ÷ID, ´øsµÄ  | 
| #    return ReadChConfig.GetPyMongoConfig("platform", "ServerID")  | 
| #===============================================================================  | 
|   | 
| Def_AccID_Split_Sign = "@"  | 
|   | 
| ##Íæ¼ÒÓÎÏ·Õ˺Ÿñʽ: Æ½Ì¨Õ˺Å@ƽ̨Ãû@sÇø·þID, Æ½Ì¨Õ˺ſÉÄÜ´ø@£¬ÈçÓÊÏäyhlz123@qq.com@173on_lan@s519  | 
| ##»ñÈ¡Íæ¼ÒËùÊôÇø·þID  | 
| # @param curPlayer  | 
| # @return  | 
| def GetPlayerServerID(curPlayer):  | 
|     accID = curPlayer.GetAccID()  | 
|     infoList = accID.split(Def_AccID_Split_Sign)  | 
|     return 0 if len(infoList) < 3 else int(infoList[-1][1:])  | 
|   | 
| def GetPlayerServerSID(curPlayer):  | 
|     # ·µ»Øº¬sµÄserverID  | 
|     accID = curPlayer.GetAccID()  | 
|     infoList = accID.split(Def_AccID_Split_Sign)  | 
|     return "" if len(infoList) < 3 else infoList[-1]  | 
|   | 
| def GetPlayerMainServerID(accIDPlatform):  | 
|     # Íæ¼ÒºÏ·þºóËùÊôÖ÷·þID  | 
|     # @param accIDPlatform: Íæ¼ÒÕ˺ÅËùÊôµÄƽ̨  | 
|     mainServerID = ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "%sMainServerID" % accIDPlatform), None)  | 
|     if mainServerID != None:  | 
|         return mainServerID  | 
|     return 0  | 
|   | 
|   | 
| #===============================================================================  | 
| # Æ½Ì¨ID = appid  | 
| # ÔËÓªID = spid  | 
| # ·þÎñÆ÷Õ˺Ÿü¸Ä  | 
| # ÔÏÈÕ˺Å×éºÏΪ  | 
| # ÔËÓªÌṩµÄÍæ¼ÒÕ˺ÅID + Æ½Ì¨ID + Çø·þ×é³É  | 
| #   | 
| # ÒòΪIOSºÍ°²×¿ÔÚÖ§³Ö»ì·þµÄÇé¿öÏ£¬»¹ÒªÄÜÖ§³Öͬһ¸ö½ÇÉ«ºÅ£¬¹ÊÒýÈëÒ»¸öеÄÔËÓªID£¨¿Í»§¶Ë´ò°üÅäÖã©£¬ÒÔ±£Ö¤Íæ¼ÒÕ˺ÅΪͬһ¸ö  | 
| # Õ˺Å×éºÏ±ä¸ü  | 
| # ÔËÓªÌṩµÄÍæ¼ÒÕ˺ÅID + ÔËÓªID + Çø·þ×é³É  | 
| #   | 
| # ÔÓÎÏ·Öлñȡƽ̨ID½Ó¿Ú±ä¸ü  | 
| # 1. db ´ÓÊý¾Ý¿âÖеÄÕ˺űí»ñÈ¡AppID  | 
| # 2. GameServerºÍMapServer ½Ó¿Ú¸ÄΪGetOperator ²Î¿¼ GetPlayerPlatform  | 
| #===============================================================================  | 
|   | 
| ##»ñÈ¡Íæ¼ÒËùÊôƽ̨  | 
| def GetPlayerPlatform(curPlayer):  | 
|     return curPlayer.GetAccountInfo().GetOperator()  | 
|   | 
| ##»ñȡƽ̨Õ˺Š | 
| def GetPlatformAccID(gameAccID):  | 
|     infoList = gameAccID.split(Def_AccID_Split_Sign)  | 
|     paInfoList = infoList[:-2]  | 
|     platformAccID = Def_AccID_Split_Sign.join(paInfoList)  | 
|     return platformAccID  | 
|   | 
| ##»ñÈ¡Íæ¼ÒÕ˺ÅËùÊôƵµÀ  | 
| # @param curPlayer  | 
| # @return  | 
| def GetPlayerChannelCode(curPlayer):  | 
|     userDataDict = GetUserData(curPlayer)  | 
|     return userDataDict.get("channel_code", "")  | 
|   | 
| ## »ñÈ¡Óû§ÐÅÏ¢×Öµä  | 
| #  @param curPlayer  | 
| #  @param key  | 
| #  @param default  | 
| #  @return  | 
| def GetUserData(curPlayer):  | 
|     playerUserDataStr = curPlayer.GetUserData()  | 
|       | 
|     if not playerUserDataStr:  | 
|         return {}  | 
|       | 
|     try:  | 
|         curPlayerUserData = eval(playerUserDataStr)  | 
|     except:  | 
|         ErrLog("data error UserData = %s"%playerUserDataStr )  | 
|         return {}  | 
|       | 
|     if not isinstance(curPlayerUserData, dict):  | 
|         ErrLog("type error UserData = %s"%playerUserDataStr )  | 
|         return {}  | 
|       | 
|     return curPlayerUserData  | 
|   | 
| ## »ñµÃ²éѯµÄÍæ¼ÒËùÔڵĵØÍ¼ID  | 
| #  @param tagPlayer Ä¿±êÍæ¼Ò  | 
| #  @return RealMapID  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetQueryPlayerMapID(tagPlayer):  | 
|     if not tagPlayer or not tagPlayer.GetInitOK():  | 
|         return 0  | 
|           | 
|     return tagPlayer.GetRealMapID()  | 
|   | 
| #---------------------------------------------------------------------  | 
|   | 
| def GetTemplateID(ipyData, cfgID, dayIndex):  | 
|     if cfgID == None or dayIndex == None or not ipyData:  | 
|         return 0  | 
|     templateIDList = ipyData.GetTemplateIDList()  | 
|     templateID = templateIDList[-1] if dayIndex >= len(templateIDList) else templateIDList[dayIndex]  | 
|     return templateID  | 
|   | 
| def GetOperationActionDateStr(ipyData):  | 
|     ## »ñÈ¡ÔËÓª»î¶¯¶ÔÓ¦ÈÕÆÚ£¬´æÊý×Ö´ú±í¿ª·þÌìÅäÖã¬ÐèҪת»¯Îª¶ÔÓ¦µÄÈÕÆÚ  | 
|     curDateTime = datetime.datetime.today()  | 
|     startDateStr = ipyData.GetStartDate()  | 
|     endDateStr = ipyData.GetEndDate()  | 
|     if not startDateStr:  | 
|         startDateStr = "%d-%d-%d" % (curDateTime.year, curDateTime.month, curDateTime.day)  | 
|     if not endDateStr:  | 
|         endDateStr = "%d-%d-%d" % (curDateTime.year, curDateTime.month, curDateTime.day)  | 
|           | 
|     # ÈÕÆÚÖ±½Ó·µ»Ø  | 
|     if startDateStr.count("-") == 2 and "W" not in startDateStr:  | 
|         return startDateStr, endDateStr  | 
|       | 
|     # ¿ª·þÌì  | 
|     if startDateStr.isdigit():  | 
|         diffDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ServerDay) + 1  | 
|         startDateTime = curDateTime + datetime.timedelta(days=(int(startDateStr)-diffDay))  | 
|         endDateTime = curDateTime + datetime.timedelta(days=(int(endDateStr)-diffDay))  | 
|           | 
|     # ºÏ·þÌì  | 
|     elif startDateStr.startswith("Mix"):  | 
|         diffDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_MixServerDay) + 1  | 
|         startDateTime = curDateTime + datetime.timedelta(days=(int(startDateStr[3:])-diffDay))  | 
|         endDateTime = curDateTime + datetime.timedelta(days=(int(endDateStr[3:])-diffDay))  | 
|           | 
|     # ÖÜÑ»·, Ö±½ÓÅäÖàWx »ò Wx|ÓÐЧ¿ªÊ¼ÈÕÆÚ  »ò Wx|ÓÐЧ½áÊøÈÕÆÚ  | 
|     elif startDateStr.startswith("W"):  | 
|         curWeekday = curDateTime.weekday() + 1  | 
|           | 
|         startWeekDateInfo = startDateStr.split("|")  | 
|         startWeekInfo = startWeekDateInfo[0]  | 
|         startWeekday = int(startWeekInfo[1:])  | 
|         startDateTime = curDateTime + datetime.timedelta(days=(startWeekday-curWeekday))  | 
|           | 
|         # ÏÞÖÆ¿ªÆôÑ»·ÈÕÆÚ  | 
|         if len(startWeekDateInfo) > 1:  | 
|             startLoopDateStr = startWeekDateInfo[1]  | 
|             startLoopDateTime = ChangeStrToDatetime(startLoopDateStr, ChConfig.TYPE_Time_YmdFormat)  | 
|             if startLoopDateTime > startDateTime:  | 
|                 startDateTime = startLoopDateTime  | 
|                   | 
|         startWeekDay = startDateTime.weekday() + 1 # Êµ¼Ê¿ªÆô»î¶¯ÊÇÖܼ¸£¬²»Ò»¶¨ºÍÅäÖõÄÖܼ¸Ò»Ñù£¬¿ÉÄÜ´ÓÖм䱻½Ø¶Ï¿ªÊ¼  | 
|           | 
|         # ´¦ÀíÖÜÑ»·µÄ½áÊøÈÕÆÚ  | 
|         endWeekDateInfo = endDateStr.split("|")  | 
|         endWeekInfo = endWeekDateInfo[0]  | 
|         endWeekday = int(endWeekInfo[1:])  | 
|         endDateTime = startDateTime + datetime.timedelta(days=(endWeekday-startWeekDay))  | 
|         if len(endWeekDateInfo) > 1:  | 
|             endLoopDateStr = endWeekDateInfo[1]  | 
|             endLoopDateTime = ChangeStrToDatetime(endLoopDateStr, ChConfig.TYPE_Time_YmdFormat)  | 
|             if endDateTime > endLoopDateTime:  | 
|                 endDateTime = endLoopDateTime  | 
|                   | 
|             # Ö»ÅäÖýáÊøÈÕÆÚµÄʱºò¿ÉÄܵ¼Ö¿ªÊ¼ÈÕÆÚ¼ÆËã³öÀ´±È½áÊøÈÕÆÚ»¹´ó£¬¼´µ±Ç°Ê±¼ä³¬¹ý½áÊøÈÕÆÚ£¬ÇÒ ÅäÖû¹´æÔÚµÄÇé¿ö  | 
|             if startDateTime > endDateTime:  | 
|                 startDateTime = endDateTime # ·´Õý¶¼ÎÞ·¨¿ªÆô£¬Ëæ±ã¸ø¸öÈÕÆÚ£¬²»³¬¹ý½áÊøÈÕÆÚ¼´¿É  | 
|                   | 
|     # Ä¬ÈÏ  | 
|     else:  | 
|         startDateTime = curDateTime  | 
|         endDateTime = curDateTime  | 
|           | 
|     startDateStr = "%d-%d-%d" % (startDateTime.year, startDateTime.month, startDateTime.day)  | 
|     endDateStr = "%d-%d-%d" % (endDateTime.year, endDateTime.month, endDateTime.day)  | 
|     return startDateStr, endDateStr  | 
|   | 
| ##»ñµÃϵͳʱ¼ä  | 
| # @param ÎÞÒâÒå  | 
| # @return ÏµÍ³Ê±¼ä  | 
| # @remarks »ñµÃϵͳʱ¼ä  | 
| def GetServerTime():  | 
|     return datetime.datetime.today()  | 
|   | 
| def GetWeekOfYear():  | 
|     ## Ò»ÄêÖеĵڼ¸ÖÜ, 1´ú±íµÚ1ÖÜ  | 
|     return datetime.datetime.isocalendar(datetime.datetime.today())[1]  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡2¸öʱ¼äÖ®¼ä²îÒìµÄTimeDeltaÀàʵÀý  | 
| # @param compareTimeStr ±È½ÏµÄʱ¼ä×Ö·û, Èç"2010-05-26 11:21:25"  | 
| # @return class timedelta ÊµÀý »ò None  | 
| # @remarks »ñÈ¡2¸öʱ¼äÖ®¼ä²îÒìµÄTimeDeltaÀàʵÀý  | 
| def __GetPastTimeDelta(compareTimeStr):  | 
|     #ÏÖÔÚʱ¼ä  | 
|     curDataTime = GetServerTime()  | 
|     #±È½Ïʱ¼ä  | 
|     compareDataTime = GetDateTimeByStr(compareTimeStr)  | 
|     #»ñȡת»»ºóµÄʱ¼äÒì³£  | 
|     if curDataTime == None or compareDataTime == None:  | 
|         return  | 
|       | 
|     return (curDataTime - compareDataTime)  | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÌìÊý  | 
| # @param dateTimeStr ±È½Ïʱ¼ä×Ö·û Èç"2010-05-26 11:21:25"  | 
| # @return ·µ»ØÖµ, Ïà²îµÄÌìÊý  | 
| # @remarks »ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÌìÊý  | 
| def GetPastDay(dateTimeStr):  | 
|     pastTimeDelta = __GetPastTimeDelta(dateTimeStr)  | 
|       | 
|     if pastTimeDelta == None:  | 
|         ErrLog("GetPastDay Err dateTimeStr = %s"%(dateTimeStr))  | 
|         return 0  | 
|   | 
|     return pastTimeDelta.days  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÓëÏÖʵʱ¼ä²î¾àµÄСʱÊý  | 
| # @param dateTimeStr ±È½Ïʱ¼ä×Ö·û Èç"2010-05-26 11:21:25"  | 
| # @return ·µ»ØÖµ, Ïà²îµÄСʱÊý  | 
| # @remarks »ñµÃÓëÏÖʵʱ¼ä²î¾àµÄСʱÊý  | 
| def GetPastHour(dateTimeStr):  | 
|     pastTimeDelta = __GetPastTimeDelta(dateTimeStr)  | 
|       | 
|     if pastTimeDelta == None:  | 
|         ErrLog("GetPastHour Err dateTimeStr = %s"%(dateTimeStr))  | 
|         return 0  | 
|   | 
|     return pastTimeDelta.days * 24 + pastTimeDelta.seconds / 3600  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÃëÊý  | 
| # @param dateTimeStr ±È½Ïʱ¼ä×Ö·û Èç"2010-05-26 11:21:25"  | 
| # @return ·µ»ØÖµ, Ïà²îµÄÃëÊý  | 
| # @remarks »ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÃëÊý  | 
| def GetPastSeconds(dateTimeStr):  | 
|     pastTimeDelta = __GetPastTimeDelta(dateTimeStr)  | 
|       | 
|     if pastTimeDelta == None:  | 
|         ErrLog("GetPastSeconds Err dateTimeStr = %s"%(dateTimeStr))  | 
|         return 0  | 
|   | 
|     return pastTimeDelta.days * 24 * 60 * 60 + pastTimeDelta.seconds  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##ÉèÖÃÊÀ½ç·þÎñÆ÷×Öµä  | 
| # @param key ×ÖµäÖµ  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks ÉèÖÃÊÀ½ç·þÎñÆ÷×Öµä  | 
| def SetWorldDictKey(key, tick):  | 
|     worldMgr = GetGameWorld()  | 
|     lastTick = worldMgr.GetTickByType(key)  | 
|       | 
|     if lastTick == -1:  | 
|         #δ³õʼ»¯²»·¢ÐÅÏ¢  | 
|         return False  | 
|       | 
|     if tick - lastTick < ChConfig.TYPE_Tick_Time[key]:  | 
|         return False  | 
|       | 
|     worldMgr.SetTickByType(key, tick)  | 
|     return True  | 
| #---------------------------------------------------------------------  | 
| ##ÉèÖÃÍæ¼Ò×Öµä  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param key ×ÖµäÖµ  | 
| # @param lastTick ³ÖÐøÊ±¼ä  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks ÉèÖÃÍæ¼Ò×Öµä  | 
| def SetPlayerDictKey(curPlayer, key, lastTick, tick):  | 
|     key = str(key)  | 
|     curPlayerKeyValue = curPlayer.GetDictByKey(key)  | 
|     #µÚÒ»´Î¼Ç¼  | 
|     if not curPlayerKeyValue:  | 
|         curPlayer.SetDict(key, tick)  | 
|         return True  | 
|       | 
|     if tick - curPlayerKeyValue < lastTick:  | 
|         #ʱ¼äδµ½  | 
|         return False  | 
|       | 
|     curPlayer.SetDict(key, tick)  | 
|     return True  | 
|   | 
|   | 
| ## Ë¢ÐÂÍæ¼Ò¸öÈËʱ¼ä  | 
| #  @param curPlayer Íæ¼ÒʵÀý  | 
| #  @param tickType Ê±¼äÀàÐÍ  | 
| #  @param tick Ê±¼ä´Á  | 
| #  @return ²¼¶ûÖµ  | 
| def RefurbishPlayerTick(curPlayer, tickType, tick):  | 
|       | 
|     dictKey = "Player_Tick_%s"%tickType  | 
|     lastTick = curPlayer.GetDictByKey(dictKey)  | 
|       | 
|     #µÚÒ»´Î¼Ç¼  | 
|     if not lastTick:  | 
|         curPlayer.SetDict(dictKey, tick)  | 
|         return True  | 
|       | 
|     #¼ä¸ôδµ½  | 
|     if tick - lastTick < ChConfig.TYPE_Player_Tick_Time[tickType]:  | 
|         #ʱ¼äδµ½  | 
|         return False  | 
|       | 
|     curPlayer.SetDict(dictKey, tick)  | 
|     return True  | 
|   | 
|   | 
| ##¹ã²¥MapServer£¬'+'·Ö¸ôkey ºÍValue, ÓÃÓÚÖ»´¦ÀíMapServerµÄ SetGameWorldDictµÄ²ÎÊý  | 
| # @param keyName ×ÖµäÃû  | 
| # @param value Öµ  | 
| # @param mapID µØÍ¼ID£¬0Ϊȫ¹ã²¥  | 
| # @return ÎÞ  | 
| # @remarks ¹ã²¥MapServer£¬'+'·Ö¸ôkey ºÍValue, ÓÃÓÚÖ»´¦ÀíMapServerµÄ SetGameWorldDictµÄ²ÎÊý  | 
| def SendMapServerMsgEx(keyName, value, mapID = 0, routeServerIndex = 1):  | 
|     GetGameWorld().SendMapServerMsg(mapID, "%s%s%s" % (keyName, ShareDefine.Def_Notify_Separator, value), routeServerIndex)  | 
|     return  | 
|   | 
| def SendCommMapServerMsg(keyName, value):  | 
|     ## ¹ã²¥¸ø³£¹æµØÍ¼ÐÅÏ¢£¬¸±±¾²»»áÊÕµ½  | 
|     sendMapIDList = []  | 
|     for mapLineInfo, routeServerIndex in PyGameData.g_commMapLineRouteDict.items():  | 
|         if mapLineInfo not in PyGameData.g_commMapLineInfo:  | 
|             continue  | 
|         realMapID = PyGameData.g_commMapLineInfo[mapLineInfo][0]  | 
|         if realMapID in sendMapIDList:  | 
|             continue  | 
|         sendMapIDList.append(realMapID)  | 
|         SendMapServerMsgEx(keyName, value, realMapID, routeServerIndex)  | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡²é¿´Ò³ÊýµÄÆðʼË÷ÒýºÍ½áÊøË÷Òý.  | 
| # @param viewPageIndex ²é¿´Ë÷Òý  | 
| # @param singePageCnt µ¥Ò³ÊýÁ¿  | 
| # @param totalCnt ×ÜÁ¿  | 
| # @return ¿ªÊ¼Ë÷Òý, ½áÊøË÷Òý  | 
| # @remarks ¿Í»§¶Ë·â°üÏìÓ¦  | 
| def GetViewPageBeginIndexAndEndIndex(viewPageIndex, singePageCnt, totalCnt):  | 
|     endIndex = max((viewPageIndex + 1) * singePageCnt - 1, 0)  | 
|     #¼ÓÒ»¸ö·À·¶, ±ÜÃⳬ³öÉÏÏÞ  | 
|     endIndex = max(min(endIndex, totalCnt - 1), 0)  | 
|     #»ñÈ¡¿ªÆôË÷Òý  | 
|     startIndex = min(viewPageIndex * singePageCnt, endIndex)  | 
|     return startIndex, endIndex  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡Ó뵱ǰʱ¼äÏà²îÌìÊýµÄdatetime¸ñʽÊý¾Ý  | 
| # @param diffDays ²î¾àÌìÊý  | 
| # @return datetime ÀàÐÍÊý¾Ý  | 
| # @remarks ¿Í»§¶Ë·â°üÏìÓ¦  | 
| def GetDatetimeByDiffDays(diffDays):  | 
|     return GetServerTime() + datetime.timedelta(days = diffDays)  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÓÅ»¯µÄº¯ÊýÖ¸Õë  | 
| # @param func º¯ÊýÖ¸Õë  | 
| # @return ÓÅ»¯ºóµÄº¯ÊýÖ¸Õë  | 
| # @remarks   | 
| def GetPsycoFunc(func):  | 
|     return func  | 
| #    if not __GetPsycoIsOpen():  | 
| #        #¹Ø±Õpsyco, ·µ»ØÔº¯Êý  | 
| #        return func  | 
| #  | 
| #    return psyco.proxy(func)  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡psyco¿ª¹Ø  | 
| # @param ÎÞ²ÎÊý  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks   | 
| def __GetPsycoIsOpen():  | 
|     return ReadChConfig.GetEvalChConfig('PsycoSwitch')  | 
|   | 
| ##ÖØÐ¼ÓÔØ½Å±¾.  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ÖØÐ¼ÓÔØ½Å±¾  | 
| def PsycoReload(tick):  | 
|     if not SetWorldDictKey(ChConfig.TYPE_ReloadScript, tick):  | 
|         #¼ä¸ôδµ½  | 
|         return  | 
|       | 
|     moduleNameList = []  | 
|     for moduleName in sys.modules.keys():  | 
|         moduleNameList.append([moduleName, moduleName.split(".")[-1]])  | 
|       | 
|     TravelFile(ChConfig.GameServerPath, "", moduleNameList)  | 
|     Log("PsycoReload Begin : time = %s"%GetCurrentDataTimeStr())  | 
|     return  | 
|   | 
| ## ±éÀúÎļþ  | 
| #  @param scriptPath  | 
| #  @param filePath  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def TravelFile(scriptPath, filePath, moduleNameList):  | 
|      | 
|     for fileName in os.listdir(scriptPath + filePath):  | 
|           | 
|         if fileName.startswith("."):  | 
|             continue  | 
|           | 
|         curModuleName = fileName.split('.')[0]  | 
|         for reloadName, moduleName in moduleNameList:  | 
|             if curModuleName != moduleName:  | 
|                 continue  | 
|   | 
|             module = sys.modules.get(reloadName)  | 
|   | 
|             if not module:  | 
|                 continue  | 
|               | 
|             reload(module)  | 
|   | 
|         #ÊÇÎļþ¼Ð  | 
|         if os.path.isdir(scriptPath + filePath + "\\" + fileName):  | 
|             TravelFile(scriptPath, filePath + "\\" + fileName + "\\", moduleNameList)  | 
|               | 
|     return  | 
|   | 
|   | 
| ## È«¾Öº¯Êý¼òҪ˵Ã÷£º×ª»¯³Éʱ¡¢·Ö¡¢Ãë  | 
| #  @param ²ÎÊý£ºÊ±¼ä£¨ºÁÃë¼¶£©  | 
| #  @return ·µ»ØÖµ£ºÊ±¡¢·Ö¡¢Ãë  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷£º  | 
| def ChangeInputTime(inputTime):  | 
|     curTimeHour = int(inputTime/1000)/3600  | 
|     curTimeMinute = int(inputTime/1000)/60%60  | 
|     curTimeSecond = int(inputTime/1000)%60  | 
|     return curTimeHour,curTimeMinute,curTimeSecond  | 
|   | 
|   | 
| ## Êýֵʱ¼äת»»³Éʱ¼ä¸ñʽ  | 
| #  @param timeNum: Êýֵʱ¼ä  | 
| #  @return: 2012-03-30 22:16:41 <type 'datetime.datetime'>  | 
| def ChangeTimeNumToStr(timeNum, timeFormat=ChConfig.TYPE_Time_Format):  | 
|     return time.strftime(timeFormat, time.localtime(timeNum))  | 
|   | 
| ## Êýֵʱ¼äת»»³Éʱ¼ä¸ñʽ  | 
| #  @param timeNum: Êýֵʱ¼ä  | 
| #  @return: 2012-03-30 22:16:41 <type 'datetime.datetime'>  | 
| def ChangeTimeNumToDatetime(timeNum, timeFormat=ChConfig.TYPE_Time_Format):  | 
|     timeStr = time.strftime(timeFormat, time.localtime(timeNum))  | 
|     return datetime.datetime.strptime(timeStr, timeFormat)  | 
|   | 
| ## Ê±¼ä¸ñʽת»»³ÉÊýֵʱ¼ä£¬¿É²Î¿¼datetime.datetime.fromtimestamp(102645645)  | 
| #  @param timeNum  | 
| #  @return Ê±¼äÊýÖµ 1970ÄêÆð  | 
| def ChangeTimeStrToNum(timeStr, timeFormat=ChConfig.TYPE_Time_Format):  | 
|     timeStr = datetime.datetime.strptime(timeStr, timeFormat).timetuple()   | 
|     return int(time.mktime(timeStr))   | 
|   | 
| def ChangeStrToDatetime(timeStr, timeFormat=ChConfig.TYPE_Time_Format):  | 
|     return datetime.datetime.strptime(timeStr, timeFormat)  | 
|   | 
| ##»ñÈ¡Ó뵱ǰʱ¼äÏà²îÌìÊýµÄdatetime¸ñʽÊý¾Ý  | 
| # @param diffDays ²î¾àÌìÊý  | 
| # @return datetime ÀàÐÍÊý¾Ý  | 
| # @remarks ¿Í»§¶Ë·â°üÏìÓ¦  | 
| def GetDatetimeBySubDays(diffDays):  | 
|     return datetime.datetime.today() - datetime.timedelta(days = diffDays)  | 
|   | 
| def GetDailyDateStr():  | 
|     ## »ñÈ¡ÈÕ³£ÈÕÆÚ yyyy-MM-dd  | 
|     curDate = GetServerTime()  | 
|     if curDate.hour >= ShareDefine.Def_OnEventHour:  | 
|         return "%d-%s-%s" % (curDate.year, curDate.month, curDate.day)  | 
|     preDate = curDate - datetime.timedelta(days = -1) # ÊôÓÚǰһÌì  | 
|     return "%s-%s-%s" % (preDate.year, preDate.month, preDate.day)  | 
|   | 
| def IsCrossServer():  | 
|     ## ÊÇ·ñ¿ç·þ·þÎñÆ÷  | 
|     return ToIntDef(ReadChConfig.GetPyMongoConfig("Merge", "IsMergeServer"), 0)  | 
|   | 
| def IsCrossRealmOpen():  | 
|     ## ÊÇ·ñ¿ªÆô¿ç·þ»î¶¯  | 
|     return ReadChConfig.GetPyMongoConfig("Merge", "MergeServerIP") or IsCrossServer()  | 
|   | 
| def GetCrossZoneName():  | 
|     ## ¿ç·þ·þÎñÆ÷·ÖÇøÃû£¬±ê¼ÇÒ»Æð¿ç·þ·ÖÇøµÄÃû×Ö£¬ÅäÖÃÔÚ¿ç·þ·þÎñÆ÷£¬×Ó·þ²»ÓÃÅäÖã¬ÓÉ¿ç·þ·þÎñÆ÷ͬ²½  | 
|     if IsCrossServer():  | 
|         return ReadChConfig.GetPyMongoConfig("Merge", "CrossZoneName")  | 
|     return PyGameData.g_crossZoneName  | 
|   | 
| def GetCrossServerTimeStr():  | 
|     ## ¿ç·þ·þÎñÆ÷ʱ¼ä  | 
|     if IsCrossServer():  | 
|         return GetCurrentDataTimeStr()  | 
|     lastCrossServerTime, lastServerTime, _ = PyGameData.g_crossServerTimeInfo  | 
|     if not lastCrossServerTime:  | 
|         return GetCurrentDataTimeStr()  | 
|     curTime = int(time.time())  | 
|     crossServerTime = lastCrossServerTime + (curTime - lastServerTime)  | 
|     return ChangeTimeNumToStr(crossServerTime)  | 
|   | 
| ## »ñÈ¡Íæ¼ÒµÄÇø·þÃû£¬½öÔÚ¿ç·þÓÐЧ  | 
| #  @param curPlayer Íæ¼ÒʵÀý  | 
| #  @return: Çø·þÃû  | 
| def GetAreaName(curPlayer):  | 
|     operator = curPlayer.GetAccountInfo().GetOperator()  | 
|     areaID = curPlayer.GetAccountInfo().GetAreaID()  | 
|       | 
|     # "%s-%s"%(operator, areaID)  | 
|     areaNameInfo = ReadChConfig.GetEvalChConfig("AreaNameInfo")  | 
|     areaName = eval(areaNameInfo.get("NameExpr", ""))  | 
|       | 
|     return areaName  | 
|       | 
|   | 
| ## »ñÈ¡Íæ¼ÒµÄÇø·þÃûCRC£¬½öÔÚ¿ç·þÓÐЧ  | 
| #  @param curPlayer Íæ¼ÒʵÀý  | 
| #  @return: Çø·þÃû  | 
| def GetAreaCrc(curPlayer):  | 
|     areaName = GetAreaName(curPlayer)  | 
|     return CommFunc.GetStrCrc(areaName)  | 
|   | 
|   | 
| ## »ñÈ¡Íæ¼ÒÈ«Ãû£¬Ò»°ã´´½Ç¼°¸ÄÃûʱÓà  | 
| def GetPlayerFullName(curPlayer, playerName, serverID):  | 
|     roleNameFormat = eval(ReadChConfig.GetChConfig("RoleNameFormat"))  | 
|     nameFormat, paramList, maxLen, maxServerID, specServerDict = roleNameFormat  | 
|     if serverID > maxServerID or serverID <= 0:  | 
|         ErrLog("GetPlayerFullName serverID=%s error! maxServerID=%s, check RoleNameFormat.txt" % (serverID, maxServerID))  | 
|         return ""  | 
|       | 
|     nameFormatInfo = GetDictValueByRangeKey(specServerDict, serverID)  | 
|     if nameFormatInfo:  | 
|         nameFormat, paramList = nameFormatInfo  | 
|           | 
|     fullName = nameFormat % tuple(paramList)  | 
|     if len(fullName) > maxLen:  | 
|         ErrLog("GetPlayerFullName playerName=%s,È«Ãû=%s len=%s > %s, check RoleNameFormat.txt" % (playerName, fullName, len(fullName), maxLen))  | 
|         return ""  | 
|       | 
|     return fullName  | 
|   | 
|   | 
| ## ´ÓÁбíÖвúÉúÎïÆ·£¬[[¼¸ÂÊ£¬object], ....],Íò·ÖÂÊ  | 
| #  @param itemList ´ýÑ¡ÁÐ±í  | 
| #  @return object  | 
| def GetResultByRandomList(randList, defValue=None, maxRateValue=ChConfig.Def_MaxRateValue):  | 
|     if not randList:  | 
|         return defValue  | 
|     rate = random.randint(0, randList[-1][0])  | 
|     return GetResultByRiseList(randList, rate, defValue)  | 
|   | 
| ## Ôö³¤ÁÐ±í£¨ÀàËÆ±ýͼ£©´ÓÖлñµÃÖ¸¶¨µÄÐÅÏ¢  | 
| #  @param itemList ´ýÑ¡ÁÐ±í  | 
| #  @param point Ö¸¶¨Öµ  | 
| #  @return µÚ¶þ¸öΪ¾ßÌåÐÅÏ¢ or None  | 
| #  @remarks Áбí½á¹¹£¬Ã¿¸öÔªËØÎªÐ¡ÁÐ±í£¬Ð¡ÁÐ±í³¤¶ÈΪ2£¬µÚÒ»¸öÔªËØÎª±È½ÏÖµ£¬µÚ¶þ¸öΪ¾ßÌåÐÅÏ¢  | 
| def GetResultByRiseList(riseList, point, defValue=None):  | 
|     for smallList in riseList:  | 
|         if point > smallList[0]:  | 
|             continue  | 
|           | 
|         return smallList[1]  | 
|       | 
|     return defValue  | 
|   | 
| ## ´ÓÁбíÖвúÉúÎïÆ·£¬[[È¨ÖØ, object], ....]  | 
| #  @param weightList ´ýÑ¡ÁÐ±í  | 
| def GetResultByWeightList(weightList, defValue=None):  | 
|     randList = []  | 
|     weight = 0  | 
|     for info in weightList:  | 
|         weight += info[0]  | 
|         randList.append([weight, info[1] if len(info) == 2 else info[1:]])  | 
|     if not randList:  | 
|         return defValue  | 
|     rate = random.randint(1, randList[-1][0])  | 
|     return GetResultByRiseList(randList, rate, defValue)  | 
|   | 
| ## »ñµÃ¶ÔÓ¦ÊýλµÄÖµ  | 
| #  @param numValue ÊýÖµ  | 
| #  @param dataIndex ÊýλË÷Òý  | 
| #  @return »ñµÃµÄÖµ   | 
| def GetDataByDigitPlace(numValue, dataIndex):  | 
|     return (numValue/pow(10, dataIndex))%10  | 
|       | 
|   | 
| ## ÉèÖöÔÓ¦ÊýλµÄÖµ  | 
| #  @param numValue ÊýÖµ  | 
| #  @param dataIndex ÊýλË÷Òý  | 
| #  @param dataValue µ±Ç°ÐÞ¸ÄÊýÖµ  | 
| #  @return »ñµÃµÄÖµ   | 
| def ChangeDataByDigitPlace(numValue, dataIndex, dataValue):  | 
|       | 
|     if dataValue < 0 or dataValue > 9 or dataIndex > ShareDefine.Def_PDictDigitCnt:  | 
|         return numValue  | 
|       | 
|     # »ñµÃ¶ÔÓ¦ÊýλµÄÖµ  | 
|     lastTagLV = GetDataByDigitPlace(numValue, dataIndex)  | 
|       | 
|     numValue += pow(10, dataIndex)*(dataValue - lastTagLV)  | 
|     return numValue  | 
|   | 
| def GetBitValue(dataValue, index):  | 
|     """ µÃµ½Ä³¸ö×Ö½ÚÖµÖÐijһλ(Bit)µÄÖµ  | 
|     @param dataValue: ´ýȡֵµÄ×Ö½ÚÖµ  | 
|     @param index: ´ý¶ÁȡλµÄÐòºÅ£¬´ÓÓÒÏò×ó0¿ªÊ¼£¬0-7Ϊһ¸öÍêÕû×Ö½ÚµÄ8¸öλ  | 
|     @return: ·µ»Ø¶ÁÈ¡¸ÃλµÄÖµ£¬0»ò1  | 
|     """  | 
|     return 1 if dataValue & (1 << index) else 0  | 
|   | 
| def SetBitValue(dataValue, index, val):  | 
|     """ ¸ü¸Äij¸ö×Ö½ÚÖµÖÐijһλ(Bit)µÄÖµ  | 
|     @param dataValue: ×¼±¸¸ü¸ÄµÄ×Ö½ÚÔÖµ  | 
|     @param index: ´ý¸ü¸ÄλµÄÐòºÅ£¬´ÓÓÒÏò×ó0¿ªÊ¼£¬0-7Ϊһ¸öÍêÕû×Ö½ÚµÄ8¸öλ  | 
|     @param val: Ä¿±êλԤ¸ü¸ÄµÄÖµ£¬0»ò1  | 
|     @return: ·µ»Ø¸ü¸Äºó×Ö½ÚµÄÖµ  | 
|     """  | 
|     if val:  | 
|         return dataValue | (1 << index)  | 
|     return dataValue & ~(1 << index)  | 
|   | 
| ## ¸ù¾Ý×Öµäkey»ñÈ¡valueÖµ  | 
| #  @return   | 
| def GetDictValueByKey(attrDict, findKey, defaultValue=None):  | 
|       | 
|     if findKey in attrDict:  | 
|         return attrDict[findKey]  | 
|       | 
|     for key, value in attrDict.items():  | 
|           | 
|         if isinstance(key, tuple) and findKey in key:  | 
|             return value  | 
|       | 
|     return defaultValue  | 
|   | 
| ## ¸ù¾Ý×Öµäkey·¶Î§»ñÈ¡valueÖµ  | 
| def GetDictValueByRangeKey(srcDict, findKey, defaultValue=None):  | 
|       | 
|     if findKey in srcDict:  | 
|         return srcDict[findKey]  | 
|       | 
|     for rangeKey, value in srcDict.items():  | 
|         if isinstance(rangeKey, tuple) and len(rangeKey) == 2 and rangeKey[0] <= findKey <= rangeKey[1]:  | 
|             return value  | 
|           | 
|     return defaultValue  | 
|   | 
| def CombineSumDict(adict, bdict):  | 
|     # ½«bdictÊý¾ÝºÏ²¢µ½adict, ÏàͬkeyÖµµÄÊý¾ÝÏà¼Ó  | 
|     bdict = copy.deepcopy(bdict)  | 
|     for key, value in adict.items():  | 
|         if key not in bdict:  | 
|             continue  | 
|         adict[key] = value + bdict.pop(key)  | 
|     adict.update(bdict)  | 
|     return adict  | 
|   | 
| ## ¸ù¾ÝÅÅÐлñÈ¡Ãû´Î¶ÔÓ¦Öµ  | 
| #  @param orderDict {Ãû´Î:obj, ...} Ãû´ÎÖ§³Ö¶ÎÌøÔ¾  | 
| #  @param order Ãû´Î£¬´Ó1¿ªÊ¼  | 
| #  @param isDefaultLast ÕÒ²»µ½µÄÃû´ÎÊÇ·ñĬÈÏÈ¡×îºóÒ»ÃûµÄ  | 
| #  @return obj or None  | 
| def GetOrderValueByDict(orderDict, order, isDefaultLast=True, defaultValue=None):  | 
|     if order in orderDict:  | 
|         return orderDict[order]  | 
|       | 
|     orderList = sorted(orderDict.keys())  | 
|     if order > 0:  | 
|         for dOrder in orderList:  | 
|             if order <= dOrder:  | 
|                 return orderDict[dOrder]  | 
|           | 
|     # ÕÒ²»µ½µÄĬÈÏÈ¡×îºóÒ»Ãû  | 
|     return orderDict[orderList[-1]] if isDefaultLast else defaultValue  | 
|   | 
| ##¸ÅÂÊÏà¹Ø, Õâ¸öʼþÊÇ·ñÄܹ»³öÏÖ  | 
| # @param rate »ù´¡¼¸ÂÊ  | 
| # @param maxRate ×î´ó¼¸ÂÊ  | 
| # @return ·µ»ØÖµ. ÊÇ·ñͨ¹ý¼ì²é  | 
| # @remarks ¸ÅÂÊÏà¹Ø, Õâ¸öʼþÊÇ·ñÄܹ»³öÏÖ  | 
| def CanHappen(rate, maxRate=ShareDefine.Def_MaxRateValue):  | 
|     if random.randint(0, maxRate -1) < rate:  | 
|         return 1  | 
|       | 
|     return 0  | 
|   | 
| def DebugAnswer(curPlayer, text):  | 
|     '''תÂëºóÔÙ·¢DebugAnswer'''  | 
|     #===========================================================================  | 
|     # if not GetGameWorld().GetDebugLevel():  | 
|     #    return  | 
|     #===========================================================================  | 
|     DebugLog(text)  | 
|     text = text.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding())  | 
|     curPlayer.DebugAnswer(text)  | 
|     return  | 
|   | 
| def CrossServerMsg_DebugAnswer(msgData):  | 
|     playerID, text = msgData  | 
|     curPlayer = GetPlayerManager().FindPlayerByID(playerID)  | 
|     if not curPlayer:  | 
|         return  | 
|     curPlayer.DebugAnswer(text)  | 
|     return  | 
|   | 
| def DebugAnswerCross(playerID, serverGroupID, text):  | 
|     DebugLog(text)  | 
|     text = text.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding())  | 
|       | 
|     import CrossRealmMsg  | 
|     dataMsg = [playerID, text]  | 
|     serverGroupIDList = [serverGroupID]  | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_DebugAnswer, dataMsg, serverGroupIDList)  | 
|     return  | 
|   | 
| def GetMap(mapID): return IpyGameDataPY.GetIpyGameData("ChinMap", mapID)  | 
|   | 
| def GetNPCData(npcID): return IpyGameDataPY.GetIpyGameData("ChinNPC", npcID)  | 
|   | 
| # »ñµÃÓÎÏ·ÉèÖõÄ×Ö·û±àÂë, Í³Ò»µ÷ÓñãÓÚº£Íâ°æ±¾  | 
| def GetCharacterEncoding():  | 
|     encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")  | 
|       | 
|     if len(encodingList) != 2:  | 
|         ErrLog("EncodingTex.txt Error len != 2")  | 
|         return 'utf8'  | 
|     return encodingList[1]  | 
|   | 
|   | 
| # ·þÎñÆ÷ĬÈÏGBK£¬×ªÅäÖñàÂëÈçUTF8£¬Ò»°ãÓÃÓÚÓëÏÔʾ²ã½»»¥£¬²»ÅжÏÊÇ·ñbase64  | 
| def GbkToCode(inputText):  | 
|     encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")  | 
|       | 
|     if len(encodingList) != 2:  | 
|         ErrLog("EncodingTex.txt Error len != 2")  | 
|         return inputText  | 
|       | 
|     try:  | 
|         return inputText.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding())  | 
|     except:  | 
|         return inputText  | 
|       | 
|     return inputText  | 
|   | 
| # ·þÎñÆ÷ĬÈÏGBK£¬×ªÅäÖñàÂëÈçUTF8£¬Ò»°ãÓÃÓÚÓëÏÔʾ²ã½»»¥£¬²»ÅжÏÊÇ·ñbase64  | 
| def CodeToGBK(inputText):  | 
|     encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")  | 
|       | 
|     if len(encodingList) != 2:  | 
|         ErrLog("EncodingTex.txt Error len != 2")  | 
|         return inputText  | 
|       | 
|     try:  | 
|         return inputText.decode(GetCharacterEncoding()).encode(ShareDefine.Def_Game_Character_Encoding)  | 
|     except:  | 
|         return inputText  | 
|       | 
|     return inputText  | 
|   | 
| def RaiseException(errorMsg, playerID=0):  | 
|     ## ´¦ÀíÅ׳öÒì³£ÐÅÏ¢£¬debugÏÂÖ±½ÓÅ׳öÒì³£±¨´íÐÅÏ¢£¬·ñÔò·¢ËÍÔËάÓʼþÌáÐÑ  | 
|     ErrLog(errorMsg, playerID)  | 
|     if GetGameWorld().GetDebugLevel():  | 
|         raise Exception(errorMsg)  | 
|     else:  | 
|         SendGameError("GameServerRaiseException", errorMsg)  | 
|     return  | 
|   | 
| def SendGameError(errType, msgInfo=""):  | 
|     ''' ÏòÔËά·¢ËÍÓʼþ£¬ÓÃÓÚÐèÒª½ô¼±´¦ÀíµÄÐÅÏ¢  | 
|     @param errType: ´íÎóÀàÐÍ£¬×Ô¶¨Òå¼´¿É  | 
|     @param msgInfo: ´íÎóÐÅÏ¢£¬¿ÉÑ¡  | 
|     '''  | 
|     getUrl = ReadChConfig.GetPyMongoConfig("EventReport", "OpenStateUrl")  | 
|     groupID = ReadChConfig.GetPyMongoConfig("platform", "GroupID")  | 
|     userDBName = ReadChConfig.GetPyMongoConfig("connect", "USER_DB_NAME")  | 
|     getUrl = getUrl + "?Type=%s&groupID=%s&userDBName=%s"%(errType, groupID, userDBName)  | 
|     if msgInfo:  | 
|         getUrl = getUrl + "&MsgInfo=%s" % urllib.quote_plus(msgInfo)  | 
|     GetGameWorld().EventReport_EventReport("", "", "", "", 0, getUrl)  | 
|     return  |