Files
gridpilot.gg/core/racing/domain/value-objects/RecurrenceStrategy.ts
2025-12-17 01:23:09 +01:00

85 lines
2.7 KiB
TypeScript

import type { IValueObject } from '@core/shared/domain';
import { WeekdaySet } from './WeekdaySet';
import { MonthlyRecurrencePattern } from './MonthlyRecurrencePattern';
import { RacingDomainValidationError } from '../errors/RacingDomainError';
export type WeeklyRecurrenceStrategyProps = {
kind: 'weekly';
weekdays: WeekdaySet;
};
export type EveryNWeeksRecurrenceStrategyProps = {
kind: 'everyNWeeks';
weekdays: WeekdaySet;
intervalWeeks: number;
};
export type MonthlyNthWeekdayRecurrenceStrategyProps = {
kind: 'monthlyNthWeekday';
monthlyPattern: MonthlyRecurrencePattern;
};
export type RecurrenceStrategyProps =
| WeeklyRecurrenceStrategyProps
| EveryNWeeksRecurrenceStrategyProps
| MonthlyNthWeekdayRecurrenceStrategyProps;
export class RecurrenceStrategy implements IValueObject<RecurrenceStrategyProps> {
private constructor(private readonly strategy: RecurrenceStrategyProps) {}
get props(): RecurrenceStrategyProps {
return this.strategy;
}
static weekly(weekdays: WeekdaySet): RecurrenceStrategy {
if (weekdays.getAll().length === 0) {
throw new RacingDomainValidationError('weekdays are required for weekly recurrence');
}
return new RecurrenceStrategy({
kind: 'weekly',
weekdays,
});
}
static everyNWeeks(intervalWeeks: number, weekdays: WeekdaySet): RecurrenceStrategy {
if (!Number.isInteger(intervalWeeks) || intervalWeeks <= 0) {
throw new RacingDomainValidationError('intervalWeeks must be a positive integer');
}
if (weekdays.getAll().length === 0) {
throw new RacingDomainValidationError('weekdays are required for everyNWeeks recurrence');
}
return new RecurrenceStrategy({
kind: 'everyNWeeks',
weekdays,
intervalWeeks,
});
}
static monthlyNthWeekday(pattern: MonthlyRecurrencePattern): RecurrenceStrategy {
return new RecurrenceStrategy({
kind: 'monthlyNthWeekday',
monthlyPattern: pattern,
});
}
equals(other: IValueObject<RecurrenceStrategyProps>): boolean {
const otherProps = other.props;
if (this.strategy.kind !== otherProps.kind) {
return false;
}
switch (this.strategy.kind) {
case 'weekly':
return this.strategy.weekdays.equals((otherProps as WeeklyRecurrenceStrategyProps).weekdays);
case 'everyNWeeks':
const everyN = otherProps as EveryNWeeksRecurrenceStrategyProps;
return this.strategy.intervalWeeks === everyN.intervalWeeks && this.strategy.weekdays.equals(everyN.weekdays);
case 'monthlyNthWeekday':
const monthly = otherProps as MonthlyNthWeekdayRecurrenceStrategyProps;
return this.strategy.monthlyPattern.equals(monthly.monthlyPattern);
default:
return false;
}
}
}