import type { UseCase } from '@core/shared/application/UseCase'; import type { IRaceEventRepository } from '../../domain/repositories/IRaceEventRepository'; import type { IDomainEventPublisher } from '@core/shared/domain'; import type { RaceEventStewardingClosedEvent } from '../../domain/events/RaceEventStewardingClosed'; /** * Use Case: CloseRaceEventStewardingUseCase * * Scheduled job that checks for race events with expired stewarding windows * and closes them, triggering final results notifications. * * This would typically be run by a scheduled job (e.g., every 5 minutes) * to automatically close stewarding windows based on league configuration. */ export interface CloseRaceEventStewardingCommand { // No parameters needed - finds all expired events automatically } export class CloseRaceEventStewardingUseCase implements UseCase { constructor( private readonly raceEventRepository: IRaceEventRepository, private readonly domainEventPublisher: IDomainEventPublisher, ) {} async execute(command: CloseRaceEventStewardingCommand): Promise { // Find all race events awaiting stewarding that have expired windows const expiredEvents = await this.raceEventRepository.findAwaitingStewardingClose(); for (const raceEvent of expiredEvents) { await this.closeStewardingForRaceEvent(raceEvent); } } private async closeStewardingForRaceEvent(raceEvent: any): Promise { try { // Close the stewarding window const closedRaceEvent = raceEvent.closeStewarding(); await this.raceEventRepository.update(closedRaceEvent); // Get list of participating drivers (would need to be implemented) const driverIds = await this.getParticipatingDriverIds(raceEvent); // Check if any penalties were applied during stewarding const hadPenaltiesApplied = await this.checkForAppliedPenalties(raceEvent); // Publish domain event to trigger final results notifications const event = new RaceEventStewardingClosedEvent({ raceEventId: raceEvent.id, leagueId: raceEvent.leagueId, seasonId: raceEvent.seasonId, closedAt: new Date(), driverIds, hadPenaltiesApplied, }); await this.domainEventPublisher.publish(event); } catch (error) { console.error(`Failed to close stewarding for race event ${raceEvent.id}:`, error); // In production, this would trigger alerts/monitoring } } private async getParticipatingDriverIds(raceEvent: any): Promise { // In a real implementation, this would query race registrations // For the prototype, we'll return a mock list // This would typically involve: // 1. Get all sessions in the race event // 2. For each session, get registered drivers // 3. Return unique driver IDs across all sessions // Mock implementation for prototype return ['driver-1', 'driver-2', 'driver-3']; // Would be dynamic in real implementation } private async checkForAppliedPenalties(raceEvent: any): Promise { // In a real implementation, this would check if any penalties were issued // during the stewarding window for this race event // This would query the penalty repository for penalties related to this race event // Mock implementation for prototype - randomly simulate penalties return Math.random() > 0.7; // 30% chance of penalties being applied } }