def test_from_player_swtichteam(self): ps = PlayerScores() ps.player_score['A'] = [10, 0] ps.from_player_switchteam(gen_switch_team(3, 'A', 'Free', 'Spect')) assert ps.scores[0] == (3, 'A', 0, 'SWITCHTEAM') ps.player_score['A'] == [0, 0]
def test_from_player_death(self): ps = PlayerScores() ps.from_player_death(gen_death(3, 'A', 'B', 'MOD_ROCKET')) assert ps.scores == [] assert ps.player_score['B'] == [0, 0] assert ps.deaths[0] == (3, 'A', 'B', 'MOD_ROCKET')
def test_from_player_kill_selfkill(self): ps = PlayerScores() ps.from_player_kill(gen_kill(2, 'A', 'A', 'SHOTGUN')) assert ps.player_score['A'] == [0, 0] assert ps.kills == [(2, 'A', 'A', 'SHOTGUN')] assert ps.scores == []
def test_from_player_death_selfkill(self): ps = PlayerScores() ps.from_player_death(gen_death(3, 'B', 'B', 'FALLING')) assert ps.scores[0] == (3, 'B', -1, 'FALLING') assert ps.player_score['B'] == [-1, 0] assert ps.deaths[0] == (3, 'B', 'B', 'FALLING')
def __init__(self): self.match_metadata = MatchMetadata() self.server_info = ServerInfo() self.team_lifecycle = TeamLifecycle() self.player_scores = PlayerScores() self.players = {} self.special_scores = SpecialScores(self.player_scores) self.badger = Badger(self.player_scores, self.special_scores) self.specific_analyzer = None
def test_from_player_kill(self): ps = PlayerScores() assert ps.kdr['A'].r == 0 ps.from_player_kill(gen_kill(1, 'A', 'B', 'SHOTGUN')) assert len(ps.scores) == 1 assert ps.player_score['A'] == [1, 1] assert ps.scores[0] == (1, 'A', 1, 'SHOTGUN') assert len(ps.kills) == 1 assert ps.kills[0] == (1, 'A', 'B', 'SHOTGUN') assert ps.kdr['A'].r == 1 ps.from_player_kill(gen_kill(2, 'A', 'C', 'MOD3')) assert len(ps.scores) == 2 assert ps.player_score['A'] == [2, 2] assert ps.scores[1] == (2, 'A', 2, 'MOD3') assert len(ps.kills) == 2 assert ps.kills[1] == (2, 'A', 'C', 'MOD3') assert ps.kdr['A'].r == 2 ps.from_player_kill(gen_kill(2, 'B', 'A', 'MOD3')) assert len(ps.scores) == 3 assert ps.player_score['B'] == [1, 2] assert ps.scores[2] == (2, 'B', 1, 'MOD3') assert len(ps.kills) == 3 assert ps.kills[2] == (2, 'B', 'A', 'MOD3')
def test_from_player_disconnect(self): ps = PlayerScores() ps.match_duration = 100 ps.player_score['A'] = [10, 0] ps.from_player_disconnect(gen_disconnect(3, 'A')) assert ps.scores[0] == (3, 'A', 0, 'DISCONNECTED') assert ps.player_score['A'] == [0, 0] ps.player_score['A'] = [10, 1] ps.from_player_disconnect(gen_disconnect(300, 'A')) assert ps.player_score['A'] == [10, 1]
def test_from_player_disconnect(self): ps = PlayerScores() ps.match_duration = 100 ps.player_score['A'] = [10, 0] ps.from_player_disconnect({"TIME": 3, "STEAM_ID": 'A'}) assert ps.scores[0] == (3, 'A', 0, 'DISCONNECTED') assert ps.player_score['A'] == [0, 0] ps.player_score['A'] = [10, 1] ps.from_player_disconnect({"TIME": 300, "STEAM_ID": 'A'}) assert ps.player_score['A'] == [10, 1]
class Analyzer: def __init__(self): self.match_metadata = MatchMetadata() self.server_info = ServerInfo() self.team_lifecycle = TeamLifecycle() self.player_scores = PlayerScores() self.players = {} self.special_scores = SpecialScores(self.player_scores) self.badger = Badger(self.player_scores, self.special_scores) self.player_stats = {} self.specific_analyzer = None def analyze(self, full_match_info) -> AnalysisResult: """ :param full_match_info: FullMatchInfo :return: AnalysisResult """ self.full_match_info = full_match_info self.match_guid = full_match_info.match_guid self.player_scores.match_duration = self.full_match_info.duration self.team_lifecycle.match_duration = self.full_match_info.duration self.match_metadata.from_full_match_info(full_match_info) self.server_info.from_full_match_info(full_match_info) for raw_event in full_match_info.events: self.analyze_event(raw_event) self.badger.assign() # report generation report = AnalysisResult() report.server_info = self.server_info report.players = self.players report.scores = self.player_scores.scores report.final_scores = self.player_scores.player_score report.special_scores = self.special_scores.scores report.team_scores = "NOT IMPLEMENTED" report.team_switches = self.team_lifecycle.switches report.teams = self.team_lifecycle.team_map report.match_metadata = self.match_metadata report.kills = self.player_scores.kills report.badges = self.badger.badges report.player_stats = list(self.player_stats.values()) report.generate_summary() return report def analyze_event(self, raw_event): event = Event.from_dict(raw_event) dispatcher = { "MATCH_REPORT": self.on_match_report, "MATCH_STARTED": self.on_match_start, "PLAYER_DEATH": self.on_player_death, "PLAYER_DISCONNECT": self.on_player_disconnect, "PLAYER_KILL": self.on_player_kill, "PLAYER_SWITCHTEAM": self.on_player_switchteam, "PLAYER_STATS": self.on_player_stats, } try: handler = dispatcher[event.type] except KeyError: return handler(event) def add_player_if_needed(self, player_id, player_name): if player_id not in self.players: player_info = PlayerInfo() player_info.steam_id = player_id player_info.name = player_name self.players[player_id] = player_info def on_match_report(self, event): self.match_metadata.from_match_report(event) self.server_info.from_match_report(event) self.player_scores.from_match_report(event) self.special_scores.from_match_report(event) def on_match_start(self, event): self.match_metadata.from_match_started(event) for player in event.iter_players(): self.add_player_if_needed(player.id, player.name) self.team_lifecycle.from_match_started(event) self.player_scores.from_match_started(event) if self.match_metadata.game_type == "CA": self.specific_analyzer = CA_Analyzer(self.players, self.team_lifecycle) else: self.specific_analyzer = SpecializedAnalyzer( self.players, self.team_lifecycle) def on_player_switchteam(self, event): self.team_lifecycle.from_player_switchteam(event) player_id = event.player_id player_name = event.player_name self.add_player_if_needed(player_id, player_name) self.player_scores.from_player_switchteam(event) def on_player_disconnect(self, event): self.player_scores.from_player_disconnect(event) self.team_lifecycle.from_player_disconnect(event) def on_player_kill(self, event): # in q3 player can change his nickname. the generated id is # properly preserved between events but the name is not player_id = event.killer_id if event.killer_name: self.players[player_id].name = event.killer_name self.player_scores.from_player_kill(event) self.special_scores.from_player_kill(event) def on_player_death(self, event): # nice to have it here self.player_scores.from_player_death(event) self.specific_analyzer.on_player_death(event) self.special_scores.from_player_death(event) def on_player_stats(self, event): # if player has multiple stats events just use the last one # TODO consider merging stats (e.g. player reconnects/rejoins match) # ordinary stats sum grouped by player_id would be sufficient self.player_stats[event.player_id] = { "player_id": event.player_id, "total_armor_pickup": event.total_armor, "total_health_pickup": event.total_health, "damage_dealt": event.damage_dealt, "damage_taken": event.damage_taken, "weapons": event.weapon_stats, }
def test_players_sorted_by_score(self): ps = PlayerScores() ps.match_duration = 900 ps.from_player_kill(gen_kill(1, 'A', 'B', 'SHOTGUN')) ps.from_player_kill(gen_kill(2, 'A', 'B', 'SHOTGUN')) ps.from_player_kill(gen_kill(1, 'B', 'C', 'SHOTGUN')) assert ps.players_sorted_by_score() == ['A', 'B'] ps.from_player_kill(gen_kill(3, 'B', 'C', 'SHOTGUN')) assert ps.players_sorted_by_score() == ['B', 'A'] ps.from_player_kill(gen_kill(4, 'A', 'B', 'SHOTGUN')) assert ps.players_sorted_by_score() == ['A', 'B'] ps.from_player_disconnect(gen_disconnect(10, 'A')) assert ps.players_sorted_by_score() == ['B'] ps.from_player_switchteam(gen_switch_team(10, 'B', 'Free', 'Spect')) assert ps.players_sorted_by_score() == []
class Analyzer(): def __init__(self): self.match_metadata = MatchMetadata() self.server_info = ServerInfo() self.team_lifecycle = TeamLifecycle() self.player_scores = PlayerScores() self.players = {} self.special_scores = SpecialScores(self.player_scores) self.badger = Badger(self.player_scores, self.special_scores) self.specific_analyzer = None def analyze(self, full_match_info): """ :param full_match_info: FullMatchInfo :return: AnalysisResult """ self.full_match_info = full_match_info self.match_guid = full_match_info.match_guid self.player_scores.match_duration = self.full_match_info.duration self.team_lifecycle.match_duration = self.full_match_info.duration self.match_metadata.from_full_match_info(full_match_info) self.server_info.from_full_match_info(full_match_info) for raw_event in full_match_info.events: self.analyze_event(raw_event) self.badger.assign() # report generation report = AnalysisResult() report.server_info = self.server_info report.players = self.players report.scores = self.player_scores.scores report.final_scores = self.player_scores.player_score report.special_scores = self.special_scores.scores report.team_scores = "NOT IMPLEMENTED" report.team_switches = self.team_lifecycle.switches report.teams = self.team_lifecycle.team_map report.match_metadata = self.match_metadata report.kills = self.player_scores.kills report.badges = self.badger.badges return report def analyze_event(self, raw_event): event = Event.from_dict(raw_event) dispatcher = { 'MATCH_REPORT': self.on_match_report, 'MATCH_STARTED': self.on_match_start, 'PLAYER_DEATH': self.on_player_death, 'PLAYER_DISCONNECT': self.on_player_disconnect, 'PLAYER_KILL': self.on_player_kill, 'PLAYER_SWITCHTEAM': self.on_player_switchteam, } try: handler = dispatcher[event.type] except KeyError: return handler(event) def add_player_if_needed(self, player_id, player_name): if player_id not in self.players: player_info = PlayerInfo() player_info.steam_id = player_id player_info.name = player_name self.players[player_id] = player_info def on_match_report(self, event): self.match_metadata.from_match_report(event['DATA']) self.server_info.from_match_report(event['DATA']) self.player_scores.from_match_report(event['DATA']) self.special_scores.from_match_report(event['DATA']) def on_match_start(self, event): self.match_metadata.from_match_started(event['DATA']) if 'PLAYERS' in event['DATA']: self.team_lifecycle.from_match_started(event['DATA']) self.player_scores.from_match_started(event['DATA']) for player in event['DATA']['PLAYERS']: self.add_player_if_needed( player['STEAM_ID'], player['NAME']) if self.match_metadata.game_type == 'CA': self.specific_analyzer = CA_Analyzer( self.players, self.team_lifecycle) else: self.specific_analyzer = SpecializedAnalyzer( self.players, self.team_lifecycle) def on_player_switchteam(self, event): self.team_lifecycle.from_player_switchteam(event) player_id = event.player_id player_name = event.player_name self.add_player_if_needed(player_id, player_name) self.player_scores.from_player_switchteam(event) def on_player_disconnect(self, event): self.player_scores.from_player_disconnect(event['DATA']) self.team_lifecycle.from_player_disconnect(event['DATA']) def on_player_kill(self, event): # in q3 player can change his nickname. the generated id is # properly preserved between events but the name is not player_id = event.killer_id self.players[player_id].name = event.killer_name self.player_scores.from_player_kill(event) self.special_scores.from_player_kill(event) def on_player_death(self, event): # nice to have it here self.player_scores.from_player_death(event) self.specific_analyzer.on_player_death(event) self.special_scores.from_player_death(event)