Some checks failed
CI / lint-typecheck (pull_request) Failing after 4m51s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
89 lines
2.7 KiB
TypeScript
89 lines
2.7 KiB
TypeScript
/**
|
|
* 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<RatingLeaderboardEntry[]> {
|
|
const { ratingRepository, driverRepository } = this.ports;
|
|
const { limit = 50, offset = 0 } = request;
|
|
|
|
try {
|
|
// Get all ratings
|
|
const allRatings: Rating[] = [];
|
|
const driverIds = new Set<string>();
|
|
|
|
// Group ratings by driver and get latest rating for each driver
|
|
const driverRatings = new Map<string, Rating>();
|
|
|
|
// 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}`);
|
|
}
|
|
}
|
|
}
|