5.4 KiB
League Standings Issues Summary
Quick Overview
The leagues feature's standings calculation has 7 critical issues that prevent accurate season-specific standings.
Issues Found
1. ❌ InMemoryStandingRepository.recalculate() Doesn't Consider Seasons
File: adapters/racing/persistence/inmemory/InMemoryStandingRepository.ts:169-270
Problem: Calculates standings from ALL completed races in a league, not just races from a specific season.
Impact: Standings mix results from all seasons, making them inaccurate for any specific season.
2. ❌ CompleteRaceUseCase Uses Hardcoded Points System
File: core/racing/application/use-cases/CompleteRaceUseCase.ts:200-203
Problem: Uses hardcoded F1 points system instead of league's configured points system.
Impact: All leagues use same points system regardless of configuration (F1, IndyCar, custom).
3. ❌ ImportRaceResultsUseCase Recalculates All League Standings
File: core/racing/application/use-cases/ImportRaceResultsUseCase.ts:156
Problem: Recalculates ALL standings for the league when importing one race.
Impact: Performance issue + includes results from all seasons.
4. ❌ Standing Entity Doesn't Track Season Association
File: core/racing/domain/entities/Standing.ts
Problem: Standing entity only tracks leagueId and driverId, no seasonId.
Impact: Can't distinguish between standings from different seasons.
5. ❌ GetLeagueStandingsUseCase Retrieves League-Level Standings
File: core/racing/application/use-cases/GetLeagueStandingsUseCase.ts:39
Problem: Retrieves standings that include results from all seasons.
Impact: Returns inaccurate standings for any specific season.
6. ❌ LeagueStandingsRepository Not Connected to Standing Calculation
File: adapters/racing/persistence/inmemory/InMemoryLeagueStandingsRepository.ts
Problem: Repository exists but not used by standing calculation logic.
Impact: No clear connection between standing calculation and this repository.
7. ❌ LeagueStandingsPresenter Hardcodes Metrics
File: apps/api/src/domain/league/presenters/LeagueStandingsPresenter.ts:24-30
Problem: Hardcodes wins, podiums, and races to 0.
Impact: API always returns 0 for these metrics.
Root Cause
Design Inconsistency: Two parallel standings systems that don't align:
-
League-level standings (
Standingentity):- Updated immediately when races complete
- Used by
GetLeagueStandingsUseCase - Don't support season-specific features
-
Season-level standings (
ChampionshipStandingentity):- Calculated using
RecalculateChampionshipStandingsUseCase - Support drop score policies per season
- Not used by main standings API
- Calculated using
Recommended Fixes
Short-term (Quick Wins)
- ✅ Fix CompleteRaceUseCase to use league's points system
- ✅ Fix ImportRaceResultsUseCase to recalculate only relevant standings
- ✅ Add seasonId to Standing entity
- ✅ Fix GetLeagueStandingsUseCase to accept seasonId parameter
Long-term (Refactoring)
- ✅ Consolidate standings into single system (use ChampionshipStanding)
- ✅ Update CompleteRaceUseCase to use RecalculateChampionshipStandingsUseCase
- ✅ Update ImportRaceResultsUseCase to use RecalculateChampionshipStandingsUseCase
- ✅ Update GetLeagueStandingsUseCase to retrieve ChampionshipStanding
- ✅ Remove LeagueStandingsRepository
- ✅ Fix LeagueStandingsPresenter to return actual metrics
Testing Strategy
Unit Tests
- Test CompleteRaceUseCase with different points systems
- Test ImportRaceResultsUseCase with season-specific recalculation
- Test GetLeagueStandingsUseCase with seasonId parameter
- Test Standing entity with seasonId field
Integration Tests
- Test complete race flow with season-specific standings
- Test import race results flow with season-specific standings
- Test standings recalculation for specific season
- Test API endpoints with season-specific standings
End-to-End Tests
- Test league standings API with season parameter
- Test standings calculation across multiple seasons
- Test drop score policy application per season
Files to Modify
Core Domain
core/racing/domain/entities/Standing.ts- Add seasonId fieldcore/racing/domain/repositories/StandingRepository.ts- Update interface
Application Layer
core/racing/application/use-cases/CompleteRaceUseCase.ts- Use league points systemcore/racing/application/use-cases/ImportRaceResultsUseCase.ts- Season-specific recalculationcore/racing/application/use-cases/GetLeagueStandingsUseCase.ts- Accept seasonId parameter
Persistence Layer
adapters/racing/persistence/inmemory/InMemoryStandingRepository.ts- Update recalculate methodadapters/racing/persistence/inmemory/InMemoryLeagueStandingsRepository.ts- Remove or refactor
API Layer
apps/api/src/domain/league/presenters/LeagueStandingsPresenter.ts- Return actual metrics
Priority
HIGH: Issues 1, 2, 4, 5 (affect accuracy of standings) MEDIUM: Issues 3, 6 (affect performance and architecture) LOW: Issue 7 (affects API response quality)
Next Steps
- Create implementation plan for short-term fixes
- Design long-term refactoring strategy
- Update tests to cover season-specific scenarios
- Implement fixes incrementally
- Verify standings accuracy after each fix