diff --git a/assets/html/player/player.html b/assets/html/player/player.html index ee5459e..a37b2a6 100644 --- a/assets/html/player/player.html +++ b/assets/html/player/player.html @@ -550,7 +550,7 @@

Statistics

new Chart("avg_role_score_radar", { type: "radar", data: { - labels: {{ role_plot_labels }}, + labels: {{ role_plot_labels_with_game_count }}, datasets: [ { label: "Player's Median Score", diff --git a/handlers/player/player.py b/handlers/player/player.py index 43b2776..c93ca68 100644 --- a/handlers/player/player.py +++ b/handlers/player/player.py @@ -13,7 +13,7 @@ from helpers.laserballhelper import get_laserball_rating_over_time from helpers.sm5helper import get_sm5_rating_over_time from helpers.statshelper import sentry_trace, create_time_series_ordered_graph -from helpers.userhelper import get_median_role_score +from helpers.userhelper import get_median_role_score, get_per_role_game_count from shared import app from utils import render_cached_template, get_post @@ -38,26 +38,43 @@ async def get_laserball_stat(game, entity_start) -> Optional[LaserballStats]: return await game.laserball_stats.filter(entity=entity_start).first() -async def get_role_labels_from_medians(median_role_score) -> list: +# Returns the label, plus the number of games played if that number is provided. +def _role_label(role: str, games: Optional[int]) -> str: + if not games: + return role + + return f"{role} ({games} game{'s' if games != 1 else ''})" + + +# Returns a list of all roles that the player played at least once. If games_per_role is provided, also includes the +# number of games played as part of the label. +async def get_role_labels_from_medians(median_role_score, games_per_role: Optional[list[int]] = None) -> list: labels = [] for i, role_score in enumerate(median_role_score): if role_score == 0: continue else: + games = games_per_role[i] if games_per_role else None if i == 0: - labels.append("Commander") + labels.append(_role_label("Commander", games)) elif i == 1: - labels.append("Heavy") + labels.append(_role_label("Heavy", games)) elif i == 2: - labels.append("Scout") + labels.append(_role_label("Scout", games)) elif i == 3: - labels.append("Ammo") + labels.append(_role_label("Ammo", games)) elif i == 4: - labels.append("Medic") + labels.append(_role_label("Medic", games)) return labels +def get_games_per_role_filtered(games_per_role: list[int]) -> list: + return [ + game_count for game_count in games_per_role if game_count > 0 + ] + + @app.get("/player/") @sentry_trace @cache_template() @@ -71,9 +88,9 @@ async def player_get(request: Request, id: Union[int, str]) -> str: if not player: try: - player = await Player.filter(codename=id).get_or_none() # could be a codename + player = await Player.filter(codename=id).get_or_none() # could be a codename if not player: - player = await Player.filter(entity_id=id).get_or_none() # could be an entity_id + player = await Player.filter(entity_id=id).get_or_none() # could be an entity_id except Exception: raise exceptions.NotFound("Not found: Invalid ID or codename") @@ -90,6 +107,7 @@ async def player_get(request: Request, id: Union[int, str]) -> str: "-start_time").limit(5).offset(_GAMES_PER_PAGE * lbpage) median_role_score = await get_median_role_score(player) + per_role_game_count = await get_per_role_game_count(player) logger.debug("Loading team rate pies") @@ -106,12 +124,12 @@ async def player_get(request: Request, id: Union[int, str]) -> str: blue_wins_laserball = await player.get_wins_as_team(Team.BLUE, GameType.LASERBALL) sm5_win_percent = (red_wins_sm5 + green_wins_sm5) / (red_teams_sm5 + green_teams_sm5) if ( - red_teams_sm5 + green_teams_sm5) != 0 else 0 + red_teams_sm5 + green_teams_sm5) != 0 else 0 laserball_win_percent = (red_wins_laserball + blue_wins_laserball) / ( - red_teams_laserball + blue_teams_laserball) if (red_teams_laserball + blue_teams_laserball) != 0 else 0 + red_teams_laserball + blue_teams_laserball) if (red_teams_laserball + blue_teams_laserball) != 0 else 0 win_percent = (red_wins_sm5 + green_wins_sm5 + red_wins_laserball + blue_wins_laserball) / ( - red_teams_sm5 + green_teams_sm5 + red_teams_laserball + blue_teams_laserball) if ( - red_teams_sm5 + green_teams_sm5 + red_teams_laserball + blue_teams_laserball) != 0 else 0 + red_teams_sm5 + green_teams_sm5 + red_teams_laserball + blue_teams_laserball) if ( + red_teams_sm5 + green_teams_sm5 + red_teams_laserball + blue_teams_laserball) != 0 else 0 logger.debug("Loading stat chart") @@ -183,6 +201,8 @@ async def player_get(request: Request, id: Union[int, str]) -> str: role_plot_data_player=[x for x in median_role_score if x != 0], role_plot_data_world=await Player.get_median_role_score_world(median_role_score), role_plot_labels=await get_role_labels_from_medians(median_role_score), + role_plot_labels_with_game_count=await get_role_labels_from_medians(median_role_score, per_role_game_count), + role_plot_game_count=get_games_per_role_filtered(per_role_game_count), # total number of roles that aren't 0 role_plot_total_roles=len([x for x in median_role_score if x != 0]), # stat chart diff --git a/helpers/userhelper.py b/helpers/userhelper.py index 7dfeee7..7f101c2 100644 --- a/helpers/userhelper.py +++ b/helpers/userhelper.py @@ -40,6 +40,23 @@ async def get_median_role_score(player: Optional[Player] = None) -> List[int]: return data +async def get_per_role_game_count(player: Player) -> List[int]: + """ + Returns the number of times a player played each role. + """ + data = [] + + for role in range(1, 6): + try: + game_count = await EntityEnds.filter(entity__entity_id=player.entity_id, entity__role=IntRole(role), + entity__sm5games__ranked=True).count() + except Exception: + game_count = 0 + data.append(game_count) + + return data + + def hash_password(password: str) -> str: """ Hashes a password using bcrypt