Files
gridpilot.gg/apps/website/lib/presenters/TeamsLeaderboardPresenter.ts
2025-12-11 21:06:25 +01:00

100 lines
2.6 KiB
TypeScript

import type {
ITeamsLeaderboardPresenter,
TeamsLeaderboardViewModel,
TeamLeaderboardItemViewModel,
SkillLevel,
TeamsLeaderboardResultDTO,
} from '@gridpilot/racing/application/presenters/ITeamsLeaderboardPresenter';
interface TeamLeaderboardInput {
id: string;
name: string;
memberCount: number;
rating: number | null;
totalWins: number;
totalRaces: number;
performanceLevel: SkillLevel;
isRecruiting: boolean;
createdAt: Date;
description?: string | null;
specialization?: string | null;
region?: string | null;
languages?: string[];
}
export class TeamsLeaderboardPresenter implements ITeamsLeaderboardPresenter {
private viewModel: TeamsLeaderboardViewModel | null = null;
reset(): void {
this.viewModel = null;
}
present(input: TeamsLeaderboardResultDTO): void {
const teams = (input.teams ?? []) as TeamLeaderboardInput[];
const recruitingCount = input.recruitingCount ?? 0;
const transformedTeams = teams.map((team) => this.transformTeam(team));
const groupsBySkillLevel = transformedTeams.reduce<Record<SkillLevel, TeamLeaderboardItemViewModel[]>>(
(acc, team) => {
if (!acc[team.performanceLevel]) {
acc[team.performanceLevel] = [];
}
acc[team.performanceLevel]!.push(team);
return acc;
},
{
beginner: [],
intermediate: [],
advanced: [],
pro: [],
},
);
const topTeams = transformedTeams
.filter((t) => t.rating !== null)
.slice()
.sort((a, b) => (b.rating ?? 0) - (a.rating ?? 0))
.slice(0, 5);
this.viewModel = {
teams: transformedTeams,
recruitingCount,
groupsBySkillLevel,
topTeams,
};
}
getViewModel(): TeamsLeaderboardViewModel | null {
return this.viewModel;
}
private transformTeam(team: TeamLeaderboardInput): TeamLeaderboardItemViewModel {
let specialization: TeamLeaderboardItemViewModel['specialization'];
if (
team.specialization === 'endurance' ||
team.specialization === 'sprint' ||
team.specialization === 'mixed'
) {
specialization = team.specialization;
} else {
specialization = undefined;
}
return {
id: team.id,
name: team.name,
memberCount: team.memberCount,
rating: team.rating,
totalWins: team.totalWins,
totalRaces: team.totalRaces,
performanceLevel: team.performanceLevel,
isRecruiting: team.isRecruiting,
createdAt: team.createdAt,
description: team.description ?? '',
specialization: specialization ?? 'mixed',
region: team.region ?? '',
languages: team.languages ?? [],
};
}
}