seed data
This commit is contained in:
@@ -78,6 +78,10 @@ export class SeedRacingData {
|
||||
return process.env.DATABASE_URL ? 'postgres' : 'inmemory';
|
||||
}
|
||||
|
||||
private getMediaBaseUrl(): string {
|
||||
return process.env.NODE_ENV === 'development' ? 'http://localhost:3001' : 'https://api.gridpilot.io';
|
||||
}
|
||||
|
||||
async execute(): Promise<void> {
|
||||
const existingDrivers = await this.seedDeps.driverRepository.findAll();
|
||||
const persistence = this.getApiPersistence();
|
||||
@@ -428,7 +432,7 @@ export class SeedRacingData {
|
||||
private calculateTeamStats(team: Team, results: Result[], drivers: Driver[]): TeamStats {
|
||||
const wins = results.filter(r => r.position.toNumber() === 1).length;
|
||||
const totalRaces = results.length;
|
||||
|
||||
|
||||
// Calculate rating
|
||||
const baseRating = 1000;
|
||||
const winBonus = wins * 50;
|
||||
@@ -462,7 +466,7 @@ export class SeedRacingData {
|
||||
})));
|
||||
|
||||
return {
|
||||
logoUrl: `https://api.gridpilot.io/media/team/${team.id}/logo.png`,
|
||||
logoUrl: `${this.getMediaBaseUrl()}/api/media/teams/${team.id}/logo`,
|
||||
performanceLevel,
|
||||
specialization,
|
||||
region,
|
||||
@@ -482,21 +486,22 @@ export class SeedRacingData {
|
||||
}
|
||||
|
||||
private async seedMediaAssets(seed: any): Promise<void> {
|
||||
// Seed driver avatars
|
||||
const baseUrl = this.getMediaBaseUrl();
|
||||
|
||||
// Seed driver avatars using static files
|
||||
for (const driver of seed.drivers) {
|
||||
const avatarUrl = `https://api.gridpilot.io/media/driver/${driver.id}/avatar.png`;
|
||||
|
||||
// Type assertion to access the helper method
|
||||
const avatarUrl = this.getDriverAvatarUrl(driver.id);
|
||||
|
||||
const mediaRepo = this.seedDeps.mediaRepository as any;
|
||||
if (mediaRepo.setDriverAvatar) {
|
||||
mediaRepo.setDriverAvatar(driver.id, avatarUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// Seed team logos
|
||||
// Seed team logos using API routes
|
||||
for (const team of seed.teams) {
|
||||
const logoUrl = `https://api.gridpilot.io/media/team/${team.id}/logo.png`;
|
||||
|
||||
const logoUrl = `${baseUrl}/api/media/teams/${team.id}/logo`;
|
||||
|
||||
const mediaRepo = this.seedDeps.mediaRepository as any;
|
||||
if (mediaRepo.setTeamLogo) {
|
||||
mediaRepo.setTeamLogo(team.id, logoUrl);
|
||||
@@ -505,8 +510,8 @@ export class SeedRacingData {
|
||||
|
||||
// Seed track images
|
||||
for (const track of seed.tracks || []) {
|
||||
const trackImageUrl = `https://api.gridpilot.io/media/track/${track.id}/image.png`;
|
||||
|
||||
const trackImageUrl = `${baseUrl}/api/media/tracks/${track.id}/image`;
|
||||
|
||||
const mediaRepo = this.seedDeps.mediaRepository as any;
|
||||
if (mediaRepo.setTrackImage) {
|
||||
mediaRepo.setTrackImage(track.id, trackImageUrl);
|
||||
@@ -516,8 +521,8 @@ export class SeedRacingData {
|
||||
// Seed category icons (if categories exist)
|
||||
const categories = ['beginner', 'intermediate', 'advanced', 'pro', 'endurance', 'sprint'];
|
||||
for (const category of categories) {
|
||||
const iconUrl = `https://api.gridpilot.io/media/category/${category}/icon.png`;
|
||||
|
||||
const iconUrl = `${baseUrl}/api/media/categories/${category}/icon`;
|
||||
|
||||
const mediaRepo = this.seedDeps.mediaRepository as any;
|
||||
if (mediaRepo.setCategoryIcon) {
|
||||
mediaRepo.setCategoryIcon(category, iconUrl);
|
||||
@@ -526,8 +531,8 @@ export class SeedRacingData {
|
||||
|
||||
// Seed sponsor logos
|
||||
for (const sponsor of seed.sponsors || []) {
|
||||
const logoUrl = `https://api.gridpilot.io/media/sponsor/${sponsor.id}/logo.png`;
|
||||
|
||||
const logoUrl = `${baseUrl}/api/media/sponsors/${sponsor.id}/logo`;
|
||||
|
||||
const mediaRepo = this.seedDeps.mediaRepository as any;
|
||||
if (mediaRepo.setSponsorLogo) {
|
||||
mediaRepo.setSponsorLogo(sponsor.id, logoUrl);
|
||||
@@ -537,6 +542,48 @@ export class SeedRacingData {
|
||||
this.logger.info(`[Bootstrap] Seeded media assets for ${seed.drivers.length} drivers, ${seed.teams.length} teams`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get deterministic avatar URL for a driver based on their ID
|
||||
* Uses static files from the website public directory
|
||||
*/
|
||||
private getDriverAvatarUrl(driverId: string): string {
|
||||
// Deterministic selection based on driver ID
|
||||
const numericSuffixMatch = driverId.match(/(\d+)$/);
|
||||
let useFemale = false;
|
||||
let useNeutral = false;
|
||||
|
||||
if (numericSuffixMatch && numericSuffixMatch[1]) {
|
||||
const numericSuffix = parseInt(numericSuffixMatch[1], 10);
|
||||
// 40% female, 40% male, 20% neutral
|
||||
if (numericSuffix % 5 === 0) {
|
||||
useNeutral = true;
|
||||
} else if (numericSuffix % 2 === 0) {
|
||||
useFemale = true;
|
||||
}
|
||||
} else {
|
||||
// Fallback hash
|
||||
let hash = 0;
|
||||
for (let i = 0; i < driverId.length; i++) {
|
||||
hash = (hash * 31 + driverId.charCodeAt(i)) | 0;
|
||||
}
|
||||
const hashValue = Math.abs(hash);
|
||||
if (hashValue % 5 === 0) {
|
||||
useNeutral = true;
|
||||
} else if (hashValue % 2 === 0) {
|
||||
useFemale = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return static file paths that Next.js can serve
|
||||
if (useNeutral) {
|
||||
return '/images/avatars/neutral-default-avatar.jpeg';
|
||||
} else if (useFemale) {
|
||||
return '/images/avatars/female-default-avatar.jpeg';
|
||||
} else {
|
||||
return '/images/avatars/male-default-avatar.jpg';
|
||||
}
|
||||
}
|
||||
|
||||
private async clearExistingRacingData(): Promise<void> {
|
||||
// Get all existing drivers
|
||||
const drivers = await this.seedDeps.driverRepository.findAll();
|
||||
|
||||
Reference in New Issue
Block a user