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
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @todo: CTGOK排行
 
import CommFunc
import ConfigParser
import DBOperate
 
import operator
import logging
import mylog
#==================== 配置 ====================
cfg = ConfigParser.ConfigParser()
cfg.read("../../InterfaceConfig.php")
ServerPath = cfg.get("ServerInfo", "ServerPath")
 
# 获取字段key列表,  [[key, 是否累加], ...], 最终的内容会按照配置的字段值导出, 如果空则全部导出
KeyList = [["AccID", False], ["PlayerID", False], ["orderCoin", True], ["orderMoneyType", False], ["orderMoneyValue", True]]
# 根据什么字段名统计累加
PKKey = "AccID"
 
# 过滤设定, {过滤key:[过滤值列表], ...}, 即会过滤掉对应key为某些值的内容
Filter_Set = {"eventName":[1003, "GMTCTG"]}
 
# 匹配设定, {匹配key:[匹配值列表], ...}, 即只会匹配对应key为指定值的内容
# coinType: 0-直充;1-直购;2-道具;4-现金点;6-代币转换;7-代币充值
Match_Set = {"coinType":[0, 1, 7]}
#==================== 配置 ====================
 
# 支付订单支持类型 1-人民币;2-美元;3-越南盾;4-soha币; 5-使用订单价值对应货币支付
DefaultOrderType = 1 # 默认人民币
PayByMoneyOrderTypeList = [5] # 使用游戏货币支付的订单类型
OnlyServerID = 0
 
class ValueObj():
    def __init__(self):
        return
    
def getCTGOKSumInfo(argvDict):
    ## 统计所有玩家充值累加
    global OnlyServerID
    
    startDate = argvDict.get("startDate", "")
    endDate = argvDict.get("endDate", "")
    OnlyServerID = CommFunc.toInt(argvDict.get("OnlyServerID", "0"))
    logging.info("OnlyServerID:%s" % OnlyServerID)
 
    # 查询中心备份的
    if CommFunc.isQueryCenterbak(argvDict):
        getCTGOKSumInfo_Centerbak(startDate, endDate, argvDict)
        return
    
    showSumInfoDict = getShowSumInfoDict(argvDict)
    
    needQueryCenterbak = CommFunc.loopMainServerDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc_CtgOKSum,
                                                   parseLineFunc_CtgOKSum, showSumInfoDict, argvDict)
    if needQueryCenterbak:
        showSumInfoDictBak = CommFunc.queryBackupCenterDR(cfg, argvDict)
        if showSumInfoDictBak == None:
            return
        for payOrderTypeStr, sumInfoDictBak in showSumInfoDictBak.items():
            sumInfoDict = showSumInfoDict[int(payOrderTypeStr)]
            
            for pkValue, bakData in sumInfoDictBak.items():
                if pkValue not in sumInfoDict:
                    sumInfoDict[pkValue] = ValueObj()
                vObj = sumInfoDict[pkValue]
                
                for key, isSum in KeyList:
                    if isSum:
                        value = getattr(vObj, key, 0) + bakData.get(key, 0)
                    else:
                        value = bakData.get(key, "")
                    setattr(vObj, key, value)
                    
    maxOrder = CommFunc.toInt(argvDict.get("maxOrder"), 10)
    # 排序
    accIDList = []
    showSumInfoSortDict = {}
    for payOrderType, sumInfoDict in showSumInfoDict.items():
        sortList = sumInfoDict.values()
        if payOrderType in PayByMoneyOrderTypeList:
            sortList.sort(key=operator.attrgetter("orderMoneyValue"), reverse=True)
        else:
            sortList.sort(key=operator.attrgetter("orderCoin"), reverse=True)
        if maxOrder and len(sortList) > maxOrder:
            sortList = sortList[:maxOrder]
        
        for vObj in sortList:
            if payOrderType in PayByMoneyOrderTypeList:
                orderValue = getattr(vObj, "orderMoneyValue", 0)
            else:
                orderValue = CommFunc.coinToY(getattr(vObj, "orderCoin", 0), CommFunc.getPayOrderCoinRate(payOrderType))
            setattr(vObj, "orderValue", orderValue)
            
            accID = getattr(vObj, PKKey)
            if accID not in accIDList:
                accIDList.append(accID)
                
        showSumInfoSortDict[payOrderType] = sortList
        
    if accIDList:
        dboper = DBOperate.DBOper(ServerPath)
        findDBRet = dboper.findPlayerInfoByAccID(accIDList)
        dboper.close()
        dbPlayerInfo = {}
        for dbPlayer in findDBRet:
            accID = dbPlayer["AccID"]
            dbPlayerInfo[accID] = dbPlayer
            
        for vObjList in showSumInfoSortDict.values():
            for vObj in vObjList:
                accID = getattr(vObj, PKKey)
                if accID not in dbPlayerInfo:
                    continue
                dbPlayer = dbPlayerInfo[accID]
                setattr(vObj, "PlayerID", dbPlayer["PlayerID"])
                setattr(vObj, "PlayerName", dbPlayer["PlayerName"])
                
    printStr = "<center><p>" + _(u"充值排行") + "</p></center>"
    if startDate:
        printStr += _(u"开始日期") + ": %s<br/>" % startDate;
    if endDate:
        printStr += _(u"结束日期") + ": %s<br/>" % endDate;
        
    if argvDict.get("ItemCTG"):
        printStr += _(u"包含道具充值") + "<br/>"
    else:
        printStr += _(u"不含道具充值") + "<br/>"
        
    if argvDict.get("BuyOrderInfo"):
        printStr += _(u"包含货币购买") + "<br/>"
    else:
        printStr += _(u"不含货币购买") + "<br/>"
              
    if argvDict.get("GMCTG"):
        printStr += _(u"包含后台充值") + "<br/>"
    else:
        printStr += _(u"不含后台充值") + "<br/>"  
        
    if argvDict.get("ExchangePayCoin"):
        printStr += _(u"包含代币转换") + "<br/>"
    else:
        printStr += _(u"不含代币转换") + "<br/>"  
 
    # 表格输出
    for payOrderType, vObjList in showSumInfoSortDict.items():
        printStr += "<hr/>"
        orderTypeName = CommFunc.getPayOrderTypeName(payOrderType)
        printStr += "=== 【%s】支付%s ===<br/>" % (orderTypeName, _(u"充值排行"))
        if not vObjList:
            continue
        printStr += CommFunc.editTableHtml(vObjList, ["AccID", "PlayerID", "PlayerName", "orderValue"], _(u"排名"),
                                           styleInfo={"AccID":{"align":"left", "title":_(u"账号")},
                                                      "PlayerID":{"align":"left", "title":_(u"玩家ID")},
                                                      "PlayerName":{"align":"left", "title":_(u"玩家名")},
                                                      "orderValue":{"align":"right", "title":orderTypeName},
                                                      })
        
    # 只会返回最后一个print的内容
    print printStr
    return
 
