Add table of played games to user pages

This commit is contained in:
Maximilian Keßler 2023-12-23 10:50:18 +01:00
parent d238c3b67e
commit 7446bd2916
Signed by: max
GPG key ID: BCC5A619923C0BA5
4 changed files with 58 additions and 12 deletions

View file

@ -97,8 +97,11 @@ class GameRow:
num_players: int num_players: int
users: List[str] users: List[str]
user_ids: List[int] user_ids: List[int]
user_rating_changes: List[float]
user_ratings_after: List[float]
variant_id: int variant_id: int
variant_name: str variant_name: str
rating_type: int
seed: str seed: str
score: int score: int
num_turns: int num_turns: int
@ -132,7 +135,7 @@ class PlayerRow:
stats: PlayerStats stats: PlayerStats
def get_games(): def get_games() -> List[GameRow]:
cur = conn_manager.get_connection().cursor(cursor_factory=psycopg2.extras.DictCursor) cur = conn_manager.get_connection().cursor(cursor_factory=psycopg2.extras.DictCursor)
cur.execute( cur.execute(
"SELECT" "SELECT"
@ -140,8 +143,11 @@ def get_games():
" game_data.num_players," " game_data.num_players,"
" users," " users,"
" user_ids," " user_ids,"
" user_rating_changes,"
" user_ratings_after,"
" game_data.variant_id," " game_data.variant_id,"
" variants.name AS variant_name," " variants.name AS variant_name,"
" rating_type,"
" seed," " seed,"
" score," " score,"
" num_turns," " num_turns,"
@ -158,11 +164,13 @@ def get_games():
" num_players," " num_players,"
" array_agg(users.player_name ORDER BY users.player_name) AS users," " array_agg(users.player_name ORDER BY users.player_name) AS users,"
" array_agg(users.id ORDER BY users.player_name) AS user_ids," " array_agg(users.id ORDER BY users.player_name) AS user_ids,"
" array_agg(user_ratings.change ORDER BY users.player_name) AS user_rating_changes,"
" array_agg(user_ratings.value_after ORDER BY users.player_name) AS user_ratings_after,"
" variant_id," " variant_id,"
" seed," " seed,"
" score," " score,"
" num_turns," " num_turns,"
" league_id," " games.league_id,"
" num_bottom_deck_risks," " num_bottom_deck_risks,"
" num_crits_lost " " num_crits_lost "
" FROM games " " FROM games "
@ -172,9 +180,11 @@ def get_games():
" ON games.id = game_participants.game_id " " ON games.id = game_participants.game_id "
" LEFT OUTER JOIN users" " LEFT OUTER JOIN users"
" ON game_participants.user_id = users.id " " ON game_participants.user_id = users.id "
" LEFT OUTER JOIN user_ratings"
" ON user_ratings.league_id = games.league_id AND user_ratings.user_id = game_participants.user_id"
" GROUP BY (" " GROUP BY ("
" games.id, num_players, variant_id, seed, score, num_turns," " games.id, num_players, variant_id, seed, score, num_turns,"
" league_id, num_bottom_deck_risks, num_crits_lost" " games.league_id, num_bottom_deck_risks, num_crits_lost"
" )" " )"
" ) AS game_data " " ) AS game_data "
"LEFT OUTER JOIN game_outcomes " "LEFT OUTER JOIN game_outcomes "
@ -185,7 +195,7 @@ def get_games():
" ON variant_ratings.league_id = game_data.league_id AND variant_ratings.primary_change = true " " ON variant_ratings.league_id = game_data.league_id AND variant_ratings.primary_change = true "
"GROUP BY (" "GROUP BY ("
" game_data.game_id, game_data.num_players, users, user_ids, game_data.variant_id, variants.name, seed, score, num_turns," " game_data.game_id, game_data.num_players, users, user_ids, game_data.variant_id, variants.name, seed, score, num_turns,"
" game_data.league_id, num_bottom_deck_risks, num_crits_lost, change, value_after" " game_data.league_id, num_bottom_deck_risks, num_crits_lost, change, value_after, rating_type, user_rating_changes, user_ratings_after"
" ) " " ) "
"ORDER BY league_id DESC", "ORDER BY league_id DESC",
(True,) (True,)
@ -210,6 +220,19 @@ def group_games_by_var_id(games: List[GameRow]):
return ret return ret
def group_games_by_player(games: List[GameRow]):
ret = {}
for game in games:
for i, user in enumerate(game.users):
if user not in ret.keys():
ret[user] = []
row = dataclasses.asdict(game)
row["user_rating_change"] = round(game.user_rating_changes[i], 1)
row["user_rating_after"] = round(game.user_ratings_after[i], 1)
ret[user].append(row)
return ret
def get_rating_lists() -> Dict[int, List[PlayerEntry]]: def get_rating_lists() -> Dict[int, List[PlayerEntry]]:
cur = conn_manager.get_connection().cursor() cur = conn_manager.get_connection().cursor()
rating_types = [utils.get_rating_type(x) for x in [False, True]] rating_types = [utils.get_rating_type(x) for x in [False, True]]
@ -502,6 +525,9 @@ def render_variant_pages(env: jinja2.Environment, out_dir: Path):
def render_player_pages(env: jinja2.Environment, out_dir: Path): def render_player_pages(env: jinja2.Environment, out_dir: Path):
player_stats = get_player_stats() player_stats = get_player_stats()
games = get_games()
games_grouped_by_player = group_games_by_player(games)
player_template = env.get_template('player.html') player_template = env.get_template('player.html')
for player_name, player_stat in player_stats.items(): for player_name, player_stat in player_stats.items():
rendered_player = player_template.render( rendered_player = player_template.render(
@ -509,7 +535,8 @@ def render_player_pages(env: jinja2.Environment, out_dir: Path):
total_players=get_num_players(), total_players=get_num_players(),
latest_run=datetime.datetime.now().isoformat(), latest_run=datetime.datetime.now().isoformat(),
player_name=player_name, player_name=player_name,
player_stat=player_stat player_stat=player_stat,
player_games=games_grouped_by_player.get(player_name, [])
) )
output_file = out_dir / 'player' / urllib.parse.quote_plus(player_name) / 'index.html' output_file = out_dir / 'player' / urllib.parse.quote_plus(player_name) / 'index.html'

View file

@ -35,9 +35,25 @@
{% endif %} {% endif %}
</h4> </h4>
{{ stats_list(player_row.stats, True, True) }} {{ stats_list(player_row.stats, True, True) }}
<div id="table-{{rating_type}}"></div>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
</div> </div>
<!-- JavaScript part for the tables -->
<script>
let tabledata = [
{% for game in player_games %}
{{- game -}},
{% endfor %}
];
{% for rating_type in player_stat.keys() %}
{{ games_table_js("tabledata", rating_type, True, False, True) }}
// Filter table on corresponding rating type
table_{{rating_type}}.setFilter("rating_type", "=", {{rating_type}});
{% endfor %}
</script>
{% endblock %} {% endblock %}

View file

@ -65,13 +65,12 @@
{% endmacro %} {% endmacro %}
{% macro games_table_js(data, div_id, show_player_num, show_var_rating) %} {% macro games_table_js(data, div_id, show_player_num, show_var_rating, show_user_rating) %}
var table_{{div_id}} = new Tabulator("#table-{{div_id}}", { var table_{{div_id}} = new Tabulator("#table-{{div_id}}", {
height: 400, maxHeight: 400,
data: {{data}}, data: {{data}},
layout: "fitDataStretch", layout: "fitDataStretch",
columns: [ columns: [
{title: "id", field: "league_id"},
{title: "Game", field: "game_id", formatter: "link", formatterParams:{ {title: "Game", field: "game_id", formatter: "link", formatterParams:{
urlPrefix: "https://hanab.live/replay/", urlPrefix: "https://hanab.live/replay/",
target:"_blank" target:"_blank"
@ -80,8 +79,12 @@ var table_{{div_id}} = new Tabulator("#table-{{div_id}}", {
{title: "# Players", field: "num_players"}, {title: "# Players", field: "num_players"},
{% endif %} {% endif %}
{% if show_var_rating %} {% if show_var_rating %}
{title: "Rating Change", field: "variant_rating_change"}, {title: "+/-", field: "variant_rating_change"},
{title: "Rating After", field: "variant_rating_after"}, {title: "ELO After", field: "variant_rating_after"},
{% endif %}
{% if show_user_rating %}
{title: "+/-", field: "user_rating_change"},
{title: "ELO After", field: "user_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/${encodeURIComponent(player)}">${player}</a>`); let links = cell.getValue().map(player => `<a href="/player/${encodeURIComponent(player)}">${player}</a>`);

View file

@ -76,10 +76,10 @@
]; ];
// Main table // Main table
{{ games_table_js("tabledata", "overview", True, False) }} {{ games_table_js("tabledata", "overview", True, False, False) }}
{% for num_players in variant_stats_by_player.keys() %} {% for num_players in variant_stats_by_player.keys() %}
{{ games_table_js("tabledata", num_players, False, True) }} {{ games_table_js("tabledata", num_players, False, True, False) }}
// Filter table on corresponding page to only display games with corresponding player number // Filter table on corresponding page to only display games with corresponding player number
table_{{num_players}}.setFilter("num_players", "=", {{num_players}}); table_{{num_players}}.setFilter("num_players", "=", {{num_players}});
{% endfor %} {% endfor %}