hxp
2025-06-04 f4a514d5ac952110da846636ecbb9de951eaf3d2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @todo: 战力分析
 
import CommFunc
import ConfigParser
import DBOperate
import operator
import logging
import mylog
 
cfg = ConfigParser.ConfigParser()
cfg.read("../../InterfaceConfig.php")
ServerPath = cfg.get("ServerInfo", "ServerPath")
 
MFPNameDict = {}
OtherMFPType = 99 # 兼容多版本,所有版本的战力流向最大模块默认设置为其他99
 
def initMFPTNameDict():
    global MFPNameDict
    MFPNameDict = {0:_(u"角色"), 1:_(u"装备"), 2:_(u"强化"), 3:_(u"宝石"), 4:_(u"灵根"), 5:_(u"灵器"), 6:_(u"洗练"), 7:_(u"灵宠"), 8:_(u"坐骑"), 9:_(u"境界"),
                   10:_(u"神兵"), 11:_(u"称号"), 12:_(u"符印"), 13:_(u"升星"), 14:_(u"人族"), 15:_(u"丹药"), 16:_(u"魔族"), 17:_(u"仙族"), 18:_(u"灵宠魂石"), 19:_(u"坐骑魂石"),
                   20:_(u"法器"), 21:_(u"神兽"), 22:_(u"聚魂"), 23:_(u"王者法宝"), 24:_(u"时装"), 25:_(u"情缘"), 26:_(u"魅力"), 27:_(u"炼体"), 28:_(u"附魔"), 29:_(u"古宝"),
                   30:_(u"神通"), 31:_(u"阵法"), 32:_(u"聚魂新"), 33:_(u"头像"), 34:_(u"头像框"), 35:_(u"气泡框"), 
                   }
    addMFPTName(OtherMFPType, _(u"其他"))
    return
 
def addMFPTName(mfpType, mfpName=None):
    if not mfpName:
        mfpName = _(u"未知")
    global MFPNameDict
    if mfpType not in MFPNameDict:
        MFPNameDict[mfpType] = "<font color='red'>%s%s</font>" % (mfpName, mfpType)
    return
 
def parseUnknownMFP(drDict):
    '''处理未知战力模块,兼容不同游戏版本
    如版本一: {1:1000, ..., 26:100} 此处26是其他战力模块
    如版本二: {1:1000, ..., 26:200, 27:100} 此处26是魅力模块,27才是其他战力模块
    总结: 流向中最大数字ID的为其他模块战力
    '''
    mfpTList = []
    for k in drDict.keys():
        mfpType = CommFunc.toInt(k, None)
        if mfpType != None:
            drDict[mfpType] = drDict.pop(k)
            mfpTList.append(mfpType)
            
    maxMFPType = max(mfpTList)
    
    # 添加未知模块
    for mfpType in mfpTList:
        if mfpType != maxMFPType:
            addMFPTName(mfpType, _(u"未知"))
        else:
            drDict[OtherMFPType] = drDict.pop(mfpType) # 将此版本的真正其他战力模块设置为方便统一处理的其他战力模块
            
    return
 
def getMFPKVNameStr():
    printStr = "<br/>"
    printStr += "%s:" % _(u"模块对应名")
    for k, v in MFPNameDict.items():
        if k % 10 == 0:
            printStr += "<br/>"
        printStr += "%s-%s;" % (k, v)
    printStr += "<br/>"
    printStr += "<br/>"
    return printStr
 
