import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository'; import type { ISeasonRepository } from '../../domain/repositories/ISeasonRepository'; import type { ILeagueScoringConfigRepository } from '../../domain/repositories/ILeagueScoringConfigRepository'; import type { IGameRepository } from '../../domain/repositories/IGameRepository'; import type { ChampionshipConfig } from '../../domain/value-objects/ChampionshipConfig'; import type { DropScorePolicy } from '../../domain/value-objects/DropScorePolicy'; import type { LeagueConfigFormModel, LeagueDropPolicyFormDTO, } from '../dto/LeagueConfigFormDTO'; /** * Query returning a unified LeagueConfigFormModel for a given league. * * First iteration focuses on: * - Basics derived from League * - Simple solo structure derived from League.settings.maxDrivers * - Championships flags with driver enabled and others disabled * - Scoring pattern id taken from LeagueScoringConfig.scoringPresetId * - Drop policy inferred from the primary championship configuration */ export class GetLeagueFullConfigQuery { constructor( private readonly leagueRepository: ILeagueRepository, private readonly seasonRepository: ISeasonRepository, private readonly leagueScoringConfigRepository: ILeagueScoringConfigRepository, private readonly gameRepository: IGameRepository, ) {} async execute(params: { leagueId: string }): Promise { const { leagueId } = params; const league = await this.leagueRepository.findById(leagueId); if (!league) { return null; } const seasons = await this.seasonRepository.findByLeagueId(leagueId); const activeSeason = seasons && seasons.length > 0 ? seasons.find((s) => s.status === 'active') ?? seasons[0] : null; const scoringConfig = activeSeason ? await this.leagueScoringConfigRepository.findBySeasonId(activeSeason.id) : null; const game = activeSeason && activeSeason.gameId ? await this.gameRepository.findById(activeSeason.gameId) : null; const patternId = scoringConfig?.scoringPresetId; const primaryChampionship: ChampionshipConfig | undefined = scoringConfig && scoringConfig.championships && scoringConfig.championships.length > 0 ? scoringConfig.championships[0] : undefined; const dropPolicy: DropScorePolicy | undefined = primaryChampionship?.dropScorePolicy ?? undefined; const dropPolicyForm: LeagueDropPolicyFormDTO = this.mapDropPolicy(dropPolicy); const defaultQualifyingMinutes = 30; const defaultMainRaceMinutes = 40; const mainRaceMinutes = typeof league.settings.sessionDuration === 'number' ? league.settings.sessionDuration : defaultMainRaceMinutes; const qualifyingMinutes = defaultQualifyingMinutes; const roundsPlanned = 8; let sessionCount = 2; if ( primaryChampionship && Array.isArray((primaryChampionship as any).sessionTypes) && (primaryChampionship as any).sessionTypes.length > 0 ) { sessionCount = (primaryChampionship as any).sessionTypes.length; } const practiceMinutes = 20; const sprintRaceMinutes = patternId === 'sprint-main-driver' ? 20 : undefined; const form: LeagueConfigFormModel = { leagueId: league.id, basics: { name: league.name, description: league.description, visibility: 'public', // current domain model does not track visibility; default to public for now gameId: game?.id ?? 'iracing', }, structure: { // First slice: treat everything as solo structure based on maxDrivers mode: 'solo', maxDrivers: league.settings.maxDrivers ?? 32, maxTeams: undefined, driversPerTeam: undefined, multiClassEnabled: false, }, championships: { enableDriverChampionship: true, enableTeamChampionship: false, enableNationsChampionship: false, enableTrophyChampionship: false, }, scoring: { patternId: patternId ?? undefined, customScoringEnabled: !patternId, }, dropPolicy: dropPolicyForm, timings: { practiceMinutes, qualifyingMinutes, sprintRaceMinutes, mainRaceMinutes, sessionCount, roundsPlanned, }, }; return form; } private mapDropPolicy(policy: DropScorePolicy | undefined): LeagueDropPolicyFormDTO { if (!policy || policy.strategy === 'none') { return { strategy: 'none' }; } if (policy.strategy === 'bestNResults') { const n = typeof policy.count === 'number' ? policy.count : undefined; return n !== undefined ? { strategy: 'bestNResults', n } : { strategy: 'none' }; } if (policy.strategy === 'dropWorstN') { const n = typeof policy.dropCount === 'number' ? policy.dropCount : undefined; return n !== undefined ? { strategy: 'dropWorstN', n } : { strategy: 'none' }; } return { strategy: 'none' }; } }