100 lines
2.6 KiB
TypeScript
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 ?? [],
|
|
};
|
|
}
|
|
} |