def queryAccIDMFPInfo(argvDict):
    ## 查询个人战力模块分布
    
    startDate = argvDict.get("startDate", "")
    endDate = argvDict.get("endDate", "")
    queryType = argvDict.get("queryType", "")
    playerFind = argvDict.get("playerFind", "")
    
    # 查询中心备份的
    if CommFunc.isQueryCenterbak(argvDict):
        queryAccIDMFPInfo_Centerbak(startDate, endDate, argvDict)
        return
    
    playerName = ""
    queryAccID = playerFind
    if queryType == "playerName":
        # 根据玩家名查找的,以db为准,找到对应的账号进行匹配,不然玩家改名将导致匹配结果错误
        dboper = DBOperate.DBOper(ServerPath)
        findDBRet = dboper.findPlayerInfoByName([playerFind])
        dboper.close()
        if not findDBRet or findDBRet.count() == 0:
            print "找不到该玩家!<br/>%s<br/>" % playerFind
            return
        
        dbPlayer = findDBRet[0]
        queryAccID = CommFunc.encode(dbPlayer["AccID"])
        playerName = CommFunc.encode(dbPlayer["PlayerName"])
        
    dateMFPDict = {}
    needQueryCenterbak = CommFunc.loopMainServerDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc_AccIDMFPInfo,
                                                   parseLineFunc_AccIDMFPInfo, queryAccID, dateMFPDict)
    if needQueryCenterbak:
        argvDict["queryAccID"] = queryAccID
        bakDataList = CommFunc.queryBackupCenterDR(cfg, argvDict)
        if bakDataList == None:
            return
        bakMFPDict = bakDataList[0]
        bakMFPDict.update(dateMFPDict)
        dateMFPDict = bakMFPDict
    
    dateStrList = dateMFPDict.keys()
    dateStrList.sort(reverse=True)
    
    fightPower = None
    mfpDRList = []
    for dateStr in dateStrList:
        mfpDict = dateMFPDict[dateStr]
        parseUnknownMFP(mfpDict)
        if fightPower == None:
            fightPower = mfpDict["fightPower"]
        mfpDict["dateStr"] = dateStr
        mfpDict["fightPower"] = CommFunc.transformNum(mfpDict["fightPower"])
        mfpDRList.append(mfpDict)
        
    printStr = "<center><p>%s</p></center>" % _(u"战力模块")
    printStr += "%s: %s<br/>" % (_(u"玩家账号"), queryAccID)
    if playerName:
        printStr += "%s: %s<br/>" % (_(u"玩家名称"), playerName)
        
    if startDate:
        printStr += "%s: %s<br/>" % (_(u"开始日期"), startDate)
    if endDate:
        printStr += "%s: %s<br/>" % (_(u"结束日期"), endDate)
        
    # 表格输出        
    printStr += "=== %s ===<br/>" % _(u"战力分析记录")
    printStr += getMFPKVNameStr()
    
    printStr += "%s: %s<br/>" % (_(u"最近记录总战力"), fightPower)
    
    mfpTypeList = MFPNameDict.keys()
    mfpTypeList.sort()
    tdList = ["dateStr", "fightPower", "LV"] + mfpTypeList
    styleInfo = {}
    for mfpType in mfpTypeList:
        mfpTitle = MFPNameDict[mfpType]
        styleInfo[mfpType] = {"title":mfpTitle}
    styleInfo.update({"dateStr":{"title":_(u"日期")}, "fightPower":{"title":_(u"总战力")}})
    printStr += CommFunc.editTableHtml(mfpDRList, tdList, styleInfo=styleInfo)
    
    # 只会返回最后一个print的内容
    print printStr
    return
 
 
def queryAccIDMFPInfo_Centerbak(startDate, endDate, argvDict):
    queryAccID = argvDict.get("queryAccID")
    if not queryAccID:
        return CommFunc.queryBackupCenterError("queryAccID is none")
    
    dateMFPDict = {}
    if not CommFunc.loopCenterbakRarDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc_AccIDMFPInfo,
                                       parseLineFunc_AccIDMFPInfo, queryAccID, dateMFPDict):
        return
    
    return CommFunc.queryBackupCenterOK([dateMFPDict])
 
def checkDrFileNeedParseFunc_AccIDMFPInfo(drFileName, *parseArgs, **kv):
    ''' 检查流向是否需要处理
    @param drFileName: 流向文件名  xxx_日期.txt
    @param *parseArgs: 自定义参数
    @return: isNeed, checkNeedParseRetInfo
    '''
    isNeed = drFileName.startswith("LogInOut_")
    return isNeed, None
 
def parseLineFunc_AccIDMFPInfo(drName, dateStr, checkNeedParseRetInfo, line, *parseArgs, **kv):
    ''' 解析流向行内容
    @param drName: 流向名
    @param dateStr: 对应日期字符串
    @param checkNeedParseRetInfo: checkDrFileNeedParseFunc 返回的内容
    @param line: 本行内容
    @param *parseArgs: 自定义参数
    '''
    
    queryAccID, dateMFPDict = parseArgs
    
    if queryAccID not in line:
        return
    
    drDict = eval(line)
    if queryAccID != drDict["AccID"]:
        return
    fightPower = drDict["fightPower"]
    if dateStr in dateMFPDict:
        infoDict = dateMFPDict[dateStr]
        if infoDict["fightPower"] >= fightPower: # 每日只保留最高战力记录
            return
        
    infoDict = drDict["MFPFightPower"]
    infoDict["fightPower"] = fightPower
    infoDict["LV"] = drDict["LV"]
    dateMFPDict[dateStr] = infoDict
    return
 
