/** * GetRatingLeaderboardUseCase * * Retrieves rating leaderboard for drivers. */ import { RatingRepository } from '../../ports/RatingRepository'; import { DriverRepository } from '../../../racing/domain/repositories/DriverRepository'; import { Rating } from '../../domain/Rating'; export interface GetRatingLeaderboardUseCasePorts { ratingRepository: RatingRepository; driverRepository: DriverRepository; } export interface GetRatingLeaderboardRequest { limit?: number; offset?: number; } export interface RatingLeaderboardEntry { driverId: string; driverName: string; rating: number; components: { resultsStrength: number; consistency: number; cleanDriving: number; racecraft: number; reliability: number; teamContribution: number; }; } export class GetRatingLeaderboardUseCase { constructor(private readonly ports: GetRatingLeaderboardUseCasePorts) {} async execute(request: GetRatingLeaderboardRequest): Promise { const { ratingRepository, driverRepository } = this.ports; const { limit = 50, offset = 0 } = request; try { // Get all ratings const allRatings: Rating[] = []; const driverIds = new Set(); // Group ratings by driver and get latest rating for each driver const driverRatings = new Map(); // In a real implementation, this would be optimized with a database query // For now, we'll simulate getting the latest rating for each driver const drivers = await driverRepository.findAll(); for (const driver of drivers) { const driverRatingsList = await ratingRepository.findByDriver(driver.id); if (driverRatingsList.length > 0) { // Get the latest rating (most recent timestamp) const latestRating = driverRatingsList.reduce((latest, current) => current.timestamp > latest.timestamp ? current : latest ); driverRatings.set(driver.id, latestRating); } } // Convert to leaderboard entries const entries: RatingLeaderboardEntry[] = []; for (const [driverId, rating] of driverRatings.entries()) { const driver = await driverRepository.findById(driverId); if (driver) { entries.push({ driverId, driverName: driver.name.toString(), rating: rating.rating, components: rating.components, }); } } // Sort by rating (descending) entries.sort((a, b) => b.rating - a.rating); // Apply pagination return entries.slice(offset, offset + limit); } catch (error) { throw new Error(`Failed to get rating leaderboard: ${error}`); } } }