def getShowSumInfoDict(argvDict):
    showSumInfoDict = {} # {payOrderType:{accID:obj, ...}}
    for payOrderType in range(1, 10):
        if "payOrderType%s" % payOrderType in argvDict:
            showSumInfoDict[payOrderType] = {}
    if not showSumInfoDict:
            showSumInfoDict[DefaultOrderType] = {} # 默认只显示人民币
    return showSumInfoDict
 
def getCTGOKSumInfo_Centerbak(startDate, endDate, argvDict):
    ## 查询中心服务器备份充值信息
    showSumInfoDict = getShowSumInfoDict(argvDict)
    if not CommFunc.loopCenterbakRarDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc_CtgOKSum,
                                       parseLineFunc_CtgOKSum, showSumInfoDict, argvDict):
        return
    return CommFunc.queryBackupCenterOK(showSumInfoDict)
 
def checkDrFileNeedParseFunc_CtgOKSum(drFileName, *parseArgs, **kv):
    ''' 检查流向是否需要处理
    @param drFileName: 流向文件名  xxx_日期.txt
    @param *parseArgs: 自定义参数
    @return: isNeed, checkNeedParseRetInfo
    '''
    isNeed = drFileName.startswith("CTGOK_")
    return isNeed, None
 
def parseLineFunc_CtgOKSum(drName, dateStr, checkNeedParseRetInfo, line, *parseArgs, **kv):
    ''' 解析流向行内容
    @param drName: 流向名
    @param dateStr: 对应日期字符串
    @param checkNeedParseRetInfo: checkDrFileNeedParseFunc 返回的内容
    @param line: 本行内容
    @param *parseArgs: 自定义参数
    '''
    
    showSumInfoDict, argvDict = parseArgs
    
    drDict = eval(line)
 
    if not checkDRNeed(drDict, argvDict):
        return
 
    if PKKey not in drDict:
        return
    
    payOrderType = drDict.get("payOrderType", DefaultOrderType)
    if payOrderType not in showSumInfoDict:
        return
    sumInfoDict = showSumInfoDict[payOrderType]
    
    pkValue = drDict[PKKey]
    if OnlyServerID:
        serverID = CommFunc.getServerID(pkValue)
        if CommFunc.getServerID(pkValue) != OnlyServerID:
            # logging.info("OnlyServerID:%s, 不统计 %s" % (OnlyServerID, pkValue))
            return
 
    if pkValue not in sumInfoDict:
        sumInfoDict[pkValue] = ValueObj()
    vObj = sumInfoDict[pkValue]
    
    for key, isSum in KeyList:
        if key not in drDict:
            continue
        if isSum:
            value = getattr(vObj, key, 0) + drDict.get(key, 0)
        else:
            value = drDict.get(key, "")
        setattr(vObj, key, value)
    return
 
