seed data

This commit is contained in:
2025-12-30 00:15:35 +01:00
parent 7a853d4e43
commit ccaa39c39c
22 changed files with 1342 additions and 173 deletions

View File

@@ -11,29 +11,273 @@ export class RacingLeagueFactory {
) {}
create(): League[] {
const leagueCount = 20;
const leagueCount = 30;
// Create diverse league configurations
// Create diverse league configurations covering ALL enum combinations
// Points systems: f1-2024, indycar, custom (3)
// Qualifying formats: single-lap, open (2)
// Visibility: ranked, unranked (2)
// Decision modes: admin_only, steward_decides, steward_vote, member_vote, steward_veto, member_veto (6)
// Total combinations: 3 * 2 * 2 * 6 = 72, but we'll sample 30 covering extremes
const leagueConfigs = [
// Small sprint leagues
{ maxDrivers: 16, sessionDuration: 30, pointsSystem: 'f1-2024' as const, qualifyingFormat: 'single-lap' as const },
{ maxDrivers: 20, sessionDuration: 45, pointsSystem: 'f1-2024' as const, qualifyingFormat: 'open' as const },
// Medium endurance leagues
{ maxDrivers: 24, sessionDuration: 60, pointsSystem: 'indycar' as const, qualifyingFormat: 'open' as const },
{ maxDrivers: 28, sessionDuration: 90, pointsSystem: 'custom' as const, qualifyingFormat: 'open' as const },
// Large mixed leagues
{ maxDrivers: 32, sessionDuration: 120, pointsSystem: 'f1-2024' as const, qualifyingFormat: 'open' as const },
{ maxDrivers: 36, sessionDuration: 75, pointsSystem: 'indycar' as const, qualifyingFormat: 'single-lap' as const },
{ maxDrivers: 40, sessionDuration: 100, pointsSystem: 'custom' as const, qualifyingFormat: 'open' as const },
{ maxDrivers: 44, sessionDuration: 85, pointsSystem: 'f1-2024' as const, qualifyingFormat: 'open' as const },
{ maxDrivers: 48, sessionDuration: 110, pointsSystem: 'indycar' as const, qualifyingFormat: 'single-lap' as const },
{ maxDrivers: 50, sessionDuration: 95, pointsSystem: 'custom' as const, qualifyingFormat: 'open' as const },
// 1-5: Ranked, F1-2024, various stewarding
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'ranked' as const,
maxDrivers: 40,
sessionDuration: 60,
stewarding: { decisionMode: 'admin_only' as const, requireDefense: false }
},
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'open' as const,
visibility: 'ranked' as const,
maxDrivers: 32,
sessionDuration: 45,
stewarding: { decisionMode: 'steward_vote' as const, requiredVotes: 3, requireDefense: true, defenseTimeLimit: 24 }
},
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'ranked' as const,
maxDrivers: 50,
sessionDuration: 90,
stewarding: { decisionMode: 'member_vote' as const, requiredVotes: 5, requireDefense: false }
},
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'open' as const,
visibility: 'ranked' as const,
maxDrivers: 24,
sessionDuration: 30,
stewarding: { decisionMode: 'steward_veto' as const, requiredVotes: 2, requireDefense: true }
},
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'ranked' as const,
maxDrivers: 60,
sessionDuration: 120,
stewarding: { decisionMode: 'member_veto' as const, requiredVotes: 4, requireDefense: false }
},
// 6-10: Ranked, IndyCar, various stewarding
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'open' as const,
visibility: 'ranked' as const,
maxDrivers: 28,
sessionDuration: 75,
stewarding: { decisionMode: 'steward_decides' as const, requireDefense: true, defenseTimeLimit: 48 }
},
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'ranked' as const,
maxDrivers: 36,
sessionDuration: 60,
stewarding: { decisionMode: 'admin_only' as const, requireDefense: false }
},
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'open' as const,
visibility: 'ranked' as const,
maxDrivers: 44,
sessionDuration: 100,
stewarding: { decisionMode: 'steward_vote' as const, requiredVotes: 4, requireDefense: true, voteTimeLimit: 72 }
},
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'ranked' as const,
maxDrivers: 20,
sessionDuration: 45,
stewarding: { decisionMode: 'member_vote' as const, requiredVotes: 6, requireDefense: false }
},
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'open' as const,
visibility: 'ranked' as const,
maxDrivers: 48,
sessionDuration: 110,
stewarding: { decisionMode: 'steward_veto' as const, requiredVotes: 3, requireDefense: true }
},
// 11-15: Ranked, Custom, various stewarding
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'ranked' as const,
maxDrivers: 32,
sessionDuration: 50,
stewarding: { decisionMode: 'member_veto' as const, requiredVotes: 5, requireDefense: false }
},
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'open' as const,
visibility: 'ranked' as const,
maxDrivers: 40,
sessionDuration: 85,
stewarding: { decisionMode: 'admin_only' as const, requireDefense: false }
},
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'ranked' as const,
maxDrivers: 52,
sessionDuration: 95,
stewarding: { decisionMode: 'steward_decides' as const, requireDefense: true, defenseTimeLimit: 36 }
},
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'open' as const,
visibility: 'ranked' as const,
maxDrivers: 26,
sessionDuration: 65,
stewarding: { decisionMode: 'steward_vote' as const, requiredVotes: 2, requireDefense: false }
},
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'ranked' as const,
maxDrivers: 56,
sessionDuration: 105,
stewarding: { decisionMode: 'member_vote' as const, requiredVotes: 7, requireDefense: true, protestDeadlineHours: 24 }
},
// 16-20: Unranked, F1-2024, various stewarding (smaller, no participant requirements)
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'open' as const,
visibility: 'unranked' as const,
maxDrivers: 8,
sessionDuration: 30,
stewarding: { decisionMode: 'admin_only' as const, requireDefense: false }
},
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'unranked' as const,
maxDrivers: 12,
sessionDuration: 45,
stewarding: { decisionMode: 'steward_decides' as const, requireDefense: true }
},
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'open' as const,
visibility: 'unranked' as const,
maxDrivers: 16,
sessionDuration: 60,
stewarding: { decisionMode: 'steward_vote' as const, requiredVotes: 2, requireDefense: false }
},
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'unranked' as const,
maxDrivers: 10,
sessionDuration: 35,
stewarding: { decisionMode: 'member_vote' as const, requiredVotes: 3, requireDefense: true }
},
{
pointsSystem: 'f1-2024' as const,
qualifyingFormat: 'open' as const,
visibility: 'unranked' as const,
maxDrivers: 20,
sessionDuration: 55,
stewarding: { decisionMode: 'steward_veto' as const, requiredVotes: 2, requireDefense: false }
},
// 21-25: Unranked, IndyCar, various stewarding
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'unranked' as const,
maxDrivers: 14,
sessionDuration: 40,
stewarding: { decisionMode: 'member_veto' as const, requiredVotes: 3, requireDefense: true }
},
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'open' as const,
visibility: 'unranked' as const,
maxDrivers: 18,
sessionDuration: 50,
stewarding: { decisionMode: 'admin_only' as const, requireDefense: false }
},
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'unranked' as const,
maxDrivers: 22,
sessionDuration: 65,
stewarding: { decisionMode: 'steward_decides' as const, requireDefense: true, defenseTimeLimit: 12 }
},
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'open' as const,
visibility: 'unranked' as const,
maxDrivers: 6,
sessionDuration: 25,
stewarding: { decisionMode: 'steward_vote' as const, requiredVotes: 2, requireDefense: false }
},
{
pointsSystem: 'indycar' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'unranked' as const,
maxDrivers: 24,
sessionDuration: 70,
stewarding: { decisionMode: 'member_vote' as const, requiredVotes: 4, requireDefense: true }
},
// 26-30: Unranked, Custom, various stewarding
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'open' as const,
visibility: 'unranked' as const,
maxDrivers: 12,
sessionDuration: 35,
stewarding: { decisionMode: 'steward_veto' as const, requiredVotes: 2, requireDefense: false }
},
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'unranked' as const,
maxDrivers: 16,
sessionDuration: 45,
stewarding: { decisionMode: 'member_veto' as const, requiredVotes: 3, requireDefense: true }
},
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'open' as const,
visibility: 'unranked' as const,
maxDrivers: 20,
sessionDuration: 55,
stewarding: { decisionMode: 'admin_only' as const, requireDefense: false }
},
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'single-lap' as const,
visibility: 'unranked' as const,
maxDrivers: 8,
sessionDuration: 30,
stewarding: { decisionMode: 'steward_decides' as const, requireDefense: true, defenseTimeLimit: 18 }
},
{
pointsSystem: 'custom' as const,
qualifyingFormat: 'open' as const,
visibility: 'unranked' as const,
maxDrivers: 24,
sessionDuration: 60,
stewarding: { decisionMode: 'steward_vote' as const, requiredVotes: 3, requireDefense: false }
},
];
return Array.from({ length: leagueCount }, (_, idx) => {
const i = idx + 1;
const owner = faker.helpers.arrayElement(this.drivers);
const config = leagueConfigs[idx % leagueConfigs.length]!;
const config = leagueConfigs[idx]!;
const createdAt =
// Ensure some "New" leagues (created within 7 days) so `/leagues` featured categories are populated.
@@ -41,6 +285,31 @@ export class RacingLeagueFactory {
? faker.date.recent({ days: 6, refDate: this.baseDate })
: faker.date.past({ years: 2, refDate: this.baseDate });
// Calculate participant count based on visibility and league
let participantCount: number;
if (config.visibility === 'ranked') {
// Ranked leagues need >= 10 participants
// Some are full (max), some have minimum, some have none
if (idx % 5 === 0) {
participantCount = config.maxDrivers; // Full league
} else if (idx % 3 === 0) {
participantCount = 12; // Just meets minimum
} else if (idx % 7 === 0) {
participantCount = 0; // Empty but valid
} else {
participantCount = faker.number.int({ min: 10, max: config.maxDrivers - 5 });
}
} else {
// Unranked can have any count, but must have at least 2 if not empty
if (idx % 4 === 0) {
participantCount = config.maxDrivers; // Full
} else if (idx % 5 === 0) {
participantCount = 0; // Empty
} else {
participantCount = faker.number.int({ min: 2, max: Math.min(config.maxDrivers, 15) });
}
}
const leagueData: {
id: string;
name: string;
@@ -51,6 +320,18 @@ export class RacingLeagueFactory {
maxDrivers: number;
sessionDuration: number;
qualifyingFormat: 'open' | 'single-lap';
visibility?: 'ranked' | 'unranked';
stewarding?: {
decisionMode: 'admin_only' | 'steward_decides' | 'steward_vote' | 'member_vote' | 'steward_veto' | 'member_veto';
requiredVotes?: number;
requireDefense?: boolean;
defenseTimeLimit?: number;
voteTimeLimit?: number;
protestDeadlineHours?: number;
stewardingClosesHours?: number;
notifyAccusedOnProtest?: boolean;
notifyOnVoteRequired?: boolean;
};
};
createdAt: Date;
socialLinks?: { discordUrl?: string; youtubeUrl?: string; websiteUrl?: string };
@@ -60,11 +341,23 @@ export class RacingLeagueFactory {
name: faker.company.name() + ' Racing League',
description: faker.lorem.sentences(2),
ownerId: owner.id.toString(),
settings: config,
settings: {
pointsSystem: config.pointsSystem,
maxDrivers: config.maxDrivers,
sessionDuration: config.sessionDuration,
qualifyingFormat: config.qualifyingFormat,
visibility: config.visibility,
stewarding: {
...config.stewarding,
voteTimeLimit: 72,
protestDeadlineHours: 48,
stewardingClosesHours: 168,
notifyAccusedOnProtest: true,
notifyOnVoteRequired: true,
},
},
createdAt,
// Start with some participants for ranked leagues to meet minimum requirements
// Note: ranked leagues require >= 10 participants (see LeagueVisibility)
participantCount: i % 3 === 0 ? 12 : 0,
participantCount,
};
// Add social links with varying completeness