/** * Domain Value Object: ParticipantCount * * Represents the number of participants in a league or race. * Enforces constraints based on league visibility and other business rules. */ import type { ValueObject } from '@core/shared/domain/ValueObject'; import { RacingDomainValidationError } from '../errors/RacingDomainError'; export interface ParticipantCountProps { value: number; } export class ParticipantCount implements ValueObject { readonly value: number; private constructor(value: number) { this.value = value; } static create(value: number): ParticipantCount { if (!Number.isInteger(value) || value < 0) { throw new RacingDomainValidationError('Participant count must be a non-negative integer'); } return new ParticipantCount(value); } /** * Validate against minimum requirements for ranked leagues */ validateForRankedLeague(): { valid: boolean; error?: string } { if (this.value < 10) { return { valid: false, error: 'Ranked leagues require at least 10 participants' }; } return { valid: true }; } /** * Validate against minimum requirements for unranked leagues */ validateForUnrankedLeague(): { valid: boolean; error?: string } { if (this.value < 2) { return { valid: false, error: 'Unranked leagues require at least 2 participants' }; } return { valid: true }; } /** * Validate against maximum capacity */ validateAgainstMax(maxParticipants: number): { valid: boolean; error?: string } { if (this.value > maxParticipants) { return { valid: false, error: `Participant count (${this.value}) exceeds maximum capacity (${maxParticipants})` }; } return { valid: true }; } /** * Check if count meets minimum for given visibility type */ meetsMinimumForVisibility(isRanked: boolean): boolean { return isRanked ? this.value >= 10 : this.value >= 2; } /** * Increment count by 1 */ increment(): ParticipantCount { return new ParticipantCount(this.value + 1); } /** * Decrement count by 1 (if > 0) */ decrement(): ParticipantCount { if (this.value === 0) { throw new RacingDomainValidationError('Cannot decrement below zero'); } return new ParticipantCount(this.value - 1); } /** * Check if count is zero */ isZero(): boolean { return this.value === 0; } /** * Check if count is at least the given minimum */ isAtLeast(min: number): boolean { return this.value >= min; } get props(): ParticipantCountProps { return { value: this.value }; } equals(other: ValueObject): boolean { return this.value === other.props.value; } toString(): string { return this.value.toString(); } toNumber(): number { return this.value; } }