##=================================================================================================
def checkDRNeed(drDict, argvDict):
    ## 通用检查该流向是否需要
 
    noCheckRealCTGPayTypeList = [5, 6] # 5-金票支付 6-代币支付
    payOrderType = drDict.get("payOrderType", DefaultOrderType)
 
    matchSet, filterSet = {}, {}
 
    if not argvDict.get("ItemCTG") and not argvDict.get("GMCTG") and not argvDict.get("BuyOrderInfo"):
        if payOrderType not in noCheckRealCTGPayTypeList and not IsRealCTG(drDict):
            return
 
    coinTypeList = [0, 1, 7] # 0-直充;1-直购;2-道具;4-现金点;6-代币转换;7-代币充值
    if argvDict.get("ItemCTG"):
        coinTypeList.append(2)
    if argvDict.get("BuyOrderInfo"):
        coinTypeList.append(4)
    if argvDict.get("ExchangePayCoin"):
        coinTypeList.append(6)
    matchSet["coinType"] = coinTypeList
    
    if not argvDict.get("GMCTG"):
        if drDict["coinType"] in [0, 1, 7] and payOrderType not in noCheckRealCTGPayTypeList and not IsRealCTG(drDict):
            return
        filterSet["eventName"] = [1003, "GMTCTG"] # 排除GM充值的事件类型   
 
    if not CommFunc.matchDr(drDict, matchSet, filterSet):
        return
 
    return True
 
