Repository navigation
v1.5.3
v1.5.3
Bug Fixes
Glicko-2: Winner RD and Volatility Never Updated
calc_elo() was assigning winner_ladder.rd = winner_ladder.rd and winner_ladder.vol = winner_ladder.vol (self-assignment), so the winner's RD and volatility never changed after any game. Fixed to use winner_player.rd and winner_player.vol. This is a major bug that affected all player ELOs in all game modes.
recalc_elo(): Integer Truncation Mismatch
Ladder ratings are stored as Integer columns, so each DB commit truncates Glicko-2 floats. recalc_elo() was accumulating full-precision floats across all games, producing different results than process_game() which commits game-by-game. Fixed by explicitly truncating to int after each game during recalculation.
Ladder Query: admin_accept = NULL → admin_accept IS NULL
The ladder CTE in tag.py used = NULL instead of IS NULL, causing the admin_accept condition to always evaluate to UNKNOWN in SQL and effectively excluding all user-accepted games from the ladder. Fixed in four places.
db_setup.py: TrustedUser Group Never Created
The banned variable was reassigned to the TrustedUser group object before being added to the session, so banned was never added and TrustedUser was added twice. Fixed to use a separate trusted_user variable.
Status Codes Standardized
New Features
Manual Game Submission via /populate_db/
Admins and Trusted Users can now submit existing stat files directly via POST /populate_db/?submitter_rio_key=<key>. The stat file JSON is unchanged; usernames in the Home Player/Away Player fields are resolved against the database and swapped for rio_keys before ingestion proceeds.
/manual_submit_game/ — Full Rewrite
The manual game history submission endpoint now:
- Performs additional game validations
- Correctly scopes submitter authorization: site Admins/TrustedUsers, community admins, and the players themselves can all submit; ELO is only calculated immediately when an admin submits
- Uses
flush()/ singlecommit()for atomicity
/update_game_status/ — Full Rewrite
Game acceptance confirmation endpoint now:
- Accepts only
game_history_idinstead ofgame_idsince game_id for manual submissions is always None - Allows site Admins and TrustedUsers (not just community admins) to override game status
- Uses
flush()/singlecommit()with rollback on error
/move_games/ (renamed from /reassign_game_history_game_mode/)
- Major bug fixes to the endpoint
- Accepts a single
game_id(int) or a listgame_ids(list of ints) in one request - Validates all games and community membership before making any changes
- Recalculates ELO once per affected TagSet rather than once per game
- Returns descriptive 400/404 errors instead of 409 for everything
/upload_status/ (new)
Public endpoint showing ingestion pipeline health: pending file count, defect file count, and ongoing games. Admin callers additionally receive filenames, file sizes, error messages, and game metadata from defect files.
/system_status/ (new)
Public health-check endpoint ({"status": "ok"}). Admin callers receive full CPU, memory, disk, disk I/O, network I/O, and database connectivity stats via psutil.
/populate_db/process/ (new, admin-only)
Admin endpoint to immediately flush all pending game files for processing. Primarily used in integration tests to avoid waiting for the APScheduler tick.
/user/delete (new, Admin-only)
Delete a user account with safety guards: blocks deletion if the user has any game history, is in an ongoing game, or sponsors a community. Cleans up all FK references (groups, community memberships, IP records, API key) before deleting.
Stale Ongoing Game Pruning
The APScheduler job now prunes OngoingGame rows older than 2 hours on every tick, preventing stale entries from accumulating.
Improvements
recalc_elo Refactored to a Pure Internal Function
recalc_elo() is no longer an endpoint itself; it's a plain function that uses flush() and defers commit to the caller. A thin recalc_elo_endpoint() wraps it for the /recalc_elo/ route. This makes it composable (used by /update_game_status/, /move_games/, /manual_submit_game/) without nested transactions.
Linescore Optimization
_build_linescores() and _build_scoring_plays() merged into a single build_linescore_and_scoring_plays() function that runs one DB query for both. Scoreless innings are now correctly filled with 0 using innings_played rather than being omitted. Walk-off innings now correctly display 'X' instead of 0.
get_user_by_username() Added to user_util.py
New helper for case-insensitive, normalized username lookups via SQLAlchemy 2.0 style select().
New Dependency: psutil==5.9.7
Required by /system_status/ for server resource metrics.