diff --git a/assets/html/player/player.html b/assets/html/player/player.html
index a37b2a6..3de427b 100644
--- a/assets/html/player/player.html
+++ b/assets/html/player/player.html
@@ -364,6 +364,7 @@
Statistics
+
@@ -545,6 +546,79 @@ Statistics
}
});
+ new Chart("games_played_per_role", {
+ type: "bar",
+ data: {
+ labels: {{ role_names }},
+ datasets: [
+ {
+ label: "Ranked Games",
+ data: {{ per_role_game_count_ranked }},
+ backgroundColor: [
+ "rgb(50, 116, 161)",
+ "rgb(225, 129, 44)",
+ "rgb(58, 146, 58)",
+ "rgb(192, 61, 62)",
+ "rgb(147, 114, 178)"
+ ]
+ },
+ {
+ label: "Unranked Games",
+ data: {{ per_role_game_count_unranked }},
+ backgroundColor: [
+ "rgb(50, 166, 161)",
+ "rgb(225, 179, 44)",
+ "rgb(58, 196, 58)",
+ "rgb(192, 121, 62)",
+ "rgb(147, 174, 178)"
+ ]
+ }
+ ]
+ },
+ options: {
+ responsive: true,
+ scales: {
+ yAxes: [{
+ ticks: {
+ min: 0,
+ },
+ stacked: true,
+ }],
+ xAxes: [{
+ gridLines: {
+ display: false,
+ },
+ stacked: true
+ }],
+ },
+ tooltips: {
+ callbacks: {
+ label: function(tooltipItem, data) {
+ const index = tooltipItem["index"];
+ const datasetIndex = tooltipItem["datasetIndex"];
+ const label = data.datasets[datasetIndex].label;
+ const game_count = data.datasets[datasetIndex].data[index];
+
+ const all_games = data.datasets[0].data[index] + data.datasets[1].data[index];
+
+ return `${label}: ${game_count} / ${all_games}`;
+ }
+ }
+ },
+ plugins: {
+ legend: {
+ labels: {
+ color: "rgb(255, 255, 255)"
+ }
+ },
+ title: {
+ display: true,
+ text: "Number of games played per role"
+ }
+ }
+ }
+ });
+
// median score vs world radar chart
new Chart("avg_role_score_radar", {
diff --git a/handlers/player/player.py b/handlers/player/player.py
index c93ca68..235c7bd 100644
--- a/handlers/player/player.py
+++ b/handlers/player/player.py
@@ -18,6 +18,13 @@
from utils import render_cached_template, get_post
_GAMES_PER_PAGE = 5
+_ROLES = [
+ "Commander",
+ "Heavy",
+ "Scout",
+ "Ammo",
+ "Medic",
+]
sql = app.ctx.sql
@@ -48,23 +55,14 @@ def _role_label(role: str, games: Optional[int]) -> str:
# 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:
+def get_role_labels_from_medians(median_role_score: list[int], 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(_role_label("Commander", games))
- elif i == 1:
- labels.append(_role_label("Heavy", games))
- elif i == 2:
- labels.append(_role_label("Scout", games))
- elif i == 3:
- labels.append(_role_label("Ammo", games))
- elif i == 4:
- labels.append(_role_label("Medic", games))
+ labels.append(_role_label(_ROLES[i], games))
return labels
@@ -107,7 +105,9 @@ 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)
+ per_role_game_count_ranked = await get_per_role_game_count(player, ranked_only=True)
+ per_role_game_count_all = await get_per_role_game_count(player, ranked_only=False)
+ per_role_game_count_unranked = [all_games_played - per_role_game_count_ranked[i] for i, all_games_played in enumerate(per_role_game_count_all)]
logger.debug("Loading team rate pies")
@@ -200,9 +200,14 @@ async def player_get(request: Request, id: Union[int, str]) -> str:
# role score plot (sm5)
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),
+ role_plot_labels=get_role_labels_from_medians(median_role_score),
+ role_plot_labels_with_game_count=get_role_labels_from_medians(median_role_score, per_role_game_count_ranked),
+ role_plot_game_count=get_games_per_role_filtered(per_role_game_count_ranked),
+ # Games played per role
+ per_role_game_count_ranked=per_role_game_count_ranked,
+ per_role_game_count_all=per_role_game_count_all,
+ per_role_game_count_unranked=per_role_game_count_unranked,
+ role_names=_ROLES,
# 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 7f101c2..a84923c 100644
--- a/helpers/userhelper.py
+++ b/helpers/userhelper.py
@@ -40,7 +40,7 @@ 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]:
+async def get_per_role_game_count(player: Player, ranked_only: bool) -> List[int]:
"""
Returns the number of times a player played each role.
"""
@@ -48,8 +48,14 @@ async def get_per_role_game_count(player: Player) -> List[int]:
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()
+ kwargs = {"entity__entity_id": player.entity_id, "entity__role": IntRole(role)}
+
+ if ranked_only:
+ kwargs["entity__sm5games__ranked"]=True
+ else:
+ kwargs["sm5games__mission_name__icontains"] = "space marines"
+
+ game_count = await EntityEnds.filter(**kwargs).count()
except Exception:
game_count = 0
data.append(game_count)