## ---------------------------------------------------------------------------
 
def getMFPBillboard(argvDict):
    ## 查询战力排行榜
    
    startDate = argvDict.get("startDate", "")
    endDate = argvDict.get("endDate", "")
    topOrderCount = CommFunc.toInt(argvDict.get("maxOrder"), 10)
    
    # 查询中心备份的
    if CommFunc.isQueryCenterbak(argvDict):
        getMFPBillboard_Centerbak(startDate, endDate, argvDict)
        return
    
    # 以下榜单数据有一定延迟,非实时排行数据,存档时间5分钟
    # 1. 合并数据 - 战力榜
    dboper = DBOperate.DBOper(ServerPath)
    col = dboper.db["tagDBPlayer"]
    spec = {}
    fields = {'_id':0, "FightPower":1, "FightPowerEx":1, "PlayerName":1, "AccID":1, "LV":1}
    fightPowerRet = col.find(spec, fields).sort([("FightPowerEx", -1), ("FightPower", -1)]).limit(topOrderCount)
    fightPowerList = []
    for dataInfo in fightPowerRet:
        dataDict = {k:v for k, v in dataInfo.items()}
        dataDict["Name"] = dataInfo.pop("PlayerName", "")
        dataDict["fightPower"] = CommFunc.transformNum(dataInfo.pop("FightPowerEx", 0) * 100000000 + dataInfo.pop("FightPower", 0))
        fightPowerList.append(dataDict)
    
    # 2. 实际排行 - 战力
    col = dboper.db["tagDBBillboard"]
    spec = {"Type":0}
    fields = {'_id':0, "CmpValue":1, "CmpValue2":1, "Name1":1, "Name2":1}
    billboard_FightPowerRet = col.find(spec, fields).sort([("CmpValue", -1), ("CmpValue2", -1)]).limit(topOrderCount)
    billboard_FightPowerList = []
    for dataInfo in billboard_FightPowerRet:
        dataDict = {k:v for k, v in dataInfo.items()}
        dataDict["Name"] = dataInfo.pop("Name1", "")
        dataDict["AccID"] = dataInfo.pop("Name2", "")
        dataDict["fightPower"] = CommFunc.transformNum(dataInfo.pop("CmpValue", 0) * 100000000 + dataInfo.pop("CmpValue2", 0))
        billboard_FightPowerList.append(dataDict)
        
    # 关闭
    dboper.close()
    
    # 3. 流向战力排名
    accIDMFPDict = {}
    needQueryCenterbak = CommFunc.loopMainServerDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc_getMFPBillboard,
                                                   parseLineFunc_getMFPBillboard, accIDMFPDict)
    if needQueryCenterbak:
        bakDataList = CommFunc.queryBackupCenterDR(cfg, argvDict)
        if bakDataList == None:
            return
        bakAccIDMFPDict = bakDataList[0]
        for accID, infoDict in bakAccIDMFPDict.items():
            if accID not in accIDMFPDict:
                accIDMFPDict[accID] = infoDict # 备档正常情况下战力肯定比当前服流向记录的低,就不做高低验证,仅添加当前服流向没有的账号
    
    accIDFPInfoList = accIDMFPDict.values()
    accIDFPInfoList.sort(key=operator.itemgetter("fightPower"), reverse=True)
    accIDFPInfoList = accIDFPInfoList[:topOrderCount]
    
    for mfpDict in accIDFPInfoList:
        parseUnknownMFP(mfpDict)
        mfpDict["fightPower"] = CommFunc.transformNum(mfpDict["fightPower"])
            
    # 战力
    styleInfo = {"Name":{"title":_(u"玩家")}, "AccID":{"align":"right", "title":_(u"账号")},
                 "LV":{"title":_(u"等级")}, "fightPower":{"align":"right", "title":_(u"战斗力")}}
    
    printStr = "<center><p>%s</p></center>" % _(u"战力排行")
    printStr += "%s<br/>" % _(u"以下排行榜非实时数据")
    printStr += "<br/>%s,<font color='red'>%s</font>:<br/>" % (_(u"所有角色战力排行"), _(u"包含合服后未登录的账号"))
    tdList = ["Name", "AccID", "LV", "fightPower"]
    printStr += CommFunc.editTableHtml(fightPowerList, tdList, _(u"排名"), styleInfo=styleInfo)
    
    printStr += "<br/>--------------------------------------------------------------------------<br/>"
    printStr += "<br/>%s,<font color='red'>%s</font>:<br/>" % (_(u"活跃角色战力排行"), _(u"仅包含合服后登录的账号"))
    tdList = ["Name", "AccID", "fightPower"]
    printStr += CommFunc.editTableHtml(billboard_FightPowerList, tdList, _(u"排名"), styleInfo=styleInfo)
    
    printStr += "<br/>--------------------------------------------------------------------------<br/>"
    printStr += getMFPKVNameStr()
    
    printStr += "%s:<br/>" % _(u"查询时间范围内<font color='red'>有登录/登出流向</font>的账号战力明细排行")
    if startDate:
        printStr += "%s: %s<br/>" % (_(u"开始日期"), startDate)
    if endDate:
        printStr += "%s: %s<br/>" % (_(u"结束日期"), endDate)
        
    mfpTypeList = MFPNameDict.keys()
    mfpTypeList.sort()
    tdList = ["Name", "AccID", "LV", "fightPower"] + mfpTypeList
    for mfpType in mfpTypeList:
        mfpTitle = MFPNameDict[mfpType]
        styleInfo[mfpType] = {"align":"right", "title":mfpTitle}
    printStr += CommFunc.editTableHtml(accIDFPInfoList, tdList, _(u"排名"), styleInfo=styleInfo)
    printStr += "<br/>--------------------------------------------------------------------------<br/>"
    
    print printStr
    return
 
