Insurgency specific code

This commit is contained in:
Yannik Schmidt
2019-01-27 17:37:47 +01:00
commit f1d0d45ced
3 changed files with 284 additions and 0 deletions

82
insurgencyEvent.py Normal file
View File

@@ -0,0 +1,82 @@
import Player
from datetime import datetime, timedelta
NO_TEAM = 0
OBSERVERS = 1
SECURITY = 2
INSURGENT = 3
class Event:
def __init__(self,timestamp,_map=None):
self.map = _map
self.timestamp = timestamp
def serialize(self):
raise NotImplementedError()
class DisconnectEvent(Event):
def __init__(self,player,timestamp,line):
self.timestamp = timestamp
self.player = player
self.string = line
def serialize(self):
return {"etype":"DCE","timestamp":self.timestamp.strftime(),"string":self.string}
class TeamchangeEvent(Event):
def __init__(self,player,old_team,timestamp,line):
self.timestamp = timestamp
self.player = player
self.old_team = int(old_team)
self.string = line
def serialize(self):
return {"etype":"TCE","timestamp":self.timestamp.strftime(),"string":self.string}
class ActivePlayersEvent(Event):
def __init__(self,player_str,timestamp):
self.timestamp = timestamp
self.players = []
self.string = player_str
#print(player_str)
try:
for s in player_str.split(","):
#print(s)
if not s or len(s.split("|"))==1:
continue
steamid = s.split("|")[1]
name = s.split("|")[2]
team = int(s.split("|")[3])
self.players += [Player.PlayerInRound(steamid,name,team,self.timestamp)]
except IndexError:
print("ERROR: CANNOT PARSE LOGLINE: {}".format(player_str))
print("WARNING: EVENT WILL BE USED IN INCOMPLETE STATE")
def serialize(self):
return {"etype":"APE","timestamp":self.timestamp.strftime(),"string":self.string}
class WinnerInformationEvent(Event):
def __init__(self,winner_side,timestamp,line):
self.timestamp = timestamp
self.winner = winner_side
self.string = line
def serialize(self):
return {"etype":"WIE","timestamp":self.timestamp.strftime(),"string":self.string}
class MapInformationEvent(Event):
def __init__(self,_map,timestamp,line):
self.timestamp = timestamp
self.map = _map
self.string = line
def serialize(self):
return {"etype":"MIE","timestamp":self.timestamp.strftime(),"string":self.string}
class MapInformationEvent(Event):
def __init__(self,_map,timestamp,line):
self.timestamp = timestamp
self.map = _map
self.string = line
def serialize(self):
return {"etype":"MIE","timestamp":self.timestamp.strftime(),"string":self.string}

94
insurgencyEventSeries.py Normal file
View File

