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

100 lines
2.7 KiB
TypeScript

import type { ValueObject } from '@core/shared/domain/ValueObject';
import { RacingDomainValidationError } from '../errors/RacingDomainError';
export interface TeamDrivingReasonCodeProps {
value: string;
}
/**
* Valid reason codes for team driving rating events
*/
export const TEAM_DRIVING_REASON_CODES = [
'RACE_PERFORMANCE',
'RACE_GAIN_BONUS',
'RACE_INCIDENTS',
'RACE_DNF',
'RACE_DSQ',
'RACE_DNS',
'RACE_AFK',
'RACE_PACE',
'RACE_DEFENSE',
'RACE_OVERTAKE',
'RACE_QUALIFYING',
'RACE_CONSISTENCY',
'RACE_TEAMWORK',
'RACE_SPORTSMANSHIP',
] as const;
export type TeamDrivingReasonCodeValue = (typeof TEAM_DRIVING_REASON_CODES)[number];
/**
* Value object representing a team driving reason code
*/
export class TeamDrivingReasonCode implements ValueObject<TeamDrivingReasonCodeProps> {
readonly value: TeamDrivingReasonCodeValue;
private constructor(value: TeamDrivingReasonCodeValue) {
this.value = value;
}
static create(value: string): TeamDrivingReasonCode {
if (!value || value.trim().length === 0) {
throw new RacingDomainValidationError('Team driving reason code cannot be empty');
}
// Strict validation: no leading/trailing whitespace allowed
if (value !== value.trim()) {
throw new RacingDomainValidationError(
`Team driving reason code cannot have leading or trailing whitespace: "${value}"`
);
}
if (!TEAM_DRIVING_REASON_CODES.includes(value as TeamDrivingReasonCodeValue)) {
throw new RacingDomainValidationError(
`Invalid team driving reason code: ${value}. Valid options: ${TEAM_DRIVING_REASON_CODES.join(', ')}`
);
}
return new TeamDrivingReasonCode(value as TeamDrivingReasonCodeValue);
}
get props(): TeamDrivingReasonCodeProps {
return { value: this.value };
}
equals(other: ValueObject<TeamDrivingReasonCodeProps>): boolean {
return this.value === other.props.value;
}
toString(): string {
return this.value;
}
/**
* Check if this is a performance-related reason
*/
isPerformance(): boolean {
return ['RACE_PERFORMANCE', 'RACE_GAIN_BONUS', 'RACE_PACE', 'RACE_QUALIFYING', 'RACE_CONSISTENCY'].includes(this.value);
}
/**
* Check if this is a penalty-related reason
*/
isPenalty(): boolean {
return ['RACE_INCIDENTS', 'RACE_DNF', 'RACE_DSQ', 'RACE_DNS', 'RACE_AFK'].includes(this.value);
}
/**
* Check if this is a positive reason
*/
isPositive(): boolean {
return ['RACE_PERFORMANCE', 'RACE_GAIN_BONUS', 'RACE_OVERTAKE', 'RACE_DEFENSE', 'RACE_TEAMWORK', 'RACE_SPORTSMANSHIP'].includes(this.value);
}
/**
* Check if this is a negative reason
*/
isNegative(): boolean {
return ['RACE_INCIDENTS', 'RACE_DNF', 'RACE_DSQ', 'RACE_DNS', 'RACE_AFK'].includes(this.value);
}
}