Repository navigation
Scoring Rewrite - #459
Merged
Merged
Scoring Rewrite#459
Conversation
Full Release of v0.8.0
Release v0.8.1
MetalLB >= 0.13 (annotation-based, recommended):
service:
type: LoadBalancer
annotations:
metallb.universe.tf/loadBalancerIPs: 192.168.1.100
# optionally pin to a specific pool:
# metallb.universe.tf/address-pool: default
MetalLB < 0.13 (spec-based):
service:
type: LoadBalancer
loadBalancerIP: "192.168.1.100"
Multiple LB controllers (need to tell MetalLB it's in charge):
service:
type: LoadBalancer
loadBalancerClass: "metallb"
The externalTrafficPolicy: Local option is also there if you want to preserve client source IPs (common when your ingress controller sits behind the LB).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…st alias Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rovements to bring it in line with matches
Adds scoring_type-aware infrastructure across the full stack, replacing hardcoded blue/red team model with N-team support and a new Series entity for multi-event championships. Key changes: - Migrations 019-022: match_teams, match_game_placements, cumulative-points tournament format, backfill, and series tables - scoring-functions.ts: dual-write placements for Normal/FFA/Position; getGameResult() returns typed discriminated union - match-setup.ts: createMatchTeams(), assignParticipantToTeam(), getMatchTeams(), setTeamVoiceChannel(), MAX_VOICE_CHANNELS_PER_MATCH - transition-handlers.ts: createMatchTeams() on assign transition, dual-write voice channel IDs to match_teams - announcement-helpers.ts: fetchMatchTeamRows() reads from match_teams; fetchMatchStartData() uses team names/voice channels from new table - tournament-bracket.ts: generateCumulativeMatches() + addAllTeamsToMatch() - standings/leaderboard routes: cumulative-points format support - Series library + REST API (/api/series) - AI extractor: scoring_type-aware prompt + placements write-back - UI: TeamMapScoring/FfaMapScoring components, scoring page dispatcher, teamCount/positionScoringOverride in match creation form Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Series: full UI at /series (dashboard, create, detail, edit, history); navigation entry added with IconTimeline; API already existed from Phase 6 - Setup phase: new src/components/setup/ with setup-phase.tsx dispatcher, confirm-participants.tsx, grid-order.tsx, qualifying.tsx, classes.tsx - Tournament: add 'cumulative-points' to format selector and API validation; update TournamentFormat type in shared/types.ts - CLAUDE.md: document scoring_type system, match_teams, match_game_placements, Series system, Phase 8 pending note, updated schema and migration count All 2215 tests pass; typecheck clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix savePlacementsForNormal to look up match_teams by team_order instead of hardcoded backfill IDs (mt_blue_/mt_red_) which don't exist for new matches created via createMatchTeams() - Fix getSeriesStandings to group by user_id instead of participant_id so standings aggregate correctly across multiple events for the same player; update series-detail-page.tsx to match - Add tests/unit/lib/match-setup.test.ts: full coverage of createMatchTeams (Normal, FFA, idempotency, team_count), assignParticipantToTeam, getMatchTeams ordering, and setTeamVoiceChannel - Add tests/unit/lib/series.test.ts: full coverage of series CRUD, addSeriesEvent, listSeriesEvents, removeSeriesEvent, and getSeriesStandings (points aggregation, multiplier, ranking) - Add tests/integration/api/series.test.ts: integration tests for all series API endpoints (CRUD, events, standings) - Add migration assertions for new scoring-rewrite tables and columns to tests/integration/database/migrations.test.ts - Add cumulative-points tournament format test to tournaments.test.ts - Add match_teams creation tests to transition-handlers.test.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The v082 scoring rewrite built a solid schema and dual-write engine but left the actual UI and lifecycle disconnected from it: the live assign page was still the pre-rewrite hardcoded Blue/Red UI, the "new" scoring components were stub wrappers around the untouched legacy component, and the core engine hardcoded every write/read to exactly two teams despite match_teams supporting N. - scoring-functions.ts: savePlacementsForNormal/getOverallMatchScore/ determineMatchWinner now handle arbitrary team counts instead of only team_order 0/1; Position placements also derive team-level rows for team-endurance matches (participants grouped into match_teams) - result API route now actually uses winnerTeamId/loserTeamId/scores instead of silently dropping them and defaulting to team1 - match-setup.ts: team_count/max_teams are now consulted when creating match_teams (was always hardcoded to 2); added team-endurance team creation that distributes participants across N teams - voice-channel-manager.ts + Discord bot queue processor: channel creation is N-team aware (capped), and the buggy sync loop that collided every team beyond order 0 onto the same Discord channel is gone - assign page now dispatches on scoring_type: Normal renders an N-team assignment board (was hardcoded to Reserve/Blue/Red, forcing FFA matches through a nonsensical team-assignment UI), FFA/Position render the previously-unwired SetupPhase dispatcher - GET /api/matches/[matchId] now joins game_modes so scoring_type/ setup_components actually reach the client - TeamMapScoring/FfaMapScoring are real components now instead of both wrapping the untouched legacy SimpleMapScoring; TeamMapScoring renders a win-card per match_teams row and submits winnerTeamId Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D9hMfCteigpmYvw2v5z4Vk
…ation data loss Tournaments: the cumulative-points (FFA/Position) standings API returned a totally different shape than the bracket-format one, but the frontend always rendered the bracket-format TeamStanding fields — cumulative tournaments showed a blank standings tab and an empty bracket tab. Added a dedicated LeaderboardView and gated the Teams/Bracket tabs to bracket formats only. Also found and fixed a real bug in the cumulative standings query itself: the status='completed' filter was applied to the wrong JOIN and never actually excluded pending games' placements from the point total. tournaments.position_scoring_override was schema that nothing read or wrote — the documented match → tournament → game fallback chain was actually only two levels. Wired it into both scoring-functions.ts resolvers and the tournament create/edit APIs. Also added a cross-check between tournament format and the mode's scoring_type: previously an FFA/Position mode with a bracket format either threw an opaque error or silently built a nonsense 1-person bracket. Migration 021: fixed the inconsistent JOIN types (LEFT for Normal, INNER for FFA/Position) that could silently default an orphaned-mode FFA/Position match to Normal — fabricating Blue/Red teams for it while permanently skipping the migration of its real result data. Every match's scoring_type is now resolved once (inferring from match_games shape when the mode row is gone) and used consistently across every backfill section. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D9hMfCteigpmYvw2v5z4Vk
The scoring rewrite plan called for an ai_processor_version setting so the scoring_type-aware extraction prompt could be rolled back if it produced worse results than the old mode-blind one — that setting never existed anywhere outside the plan doc, so there was no way to roll back a bad extraction-quality regression short of a code deploy. Added it as a real stats_settings column, wired into the extractor (legacy forces the original mode-blind blue/red-only prompt) and exposed via the stats settings page. scorecard_player_stats.team_id — the new authoritative FK the plan says replaces team_side — was never written by the extractor; it resolves the match's actual match_teams row from team_side now, so team_id is populated for Normal-mode matches going forward. (Went with resolving team_id from the existing blue/red team_side rather than rewriting the AI prompt to handle arbitrary N teams: the DM submission flow, review UI, and winner-vote handler are all blue/red-only throughout, so a partial N-team rewrite of just the prompt would produce data the rest of that pipeline can't use.) stat-image-generator.ts had zero scoring_type branching — FFA/Position matches got a "Team: RED/BLUE" column that's meaningless for them, reading team_assignment values that don't apply to those modes. Non-Normal matches now skip that column instead of showing nonsense. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D9hMfCteigpmYvw2v5z4Vk
…er race fix getSeriesStandings ignored series.scoring_config entirely — it summed match_game_placements.points_awarded directly, a field only Position-mode scoring ever populates. Every Normal (win/loss) or FFA match added to a series silently contributed 0 points regardless of who won. Implemented the documented conversion rules: match_win_points/match_loss_points for Normal/FFA match events (via the match's overall winner), each match's own point spread for Position events (position_event_use_event_spread), and tournament_position_points for tournament events — per-participant rank for cumulative-points tournaments, champion-only recognition for bracket tournaments (full bracket placement — runner-up, 3rd/4th — needs dedicated placement logic beyond this fix's scope). Added a scoring-config-editor to the series create/edit pages so this is actually reachable from the UI, which it wasn't before. Added POST /api/series/[seriesId]/transition with real transition-legality validation (created → active → complete, cancel from non-terminal states only) and stripped status from the plain PATCH endpoint, which previously let status jump to any value with no validation at all. Fixed a real race in addSeriesEvent: two concurrent calls with no explicit event_order can both read the same MAX(event_order) before either INSERT commits, so the loser hit an unhandled UNIQUE constraint 500. It now retries with a freshly computed order when the conflict is on an auto-assigned order; an explicitly-requested order that conflicts still errors. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D9hMfCteigpmYvw2v5z4Vk
…2z0a5 Phase 1: Scoring & Match Type System Rewrite
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
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.
Completely rewrite scoring systems to better support how this app has grown.
Also add initial support for series. Create entire seasons of events with leaderboards and tracking.