71 lines
2.2 KiB
TypeScript
71 lines
2.2 KiB
TypeScript
import { ChampionshipStanding } from '../entities/championship/ChampionshipStanding';
|
|
import type { ChampionshipConfig } from '../types/ChampionshipConfig';
|
|
import type { ParticipantRef } from '../types/ParticipantRef';
|
|
import { DropScoreApplier, type EventPointsEntry } from './DropScoreApplier';
|
|
import type { ParticipantEventPoints } from './EventScoringService';
|
|
|
|
export class ChampionshipAggregator {
|
|
constructor(private readonly dropScoreApplier: DropScoreApplier) {}
|
|
|
|
aggregate(params: {
|
|
seasonId: string;
|
|
championship: ChampionshipConfig;
|
|
eventPointsByEventId: Record<string, ParticipantEventPoints[]>;
|
|
}): ChampionshipStanding[] {
|
|
const { seasonId, championship, eventPointsByEventId } = params;
|
|
|
|
const perParticipantEvents = new Map<
|
|
string,
|
|
{ participant: ParticipantRef; events: EventPointsEntry[] }
|
|
>();
|
|
|
|
for (const [eventId, pointsList] of Object.entries(eventPointsByEventId)) {
|
|
for (const entry of pointsList) {
|
|
const key = entry.participant.id;
|
|
const existing = perParticipantEvents.get(key);
|
|
const eventEntry: EventPointsEntry = {
|
|
eventId,
|
|
points: entry.totalPoints,
|
|
};
|
|
|
|
if (existing) {
|
|
existing.events.push(eventEntry);
|
|
} else {
|
|
perParticipantEvents.set(key, {
|
|
participant: entry.participant,
|
|
events: [eventEntry],
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
const standings: ChampionshipStanding[] = [];
|
|
|
|
for (const { participant, events } of perParticipantEvents.values()) {
|
|
const dropResult = this.dropScoreApplier.apply(
|
|
championship.dropScorePolicy,
|
|
events,
|
|
);
|
|
|
|
const totalPoints = dropResult.totalPoints;
|
|
const resultsCounted = dropResult.counted.length;
|
|
const resultsDropped = dropResult.dropped.length;
|
|
|
|
standings.push(
|
|
ChampionshipStanding.create({
|
|
seasonId,
|
|
championshipId: championship.id,
|
|
participant,
|
|
totalPoints,
|
|
resultsCounted,
|
|
resultsDropped,
|
|
position: 1,
|
|
}),
|
|
);
|
|
}
|
|
|
|
standings.sort((a, b) => b.totalPoints.toNumber() - a.totalPoints.toNumber());
|
|
|
|
return standings.map((s, index) => s.withPosition(index + 1));
|
|
}
|
|
} |