/** * Infrastructure Adapter: InMemoryRaceRegistrationRepository * * In-memory implementation of IRaceRegistrationRepository. * Stores race registrations in Maps keyed by raceId and driverId. */ import type { RaceRegistration } from '@gridpilot/racing/domain/entities/RaceRegistration'; import type { IRaceRegistrationRepository } from '@gridpilot/racing/domain/repositories/IRaceRegistrationRepository'; type RaceRegistrationSeed = Pick; export class InMemoryRaceRegistrationRepository implements IRaceRegistrationRepository { private registrationsByRace: Map>; private registrationsByDriver: Map>; constructor(seedRegistrations?: RaceRegistrationSeed[]) { this.registrationsByRace = new Map(); this.registrationsByDriver = new Map(); if (seedRegistrations) { seedRegistrations.forEach((registration) => { this.addToIndexes(registration.raceId, registration.driverId, registration.registeredAt); }); } } private addToIndexes(raceId: string, driverId: string, _registeredAt: Date): void { let raceSet = this.registrationsByRace.get(raceId); if (!raceSet) { raceSet = new Set(); this.registrationsByRace.set(raceId, raceSet); } raceSet.add(driverId); let driverSet = this.registrationsByDriver.get(driverId); if (!driverSet) { driverSet = new Set(); this.registrationsByDriver.set(driverId, driverSet); } driverSet.add(raceId); } private removeFromIndexes(raceId: string, driverId: string): void { const raceSet = this.registrationsByRace.get(raceId); if (raceSet) { raceSet.delete(driverId); if (raceSet.size === 0) { this.registrationsByRace.delete(raceId); } } const driverSet = this.registrationsByDriver.get(driverId); if (driverSet) { driverSet.delete(raceId); if (driverSet.size === 0) { this.registrationsByDriver.delete(driverId); } } } async isRegistered(raceId: string, driverId: string): Promise { const raceSet = this.registrationsByRace.get(raceId); if (!raceSet) return false; return raceSet.has(driverId); } async getRegisteredDrivers(raceId: string): Promise { const raceSet = this.registrationsByRace.get(raceId); if (!raceSet) return []; return Array.from(raceSet.values()); } async getRegistrationCount(raceId: string): Promise { const raceSet = this.registrationsByRace.get(raceId); return raceSet ? raceSet.size : 0; } async register(registration: RaceRegistration): Promise { const alreadyRegistered = await this.isRegistered(registration.raceId, registration.driverId); if (alreadyRegistered) { throw new Error('Already registered for this race'); } this.addToIndexes(registration.raceId, registration.driverId, registration.registeredAt); } async withdraw(raceId: string, driverId: string): Promise { const alreadyRegistered = await this.isRegistered(raceId, driverId); if (!alreadyRegistered) { throw new Error('Not registered for this race'); } this.removeFromIndexes(raceId, driverId); } async getDriverRegistrations(driverId: string): Promise { const driverSet = this.registrationsByDriver.get(driverId); if (!driverSet) return []; return Array.from(driverSet.values()); } async clearRaceRegistrations(raceId: string): Promise { const raceSet = this.registrationsByRace.get(raceId); if (!raceSet) return; for (const driverId of raceSet.values()) { const driverSet = this.registrationsByDriver.get(driverId); if (driverSet) { driverSet.delete(raceId); if (driverSet.size === 0) { this.registrationsByDriver.delete(driverId); } } } this.registrationsByRace.delete(raceId); } }