stats: implement total number of moves

This commit is contained in:
Maximilian Keßler 2023-11-23 21:33:32 +01:00
parent cabec71e4f
commit 16105d1965
Signed by: max
GPG key ID: BCC5A619923C0BA5
2 changed files with 48 additions and 8 deletions

View file

@ -340,13 +340,13 @@ CREATE TABLE user_statistics (
user_id INTEGER NOT NULL REFERENCES users (id), user_id INTEGER NOT NULL REFERENCES users (id),
/** We track stats separately for each variant type */ /** We track stats separately for each variant type */
variant_type SMALLINT NOT NULL, variant_type SMALLINT NOT NULL,
current_streak INTEGER NOT NULL, current_streak INTEGER,
games_played INTEGER NOT NULL, games_played INTEGER,
games_won INTEGER NOT NULL, games_won INTEGER,
total_bdr INTEGER NOT NULL, total_bdr INTEGER,
/** Number of critical cards that were either discarded or misplayed */ /** Number of critical cards that were either discarded or misplayed */
total_crits_lots INTEGER NOT NULL, total_crits_lots INTEGER,
total_game_moves INTEGER NOT NULL, total_game_moves INTEGER,
PRIMARY KEY (user_id, variant_type) PRIMARY KEY (user_id, variant_type)
); );

View file

@ -2,7 +2,7 @@ import enum
from typing import List, Tuple from typing import List, Tuple
from hanabi import hanab_game from hanabi import hanab_game
import utils
from database import conn_manager from database import conn_manager
@ -63,10 +63,50 @@ def analyze_game(instance: hanab_game.HanabiInstance, actions: List[hanab_game.A
return GameAnalysisResult(outcomes, bdrs) return GameAnalysisResult(outcomes, bdrs)
def update_user_statistics(user_ids: List[int]): def update_user_statistics():
""" """
Update the cumulative user statistics for this user, assuming that the corresponding game statistics have Update the cumulative user statistics for this user, assuming that the corresponding game statistics have
been computed already. been computed already.
@param user_ids: @param user_ids:
@return: @return:
""" """
# Note that some of these statistics could be computed by updating them on each new game insertion.
# However, it would be tedious to ensure that *every* new game triggers an update of these statistics.
# Also, this would be error-prone, since doing a mistake once means that values will be off forever
# (unless the DB is reset).
# Since it is cheap to accumulate some values over the whole DB, we therefore recreate the statistics as a whole,
# reusing only the individual results (that never change and therefore can only be missing, but never wrong)
cur = conn_manager.get_new_cursor()
# Update total number of moves
for clue_starved in [True, False]:
# We insert 0 here to ensure that we have an entry for each player
# Note that this will immediately be changed by the next query in case it is nonzero,
# so the zero value never shows up in the database if it was nonzero before.
cur.execute(
"INSERT INTO user_statistics (user_id, variant_type, total_game_moves)"
" ("
" SELECT id, %s, %s FROM users"
" )"
"ON CONFLICT (user_id, variant_type) DO UPDATE "
"SET total_game_moves = EXCLUDED.total_game_moves",
(utils.get_rating_type(clue_starved), 0)
)
cur.execute(
"INSERT INTO user_statistics (user_id, variant_type, total_game_moves)"
" ("
" SELECT users.id, %s, SUM(games.num_turns) FROM users "
" LEFT OUTER JOIN game_participants "
" ON game_participants.user_id = users.id "
" LEFT OUTER JOIN games "
" ON game_participants.game_id = games.id "
" LEFT OUTER JOIN variants"
" ON variants.id = games.variant_id "
" WHERE variants.clue_starved = %s OR variants.clue_starved IS NULL"
" GROUP BY users.id "
" ) "
"ON CONFLICT (user_id, variant_type) DO UPDATE "
"SET total_game_moves = EXCLUDED.total_game_moves",
(utils.get_rating_type(clue_starved), clue_starved)
)
conn_manager.get_connection().commit()