This commit is contained in:
2025-12-04 23:31:55 +01:00
parent 9fa21a488a
commit fb509607c1
96 changed files with 5839 additions and 1609 deletions

View File

@@ -0,0 +1,8 @@
export type BonusRuleType = 'fastestLap' | 'polePosition' | 'mostPositionsGained';
export interface BonusRule {
id: string;
type: BonusRuleType;
points: number;
requiresFinishInTopN?: number;
}

View File

@@ -0,0 +1,15 @@
import type { ChampionshipType } from './ChampionshipType';
import type { SessionType } from './SessionType';
import { PointsTable } from './PointsTable';
import type { BonusRule } from './BonusRule';
import type { DropScorePolicy } from './DropScorePolicy';
export interface ChampionshipConfig {
id: string;
name: string;
type: ChampionshipType;
sessionTypes: SessionType[];
pointsTableBySessionType: Record<SessionType, PointsTable>;
bonusRulesBySessionType?: Record<SessionType, BonusRule[]>;
dropScorePolicy: DropScorePolicy;
}

View File

@@ -0,0 +1 @@
export type ChampionshipType = 'driver' | 'team' | 'nations' | 'trophy';

View File

@@ -0,0 +1,13 @@
export type DropScoreStrategy = 'none' | 'bestNResults' | 'dropWorstN';
export interface DropScorePolicy {
strategy: DropScoreStrategy;
/**
* For 'bestNResults': number of best-scoring events to count.
*/
count?: number;
/**
* For 'dropWorstN': number of worst-scoring events to drop.
*/
dropCount?: number;
}

View File

@@ -0,0 +1,6 @@
import type { ChampionshipType } from './ChampionshipType';
export interface ParticipantRef {
type: ChampionshipType;
id: string;
}

View File

@@ -0,0 +1,21 @@
export class PointsTable {
private readonly pointsByPosition: Map<number, number>;
constructor(pointsByPosition: Record<number, number> | Map<number, number>) {
if (pointsByPosition instanceof Map) {
this.pointsByPosition = new Map(pointsByPosition);
} else {
this.pointsByPosition = new Map(
Object.entries(pointsByPosition).map(([key, value]) => [Number(key), value]),
);
}
}
getPointsForPosition(position: number): number {
if (!Number.isInteger(position) || position < 1) {
return 0;
}
const value = this.pointsByPosition.get(position);
return typeof value === 'number' ? value : 0;
}
}

View File

@@ -0,0 +1,9 @@
export type SessionType =
| 'practice'
| 'qualifying'
| 'q1'
| 'q2'
| 'q3'
| 'sprint'
| 'main'
| 'timeTrial';