This commit is contained in:
2025-12-05 12:24:38 +01:00
parent fb509607c1
commit 5a9cd28d5b
47 changed files with 5456 additions and 228 deletions

View File

@@ -10,6 +10,8 @@ import { League } from '@gridpilot/racing/domain/entities/League';
import { Race } from '@gridpilot/racing/domain/entities/Race';
import { Result } from '@gridpilot/racing/domain/entities/Result';
import { Standing } from '@gridpilot/racing/domain/entities/Standing';
import { Game } from '@gridpilot/racing/domain/entities/Game';
import { Season } from '@gridpilot/racing/domain/entities/Season';
import type { IDriverRepository } from '@gridpilot/racing/domain/repositories/IDriverRepository';
import type { ILeagueRepository } from '@gridpilot/racing/domain/repositories/ILeagueRepository';
@@ -17,6 +19,9 @@ import type { IRaceRepository } from '@gridpilot/racing/domain/repositories/IRac
import type { IResultRepository } from '@gridpilot/racing/domain/repositories/IResultRepository';
import type { IStandingRepository } from '@gridpilot/racing/domain/repositories/IStandingRepository';
import type { IPenaltyRepository } from '@gridpilot/racing/domain/repositories/IPenaltyRepository';
import type { IGameRepository } from '@gridpilot/racing/domain/repositories/IGameRepository';
import type { ISeasonRepository } from '@gridpilot/racing/domain/repositories/ISeasonRepository';
import type { ILeagueScoringConfigRepository } from '@gridpilot/racing/domain/repositories/ILeagueScoringConfigRepository';
import type {
ITeamRepository,
ITeamMembershipRepository,
@@ -34,6 +39,13 @@ import { InMemoryRaceRepository } from '@gridpilot/racing/infrastructure/reposit
import { InMemoryResultRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryResultRepository';
import { InMemoryStandingRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryStandingRepository';
import { InMemoryPenaltyRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryPenaltyRepository';
import {
InMemoryGameRepository,
InMemorySeasonRepository,
InMemoryLeagueScoringConfigRepository,
getLeagueScoringPresetById,
} from '@gridpilot/racing/infrastructure/repositories/InMemoryScoringRepositories';
import { InMemoryLeagueScoringPresetProvider } from '@gridpilot/racing/infrastructure/repositories/InMemoryLeagueScoringPresetProvider';
import { InMemoryTeamRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryTeamRepository';
import { InMemoryTeamMembershipRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryTeamMembershipRepository';
import { InMemoryRaceRegistrationRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryRaceRegistrationRepository';
@@ -58,13 +70,28 @@ import {
GetLeagueStandingsQuery,
GetLeagueDriverSeasonStatsQuery,
GetAllLeaguesWithCapacityQuery,
GetAllLeaguesWithCapacityAndScoringQuery,
ListLeagueScoringPresetsQuery,
GetLeagueScoringConfigQuery,
CreateLeagueWithSeasonAndScoringUseCase,
GetLeagueFullConfigQuery,
} from '@gridpilot/racing/application';
import { createStaticRacingSeed, type RacingSeedData } from '@gridpilot/testing-support';
import {
createStaticRacingSeed,
type RacingSeedData,
getDemoLeagueArchetypeByName,
} from '@gridpilot/testing-support';
import type {
LeagueScheduleDTO,
LeagueSchedulePreviewDTO,
} from '@gridpilot/racing/application';
import { PreviewLeagueScheduleQuery } from '@gridpilot/racing/application';
import {
InMemoryFeedRepository,
InMemorySocialGraphRepository,
} from '@gridpilot/social/infrastructure/inmemory/InMemorySocialAndFeed';
import { DemoImageServiceAdapter } from '@gridpilot/demo-infrastructure';
import type { LeagueScoringPresetProvider } from '@gridpilot/racing/application/ports/LeagueScoringPresetProvider';
/**
* Seed data for development
@@ -138,6 +165,10 @@ class DIContainer {
private _teamMembershipRepository: ITeamMembershipRepository;
private _raceRegistrationRepository: IRaceRegistrationRepository;
private _leagueMembershipRepository: ILeagueMembershipRepository;
private _gameRepository: IGameRepository;
private _seasonRepository: ISeasonRepository;
private _leagueScoringConfigRepository: ILeagueScoringConfigRepository;
private _leagueScoringPresetProvider: LeagueScoringPresetProvider;
private _feedRepository: IFeedRepository;
private _socialRepository: ISocialGraphRepository;
private _imageService: ImageServicePort;
@@ -151,6 +182,13 @@ class DIContainer {
private _getLeagueStandingsQuery: GetLeagueStandingsQuery;
private _getLeagueDriverSeasonStatsQuery: GetLeagueDriverSeasonStatsQuery;
private _getAllLeaguesWithCapacityQuery: GetAllLeaguesWithCapacityQuery;
private _getAllLeaguesWithCapacityAndScoringQuery: GetAllLeaguesWithCapacityAndScoringQuery;
private _listLeagueScoringPresetsQuery: ListLeagueScoringPresetsQuery;
private _getLeagueScoringConfigQuery: GetLeagueScoringConfigQuery;
private _createLeagueWithSeasonAndScoringUseCase: CreateLeagueWithSeasonAndScoringUseCase;
private _getLeagueFullConfigQuery: GetLeagueFullConfigQuery;
// Placeholder for future schedule preview wiring
private _previewLeagueScheduleQuery: PreviewLeagueScheduleQuery;
private _createTeamUseCase: CreateTeamUseCase;
private _joinTeamUseCase: JoinTeamUseCase;
@@ -190,10 +228,51 @@ class DIContainer {
// Race registrations (start empty; populated via use-cases)
this._raceRegistrationRepository = new InMemoryRaceRegistrationRepository();
// Penalties (seeded in-memory adapter)
this._penaltyRepository = new InMemoryPenaltyRepository();
// Scoring preset provider and seeded game/season/scoring config repositories
this._leagueScoringPresetProvider = new InMemoryLeagueScoringPresetProvider();
const game = Game.create({ id: 'iracing', name: 'iRacing' });
const seededSeasons: Season[] = [];
const seededScoringConfigs = [];
for (const league of seedData.leagues) {
const archetype = getDemoLeagueArchetypeByName(league.name);
if (!archetype) continue;
const season = Season.create({
id: `season-${league.id}-demo`,
leagueId: league.id,
gameId: game.id,
name: `${league.name} Demo Season`,
year: new Date().getFullYear(),
order: 1,
status: 'active',
startDate: new Date(),
endDate: new Date(),
});
seededSeasons.push(season);
const infraPreset = getLeagueScoringPresetById(
archetype.scoringPresetId,
);
if (!infraPreset) {
// If a preset is missing, skip scoring config for this league in alpha seed.
continue;
}
const config = infraPreset.createConfig({ seasonId: season.id });
seededScoringConfigs.push(config);
}
this._gameRepository = new InMemoryGameRepository([game]);
this._seasonRepository = new InMemorySeasonRepository(seededSeasons);
this._leagueScoringConfigRepository =
new InMemoryLeagueScoringConfigRepository(seededScoringConfigs);
// League memberships seeded from static memberships with guaranteed owner roles
const seededMemberships: LeagueMembership[] = seedData.memberships.map((m) => ({
leagueId: m.leagueId,
@@ -371,6 +450,46 @@ class DIContainer {
this._leagueMembershipRepository,
);
this._getAllLeaguesWithCapacityAndScoringQuery =
new GetAllLeaguesWithCapacityAndScoringQuery(
this._leagueRepository,
this._leagueMembershipRepository,
this._seasonRepository,
this._leagueScoringConfigRepository,
this._gameRepository,
this._leagueScoringPresetProvider,
);
this._listLeagueScoringPresetsQuery = new ListLeagueScoringPresetsQuery(
this._leagueScoringPresetProvider,
);
this._getLeagueScoringConfigQuery = new GetLeagueScoringConfigQuery(
this._leagueRepository,
this._seasonRepository,
this._leagueScoringConfigRepository,
this._gameRepository,
this._leagueScoringPresetProvider,
);
this._getLeagueFullConfigQuery = new GetLeagueFullConfigQuery(
this._leagueRepository,
this._seasonRepository,
this._leagueScoringConfigRepository,
this._gameRepository,
);
this._createLeagueWithSeasonAndScoringUseCase =
new CreateLeagueWithSeasonAndScoringUseCase(
this._leagueRepository,
this._seasonRepository,
this._leagueScoringConfigRepository,
this._leagueScoringPresetProvider,
);
// Schedule preview query (used by league creation wizard step 3)
this._previewLeagueScheduleQuery = new PreviewLeagueScheduleQuery();
this._createTeamUseCase = new CreateTeamUseCase(
this._teamRepository,
this._teamMembershipRepository,
@@ -464,6 +583,22 @@ class DIContainer {
return this._leagueMembershipRepository;
}
get gameRepository(): IGameRepository {
return this._gameRepository;
}
get seasonRepository(): ISeasonRepository {
return this._seasonRepository;
}
get leagueScoringConfigRepository(): ILeagueScoringConfigRepository {
return this._leagueScoringConfigRepository;
}
get leagueScoringPresetProvider(): LeagueScoringPresetProvider {
return this._leagueScoringPresetProvider;
}
get joinLeagueUseCase(): JoinLeagueUseCase {
return this._joinLeagueUseCase;
}
@@ -496,6 +631,31 @@ class DIContainer {
return this._getAllLeaguesWithCapacityQuery;
}
get getAllLeaguesWithCapacityAndScoringQuery(): GetAllLeaguesWithCapacityAndScoringQuery {
return this._getAllLeaguesWithCapacityAndScoringQuery;
}
get listLeagueScoringPresetsQuery(): ListLeagueScoringPresetsQuery {
return this._listLeagueScoringPresetsQuery;
}
get getLeagueScoringConfigQuery(): GetLeagueScoringConfigQuery {
return this._getLeagueScoringConfigQuery;
}
get getLeagueFullConfigQuery(): GetLeagueFullConfigQuery {
return this._getLeagueFullConfigQuery;
}
// Placeholder accessor for schedule preview; API route/UI can call this later.
get previewLeagueScheduleQuery(): PreviewLeagueScheduleQuery {
return this._previewLeagueScheduleQuery;
}
get createLeagueWithSeasonAndScoringUseCase(): CreateLeagueWithSeasonAndScoringUseCase {
return this._createLeagueWithSeasonAndScoringUseCase;
}
get createTeamUseCase(): CreateTeamUseCase {
return this._createTeamUseCase;
}
@@ -628,6 +788,31 @@ export function getGetAllLeaguesWithCapacityQuery(): GetAllLeaguesWithCapacityQu
return DIContainer.getInstance().getAllLeaguesWithCapacityQuery;
}
export function getGetAllLeaguesWithCapacityAndScoringQuery(): GetAllLeaguesWithCapacityAndScoringQuery {
return DIContainer.getInstance().getAllLeaguesWithCapacityAndScoringQuery;
}
export function getGetLeagueScoringConfigQuery(): GetLeagueScoringConfigQuery {
return DIContainer.getInstance().getLeagueScoringConfigQuery;
}
export function getGetLeagueFullConfigQuery(): GetLeagueFullConfigQuery {
return DIContainer.getInstance().getLeagueFullConfigQuery;
}
// Placeholder export for future schedule preview API wiring.
export function getPreviewLeagueScheduleQuery(): PreviewLeagueScheduleQuery {
return DIContainer.getInstance().previewLeagueScheduleQuery;
}
export function getListLeagueScoringPresetsQuery(): ListLeagueScoringPresetsQuery {
return DIContainer.getInstance().listLeagueScoringPresetsQuery;
}
export function getCreateLeagueWithSeasonAndScoringUseCase(): CreateLeagueWithSeasonAndScoringUseCase {
return DIContainer.getInstance().createLeagueWithSeasonAndScoringUseCase;
}
export function getTeamRepository(): ITeamRepository {
return DIContainer.getInstance().teamRepository;
}