PySysDB/Éú³ÉIpyGameDataPY/IpyGameDataPYTemp.py
@@ -21,6 +21,7 @@
import hashlib
import os
import gc
'''表结构定义字典
{
@@ -50,55 +51,102 @@
class IPY_DataMgr():
    
    def __init__(self):
        Log("IPY_DataMgr Init...")
        self.fileMD5Dict = {} # æ•°æ®è¡¨æ–‡ä»¶md5字典, ç”¨äºŽå¯¹æ¯”文件差异判断是否重读 {dtName:md5, ...}
        self.ipyConfigEx = {} # è‡ªå®šä¹‰æ•°æ®ç¼“å­˜ {key:configData, ...}
        self.ipyDataIndexMap = {} # æ•°æ®è¡¨ç´¢å¼•查询缓存 {dtName:{args:[index, ...], ...}, ...}
        self.ipyDataIndexMapEx = {} # æ•°æ®è¡¨è‡ªå®šä¹‰æŸ¥è¯¢æ¡ä»¶æŸ¥è¯¢ç¼“å­˜ {dtName_(findKey,...):{(findKeyValue, ...):[index, ...], ...}, ...}
        self.ipyFuncConfigDict = {} # åŠŸèƒ½é…ç½®è¡¨ç¼“å­˜ {key:IPY_FuncConfig, ...}
        self.classSizeDict = {} # æ•°æ®è¡¨ç±»å¯¹è±¡å ç”¨å†…存大小 {dtName:size, ...}
        self.IpyDataClear(True)
        return
    def Recycle(self):
        Log("IPY_DataMgr Recycle")
        for tableName in Def_IpyTable.keys():
            if not hasattr(self, "ipy%sLen" % tableName):
                continue
            cacheList = getattr(self, "ipy%sCache" % tableName)
            del cacheList
            delattr(self, "ipy%sLen" % tableName)
            delattr(self, "ipy%sCache" % tableName)
            Log("Recycle IPY_%s" % tableName)
        del self.fileMD5Dict, self.ipyConfigEx, self.ipyDataIndexMap, self.ipyDataIndexMapEx, self.ipyFuncConfigDict, self.classSizeDict
        self.fileMD5Dict = {}
        self.ipyConfigEx = {}
        self.ipyDataIndexMap = {}
        self.ipyDataIndexMapEx = {}
        self.ipyFuncConfigDict = {}
        self.classSizeDict = {}
        gc.collect()
        return
    def LoadAll(self):
        ## åŠ è½½å…¨éƒ¨æ•°æ®ï¼Œæµ‹è¯•å†…å­˜ç”¨ï¼Œå®žé™…åº”ç”¨ä¸­ä¸è°ƒç”¨
        for tableName in Def_IpyTable.keys():
            setattr(self, "ipy%sLen" % tableName, 0)
        self.IpyDataClear()
        return
    
    def IpyDataClear(self):
        Log("IPY_DataMgr Init...")
        self.ipyConfigEx = {}
    def IpyDataClear(self, onlyCheck=False):
        Log("IPY_DataMgr Reload... onlyCheck=%s" % onlyCheck)
        if not onlyCheck:
            self.ipyConfigEx = {}
        #<%Ipy_Cache_Init%>
        Log("IPY_FuncConfig count=%s" % len(self.ipyFuncConfigDict))
        Log("IPY_DataMgr InitOK!")
        Log("IPY_DataMgr ReloadOK! onlyCheck=%s" % onlyCheck)
        return
    
    def __LoadFileData(self, tableName, Class):
    def CheckLoadData(self, dtName):
        if hasattr(self, "ipy%sLen" % dtName):
            return
        setattr(self, "ipy%sLen" % dtName, 0) # è®¾ç½®è¯¥å±žæ€§ï¼Œé€šè¿‡åˆ¤æ–­æ˜¯å¦æœ‰è¯¥å±žæ€§å†³å®šæ˜¯å¦åŠ è½½
        self.__LoadFileData(dtName)
        return
    def __LoadFileData(self, tableName, onlyCheck=False):
        # @param onlyCheck: æ˜¯å¦ä»…检查格式,一般启动时用
        curPath = "<%LoadStructPath%>" + "\\PySysDB\\tag" + tableName + ".txt"
        if not os.path.isfile(curPath):
            ErrLog("can not find file = %s,%s" % (tableName, curPath))
            raise Exception("can not find file = %s,%s" % (tableName, curPath))
        
        if not onlyCheck:
            if not hasattr(self, "ipy%sLen" % tableName):
                # æ²¡æœ‰è¯¥å±žæ€§çš„不加载
                return
        fileObj = open(curPath, 'rb')
        content = fileObj.read()
        fileObj.close()
        
        md5_obj = hashlib.md5()
        md5_obj.update(content)
        newMD5Code = md5_obj.hexdigest()
        if tableName in self.fileMD5Dict:
            oldMD5Code = self.fileMD5Dict[tableName]
            if newMD5Code == oldMD5Code:
                return getattr(self, "ipy%sCache" % tableName)
        if not onlyCheck:
            md5_obj = hashlib.md5()
            md5_obj.update(content)
            newMD5Code = md5_obj.hexdigest()
            if tableName in self.fileMD5Dict:
                oldMD5Code = self.fileMD5Dict[tableName]
                if newMD5Code == oldMD5Code:
                    return getattr(self, "ipy%sCache" % tableName)
                if tableName in self.ipyDataIndexMap:
                    self.ipyDataIndexMap.pop(tableName)
                for dtName_Findkey in self.ipyDataIndexMapEx.keys():
                    findStr = "%s_" % tableName
                    if findStr in dtName_Findkey:
                        self.ipyDataIndexMapEx.pop(dtName_Findkey)
                if tableName == "FuncConfig":
                    self.ipyFuncConfigDict = {}
            self.fileMD5Dict[tableName] = newMD5Code
            
            if tableName in self.ipyDataIndexMap:
                self.ipyDataIndexMap.pop(tableName)
            for dtName_Findkey in self.ipyDataIndexMapEx.keys():
                findStr = "%s_" % tableName
                if findStr in dtName_Findkey:
                    self.ipyDataIndexMapEx.pop(dtName_Findkey)
            if tableName == "FuncConfig":
                self.ipyFuncConfigDict = {}
        self.fileMD5Dict[tableName] = newMD5Code
        dataIndex = 0
        indexDict = {}
        cacheList = []
        fieldList = Def_IpyTable[tableName]
        infoList = content.split('\r\n')
        curClassSizeTotal = 0
        dataCount = 0
        Class = eval("IPY_%s" % tableName)
        for line in xrange(len(infoList)):
            if line == 0:
                continue
@@ -109,27 +157,43 @@
            if len(fieldList) != len(rowList):
                ErrLog("field count error!, %s, line=%s, len=%s,rowCount=%s" % (tableName, line, len(fieldList), len(rowList)))
                raise Exception("field count error!, %s, line=%s, len=%s,rowCount=%s" % (tableName, line,len(fieldList), len(rowList)))
            if tableName == "FuncConfig":
                classObj = self.__LoadFuncConfigData(fieldList, rowList, onlyCheck)
                dataCount += 1
                if onlyCheck:
                    continue
                curClassSizeTotal += ChConfig.GetSizeof(classObj)
                continue
            try:
                indexKey = []
                classObj = Class()
                valueList = []
                for j, value in enumerate(rowList):
                    fieldType, fieldName, isIndex = fieldList[j]
                    if fieldType == "char":
                        attrValue = value
                    elif fieldType == "dict":
                        attrValue = self.__StrToDict(value)
                        if type(attrValue) != dict:
                            raise
                    elif fieldType == "list":
                        attrValue = self.__StrToList(value)
                        if type(attrValue) not in [list, tuple]:
                            raise
                    elif fieldType == "eval":
                        attrValue = self.__StrToEval(value)
                    elif fieldType == "float":
                        attrValue = float(value)
                    else:
                        attrValue = 0 if not value.isdigit() else int(value)
                    setattr(classObj, "%s" % fieldName, attrValue)
                    valueList.append(attrValue)
                    if isIndex:
                        indexKey.append(attrValue)
                dataCount += 1
                if onlyCheck:
                    continue
                classObj = Class()
                setattr(classObj, "attrTuple", tuple(valueList))
                curClassSizeTotal += ChConfig.GetSizeof(classObj)
                cacheList.append(classObj)
                indexKey = tuple(indexKey)
                indexList = indexDict.get(indexKey, [])
@@ -139,22 +203,26 @@
            except BaseException:
                ErrLog("SetIpyDataError: tableName=%s,line=%s,fieldName=%s,fieldType=%s,value=%s" % (tableName, line, fieldName, fieldType, value))
                raise
            if tableName == "FuncConfig":
                self.__LoadFuncConfigData(fieldList, rowList)
        if onlyCheck:
            Log("CheckIpydata: %s, dataCount=%s OK" % (tableName, dataCount))
            return
        if tableName != "FuncConfig":
            self.ipyDataIndexMap[tableName] = indexDict
        Log("LoadIpydata: %s, content count=%s" % (tableName, len(cacheList)))
        return cacheList
        self.classSizeDict[tableName] = curClassSizeTotal
        classSizeTotal = sum(self.classSizeDict.values())
        alreadyLoad = len(self.classSizeDict)
        setattr(self, "ipy%sCache" % tableName, cacheList)
        setattr(self, "ipy%sLen" % tableName, len(cacheList))
        Log("LoadIpydata: %s, dataCount=%s, alreadyLoad=%s" % (tableName, dataCount, alreadyLoad), curClassSizeTotal, classSizeTotal)
        return
    
    def __LoadFuncConfigData(self, fieldList, rowList):
        funcConfigObj = IPY_FuncConfig()
    def __LoadFuncConfigData(self, fieldList, rowList, onlyCheck):
        key = rowList[0]
        funcConfigObj.Key = key
        valueList = [key]
        for i, strValue in enumerate(rowList):
            if i == 0:
                continue
            try:
                fieldName = fieldList[i][1]
                strValue = strValue.lstrip().rstrip()
                if strValue.isdigit():
                    configValue = int(strValue)
@@ -173,9 +241,15 @@
            except BaseException:
                ErrLog("SetIpyDataError: tableName=%s,key=%s,i=%s,value=%s" % ("FuncConfig", key, i, strValue))
                raise
            setattr(funcConfigObj, fieldName, configValue)
            if onlyCheck:
                continue
            valueList.append(configValue)
        if onlyCheck:
            return
        funcConfigObj = IPY_FuncConfig()
        setattr(funcConfigObj, "attrTuple", tuple(valueList))
        self.ipyFuncConfigDict[key] = funcConfigObj
        return
        return funcConfigObj
    
    def __ToFloat(self, strValue):
        try:
@@ -255,6 +329,7 @@
    @return: å¯¹åº”查询条件的 ipyData æ•°æ®å®žä¾‹ï¼Œåªè¿”回单个实例
    @使用说明: IpyGameDataPY.GetIpyGameData(表名, ç´¢å¼•1查询值, ç´¢å¼•2查询值, â€¦ )
    '''
    IPYData.CheckLoadData(dtName)
    if dtName not in IPYData.ipyDataIndexMap:
        ErrLog("Can not found ipyData dtName=%s" % (dtName))
        return
