wip
This commit is contained in:
131
packages/racing/domain/value-objects/SeasonStewardingConfig.ts
Normal file
131
packages/racing/domain/value-objects/SeasonStewardingConfig.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { RacingDomainValidationError } from '../errors/RacingDomainError';
|
||||
import type { IValueObject } from '@gridpilot/shared/domain';
|
||||
import type { StewardingDecisionMode } from '../entities/League';
|
||||
|
||||
export interface SeasonStewardingConfigProps {
|
||||
decisionMode: StewardingDecisionMode;
|
||||
requiredVotes?: number;
|
||||
requireDefense: boolean;
|
||||
defenseTimeLimit: number;
|
||||
voteTimeLimit: number;
|
||||
protestDeadlineHours: number;
|
||||
stewardingClosesHours: number;
|
||||
notifyAccusedOnProtest: boolean;
|
||||
notifyOnVoteRequired: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value Object: SeasonStewardingConfig
|
||||
*
|
||||
* Encapsulates stewarding configuration owned by a Season.
|
||||
* Shape intentionally mirrors LeagueStewardingFormDTO used by the wizard.
|
||||
*/
|
||||
export class SeasonStewardingConfig
|
||||
implements IValueObject<SeasonStewardingConfigProps>
|
||||
{
|
||||
readonly decisionMode: StewardingDecisionMode;
|
||||
readonly requiredVotes?: number;
|
||||
readonly requireDefense: boolean;
|
||||
readonly defenseTimeLimit: number;
|
||||
readonly voteTimeLimit: number;
|
||||
readonly protestDeadlineHours: number;
|
||||
readonly stewardingClosesHours: number;
|
||||
readonly notifyAccusedOnProtest: boolean;
|
||||
readonly notifyOnVoteRequired: boolean;
|
||||
|
||||
constructor(props: SeasonStewardingConfigProps) {
|
||||
if (!props.decisionMode) {
|
||||
throw new RacingDomainValidationError(
|
||||
'SeasonStewardingConfig.decisionMode is required',
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
(props.decisionMode === 'steward_vote' ||
|
||||
props.decisionMode === 'member_vote' ||
|
||||
props.decisionMode === 'steward_veto' ||
|
||||
props.decisionMode === 'member_veto') &&
|
||||
(props.requiredVotes === undefined ||
|
||||
!Number.isInteger(props.requiredVotes) ||
|
||||
props.requiredVotes <= 0)
|
||||
) {
|
||||
throw new RacingDomainValidationError(
|
||||
'SeasonStewardingConfig.requiredVotes must be a positive integer for voting/veto modes',
|
||||
);
|
||||
}
|
||||
|
||||
if (!Number.isInteger(props.defenseTimeLimit) || props.defenseTimeLimit < 0) {
|
||||
throw new RacingDomainValidationError(
|
||||
'SeasonStewardingConfig.defenseTimeLimit must be a non-negative integer (hours)',
|
||||
);
|
||||
}
|
||||
|
||||
if (!Number.isInteger(props.voteTimeLimit) || props.voteTimeLimit <= 0) {
|
||||
throw new RacingDomainValidationError(
|
||||
'SeasonStewardingConfig.voteTimeLimit must be a positive integer (hours)',
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!Number.isInteger(props.protestDeadlineHours) ||
|
||||
props.protestDeadlineHours <= 0
|
||||
) {
|
||||
throw new RacingDomainValidationError(
|
||||
'SeasonStewardingConfig.protestDeadlineHours must be a positive integer (hours)',
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!Number.isInteger(props.stewardingClosesHours) ||
|
||||
props.stewardingClosesHours <= 0
|
||||
) {
|
||||
throw new RacingDomainValidationError(
|
||||
'SeasonStewardingConfig.stewardingClosesHours must be a positive integer (hours)',
|
||||
);
|
||||
}
|
||||
|
||||
this.decisionMode = props.decisionMode;
|
||||
if (props.requiredVotes !== undefined) {
|
||||
this.requiredVotes = props.requiredVotes;
|
||||
}
|
||||
this.requireDefense = props.requireDefense;
|
||||
this.defenseTimeLimit = props.defenseTimeLimit;
|
||||
this.voteTimeLimit = props.voteTimeLimit;
|
||||
this.protestDeadlineHours = props.protestDeadlineHours;
|
||||
this.stewardingClosesHours = props.stewardingClosesHours;
|
||||
this.notifyAccusedOnProtest = props.notifyAccusedOnProtest;
|
||||
this.notifyOnVoteRequired = props.notifyOnVoteRequired;
|
||||
}
|
||||
|
||||
get props(): SeasonStewardingConfigProps {
|
||||
return {
|
||||
decisionMode: this.decisionMode,
|
||||
...(this.requiredVotes !== undefined
|
||||
? { requiredVotes: this.requiredVotes }
|
||||
: {}),
|
||||
requireDefense: this.requireDefense,
|
||||
defenseTimeLimit: this.defenseTimeLimit,
|
||||
voteTimeLimit: this.voteTimeLimit,
|
||||
protestDeadlineHours: this.protestDeadlineHours,
|
||||
stewardingClosesHours: this.stewardingClosesHours,
|
||||
notifyAccusedOnProtest: this.notifyAccusedOnProtest,
|
||||
notifyOnVoteRequired: this.notifyOnVoteRequired,
|
||||
};
|
||||
}
|
||||
|
||||
equals(other: IValueObject<SeasonStewardingConfigProps>): boolean {
|
||||
const a = this.props;
|
||||
const b = other.props;
|
||||
return (
|
||||
a.decisionMode === b.decisionMode &&
|
||||
a.requiredVotes === b.requiredVotes &&
|
||||
a.requireDefense === b.requireDefense &&
|
||||
a.defenseTimeLimit === b.defenseTimeLimit &&
|
||||
a.voteTimeLimit === b.voteTimeLimit &&
|
||||
a.protestDeadlineHours === b.protestDeadlineHours &&
|
||||
a.stewardingClosesHours === b.stewardingClosesHours &&
|
||||
a.notifyAccusedOnProtest === b.notifyAccusedOnProtest &&
|
||||
a.notifyOnVoteRequired === b.notifyOnVoteRequired
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user