import { LeagueScoringConfig } from '@core/racing/domain/entities/LeagueScoringConfig'; import type { BonusRule } from '@core/racing/domain/types/BonusRule'; import type { ChampionshipConfig } from '@core/racing/domain/types/ChampionshipConfig'; import type { ChampionshipType } from '@core/racing/domain/types/ChampionshipType'; import type { DropScorePolicy } from '@core/racing/domain/types/DropScorePolicy'; import type { SessionType } from '@core/racing/domain/types/SessionType'; import { PointsTable } from '@core/racing/domain/value-objects/PointsTable'; export type LeagueScoringPresetPrimaryChampionshipType = | 'driver' | 'team' | 'nations' | 'trophy'; export interface LeagueScoringPresetTimingDefaults { practiceMinutes: number; qualifyingMinutes: number; sprintRaceMinutes: number; mainRaceMinutes: number; sessionCount: number; } export interface LeagueScoringPreset { id: string; name: string; description: string; primaryChampionshipType: LeagueScoringPresetPrimaryChampionshipType; dropPolicySummary: string; sessionSummary: string; bonusSummary: string; defaultTimings: LeagueScoringPresetTimingDefaults; createConfig: (options: { seasonId: string }) => LeagueScoringConfig; } const mainPointsSprintMain = new PointsTable({ 1: 25, 2: 18, 3: 15, 4: 12, 5: 10, 6: 8, 7: 6, 8: 4, 9: 2, 10: 1, }); const sprintPointsSprintMain = new PointsTable({ 1: 8, 2: 7, 3: 6, 4: 5, 5: 4, 6: 3, 7: 2, 8: 1, }); const clubMainPoints = new PointsTable({ 1: 20, 2: 15, 3: 12, 4: 10, 5: 8, 6: 6, 7: 4, 8: 2, 9: 1, }); const enduranceMainPoints = new PointsTable({ 1: 50, 2: 36, 3: 30, 4: 24, 5: 20, 6: 16, 7: 12, 8: 8, 9: 4, 10: 2, }); export const leagueScoringPresets: LeagueScoringPreset[] = [ { id: 'sprint-main-driver', name: 'Sprint + Main', description: 'Short sprint race plus main race; sprint gives fewer points.', primaryChampionshipType: 'driver', dropPolicySummary: 'Best 6 results of 8 count towards the championship.', sessionSummary: 'Sprint + Main', bonusSummary: 'Fastest lap +1 point in main race if finishing P10 or better.', defaultTimings: { practiceMinutes: 20, qualifyingMinutes: 30, sprintRaceMinutes: 20, mainRaceMinutes: 40, sessionCount: 2, }, createConfig: ({ seasonId }) => { const fastestLapBonus: BonusRule = { id: 'fastest-lap-main', type: 'fastestLap', points: 1, requiresFinishInTopN: 10, }; const sessionTypes: SessionType[] = ['sprint', 'main']; const pointsTableBySessionType: Record = { sprint: sprintPointsSprintMain, main: mainPointsSprintMain, practice: new PointsTable({}), qualifying: new PointsTable({}), q1: new PointsTable({}), q2: new PointsTable({}), q3: new PointsTable({}), timeTrial: new PointsTable({}), }; const bonusRulesBySessionType: Record = { sprint: [], main: [fastestLapBonus], practice: [], qualifying: [], q1: [], q2: [], q3: [], timeTrial: [], }; const dropScorePolicy: DropScorePolicy = { strategy: 'bestNResults', count: 6, }; const championship: ChampionshipConfig = { id: 'driver-champ-sprint-main', name: 'Driver Championship', type: 'driver' as ChampionshipType, sessionTypes, pointsTableBySessionType, bonusRulesBySessionType, dropScorePolicy, }; return LeagueScoringConfig.create({ id: `lsc-${seasonId}-sprint-main-driver`, seasonId, scoringPresetId: 'sprint-main-driver', championships: [championship], }); }, }, { id: 'club-default', name: 'Club ladder', description: 'Simple club ladder with a single main race and no bonuses or drop scores.', primaryChampionshipType: 'driver', dropPolicySummary: 'All race results count, no drop scores.', sessionSummary: 'Main race only', bonusSummary: 'No bonus points.', defaultTimings: { practiceMinutes: 20, qualifyingMinutes: 20, sprintRaceMinutes: 0, mainRaceMinutes: 40, sessionCount: 1, }, createConfig: ({ seasonId }) => { const sessionTypes: SessionType[] = ['main']; const pointsTableBySessionType: Record = { sprint: new PointsTable({}), main: clubMainPoints, practice: new PointsTable({}), qualifying: new PointsTable({}), q1: new PointsTable({}), q2: new PointsTable({}), q3: new PointsTable({}), timeTrial: new PointsTable({}), }; const dropScorePolicy: DropScorePolicy = { strategy: 'none', }; const championship: ChampionshipConfig = { id: 'driver-champ-club-default', name: 'Driver Championship', type: 'driver' as ChampionshipType, sessionTypes, pointsTableBySessionType, dropScorePolicy, }; return LeagueScoringConfig.create({ id: `lsc-${seasonId}-club-default`, seasonId, scoringPresetId: 'club-default', championships: [championship], }); }, }, { id: 'endurance-main-double', name: 'Endurance weekend', description: 'Single main endurance race with double points and a simple drop policy.', primaryChampionshipType: 'driver', dropPolicySummary: 'Best 4 results of 6 count towards the championship.', sessionSummary: 'Main race only', bonusSummary: 'No bonus points.', defaultTimings: { practiceMinutes: 30, qualifyingMinutes: 20, sprintRaceMinutes: 0, mainRaceMinutes: 120, sessionCount: 1, }, createConfig: ({ seasonId }) => { const sessionTypes: SessionType[] = ['main']; const pointsTableBySessionType: Record = { sprint: new PointsTable({}), main: enduranceMainPoints, practice: new PointsTable({}), qualifying: new PointsTable({}), q1: new PointsTable({}), q2: new PointsTable({}), q3: new PointsTable({}), timeTrial: new PointsTable({}), }; const dropScorePolicy: DropScorePolicy = { strategy: 'bestNResults', count: 4, }; const championship: ChampionshipConfig = { id: 'driver-champ-endurance-main-double', name: 'Driver Championship', type: 'driver' as ChampionshipType, sessionTypes, pointsTableBySessionType, dropScorePolicy, }; return LeagueScoringConfig.create({ id: `lsc-${seasonId}-endurance-main-double`, seasonId, scoringPresetId: 'endurance-main-double', championships: [championship], }); }, }, { id: 'sprint-main-team', name: 'Sprint + Main (Teams)', description: 'Teams championship using the Sprint + Main weekend format.', primaryChampionshipType: 'team', dropPolicySummary: 'Best 6 results of 8 count towards the championship.', sessionSummary: 'Sprint + Main', bonusSummary: 'Fastest lap +1 point in main race if finishing P10 or better.', defaultTimings: { practiceMinutes: 20, qualifyingMinutes: 30, sprintRaceMinutes: 20, mainRaceMinutes: 40, sessionCount: 2, }, createConfig: ({ seasonId }) => { const fastestLapBonus: BonusRule = { id: 'fastest-lap-main-team', type: 'fastestLap', points: 1, requiresFinishInTopN: 10, }; const sessionTypes: SessionType[] = ['sprint', 'main']; const pointsTableBySessionType: Record = { sprint: sprintPointsSprintMain, main: mainPointsSprintMain, practice: new PointsTable({}), qualifying: new PointsTable({}), q1: new PointsTable({}), q2: new PointsTable({}), q3: new PointsTable({}), timeTrial: new PointsTable({}), }; const bonusRulesBySessionType: Record = { sprint: [], main: [fastestLapBonus], practice: [], qualifying: [], q1: [], q2: [], q3: [], timeTrial: [], }; const dropScorePolicy: DropScorePolicy = { strategy: 'bestNResults', count: 6, }; const championship: ChampionshipConfig = { id: 'team-champ-sprint-main', name: 'Team Championship', type: 'team' as ChampionshipType, sessionTypes, pointsTableBySessionType, bonusRulesBySessionType, dropScorePolicy, }; return LeagueScoringConfig.create({ id: `lsc-${seasonId}-sprint-main-team`, seasonId, scoringPresetId: 'sprint-main-team', championships: [championship], }); }, }, { id: 'club-default-nations', name: 'Club ladder (Nations)', description: 'Nation vs nation ladder with a single main race and no bonuses.', primaryChampionshipType: 'nations', dropPolicySummary: 'All race results count, no drop scores.', sessionSummary: 'Main race only', bonusSummary: 'No bonus points.', defaultTimings: { practiceMinutes: 20, qualifyingMinutes: 20, sprintRaceMinutes: 0, mainRaceMinutes: 40, sessionCount: 1, }, createConfig: ({ seasonId }) => { const sessionTypes: SessionType[] = ['main']; const pointsTableBySessionType: Record = { sprint: new PointsTable({}), main: clubMainPoints, practice: new PointsTable({}), qualifying: new PointsTable({}), q1: new PointsTable({}), q2: new PointsTable({}), q3: new PointsTable({}), timeTrial: new PointsTable({}), }; const dropScorePolicy: DropScorePolicy = { strategy: 'none', }; const championship: ChampionshipConfig = { id: 'nations-champ-club-default', name: 'Nations Championship', type: 'nations' as ChampionshipType, sessionTypes, pointsTableBySessionType, dropScorePolicy, }; return LeagueScoringConfig.create({ id: `lsc-${seasonId}-club-default-nations`, seasonId, scoringPresetId: 'club-default-nations', championships: [championship], }); }, }, { id: 'endurance-main-trophy', name: 'Endurance Trophy Event', description: 'Trophy-style endurance event with a single long main race.', primaryChampionshipType: 'trophy', dropPolicySummary: 'Best 4 results of 6 count towards the championship.', sessionSummary: 'Main race only', bonusSummary: 'No bonus points.', defaultTimings: { practiceMinutes: 30, qualifyingMinutes: 20, sprintRaceMinutes: 0, mainRaceMinutes: 120, sessionCount: 1, }, createConfig: ({ seasonId }) => { const sessionTypes: SessionType[] = ['main']; const pointsTableBySessionType: Record = { sprint: new PointsTable({}), main: enduranceMainPoints, practice: new PointsTable({}), qualifying: new PointsTable({}), q1: new PointsTable({}), q2: new PointsTable({}), q3: new PointsTable({}), timeTrial: new PointsTable({}), }; const dropScorePolicy: DropScorePolicy = { strategy: 'bestNResults', count: 4, }; const championship: ChampionshipConfig = { id: 'trophy-champ-endurance-main', name: 'Trophy Championship', type: 'trophy' as ChampionshipType, sessionTypes, pointsTableBySessionType, dropScorePolicy, }; return LeagueScoringConfig.create({ id: `lsc-${seasonId}-endurance-main-trophy`, seasonId, scoringPresetId: 'endurance-main-trophy', championships: [championship], }); }, }, ]; export function listLeagueScoringPresets(): LeagueScoringPreset[] { return [...leagueScoringPresets]; } export function getLeagueScoringPresetById( id: string, ): LeagueScoringPreset | undefined { return leagueScoringPresets.find((preset) => preset.id === id); }