fix issues in core

This commit is contained in:
2025-12-23 15:38:50 +01:00
parent df5c20c5cc
commit 120d3bb1a1
125 changed files with 1005 additions and 793 deletions

View File

@@ -190,7 +190,7 @@ export class CreateSeasonForLeagueUseCase {
const season = Season.create({
id: seasonId,
leagueId: league.id,
leagueId: league.id.toString(),
gameId: command.gameId,
name: command.name,
year: new Date().getFullYear(),
@@ -235,31 +235,52 @@ export class CreateSeasonForLeagueUseCase {
maxDrivers?: number;
} {
const schedule = this.buildScheduleFromTimings(config);
const scoring = config.scoring ?? {};
const scoringConfig = new SeasonScoringConfig({
scoringPresetId: config.scoring.patternId ?? 'custom',
customScoringEnabled: config.scoring.customScoringEnabled ?? false,
scoringPresetId: scoring.patternId ?? 'custom',
customScoringEnabled: scoring.customScoringEnabled ?? false,
});
const dropPolicyInput = config.dropPolicy ?? {};
const dropStrategy = dropPolicyInput.strategy;
const dropPolicy = new SeasonDropPolicy({
strategy: config.dropPolicy.strategy,
...(config.dropPolicy.n !== undefined ? { n: config.dropPolicy.n } : {}),
strategy:
dropStrategy === 'none' ||
dropStrategy === 'bestNResults' ||
dropStrategy === 'dropWorstN'
? dropStrategy
: 'none',
...(dropPolicyInput.n !== undefined ? { n: dropPolicyInput.n } : {}),
});
const stewardingInput = config.stewarding ?? {};
const decisionMode = stewardingInput.decisionMode;
const stewardingConfig = new SeasonStewardingConfig({
decisionMode: config.stewarding.decisionMode,
...(config.stewarding.requiredVotes !== undefined
? { requiredVotes: config.stewarding.requiredVotes }
decisionMode:
decisionMode === 'admin_only' ||
decisionMode === 'steward_decides' ||
decisionMode === 'steward_vote' ||
decisionMode === 'member_vote' ||
decisionMode === 'steward_veto' ||
decisionMode === 'member_veto'
? decisionMode
: 'admin_only',
...(stewardingInput.requiredVotes !== undefined
? { requiredVotes: stewardingInput.requiredVotes }
: {}),
requireDefense: config.stewarding.requireDefense,
defenseTimeLimit: config.stewarding.defenseTimeLimit,
voteTimeLimit: config.stewarding.voteTimeLimit,
protestDeadlineHours: config.stewarding.protestDeadlineHours,
stewardingClosesHours: config.stewarding.stewardingClosesHours,
notifyAccusedOnProtest: config.stewarding.notifyAccusedOnProtest,
notifyOnVoteRequired: config.stewarding.notifyOnVoteRequired,
requireDefense: stewardingInput.requireDefense ?? false,
defenseTimeLimit: stewardingInput.defenseTimeLimit ?? 48,
voteTimeLimit: stewardingInput.voteTimeLimit ?? 72,
protestDeadlineHours: stewardingInput.protestDeadlineHours ?? 48,
stewardingClosesHours: stewardingInput.stewardingClosesHours ?? 168,
notifyAccusedOnProtest: stewardingInput.notifyAccusedOnProtest ?? true,
notifyOnVoteRequired: stewardingInput.notifyOnVoteRequired ?? true,
});
const structure = config.structure;
const maxDrivers =
typeof structure.maxDrivers === 'number' && structure.maxDrivers > 0
typeof structure?.maxDrivers === 'number' && structure.maxDrivers > 0
? structure.maxDrivers
: undefined;
@@ -275,44 +296,50 @@ export class CreateSeasonForLeagueUseCase {
private buildScheduleFromTimings(
config: LeagueConfigFormModel,
): SeasonSchedule | undefined {
const { timings } = config;
if (!timings.seasonStartDate || !timings.raceStartTime) {
const timings = config.timings;
if (!timings?.seasonStartDate || !timings.raceStartTime) {
return undefined;
}
const startDate = new Date(timings.seasonStartDate);
const timeOfDay = RaceTimeOfDay.fromString(timings.raceStartTime);
const timezoneId = timings.timezoneId ?? 'UTC';
const timezone = new LeagueTimezone(timezoneId);
const timezone = LeagueTimezone.create(timings.timezoneId ?? 'UTC');
const plannedRounds =
typeof timings.roundsPlanned === 'number' && timings.roundsPlanned > 0
? timings.roundsPlanned
: timings.sessionCount;
: timings.sessionCount ?? 0;
if (!Number.isInteger(plannedRounds) || plannedRounds <= 0) {
return undefined;
}
const weekdaysRaw = timings.weekdays ?? [];
const weekdays = WeekdaySet.fromArray(
weekdaysRaw
.filter((d): d is Weekday => (['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as const).includes(d as Weekday))
.slice(0),
);
const safeWeekdays = weekdays.getAll().length > 0 ? weekdays : WeekdaySet.fromArray(['Mon']);
const recurrence = (() => {
const weekdays: WeekdaySet =
timings.weekdays && timings.weekdays.length > 0
? WeekdaySet.fromArray(
timings.weekdays as unknown as Weekday[],
)
: WeekdaySet.fromArray(['Mon']);
switch (timings.recurrenceStrategy) {
case 'everyNWeeks':
return RecurrenceStrategyFactory.everyNWeeks(
timings.intervalWeeks ?? 2,
weekdays,
safeWeekdays,
);
case 'monthlyNthWeekday': {
const pattern = new MonthlyRecurrencePattern({
ordinal: (timings.monthlyOrdinal ?? 1) as 1 | 2 | 3 | 4,
weekday: (timings.monthlyWeekday ?? 'Mon') as Weekday,
});
const pattern = MonthlyRecurrencePattern.create(
(timings.monthlyOrdinal ?? 1) as 1 | 2 | 3 | 4,
(timings.monthlyWeekday ?? 'Mon') as Weekday,
);
return RecurrenceStrategyFactory.monthlyNthWeekday(pattern);
}
case 'weekly':
default:
return RecurrenceStrategyFactory.weekly(weekdays);
return RecurrenceStrategyFactory.weekly(safeWeekdays);
}
})();
@@ -350,7 +377,7 @@ export class ListSeasonsForLeagueUseCase {
});
}
const seasons = await this.seasonRepository.listByLeague(league.id);
const seasons = await this.seasonRepository.listByLeague(league.id.toString());
this.output.present({ seasons });
@@ -391,7 +418,7 @@ export class GetSeasonDetailsUseCase {
}
const season = await this.seasonRepository.findById(query.seasonId);
if (!season || season.leagueId !== league.id) {
if (!season || season.leagueId !== league.id.toString()) {
return Result.err({
code: 'SEASON_NOT_FOUND',
details: {
@@ -439,7 +466,7 @@ export class ManageSeasonLifecycleUseCase {
}
const season = await this.seasonRepository.findById(command.seasonId);
if (!season || season.leagueId !== league.id) {
if (!season || season.leagueId !== league.id.toString()) {
return Result.err({
code: 'SEASON_NOT_FOUND',
details: {