import type { ILeagueDriverSeasonStatsPresenter, LeagueDriverSeasonStatsItemViewModel, LeagueDriverSeasonStatsViewModel, } from '@gridpilot/racing/application/presenters/ILeagueDriverSeasonStatsPresenter'; export class LeagueDriverSeasonStatsPresenter implements ILeagueDriverSeasonStatsPresenter { private viewModel: LeagueDriverSeasonStatsViewModel | null = null; present( leagueId: string, standings: Array<{ driverId: string; position: number; points: number; racesCompleted: number; }>, penalties: Map, driverResults: Map>, driverRatings: Map ): LeagueDriverSeasonStatsViewModel { const stats: LeagueDriverSeasonStatsItemViewModel[] = standings.map((standing) => { const penalty = penalties.get(standing.driverId) ?? { baseDelta: 0, bonusDelta: 0 }; const totalPenaltyPoints = penalty.baseDelta; const bonusPoints = penalty.bonusDelta; const racesCompleted = standing.racesCompleted; const pointsPerRace = racesCompleted > 0 ? standing.points / racesCompleted : 0; const ratingInfo = driverRatings.get(standing.driverId) ?? { rating: null, ratingChange: null }; const results = driverResults.get(standing.driverId) ?? []; let avgFinish: number | null = null; if (results.length > 0) { const totalPositions = results.reduce((sum, r) => sum + r.position, 0); const avg = totalPositions / results.length; avgFinish = Number.isFinite(avg) ? Number(avg.toFixed(2)) : null; } return { leagueId, driverId: standing.driverId, position: standing.position, driverName: '', teamId: '', teamName: '', totalPoints: standing.points + totalPenaltyPoints + bonusPoints, basePoints: standing.points, penaltyPoints: Math.abs(totalPenaltyPoints), bonusPoints, pointsPerRace, racesStarted: results.length, racesFinished: results.length, dnfs: 0, noShows: 0, avgFinish, rating: ratingInfo.rating, ratingChange: ratingInfo.ratingChange, }; }); stats.sort((a, b) => a.position - b.position); this.viewModel = { leagueId, stats, }; return this.viewModel; } getViewModel(): LeagueDriverSeasonStatsViewModel { if (!this.viewModel) { throw new Error('Presenter has not been called yet'); } return this.viewModel; } }