import { League } from '@core/racing/domain/entities/League'; import { Race } from '@core/racing/domain/entities/Race'; import { Result as RaceResult } from '@core/racing/domain/entities/result/Result'; import { Standing } from '@core/racing/domain/entities/Standing'; import { getPointsSystems } from '../PointsSystems'; export class RacingStandingFactory { create(leagues: League[], races: Race[], results: RaceResult[]): Standing[] { const pointsSystems = getPointsSystems(); const racesByLeague = new Map>(); for (const race of races) { if (!race.status.isCompleted()) continue; const set = racesByLeague.get(race.leagueId) ?? new Set(); set.add(race.id); racesByLeague.set(race.leagueId, set); } const standings: Standing[] = []; for (const league of leagues) { const leagueId = league.id.toString(); const completedRaceIds = racesByLeague.get(leagueId) ?? new Set(); if (completedRaceIds.size === 0) continue; const pointsTable = this.resolvePointsSystem(league, pointsSystems); const byDriver = new Map(); for (const result of results) { if (!completedRaceIds.has(result.raceId.toString())) continue; const driverId = result.driverId.toString(); const previousStanding = byDriver.get(driverId) ?? Standing.create({ leagueId, driverId, position: 1 }); const nextStanding = previousStanding.addRaceResult(result.position.toNumber(), pointsTable); byDriver.set(driverId, nextStanding); } const sorted = Array.from(byDriver.values()).sort((a, b) => { if (b.points.toNumber() !== a.points.toNumber()) return b.points.toNumber() - a.points.toNumber(); if (b.wins !== a.wins) return b.wins - a.wins; return b.racesCompleted - a.racesCompleted; }); sorted.forEach((standing, index) => standings.push(standing.updatePosition(index + 1))); } return standings; } private resolvePointsSystem( league: League, pointsSystems: Record>, ): Record { const settings = league.settings; return settings.customPoints ?? pointsSystems[settings.pointsSystem] ?? pointsSystems['f1-2024'] ?? {}; } }