import { League } from '@core/racing/domain/entities/League'; import { Race } from '@core/racing/domain/entities/Race'; import { Driver } from '@core/racing/domain/entities/Driver'; import { Money } from '@core/racing/domain/value-objects/Money'; import { SponsorshipPricing } from '@core/racing/domain/value-objects/SponsorshipPricing'; import { SponsorshipRequest, type SponsorableEntityType, } from '@core/racing/domain/entities/SponsorshipRequest'; import type { DemoTeamDTO } from './RacingSeedCore'; /** * Demo sponsor data for seeding. */ export interface DemoSponsorDTO { id: string; name: string; contactEmail: string; logoUrl: string; websiteUrl: string; tagline: string; } /** * Demo season sponsorship data. * This remains a simple DTO since the SeasonSponsorship * domain entity is instantiated in the DI config. */ export interface DemoSeasonSponsorshipDTO { id: string; seasonId: string; sponsorId: string; tier: 'main' | 'secondary'; pricingAmount: number; pricingCurrency: 'USD' | 'EUR' | 'GBP'; status: 'pending' | 'active' | 'cancelled'; description?: string; } /** * Demo sponsorship request data for seeding. * Backed directly by the SponsorshipRequest domain entity. */ export type DemoSponsorshipRequestDTO = SponsorshipRequest; /** * Demo sponsorship pricing configuration for entities, using the * SponsorshipPricing value object to keep pricing logic in the domain. */ export interface DemoSponsorshipPricingDTO { entityType: SponsorableEntityType; entityId: string; pricing: SponsorshipPricing; } /** * Demo sponsors data - realistic sim racing sponsors. */ export const DEMO_SPONSORS: DemoSponsorDTO[] = [ { id: 'sponsor-fanatec', name: 'Fanatec', contactEmail: 'partnerships@fanatec.com', logoUrl: '/images/sponsors/fanatec.svg', websiteUrl: 'https://fanatec.com', tagline: "The world's leading sim racing hardware", }, { id: 'sponsor-simucube', name: 'Simucube', contactEmail: 'sponsors@simucube.com', logoUrl: '/images/sponsors/simucube.svg', websiteUrl: 'https://simucube.com', tagline: 'Professional Direct Drive Wheels', }, { id: 'sponsor-heusinkveld', name: 'Heusinkveld', contactEmail: 'info@heusinkveld.com', logoUrl: '/images/sponsors/heusinkveld.svg', websiteUrl: 'https://heusinkveld.com', tagline: 'Sim Racing Pedals & Hardware', }, { id: 'sponsor-trak-racer', name: 'Trak Racer', contactEmail: 'partnerships@trakracer.com', logoUrl: '/images/sponsors/trak-racer.svg', websiteUrl: 'https://trakracer.com', tagline: 'Premium Racing Simulators & Cockpits', }, { id: 'sponsor-simlab', name: 'Sim-Lab', contactEmail: 'sponsor@sim-lab.eu', logoUrl: '/images/sponsors/simlab.svg', websiteUrl: 'https://sim-lab.eu', tagline: 'Aluminum Profile Sim Racing Rigs', }, { id: 'sponsor-motionrig', name: 'MotionRig Pro', contactEmail: 'business@motionrigpro.com', logoUrl: '/images/sponsors/motionrig.svg', websiteUrl: 'https://motionrigpro.com', tagline: 'Feel every turn, every bump', }, ]; /** * Create season sponsorships linking sponsors to leagues. */ export function createSeasonSponsorships( leagues: League[], sponsors: DemoSponsorDTO[], ): DemoSeasonSponsorshipDTO[] { const sponsorships: DemoSeasonSponsorshipDTO[] = []; const FANATEC_ID = sponsors.find((s) => s.id === 'sponsor-fanatec')?.id ?? 'sponsor-fanatec'; const HEUSINKVELD_ID = sponsors.find((s) => s.id === 'sponsor-heusinkveld')?.id ?? 'sponsor-heusinkveld'; const SIMUCUBE_ID = sponsors.find((s) => s.id === 'sponsor-simucube')?.id ?? 'sponsor-simucube'; const TRAK_RACER_ID = sponsors.find((s) => s.id === 'sponsor-trak-racer')?.id ?? 'sponsor-trak-racer'; const SIMLAB_ID = sponsors.find((s) => s.id === 'sponsor-simlab')?.id ?? 'sponsor-simlab'; const MOTIONRIG_ID = sponsors.find((s) => s.id === 'sponsor-motionrig')?.id ?? 'sponsor-motionrig'; // GridPilot Sprint Series - sponsored by Fanatec (main) + Heusinkveld & Simucube (secondary) const sprintLeague = leagues.find((l) => l.name === 'GridPilot Sprint Series'); if (sprintLeague) { sponsorships.push({ id: `sponsorship-${sprintLeague.id}-fanatec`, seasonId: `season-${sprintLeague.id}-demo`, sponsorId: FANATEC_ID, tier: 'main', pricingAmount: 5000, pricingCurrency: 'USD', status: 'active', description: 'Main sponsor for the Sprint Series - premium wheel branding', }); sponsorships.push({ id: `sponsorship-${sprintLeague.id}-heusinkveld`, seasonId: `season-${sprintLeague.id}-demo`, sponsorId: HEUSINKVELD_ID, tier: 'secondary', pricingAmount: 2000, pricingCurrency: 'USD', status: 'active', }); sponsorships.push({ id: `sponsorship-${sprintLeague.id}-simucube`, seasonId: `season-${sprintLeague.id}-demo`, sponsorId: SIMUCUBE_ID, tier: 'secondary', pricingAmount: 2000, pricingCurrency: 'USD', status: 'active', }); } // GridPilot Endurance Cup - sponsored by Trak Racer (main) + Sim-Lab (secondary) const enduranceLeague = leagues.find((l) => l.name === 'GridPilot Endurance Cup'); if (enduranceLeague) { sponsorships.push({ id: `sponsorship-${enduranceLeague.id}-trakracer`, seasonId: `season-${enduranceLeague.id}-demo`, sponsorId: TRAK_RACER_ID, tier: 'main', pricingAmount: 7500, pricingCurrency: 'USD', status: 'active', description: 'Endurance series naming rights', }); sponsorships.push({ id: `sponsorship-${enduranceLeague.id}-simlab`, seasonId: `season-${enduranceLeague.id}-demo`, sponsorId: SIMLAB_ID, tier: 'secondary', pricingAmount: 3000, pricingCurrency: 'USD', status: 'active', }); } // GridPilot Club Ladder - sponsored by MotionRig Pro (main) const clubLeague = leagues.find((l) => l.name === 'GridPilot Club Ladder'); if (clubLeague) { sponsorships.push({ id: `sponsorship-${clubLeague.id}-motionrig`, seasonId: `season-${clubLeague.id}-demo`, sponsorId: MOTIONRIG_ID, tier: 'main', pricingAmount: 3500, pricingCurrency: 'USD', status: 'active', description: 'Club ladder motion platform showcase', }); } return sponsorships; } /** * Create sponsorship pricing configurations for demo entities. * Uses the SponsorshipPricing value object to ensure domain consistency * and to provide a mix of season, team, driver and race offerings. */ export function createSponsorshipPricings( leagues: League[], teams: DemoTeamDTO[], drivers: Driver[], races: Race[], ): DemoSponsorshipPricingDTO[] { const pricings: DemoSponsorshipPricingDTO[] = []; // League/Season pricing - all leagues can accept sponsorships, with varied configs leagues.forEach((league, index) => { let pricing = SponsorshipPricing.defaultLeague(); // Vary league pricing/availability for demo richness if (index % 3 === 1) { // Some leagues closed for applications pricing = pricing.setAcceptingApplications(false); } else if (index % 3 === 2) { // Some leagues with main-only sponsorship pricing = pricing.updateSecondarySlot({ available: false, maxSlots: 0 }); } else { // Slightly higher price for featured leagues pricing = pricing.updateMainSlot({ price: Money.create(1000 + index * 50, 'USD'), }); } pricings.push({ entityType: 'season', entityId: `season-${league.id}-demo`, pricing, }); }); // Team pricing - first 10 teams accept sponsorships using team defaults, // with some teams pausing applications. teams.slice(0, 10).forEach((team, index) => { let pricing = SponsorshipPricing.defaultTeam(); if (index % 4 === 1) { // Teams with main + secondary but not currently accepting pricing = pricing.setAcceptingApplications(false); } else if (index % 4 === 2) { // Teams with only secondary slots pricing = pricing.updateMainSlot({ available: false, maxSlots: 0 }); } else if (index % 4 === 3) { // Teams with premium main slot pricing pricing = pricing.updateMainSlot({ price: Money.create(750 + index * 25, 'USD'), }); } pricings.push({ entityType: 'team', entityId: team.id, pricing, }); }); // Driver pricing - first 20 drivers accept sponsorships with varied availability. drivers.slice(0, 20).forEach((driver, index) => { let pricing = SponsorshipPricing.defaultDriver(); if (index % 3 === 0) { // Higher profile drivers pricing = pricing.updateMainSlot({ price: Money.create(250 + index * 10, 'USD'), }); } else if (index % 3 === 1) { // Drivers temporarily not accepting sponsorships pricing = pricing.setAcceptingApplications(false); } pricings.push({ entityType: 'driver', entityId: driver.id, pricing, }); }); // Race pricing - upcoming races can have title sponsors with different tiers const upcomingRaces = races.filter((r) => r.status === 'scheduled').slice(0, 10); upcomingRaces.forEach((race, index) => { let pricing = SponsorshipPricing.defaultRace(); if (index % 2 === 0) { // Premium events with higher pricing pricing = pricing.updateMainSlot({ price: Money.create(350 + index * 30, 'USD'), }); } pricings.push({ entityType: 'race', entityId: race.id, pricing, }); }); return pricings; } /** * Create demo sponsorship requests (some pending, some accepted/rejected). * Uses the SponsorshipRequest domain entity and Money value object so that * all downstream sponsor flows can rely on domain behavior. */ export function createSponsorshipRequests( sponsors: DemoSponsorDTO[], leagues: League[], teams: DemoTeamDTO[], drivers: Driver[], races: Race[], ): DemoSponsorshipRequestDTO[] { const requests: DemoSponsorshipRequestDTO[] = []; const now = new Date(); const SIMUCUBE_ID = sponsors.find((s) => s.id === 'sponsor-simucube')?.id ?? 'sponsor-simucube'; const HEUSINKVELD_ID = sponsors.find((s) => s.id === 'sponsor-heusinkveld')?.id ?? 'sponsor-heusinkveld'; const TRAK_RACER_ID = sponsors.find((s) => s.id === 'sponsor-trak-racer')?.id ?? 'sponsor-trak-racer'; const MOTIONRIG_ID = sponsors.find((s) => s.id === 'sponsor-motionrig')?.id ?? 'sponsor-motionrig'; const SIMLAB_ID = sponsors.find((s) => s.id === 'sponsor-simlab')?.id ?? 'sponsor-simlab'; // Pending request: Simucube wants to sponsor a driver if (drivers.length > 6) { const targetDriver = drivers[5]; if (targetDriver) { requests.push( SponsorshipRequest.create({ id: 'req-simucube-driver-1', sponsorId: SIMUCUBE_ID, entityType: 'driver', entityId: targetDriver.id, tier: 'main', offeredAmount: Money.create(250, 'USD'), message: 'We would love to sponsor your racing career! Simucube offers the best direct drive wheels in sim racing.', createdAt: new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000), // 2 days ago }), ); } } // Pending request: Heusinkveld wants to sponsor a team if (teams.length > 3) { const targetTeam = teams[2]; if (targetTeam) { requests.push( SponsorshipRequest.create({ id: 'req-heusinkveld-team-1', sponsorId: HEUSINKVELD_ID, entityType: 'team', entityId: targetTeam.id, tier: 'main', offeredAmount: Money.create(550, 'USD'), message: 'Heusinkveld pedals are known for their precision. We believe your team embodies the same values.', createdAt: new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000), // 3 days ago }), ); } } // Pending request: Trak Racer wants to sponsor a race const upcomingRace = races.find((r) => r.status === 'scheduled'); if (upcomingRace) { requests.push( SponsorshipRequest.create({ id: 'req-trakracer-race-1', sponsorId: TRAK_RACER_ID, entityType: 'race', entityId: upcomingRace.id, tier: 'main', offeredAmount: Money.create(350, 'USD'), message: 'We would like to be the title sponsor for this exciting race event!', createdAt: new Date(now.getTime() - 1 * 24 * 60 * 60 * 1000), // 1 day ago }), ); } // Pending request: MotionRig Pro wants secondary spot on a league season const clubLeague = leagues.find((l) => l.name === 'Sprint Challenge League'); if (clubLeague) { requests.push( SponsorshipRequest.create({ id: 'req-motionrig-league-1', sponsorId: MOTIONRIG_ID, entityType: 'season', entityId: `season-${clubLeague.id}-demo`, tier: 'secondary', offeredAmount: Money.create(1500, 'USD'), message: 'MotionRig Pro would love to be a secondary sponsor. Our motion platforms are perfect for your competitive drivers.', createdAt: new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000), // 5 days ago }), ); } // Already accepted request (for history) if (teams.length > 0) { const acceptedTeam = teams[0]; if (acceptedTeam) { requests.push( SponsorshipRequest.create({ id: 'req-simlab-team-accepted', sponsorId: SIMLAB_ID, entityType: 'team', entityId: acceptedTeam.id, tier: 'secondary', offeredAmount: Money.create(300, 'USD'), message: 'Sim-Lab rigs are the foundation of any competitive setup.', status: 'accepted', createdAt: new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000), // 30 days ago }), ); } } // Already rejected request (for history) if (drivers.length > 10) { const rejectedDriver = drivers[10]; if (rejectedDriver) { requests.push( SponsorshipRequest.create({ id: 'req-motionrig-driver-rejected', sponsorId: MOTIONRIG_ID, entityType: 'driver', entityId: rejectedDriver.id, tier: 'main', offeredAmount: Money.create(150, 'USD'), message: 'Would you like to represent MotionRig Pro?', status: 'rejected', createdAt: new Date(now.getTime() - 20 * 24 * 60 * 60 * 1000), // 20 days ago }), ); } } return requests; }