improving transition - config tool for oregyen :)
This commit is contained in:
9
logs/base.py
Normal file
9
logs/base.py
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
class Log(object):
|
||||
matcher = None
|
||||
|
||||
@classmethod
|
||||
def is_handler(cls, log):
|
||||
return False
|
||||
|
||||
319
logs/combat.py
319
logs/combat.py
@@ -1,162 +1,157 @@
|
||||
"""
|
||||
todo:
|
||||
- English implementation first.
|
||||
- parsing combat.log
|
||||
|
||||
Prosa.
|
||||
All logs start with something like
|
||||
23:53:29.137 | LOGDATA
|
||||
|
||||
LOGDATA can be quite different depending on the logfile.
|
||||
|
||||
other forms encountered:
|
||||
23:54:00.600 WARNING|
|
||||
|
||||
combat logs:
|
||||
01:04:38.805 CMBT |
|
||||
|
||||
|
||||
The typical log entry
|
||||
"""
|
||||
import re
|
||||
|
||||
class Log(object):
|
||||
matcher = None
|
||||
|
||||
@classmethod
|
||||
def is_handler(cls, log):
|
||||
return False
|
||||
|
||||
class CombatLog(Log):
|
||||
@classmethod
|
||||
def _log_handler(cls, log):
|
||||
if log.get('log', '').strip().startswith(cls.__name__):
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def is_handler(cls, log):
|
||||
if log.get('logtype', None) == 'CMBT':
|
||||
return cls._log_handler(log)
|
||||
return False
|
||||
|
||||
def __init__(self, values=None):
|
||||
self.values = values
|
||||
|
||||
def unpack(self):
|
||||
# unpacks the data from the values.
|
||||
if hasattr(self, 'matcher') and self.matcher:
|
||||
matchers = self.matcher
|
||||
if not isinstance(matchers, list):
|
||||
matchers = [matchers,]
|
||||
for matcher in matchers:
|
||||
m = matcher.match(self.values.get('log', ''))
|
||||
if m:
|
||||
self.values.update(m.groupdict())
|
||||
return True
|
||||
|
||||
# @todo: where does this come from?
|
||||
class Action(CombatLog):
|
||||
pass
|
||||
|
||||
class Gameplay(CombatLog):
|
||||
matcher = [
|
||||
# usual: team(reason). explained reason.
|
||||
re.compile(r"^Gameplay\sfinished\.\sWinner\steam\:\s+(?P<winner_team>\d+)\((?P<winner_reason>\w+)\)\.\sFinish\sreason\:\s'(?P<reason_verbose>[^']+)'\.\sActual\sgame\stime\s+(?P<game_time>\d+|\d+\.\d+)\ssec"),
|
||||
# team, unexplained reason (unknown, Timeout)
|
||||
re.compile(r"^Gameplay\sfinished\.\sWinner\steam\:\s+(?P<winner_team>\d+).\sFinish\sreason\:\s'(?P<winner_reason>[^']+)'\.\sActual\sgame\stime\s+(?P<game_time>\d+|\d+\.\d+)\ssec"),
|
||||
]
|
||||
|
||||
class Apply(CombatLog): # Apply Aura.
|
||||
matcher = re.compile(r"^Apply\saura\s'(?P<aura_name>\w+)'\sid\s(?P<id>\d+)\stype\s(?P<aura_type>\w+)\sto\s'(?P<target_name>[^\']+)'")
|
||||
|
||||
class Damage(CombatLog):
|
||||
matcher = re.compile(r"^Damage\s+(?P<source_name>[^\s]+)\s\->\s+(?P<target_name>[^\s]+)\s+(?P<amount>(?:\d+|\d+\.\d+))(?:\s(?P<module_class>[^\s]+)\s|\s{2,2})(?P<flags>(?:\w|\|)+)")
|
||||
|
||||
class Spawn(CombatLog):
|
||||
matcher = re.compile(r"^Spawn\sSpaceShip\sfor\splayer(?P<player>\d+)\s\((?P<name>[^,]+),\s+(?P<hash>#\w+)\)\.\s+'(?P<ship_class>\w+)'")
|
||||
|
||||
class Spell(CombatLog):
|
||||
matcher = re.compile(r"^Spell\s'(?P<spell_name>\w+)'\sby\s+(?P<source_name>.*)(?:\((?P<module_name>\w+)\)|)\stargets\((?P<target_num>\d+)\)\:(?:$|\s(?P<targets>.+))")
|
||||
|
||||
class Reward(CombatLog):
|
||||
matcher = re.compile(r"^Reward\s+(?P<name>[^\s]+)(?:\s(?P<ship_class>\w+)\s+|\s+)(?P<amount>\d+)\s(?P<reward_type>.*)\s+for\s(?P<reward_reason>.*)")
|
||||
|
||||
class Participant(CombatLog):
|
||||
matcher = re.compile(r"^\s+Participant\s+(?P<source_name>[^\s]+)(?:\s{2}(?P<ship_class>\w+)|\s{30,})\s+(?:totalDamage\s(?P<total_damage>(?:\d+|\d+\.\d+));\smostDamageWith\s'(?P<module_class>[^']+)';(?P<additional>.*)|<(?P<other>\w+)>)")
|
||||
|
||||
class Rocket(CombatLog):
|
||||
matcher = re.compile(r"^Rocket\s(?P<event>launch|detonation)\.\sowner\s'(?P<name>[^']+)'(?:,\s(?:def\s'(?P<missile_type>\w+)'|target\s'(?P<target>[^']+)'|reason\s'(?P<reason>\w+)'|directHit\s'(?P<direct_hit>[^']+)'))+")
|
||||
|
||||
class Heal(CombatLog):
|
||||
matcher = [
|
||||
# heal by module
|
||||
re.compile(r"^Heal\s+(?P<source_name>[^\s]+)\s\->\s+(?P<target_name>[^\s]+)\s+(?P<amount>(?:\d+|\d+\.\d+))\s(?P<module_class>[^\s]+)"),
|
||||
# direct heal by source or n/a (global buff)
|
||||
re.compile(r"^Heal\s+(?:n/a|(?P<source_name>\w+))\s+\->\s+(?P<target_name>[^\s]+)\s+(?P<amount>(?:\d+|\d+\.\d+))"),
|
||||
]
|
||||
|
||||
class Killed(CombatLog):
|
||||
matcher = [
|
||||
re.compile(r"^Killed\s(?P<target_name>[^\s]+)\s+(?P<ship_class>\w+);\s+killer\s(?P<source_name>[^\s]+)\s*"),
|
||||
re.compile(r"^Killed\s(?P<object>[^\(]+)\((?P<target_name>\w+)\);\s+killer\s(?P<source_name>[^\s]+)\s*"),
|
||||
re.compile(r"^Killed\s(?P<object>[^\;]+);\s+killer\s(?P<source_name>[^\s]+)\s+.*"),
|
||||
]
|
||||
|
||||
class Captured(CombatLog):
|
||||
matcher = re.compile(r"^Captured\s'(?P<objective>[^']+)'\(team\s(?P<team>\d+)\)\.(?:\sAttackers\:(?P<attackers>.*)|.*)")
|
||||
|
||||
class AddStack(CombatLog):
|
||||
matcher = re.compile(r"^AddStack\saura\s'(?P<spell_name>\w+)'\sid\s(?P<id>\d+)\stype\s(?P<type>\w+)\.\snew\sstacks\scount\s(?P<stack_count>\d+)")
|
||||
|
||||
class Cancel(CombatLog):
|
||||
matcher = re.compile(r"^Cancel\saura\s'(?P<spell_name>\w+)'\sid\s(?P<id>\d+)\stype\s(?P<type>\w+)\sfrom\s'(?P<source_name>[^']+)'")
|
||||
|
||||
class Scores(CombatLog):
|
||||
matcher = re.compile(r"^Scores\s+-\sTeam1\((?P<team1_score>(?:\d+|\d+\.\d+))\)\sTeam2\((?P<team2_score>(?:\d+|\d+\.\d+))\)")
|
||||
|
||||
# Special classes
|
||||
class GameEvent(CombatLog):
|
||||
matcher = [
|
||||
# game session identifier.
|
||||
re.compile(r"^Connect\sto\sgame\ssession\s+(?P<game_session>\d+)"),
|
||||
# start gameplay identifier.
|
||||
re.compile(r"^Start\sgameplay\s'(?P<gameplay_name>\w+)'\smap\s+'(?P<map_id>\w+)',\slocal\sclient\steam\s(?P<local_team>\d+)"),
|
||||
# pve mission identifier.
|
||||
re.compile(r"^Start\sPVE\smission\s'(?P<pve_name>\w+)'\smap\s+'(?P<map_id>\w+)'"),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _log_handler(cls, log):
|
||||
if log.get('log', '').strip().startswith('======='):
|
||||
return True
|
||||
return False
|
||||
|
||||
def unpack(self):
|
||||
# unpacks the data from the values.
|
||||
if hasattr(self, 'matcher') and self.matcher:
|
||||
matchers = self.matcher
|
||||
if not isinstance(matchers, list):
|
||||
matchers = [matchers,]
|
||||
for matcher in matchers:
|
||||
m = matcher.match(self.values.get('log', '').strip('=').strip())
|
||||
if m:
|
||||
self.values.update(m.groupdict())
|
||||
return True
|
||||
|
||||
class UserEvent(CombatLog):
|
||||
""" special class for combat logs that might be associated with the playing player """
|
||||
@classmethod
|
||||
def _log_handler(cls, log):
|
||||
if log.get('log', '').strip():
|
||||
return True
|
||||
return False
|
||||
|
||||
# Action?
|
||||
COMBAT_LOGS = [ Apply, Damage, Spawn, Spell, Reward, Participant, Rocket, Heal,
|
||||
Gameplay, #?
|
||||
Scores,
|
||||
Killed, Captured, AddStack, Cancel,
|
||||
GameEvent, UserEvent
|
||||
]
|
||||
|
||||
"""
|
||||
todo:
|
||||
- English implementation first.
|
||||
- parsing combat.log
|
||||
|
||||
Prosa.
|
||||
All logs start with something like
|
||||
23:53:29.137 | LOGDATA
|
||||
|
||||
LOGDATA can be quite different depending on the logfile.
|
||||
|
||||
other forms encountered:
|
||||
23:54:00.600 WARNING|
|
||||
|
||||
combat logs:
|
||||
01:04:38.805 CMBT |
|
||||
|
||||
|
||||
The typical log entry
|
||||
"""
|
||||
import re
|
||||
from base import Log
|
||||
|
||||
class CombatLog(Log):
|
||||
@classmethod
|
||||
def _log_handler(cls, log):
|
||||
if log.get('log', '').strip().startswith(cls.__name__):
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def is_handler(cls, log):
|
||||
if log.get('logtype', None) == 'CMBT':
|
||||
return cls._log_handler(log)
|
||||
return False
|
||||
|
||||
def __init__(self, values=None):
|
||||
self.values = values
|
||||
|
||||
def unpack(self):
|
||||
# unpacks the data from the values.
|
||||
if hasattr(self, 'matcher') and self.matcher:
|
||||
matchers = self.matcher
|
||||
if not isinstance(matchers, list):
|
||||
matchers = [matchers,]
|
||||
for matcher in matchers:
|
||||
m = matcher.match(self.values.get('log', ''))
|
||||
if m:
|
||||
self.values.update(m.groupdict())
|
||||
return True
|
||||
|
||||
# @todo: where does this come from?
|
||||
class Action(CombatLog):
|
||||
pass
|
||||
|
||||
class Gameplay(CombatLog):
|
||||
matcher = [
|
||||
# usual: team(reason). explained reason.
|
||||
re.compile(r"^Gameplay\sfinished\.\sWinner\steam\:\s+(?P<winner_team>\d+)\((?P<winner_reason>\w+)\)\.\sFinish\sreason\:\s'(?P<reason_verbose>[^']+)'\.\sActual\sgame\stime\s+(?P<game_time>\d+|\d+\.\d+)\ssec"),
|
||||
# team, unexplained reason (unknown, Timeout)
|
||||
re.compile(r"^Gameplay\sfinished\.\sWinner\steam\:\s+(?P<winner_team>\d+).\sFinish\sreason\:\s'(?P<winner_reason>[^']+)'\.\sActual\sgame\stime\s+(?P<game_time>\d+|\d+\.\d+)\ssec"),
|
||||
]
|
||||
|
||||
class Apply(CombatLog): # Apply Aura.
|
||||
matcher = re.compile(r"^Apply\saura\s'(?P<aura_name>\w+)'\sid\s(?P<id>\d+)\stype\s(?P<aura_type>\w+)\sto\s'(?P<target_name>[^\']+)'")
|
||||
|
||||
class Damage(CombatLog):
|
||||
matcher = re.compile(r"^Damage\s+(?P<source_name>[^\s]+)\s\->\s+(?P<target_name>[^\s]+)\s+(?P<amount>(?:\d+|\d+\.\d+))(?:\s(?P<module_class>[^\s]+)\s|\s{2,2})(?P<flags>(?:\w|\|)+)")
|
||||
|
||||
class Spawn(CombatLog):
|
||||
matcher = re.compile(r"^Spawn\sSpaceShip\sfor\splayer(?P<player>\d+)\s\((?P<name>[^,]+),\s+(?P<hash>#\w+)\)\.\s+'(?P<ship_class>\w+)'")
|
||||
|
||||
class Spell(CombatLog):
|
||||
matcher = re.compile(r"^Spell\s'(?P<spell_name>\w+)'\sby\s+(?P<source_name>.*)(?:\((?P<module_name>\w+)\)|)\stargets\((?P<target_num>\d+)\)\:(?:$|\s(?P<targets>.+))")
|
||||
|
||||
class Reward(CombatLog):
|
||||
matcher = re.compile(r"^Reward\s+(?P<name>[^\s]+)(?:\s(?P<ship_class>\w+)\s+|\s+)(?P<amount>\d+)\s(?P<reward_type>.*)\s+for\s(?P<reward_reason>.*)")
|
||||
|
||||
class Participant(CombatLog):
|
||||
matcher = re.compile(r"^\s+Participant\s+(?P<source_name>[^\s]+)(?:\s{2}(?P<ship_class>\w+)|\s{30,})\s+(?:totalDamage\s(?P<total_damage>(?:\d+|\d+\.\d+));\smostDamageWith\s'(?P<module_class>[^']+)';(?P<additional>.*)|<(?P<other>\w+)>)")
|
||||
|
||||
class Rocket(CombatLog):
|
||||
matcher = re.compile(r"^Rocket\s(?P<event>launch|detonation)\.\sowner\s'(?P<name>[^']+)'(?:,\s(?:def\s'(?P<missile_type>\w+)'|target\s'(?P<target>[^']+)'|reason\s'(?P<reason>\w+)'|directHit\s'(?P<direct_hit>[^']+)'))+")
|
||||
|
||||
class Heal(CombatLog):
|
||||
matcher = [
|
||||
# heal by module
|
||||
re.compile(r"^Heal\s+(?P<source_name>[^\s]+)\s\->\s+(?P<target_name>[^\s]+)\s+(?P<amount>(?:\d+|\d+\.\d+))\s(?P<module_class>[^\s]+)"),
|
||||
# direct heal by source or n/a (global buff)
|
||||
re.compile(r"^Heal\s+(?:n/a|(?P<source_name>\w+))\s+\->\s+(?P<target_name>[^\s]+)\s+(?P<amount>(?:\d+|\d+\.\d+))"),
|
||||
]
|
||||
|
||||
class Killed(CombatLog):
|
||||
matcher = [
|
||||
re.compile(r"^Killed\s(?P<target_name>[^\s]+)\s+(?P<ship_class>\w+);\s+killer\s(?P<source_name>[^\s]+)\s*"),
|
||||
re.compile(r"^Killed\s(?P<object>[^\(]+)\((?P<target_name>\w+)\);\s+killer\s(?P<source_name>[^\s]+)\s*"),
|
||||
re.compile(r"^Killed\s(?P<object>[^\;]+);\s+killer\s(?P<source_name>[^\s]+)\s+.*"),
|
||||
]
|
||||
|
||||
class Captured(CombatLog):
|
||||
matcher = re.compile(r"^Captured\s'(?P<objective>[^']+)'\(team\s(?P<team>\d+)\)\.(?:\sAttackers\:(?P<attackers>.*)|.*)")
|
||||
|
||||
class AddStack(CombatLog):
|
||||
matcher = re.compile(r"^AddStack\saura\s'(?P<spell_name>\w+)'\sid\s(?P<id>\d+)\stype\s(?P<type>\w+)\.\snew\sstacks\scount\s(?P<stack_count>\d+)")
|
||||
|
||||
class Cancel(CombatLog):
|
||||
matcher = re.compile(r"^Cancel\saura\s'(?P<spell_name>\w+)'\sid\s(?P<id>\d+)\stype\s(?P<type>\w+)\sfrom\s'(?P<source_name>[^']+)'")
|
||||
|
||||
class Scores(CombatLog):
|
||||
matcher = re.compile(r"^Scores\s+-\sTeam1\((?P<team1_score>(?:\d+|\d+\.\d+))\)\sTeam2\((?P<team2_score>(?:\d+|\d+\.\d+))\)")
|
||||
|
||||
# Special classes
|
||||
class GameEvent(CombatLog):
|
||||
matcher = [
|
||||
# game session identifier.
|
||||
re.compile(r"^Connect\sto\sgame\ssession\s+(?P<game_session>\d+)"),
|
||||
# start gameplay identifier.
|
||||
re.compile(r"^Start\sgameplay\s'(?P<gameplay_name>\w+)'\smap\s+'(?P<map_id>\w+)',\slocal\sclient\steam\s(?P<local_team>\d+)"),
|
||||
# pve mission identifier.
|
||||
re.compile(r"^Start\sPVE\smission\s'(?P<pve_name>\w+)'\smap\s+'(?P<map_id>\w+)'"),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _log_handler(cls, log):
|
||||
if log.get('log', '').strip().startswith('======='):
|
||||
return True
|
||||
return False
|
||||
|
||||
def unpack(self):
|
||||
# unpacks the data from the values.
|
||||
# small override to remove trailing "="s in the matching.
|
||||
if hasattr(self, 'matcher') and self.matcher:
|
||||
matchers = self.matcher
|
||||
if not isinstance(matchers, list):
|
||||
matchers = [matchers,]
|
||||
for matcher in matchers:
|
||||
m = matcher.match(self.values.get('log', '').strip('=').strip())
|
||||
if m:
|
||||
self.values.update(m.groupdict())
|
||||
return True
|
||||
|
||||
class UserEvent(CombatLog):
|
||||
""" special class for combat logs that might be associated with the playing player """
|
||||
@classmethod
|
||||
def _log_handler(cls, log):
|
||||
if log.get('log', '').strip():
|
||||
return True
|
||||
return False
|
||||
|
||||
# Action?
|
||||
COMBAT_LOGS = [ Apply, Damage, Spawn, Spell, Reward, Participant, Rocket, Heal,
|
||||
Gameplay, #?
|
||||
Scores,
|
||||
Killed, Captured, AddStack, Cancel,
|
||||
GameEvent, UserEvent
|
||||
]
|
||||
|
||||
|
||||
4
logs/game.py
Normal file
4
logs/game.py
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
|
||||
GAME_LOGS = []
|
||||
160
logs/logfile.py
160
logs/logfile.py
@@ -1,78 +1,82 @@
|
||||
#
|
||||
"""
|
||||
Author: Gabor Guzmics, 2013-2014
|
||||
|
||||
LogFile is an object capable to load SCon Logfiles and parse their ingredients
|
||||
It can be extended by overriding resolve to understand Logentries further.
|
||||
Each Logfile represents a physical file parsed, however theoretically, you can also parse arbitrary
|
||||
data by setting the LogFile<instance>._data yourself.
|
||||
"""
|
||||
import re
|
||||
RE_SCLOG = r'^(?P<hh>\d{2,2})\:(?P<mm>\d{2,2})\:(?P<ss>\d{2,2})\.(?P<ns>\d{3,3})\s(?P<logtype>\s*[^\|\s]+\s*|\s+)\|\s(?P<log>.*)'
|
||||
R_SCLOG = re.compile(RE_SCLOG)
|
||||
|
||||
class LogFile(object):
|
||||
def __init__(self, fname=None,
|
||||
folder=None):
|
||||
self.fname = fname
|
||||
self.folder = folder # only for custom tagging.
|
||||
self.lines = []
|
||||
self._data = None
|
||||
if self.fname is not None:
|
||||
self.open(self.fname)
|
||||
|
||||
def open(self, fname):
|
||||
f = open(fname, 'r')
|
||||
self._data = f.read()
|
||||
f.close()
|
||||
|
||||
def parse(self):
|
||||
# parse _data if we still have no lines.
|
||||
if self._data:
|
||||
data_lines = self._data.replace('\r', '\n').replace('\n\n', '\n').split('\n')
|
||||
lines = []
|
||||
for line in data_lines:
|
||||
if not line:
|
||||
continue
|
||||
elif not isinstance(line, basestring):
|
||||
lines.append(line)
|
||||
continue
|
||||
elif line.startswith('---'):
|
||||
continue
|
||||
else:
|
||||
# get the timecode & logtype
|
||||
m = R_SCLOG.match(line)
|
||||
if m:
|
||||
g = m.groupdict()
|
||||
if 'logtype' in g.keys():
|
||||
g['logtype'] = g['logtype'].strip()
|
||||
lines.append(g)
|
||||
else:
|
||||
lines.append(line)
|
||||
self.lines = lines
|
||||
# try to identify (resolve) lines.
|
||||
if self.lines:
|
||||
lines = []
|
||||
for line in self.lines:
|
||||
l = line
|
||||
if isinstance(line, basestring):
|
||||
# Unknown Log?
|
||||
pass
|
||||
elif isinstance(line, dict):
|
||||
# Unresolved Log.
|
||||
l = self.resolve(line)
|
||||
elif line is None:
|
||||
# dafuq?
|
||||
pass
|
||||
else:
|
||||
# might be an object?
|
||||
pass
|
||||
lines.append(l)
|
||||
|
||||
self.lines = lines
|
||||
|
||||
def resolve(self, line):
|
||||
# line is a dict.
|
||||
# try to find a class that is responsible for this log.
|
||||
return line
|
||||
|
||||
#
|
||||
"""
|
||||
Author: Gabor Guzmics, 2013-2014
|
||||
|
||||
LogFile is an object capable to load SCon Logfiles and parse their ingredients
|
||||
It can be extended by overriding resolve to understand Logentries further.
|
||||
Each Logfile represents a physical file parsed, however theoretically, you can also parse arbitrary
|
||||
data by setting the LogFile<instance>._data yourself.
|
||||
"""
|
||||
import re
|
||||
RE_SCLOG = r'^(?P<hh>\d{2,2})\:(?P<mm>\d{2,2})\:(?P<ss>\d{2,2})\.(?P<ns>\d{3,3})\s(?P<logtype>\s*[^\|\s]+\s*|\s+)\|\s(?P<log>.*)'
|
||||
R_SCLOG = re.compile(RE_SCLOG)
|
||||
|
||||
class LogFile(object):
|
||||
def __init__(self, fname=None,
|
||||
folder=None):
|
||||
self.fname = fname
|
||||
self.folder = folder # only for custom tagging.
|
||||
self.lines = []
|
||||
self._data = None
|
||||
|
||||
def read(self, fname=None):
|
||||
fname = fname or self.fname
|
||||
try:
|
||||
f = open(fname, 'r')
|
||||
self._data = f.read()
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def set_data(self, data):
|
||||
self._data = data
|
||||
|
||||
def parse(self):
|
||||
# parse _data if we still have no lines.
|
||||
if self._data:
|
||||
data_lines = self._data.replace('\r', '\n').replace('\n\n', '\n').split('\n')
|
||||
lines = []
|
||||
for line in data_lines:
|
||||
if not line:
|
||||
continue
|
||||
elif not isinstance(line, basestring):
|
||||
lines.append(line)
|
||||
continue
|
||||
elif line.startswith('---'):
|
||||
continue
|
||||
else:
|
||||
# get the timecode & logtype
|
||||
m = R_SCLOG.match(line)
|
||||
if m:
|
||||
g = m.groupdict()
|
||||
if 'logtype' in g.keys():
|
||||
g['logtype'] = g['logtype'].strip()
|
||||
lines.append(g)
|
||||
else:
|
||||
lines.append(line)
|
||||
self.lines = lines
|
||||
# try to identify (resolve) lines.
|
||||
if self.lines:
|
||||
lines = []
|
||||
for line in self.lines:
|
||||
l = line
|
||||
if isinstance(line, basestring):
|
||||
# Unknown Log?
|
||||
pass
|
||||
elif isinstance(line, dict):
|
||||
# Unresolved Log.
|
||||
l = self.resolve(line)
|
||||
elif line is None:
|
||||
# dafuq?
|
||||
pass
|
||||
else:
|
||||
# might be an object?
|
||||
pass
|
||||
lines.append(l)
|
||||
|
||||
self.lines = lines
|
||||
|
||||
def resolve(self, line):
|
||||
# line is a dict.
|
||||
# try to find a class that is responsible for this log.
|
||||
return line
|
||||
|
||||
|
||||
38
logs/logfiles.py
Normal file
38
logs/logfiles.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
Resolves Logs.
|
||||
"""
|
||||
|
||||
from logfile import LogFile
|
||||
from combat import COMBAT_LOGS
|
||||
from game import GAME_LOGS
|
||||
|
||||
class LogFileResolver(LogFile):
|
||||
''' dynamic logfile resolver '''
|
||||
resolution_classes = COMBAT_LOGS
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LogFileResolver, self).__init__(*args, **kwargs)
|
||||
self.resolution_classes = self.resolution_classes or []
|
||||
|
||||
def resolve(self, line):
|
||||
for klass in self.resolution_classes:
|
||||
if klass.is_handler(line):
|
||||
return klass(line)
|
||||
return line
|
||||
|
||||
class CombatLogFile(LogFile):
|
||||
''' Combat Log '''
|
||||
def resolve(self, line):
|
||||
for klass in COMBAT_LOGS:
|
||||
if klass.is_handler(line):
|
||||
return klass(line)
|
||||
return line
|
||||
|
||||
class GameLogFile(LogFile):
|
||||
''' Game Log '''
|
||||
def resolve(self, line):
|
||||
for klass in GAME_LOGS:
|
||||
if klass.is_handler(line):
|
||||
return klass(line)
|
||||
return line
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
"""
|
||||
Resolves Logs.
|
||||
"""
|
||||
|
||||
from logfile import LogFile
|
||||
from combat import COMBAT_LOGS
|
||||
|
||||
class LogFileResolver(LogFile):
|
||||
resolution_classes = COMBAT_LOGS
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LogFileResolver, self).__init__(*args, **kwargs)
|
||||
self.resolution_classes = self.resolution_classes or []
|
||||
|
||||
def resolve(self, line):
|
||||
for klass in self.resolution_classes:
|
||||
if klass.is_handler(line):
|
||||
return klass(line)
|
||||
return line
|
||||
70
logs/session.py
Normal file
70
logs/session.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""
|
||||
Logging Session.
|
||||
"""
|
||||
import zipfile, logging, os
|
||||
from logfiles import CombatLogFile, GameLogFile
|
||||
|
||||
class LogSession(object):
|
||||
"""
|
||||
The Log-Session is supposed to save one directory of logs.
|
||||
It can parse its logs, and build up its internal structure into Battle Instances etc.
|
||||
"""
|
||||
|
||||
def __init__(self, directory):
|
||||
''' if directory is a file, it will be handled as a compressed folder '''
|
||||
self.battles = []
|
||||
self.user = None
|
||||
|
||||
# various logfiles used.
|
||||
self.combat_log = None
|
||||
self.game_log = None
|
||||
self.chat_log = None
|
||||
# self.net_log = None
|
||||
|
||||
self.directory = directory
|
||||
self._zip_source = False
|
||||
|
||||
def parse_files(self):
|
||||
''' parses the logfiles '''
|
||||
# check if directory is a file
|
||||
self._zip_source = os.path.isfile(self.directory) or False
|
||||
if self._zip_source:
|
||||
self._unzip_logs()
|
||||
else:
|
||||
self.combat_log = CombatLogFile(os.path.join(self.directory, 'combat.log'))
|
||||
self.combat_log.read()
|
||||
self.game_log = GameLogFile(os.path.join(self.directory, 'game.log'))
|
||||
self.game_log.read()
|
||||
# parse all files
|
||||
self.combat_log.parse()
|
||||
self.game_log.parse()
|
||||
|
||||
def determine_owner(self):
|
||||
''' determines the user in the parsed gamelog '''
|
||||
pass
|
||||
|
||||
def parse_battles(self):
|
||||
''' parses the battles '''
|
||||
pass
|
||||
|
||||
def _unzip_logs(self):
|
||||
z = zipfile.ZipFile(self.directory, "r")
|
||||
for filename in z.namelist():
|
||||
fn = os.path.split(filename)[1] or ''
|
||||
fn = fn.lower()
|
||||
if fn:
|
||||
if fn == 'combat.log':
|
||||
self.combat_log = CombatLogFile(fn)
|
||||
self.combat_log.set_data(z.read(filename))
|
||||
elif fn == 'game.log':
|
||||
self.game_log = GameLogFile(fn)
|
||||
self.game_log.set_data(z.read(filename))
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
l_raw = LogSession('D:\\Users\\g4b\\Documents\\My Games\\sc\\2014.05.17 15.50.28')
|
||||
l_zip = LogSession('D:\\Users\\g4b\\Documents\\My Games\\sc\\2014.05.20 23.49.19.zip')
|
||||
|
||||
l_zip.parse_files()
|
||||
print l_zip.combat_log.lines
|
||||
Reference in New Issue
Block a user