mirror of
https://github.com/FAUSheppy/skillbird
synced 2025-12-09 16:08:31 +01:00
Insurgency specific code
This commit is contained in:
82
insurgencyEvent.py
Normal file
82
insurgencyEvent.py
Normal 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
94
insurgencyEventSeries.py
Normal 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
108
insurgencyParsing.py
Normal 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
|
||||
Reference in New Issue
Block a user