/** * Application Use Case: RankingUseCase * * Computes driver rankings from real standings and results data. * Orchestrates repositories to provide ranking data to presentation layer. */ import type { Logger } from '@core/shared/application'; import type { IStandingRepository } from '../../domain/repositories/IStandingRepository'; import type { IDriverRepository } from '../../domain/repositories/IDriverRepository'; import type { IRankingUseCase, DriverRanking } from './IRankingUseCase'; export class RankingUseCase implements IRankingUseCase { constructor( private readonly standingRepository: IStandingRepository, private readonly driverRepository: IDriverRepository, private readonly logger: Logger ) { this.logger.info('[RankingUseCase] Initialized with real data repositories'); } async getAllDriverRankings(): Promise { this.logger.debug('[RankingUseCase] Computing rankings from standings'); try { // Get all standings from all leagues const standings = await this.standingRepository.findAll(); if (standings.length === 0) { this.logger.warn('[RankingUseCase] No standings found'); return []; } // Get all drivers for name resolution const drivers = await this.driverRepository.findAll(); const driverMap = new Map(drivers.map(d => [d.id, d])); // Group standings by driver and aggregate stats const driverStats = new Map(); for (const standing of standings) { const driverId = standing.driverId.toString(); const existing = driverStats.get(driverId) || { rating: 0, wins: 0, races: 0 }; existing.races += standing.racesCompleted; existing.wins += standing.wins; // Calculate rating from points and position const baseRating = 1000; const pointsBonus = standing.points.toNumber() * 2; const positionBonus = Math.max(0, 50 - (standing.position.toNumber() * 2)); const winBonus = standing.wins * 100; existing.rating = Math.round(baseRating + pointsBonus + positionBonus + winBonus); // Add driver name if available const driver = driverMap.get(driverId); if (driver) { existing.driverName = driver.name.toString(); } driverStats.set(driverId, existing); } // Convert to rankings const rankings: DriverRanking[] = Array.from(driverStats.entries()).map(([driverId, stats]) => ({ driverId, rating: stats.rating, wins: stats.wins, totalRaces: stats.races, overallRank: null })); // Sort by rating descending and assign ranks rankings.sort((a, b) => b.rating - a.rating); rankings.forEach((r, idx) => r.overallRank = idx + 1); this.logger.info(`[RankingUseCase] Computed rankings for ${rankings.length} drivers`); return rankings; } catch (error) { this.logger.error('[RankingUseCase] Error computing rankings:', error instanceof Error ? error : new Error(String(error))); throw error; } } }