forked from Hanabi/hanabi-league
Move leader cards to separate page. add current streaks
This commit is contained in:
parent
ee40c27bc7
commit
0b67cea089
5 changed files with 63 additions and 48 deletions
|
@ -11,6 +11,11 @@
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #17a2b8; /* Bootstrap's teal color */
|
color: #17a2b8; /* Bootstrap's teal color */
|
||||||
}
|
}
|
||||||
|
.current-streak {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #676767; /* Bootstrap's teal color */
|
||||||
|
}
|
||||||
.table td, .table th {
|
.table td, .table th {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,11 @@ class PlayerEntry:
|
||||||
score: int
|
score: int
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PlayerStreakEntry(PlayerEntry):
|
||||||
|
current_streak: int
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Leader:
|
class Leader:
|
||||||
title: str
|
title: str
|
||||||
|
@ -59,6 +64,7 @@ class VariantStats:
|
||||||
return 0
|
return 0
|
||||||
return round(float(self.total_moves) / self.games_played, 3)
|
return round(float(self.total_moves) / self.games_played, 3)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class VariantRow:
|
class VariantRow:
|
||||||
variant_id: int
|
variant_id: int
|
||||||
|
@ -117,7 +123,7 @@ def get_leaders(rating_lists: Dict, streak_lists: Dict) -> Dict[int, Dict[str, L
|
||||||
return leaders
|
return leaders
|
||||||
|
|
||||||
|
|
||||||
def get_stat_lists(stat_type: str, order_type: str = 'DESC', precision: int = 0, default: float | int = 0, percents: bool = False):
|
def get_streak_list():
|
||||||
cur = conn_manager.get_connection().cursor(cursor_factory=psycopg2.extras.DictCursor)
|
cur = conn_manager.get_connection().cursor(cursor_factory=psycopg2.extras.DictCursor)
|
||||||
rating_types = [utils.get_rating_type(x) for x in [False, True]]
|
rating_types = [utils.get_rating_type(x) for x in [False, True]]
|
||||||
leaderboard = {
|
leaderboard = {
|
||||||
|
@ -128,27 +134,23 @@ def get_stat_lists(stat_type: str, order_type: str = 'DESC', precision: int = 0,
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"SELECT * FROM ("
|
"SELECT * FROM ("
|
||||||
" SELECT "
|
" SELECT "
|
||||||
" player_name,"
|
" player_name,"
|
||||||
" string_agg(user_accounts.username, %s ORDER BY user_accounts.username) AS user_accounts,"
|
" STRING_AGG(user_accounts.username, %s ORDER BY user_accounts.username) AS user_accounts,"
|
||||||
f" COALESCE({stat_type}, %s) AS value"
|
" COALESCE(maximum_streak, 0) AS maximum_streak,"
|
||||||
" FROM users "
|
" COALESCE(current_streak, 0) AS current_streak"
|
||||||
" LEFT OUTER JOIN user_statistics"
|
" FROM users "
|
||||||
" ON users.id = user_statistics.user_id AND variant_type = %s"
|
" LEFT OUTER JOIN user_statistics"
|
||||||
" LEFT OUTER JOIN user_accounts "
|
" ON users.id = user_statistics.user_id AND variant_type = %s"
|
||||||
" ON users.id = user_accounts.user_id "
|
" LEFT OUTER JOIN user_accounts "
|
||||||
f" GROUP BY (user_accounts.user_id, player_name, {stat_type}) "
|
" ON users.id = user_accounts.user_id "
|
||||||
|
" GROUP BY (user_accounts.user_id, player_name, maximum_streak, current_streak) "
|
||||||
" ) AS streaks "
|
" ) AS streaks "
|
||||||
# As a tiebreak, just sort by player name for now for determinancy
|
# As a tiebreak, just sort by player name for now for determinancy
|
||||||
f"ORDER BY value {order_type}, player_name",
|
"ORDER BY maximum_streak, player_name",
|
||||||
(", ", default, rating_type)
|
(", ", rating_type)
|
||||||
)
|
)
|
||||||
for (player_name, user_accounts, value) in cur.fetchall():
|
for (player_name, user_accounts, max_streak, current_streak) in cur.fetchall():
|
||||||
if percents:
|
leaderboard[rating_type].append(PlayerStreakEntry(player_name, user_accounts, max_streak, current_streak))
|
||||||
value = round(100 * value, precision)
|
|
||||||
value = str(value) + ' %'
|
|
||||||
else:
|
|
||||||
value = round(value, precision)
|
|
||||||
leaderboard[rating_type].append(PlayerEntry(player_name, user_accounts, value))
|
|
||||||
return leaderboard
|
return leaderboard
|
||||||
|
|
||||||
|
|
||||||
|
@ -228,7 +230,7 @@ def build_variant_stats_per_variant(variant_rows: List[VariantRow]):
|
||||||
|
|
||||||
def render_leaderboard():
|
def render_leaderboard():
|
||||||
rating_lists = get_rating_lists()
|
rating_lists = get_rating_lists()
|
||||||
streak_lists = get_stat_lists("maximum_streak")
|
streak_lists = get_streak_list()
|
||||||
leaders = get_leaders(rating_lists, streak_lists)
|
leaders = get_leaders(rating_lists, streak_lists)
|
||||||
|
|
||||||
variant_rows: List[VariantRow] = get_variant_rows()
|
variant_rows: List[VariantRow] = get_variant_rows()
|
||||||
|
@ -237,9 +239,6 @@ def render_leaderboard():
|
||||||
leaderboards = {
|
leaderboards = {
|
||||||
'Player Rating': rating_lists,
|
'Player Rating': rating_lists,
|
||||||
'Maximum Streak': streak_lists,
|
'Maximum Streak': streak_lists,
|
||||||
'Current Streak': get_stat_lists("current_streak", order_type="DESC"),
|
|
||||||
'Average Bottom Deck Risk': get_stat_lists("average_bdr", 'ASC', precision=2, default=float("inf")),
|
|
||||||
'Winrate': get_stat_lists('winrate', order_type='DESC', precision=1, percents=True)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
env = jinja2.Environment(loader=jinja2.FileSystemLoader('templates'))
|
env = jinja2.Environment(loader=jinja2.FileSystemLoader('templates'))
|
||||||
|
|
|
@ -1,22 +1,27 @@
|
||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="tab-content" id="myTabContent">
|
<div class="tab-content" id="myTabContent">
|
||||||
{% for rating_type, leaders in leaders.items() %}
|
<div class="tab-pane fade active show" id="summary">
|
||||||
<div class="tab-pane fade{{' active show' if rating_type == 0 else ''}}" id="leaderboards-{{rating_type}}">
|
<!-- Leader Cards -->
|
||||||
<div class="container my-5">
|
<div class="card-deck mb-5">
|
||||||
<!-- Leader Cards -->
|
{% for rating_type, leaders in leaders.items() %}
|
||||||
<div class="card-deck mb-5">
|
{% for category, data in leaders.items() %}
|
||||||
{% for category, data in leaders.items() %}
|
<div class="card text-center">
|
||||||
<div class="card text-center">
|
<div class="card-body">
|
||||||
<div class="card-body">
|
<h5 class="card-title mb-4">{{ data.title }}</h5>
|
||||||
<h5 class="card-title mb-4">{{ data.title }}</h5>
|
<p class="mb-0 player-name">{{ data.entry.player_name }}</p>
|
||||||
<p class="mb-0 player-name">{{ data.entry.player_name }}</p>
|
<p class="mt-1 alt-name">{{ data.entry.user_accounts }}</p>
|
||||||
<p class="mt-1 alt-name">{{ data.entry.user_accounts }}</p>
|
<p class="score-large">{{ data.entry.score }}</p>
|
||||||
<p class="score-large">{{ data.entry.score }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% for rating_type, leaders in leaders.items() %}
|
||||||
|
<div class="tab-pane fade" id="leaderboards-{{rating_type}}">
|
||||||
|
<div class="container my-5">
|
||||||
|
|
||||||
<!-- Leaderboards -->
|
<!-- Leaderboards -->
|
||||||
<div id="leaderboards-{{rating_type}}-data" class="accordion">
|
<div id="leaderboards-{{rating_type}}-data" class="accordion">
|
||||||
|
@ -37,6 +42,9 @@
|
||||||
<div class="alt-name">{{ entry.user_accounts }}</div>
|
<div class="alt-name">{{ entry.user_accounts }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="score">{{ entry.score }}</td>
|
<td class="score">{{ entry.score }}</td>
|
||||||
|
{% if entry.current_streak is defined %}
|
||||||
|
<td class="current-streak">({{ entry.current_streak }})</td>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -17,7 +17,10 @@
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
<ul class="navbar-nav ml-auto">
|
<ul class="navbar-nav ml-auto">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" id="leaderboards-0-tab" data-toggle="tab" href="#leaderboards-0">No Variant</a>
|
<a class="nav-link active" id="summary-tab" data-toggle="tab" href="#summary">Summary</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" id="leaderboards-0-tab" data-toggle="tab" href="#leaderboards-0">No Variant</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="leaderboards-1-tab" data-toggle="tab" href="#leaderboards-1">Clue Starved</a>
|
<a class="nav-link" id="leaderboards-1-tab" data-toggle="tab" href="#leaderboards-1">Clue Starved</a>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand" href="#">The Hanabi Pro Hunting League<small class="text-muted"> - Variant Statistics for {{variant_name}}</small></a>
|
<a class="navbar-brand" href="/">The Hanabi Pro Hunting League</a><a class="navbar-brand" href="#"><small class="text-muted">- Variant Statistics for {{variant_name}}</small></a>
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
<div class="tab-pane fade" id="stats-{{num_players}}p">
|
<div class="tab-pane fade" id="stats-{{num_players}}p">
|
||||||
<div class="container my-5">
|
<div class="container my-5">
|
||||||
<h3>
|
<h3>
|
||||||
League statistics for {{variant_name}} ({{num_players}} players)
|
League Statistics for {{variant_name}} - {{num_players}} Players
|
||||||
</h3>
|
</h3>
|
||||||
<div class="history-bullets">
|
<div class="history-bullets">
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -45,25 +45,25 @@
|
||||||
{{stats.rating}}
|
{{stats.rating}}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Total perfect scores:</span>
|
<span class="stat-description">Total Perfect Scores:</span>
|
||||||
{{stats.games_won}}
|
{{stats.games_won}}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Total bottom deck risk:</span>
|
<span class="stat-description">Total Bottom Deck Risk:</span>
|
||||||
{{stats.total_bdr}}
|
{{stats.total_bdr}}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Total crits lost:</span>
|
<span class="stat-description">Total Crits Lost:</span>
|
||||||
{{stats.total_crits_lost}}
|
{{stats.total_crits_lost}}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Total turns taken:</span>
|
<span class="stat-description">Total Turns Taken:</span>
|
||||||
{{stats.total_moves}}
|
{{stats.total_moves}}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Total games played:</span>
|
<span class="stat-description">Total Games Played:</span>
|
||||||
{{stats.games_played}}
|
{{stats.games_played}}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -71,15 +71,15 @@
|
||||||
{{stats.winrate}}%
|
{{stats.winrate}}%
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Average bottom deck risk:</span>
|
<span class="stat-description">Average Bottom Deck Risk:</span>
|
||||||
{{stats.average_bdr}}
|
{{stats.average_bdr}}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Average crits lost:</span>
|
<span class="stat-description">Average Crits Lost:</span>
|
||||||
{{stats.average_crits_lost}}
|
{{stats.average_crits_lost}}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Average turns taken:</span>
|
<span class="stat-description">Average Turns Taken:</span>
|
||||||
{{stats.average_moves}}
|
{{stats.average_moves}}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
Loading…
Reference in a new issue