Files
gridpilot.gg/core/racing/domain/value-objects/SessionDuration.ts
2026-01-16 16:46:57 +01:00

98 lines
2.2 KiB
TypeScript

/**
* 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<SessionDurationProps> {
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<SessionDurationProps>): boolean {
return this.value === other.props.value;
}
toString(): string {
return `${this.value} minutes`;
}
toNumber(): number {
return this.value;
}
}