import type { IAllLeaguesWithCapacityAndScoringPresenter, LeagueEnrichedData, LeagueSummaryViewModel, AllLeaguesWithCapacityAndScoringViewModel, } from '@gridpilot/racing/application/presenters/IAllLeaguesWithCapacityAndScoringPresenter'; export class AllLeaguesWithCapacityAndScoringPresenter implements IAllLeaguesWithCapacityAndScoringPresenter { private viewModel: AllLeaguesWithCapacityAndScoringViewModel | null = null; reset(): void { this.viewModel = null; } present(enrichedLeagues: LeagueEnrichedData[]): void { const leagueItems: LeagueSummaryViewModel[] = enrichedLeagues.map((data) => { const { league, usedDriverSlots, season, scoringConfig, game, preset } = data; const configuredMaxDrivers = league.settings.maxDrivers ?? usedDriverSlots; const safeMaxDrivers = Math.max(configuredMaxDrivers, usedDriverSlots); const structureSummary = `Solo • ${safeMaxDrivers} drivers`; const qualifyingMinutes = 30; const mainRaceMinutes = typeof league.settings.sessionDuration === 'number' ? league.settings.sessionDuration : 40; const timingSummary = `${qualifyingMinutes} min Quali • ${mainRaceMinutes} min Race`; let scoringPatternSummary: string | null = null; let scoringSummary: LeagueSummaryViewModel['scoring']; if (season && scoringConfig && game) { const dropPolicySummary = preset?.dropPolicySummary ?? this.deriveDropPolicySummary(scoringConfig); const primaryChampionshipType = preset?.primaryChampionshipType ?? (scoringConfig.championships[0]?.type ?? 'driver'); const scoringPresetName = preset?.name ?? 'Custom'; scoringPatternSummary = `${scoringPresetName} • ${dropPolicySummary}`; scoringSummary = { gameId: game.id, gameName: game.name, primaryChampionshipType, scoringPresetId: scoringConfig.scoringPresetId ?? 'custom', scoringPresetName, dropPolicySummary, scoringPatternSummary, }; } else { const dropPolicySummary = 'All results count'; const scoringPresetName = 'Custom'; scoringPatternSummary = scoringPatternSummary ?? `${scoringPresetName} • ${dropPolicySummary}`; scoringSummary = { gameId: 'unknown', gameName: 'Unknown', primaryChampionshipType: 'driver', scoringPresetId: 'custom', scoringPresetName, dropPolicySummary, scoringPatternSummary, }; } const base: LeagueSummaryViewModel = { id: league.id, name: league.name, description: league.description, ownerId: league.ownerId, createdAt: league.createdAt.toISOString(), maxDrivers: safeMaxDrivers, usedDriverSlots, // Team capacity is not yet modeled here; use zero for now to satisfy strict typing. maxTeams: 0, usedTeamSlots: 0, structureSummary, scoringPatternSummary: scoringPatternSummary ?? '', timingSummary, scoring: scoringSummary, }; return base; }); this.viewModel = { leagues: leagueItems, totalCount: leagueItems.length, }; } getViewModel(): AllLeaguesWithCapacityAndScoringViewModel | null { return this.viewModel; } private deriveDropPolicySummary(config: { championships: Array<{ dropScorePolicy: { strategy: string; count?: number; dropCount?: number }; }>; }): string { const championship = config.championships[0]; if (!championship) { return 'All results count'; } const policy = championship.dropScorePolicy; if (!policy || policy.strategy === 'none') { return 'All results count'; } if (policy.strategy === 'bestNResults' && typeof policy.count === 'number') { return `Best ${policy.count} results count`; } if ( policy.strategy === 'dropWorstN' && typeof policy.dropCount === 'number' ) { return `Worst ${policy.dropCount} results are dropped`; } return 'Custom drop score rules'; } }