Files
skillbird/insurgencyParsing.py
2019-02-10 11:55:03 +01:00

216 lines
6.2 KiB
Python

# insurgency specific
import insurgencyEvent as Event
import StorrageBackend as SB
import TrueSkillWrapper as TS
from insurgencyEventSeries import EventSeries
# general
import Player
import Round
from datetime import datetime
import time
def is_round_end(line):
return "0x42,round_end_active" in line
def is_plugin_output(line):
return "0x42" in line
def is_winner_event(line):
return "0x42,winner" in line
def get_key(dic,key):
tmp = list(dic)
return tmp[tmp.index(key)]
def loadCache(cacheFile):
rounds = []
if not cacheFile:
return None
with open(cacheFile, "r") as f:
for line in f:
rounds += [Round.Round.deserialize(line)]
# return if file was empty #
if len(rounds) == 0:
return None
# put them in right order #
rounds = sorted(rounds, key=lambda r: r.start)
# parse Rounds #
for r in rounds:
try:
SB.sync_from_database(r.winners)
SB.sync_from_database(r.losers)
TS.evaluate_round(r)
except Warning:
pass
# find newest #
lastRoundByDate = rounds[-1].start
return lastRoundByDate
def parse(f, exit_on_eof=True, start_at_end=False, cacheFile=None):
last_round_end = None
seek_start = True
round_lines = []
last_line_was_winner = False
lineCount = 0
startTime = datetime.now()
while True:
old_line_nr = f.tell()
line = f.readline()
# if no line or incomplete line, sleep and try again #
if not line or not line.strip("\n"):
if exit_on_eof:
return
time.sleep(5000)
continue
elif not line.endswith("\n"):
f.seek(old_line_nr)
time.sleep(5000)
continue
lineCount += 1
if lineCount % 100000 == 0:
diff = datetime.now() - startTime
print("At Line: {} Tot: {} Per 100k:{}".format(\
lineCount, diff, diff/(lineCount/100000)))
if seek_start and not "round_start_active" in line and line:
continue
elif "round_start_active" in line:
seek_start = False
elif "plugin unloaded" in line:
round_lines = []
seek_start = True
continue
evalRound = False
# ad line and stop if it was round end #
round_lines += [line]
if is_round_end(line):
last_round_end = line
evalRound = True
elif is_winner_event(line):
last_line_was_winner = True
# parse and evaluate round #
if evalRound:
nextRound = parseRoundFromLines(round_lines, cacheFile)
round_lines = []
evalRound = False
if nextRound:
try:
TS.evaluate_round(nextRound)
except Warning as e:
pass
def parseRoundFromLines(r, cacheFile=None):
# get an event series #
es = EventSeries()
for l in r:
if is_plugin_output(l):
e = parse_line_to_event(l)
if e != None:
es += [e]
# get players with teams #
try:
winners = es.get_winners()
losers = es.get_losers()
except Warning as e:
TS.dirty_rounds += 1
return None
# deal with teamchanges #
losers_pop = []
winners_pop = []
for p in winners:
if p in losers:
if get_key(losers,p).active_time < get_key(winners,p).active_time:
get_key(winners,p).active_time -= get_key(losers,p).active_time
losers_pop += [p]
else:
get_key(losers,p).active_time -= get_key(winners,p).active_time
winners_pop += [p]
# we cannot change dict during iteration #
for p in losers_pop:
losers.pop(p)
for p in winners_pop:
winners.pop(p)
# get ratings if there are any yet #
SB.sync_from_database(winners)
SB.sync_from_database(losers)
try:
es.get_duration()
except Warning as e:
TS.dirty_rounds += 1
return None
return Round.Round(winners, losers, es.get_map(), es.get_duration(), \
es.get_starttime(), cache=cacheFile)
def create_event(etype,line,timestamp):
TEAMCHANGE = ["teamchange"]
ACTIVE_PLAYERS = ["ct","dc","round_start_active","round_end_active","tc"]
DISCONNECT = ["disconnect"]
WINNER_INFO = ["winner"]
MAP_INFO = ["mapname"]
IGNORE = ["map_start_active","start","plugin unloaded"]
if etype in TEAMCHANGE:
player = Player.DummyPlayer(line.split(",")[1])
old_team = line.split(",")[2]
return Event.TeamchangeEvent(player,old_team,timestamp,line)
elif etype in ACTIVE_PLAYERS:
return Event.ActivePlayersEvent(line,timestamp)
elif etype in DISCONNECT:
player = Player.DummyPlayer(line.split(",")[1])
return Event.DisconnectEvent(player,timestamp,line)
elif etype in WINNER_INFO:
winner_side = line.split(",")[1]
return Event.WinnerInformationEvent(winner_side,timestamp,line)
elif etype in MAP_INFO:
return Event.MapInformationEvent(line.split(",")[1],timestamp,line)
elif etype in IGNORE:
pass
else:
raise Exception("Cannot create event from logline. (etype was: '{}')".format(etype))
def parseDate(l):
if ": L " in l.split("0x42")[0]:
timestamp = datetime.strptime(l.split(": L ")[1].split(": [")[0],"%m/%d/%Y - %H:%M:%S")
else:
timestamp = datetime.strptime(l.split(": [ints_logging.smx]")[0],"L %m/%d/%Y - %H:%M:%S")
return timestamp
def parse_line_to_event(l):
tmp = l.split("0x42,")[1].strip("\n")
etype = tmp.split(",")[0].split("|")[0]
try:
timestamp = parseDate(l)
event = create_event(etype,tmp,timestamp)
except ValueError:
print(" ---- NO TIME ---- | WARNING: Failed to parse time for event, SKIP")
return None
except IndexError as e:
print("Failed to parse Event in line, skipping: {}".format(str(e)))
return None
SB.save_event(event);
return event