123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- #!/usr/bin/env python3
- """
- # urbanterrorstats
- # Copyright (c) 2011 Michael Buesch <m@bues.ch>
- # Licensed under the GNU/GPL version 2 or later.
- """
- import sys
- from gamestats import *
- class UTParser(Parser):
- _re_name = r'(.*)' # Player/item name
- _re_team = r'(.*)'
- _re_weapon = r'(.*)' # Weapon name #FIXME
- _re_esc = r'(?:\^\d)?'
- re_files_pk3 = re.compile(r'^(\d+) files in pk3 files$')
- re_gameinit = re.compile(r'^CL_InitCGame:\s+([\d\.]+)\s+seconds$')
- re_imgdraw = re.compile(r'^(\d+) msec to draw all images$')
- re_connected = re.compile(r'^' + _re_name + r' connected$')
- re_disconnected = re.compile(r'^' + _re_name + r' disconnected$')
- re_enter_game = re.compile(r'^' + _re_name + r' entered the game$')
- re_join_team = re.compile(r'^' + _re_name + r' joined the ' +\
- _re_team + r' team.$')
- re_join_spec = re.compile(r'^' + _re_name + r' joined the spectators\.$')
- re_bled_death = re.compile(r'^' + _re_name + r'bled to death from ' +\
- _re_name + r"'s attacks\.$")
- re_you_hit = re.compile(r'^You were hit in the (\w+) by ' + _re_name +\
- r' for (\d+)% damage\.$')
- re_other_hit = re.compile(r'^You hit ' + _re_name +\
- r' in the (\w+) for (\d+)% damage\.$')
- re_fragged0 = re.compile(r'^' + _re_name + r' was on the wrong end of ' +\
- _re_name + r"'s " + _re_weapon + r'\.$')
- re_fragged1 = re.compile(r'^' + _re_name + r' got shredded to pieces by ' +\
- _re_name + r"'s " + _re_weapon + r'$')
- re_fragged2 = re.compile(r'^' + _re_name + r" played 'catch the shiny bullet' with " +\
- _re_name + r"'s" + _re_weapon + r' rounds\.$')
- re_fragged3 = re.compile(r'^' + _re_name + r' has become a nasty stain thanks to ' +\
- _re_name + r"'s " + _re_weapon + r'\.$')
- re_fragged4 = re.compile(r'^' + _re_name + r' danced the ' + _re_weapon +\
- r' tango to ' + _re_name + r"'s sweet sweet music\.$")
- re_fragged5 = re.compile(r'^' + _re_name + r' was torn asunder by ' + _re_name +\
- r"'s crass " + _re_weapon + r'\.$')
- re_fragged6 = re.compile(r'^' + _re_name + r' was ' + _re_weapon + r' spammed without mercy by ' +\
- _re_name + r'\.$')
- re_fragged7 = re.compile(r'^' + _re_name + r' HEARD ' + _re_name + r"'s " +\
- _re_weapon + r"\.\.\. didn't AVOID it\. Sucka\.$")
- re_fragged8 = re.compile(r'^' + _re_name + r' got a whole lot of hole from ' +\
- _re_name + r"'s " + _re_weapon + r' round\.$')
- re_fragged9 = re.compile(r'^' + _re_name + r" was BBQ'ed by " + _re_name +\
- r"'s " + _re_weapon + r'\.$')
- re_fragged10 = re.compile(r'^' + _re_name + r' got nailed to the wall by ' +\
- _re_name + r"'s " + _re_weapon + r'$')
- re_fragged11 = re.compile(r'^' + _re_name + r' was taken out by ' + _re_name +\
- r"'s " + _re_weapon + r'\. Plink!$')
- re_selfkill0 = re.compile(r'^' + _re_name + r' did the lemming thing\.$')
- re_selfkill1 = re.compile(r'^' + _re_name + r' stepped on his own grenade\.$')
- re_slowdown = re.compile(r'^' + _re_name + r' managed to slow down ' +\
- _re_name + r"'s " + _re_weapon + r' round just a little\.(?: NEEP NEEP!)?$')
- re_had_health = re.compile(r'^' + _re_name + r' had (\d+)% Health\.$')
- re_flag_prot = re.compile(r'^' + _re_name + r' protected the ' + _re_name + r' flag\.$')
- re_flag_ret = re.compile(r'^' + _re_name + r' returned the ' + _re_name + r' flag!$')
- re_flag_taken = re.compile(r'^' + _re_esc + _re_name + _re_esc + r' has taken the ' +\
- _re_esc + _re_name + _re_esc + r' flag!$')
- re_flag_captured = re.compile(r'^' + _re_esc + _re_name + _re_esc + r' captured the ' +\
- _re_esc + _re_name + _re_esc + r' flag!$')
- re_flag_dropped = re.compile(r'^' + _re_esc + _re_name + _re_esc + r' dropped the ' +\
- _re_esc + _re_name + _re_esc + r' flag!$')
- def __init__(self, options):
- Parser.__init__(self, options)
- self.inClientStartup = False
- def __parseSystemMessages(self, stamp, line):
- if self.inClientStartup:
- if line.startswith("Loading vm file"):
- debugMsg("<<< Game init finished >>>")
- self.inClientStartup = False
- return True
- if line == "----- Client Initialization -----":
- debugMsg("<<< Initializing game >>>")
- self.inClientStartup = True
- return True
- if line.startswith("---") and line.endswith("---"):
- debugMsg("Separator (%s)" % line)
- return True
- if line.startswith("ioQ3 ") or\
- line.startswith("Going through search path") or\
- line.startswith("execing ") or\
- line.startswith("Hunk_Clear: reset the hunk ok") or\
- line.startswith("...loading ") or\
- line.startswith("...setting ") or\
- line.startswith("...using ") or\
- line.startswith("...ignoring ") or\
- line.startswith("Initializing OpenGL") or\
- line.startswith("GL_RENDERER: ") or\
- line.startswith("GL_VENDOR: ") or\
- line.startswith("GL_VERSION: ") or\
- line.startswith("GL_MAX_TEXTURE_SIZE: ") or\
- line.startswith("GL_MAX_ACTIVE_TEXTURES_ARB: ") or\
- line.startswith("PIXELFORMAT: ") or\
- line.startswith("MODE: ") or\
- line.startswith("GAMMA: ") or\
- line.startswith("CPU:") or\
- line.startswith("Hostname:") or\
- line.startswith("IP:") or\
- line.startswith("QKEY found.") or\
- line.startswith("Initializing Shaders") or\
- line.startswith("Initializing SDL") or\
- line.startswith("SDL audio driver is") or\
- line.startswith("Starting SDL audio") or\
- line.startswith("SDL audio initialized") or\
- line.startswith("Sound initialization") or\
- line.startswith("Sound memory manager") or\
- line.startswith("Loading vm file") or\
- line.startswith("Opening IP socket: ") or\
- line.startswith("Started tty console") or\
- line.startswith("RE_Shutdown(") or\
- line.startswith("compressed textures: ") or\
- line.startswith("Com_TouchMemory: ") or\
- line.startswith("Closing SDL audio device") or\
- line.startswith("SDL audio device shut down") or\
- line.startswith("Shutdown tty console") or\
- line.startswith("compilation took ") or\
- line.startswith("CL_InitCGame: ") or\
- line.find("SDL_Init") >= 0:
- debugMsg("Misc system message (%s)" % line)
- return True
- if line.startswith("console: "):
- debugMsg("Console (%s)" % line)
- return True
- if line == "Don't download your skill. Hackers get Banned!" or\
- line == "Welcome until you are banned!":
- debugMsg("No faggots (%s)" % line)
- return True
- m = self.re_files_pk3.match(line)
- if m:
- debugMsg("PK3 files (%s)" % line)
- return True
- m = self.re_imgdraw.match(line)
- if m:
- debugMsg("Image draw (%s)" % line)
- return True
- return False
- def __parseKill(self, timestamp, name0, name1=None, tk=False, sk=False):
- # name0 fragged name1
- if not self.assertCurrentGame("kill"):
- return
- player0 = self.currentGame.player(name0)
- if not sk:
- player1 = self.currentGame.player(name1)
- if tk:
- player0.addTeamkill(timestamp, player1)
- elif sk:
- player0.addSuicide(timestamp)
- else:
- player0.addFrag(timestamp, player1)
- if not sk:
- self.currentGame.hadFirstBlood = True
- def doParseLine(self, stamp, line):
- line = line.strip()
- if not line:
- return
- if self.__parseSystemMessages(stamp, line):
- return
- m = self.re_connected.match(line)
- if m:
- debugMsg("Connected (%s)" % line)
- return
- m = self.re_disconnected.match(line)
- if m:
- debugMsg("Disconnected (%s)" % line)
- if not self.assertCurrentGame("player disconnect"):
- return
- self.currentGame.player(m.group(1)).disconnected()
- return
- m = self.re_enter_game.match(line)
- if m:
- debugMsg("Enter game (%s)" % line)
- if not self.currentGame:
- self.currentGame = Game(options=self.options,
- timestamp=stamp,
- mode="Unknown mode",
- mapname="Unknown map",
- selfIDs=("You",))
- self.games.append(self.currentGame)
- self.currentGame.player(m.group(1)).connected()
- return
- m = self.re_join_team.match(line)
- if m:
- debugMsg("Join team (%s)" % line)
- return
- m = self.re_join_spec.match(line)
- if m:
- debugMsg("Join spectators (%s)" % line)
- return
- m = self.re_bled_death.match(line)
- if m:
- debugMsg("Bled to death (%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_you_hit.match(line)
- if m:
- debugMsg("You were hit (%s)" % line)
- return
- m = self.re_other_hit.match(line)
- if m:
- debugMsg("The enemy was hit (%s)" % line)
- return
- m = self.re_fragged0.match(line)
- if m:
- debugMsg("Fragged 0 (%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_fragged1.match(line)
- if m:
- debugMsg("Fragged 1 (%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_fragged2.match(line)
- if m:
- debugMsg("Fragged 2 (%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_fragged3.match(line)
- if m:
- debugMsg("Fragged 3 (%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_fragged4.match(line)
- if m:
- debugMsg("Fragged 4 (%s)" % line)
- self.__parseKill(stamp, m.group(3), m.group(1))
- return
- m = self.re_fragged5.match(line)
- if m:
- debugMsg("Fragged 5 (%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_fragged6.match(line)
- if m:
- debugMsg("Fragged 6(%s)" % line)
- self.__parseKill(stamp, m.group(3), m.group(1))
- return
- m = self.re_fragged7.match(line)
- if m:
- debugMsg("Fragged 7(%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_fragged8.match(line)
- if m:
- debugMsg("Fragged 8(%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_fragged9.match(line)
- if m:
- debugMsg("Fragged 9(%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_fragged10.match(line)
- if m:
- debugMsg("Fragged 10(%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_fragged11.match(line)
- if m:
- debugMsg("Fragged 11(%s)" % line)
- self.__parseKill(stamp, m.group(2), m.group(1))
- return
- m = self.re_selfkill0.match(line)
- if m:
- debugMsg("Selfkill 0 (%s)" % line)
- self.__parseKill(stamp, m.group(1), sk=True)
- return
- m = self.re_selfkill1.match(line)
- if m:
- debugMsg("Selfkill 1 (%s)" % line)
- self.__parseKill(stamp, m.group(1), sk=True)
- return
- m = self.re_slowdown.match(line)
- if m:
- debugMsg("Slowdown (%s)" % line)
- return
- m = self.re_had_health.match(line)
- if m:
- debugMsg("Had health (%s)" % line)
- return
- m = self.re_flag_prot.match(line)
- if m:
- debugMsg("Protected flag (%s)" % line)
- return
- m = self.re_flag_ret.match(line)
- if m:
- debugMsg("Returned flag (%s)" % line)
- return
- m = self.re_flag_taken.match(line)
- if m:
- debugMsg("Took flag (%s)" % line)
- return
- m = self.re_flag_captured.match(line)
- if m:
- debugMsg("Captured flag (%s)" % line)
- return
- m = self.re_flag_dropped.match(line)
- if m:
- debugMsg("Dropped flag (%s)" % line)
- return
- debugMsg("UNKNOWN console message: '%s'" % line)
- def main():
- return genericMain(scriptname="urbanterrorstats",
- usageinfo=" Example: Convert and log stats into directory:\n"
- " ioUrbanTerror.x86_64 | urbanterrorstats -n mynick -l ./logs\n"
- "\n"
- " Example: Create stats from logfile:\n"
- " urbanterrorstats -n mynick ./logs/2011....log",
- parserClass=UTParser)
- if __name__ == "__main__":
- sys.exit(main())
|