leader cards: implement ties

This commit is contained in:
Maximilian Keßler 2023-12-26 12:49:39 +01:00
parent 1c1d9664bd
commit 498f460ccd
Signed by: max
GPG key ID: BCC5A619923C0BA5
2 changed files with 27 additions and 15 deletions

View file

@ -22,6 +22,7 @@ class PlayerEntry:
player_name: str player_name: str
user_accounts: str user_accounts: str
score: int score: int
rank: int
@property @property
def player_name_encoded(self): def player_name_encoded(self):
@ -259,7 +260,10 @@ def get_rating_lists() -> Dict[int, List[PlayerEntry]]:
} }
for rating_type in rating_types: for rating_type in rating_types:
cur.execute( cur.execute(
"SELECT * FROM (" "SELECT"
" *,"
" rank() OVER (ORDER BY current_rating DESC)"
"FROM ("
" SELECT DISTINCT ON (user_accounts.user_id)" " SELECT DISTINCT ON (user_accounts.user_id)"
" 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,"
@ -275,38 +279,42 @@ def get_rating_lists() -> Dict[int, List[PlayerEntry]]:
"ORDER BY current_rating DESC", "ORDER BY current_rating DESC",
(", ", rating_type) (", ", rating_type)
) )
for (player_name, user_accounts, current_rating) in cur.fetchall(): for (player_name, user_accounts, current_rating, rank) in cur.fetchall():
leaderboard[rating_type].append(PlayerEntry(player_name, user_accounts, round(current_rating))) leaderboard[rating_type].append(PlayerEntry(player_name, user_accounts, round(current_rating), rank))
return leaderboard return leaderboard
def get_leaders(rating_lists: Dict, streak_lists: Dict) -> Dict[int, Dict[str, Leader]]: def get_leaders(rating_lists: Dict[int, List[PlayerEntry]], streak_lists: Dict[int, List[PlayerStreakEntry]]) -> Dict[int, Dict[str, List[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]
leaders[rating_type] = { leaders[rating_type] = {
'Player Rating': Leader('Highest Rating', utils.describe_rating_type(rating_type), leader) 'Player Rating': [
Leader('Highest Rating', utils.describe_rating_type(rating_type), leader)
for leader in rating_list if leader.rank == 1
]
} }
else: else:
leaders[rating_type] = { leaders[rating_type] = {
'Player Rating': Leader('Highest Rating', utils.describe_rating_type(rating_type), PlayerEntry('-', '', 0)) 'Player Rating': [Leader('Highest Rating', utils.describe_rating_type(rating_type), PlayerEntry('-', '', 0, 1))]
} }
for rating_type, streak_list in streak_lists.items(): for rating_type, streak_list in streak_lists.items():
if len(streak_list) != 0: if len(streak_list) != 0:
leader = streak_list[0]
if rating_type not in leaders.keys(): if rating_type not in leaders.keys():
leaders[rating_type] = {} leaders[rating_type] = {}
leaders[rating_type]['Top Streak'] = Leader('Longest Win Streak', utils.describe_rating_type(rating_type), leader) leaders[rating_type]['Top Streak'] = [
Leader('Longest Win Streak', utils.describe_rating_type(rating_type), leader)
for leader in streak_list if leader.rank == 1
]
else: else:
leaders[rating_type]['Top Streak'] = \ leaders[rating_type]['Top Streak'] = \
Leader('Longest Win Streak', utils.describe_rating_type(rating_type), PlayerEntry('-', '', 0)) [Leader('Longest Win Streak', utils.describe_rating_type(rating_type), PlayerEntry('-', '', 0, 1))]
return leaders return leaders
def get_streak_list(): def get_streak_list() -> Dict[int, List[PlayerStreakEntry]]:
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 = {
@ -317,6 +325,7 @@ def get_streak_list():
cur.execute( cur.execute(
"SELECT" "SELECT"
" player_name," " player_name,"
" rank() over (order by maximum_streak DESC) AS rank,"
" user_accounts," " user_accounts,"
" maximum_streak," " maximum_streak,"
" current_streak " " current_streak "
@ -337,11 +346,12 @@ def get_streak_list():
" ) AS streaks " " ) AS streaks "
# As a tiebreak, the streak that was obtained first will be shown. # As a tiebreak, the streak that was obtained first will be shown.
# If this is still the same, then we just use player name for determinancy # If this is still the same, then we just use player name for determinancy
"ORDER BY maximum_streak DESC, maximum_streak_last_game ASC, player_name", "ORDER BY maximum_streak DESC, current_streak DESC, player_name",
(", ", rating_type) (", ", rating_type)
) )
for (player_name, user_accounts, max_streak, current_streak) in cur.fetchall(): for (player_name, rank, user_accounts, max_streak, current_streak) in cur.fetchall():
leaderboard[rating_type].append(PlayerStreakEntry(player_name, user_accounts, max_streak, current_streak)) leaderboard[rating_type].append(PlayerStreakEntry(player_name, user_accounts, max_streak, rank, current_streak))
print(leaderboard)
return leaderboard return leaderboard

View file

@ -50,7 +50,8 @@
<!-- Leader Cards --> <!-- Leader Cards -->
{% for rating_type, leaders in leaders.items() %} {% for rating_type, leaders in leaders.items() %}
<div class="card-deck mb-5"> <div class="card-deck mb-5">
{% for category, data in leaders.items() %} {% for category, leaders in leaders.items() %}
{% for data in leaders %}
<div class="card text-center"> <div class="card text-center">
<div class="card-body"> <div class="card-body">
<h5 class="card-title mb-2">{{ data.title }}</h5> <h5 class="card-title mb-2">{{ data.title }}</h5>
@ -63,6 +64,7 @@
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
{% endfor %}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>