Files
gridpilot.gg/core/racing/domain/entities/LeagueScoringConfig.ts
2025-12-29 00:24:56 +01:00

99 lines
3.1 KiB
TypeScript

/**
* Domain Entity: LeagueScoringConfig
*
* Represents the scoring configuration for a league season.
*/
import type { IEntity } from '@core/shared/domain';
import { RacingDomainValidationError } from '../errors/RacingDomainError';
import type { ChampionshipConfig } from '../types/ChampionshipConfig';
import { SeasonId } from './season/SeasonId';
import { ScoringPresetId } from './ScoringPresetId';
import { LeagueScoringConfigId } from './LeagueScoringConfigId';
export interface LeagueScoringConfigProps {
id?: string;
seasonId: string;
scoringPresetId?: string;
championships: ChampionshipConfig[];
}
export interface LeagueScoringConfigRehydrateProps {
id: string;
seasonId: string;
scoringPresetId?: string;
championships: ChampionshipConfig[];
}
export class LeagueScoringConfig implements IEntity<LeagueScoringConfigId> {
readonly id: LeagueScoringConfigId;
readonly seasonId: SeasonId;
readonly scoringPresetId: ScoringPresetId | undefined;
readonly championships: ChampionshipConfig[];
private constructor(props: {
id: LeagueScoringConfigId;
seasonId: SeasonId;
scoringPresetId?: ScoringPresetId;
championships: ChampionshipConfig[];
}) {
this.id = props.id;
this.seasonId = props.seasonId;
this.scoringPresetId = props.scoringPresetId;
this.championships = props.championships;
}
static create(props: LeagueScoringConfigProps): LeagueScoringConfig {
this.validate(props);
const idString = props.id && props.id.trim().length > 0 ? props.id : this.generateId(props.seasonId);
const id = LeagueScoringConfigId.create(idString);
const seasonId = SeasonId.create(props.seasonId);
const scoringPresetId = props.scoringPresetId ? ScoringPresetId.create(props.scoringPresetId) : undefined;
return new LeagueScoringConfig({
id,
seasonId,
...(scoringPresetId ? { scoringPresetId } : {}),
championships: props.championships,
});
}
static rehydrate(props: LeagueScoringConfigRehydrateProps): LeagueScoringConfig {
this.validate(props);
if (!props.id || props.id.trim().length === 0) {
throw new RacingDomainValidationError('Scoring config ID is required');
}
const id = LeagueScoringConfigId.create(props.id);
const seasonId = SeasonId.create(props.seasonId);
const scoringPresetId = props.scoringPresetId ? ScoringPresetId.create(props.scoringPresetId) : undefined;
return new LeagueScoringConfig({
id,
seasonId,
...(scoringPresetId ? { scoringPresetId } : {}),
championships: props.championships,
});
}
private static validate(props: LeagueScoringConfigProps): void {
if (!props.seasonId || props.seasonId.trim().length === 0) {
throw new RacingDomainValidationError('Season ID is required');
}
if (!props.championships || props.championships.length === 0) {
throw new RacingDomainValidationError('At least one championship is required');
}
}
private static generateId(seasonId: string): string {
return `scoring-config-${seasonId}`;
}
equals(other: LeagueScoringConfig): boolean {
return !!other && this.id.equals(other.id);
}
}