wip
This commit is contained in:
@@ -1,38 +1,53 @@
|
||||
/**
|
||||
* Domain Entity: Race
|
||||
*
|
||||
*
|
||||
* Represents a race/session in the GridPilot platform.
|
||||
* Immutable entity with factory methods and domain validation.
|
||||
*/
|
||||
|
||||
export type SessionType = 'practice' | 'qualifying' | 'race';
|
||||
export type RaceStatus = 'scheduled' | 'completed' | 'cancelled';
|
||||
export type RaceStatus = 'scheduled' | 'running' | 'completed' | 'cancelled';
|
||||
|
||||
export class Race {
|
||||
readonly id: string;
|
||||
readonly leagueId: string;
|
||||
readonly scheduledAt: Date;
|
||||
readonly track: string;
|
||||
readonly trackId?: string;
|
||||
readonly car: string;
|
||||
readonly carId?: string;
|
||||
readonly sessionType: SessionType;
|
||||
readonly status: RaceStatus;
|
||||
readonly strengthOfField?: number;
|
||||
readonly registeredCount?: number;
|
||||
readonly maxParticipants?: number;
|
||||
|
||||
private constructor(props: {
|
||||
id: string;
|
||||
leagueId: string;
|
||||
scheduledAt: Date;
|
||||
track: string;
|
||||
trackId?: string;
|
||||
car: string;
|
||||
carId?: string;
|
||||
sessionType: SessionType;
|
||||
status: RaceStatus;
|
||||
strengthOfField?: number;
|
||||
registeredCount?: number;
|
||||
maxParticipants?: number;
|
||||
}) {
|
||||
this.id = props.id;
|
||||
this.leagueId = props.leagueId;
|
||||
this.scheduledAt = props.scheduledAt;
|
||||
this.track = props.track;
|
||||
this.trackId = props.trackId;
|
||||
this.car = props.car;
|
||||
this.carId = props.carId;
|
||||
this.sessionType = props.sessionType;
|
||||
this.status = props.status;
|
||||
this.strengthOfField = props.strengthOfField;
|
||||
this.registeredCount = props.registeredCount;
|
||||
this.maxParticipants = props.maxParticipants;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,9 +58,14 @@ export class Race {
|
||||
leagueId: string;
|
||||
scheduledAt: Date;
|
||||
track: string;
|
||||
trackId?: string;
|
||||
car: string;
|
||||
carId?: string;
|
||||
sessionType?: SessionType;
|
||||
status?: RaceStatus;
|
||||
strengthOfField?: number;
|
||||
registeredCount?: number;
|
||||
maxParticipants?: number;
|
||||
}): Race {
|
||||
this.validate(props);
|
||||
|
||||
@@ -54,9 +74,14 @@ export class Race {
|
||||
leagueId: props.leagueId,
|
||||
scheduledAt: props.scheduledAt,
|
||||
track: props.track,
|
||||
trackId: props.trackId,
|
||||
car: props.car,
|
||||
carId: props.carId,
|
||||
sessionType: props.sessionType ?? 'race',
|
||||
status: props.status ?? 'scheduled',
|
||||
strengthOfField: props.strengthOfField,
|
||||
registeredCount: props.registeredCount,
|
||||
maxParticipants: props.maxParticipants,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -91,6 +116,20 @@ export class Race {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the race (move from scheduled to running)
|
||||
*/
|
||||
start(): Race {
|
||||
if (this.status !== 'scheduled') {
|
||||
throw new Error('Only scheduled races can be started');
|
||||
}
|
||||
|
||||
return new Race({
|
||||
...this,
|
||||
status: 'running',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark race as completed
|
||||
*/
|
||||
@@ -127,6 +166,17 @@ export class Race {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update SOF and participant count
|
||||
*/
|
||||
updateField(strengthOfField: number, registeredCount: number): Race {
|
||||
return new Race({
|
||||
...this,
|
||||
strengthOfField,
|
||||
registeredCount,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if race is in the past
|
||||
*/
|
||||
@@ -140,4 +190,11 @@ export class Race {
|
||||
isUpcoming(): boolean {
|
||||
return this.status === 'scheduled' && !this.isPast();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if race is live/running
|
||||
*/
|
||||
isLive(): boolean {
|
||||
return this.status === 'running';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user