@@ -272,6 +347,7 @@
    @return: å¯¹åº”查询条件的 ipyData æ•°æ®å®žä¾‹åˆ—表
    @使用说明: ä¸Ž GetIpyGameData å‡½æ•°ç›¸åŒ
    '''
    IPYData.CheckLoadData(dtName)
    if dtName not in IPYData.ipyDataIndexMap:
        ErrLog("Can not found ipyDataList dtName=%s" % (dtName))
        return
@@ -286,6 +362,7 @@
def GetIpyGameDataNotLog(dtName, *args):
    '''与 GetIpyGameData å‡½æ•°ç›¸åŒ, åªæ˜¯æ‰¾ä¸åˆ°æ•°æ®æ—¶ä¸ä¼šè¾“出日志
    '''
    IPYData.CheckLoadData(dtName)
    if dtName not in IPYData.ipyDataIndexMap:
        #ErrLog("Can not found ipyData dtName=%s" % (dtName))
        return
@@ -299,6 +376,7 @@
def GetIpyGameDataListNotLog(dtName, *args):
    '''与 GetIpyGameDataList å‡½æ•°ç›¸åŒ, åªæ˜¯æ‰¾ä¸åˆ°æ•°æ®æ—¶ä¸ä¼šè¾“出日志
    '''
    IPYData.CheckLoadData(dtName)
    if dtName not in IPYData.ipyDataIndexMap:
        #ErrLog("Can not found ipyDataList dtName=%s" % (dtName))
        return
@@ -318,6 +396,7 @@
    @param isLogNone: æ‰¾ä¸åˆ°æ•°æ®æ—¶æ˜¯å¦æ•°æ®æ—¥å¿—,默认是
    @return: æ‰¾ä¸åˆ°æ•°æ®æ—¶è¿”回 None,有数据时根据参数是否返回列表返回对应的数据实例或数据实例列表
    '''
    IPYData.CheckLoadData(dtName)
    fieldList = keyDict.keys()
    valueList = keyDict.values()
    findFieldKey = "%s_%s" % (dtName, fieldList)
