66 lines
1.8 KiB
TypeScript
66 lines
1.8 KiB
TypeScript
import type { DomainCalculationService } from '@core/shared/domain/Service';
|
|
import type { DropScorePolicy } from '../types/DropScorePolicy';
|
|
|
|
export interface EventPointsEntry {
|
|
eventId: string;
|
|
points: number;
|
|
}
|
|
|
|
export interface DropScoreResult {
|
|
counted: EventPointsEntry[];
|
|
dropped: EventPointsEntry[];
|
|
totalPoints: number;
|
|
}
|
|
|
|
export interface DropScoreInput {
|
|
policy: DropScorePolicy;
|
|
events: EventPointsEntry[];
|
|
}
|
|
|
|
export class DropScoreApplier implements DomainCalculationService<DropScoreInput, DropScoreResult> {
|
|
calculate(input: DropScoreInput): DropScoreResult {
|
|
return this.apply(input.policy, input.events);
|
|
}
|
|
|
|
apply(policy: DropScorePolicy, events: EventPointsEntry[]): DropScoreResult {
|
|
if (policy.strategy === 'none' || events.length === 0) {
|
|
const totalPoints = events.reduce((sum, e) => sum + e.points, 0);
|
|
return {
|
|
counted: [...events],
|
|
dropped: [],
|
|
totalPoints,
|
|
};
|
|
}
|
|
|
|
if (policy.strategy === 'bestNResults') {
|
|
const count = policy.count ?? events.length;
|
|
if (count >= events.length) {
|
|
const totalPoints = events.reduce((sum, e) => sum + e.points, 0);
|
|
return {
|
|
counted: [...events],
|
|
dropped: [],
|
|
totalPoints,
|
|
};
|
|
}
|
|
|
|
const sorted = [...events].sort((a, b) => b.points - a.points);
|
|
const counted = sorted.slice(0, count);
|
|
const dropped = sorted.slice(count);
|
|
const totalPoints = counted.reduce((sum, e) => sum + e.points, 0);
|
|
|
|
return {
|
|
counted,
|
|
dropped,
|
|
totalPoints,
|
|
};
|
|
}
|
|
|
|
// For this slice, treat unsupported strategies as 'none'
|
|
const totalPoints = events.reduce((sum, e) => sum + e.points, 0);
|
|
return {
|
|
counted: [...events],
|
|
dropped: [],
|
|
totalPoints,
|
|
};
|
|
}
|
|
} |