class ChampionDmgCommand(command.Command): def __init__(self, name): super().__init__(name) self.match_filtering_flags = MatchFilteringFlags(self) self.table_output_flags = TableOutputFlags(self) def help_message(self): return f'Usage: {self._PROGRAM} {self.name}\n' 'Outputs each champ\'s damage relative to others within a game.' def _run_impl(self, args): if len(args) != 0: return self.print_invalid_usage() champ_stats = collections.defaultdict( lambda: dict(games_played=0, top_dmg=0, pct_of_top_dmg=[])) pipeline = self.match_filtering_flags.filter_steps() for match in self.db.matches.aggregate(pipeline): each_dmg = [ p['stats']['totalDamageDealtToChampions'] for p in match['participants'] ] highest_dmg = max(each_dmg) for participant in match['participants']: champ_stats[participant['championId']]['games_played'] += 1 dmg = participant['stats']['totalDamageDealtToChampions'] champ_stats[ participant['championId']]['pct_of_top_dmg'].append( float(dmg) / highest_dmg) if dmg == highest_dmg: champ_stats[participant['championId']]['top_dmg'] += 1 champion_list = cass.get_champions() champ_id_to_name = {champ.id: champ.name for champ in champion_list} table = [] for champ_id, champ_name in sorted(champ_id_to_name.items(), key=lambda t: t[1]): if champ_stats[champ_id]['games_played'] > 0: most_dmg_games = f'{100.0 * champ_stats[champ_id]["top_dmg"] / champ_stats[champ_id]["games_played"] :.3f}%' relative_top_dmg = f'{100.0 * statistics.mean(champ_stats[champ_id]["pct_of_top_dmg"]) :.3f}%' else: most_dmg_games = '-' relative_top_dmg = '-' table.append( collections.OrderedDict([ ('Champion', champ_name), ('Games Played', champ_stats[champ_id]['games_played']), ('Highest Damage Games', most_dmg_games), ('Average Relative Top Damage', relative_top_dmg), ])) self.table_output_flags.output_table(table)
class MostSeenCommand(command.Command): def __init__(self, name): super().__init__(name) self.match_filtering_flags = MatchFilteringFlags(self) self.table_output_flags = TableOutputFlags(self) self.register_flag( command.Flag( name='list_name_changes', default=False, is_boolean=True, description='Lists all the names for every summoner.')) def help_message(self): return ( f'Usage: {self._PROGRAM} {self.name} <summoner_name> [top_n]\n' 'Lists the most seen summoners in games with the specified summoner.' ) def _run_impl(self, args): if len(args) < 1 or len(args) > 2: return self.print_invalid_usage() summoner_name = args[0] n = 50 if len(args) == 2: n = int(args[1]) try: summoner = cass.Summoner(name=summoner_name).load() except datapipelines.common.NotFoundError: print(f'Summoner "{summoner_name}" not found.') return counts = collections.defaultdict(lambda: collections.defaultdict(int)) pipeline = self.match_filtering_flags.filter_steps() + [ {'$match': {'participants.accountId': summoner.account_id}}, ] # yapf: disable for match in self.db.matches.aggregate(pipeline): for participant in match['participants']: if participant['accountId'] == summoner.account_id: team = participant['side'] break for participant in match['participants']: if participant['accountId'] == '0': # BOT account continue if not counts[participant['accountId']]['name']: counts[participant['accountId']]['name'] = set( [participant['summonerName']]) elif self.flag('list_name_changes'): counts[participant['accountId']]['name'].add( participant['summonerName']) pass counts[participant['accountId']]['games_played'] += 1 same_team = team == participant['side'] counts[participant['accountId']]['same_team'] += int(same_team) if same_team: counts[participant['accountId']]['wins_with'] += int( participant['stats']['win']) else: counts[participant['accountId']]['wins_against'] += int( not participant['stats']['win']) table = [] for stats in counts.values(): if stats['same_team'] > 0: win_rate_with = float(stats['wins_with']) / stats['same_team'] wins_with = f'{stats["wins_with"]} / {stats["same_team"]} ({100 * win_rate_with:.3f})' else: wins_with = '-' if stats['same_team'] != stats['games_played']: win_rate_against = float(stats['wins_against']) / ( stats['games_played'] - stats['same_team']) wins_against = f'{stats["wins_against"]} / {stats["games_played"] - stats["same_team"]} ({100 * win_rate_against:.3f})' else: wins_against = '-' table.append( collections.OrderedDict([ ('Summoner', ','.join(stats['name'])), ('Games Played', stats['games_played']), ('Wins With', wins_with), ('Wins Against', wins_against), ])) table.sort(key=lambda i: i['Games Played']) table = table[-n:] table.reverse() self.table_output_flags.output_table(table)
class ChampionPersonalBestsCommand(command.Command): def __init__(self, name): super().__init__(name) self.match_filtering_flags = MatchFilteringFlags(self) self.table_output_flags = TableOutputFlags(self) def help_message(self): return ( f'Usage: {self._PROGRAM} {self.name} <summoner_names>\n' 'Outputs each summoner\'s personal bests on all of the champions they have played.' ) def format_result(self, result): if result is None: return '' return f'{result["champ_damage"]:,}'.replace(',', ' ') def _run_impl(self, args): if len(args) != 1: return self.print_invalid_usage() summoner_names = args[0].split(',') summoners = [] for name in summoner_names: if not name: print('Summoner name cannot be empty.') return try: summoners.append(cass.Summoner(name=name).load()) except datapipelines.common.NotFoundError: print(f'Summoner "{name}" not found.') return summoners.sort(key=lambda s: s.name) pipeline = self.match_filtering_flags.filter_steps() + [ {'$project': {'participants': True}}, {'$unwind': '$participants'}, {'$match': {'participants.accountId': {'$in': [summoner.account_id for summoner in summoners]}}}, {'$group': {'_id': {'championId': '$participants.championId', 'accountId': '$participants.accountId'}, 'champ_damage': {'$max': '$participants.stats.totalDamageDealtToChampions'}, }}, ] # yapf: disable results = {(result['_id']['championId'], result['_id']['accountId']): result for result in self.db.matches.aggregate(pipeline)} global_pipeline = self.match_filtering_flags.filter_steps() + [ {'$project': {'participants': True}}, {'$unwind': '$participants'}, {'$group': {'_id': {'championId': '$participants.championId'}, 'games_played': {'$sum': 1}, 'champ_damage': {'$max': '$participants.stats.totalDamageDealtToChampions'}, }}, ] # yapf: disable global_results = { result['_id']['championId']: result for result in self.db.matches.aggregate(global_pipeline) } champion_list = cass.get_champions() champ_id_to_name = {champ.id: champ.name for champ in champion_list} table = [] for champ_id, champ_name in sorted(champ_id_to_name.items(), key=lambda t: t[1]): row = collections.OrderedDict({'Champion': champ_name}) for summoner in summoners: row[summoner.name] = self.format_result( results.get((champ_id, summoner.account_id))) row['Global Avg'] = self.format_result( global_results.get(champ_id)) table.append(row) self.table_output_flags.output_table(table)