@@ -327,7 +406,7 @@
    if findFieldKey not in IPYData.ipyDataIndexMapEx:
        indexMapDict = {}
        for index, iData in enumerate(cacheList):
            valuekey = tuple([getattr(iData, "%s" % field) for field in fieldList])
            valuekey = tuple([getattr(iData, "Get%s" % field)() for field in fieldList])
            indexList = indexMapDict.get(valuekey, [])
            indexList.append(index)
            indexMapDict[valuekey] = indexList        
@@ -348,6 +427,7 @@
    @param key: é…ç½®key
    @return: ç›´æŽ¥è¿”回该配置key对应的配置ipyData实例
    '''
    IPYData.CheckLoadData("FuncConfig")
    if key not in IPYData.ipyFuncConfigDict:
        ErrLog("Can not found ipyData FuncConfig key=%s!" % key)
        return ""
@@ -359,20 +439,21 @@
    @param index: ç¬¬å‡ ä¸ªé…ç½®å€¼ï¼Œæ”¯æŒ1~5
    @return: ç›´æŽ¥è¿”回对应的数据类型 int、str,不用再手动转int
    '''
    IPYData.CheckLoadData("FuncConfig")
    if key not in IPYData.ipyFuncConfigDict:
        ErrLog("Can not found ipyData FuncConfig key=%s!" % key)
        return ""
    cfgObj = IPYData.ipyFuncConfigDict[key]
    if index == 1:
        return cfgObj.Numerical1
        return cfgObj.attrTuple[1]
    if index == 2:
        return cfgObj.Numerical2
        return cfgObj.attrTuple[2]
    if index == 3:
        return cfgObj.Numerical3
        return cfgObj.attrTuple[3]
    if index == 4:
        return cfgObj.Numerical4
        return cfgObj.attrTuple[4]
    if index == 5:
        return cfgObj.Numerical5
        return cfgObj.attrTuple[5]
    ErrLog("Can not found ipyData FuncConfig key=%s,index=%s!" % (key, index))
    return ""
