racing typeorm
This commit is contained in:
@@ -252,6 +252,47 @@ export class League implements IEntity<LeagueId> {
|
||||
});
|
||||
}
|
||||
|
||||
static rehydrate(props: {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
settings: LeagueSettings;
|
||||
createdAt: Date;
|
||||
participantCount: number;
|
||||
socialLinks?: {
|
||||
discordUrl?: string;
|
||||
youtubeUrl?: string;
|
||||
websiteUrl?: string;
|
||||
};
|
||||
}): League {
|
||||
const id = LeagueId.create(props.id);
|
||||
const name = LeagueName.create(props.name);
|
||||
const description = LeagueDescription.create(props.description);
|
||||
const ownerId = LeagueOwnerId.create(props.ownerId);
|
||||
const createdAt = LeagueCreatedAt.create(props.createdAt);
|
||||
|
||||
const visibilityType = props.settings.visibility ?? 'ranked';
|
||||
const visibility = LeagueVisibility.fromString(visibilityType);
|
||||
|
||||
const participantCount = ParticipantCount.create(props.participantCount);
|
||||
const socialLinks = props.socialLinks
|
||||
? LeagueSocialLinks.create(props.socialLinks)
|
||||
: undefined;
|
||||
|
||||
return new League({
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
ownerId,
|
||||
settings: props.settings,
|
||||
createdAt,
|
||||
...(socialLinks !== undefined ? { socialLinks } : {}),
|
||||
participantCount,
|
||||
visibility,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate stewarding settings configuration
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,13 @@ export interface LeagueScoringConfigProps {
|
||||
championships: ChampionshipConfig[];
|
||||
}
|
||||
|
||||
export interface LeagueScoringConfigRehydrateProps {
|
||||
id: string;
|
||||
seasonId: string;
|
||||
scoringPresetId?: string;
|
||||
championships: ChampionshipConfig[];
|
||||
}
|
||||
|
||||
export class LeagueScoringConfig implements IEntity<LeagueScoringConfigId> {
|
||||
readonly id: LeagueScoringConfigId;
|
||||
readonly seasonId: SeasonId;
|
||||
@@ -53,6 +60,25 @@ export class LeagueScoringConfig implements IEntity<LeagueScoringConfigId> {
|
||||
});
|
||||
}
|
||||
|
||||
static rehydrate(props: LeagueScoringConfigRehydrateProps): LeagueScoringConfig {
|
||||
this.validate(props);
|
||||
|
||||
if (!props.id || props.id.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Scoring config ID is required');
|
||||
}
|
||||
|
||||
const id = LeagueScoringConfigId.create(props.id);
|
||||
const seasonId = SeasonId.create(props.seasonId);
|
||||
const scoringPresetId = props.scoringPresetId ? ScoringPresetId.create(props.scoringPresetId) : undefined;
|
||||
|
||||
return new LeagueScoringConfig({
|
||||
id,
|
||||
seasonId,
|
||||
...(scoringPresetId ? { scoringPresetId } : {}),
|
||||
championships: props.championships,
|
||||
});
|
||||
}
|
||||
|
||||
private static validate(props: LeagueScoringConfigProps): void {
|
||||
if (!props.seasonId || props.seasonId.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Season ID is required');
|
||||
|
||||
@@ -157,6 +157,58 @@ export class Race implements IEntity<string> {
|
||||
});
|
||||
}
|
||||
|
||||
static rehydrate(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;
|
||||
}): Race {
|
||||
let registeredCount: ParticipantCount | undefined;
|
||||
let maxParticipants: MaxParticipants | undefined;
|
||||
|
||||
if (props.registeredCount !== undefined) {
|
||||
registeredCount = ParticipantCount.create(props.registeredCount);
|
||||
}
|
||||
|
||||
if (props.maxParticipants !== undefined) {
|
||||
maxParticipants = MaxParticipants.create(props.maxParticipants);
|
||||
|
||||
if (registeredCount && !maxParticipants.canAccommodate(registeredCount.toNumber())) {
|
||||
throw new RacingDomainValidationError(
|
||||
`Registered count (${registeredCount.toNumber()}) exceeds max participants (${maxParticipants.toNumber()})`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let strengthOfField: StrengthOfField | undefined;
|
||||
if (props.strengthOfField !== undefined) {
|
||||
strengthOfField = StrengthOfField.create(props.strengthOfField);
|
||||
}
|
||||
|
||||
return new Race({
|
||||
id: props.id,
|
||||
leagueId: props.leagueId,
|
||||
scheduledAt: props.scheduledAt,
|
||||
track: props.track,
|
||||
...(props.trackId !== undefined ? { trackId: props.trackId } : {}),
|
||||
car: props.car,
|
||||
...(props.carId !== undefined ? { carId: props.carId } : {}),
|
||||
sessionType: props.sessionType,
|
||||
status: props.status,
|
||||
...(strengthOfField !== undefined ? { strengthOfField } : {}),
|
||||
...(registeredCount !== undefined ? { registeredCount } : {}),
|
||||
...(maxParticipants !== undefined ? { maxParticipants } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the race (move from scheduled to running)
|
||||
*/
|
||||
|
||||
@@ -175,6 +175,55 @@ export class Season implements IEntity<string> {
|
||||
});
|
||||
}
|
||||
|
||||
static rehydrate(props: {
|
||||
id: string;
|
||||
leagueId: string;
|
||||
gameId: string;
|
||||
name: string;
|
||||
year?: number;
|
||||
order?: number;
|
||||
status: SeasonStatus;
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
schedule?: SeasonSchedule;
|
||||
schedulePublished: boolean;
|
||||
scoringConfig?: SeasonScoringConfig;
|
||||
dropPolicy?: SeasonDropPolicy;
|
||||
stewardingConfig?: SeasonStewardingConfig;
|
||||
maxDrivers?: number;
|
||||
participantCount: number;
|
||||
}): Season {
|
||||
const participantCount = ParticipantCount.create(props.participantCount);
|
||||
|
||||
if (props.maxDrivers !== undefined) {
|
||||
const maxParticipants = MaxParticipants.create(props.maxDrivers);
|
||||
if (!maxParticipants.canAccommodate(participantCount.toNumber())) {
|
||||
throw new RacingDomainValidationError(
|
||||
`Participant count (${participantCount.toNumber()}) exceeds season capacity (${maxParticipants.toNumber()})`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new Season({
|
||||
id: props.id,
|
||||
leagueId: props.leagueId,
|
||||
gameId: props.gameId,
|
||||
name: props.name,
|
||||
...(props.year !== undefined ? { year: props.year } : {}),
|
||||
...(props.order !== undefined ? { order: props.order } : {}),
|
||||
status: props.status,
|
||||
...(props.startDate !== undefined ? { startDate: props.startDate } : {}),
|
||||
...(props.endDate !== undefined ? { endDate: props.endDate } : {}),
|
||||
...(props.schedule !== undefined ? { schedule: props.schedule } : {}),
|
||||
schedulePublished: props.schedulePublished,
|
||||
...(props.scoringConfig !== undefined ? { scoringConfig: props.scoringConfig } : {}),
|
||||
...(props.dropPolicy !== undefined ? { dropPolicy: props.dropPolicy } : {}),
|
||||
...(props.stewardingConfig !== undefined ? { stewardingConfig: props.stewardingConfig } : {}),
|
||||
...(props.maxDrivers !== undefined ? { maxDrivers: props.maxDrivers } : {}),
|
||||
participantCount,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate stewarding configuration
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,13 @@ export interface ILeagueRepository {
|
||||
*/
|
||||
findAll(): Promise<League[]>;
|
||||
|
||||
/**
|
||||
* Count all leagues.
|
||||
*
|
||||
* Optional to avoid forcing all existing test doubles to implement it.
|
||||
*/
|
||||
countAll?(): Promise<number>;
|
||||
|
||||
/**
|
||||
* Find leagues by owner ID
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user