team rating

This commit is contained in:
2025-12-30 12:25:45 +01:00
parent ccaa39c39c
commit 83371ea839
93 changed files with 10324 additions and 490 deletions

View File

@@ -3,6 +3,8 @@ import type { ITeamRepository } from '../../domain/repositories/ITeamRepository'
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { ISocialGraphRepository } from '@core/social/domain/repositories/ISocialGraphRepository';
import type { DriverExtendedProfileProvider } from '../ports/DriverExtendedProfileProvider';
import type { IDriverStatsUseCase, DriverStats } from './IDriverStatsUseCase';
import type { IRankingUseCase, DriverRanking } from './IRankingUseCase';
import type { Driver } from '../../domain/entities/Driver';
import type { Team } from '../../domain/entities/Team';
import type { TeamMembership } from '../../domain/types/TeamMembership';
@@ -10,26 +12,6 @@ import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
interface ProfileDriverStatsAdapter {
rating: number | null;
wins: number;
podiums: number;
dnfs: number;
totalRaces: number;
avgFinish: number | null;
bestFinish: number | null;
worstFinish: number | null;
overallRank: number | null;
consistency: number | null;
percentile: number | null;
}
interface DriverRankingEntry {
driverId: string;
rating: number;
overallRank: number | null;
}
export type GetProfileOverviewInput = {
driverId: string;
};
@@ -98,8 +80,8 @@ export class GetProfileOverviewUseCase {
private readonly teamMembershipRepository: ITeamMembershipRepository,
private readonly socialRepository: ISocialGraphRepository,
private readonly driverExtendedProfileProvider: DriverExtendedProfileProvider,
private readonly getDriverStats: (driverId: string) => ProfileDriverStatsAdapter | null,
private readonly getAllDriverRankings: () => DriverRankingEntry[],
private readonly driverStatsUseCase: IDriverStatsUseCase,
private readonly rankingUseCase: IRankingUseCase,
private readonly output: UseCaseOutputPort<GetProfileOverviewResult>,
) {}
@@ -120,15 +102,15 @@ export class GetProfileOverviewUseCase {
});
}
const [statsAdapter, teams, friends] = await Promise.all([
Promise.resolve(this.getDriverStats(driverId)),
const [driverStats, teams, friends] = await Promise.all([
this.driverStatsUseCase.getDriverStats(driverId),
this.teamRepository.findAll(),
this.socialRepository.getFriends(driverId),
]);
const driverInfo = this.buildDriverInfo(driver, statsAdapter);
const stats = this.buildStats(statsAdapter);
const finishDistribution = this.buildFinishDistribution(statsAdapter);
const driverInfo = await this.buildDriverInfo(driver, driverStats);
const stats = this.buildStats(driverStats);
const finishDistribution = this.buildFinishDistribution(driverStats);
const teamMemberships = await this.buildTeamMemberships(driver.id, teams);
const socialSummary = this.buildSocialSummary(friends);
const extendedProfile =
@@ -159,11 +141,11 @@ export class GetProfileOverviewUseCase {
}
}
private buildDriverInfo(
private async buildDriverInfo(
driver: Driver,
stats: ProfileDriverStatsAdapter | null,
): ProfileOverviewDriverInfo {
const rankings = this.getAllDriverRankings();
stats: DriverStats | null,
): Promise<ProfileOverviewDriverInfo> {
const rankings = await this.rankingUseCase.getAllDriverRankings();
const fallbackRank = this.computeFallbackRank(driver.id, rankings);
const totalDrivers = rankings.length;
@@ -178,7 +160,7 @@ export class GetProfileOverviewUseCase {
private computeFallbackRank(
driverId: string,
rankings: DriverRankingEntry[],
rankings: DriverRanking[],
): number | null {
const index = rankings.findIndex(entry => entry.driverId === driverId);
if (index === -1) {
@@ -188,7 +170,7 @@ export class GetProfileOverviewUseCase {
}
private buildStats(
stats: ProfileDriverStatsAdapter | null,
stats: DriverStats | null,
): ProfileOverviewStats | null {
if (!stats) {
return null;
@@ -213,7 +195,7 @@ export class GetProfileOverviewUseCase {
finishRate,
winRate,
podiumRate,
percentile: stats.percentile,
percentile: null, // Not available in new DriverStats
rating: stats.rating,
consistency: stats.consistency,
overallRank: stats.overallRank,
@@ -221,7 +203,7 @@ export class GetProfileOverviewUseCase {
}
private buildFinishDistribution(
stats: ProfileDriverStatsAdapter | null,
stats: DriverStats | null,
): ProfileOverviewFinishDistribution | null {
if (!stats || stats.totalRaces <= 0) {
return null;