@@ -387,20 +468,21 @@
    å½“然如果配置的内容本身就为python的列表、字典结构的话可使用上面的函数
    ä¸è¿‡ä¸ºäº†ç»Ÿä¸€ï¼Œå»ºè®®åŠŸèƒ½é…ç½®è¡¨è¯»åˆ—è¡¨ã€å­—å…¸æ—¶éƒ½ä½¿ç”¨è¯¥å‡½æ•°
    '''
    IPYData.CheckLoadData("FuncConfig")
    if key not in IPYData.ipyFuncConfigDict:
        ErrLog("Can not found ipyData FuncConfig key=%s!" % key)
        return defaultValue
    cfgObj = IPYData.ipyFuncConfigDict[key]
    if index == 1:
        curConfig = cfgObj.Numerical1
        curConfig = cfgObj.attrTuple[1]
    elif index == 2:
        curConfig = cfgObj.Numerical2
        curConfig = cfgObj.attrTuple[2]
    elif index == 3:
        curConfig = cfgObj.Numerical3
        curConfig = cfgObj.attrTuple[3]
    elif index == 4:
        curConfig = cfgObj.Numerical4
        curConfig = cfgObj.attrTuple[4]
    elif index == 5:
        curConfig = cfgObj.Numerical5
        curConfig = cfgObj.attrTuple[5]
    else:
        ErrLog("Can not found ipyData FuncConfig key=%s,index=%s!" % (key, index))
        return defaultValue
@@ -427,6 +509,7 @@
    @param conditionDict: æŸ¥è¯¢æ¡ä»¶ï¼Œ{查询字段名:字段值, ...}
    @return: æ‰¾ä¸åˆ°æ•°æ®è¿”回 None ï¼Œ å¦åˆ™è¿”回对应的 ipyData æ•°æ®å®žä¾‹
    '''
    IPYData.CheckLoadData(dtName)
    if not conditionDict:
        dataList = getattr(IPYData, "ipy%sCache" % dtName)
    else:
