wip
This commit is contained in:
41
packages/racing/domain/entities/ChampionshipStanding.ts
Normal file
41
packages/racing/domain/entities/ChampionshipStanding.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { ParticipantRef } from '../value-objects/ParticipantRef';
|
||||
|
||||
export class ChampionshipStanding {
|
||||
readonly seasonId: string;
|
||||
readonly championshipId: string;
|
||||
readonly participant: ParticipantRef;
|
||||
readonly totalPoints: number;
|
||||
readonly resultsCounted: number;
|
||||
readonly resultsDropped: number;
|
||||
readonly position: number;
|
||||
|
||||
constructor(props: {
|
||||
seasonId: string;
|
||||
championshipId: string;
|
||||
participant: ParticipantRef;
|
||||
totalPoints: number;
|
||||
resultsCounted: number;
|
||||
resultsDropped: number;
|
||||
position: number;
|
||||
}) {
|
||||
this.seasonId = props.seasonId;
|
||||
this.championshipId = props.championshipId;
|
||||
this.participant = props.participant;
|
||||
this.totalPoints = props.totalPoints;
|
||||
this.resultsCounted = props.resultsCounted;
|
||||
this.resultsDropped = props.resultsDropped;
|
||||
this.position = props.position;
|
||||
}
|
||||
|
||||
withPosition(position: number): ChampionshipStanding {
|
||||
return new ChampionshipStanding({
|
||||
seasonId: this.seasonId,
|
||||
championshipId: this.championshipId,
|
||||
participant: this.participant,
|
||||
totalPoints: this.totalPoints,
|
||||
resultsCounted: this.resultsCounted,
|
||||
resultsDropped: this.resultsDropped,
|
||||
position,
|
||||
});
|
||||
}
|
||||
}
|
||||
24
packages/racing/domain/entities/Game.ts
Normal file
24
packages/racing/domain/entities/Game.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
export class Game {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
|
||||
private constructor(props: { id: string; name: string }) {
|
||||
this.id = props.id;
|
||||
this.name = props.name;
|
||||
}
|
||||
|
||||
static create(props: { id: string; name: string }): Game {
|
||||
if (!props.id || props.id.trim().length === 0) {
|
||||
throw new Error('Game ID is required');
|
||||
}
|
||||
|
||||
if (!props.name || props.name.trim().length === 0) {
|
||||
throw new Error('Game name is required');
|
||||
}
|
||||
|
||||
return new Game({
|
||||
id: props.id,
|
||||
name: props.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,17 @@ export interface LeagueSettings {
|
||||
sessionDuration?: number;
|
||||
qualifyingFormat?: 'single-lap' | 'open';
|
||||
customPoints?: Record<number, number>;
|
||||
/**
|
||||
* Maximum number of drivers allowed in the league.
|
||||
* Used for simple capacity display on the website.
|
||||
*/
|
||||
maxDrivers?: number;
|
||||
}
|
||||
|
||||
export interface LeagueSocialLinks {
|
||||
discordUrl?: string;
|
||||
youtubeUrl?: string;
|
||||
websiteUrl?: string;
|
||||
}
|
||||
|
||||
export class League {
|
||||
@@ -19,6 +30,7 @@ export class League {
|
||||
readonly ownerId: string;
|
||||
readonly settings: LeagueSettings;
|
||||
readonly createdAt: Date;
|
||||
readonly socialLinks?: LeagueSocialLinks;
|
||||
|
||||
private constructor(props: {
|
||||
id: string;
|
||||
@@ -27,6 +39,7 @@ export class League {
|
||||
ownerId: string;
|
||||
settings: LeagueSettings;
|
||||
createdAt: Date;
|
||||
socialLinks?: LeagueSocialLinks;
|
||||
}) {
|
||||
this.id = props.id;
|
||||
this.name = props.name;
|
||||
@@ -34,6 +47,7 @@ export class League {
|
||||
this.ownerId = props.ownerId;
|
||||
this.settings = props.settings;
|
||||
this.createdAt = props.createdAt;
|
||||
this.socialLinks = props.socialLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,6 +60,7 @@ export class League {
|
||||
ownerId: string;
|
||||
settings?: Partial<LeagueSettings>;
|
||||
createdAt?: Date;
|
||||
socialLinks?: LeagueSocialLinks;
|
||||
}): League {
|
||||
this.validate(props);
|
||||
|
||||
@@ -53,6 +68,7 @@ export class League {
|
||||
pointsSystem: 'f1-2024',
|
||||
sessionDuration: 60,
|
||||
qualifyingFormat: 'open',
|
||||
maxDrivers: 32,
|
||||
};
|
||||
|
||||
return new League({
|
||||
@@ -62,6 +78,7 @@ export class League {
|
||||
ownerId: props.ownerId,
|
||||
settings: { ...defaultSettings, ...props.settings },
|
||||
createdAt: props.createdAt ?? new Date(),
|
||||
socialLinks: props.socialLinks,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -102,6 +119,7 @@ export class League {
|
||||
name: string;
|
||||
description: string;
|
||||
settings: LeagueSettings;
|
||||
socialLinks: LeagueSocialLinks | undefined;
|
||||
}>): League {
|
||||
return new League({
|
||||
id: this.id,
|
||||
@@ -110,6 +128,7 @@ export class League {
|
||||
ownerId: this.ownerId,
|
||||
settings: props.settings ?? this.settings,
|
||||
createdAt: this.createdAt,
|
||||
socialLinks: props.socialLinks ?? this.socialLinks,
|
||||
});
|
||||
}
|
||||
}
|
||||
7
packages/racing/domain/entities/LeagueScoringConfig.ts
Normal file
7
packages/racing/domain/entities/LeagueScoringConfig.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { ChampionshipConfig } from '../value-objects/ChampionshipConfig';
|
||||
|
||||
export interface LeagueScoringConfig {
|
||||
id: string;
|
||||
seasonId: string;
|
||||
championships: ChampionshipConfig[];
|
||||
}
|
||||
29
packages/racing/domain/entities/Penalty.ts
Normal file
29
packages/racing/domain/entities/Penalty.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Domain Entity: Penalty
|
||||
*
|
||||
* Represents a season-long penalty or bonus applied to a driver
|
||||
* within a specific league. This is intentionally simple for the
|
||||
* alpha demo and models points adjustments only.
|
||||
*/
|
||||
export type PenaltyType = 'points-deduction' | 'points-bonus';
|
||||
|
||||
export interface Penalty {
|
||||
id: string;
|
||||
leagueId: string;
|
||||
driverId: string;
|
||||
type: PenaltyType;
|
||||
/**
|
||||
* Signed integer representing points adjustment:
|
||||
* - negative for deductions
|
||||
* - positive for bonuses
|
||||
*/
|
||||
pointsDelta: number;
|
||||
/**
|
||||
* Optional short reason/label (e.g. "Incident penalty", "Fastest laps bonus").
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* When this penalty was applied.
|
||||
*/
|
||||
appliedAt: Date;
|
||||
}
|
||||
77
packages/racing/domain/entities/Season.ts
Normal file
77
packages/racing/domain/entities/Season.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
export type SeasonStatus = 'planned' | 'active' | 'completed';
|
||||
|
||||
export class Season {
|
||||
readonly id: string;
|
||||
readonly leagueId: string;
|
||||
readonly gameId: string;
|
||||
readonly name: string;
|
||||
readonly year?: number;
|
||||
readonly order?: number;
|
||||
readonly status: SeasonStatus;
|
||||
readonly startDate?: Date;
|
||||
readonly endDate?: Date;
|
||||
|
||||
private constructor(props: {
|
||||
id: string;
|
||||
leagueId: string;
|
||||
gameId: string;
|
||||
name: string;
|
||||
year?: number;
|
||||
order?: number;
|
||||
status: SeasonStatus;
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
}) {
|
||||
this.id = props.id;
|
||||
this.leagueId = props.leagueId;
|
||||
this.gameId = props.gameId;
|
||||
this.name = props.name;
|
||||
this.year = props.year;
|
||||
this.order = props.order;
|
||||
this.status = props.status;
|
||||
this.startDate = props.startDate;
|
||||
this.endDate = props.endDate;
|
||||
}
|
||||
|
||||
static create(props: {
|
||||
id: string;
|
||||
leagueId: string;
|
||||
gameId: string;
|
||||
name: string;
|
||||
year?: number;
|
||||
order?: number;
|
||||
status?: SeasonStatus;
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
}): Season {
|
||||
if (!props.id || props.id.trim().length === 0) {
|
||||
throw new Error('Season ID is required');
|
||||
}
|
||||
|
||||
if (!props.leagueId || props.leagueId.trim().length === 0) {
|
||||
throw new Error('Season leagueId is required');
|
||||
}
|
||||
|
||||
if (!props.gameId || props.gameId.trim().length === 0) {
|
||||
throw new Error('Season gameId is required');
|
||||
}
|
||||
|
||||
if (!props.name || props.name.trim().length === 0) {
|
||||
throw new Error('Season name is required');
|
||||
}
|
||||
|
||||
const status: SeasonStatus = props.status ?? 'planned';
|
||||
|
||||
return new Season({
|
||||
id: props.id,
|
||||
leagueId: props.leagueId,
|
||||
gameId: props.gameId,
|
||||
name: props.name,
|
||||
year: props.year,
|
||||
order: props.order,
|
||||
status,
|
||||
startDate: props.startDate,
|
||||
endDate: props.endDate,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user