This commit is contained in:
2025-12-11 11:25:22 +01:00
parent 6a427eab57
commit e4c1be628d
86 changed files with 1222 additions and 736 deletions

View File

@@ -1,10 +1,12 @@
/**
* Domain Entity: Penalty
*
*
* Represents a penalty applied to a driver for an incident during a race.
* Penalties can be applied as a result of an upheld protest or directly by stewards.
*/
import { RacingDomainValidationError, RacingDomainInvariantError } from '../errors/RacingDomainError';
export type PenaltyType =
| 'time_penalty' // Add time to race result (e.g., +5 seconds)
| 'grid_penalty' // Grid position penalty for next race
@@ -47,17 +49,17 @@ export class Penalty {
private constructor(private readonly props: PenaltyProps) {}
static create(props: PenaltyProps): Penalty {
if (!props.id) throw new Error('Penalty ID is required');
if (!props.raceId) throw new Error('Race ID is required');
if (!props.driverId) throw new Error('Driver ID is required');
if (!props.type) throw new Error('Penalty type is required');
if (!props.reason?.trim()) throw new Error('Penalty reason is required');
if (!props.issuedBy) throw new Error('Penalty must be issued by a steward');
if (!props.id) throw new RacingDomainValidationError('Penalty ID is required');
if (!props.raceId) throw new RacingDomainValidationError('Race ID is required');
if (!props.driverId) throw new RacingDomainValidationError('Driver ID is required');
if (!props.type) throw new RacingDomainValidationError('Penalty type is required');
if (!props.reason?.trim()) throw new RacingDomainValidationError('Penalty reason is required');
if (!props.issuedBy) throw new RacingDomainValidationError('Penalty must be issued by a steward');
// Validate value based on type
if (['time_penalty', 'grid_penalty', 'points_deduction', 'license_points', 'fine', 'race_ban'].includes(props.type)) {
if (props.value === undefined || props.value <= 0) {
throw new Error(`${props.type} requires a positive value`);
throw new RacingDomainValidationError(`${props.type} requires a positive value`);
}
}
@@ -94,10 +96,10 @@ export class Penalty {
*/
markAsApplied(notes?: string): Penalty {
if (this.isApplied()) {
throw new Error('Penalty is already applied');
throw new RacingDomainInvariantError('Penalty is already applied');
}
if (this.props.status === 'overturned') {
throw new Error('Cannot apply an overturned penalty');
throw new RacingDomainInvariantError('Cannot apply an overturned penalty');
}
return new Penalty({
...this.props,
@@ -112,7 +114,7 @@ export class Penalty {
*/
overturn(reason: string): Penalty {
if (this.props.status === 'overturned') {
throw new Error('Penalty is already overturned');
throw new RacingDomainInvariantError('Penalty is already overturned');
}
return new Penalty({
...this.props,