Madpeople has a program that turns it into one of the endgame allegiance stats thing, I don't know where it is but I'm sure either madpeople or Adept could tell you.Death3D wrote:QUOTE (Death3D @ Oct 30 2008, 06:44 PM) What program to use to read an XML file coherently and not as a list of unsorted stats?
3hr IC vs Rix game
-
- Posts: 4606
- Joined: Sun Nov 06, 2005 8:00 am
- Contact:
-
- Posts: 3627
- Joined: Thu Jan 12, 2006 8:00 am
- Contact:
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
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

Have gaming questions? Get expert answers!



Madpeople's widget is the best, in my opinion. Can be found in his blog.Death3D wrote:QUOTE (Death3D @ Oct 31 2008, 03:44 AM) What program to use to read an XML file coherently and not as a list of unsorted stats?





<bp|> Maybe when I grow up I can be a troll like PsycH
<bp|> or an obsessive compulsive paladin of law like Adept
hi badp,
your python script is pretty cool, i kinda reinvented the wheel a bit and parsed the xml using perl instead (my preferred weapon of choice) and took it one step further: i stuff all the parsed data into a database.
this project is about halfway done, i've got a couple of things to implement to give the script a bit more intelligence, but the basic functionality is already working.
the idea here is to mass aggregate all the stats from a whole bunch of user submittted xml files and produce something similar to the Leaderboard, except with more features and maybe a bit more granularity on the different statistics.
once complete, regular users can just upload a zip file of their saved xml to my webserver and my script can take that data and store it into the database which can then be queried by anyone.
my question is, do you think a lot of alleg players save their after-game xml files and out of that fraction of people, will they bother to upload those files to me?
i've got a sizable chunk of xmls saved, but obviously, statistically speaking, the more samples i get, the better and more useful the database will become, so i'd like to gauge the interest and see if i should continue on.
i save my source code in google's svn:
http://code.google.com/p/fleetcommand/source/checkout
you can browse the work i've done so far here:
http://code.google.com/p/fleetcommand/sour...l/parsestats.pl
if you want to make it work on your local machine, you'll also want to define the structure of your mysql database:
http://code.google.com/p/fleetcommand/sour...gxml/struct.sql
your python script is pretty cool, i kinda reinvented the wheel a bit and parsed the xml using perl instead (my preferred weapon of choice) and took it one step further: i stuff all the parsed data into a database.
this project is about halfway done, i've got a couple of things to implement to give the script a bit more intelligence, but the basic functionality is already working.
the idea here is to mass aggregate all the stats from a whole bunch of user submittted xml files and produce something similar to the Leaderboard, except with more features and maybe a bit more granularity on the different statistics.
once complete, regular users can just upload a zip file of their saved xml to my webserver and my script can take that data and store it into the database which can then be queried by anyone.
my question is, do you think a lot of alleg players save their after-game xml files and out of that fraction of people, will they bother to upload those files to me?
i've got a sizable chunk of xmls saved, but obviously, statistically speaking, the more samples i get, the better and more useful the database will become, so i'd like to gauge the interest and see if i should continue on.
i save my source code in google's svn:
http://code.google.com/p/fleetcommand/source/checkout
you can browse the work i've done so far here:
http://code.google.com/p/fleetcommand/sour...l/parsestats.pl
if you want to make it work on your local machine, you'll also want to define the structure of your mysql database:
http://code.google.com/p/fleetcommand/sour...gxml/struct.sql
Last edited by fwiffo on Fri Oct 31, 2008 10:06 pm, edited 1 time in total.
fwiffo wrote:QUOTE (fwiffo @ Oct 31 2008, 07:04 PM) my question is, do you think a lot of alleg players save their after-game xml files and out of that fraction of people, will they bother to upload those files to me?
I think a number of people would... at least for a while. You know how it goes with shiny new toys...

yea, solving duplication problem with a hash of the items that make a particular game unique:
Server,GameOverReason,Date,Core
from the gameinfo section of the xml.
if that turns out not to be enough, i can throw in the first couple of scores/stats from the playerinfo section too, that ought to make it unique enough.
Server,GameOverReason,Date,Core
from the gameinfo section of the xml.
if that turns out not to be enough, i can throw in the first couple of scores/stats from the playerinfo section too, that ought to make it unique enough.
-
- Posts: 3627
- Joined: Thu Jan 12, 2006 8:00 am
- Contact:
I've been toying with such an idea as well. How would you handle forgeries?
Have gaming questions? Get expert answers!



a good point. the simple answer is that i cant. what algorithms i can come up with to try to catch forgeries would be way beyond the scope of this exercise. the only thing i can think of is to limit the submissions to come from only "trusted" sources.
it would be great if i could get that xml directly from the alleg servers after every game, but i guess there's only a small chance of that happening.
any suggestions to resolve this stumbling block?
it would be great if i could get that xml directly from the alleg servers after every game, but i guess there's only a small chance of that happening.
any suggestions to resolve this stumbling block?
Last edited by fwiffo on Fri Oct 31, 2008 11:26 pm, edited 1 time in total.