@@ -0,0 +1,94 @@
class EventSeries(list):
def __init__(self):
self.winner_side_cache = None
self.loser_side_cache = None
self.map_cache = None
self.security_cache = dict()
self.insurgent_cache = dict()
def _cache_teams(self):
for e in self:
if type(e) == ActivePlayersEvent:
# TODO deal with players that are missing without a teamchange or dc event #
for p in e.players:
if p not in self._team_from_id(p.team):
self._team_from_id(p.team).update({p:p.rating})
else:
tmp_team = list(self._team_from_id(p.team))
tmp_player = tmp_team[tmp_team.index(p)]
## Add active time if player was active last event ##
if tmp_player.active:
tmp_player.active_time += e.timestamp - tmp_player.timestamp
tmp_player.timestamp = e.timestamp
tmp_player.active = True
## set player.active to false for disconnect or teamchange, it will be set to true at the next event that player is seen in a team ##
elif type(e) == DisconnectEvent:
if e.player in self.security_cache and get_key(self.security_cache,e.player).active:
get_key(self.security_cache,e.player).active_time += e.timestamp - get_key(self.security_cache,e.player).timestamp
get_key(self.security_cache,e.player).active = False
elif e.player in self.insurgent_cache and get_key(self.insurgent_cache,e.player).active:
get_key(self.insurgent_cache,e.player).active_time += e.timestamp - get_key(self.insurgent_cache,e.player).timestamp
get_key(self.insurgent_cache,e.player).active = False
elif type(e) == TeamchangeEvent:
if e.player in self._team_from_id(e.old_team):
get_key(self._team_from_id(e.old_team),e.player).active_time += e.timestamp-get_key(self._team_from_id(e.old_team),e.player).timestamp
get_key(self._team_from_id(e.old_team),e.player).active = False
def _find_winner(self):
time = "NO_TIME_FOUND"
for e in self:
time = e.timestamp#.strftime("%d-%m-%Y %H:%M:%S")
if type(e) == WinnerInformationEvent:
if self.winner_side_cache != None:
raise Warning("%s | Info: More than one Winner in series, skipping Round."%time)
self.winner_side_cache = int(e.winner)
self.loser_side_cache = ( ( ( int(e.winner) - 2 ) + 1 ) % 2) + 2 #löl
if self.winner_side_cache:
return self.winner_side_cache
else:
raise Warning("%s | Info: No winner found in series, skipping Round."%time)
def _team_from_id(self,tid):
if tid == OBSERVERS or tid == NO_TEAM:
return dict()
elif tid == SECURITY:
return self.security_cache;
elif tid == INSURGENT:
return self.insurgent_cache;
else:
raise ValueError("TeamID must be 0 - NoTeam, 1 - Observers, 2 - Security or 3 - Insurgent, but was {}".format(tid))
def get_duration(self):
key = lambda x: x.timestamp
max_ = max(self,key=key)
min_ = min(self,key=key)
ret = max_.timestamp-min_.timestamp
if ret > timedelta(seconds=60*30):
raise Warning("%s | Info: Round Length was %s, too long, ignoring."%(min_.timestamp,ret))
if ret < timedelta(seconds=60*3):
raise Warning("%s | Info: Round Length was %s, too short, ignoring."%(min_.timestamp,ret))
return ret
def get_starttime(self):
key = lambda x: x.timestamp
return min(self,key=key).timestamp
def get_winners(self):
if not self.security_cache or not self.insurgent_cache:
self._cache_teams()
self._find_winner()
return self._team_from_id(self.winner_side_cache)
def get_losers(self):
if not self.security_cache or not self.insurgent_cache:
self._cache_teams()
self._find_winner()
return self._team_from_id(self.loser_side_cache)
def get_map(self):
if self.map_cache == None:
for e in self:
if type(e) == MapInformationEvent:
self.map_cache = e.map
return self.map_cache

108
insurgencyParsing.py Normal file
View File

@@ -0,0 +1,108 @@
from InsurgencyEventSeries import EventSeries
import InsurgencyEvent as Event
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 parseRoundFromLines(r):
# get an event series #
es = Event.EventSeries()
for l in r:
if is_plugin_output(l):
e = Event.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 #
Storrage.sync_from_database(winners)
Storrage.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())
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 TeamchangeEvent(player,old_team,timestamp,line)
elif etype in ACTIVE_PLAYERS:
return ActivePlayersEvent(line,timestamp)
elif etype in DISCONNECT:
player = Player.DummyPlayer(line.split(",")[1])
return DisconnectEvent(player,timestamp,line)
elif etype in WINNER_INFO:
winner_side = line.split(",")[1]
return WinnerInformationEvent(winner_side,timestamp,line)
elif etype in MAP_INFO:
return MapInformationEvent(line.split(",")[1],timestamp,line)
elif etype in IGNORE:
pass
else:
raise Exception("Cannot create event from logline. (etype was: '{}')".format(etype))
def parse_line_to_event(l):
tmp = l.split("0x42,")[1].strip("\n")
etype = tmp.split(",")[0].split("|")[0]
try:
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")
except ValueError:
print(" ---- NO TIME ---- | WARNING: Failed to parse time for event, SKIP")
return None
event = create_event(etype,tmp,timestamp)
Storrage.save_event(event);
return event