@@ -436,34 +519,88 @@
    
    low = 0
    lowData = dataList[0]
    lowValue = getattr(lowData, "%s" % keyName)
    lowValue = getattr(lowData, "Get%s" % keyName)()
    if keyValue < lowValue:
        return
    
    high = len(dataList) - 1
    highData = dataList[high]
    highValue = getattr(highData, "%s" % keyName)
    highValue = getattr(highData, "Get%s" % keyName)()
    if keyValue >= highValue:
        return highData
    
    near = low + int((high - low) * (keyValue - lowValue)/(highValue - lowValue))
    
    nearData = dataList[near]
    nearValue = getattr(nearData, "%s" % keyName)
    nearValue = getattr(nearData, "Get%s" % keyName)()
    
    if keyValue < nearValue:
        for i in xrange(near - 1, low - 1, -1):
            nearData = dataList[i]
            nearValue = getattr(nearData, "%s" % keyName)
            nearValue = getattr(nearData, "Get%s" % keyName)()
            if nearValue <= keyValue:
                return nearData
            
    elif keyValue > nearValue:
        for i in xrange(near + 1, high + 1):
            nearData = dataList[i]
            nearValue = getattr(nearData, "%s" % keyName)
            nearValue = getattr(nearData, "Get%s" % keyName)()
            if nearValue > keyValue:
                return dataList[i - 1]
            
    return nearData
#if __name__ == "__main__":
#    IPYDataTotalSize = ChConfig.GetSizeof(IPYData)
#    classSizeSum = sum(IPYData.classSizeDict.values())
#    Log("数据类内存: %s b = %s M" % (classSizeSum, str(classSizeSum/float(1024*1024))))
#    Log("总占用内存: %s b = %s M" % (IPYDataTotalSize, str(IPYDataTotalSize/float(1024*1024))))
#    for key in ["OpenBagItem", "RuneUnlock", "IceLodeNeedPoint", "RealmDifficulty", "TongTianLing", "TongTianLingaaa"]:
#        for i in range(1, 6):
#            v = GetFuncCfg(key, i)
#            Log("key:%s,i=%s,value=%s\t%s" % (key, i, type(v), str(v)))
#
#    ipyData = GetIpyGameData("FlashGiftbag", 303)
#    giftbagIpyDataList = GetIpyGameDataByCondition("FlashGiftbag", {"GiftbagType":1002}, True, True)
#    for ipyData in giftbagIpyDataList:
#        print
#        print type(ipyData.GetGiftbagID()), ipyData.GetGiftbagID()
#        print type(ipyData.GetGiftbagType()), ipyData.GetGiftbagType()
#        print type(ipyData.GetOriginalRMB()), ipyData.GetOriginalRMB()
#        print type(ipyData.GetBuyCountLimit()), ipyData.GetBuyCountLimit()
#        print type(ipyData.GetGiftItemList()), ipyData.GetGiftItemList()
#        print type(ipyData.GetMainItemID()), ipyData.GetMainItemID()
#        print type(ipyData.GetNotifyKey()), ipyData.GetNotifyKey()
#
#    collNPCIpyDataList = GetIpyGameDataListNotLog("MapRefreshNPC", 32050)
#    if collNPCIpyDataList:
#        npcIDList = []
#        for ipyData in collNPCIpyDataList:
#            print
#            print type(ipyData.GetMapID()), ipyData.GetMapID()
#            print type(ipyData.GetNPCIDList()), ipyData.GetNPCIDList()
#            print type(ipyData.GetRefreshMarkList()), ipyData.GetRefreshMarkList()
#            npcIDList += ipyData.GetNPCIDList()
#        print "npcIDList", npcIDList
#    else:
#        print "None"
#
#    ipyData = GetIpyGameData("RuneCompound", 4415)
#    if ipyData:
#        print
#        print type(ipyData.GetTagItemID()), ipyData.GetTagItemID()
#        print type(ipyData.GetNeedItem()), ipyData.GetNeedItem()
#        print type(ipyData.GetNeedMJ()), ipyData.GetNeedMJ()
#    else:
#        print "None"
#
#    ipyData = GetIpyGameData("DailyGiftbag", 703, 105)
#    if ipyData:
#        print
#        print type(ipyData.GetGiftbagType()), ipyData.GetGiftbagType()
#        print type(ipyData.GetGiftbagID()), ipyData.GetGiftbagID()
#        print type(ipyData.GetBuyCountLimit()), ipyData.GetBuyCountLimit()
#        print type(ipyData.GetGiftItemList()), ipyData.GetGiftItemList()
#    else:
#        print "None"