100 lines
2.7 KiB
TypeScript
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);
|
|
}
|
|
} |