forked from Quakecon/qldemo-python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
qldemosummary.py
125 lines (107 loc) · 5.59 KB
/
qldemosummary.py
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
#!/bin/env python
## qldemo2json.py
## Shawn Nock, 2014
import argparse
import json
import os
import sys
import time
from qldemo import QLDemo, gametype_to_string
from qldemo.data import GameState, Snapshot
from qldemo.constants import userinfo_map, GT_TEAM, TEAM_STRING_MAP
## Configuration ##
URL_PREFIX='/demos/'
playerinfo_override = {'n': 'name', ## The userInfo_t summary in
'cn': 'clan', ## CS_PLAYER[MAX_PLAYERS] has short
'xcn': 'xclan', ## hard to decipher names. Any map
'w': 'wins', ## here will override the name
'l': 'losses',
't': 'team'}
### END Configuration
def main():
parser = argparse.ArgumentParser(
description='Summarize, in JSON a QuakeLive Demo File (dm_73)')
parser.add_argument('file',
help='path of the dm_73 file to summarize')
args = parser.parse_args()
d = QLDemo(args.file)
list(d)
## Munge playerInfo to conform to ColonelPanic's Needs
for clientNum, player in d.gamestate.players.items():
for key, value in player.items():
new_name=playerinfo_override.get(key, None)
if new_name:
player[new_name]=player[key]
del(player[key])
# If it's a game where teams make sense, translate the teamId into a team name
if int(d.gamestate.config['serverinfo']['g_gametype']) >= GT_TEAM and 'team' in player:
player['team']=TEAM_STRING_MAP[player['team']]
if int(d.gamestate.config['serverinfo']['g_gametype']) >= GT_TEAM and 't' in player:
player['team']=TEAM_STRING_MAP[player['t']]
# Calculate demo duration
## FIXME - I think serverTime is in msec, but it is a guess based
## on a skim of the Q3A source. It'd be nice to verify
first_snap=None
last_snap=None
for i in d.packets:
if i.__class__ is Snapshot:
first_snap=i
break
for i in range(-1,-10,-1):
if d.packets[i].__class__ is Snapshot:
last_snap=d.packets[i]
break
if first_snap and last_snap:
duration = (last_snap.serverTime - first_snap.serverTime) / 1000
else:
duration = None
output = {'filename': args.file.split(os.sep)[-1],
'gametype': gametype_to_string(
d.gamestate.config['serverinfo']['g_gametype']),
'players': d.gamestate.players,
'size': os.stat(args.file).st_size,
'pov': d.gamestate.clientNum,
'timestamp': time.ctime(float(d.gamestate.config['serverinfo']['g_levelStartTime'])),
'mapname': d.gamestate.config['serverinfo']['mapname'],
'duration': duration,
'server': {'hostname': d.gamestate.config['serverinfo']['sv_hostname'],
'location': d.gamestate.config['serverinfo']['sv_location'] if 'sv_location' in d.gamestate.config['serverinfo'] else None},
'practice': True if d.gamestate.config['serverinfo']['sv_hostname'].startswith('Practice') else False
}
#output['scores'] = d.scores[-1] if d.scores else {}
output['scores'] = {}
if int(d.gamestate.config['serverinfo']['g_gametype']) >= GT_TEAM:
output['scores']['TEAM_RED'] = {}
output['scores']['TEAM_BLUE'] = {}
output['scores']['TEAM_RED']['score'] = d.gamestate.config['scores1'].strip('"')
output['scores']['TEAM_BLUE']['score'] = d.gamestate.config['scores2'].strip('"')
else:
if not d.gamestate.config['1stplayer'] in output['scores']:
output['scores'][d.gamestate.config['1stplayer']] = {}
if not d.gamestate.config['2ndplayer'] in output['scores']:
output['scores'][d.gamestate.config['2ndplayer']] = {}
output['scores'][d.gamestate.config['1stplayer']]['score'] = d.gamestate.config['scores1'].strip('"')
output['scores'][d.gamestate.config['2ndplayer']]['score'] = d.gamestate.config['scores2'].strip('"')
victor = d.gamestate.config['1stplayer'] if int(output['scores'][d.gamestate.config['1stplayer']]['score']) > int(output['scores'][d.gamestate.config['2ndplayer']]['score']) else None
victor = d.gamestate.config['2ndplayer'] if int(output['scores'][d.gamestate.config['2ndplayer']]['score']) > int(output['scores'][d.gamestate.config['1stplayer']]['score']) else victor
output['victor'] = victor
if int(d.gamestate.config['serverinfo']['g_gametype']) >= GT_TEAM:
output['teams'] = {}
for team in ['TEAM_RED','TEAM_BLUE']:
short = team.split('_')[1].lower()
output['teams'][team] = {}
output['teams'][team]['name'] = d.gamestate.config[short+'teamname'] if short+'teamname' in d.gamestate.config else None
output['teams'][team]['clan'] = d.gamestate.config[short+'teamclantag'] if short+'teamclantag' in d.gamestate.config else None
output['teams'][team]['timeouts_left'] = d.gamestate.config['timeouts_'+short] if 'timeouts_'+short in d.gamestate.config else None
output['teams'][team]['score'] = output['scores'][team]['score']
victor = 'TEAM_RED' if int(output['scores']['TEAM_RED']['score']) > int(output['scores']['TEAM_BLUE']['score']) else None
victor = 'TEAM_BLUE' if int(output['scores']['TEAM_BLUE']['score']) > int(output['scores']['TEAM_RED']['score']) else victor
output['victor'] = victor
json.dump(output,
sys.stdout,
ensure_ascii=False,
indent=2,
sort_keys=True)
return 0
if __name__ == '__main__':
main()