Files
gridpilot.gg/adapters/bootstrap/racing/RacingRaceFactory.ts
2025-12-27 02:00:17 +01:00

119 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { League } from '@core/racing/domain/entities/League';
import { Race } from '@core/racing/domain/entities/Race';
import { Track } from '@core/racing/domain/entities/Track';
export class RacingRaceFactory {
constructor(private readonly baseDate: Date) {}
create(leagues: League[], tracks: Track[]): Race[] {
const cars = ['GT3 Porsche 911', 'GT3 BMW M4', 'LMP3 Prototype', 'GT4 Alpine', 'Touring Civic'];
const leagueIds = leagues.map((l) => l.id.toString());
const trackIds = tracks.map((t) => t.id);
const demoLeagueId = 'league-5';
const races: Race[] = [];
// Create races with systematic coverage of different statuses and scenarios
const statuses: Array<'scheduled' | 'running' | 'completed' | 'cancelled'> = ['scheduled', 'running', 'completed', 'cancelled'];
for (let i = 1; i <= 50; i++) {
const leagueId = leagueIds[(i - 1) % leagueIds.length] ?? demoLeagueId;
const trackId = trackIds[(i - 1) % trackIds.length]!;
const track = tracks.find(t => t.id === trackId)!;
// Determine status systematically to ensure coverage
let status: 'scheduled' | 'running' | 'completed' | 'cancelled';
let scheduledAt: Date;
if (i <= 4) {
// First 4 races: one of each status
status = statuses[i - 1]!;
scheduledAt = this.addDays(this.baseDate, i <= 2 ? -35 + i : 1 + (i - 2) * 2);
} else if (i <= 10) {
// Next 6: completed races
status = 'completed';
scheduledAt = this.addDays(this.baseDate, -35 + i);
} else if (i <= 15) {
// Next 5: scheduled future races
status = 'scheduled';
scheduledAt = this.addDays(this.baseDate, 1 + (i - 10) * 3);
} else if (i <= 20) {
// Next 5: cancelled races
status = 'cancelled';
scheduledAt = this.addDays(this.baseDate, -20 + (i - 15));
} else {
// Rest: mix of scheduled and completed
status = i % 3 === 0 ? 'completed' : 'scheduled';
scheduledAt = status === 'completed'
? this.addDays(this.baseDate, -10 + (i - 20))
: this.addDays(this.baseDate, 5 + (i - 20) * 2);
}
const base = {
id: `race-${i}`,
leagueId,
scheduledAt,
track: track.name.toString(),
trackId: track.id,
car: cars[(i - 1) % cars.length]!,
};
// Special case for running race
if (status === 'running') {
races.push(
Race.create({
...base,
status: 'running',
strengthOfField: 1400 + (i * 10), // Varying SOF
registeredCount: 12 + (i % 5), // Varying registration counts
}),
);
continue;
}
// Add varying SOF and registration counts for completed races
if (status === 'completed') {
races.push(
Race.create({
...base,
status: 'completed',
strengthOfField: 1200 + (i * 15),
registeredCount: 8 + (i % 8),
}),
);
continue;
}
// Scheduled races with some having registration data
if (status === 'scheduled') {
const hasRegistrations = i % 4 !== 0; // 75% have registrations
races.push(
Race.create({
...base,
status: 'scheduled',
...(hasRegistrations && {
strengthOfField: 1300 + (i * 8),
registeredCount: 5 + (i % 10),
}),
}),
);
continue;
}
// Cancelled races
races.push(
Race.create({
...base,
status: 'cancelled',
}),
);
}
return races;
}
private addDays(date: Date, days: number): Date {
return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
}
}