def test_can_get_the_default_score_from_a_single_match(self): # given a match report filename = "tests/logs/L0409001.log" match_report = LogParser.from_filename(filename).get_match_report() # when given to the stats extractor scorer = DefaultScorer() stats = MatchReportCollection([match_report]) # we can know the best player player = Player("Mcd.", 538382878) assert stats.get_best_player(scorer)[0] == player
def test_can_filter_players_with_less_than_n_rounds(self): # given a list of matches logs = "tests/logs" match_reports = LogDirectoryParser(logs).get_all_match_reports() # when given to the stats extractor with a filter scorer = WinRateScorer(filter_less_than=10) stats = MatchReportCollection(match_reports) # then the confidence in a player with less than the filter rounds played is zero score_table = stats.get_full_player_scores(scorer) print(score_table) player = Player("El Bromas", 538649250) assert score_table[player].confidence == 0
def test_can_get_glicko_ranking_per_player(self): # given a list of matches logs = "tests/logs" match_reports = LogDirectoryParser(logs).get_all_match_reports() # when given to the stats extractor scorer = GlickoScorer() stats = MatchReportCollection(match_reports) # we can know the player that has the best ranking score_table = stats.get_sorted_score_table(scorer) print(score_table) player = Player("Mcd.", 538382878) best_player = score_table[0][0] assert best_player == player
def test_can_get_time_spent_in_the_server_per_player(self): # given a list of matches logs = "tests/logs" match_reports = LogDirectoryParser(logs).get_all_match_reports() # when given to the stats extractor scorer = TimeSpentScorer() stats = MatchReportCollection(match_reports) # we can know the player that spent more time in the server score_table = stats.get_sorted_score_table(scorer) print(score_table) player = Player("Rocho", 86787335) best_player = score_table[0][0] assert best_player == player
def test_can_get_the_default_score_from_many_matches(self): # given a list of matches logs = "tests/logs" match_reports = LogDirectoryParser(logs).get_all_match_reports() # when given to the stats extractor scorer = DefaultScorer() stats = MatchReportCollection(match_reports) # we can know the best player score_table = stats.get_sorted_score_table(scorer) print(score_table) player = Player("Mcd.", 538382878) best_player = score_table[0][0] assert best_player == player
def __init__( self, match_reports: Collection[MatchReport], scorer: Optional[ScorerStrategy] = None, ): self._match_reports = MatchReportCollection(match_reports) self._scorer = scorer or DefaultScorer()
class StatsTable: """ The stats table can construct a table of stats about the players, based on many different scoring strategies. """ def __init__(self, match_reports: Collection[MatchReport], scorers: Collection[ScorerStrategy]): self._match_reports = MatchReportCollection(match_reports) self._scorers = scorers def get_full_table(self) -> Mapping[Player, StatsRow]: table = defaultdict(dict) stats = {} for scorer in self._scorers: stat_name = scorer.stat_name stats[stat_name] = scorer.stat_explanation scores = self._match_reports.get_full_player_scores(scorer) for player, value in scores.items(): table[player][stat_name] = value filtered_table = { player: row for player, row in table.items() if len(row) == len(self._scorers) } return filtered_table def get_stats_explanations(self) -> Mapping[str, str]: return { scorer.stat_name: scorer.stat_explanation for scorer in self._scorers }
def get_stats_for_season(season_logs_path): match_reports = parse_logs(season_logs_path) total_amount_of_rounds = MatchReportCollection( match_reports).get_total_number_of_rounds() filter_threshold = max(100, total_amount_of_rounds / 100) scorers = [ GlickoScorer(filter_threshold), DefaultScorer(filter_threshold), KillsScorer(filter_threshold), DeathsScorer(filter_threshold), WinRateScorer(filter_threshold), TotalRoundsScorer(filter_threshold), TimeSpentScorer(filter_threshold), ] stats = StatsTable(match_reports, scorers) table = stats.get_full_table() stat_names = [scorer.stat_name for scorer in scorers] stat_details = [(scorer.stat_name, scorer.stat_explanation) for scorer in scorers] def flatten_player_row(table, player): return [table[player].get(stat_name) for stat_name in stat_names] flat_table = { player.get_nickname(): flatten_player_row(table, player) for player in table } return stat_details, flat_table
def get_player_scores( self, match_reports: MatchReportCollection) -> Mapping[Player, float]: scores: Dict[Player, int] = defaultdict(int) stats_by_player: PlayerTable = match_reports.collect_stats() for player, stats in stats_by_player.items(): scores[player] += stats.kills scores[player] -= stats.deaths return scores
def get_player_scores( self, match_reports: MatchReportCollection) -> Mapping[Player, float]: stats_by_player: PlayerTable = match_reports.collect_stats() scores = { player: stats.total_rounds_played() for player, stats in stats_by_player.items() } return scores
def get_or_create_stats_for_current_season(season_logs_path): match_reports = parse_logs(season_logs_path) total_amount_of_rounds = MatchReportCollection( match_reports).get_total_number_of_rounds() if total_amount_of_rounds in CURRENT_SEASON_CACHE: return CURRENT_SEASON_CACHE[total_amount_of_rounds] else: CURRENT_SEASON_CACHE[total_amount_of_rounds] = get_stats_for_season( season_logs_path) return CURRENT_SEASON_CACHE[total_amount_of_rounds]
def get_player_scores( self, match_reports: MatchReportCollection) -> Mapping[Player, float]: scores: Dict[Player, float] = defaultdict(int) stats_by_player: PlayerTable = match_reports.collect_stats() for player, stats in stats_by_player.items(): rounds_played = stats.total_rounds_played() if rounds_played: rounds_won = stats.rounds_won scores[player] = rounds_won / rounds_played return scores
def get_confidence_in_player_scores( self, match_reports: MatchReportCollection) -> Mapping[Player, float]: """ Returns a level of confidence in the score returned (a number between 0 and 1). Default calculation is 1 if the number of rounds the player was involved in is more than the filter_less_than parameter (and 0 otherwise). Other scorers may override this value, usually with the percentage of rounds this player was involved in. """ stats_by_player: PlayerTable = match_reports.collect_stats() confidence_table = {} for player, stats in stats_by_player.items(): player_rounds = stats.total_rounds_played() confidence_table[ player] = 1 if player_rounds >= self.filter_treshold else 0 return confidence_table
def __init__(self, match_reports: Collection[MatchReport], scorers: Collection[ScorerStrategy]): self._match_reports = MatchReportCollection(match_reports) self._scorers = scorers