pridanie rebricka (leaderboard)

Nova polozka menu Rebricek a stranka /leaderboard: top 10 podla najlepsej hry (hry len s ludmi / s aspon jednym botom) a podla hodin v hre (hry do 3 h). Backend api/leaderboard.py + socket udalost get_leaderboard, testy v tests/test_history.py.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YzEAACE9VgnLtXPuWGjwy
This commit is contained in:
timandClaude Sonnet 5.5 committed 2026-10-26 22:06:50 +01:00
1 parent 4000da0454
commit 04846aee26
11 files changed
+614 -12

No files matched your search

+1
View File
@@ -63,6 +63,7 @@ Async SQLAlchemy 2.0, independent of Socket.IO (mirrors how the engine is kept c
- Handlers: auth (`register_account`, `confirm_account`, `login`), lobby (`create_game`, `register_player`, `leave_game`, `start_game`, `end_game`), reconnect (`reconnect_to_game` via per-game token, `rejoin_game` via account), play (`game_status`, `player_cards`, `add_guess`, `play_card`), history (`get_player_history`, `get_game_detail`). Creating/joining/playing requires a logged-in `accounts[sid]`.
- **`api/auth.py`** — TOTP auth (`pyotp`), passwordless. `register_account` issues a secret + `otpauth://` URI (frontend renders the QR); `confirm_account`/`login` verify the 6-digit code and return a session token stored on `Player.auth_token`; `player_by_token` resolves the token sent in the Socket.IO `auth` handshake on `connect`.
- **`api/history.py`** — persistence orchestration over `db/`, reading values from the engine (never mutating it): `record_game_started`, `record_completed_rounds` (also tracks `series`/`round` position and sets `ended_at`), `mark_game_ended`, `get_standings` (DB-backed standings so the score survives a restart), `get_player_history`, `get_game_detail`. **Restore**: `rebuild_core(series, round)` reconstructs a `Bridzik` to a position (cards re-dealt fresh — the only non-deterministic part); `restore_game_core` / `get_unfinished_games` drive restore-on-startup.
- **`api/leaderboard.py`** — rebríčky (socket udalosť `get_leaderboard`, iba čítanie). Len z naplno dohraných hier (`FULL_GAME_ROUNDS` kôl): top 10 podľa najlepšej hry hráča osobitne pre hry len s ľuďmi a hry s aspoň jedným botom (konto `bot:*`; boti sa v rebríčku nezobrazujú) a rebríček hodín (`ended_at - created_at`, aj hry s botmi, len hry do `MAX_GAME_DURATION` = 3 h, takže hra cez polnoc sa počíta, obnovená po dlhej pauze nie). Pozor: `Game.created_at` zapisuje DB (`server_default=now()`) v jej časovej zóne (prod Postgres Europe/Bratislava), `ended_at` Python ako naivný UTC, preto `_created_at_utc` na PostgreSQL prevádza `created_at` na UTC. Každý rebríček vracia `top` aj `me` (poradie prihláseného hráča). `get_leaderboard` číta DB, `build_leaderboard` radí čisté dáta (testy v `tests/test_history.py`, trieda `LeaderboardCase`).
### Frontend — `frontend/`