include base ratings for players without games

This commit is contained in:
Maximilian Keßler 2023-12-04 01:52:45 +01:00
parent 65f174c95f
commit e8ba8ecee3
Signed by: max
GPG key ID: BCC5A619923C0BA5
3 changed files with 55 additions and 49 deletions

View file

@ -1,7 +1,8 @@
from pathlib import Path from pathlib import Path
from typing import Dict from typing import Dict, List
import jinja2 import jinja2
import datetime
import psycopg2.extras import psycopg2.extras
import constants import constants
@ -12,14 +13,6 @@ from dataclasses import dataclass
from database import conn_manager from database import conn_manager
@dataclass
class Leader:
title: str
player_name: str
user_accounts: str
score: int
@dataclass @dataclass
class PlayerEntry: class PlayerEntry:
player_name: str player_name: str
@ -27,44 +20,52 @@ class PlayerEntry:
score: int score: int
def get_rating_lists(): @dataclass
cur = conn_manager.get_connection().cursor(cursor_factory=psycopg2.extras.DictCursor) class Leader:
cur.execute( title: str
"SELECT * FROM (" entry: PlayerEntry
" SELECT DISTINCT ON (type, user_accounts.user_id)"
" type,"
" player_name," def get_rating_lists() -> Dict[int, List[PlayerEntry]]:
" string_agg(user_accounts.username, %s ORDER BY user_accounts.username) AS user_accounts," cur = conn_manager.get_connection().cursor()
" value_after AS current_rating" rating_types = [utils.get_rating_type(x) for x in [False, True]]
" FROM user_ratings "
" INNER JOIN users "
" ON user_ratings.user_id = users.id "
" LEFT OUTER JOIN user_accounts "
" ON users.id = user_accounts.user_id "
" GROUP BY (user_accounts.user_id, player_name, value_after, league_id, type) "
" ORDER BY type, user_accounts.user_id, league_id DESC"
" ) AS ratings "
"ORDER BY type ASC, current_rating DESC",
(", ",)
)
leaderboard = { leaderboard = {
utils.get_rating_type(x): [] utils.get_rating_type(x): []
for x in [True, False] for x in [True, False]
} }
for row in cur.fetchall(): for rating_type in rating_types:
rating_type = row['type'] cur.execute(
leaderboard[rating_type].append(row) "SELECT * FROM ("
" SELECT DISTINCT ON (user_accounts.user_id)"
" player_name,"
" string_agg(user_accounts.username, %s ORDER BY user_accounts.username) AS user_accounts,"
" COALESCE(value_after, rating) AS current_rating"
" FROM users "
" LEFT OUTER JOIN user_ratings "
" ON user_ratings.user_id = users.id AND user_ratings.type = %s "
" LEFT OUTER JOIN user_accounts "
" ON users.id = user_accounts.user_id "
" INNER JOIN user_base_ratings "
" ON users.id = user_base_ratings.user_id AND user_base_ratings.type = %s"
" GROUP BY (user_accounts.user_id, player_name, value_after, league_id, rating) "
" ORDER BY user_accounts.user_id, league_id DESC"
" ) AS ratings "
"ORDER BY current_rating DESC",
(", ", rating_type, rating_type)
)
for (player_name, user_accounts, current_rating) in cur.fetchall():
leaderboard[rating_type].append(PlayerEntry(player_name, user_accounts, round(current_rating)))
return leaderboard return leaderboard
def get_leaders(rating_lists: Dict): def get_leaders(rating_lists: Dict) -> Dict[int, Dict[str, Leader]]:
leaders = {} leaders = {}
for rating_type, rating_list in rating_lists.items(): for rating_type, rating_list in rating_lists.items():
if len(rating_list) != 0: if len(rating_list) != 0:
leader = rating_list[0] leader = rating_list[0]
leaders[rating_type] = { leaders[rating_type] = {
'Player Rating': Leader('Highest Rating', leader['player_name'], leader['user_accounts'], round(leader['current_rating'])) 'Player Rating': Leader('Highest Rating', leader)
} }
return leaders return leaders
@ -87,11 +88,18 @@ def get_streak_leaderboards():
def get_total_games(): def get_total_games():
cur = conn_manager.get_new_cursor() cur = conn_manager.get_new_cursor()
cur.execute("SELECT MAX(league_id) FROM games") cur.execute("SELECT COUNT(league_id) FROM games")
(num_games,) = cur.fetchone() (num_games,) = cur.fetchone()
return num_games return num_games
def get_num_players():
cur = conn_manager.get_new_cursor()
cur.execute("SELECT COUNT(id) FROM users")
(num_users,) = cur.fetchone()
return num_users
def render_leaderboard(): def render_leaderboard():
rating_lists = get_rating_lists() rating_lists = get_rating_lists()
leaders = get_leaders(rating_lists) leaders = get_leaders(rating_lists)
@ -105,13 +113,11 @@ def render_leaderboard():
# rendered_html = template.render(leaders=leaders, leaderboards=leaderboards, variants=variants) # rendered_html = template.render(leaders=leaders, leaderboards=leaderboards, variants=variants)
rendered_html = template.render( rendered_html = template.render(
leaders=leaders, leaders=leaders,
leaderboards=leaderboards leaderboards=leaderboards,
# leaders=leaders, total_games_played=get_total_games(),
# leaderboards=leaderboards, total_players=get_num_players(),
latest_run=datetime.datetime.now().isoformat()
# variants=variants, # variants=variants,
# total_games_played=constants['total_games_played'],
# latest_run=latest_run_utc_formatted,
# total_players=total_players
) )
output_file = Path(constants.WEBSITE_OUTPUT_DIRECTORY) / 'index.html' output_file = Path(constants.WEBSITE_OUTPUT_DIRECTORY) / 'index.html'
output_file.parent.mkdir(exist_ok=True, parents=True) output_file.parent.mkdir(exist_ok=True, parents=True)

View file

@ -10,9 +10,9 @@
<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.player_name }}</p> <p class="mb-0 player-name">{{ data.entry.player_name }}</p>
<p class="mt-1 alt-name">{{ data.user_accounts }}</p> <p class="mt-1 alt-name">{{ data.entry.user_accounts }}</p>
<p class="score-large">{{ data.score }}</p> <p class="score-large">{{ data.entry.score }}</p>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
@ -30,13 +30,13 @@
<div id="{{ category|lower|replace(' ', '-') }}" class="collapse" data-parent="#leaderboards-{{rating_type}}-data"> <div id="{{ category|lower|replace(' ', '-') }}" class="collapse" data-parent="#leaderboards-{{rating_type}}-data">
<div class="card-body"> <div class="card-body">
<table class="table table-striped"> <table class="table table-striped">
{% for row in leaderboard[rating_type] %} {% for entry in leaderboard[rating_type] %}
<tr> <tr>
<td> <td>
<div class="player-name">{{ row['player_name'] }}</div> <div class="player-name">{{ entry.player_name }}</div>
<div class="alt-name">{{ row['user_accounts'] }}</div> <div class="alt-name">{{ entry.user_accounts }}</div>
</td> </td>
<td class="score">{{ row['current_rating'] }}</td> <td class="score">{{ entry.score }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View file

@ -10,7 +10,7 @@
<body> <body>
<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"> - Test Season Zero</small></a> <a class="navbar-brand" href="#">The Hanabi Pro Hunting League<small class="text-muted"> - Season One</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>