bug: leaderboard sources, tournament winner reassignment, no-show penalties - #388
Merged
Conversation
…alties Leaderboard - Drop the 50 round floor that hid every new player from the board - Add a source filter so a board can be scoped to matchmaking, scrims or tournaments instead of only the combined total - Fix rolling window standings so a mid window elo reset is reflected rather than being flattened by the first in window row - Track peak elo excluding tournaments alongside the overall peak - Surface the player custom avatar on every leaderboard producer Tournaments - can_reassign_winner looked the bracket up backwards and refused reassignment on brackets that were perfectly valid. It now resolves the parent and loser parent brackets from the match and treats a match with no bracket row as reassignable - Add refresh_tournament_match_lineup_teams so a roster swap reuses the existing lineup rows and only deletes surplus rows last, which keeps the swap from tripping the minimum player delete guard Matches - Cancel expired matches now force starts a minute before the deadline when every expected player is connected, so a lobby that is ready is not cancelled out from under it - When a match is cancelled without starting, penalise only the players who were not connected at cancellation rather than the whole lineup - Track connection state on the lineup so the cancel job knows who was actually present - Apply the leaver elo penalty at change finalisation for abandoned matches - Stamp demo_processing_started_at when a map moves to WaitingForTV Other - Fix the best of three veto pattern for a five map pool so the two extra bans happen before the picks - Exclude coaches from team rank averages and add wingman and duel averages - Add banned_until, is_admin_sanctioned and is_registered computed fields - Index registration state into player search instead of filtering unregistered players out entirely - Only forfeit on a live ban when no unbanned players remain
lukepolo
force-pushed
the
fork-triage-bugs
branch
from
August 12, 2026 14:43
a371f6b to
ff70d93
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rebased onto
mainnow that #387 has merged. The veto and match-options work from #387 is not duplicated here; the changes below sit on top of it.Leaderboard
The board had a
HAVING SUM(rounds_played) >= 50floor on it, which meant a new player was invisible until their fiftieth round. Removed.Alongside that, leaderboards can now be scoped to a source — matchmaking, tournament, league, or the combined overall — rather than only ever showing the total. Every leaderboard function takes
_source TEXT DEFAULT 'overall', so existing callers are unaffected, and two classifier helpers decide which bucket a given match or tournament falls into.Two correctness fixes came out of writing tests for it:
starting_elowas taken from the first in-window row, so a reset that happened inside the window was invisible — the player's delta was computed against the wrong baseline.Also surfaces
player_custom_avatar_urlon every producer.Tournaments
can_reassign_winnerlooked the bracket up backwards. It walked from bracket to match instead of match to bracket, so it refused reassignment on brackets that were perfectly valid. Now resolves the parent and loser-parent brackets from the match, and a match with no bracket row is treated as reassignable.Roster swaps tripped the minimum-player guard. Refreshing a tournament match lineup deleted the old rows before inserting the new ones, which briefly dropped the lineup below the minimum and fired the delete guard.
refresh_tournament_match_lineup_teamsnow does it in place — reuse the existing rows, insert any surplus, and only delete surplus rows last.Match cancellation and no-shows
This is the bigger behavioural change, so it is worth stating the rule plainly:
If you were connected when the match was cancelled, you are not penalised. If you were not, you are.
Per player, not per team. Disconnects after the match goes live are already handled elsewhere — this is strictly about a match that never got going.
Three parts:
The cancel job also carries a 180-minute hung-match net, which is a different thing entirely —
isAwaitingWarmup()distinguishes the two so the force-start path does not fire on a hung match.Separately, the leaver elo penalty is now applied at change finalisation for abandoned matches, reading
leaver_elo_penalty(default 150) from settings.Everything else
Ban, Pick, Pick, Ban. The documented order is two bans, then the picks. Fixed toBan, Ban, Pick, Pick— the docs were right and the code was wrong.banned_until,is_admin_sanctioned,is_registered.demo_processing_started_atis stamped when a map moves toWaitingForTV.Tests
tournament-winner-reassignment.spec.ts— new, 4 testsCancelExpiredMatches.spec.ts— 15 tests covering force-start, no-show recording, and the hung-match pathviews.spec.ts— +357 lineselo.spec.ts— abandoned-match penaltyEach fix was verified by reverting it and confirming the corresponding test fails.
Migrations
Four, numbered
1876000000400through1876000000700.