refactor
This commit is contained in:
@@ -4,36 +4,43 @@
|
||||
* Represents a racing track/circuit in the GridPilot platform.
|
||||
* Immutable entity with factory methods and domain validation.
|
||||
*/
|
||||
|
||||
|
||||
import { RacingDomainValidationError } from '../errors/RacingDomainError';
|
||||
import type { IEntity } from '@core/shared/domain';
|
||||
import { TrackName } from '../value-objects/TrackName';
|
||||
import { TrackShortName } from '../value-objects/TrackShortName';
|
||||
import { TrackCountry } from '../value-objects/TrackCountry';
|
||||
import { TrackLength } from '../value-objects/TrackLength';
|
||||
import { TrackTurns } from '../value-objects/TrackTurns';
|
||||
import { TrackGameId } from '../value-objects/TrackGameId';
|
||||
import { TrackImageUrl } from '../value-objects/TrackImageUrl';
|
||||
|
||||
export type TrackCategory = 'oval' | 'road' | 'street' | 'dirt';
|
||||
export type TrackDifficulty = 'beginner' | 'intermediate' | 'advanced' | 'expert';
|
||||
|
||||
export class Track implements IEntity<string> {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly shortName: string;
|
||||
readonly country: string;
|
||||
readonly name: TrackName;
|
||||
readonly shortName: TrackShortName;
|
||||
readonly country: TrackCountry;
|
||||
readonly category: TrackCategory;
|
||||
readonly difficulty: TrackDifficulty;
|
||||
readonly lengthKm: number;
|
||||
readonly turns: number;
|
||||
readonly imageUrl: string | undefined;
|
||||
readonly gameId: string;
|
||||
readonly lengthKm: TrackLength;
|
||||
readonly turns: TrackTurns;
|
||||
readonly imageUrl: TrackImageUrl;
|
||||
readonly gameId: TrackGameId;
|
||||
|
||||
private constructor(props: {
|
||||
id: string;
|
||||
name: string;
|
||||
shortName: string;
|
||||
country: string;
|
||||
name: TrackName;
|
||||
shortName: TrackShortName;
|
||||
country: TrackCountry;
|
||||
category: TrackCategory;
|
||||
difficulty: TrackDifficulty;
|
||||
lengthKm: number;
|
||||
turns: number;
|
||||
imageUrl?: string | undefined;
|
||||
gameId: string;
|
||||
lengthKm: TrackLength;
|
||||
turns: TrackTurns;
|
||||
imageUrl: TrackImageUrl;
|
||||
gameId: TrackGameId;
|
||||
}) {
|
||||
this.id = props.id;
|
||||
this.name = props.name;
|
||||
@@ -62,66 +69,23 @@ export class Track implements IEntity<string> {
|
||||
imageUrl?: string;
|
||||
gameId: string;
|
||||
}): Track {
|
||||
this.validate(props);
|
||||
|
||||
const base = {
|
||||
id: props.id,
|
||||
name: props.name,
|
||||
shortName: props.shortName ?? props.name.slice(0, 3).toUpperCase(),
|
||||
country: props.country,
|
||||
category: props.category ?? 'road',
|
||||
difficulty: props.difficulty ?? 'intermediate',
|
||||
lengthKm: props.lengthKm,
|
||||
turns: props.turns,
|
||||
gameId: props.gameId,
|
||||
};
|
||||
|
||||
const withImage =
|
||||
props.imageUrl !== undefined ? { ...base, imageUrl: props.imageUrl } : base;
|
||||
|
||||
return new Track(withImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Domain validation logic
|
||||
*/
|
||||
private static validate(props: {
|
||||
id: string;
|
||||
name: string;
|
||||
country: string;
|
||||
lengthKm: number;
|
||||
turns: number;
|
||||
gameId: string;
|
||||
}): void {
|
||||
if (!props.id || props.id.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Track ID is required');
|
||||
}
|
||||
|
||||
if (!props.name || props.name.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Track name is required');
|
||||
}
|
||||
const shortNameValue = props.shortName ?? props.name.slice(0, 3).toUpperCase();
|
||||
|
||||
if (!props.country || props.country.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Track country is required');
|
||||
}
|
||||
|
||||
if (props.lengthKm <= 0) {
|
||||
throw new RacingDomainValidationError('Track length must be positive');
|
||||
}
|
||||
|
||||
if (props.turns < 0) {
|
||||
throw new RacingDomainValidationError('Track turns cannot be negative');
|
||||
}
|
||||
|
||||
if (!props.gameId || props.gameId.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Game ID is required');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formatted length string
|
||||
*/
|
||||
getFormattedLength(): string {
|
||||
return `${this.lengthKm.toFixed(2)} km`;
|
||||
return new Track({
|
||||
id: props.id,
|
||||
name: TrackName.create(props.name),
|
||||
shortName: TrackShortName.create(shortNameValue),
|
||||
country: TrackCountry.create(props.country),
|
||||
category: props.category ?? 'road',
|
||||
difficulty: props.difficulty ?? 'intermediate',
|
||||
lengthKm: TrackLength.create(props.lengthKm),
|
||||
turns: TrackTurns.create(props.turns),
|
||||
imageUrl: TrackImageUrl.create(props.imageUrl),
|
||||
gameId: TrackGameId.create(props.gameId),
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user