def queryAccIDCTGInfo(argvDict):
    ## 查询个人充值记录
    
    startDate = argvDict.get("startDate", "")
    endDate = argvDict.get("endDate", "")
    queryType = argvDict.get("queryType", "")
    playerFind = argvDict.get("playerFind", "")
    
    # 查询中心备份的
    if CommFunc.isQueryCenterbak(argvDict):
        queryAccIDCTGInfo_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 _(u"找不到该玩家") + "!<br/>%s<br/>" % playerFind
            return
        
        dbPlayer = findDBRet[0]
        queryAccID = CommFunc.encode(dbPlayer["AccID"])
        playerName = CommFunc.encode(dbPlayer["PlayerName"])
        
    ctgOKList = []
    ctgErrorList = []
    
    needQueryCenterbak = CommFunc.loopMainServerDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc_AccIDCTGInfo,
                                                   parseLineFunc_AccIDCTGInfo, queryAccID, ctgOKList, ctgErrorList, argvDict)
    if needQueryCenterbak:
        argvDict["queryAccID"] = queryAccID
        bakDataList = CommFunc.queryBackupCenterDR(cfg, argvDict)
        if bakDataList == None:
            return
        ctgOKList = bakDataList[0] + ctgOKList
        ctgErrorList = bakDataList[1] + ctgErrorList
        
    showOKOrderInfo, showErrOrderInfo = {}, {}
    for payOrderType in range(1, 10):
        if "payOrderType%s" % payOrderType in argvDict:
            showOKOrderInfo[payOrderType] = {}
            showErrOrderInfo[payOrderType] = {}
    if not showOKOrderInfo:
        showOKOrderInfo[DefaultOrderType] = {} # 默认只显示人民币
        showErrOrderInfo[DefaultOrderType] = {} # 默认只显示人民币
        
    # 成功订单
    for drDict in ctgOKList:
        # {"orderCoin":orderCoin, "payOrderType":payOrderType, "orderMoneyType":orderMoneyType, "orderMoneyValue":orderMoneyValue}
        payOrderType = drDict.get("payOrderType", DefaultOrderType)
        if payOrderType not in showOKOrderInfo:
            continue
        showInfo = showOKOrderInfo[payOrderType]
        
        if payOrderType in PayByMoneyOrderTypeList:
            orderValue = drDict["orderMoneyValue"]
            drDict["orderValue"] = orderValue
        else:
            orderValue = drDict["orderCoin"]
            drDict["orderValue"] = CommFunc.coinToY(orderValue, CommFunc.getPayOrderCoinRate(payOrderType))
        drList = showInfo.get("drList", [])
        drList.append(drDict)
        showInfo["drList"] = drList
        showInfo["orderValueTotal"] = showInfo.get("orderValueTotal", 0) + orderValue
    for payOrderType, showInfo in showOKOrderInfo.items():
        if showInfo and payOrderType not in PayByMoneyOrderTypeList:
            showInfo["orderValueTotal"] = CommFunc.coinToY(showInfo["orderValueTotal"], CommFunc.getPayOrderCoinRate(payOrderType))
            
    # 失败订单
    for drDict in ctgErrorList:
        payOrderType = drDict.get("payOrderType", DefaultOrderType)
        if payOrderType not in showErrOrderInfo:
            continue
        showInfo = showErrOrderInfo[payOrderType]
 
        if payOrderType in PayByMoneyOrderTypeList:
            orderValue = drDict["orderMoneyValue"]
            drDict["orderValue"] = orderValue
        else:
            orderValue = drDict["orderCoin"]
            drDict["orderValue"] = CommFunc.coinToY(orderValue, CommFunc.getPayOrderCoinRate(payOrderType))
        drList = showInfo.get("drList", [])
        drList.append(drDict)
        showInfo["drList"] = drList
        showInfo["orderValueTotal"] = showInfo.get("orderValueTotal", 0) + orderValue
    for payOrderType, showInfo in showErrOrderInfo.items():
        if showInfo and payOrderType not in PayByMoneyOrderTypeList:
            showInfo["orderValueTotal"] = CommFunc.coinToY(showInfo["orderValueTotal"], CommFunc.getPayOrderCoinRate(payOrderType))
            
    # 玩家名
    if not playerName and ctgOKList:
        lastDict = ctgOKList[-1]
        playerName = lastDict.get("PlayerName", "")
        
    printStr = "<center><p>" + _(u"充值记录") + "</p></center>"
    printStr += _(u"玩家账号") + ": %s<br/>" % queryAccID;
    if playerName:
        printStr += _(u"玩家名称") + ": %s<br/>" % playerName;
        
    if startDate:
        printStr += _(u"开始日期") + ": %s<br/>" % startDate;
    if endDate:
        printStr += _(u"结束日期") + ": %s<br/>" % endDate;
        
    if argvDict.get("ItemCTG"):
        printStr += _(u"包含道具充值") + "<br/>"
    else:
        printStr += _(u"不含道具充值") + "<br/>"
        
    if argvDict.get("BuyOrderInfo"):
        printStr += _(u"包含货币购买") + "<br/>"
    else:
        printStr += _(u"不含货币购买") + "<br/>"
        
    if argvDict.get("GMCTG"):
        printStr += _(u"包含后台充值") + "<br/>"
    else:
        printStr += _(u"不含后台充值") + "<br/>"
        
    if argvDict.get("ExchangePayCoin"):
        printStr += _(u"包含代币转换") + "<br/>"
    else:
        printStr += _(u"不含代币转换") + "<br/>"
        
    printStr += "coinType: %s" % _(u"0-直充;1-直购;6-代币转换;7-代币充值") + "<br/>"
    
    # 表格输出
    for payOrderType, showInfo in showErrOrderInfo.items():
        if not showInfo:
            continue
        printStr += "<hr/>"
        orderTypeName = CommFunc.getPayOrderTypeName(payOrderType)
        orderValueTotal = showInfo["orderValueTotal"]
        drList = showInfo["drList"]
        
        printStr += "=== 【%s】%s ===<br/>" % (orderTypeName, _(u"充值失败到账记录"));
        printStr += "%s: %s %s<br/>" % (_(u"充值失败到账总额度"), orderValueTotal, orderTypeName);
        printStr += CommFunc.editTableHtml(drList, ["appID", "orderInfo", "orderValue", "eventName", "ErrorInfo", "time", "orderID"], _(u"编号"),
                                           styleInfo={"orderInfo":{"align":"left", "title":_(u"商品编号")},
                                                      "orderValue":{"align":"right", "title":orderTypeName},
                                                      "ErrorInfo":{"align":"left", "title":_(u"错误信息")},
                                                      })
        
    for payOrderType, showInfo in showOKOrderInfo.items():
        printStr += "<hr/>"
        orderTypeName = CommFunc.getPayOrderTypeName(payOrderType)
        printStr += "=== 【%s】支付%s ===<br/>" % (orderTypeName, _(u"充值成功到账记录"));
        if not showInfo:
            continue
        orderValueTotal = showInfo["orderValueTotal"]
        drList = showInfo["drList"]
        printStr += "支付%s: %s %s<br/>" % (_(u"充值成功到账总额度"), orderValueTotal, orderTypeName);
        printStr += CommFunc.editTableHtml(drList, ["appID", "orderInfo", "orderValue", "eventName", "coinType", "time", "orderID", "ServerDay", "VIPLv"], _(u"编号"),
                                           styleInfo={"orderInfo":{"align":"left", "title":_(u"商品编号")},
                                                      "orderValue":{"align":"right", "title":orderTypeName},
                                                      "ServerDay":{"title":_(u"开服天")},
                                                      "VIPLv":{"title":_(u"VIP等级")},
                                                      })
        
    # 只会返回最后一个print的内容
    print printStr
    return
 
