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>( (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, }; } }