63 lines
2.2 KiB
TypeScript
63 lines
2.2 KiB
TypeScript
/**
|
|
* Rulebook View Data Builder
|
|
*
|
|
* Transforms API DTO to ViewData for templates.
|
|
*/
|
|
|
|
import type { RulebookViewData } from '@/lib/view-data/RulebookViewData';
|
|
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
|
|
|
interface RulebookApiDto {
|
|
leagueId: string;
|
|
scoringConfig: {
|
|
gameName: string;
|
|
scoringPresetName: string;
|
|
championships: Array<{
|
|
type: string;
|
|
sessionTypes: string[];
|
|
pointsPreview: Array<{
|
|
sessionType: string;
|
|
position: number;
|
|
points: number;
|
|
}>;
|
|
bonusSummary: string[];
|
|
}>;
|
|
dropPolicySummary: string;
|
|
};
|
|
}
|
|
|
|
export class RulebookViewDataBuilder {
|
|
/**
|
|
* Transform API DTO to ViewData
|
|
*
|
|
* @param apiDto - The DTO from the service
|
|
* @returns ViewData for the rulebook page
|
|
*/
|
|
public static build(apiDto: RulebookApiDto): RulebookViewData {
|
|
const primaryChampionship = apiDto.scoringConfig.championships.find(c => c.type === 'driver') ?? apiDto.scoringConfig.championships[0];
|
|
|
|
const positionPoints: { position: number; points: number }[] = (primaryChampionship?.pointsPreview || [])
|
|
.filter((p: unknown): p is { sessionType: string; position: number; points: number } => {
|
|
const point = p as { sessionType?: string; position?: number; points?: number };
|
|
return point.sessionType === primaryChampionship?.sessionTypes[0];
|
|
})
|
|
.map(p => ({ position: p.position, points: p.points }))
|
|
.sort((a, b) => a.position - b.position);
|
|
|
|
return {
|
|
leagueId: apiDto.leagueId,
|
|
gameName: apiDto.scoringConfig.gameName,
|
|
scoringPresetName: apiDto.scoringConfig.scoringPresetName || 'Custom',
|
|
championshipsCount: apiDto.scoringConfig.championships.length,
|
|
sessionTypes: primaryChampionship?.sessionTypes.join(', ') || 'Main',
|
|
dropPolicySummary: apiDto.scoringConfig.dropPolicySummary,
|
|
hasActiveDropPolicy: !!apiDto.scoringConfig.dropPolicySummary && !apiDto.scoringConfig.dropPolicySummary.toLowerCase().includes('all'),
|
|
positionPoints,
|
|
bonusPoints: primaryChampionship?.bonusSummary || [],
|
|
hasBonusPoints: (primaryChampionship?.bonusSummary.length || 0) > 0,
|
|
};
|
|
}
|
|
}
|
|
|
|
RulebookViewDataBuilder satisfies ViewDataBuilder<RulebookApiDto, RulebookViewData>;
|