CODE#!/usr/bin/python
from __future__ import division
from xml.dom.minidom import parse
import time
class nick(unicode):
def detokenize(self):
output = self[:]
# output = output.replace("*", "Squad Leader ")
# output = output.replace("^", "Assistant Squad Leader ")
# output = output.replace("+", "Zone Leader ")
# output = output.replace("$", "Hacker Extraordinaire ")
return output
def tag(self):
if '@' not in self:
return None
else:
atPos = str.index('@')
return self[atPos:]
class Player(object):
def __init__(self, xmlPlayer, _teamNo_):
readTag = (lambda x: xmlPlayer.getElementsByTagName(x)[0].firstChild.data)
self.name = nick(readTag("Name"))
self.isCommander = (readTag("IsCommander") == "true")
self.rank = int(readTag("Rank"))
self.assists = int(readTag("Assists"))
self.baseCaptures = int(readTag("BaseCaptures"))
self.baseKills = int(readTag("BaseKills"))
self.deaths = int(readTag("Deaths"))
self.ejects = int(readTag("Ejections"))
self.kills = int(readTag("Kills"))
self.score = float(readTag("Score"))
self.timePlayed = int(float(readTag("TimePlayed")))
self.killsperhr = 3600 * self.kills / self.timePlayed
self.pointsperhr = 3600 * self.score / self.timePlayed
self._teamNo_ = _teamNo_
def __repr__(self):
return "<player %s(%d)>" % (
self.name,
self.rank,
)
def __str__(self):
return """%-28s %24s.
Kills: %3d. Ejects: %3d. Base kills: %3d.
Assists: %3d. Deaths: %3d. Base captures: %3d.
""" % \
((self.isCommander and "Commander " or "Pilot ") + self.name.detokenize(),
"%d points in %s" % (self.score, strTime(self.timePlayed)),
self.kills, self.ejects, self.baseKills,
self.assists, self.deaths, self.baseCaptures,
)
class Team(object):
def __init__(self, xmlTeam, xmlPlayers):
readTag = (lambda x: xmlTeam.getElementsByTagName(x)[0].firstChild.data)
self.faction = readTag("Faction")
self._teamNo_ = readTag("TeamNumber")
try:
self.name = readTag("Name")
except:
self.name = "Anonymous Cowards %d" % (int(self._teamNo_)+1)
self.players = [Player(item, self._teamNo_) for item in xmlPlayers]
self.heloSum = sum([player.score for player in self.players])
def __repr__(self):
return "<%s team %s (%d players)>" % (
self.faction.lower(),
self.name.lower(),
len(self.players)
)
def __str__(self):
return "%s team \"%s\": %s" % (self.faction, self.name, _(self.players))
def __getitem__(self, x): return self.players[x]
def __len__(self):
return max([player.timePlayed for player in self.players])
def most(self, what):
maxStat = max([getattr(player, what) for player in self.players])
#Special case
if (maxStat == 0) and (what == "ejects"):
return self.most("deaths")
return (maxStat, [player for player in self.players if getattr(player, what) == maxStat])
def commanders(self):
return [player for player in self.players if player.isCommander]
class Game(object):
def __init__(self, xmlGame):
'''Create a game object from an Allegiance xml scores file.'''
readTag = (lambda x: xmlGame.getElementsByTagName(x)[0].firstChild.data)
self.time = time.strptime(readTag("Date"), "%m/%d/%y %H:%M:%S")
self.server = readTag("Server")
self.core = readTag("Core")
self.reason = readTag("GameOverReason") #.replace(" Adv ", " Advanced ")
self.teams = []
xmlPlayers = xmlGame.getElementsByTagName("PlayerScore")
teamNo = (lambda x: x.getElementsByTagName("TeamNumber")[0].firstChild.data)
#Works both for teams and players. Woot!
for xmlTeam in xmlGame.getElementsByTagName("Team"):
teamPlayers = [xmlFoo for xmlFoo in xmlPlayers if teamNo(xmlTeam) == teamNo(xmlFoo)]
self.teams.append(Team(xmlTeam, teamPlayers))
def __repr__(self):
return "<%s game (%s, %d teams)>" % (
self.server,
time.strftime("%a %b %d %H:%M:%S %Y", self.time),
len(self.teams)
)
def __len__(self):
#No direct way to compute this, that I know of.
#Solution:
return max(map(len, self.teams))
def __getitem__(self, x):
return self.teams[x]
def most(self, what):
teamTopGuns = [team.most(what) for team in self.teams]
maxStat = max([item[0] for item in teamTopGuns])
topGuns = []
topGuns.extend([item[1][0] for item in teamTopGuns if item[0] == maxStat])
return (maxStat, topGuns)
def parseGameData(filename):
document = parse(open(filename))
thisGame = Game(document)
return thisGame
def strTime(seconds):
minute = (seconds // 60) % 60
hour = (seconds // 3600) % 60
second = (seconds) % 60
output = u""
showSeconds = False
if hour:
pluralS = (hour == 1) and ("hour") or ("hours")
output += u"%d %s " % (hour, pluralS)
else:
showSeconds = True
if minute:
pluralS = (minute == 1) and ("minute") or ("minutes")
output += u"%d %s " % (minute, pluralS)
else:
showSeconds = True
if second and showSeconds:
pluralS = (second == 1) and ("second") or ("seconds")
output += u"%d %s " % (second, pluralS)
if output == u"":
return "%d seconds" % seconds
else:
return output.strip()
def sortPlayers(x, y):
if x.isCommander != y.isCommander:
if x.isCommander: return -1
else: return 1
else:
timeFactor = -cmp(x.timePlayed, y.timePlayed)
if timeFactor: return timeFactor
return -cmp(x.score, y.score)
def _(players):
players.sort(sortPlayers)
players = [player.name.detokenize() for player in players]
return ", ".join(players)
if __name__ == '__main__':
#usage: python -i allegXMLreader.py
import sys
filename = sys.argv[1]
thisGame = parseGameData(filename)
print u"%s." % time.strftime("%A, %B %d %Y", thisGame.time)
teamNames = [team.name for team in thisGame.teams]
print u" versus ".join(teamNames) + "."
if "--top" in sys.argv:
for team in thisGame.teams:
topGuns = team.most("kills")
topPoints = team.most("score")
topPods = team.most("ejects")
print """%s, commanded team "%s" (%s).
Top kills: %s with %d.
Top ejects: %s with %d.
Top points: %s with %d.""" % \
(_(team.commanders()), team.name, team.faction,
_(topGuns[1]), topGuns[0],
_(topPods[1]), topPods[0],
_(topPoints[1]), topPoints[0],
)
print u"After %s, %s" % (strTime(len(thisGame)), thisGame.reason)
if "--players" in sys.argv:
for team in thisGame.teams:
print "===========// Team %s //===========" % team.name
players = team.players
players.sort(sortPlayers)
for player in team:
print player
Here's something I quickly hacked together as a part of the. Hopefully it works in Windows too. In its current form, you'd have to do the following:
1. Get Python 2.5
2. Copy paste into "xmlReader.py" somewhere useful.
3. Get a command prompt
4. cd C:\Python25\
4. Drag the xmlReader.py file into the command prompt
5. Drag the xml file into the command prompt
6. Type --top --players
7. Press Enter
8. Scroll up and read from the beginning the dumped content.
Yeah, a pain. I've built an interface to Zenity, a Linux UI-from-the-commandline tool, and to WikiMarkup for copy paste on the wiki, but I can't be currently arsed to actually learn gui programming. The foundation's there though
