wip
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import type {
|
||||
ILeagueDriverSeasonStatsPresenter,
|
||||
LeagueDriverSeasonStatsItemViewModel,
|
||||
LeagueDriverSeasonStatsViewModel,
|
||||
} from '@gridpilot/racing/application/presenters/ILeagueDriverSeasonStatsPresenter';
|
||||
|
||||
export class LeagueDriverSeasonStatsPresenter implements ILeagueDriverSeasonStatsPresenter {
|
||||
private viewModel: LeagueDriverSeasonStatsViewModel | null = null;
|
||||
|
||||
present(
|
||||
leagueId: string,
|
||||
standings: Array<{
|
||||
driverId: string;
|
||||
position: number;
|
||||
points: number;
|
||||
racesCompleted: number;
|
||||
}>,
|
||||
penalties: Map<string, { baseDelta: number; bonusDelta: number }>,
|
||||
driverResults: Map<string, Array<{ position: number }>>,
|
||||
driverRatings: Map<string, { rating: number | null; ratingChange: number | null }>
|
||||
): LeagueDriverSeasonStatsViewModel {
|
||||
const stats: LeagueDriverSeasonStatsItemViewModel[] = standings.map((standing) => {
|
||||
const penalty = penalties.get(standing.driverId) ?? { baseDelta: 0, bonusDelta: 0 };
|
||||
const totalPenaltyPoints = penalty.baseDelta;
|
||||
const bonusPoints = penalty.bonusDelta;
|
||||
|
||||
const racesCompleted = standing.racesCompleted;
|
||||
const pointsPerRace = racesCompleted > 0 ? standing.points / racesCompleted : 0;
|
||||
|
||||
const ratingInfo = driverRatings.get(standing.driverId) ?? { rating: null, ratingChange: null };
|
||||
|
||||
const results = driverResults.get(standing.driverId) ?? [];
|
||||
let avgFinish: number | null = null;
|
||||
if (results.length > 0) {
|
||||
const totalPositions = results.reduce((sum, r) => sum + r.position, 0);
|
||||
const avg = totalPositions / results.length;
|
||||
avgFinish = Number.isFinite(avg) ? Number(avg.toFixed(2)) : null;
|
||||
}
|
||||
|
||||
return {
|
||||
leagueId,
|
||||
driverId: standing.driverId,
|
||||
position: standing.position,
|
||||
driverName: '',
|
||||
teamId: undefined,
|
||||
teamName: undefined,
|
||||
totalPoints: standing.points + totalPenaltyPoints + bonusPoints,
|
||||
basePoints: standing.points,
|
||||
penaltyPoints: Math.abs(totalPenaltyPoints),
|
||||
bonusPoints,
|
||||
pointsPerRace,
|
||||
racesStarted: results.length,
|
||||
racesFinished: results.length,
|
||||
dnfs: 0,
|
||||
noShows: 0,
|
||||
avgFinish,
|
||||
rating: ratingInfo.rating,
|
||||
ratingChange: ratingInfo.ratingChange,
|
||||
};
|
||||
});
|
||||
|
||||
stats.sort((a, b) => a.position - b.position);
|
||||
|
||||
this.viewModel = {
|
||||
leagueId,
|
||||
stats,
|
||||
};
|
||||
|
||||
return this.viewModel;
|
||||
}
|
||||
|
||||
getViewModel(): LeagueDriverSeasonStatsViewModel {
|
||||
if (!this.viewModel) {
|
||||
throw new Error('Presenter has not been called yet');
|
||||
}
|
||||
return this.viewModel;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user