Files
gridpilot.gg/apps/website/lib/presenters/TeamsLeaderboardPresenter.ts
2025-12-11 00:57:32 +01:00

68 lines
1.9 KiB
TypeScript

import type {
ITeamsLeaderboardPresenter,
TeamsLeaderboardViewModel,
TeamLeaderboardItemViewModel,
SkillLevel,
} from '@gridpilot/racing/application/presenters/ITeamsLeaderboardPresenter';
export class TeamsLeaderboardPresenter implements ITeamsLeaderboardPresenter {
private viewModel: TeamsLeaderboardViewModel | null = null;
present(teams: any[], recruitingCount: number): void {
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 {
if (!this.viewModel) {
throw new Error('ViewModel not yet generated. Call present() first.');
}
return this.viewModel;
}
private transformTeam(team: any): TeamLeaderboardItemViewModel {
return {
id: team.id,
name: team.name,
memberCount: team.memberCount,
rating: team.rating,
totalWins: team.totalWins,
totalRaces: team.totalRaces,
performanceLevel: team.performanceLevel as SkillLevel,
isRecruiting: team.isRecruiting,
createdAt: team.createdAt,
description: team.description,
specialization: team.specialization,
region: team.region,
languages: team.languages,
};
}
}