def queryAccIDCTGInfo_Centerbak(startDate, endDate, argvDict):
    queryAccID = argvDict.get("queryAccID")
    if not queryAccID:
        return CommFunc.queryBackupCenterError("queryAccID is none")
    
    ctgOKList = []
    ctgErrorList = []
    if not CommFunc.loopCenterbakRarDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc_AccIDCTGInfo,
                                       parseLineFunc_AccIDCTGInfo, queryAccID, ctgOKList, ctgErrorList, argvDict):
        return
    return CommFunc.queryBackupCenterOK([ctgOKList, ctgErrorList])
 
def checkDrFileNeedParseFunc_AccIDCTGInfo(drFileName, *parseArgs, **kv):
    ''' 检查流向是否需要处理
    @param drFileName: 流向文件名  xxx_日期.txt
    @param *parseArgs: 自定义参数
    @return: isNeed, checkNeedParseRetInfo
    '''
    isNeed = (drFileName.startswith("CTGOK_") or drFileName.startswith("CTGError_"))
    return isNeed, None
 
def parseLineFunc_AccIDCTGInfo(drName, dateStr, checkNeedParseRetInfo, line, *parseArgs, **kv):
    ''' 解析流向行内容
    @param drName: 流向名
    @param dateStr: 对应日期字符串
    @param checkNeedParseRetInfo: checkDrFileNeedParseFunc 返回的内容
    @param line: 本行内容
    @param *parseArgs: 自定义参数
    '''
    
    queryAccID, ctgOKList, ctgErrorList, argvDict = parseArgs
    
    if queryAccID not in line:
        return
    
    drDict = eval(line)
    if queryAccID != drDict["AccID"]:
        return
    
    drKeyList = ["appID", "orderInfo", "orderCoin", "eventName", "coinType", "time", "orderID", "ServerDay", "VIPLv", "payOrderType", "orderMoneyType", "orderMoneyValue", "ErrorInfo", "PlayerName"]
    if drName.startswith("CTGError"):
        dDict = {}
        for key in drKeyList:
            if key in drDict:
                dDict[key] = drDict[key]
        ctgErrorList.append(dDict)
        return
        
    if not checkDRNeed(drDict, argvDict):
        return
    
    if drName.startswith("CTGOK"):
        dDict = {}
        for key in drKeyList:
            if key in drDict:
                dDict[key] = drDict[key]
        ctgOKList.append(dDict)
        
    return
 
def IsRealCTG(drDict):
    ## 是否真实充值订单,真实充值订单一定有 orderID
    if not drDict.get('orderID'):
        return False
    return True
 
def main():
    CommFunc.setdefaultencoding()
    argvDict = CommFunc.parse_args()
    mylog.InitMyLog(argvDict.get("eventType", ""))
    CommFunc.gettextInstall(argvDict.get("lang", ""))
    playerFind = argvDict.get("playerFind", "")
    if playerFind != "":
        queryAccIDCTGInfo(argvDict)
    else:
        getCTGOKSumInfo(argvDict)
    return
 
if __name__ == "__main__":
    try:
        main()
    except:
        CommFunc.printExceptionError()