117 lines
3.6 KiB
TypeScript
117 lines
3.6 KiB
TypeScript
import type { DropScorePolicy } from '@gridpilot/racing/domain/types/DropScorePolicy';
|
|
import type {
|
|
ILeagueFullConfigPresenter,
|
|
LeagueFullConfigData,
|
|
LeagueConfigFormViewModel,
|
|
} from '@gridpilot/racing/application/presenters/ILeagueFullConfigPresenter';
|
|
|
|
export class LeagueFullConfigPresenter implements ILeagueFullConfigPresenter {
|
|
private viewModel: LeagueConfigFormViewModel | null = null;
|
|
|
|
reset(): void {
|
|
this.viewModel = null;
|
|
}
|
|
|
|
present(data: LeagueFullConfigData): void {
|
|
const { league, activeSeason, scoringConfig, game } = data;
|
|
|
|
const patternId = scoringConfig?.scoringPresetId;
|
|
|
|
const primaryChampionship =
|
|
scoringConfig && scoringConfig.championships && scoringConfig.championships.length > 0
|
|
? scoringConfig.championships[0]
|
|
: undefined;
|
|
|
|
const dropPolicy = primaryChampionship?.dropScorePolicy ?? undefined;
|
|
const dropPolicyForm = this.mapDropPolicy(dropPolicy);
|
|
|
|
const defaultQualifyingMinutes = 30;
|
|
const defaultMainRaceMinutes = 40;
|
|
const mainRaceMinutes =
|
|
typeof league.settings.sessionDuration === 'number'
|
|
? league.settings.sessionDuration
|
|
: defaultMainRaceMinutes;
|
|
const qualifyingMinutes = defaultQualifyingMinutes;
|
|
|
|
const roundsPlanned = 8;
|
|
|
|
let sessionCount = 2;
|
|
if (primaryChampionship && Array.isArray(primaryChampionship.sessionTypes)) {
|
|
sessionCount = primaryChampionship.sessionTypes.length;
|
|
}
|
|
|
|
const practiceMinutes = 20;
|
|
const sprintRaceMinutes = patternId === 'sprint-main-driver' ? 20 : undefined;
|
|
|
|
this.viewModel = {
|
|
leagueId: league.id,
|
|
basics: {
|
|
name: league.name,
|
|
description: league.description,
|
|
visibility: 'public',
|
|
gameId: game?.id ?? 'iracing',
|
|
},
|
|
structure: {
|
|
mode: 'solo',
|
|
maxDrivers: league.settings.maxDrivers ?? 32,
|
|
multiClassEnabled: false,
|
|
},
|
|
championships: {
|
|
enableDriverChampionship: true,
|
|
enableTeamChampionship: false,
|
|
enableNationsChampionship: false,
|
|
enableTrophyChampionship: false,
|
|
},
|
|
scoring: {
|
|
customScoringEnabled: !patternId,
|
|
...(patternId ? { patternId } : {}),
|
|
},
|
|
dropPolicy: dropPolicyForm,
|
|
timings: {
|
|
practiceMinutes,
|
|
qualifyingMinutes,
|
|
mainRaceMinutes,
|
|
sessionCount,
|
|
roundsPlanned,
|
|
...(typeof sprintRaceMinutes === 'number'
|
|
? { sprintRaceMinutes }
|
|
: {}),
|
|
},
|
|
stewarding: {
|
|
decisionMode: 'admin_only',
|
|
requireDefense: true,
|
|
defenseTimeLimit: 48,
|
|
voteTimeLimit: 72,
|
|
protestDeadlineHours: 72,
|
|
stewardingClosesHours: 168,
|
|
notifyAccusedOnProtest: true,
|
|
notifyOnVoteRequired: true,
|
|
},
|
|
};
|
|
}
|
|
|
|
getViewModel(): LeagueConfigFormViewModel | null {
|
|
if (!this.viewModel) {
|
|
throw new Error('Presenter has not been called yet');
|
|
}
|
|
return this.viewModel;
|
|
}
|
|
|
|
private mapDropPolicy(policy: DropScorePolicy | undefined): { strategy: string; n?: number } {
|
|
if (!policy || policy.strategy === 'none') {
|
|
return { strategy: 'none' };
|
|
}
|
|
|
|
if (policy.strategy === 'bestNResults') {
|
|
const n = typeof policy.count === 'number' ? policy.count : undefined;
|
|
return n !== undefined ? { strategy: 'bestNResults', n } : { strategy: 'none' };
|
|
}
|
|
|
|
if (policy.strategy === 'dropWorstN') {
|
|
const n = typeof policy.dropCount === 'number' ? policy.dropCount : undefined;
|
|
return n !== undefined ? { strategy: 'dropWorstN', n } : { strategy: 'none' };
|
|
}
|
|
|
|
return { strategy: 'none' };
|
|
}
|
|
} |