Exemple #1
0
    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]
Exemple #2
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')
Exemple #3
0
    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 == []
Exemple #4
0
    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')
Exemple #5
0
 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
Exemple #6
0
    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')
Exemple #7
0
    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]
Exemple #8
0
    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]
Exemple #9
0
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,
        }
Exemple #10
0
    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() == []
Exemple #11
0
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)