/** * Domain Value Object: SessionDuration * * Represents the duration of a racing session in minutes. * Enforces reasonable limits for different session types. */ import type { ValueObject } from '@core/shared/domain/ValueObject'; import { RacingDomainValidationError } from '../errors/RacingDomainError'; export interface SessionDurationProps { value: number; } export class SessionDuration implements ValueObject { readonly value: number; private constructor(value: number) { this.value = value; } static create(value: number): SessionDuration { if (!Number.isInteger(value) || value <= 0) { throw new RacingDomainValidationError('Session duration must be a positive integer'); } // Enforce reasonable limits if (value < 15) { throw new RacingDomainValidationError('Session duration must be at least 15 minutes'); } if (value > 240) { throw new RacingDomainValidationError('Session duration cannot exceed 240 minutes (4 hours)'); } return new SessionDuration(value); } /** * Check if duration is suitable for sprint racing */ isSprint(): boolean { return this.value >= 15 && this.value <= 45; } /** * Check if duration is suitable for standard racing */ isStandard(): boolean { return this.value > 45 && this.value <= 90; } /** * Check if duration is suitable for endurance racing */ isEndurance(): boolean { return this.value > 90; } /** * Get duration classification */ getClassification(): 'sprint' | 'standard' | 'endurance' { if (this.isSprint()) return 'sprint'; if (this.isStandard()) return 'standard'; return 'endurance'; } /** * Check if duration is within specified range */ isWithinRange(min: number, max: number): boolean { return this.value >= min && this.value <= max; } /** * Get duration in hours */ inHours(): number { return this.value / 60; } get props(): SessionDurationProps { return { value: this.value }; } equals(other: ValueObject): boolean { return this.value === other.props.value; } toString(): string { return `${this.value} minutes`; } toNumber(): number { return this.value; } }