def getMFPBillboard_Centerbak(startDate, endDate, argvDict):
    accIDMFPDict = {}
    if not CommFunc.loopCenterbakRarDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc_getMFPBillboard,
                                       parseLineFunc_getMFPBillboard, accIDMFPDict):
        return
    
    return CommFunc.queryBackupCenterOK([accIDMFPDict])
 
def checkDrFileNeedParseFunc_getMFPBillboard(drFileName, *parseArgs, **kv):
    ''' 检查流向是否需要处理
    @param drFileName: 流向文件名  xxx_日期.txt
    @param *parseArgs: 自定义参数
    @return: isNeed, checkNeedParseRetInfo
    '''
    isNeed = drFileName.startswith("LogInOut_")
    return isNeed, None
 
def parseLineFunc_getMFPBillboard(drName, dateStr, checkNeedParseRetInfo, line, *parseArgs, **kv):
    ''' 解析流向行内容
    @param drName: 流向名
    @param dateStr: 对应日期字符串
    @param checkNeedParseRetInfo: checkDrFileNeedParseFunc 返回的内容
    @param line: 本行内容
    @param *parseArgs: 自定义参数
    '''
    
    accIDMFPDict = parseArgs[0]
    
    drDict = eval(line)
    accID = drDict["AccID"]
    fightPower = drDict["fightPower"]
    
    if accID in accIDMFPDict:
        infoDict = accIDMFPDict[accID]
        if infoDict["fightPower"] >= fightPower: # 排名只保留每个账号的最高战力记录
            return
        
    infoDict = drDict["MFPFightPower"]
    infoDict["fightPower"] = fightPower
    infoDict["AccID"] = accID
    infoDict["Name"] = drDict["Name"]
    infoDict["LV"] = drDict["LV"]
    accIDMFPDict[accID] = infoDict
    return
 
def main():
    CommFunc.setdefaultencoding()
    argvDict = CommFunc.parse_args()
    mylog.InitMyLog(argvDict.get("eventType", ""))
    CommFunc.gettextInstall(argvDict.get("lang", ""))
    initMFPTNameDict()
    playerFind = argvDict.get("playerFind", "")
    if playerFind != "":
        queryAccIDMFPInfo(argvDict)
    else:
        getMFPBillboard(argvDict)
    return
 
if __name__ == "__main__":
    try:
        main()
    except:
        CommFunc.printExceptionError()