mirror of
https://github.com/FAUSheppy/skillbird
synced 2025-12-06 06:51:34 +01:00
216 lines
6.2 KiB
Python
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 RuntimeError("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 RuntimeError as e:
|
|
print("Failed to parse Event in line, skipping: {}".format(str(e)))
|
|
return None
|
|
|
|
SB.save_event(event);
|
|
return event
|