forked from Hanabi/hanabi-league
Add player pages (draft)
This commit is contained in:
parent
cd3c4190b2
commit
b1d0ae5dfd
3 changed files with 84 additions and 38 deletions
|
@ -2,6 +2,7 @@ import dataclasses
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
import jinja2
|
import jinja2
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -23,6 +24,10 @@ class PlayerEntry:
|
||||||
user_accounts: str
|
user_accounts: str
|
||||||
score: int
|
score: int
|
||||||
|
|
||||||
|
@property
|
||||||
|
def player_name_encoded(self):
|
||||||
|
return urllib.parse.quote_plus(self.player_name)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PlayerStreakEntry(PlayerEntry):
|
class PlayerStreakEntry(PlayerEntry):
|
||||||
|
@ -37,8 +42,7 @@ class Leader:
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class VariantStats:
|
class GeneralStats:
|
||||||
rating: int = 0
|
|
||||||
games_played: int = 0
|
games_played: int = 0
|
||||||
games_won: int = 0
|
games_won: int = 0
|
||||||
total_bdr: int = 0
|
total_bdr: int = 0
|
||||||
|
@ -75,6 +79,11 @@ class VariantStats:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class VariantStats(GeneralStats):
|
||||||
|
rating: int = 0
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class VariantRow:
|
class VariantRow:
|
||||||
variant_id: int
|
variant_id: int
|
||||||
|
@ -110,38 +119,17 @@ class Player:
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PlayerStats:
|
class PlayerStats(GeneralStats):
|
||||||
current_streak: int
|
current_streak: int = 0
|
||||||
max_streak: int
|
max_streak: int = 0
|
||||||
games_played: int
|
|
||||||
games_won: int
|
|
||||||
total_bdr: int
|
|
||||||
total_crits_lost: int
|
|
||||||
total_moves: int
|
|
||||||
|
|
||||||
@property
|
|
||||||
def winrate(self):
|
|
||||||
if self.games_played == 0:
|
|
||||||
return 0
|
|
||||||
return round(100 * float(self.games_won) / self.games_played, 1)
|
|
||||||
|
|
||||||
@property
|
@dataclass
|
||||||
def average_bdr(self):
|
class PlayerRow:
|
||||||
if self.games_played == 0:
|
user_id: int
|
||||||
return 0
|
name: str
|
||||||
return round(float(self.total_bdr) / self.games_played, 3)
|
user_accounts: List[str]
|
||||||
|
stats: PlayerStats
|
||||||
@property
|
|
||||||
def average_crits_lost(self):
|
|
||||||
if self.games_played == 0:
|
|
||||||
return 0
|
|
||||||
return round(float(self.total_crits_lost) / self.games_played, 3)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def average_moves(self):
|
|
||||||
if self.games_played == 0:
|
|
||||||
return 0
|
|
||||||
return round(float(self.total_moves) / self.games_played, 3)
|
|
||||||
|
|
||||||
|
|
||||||
def get_games():
|
def get_games():
|
||||||
|
@ -360,11 +348,39 @@ def get_variant_rows() -> List[VariantRow]:
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
return [
|
return [
|
||||||
VariantRow(variant_id, variant_name, num_players, VariantStats(round(rating), games_played, games_won, total_bdr, total_crits_lost, total_turns))
|
VariantRow(variant_id, variant_name, num_players, VariantStats(games_played, games_won, total_bdr, total_crits_lost, total_turns, round(rating)))
|
||||||
for (variant_id, variant_name, num_players, rating, games_played, games_won, total_bdr, total_crits_lost, total_turns) in cur.fetchall()
|
for (variant_id, variant_name, num_players, rating, games_played, games_won, total_bdr, total_crits_lost, total_turns) in cur.fetchall()
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_player_stats() -> Dict[int, Dict[int, PlayerStats]]:
|
||||||
|
cur = conn_manager.get_new_cursor()
|
||||||
|
cur.execute(
|
||||||
|
"SELECT "
|
||||||
|
" user_id,"
|
||||||
|
" player_name,"
|
||||||
|
" variant_type,"
|
||||||
|
" games_played,"
|
||||||
|
" games_won,"
|
||||||
|
" total_bdr,"
|
||||||
|
" total_crits_lots,"
|
||||||
|
" total_game_moves,"
|
||||||
|
" current_streak,"
|
||||||
|
" maximum_streak "
|
||||||
|
"FROM user_statistics "
|
||||||
|
"INNER JOIN users "
|
||||||
|
" ON user_statistics.user_id = users.id "
|
||||||
|
"ORDER BY user_id, variant_type"
|
||||||
|
)
|
||||||
|
ret = {}
|
||||||
|
for (user_id, player_name, variant_type, games_played, games_won, total_bdr, total_crits_lost, total_game_moves, current_streak, maximum_streak) in cur.fetchall():
|
||||||
|
if player_name not in ret.keys():
|
||||||
|
ret[player_name] = {}
|
||||||
|
ret[player_name][variant_type] = PlayerStats(games_played, games_won, total_bdr, total_crits_lost, total_game_moves, current_streak, maximum_streak)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def get_total_games():
|
def get_total_games():
|
||||||
cur = conn_manager.get_new_cursor()
|
cur = conn_manager.get_new_cursor()
|
||||||
cur.execute("SELECT COUNT(league_id) FROM games")
|
cur.execute("SELECT COUNT(league_id) FROM games")
|
||||||
|
@ -444,7 +460,7 @@ def render_leaderboard():
|
||||||
total_players=get_num_players(),
|
total_players=get_num_players(),
|
||||||
latest_run=datetime.datetime.now().isoformat(),
|
latest_run=datetime.datetime.now().isoformat(),
|
||||||
variant_stats_by_player=by_player_stats,
|
variant_stats_by_player=by_player_stats,
|
||||||
variant_stats=variant_stats.get(variant_id, VariantStats),
|
variant_stats=variant_stats.get(variant_id, VariantStats()),
|
||||||
variant_name=variant_names[variant_id],
|
variant_name=variant_names[variant_id],
|
||||||
variant_games=grouped_games_var.get(variant_id, [])
|
variant_games=grouped_games_var.get(variant_id, [])
|
||||||
)
|
)
|
||||||
|
@ -455,6 +471,24 @@ def render_leaderboard():
|
||||||
with open(output_file, 'w') as f:
|
with open(output_file, 'w') as f:
|
||||||
f.write(rendered_var)
|
f.write(rendered_var)
|
||||||
|
|
||||||
|
player_stats = get_player_stats()
|
||||||
|
|
||||||
|
player_template = env.get_template('player.html')
|
||||||
|
for player_name, player_stat in player_stats.items():
|
||||||
|
rendered_player = player_template.render(
|
||||||
|
total_games_played=get_total_games(),
|
||||||
|
total_players=get_num_players(),
|
||||||
|
latest_run=datetime.datetime.now().isoformat(),
|
||||||
|
player_name=player_name,
|
||||||
|
player_stat=player_stat
|
||||||
|
)
|
||||||
|
|
||||||
|
output_file = out_dir / 'player' / str(player_name) / 'index.html'
|
||||||
|
output_file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
|
||||||
|
with open(output_file, 'w') as f:
|
||||||
|
f.write(rendered_player)
|
||||||
|
|
||||||
# Copy CSS to output directory
|
# Copy CSS to output directory
|
||||||
shutil.copytree('css', 'build/css', dirs_exist_ok=True)
|
shutil.copytree('css', 'build/css', dirs_exist_ok=True)
|
||||||
shutil.copytree('deps/tabulator/dist/css', 'build/css', dirs_exist_ok=True)
|
shutil.copytree('deps/tabulator/dist/css', 'build/css', dirs_exist_ok=True)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% macro stats_list(stats, show_rating) %}
|
{% macro stats_list(stats, show_rating, show_streaks) %}
|
||||||
<!-- Table for statistics of a variant -->
|
<!-- Table for statistics of a variant -->
|
||||||
<div class="history-bullets">
|
<div class="history-bullets">
|
||||||
<ul class="stat-list">
|
<ul class="stat-list">
|
||||||
|
@ -10,6 +10,12 @@
|
||||||
-
|
-
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
|
{% if show_streaks %}
|
||||||
|
<li>
|
||||||
|
<span class="stat-description">Maximum Streak:</span>
|
||||||
|
{{stats.max_streak}}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Total Perfect Scores:</span>
|
<span class="stat-description">Total Perfect Scores:</span>
|
||||||
{{stats.games_won}}
|
{{stats.games_won}}
|
||||||
|
@ -32,6 +38,12 @@
|
||||||
<span class="stat-description">Total Games Played:</span>
|
<span class="stat-description">Total Games Played:</span>
|
||||||
{{stats.games_played}}
|
{{stats.games_played}}
|
||||||
</li>
|
</li>
|
||||||
|
{% if show_streaks %}
|
||||||
|
<li>
|
||||||
|
<span class="stat-description">Current Streak:</span>
|
||||||
|
{{stats.current_streak}}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
<li>
|
<li>
|
||||||
<span class="stat-description">Winrate:</span>
|
<span class="stat-description">Winrate:</span>
|
||||||
{{stats.winrate}}%
|
{{stats.winrate}}%
|
||||||
|
@ -72,7 +84,7 @@ var table_{{div_id}} = new Tabulator("#table-{{div_id}}", {
|
||||||
{title: "Rating After", field: "variant_rating_after"},
|
{title: "Rating After", field: "variant_rating_after"},
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{title: "Players", field: "users", formatter:function(cell, formatterParams, onRendered) {
|
{title: "Players", field: "users", formatter:function(cell, formatterParams, onRendered) {
|
||||||
let links = cell.getValue().map(player => `<a href="/player/${player}">${player}</a>`);
|
let links = cell.getValue().map(player => `<a href="/player/${encodeURIComponent(player)}">${player}</a>`);
|
||||||
return links.join(", ");
|
return links.join(", ");
|
||||||
}},
|
}},
|
||||||
{title: "Seed", field: "seed", formatter: "link", formatterParams: {
|
{title: "Seed", field: "seed", formatter: "link", formatterParams: {
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<h3>
|
<h3>
|
||||||
League Statistics for {{variant_name}}
|
League Statistics for {{variant_name}}
|
||||||
</h3>
|
</h3>
|
||||||
{{ stats_list(variant_stats, False) }}
|
{{ stats_list(variant_stats, False, False) }}
|
||||||
<h4>
|
<h4>
|
||||||
List of Played Games
|
List of Played Games
|
||||||
</h4>
|
</h4>
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
<h3>
|
<h3>
|
||||||
League Statistics for {{variant_name}} - {{num_players}} Players
|
League Statistics for {{variant_name}} - {{num_players}} Players
|
||||||
</h3>
|
</h3>
|
||||||
{{ stats_list(num_player_stats, True) }}
|
{{ stats_list(num_player_stats, True, False) }}
|
||||||
<h4>
|
<h4>
|
||||||
List of Played Games
|
List of Played Games
|
||||||
</h4>
|
</h4>
|
||||||
|
|
Loading…
Reference in a new issue