import type { ValueObject } from '@core/shared/domain/ValueObject'; import { RacingDomainValidationError } from '../errors/RacingDomainError'; export type SeasonDropStrategy = 'none' | 'bestNResults' | 'dropWorstN'; export interface SeasonDropPolicyProps { strategy: SeasonDropStrategy; /** * Number of results to consider for strategies that require a count. * - bestNResults: keep best N * - dropWorstN: drop worst N */ n?: number; } export class SeasonDropPolicy implements ValueObject { readonly strategy: SeasonDropStrategy; readonly n?: number; constructor(props: SeasonDropPolicyProps) { if (!props.strategy) { throw new RacingDomainValidationError( 'SeasonDropPolicy.strategy is required', ); } if (props.strategy === 'bestNResults' || props.strategy === 'dropWorstN') { if (props.n === undefined || !Number.isInteger(props.n) || props.n <= 0) { throw new RacingDomainValidationError( 'SeasonDropPolicy.n must be a positive integer when using bestNResults or dropWorstN', ); } } if (props.strategy === 'none' && props.n !== undefined) { throw new RacingDomainValidationError( 'SeasonDropPolicy.n must be undefined when strategy is none', ); } this.strategy = props.strategy; if (props.n !== undefined) { this.n = props.n; } } get props(): SeasonDropPolicyProps { return { strategy: this.strategy, ...(this.n !== undefined ? { n: this.n } : {}), }; } equals(other: ValueObject): boolean { const a = this.props; const b = other.props; return a.strategy === b.strategy && a.n === b.n; } }