735 lines
24 KiB
TypeScript
735 lines
24 KiB
TypeScript
/**
|
|
* Dependency Injection Container
|
|
*
|
|
* Initializes all in-memory repositories and provides accessor functions.
|
|
* Allows easy swapping to persistent repositories later.
|
|
*/
|
|
|
|
import { Driver } from '@gridpilot/racing/domain/entities/Driver';
|
|
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 type { IDriverRepository } from '@gridpilot/racing/domain/repositories/IDriverRepository';
|
|
import type { ILeagueRepository } from '@gridpilot/racing/domain/repositories/ILeagueRepository';
|
|
import type { IRaceRepository } from '@gridpilot/racing/domain/repositories/IRaceRepository';
|
|
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 {
|
|
ITeamRepository,
|
|
ITeamMembershipRepository,
|
|
IRaceRegistrationRepository,
|
|
} from '@gridpilot/racing';
|
|
import type { ILeagueMembershipRepository } from '@gridpilot/racing/domain/repositories/ILeagueMembershipRepository';
|
|
import type { LeagueMembership, JoinRequest } from '@gridpilot/racing/domain/entities/LeagueMembership';
|
|
import type { IFeedRepository } from '@gridpilot/social/domain/repositories/IFeedRepository';
|
|
import type { ISocialGraphRepository } from '@gridpilot/social/domain/repositories/ISocialGraphRepository';
|
|
import type { ImageServicePort } from '@gridpilot/media';
|
|
|
|
import { InMemoryDriverRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryDriverRepository';
|
|
import { InMemoryLeagueRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryLeagueRepository';
|
|
import { InMemoryRaceRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryRaceRepository';
|
|
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 { InMemoryTeamRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryTeamRepository';
|
|
import { InMemoryTeamMembershipRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryTeamMembershipRepository';
|
|
import { InMemoryRaceRegistrationRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryRaceRegistrationRepository';
|
|
import { InMemoryLeagueMembershipRepository } from '@gridpilot/racing/infrastructure/repositories/InMemoryLeagueMembershipRepository';
|
|
import {
|
|
JoinLeagueUseCase,
|
|
RegisterForRaceUseCase,
|
|
WithdrawFromRaceUseCase,
|
|
IsDriverRegisteredForRaceQuery,
|
|
GetRaceRegistrationsQuery,
|
|
CreateTeamUseCase,
|
|
JoinTeamUseCase,
|
|
LeaveTeamUseCase,
|
|
ApproveTeamJoinRequestUseCase,
|
|
RejectTeamJoinRequestUseCase,
|
|
UpdateTeamUseCase,
|
|
GetAllTeamsQuery,
|
|
GetTeamDetailsQuery,
|
|
GetTeamMembersQuery,
|
|
GetTeamJoinRequestsQuery,
|
|
GetDriverTeamQuery,
|
|
GetLeagueStandingsQuery,
|
|
GetLeagueDriverSeasonStatsQuery,
|
|
GetAllLeaguesWithCapacityQuery,
|
|
} from '@gridpilot/racing/application';
|
|
import { createStaticRacingSeed, type RacingSeedData } from '@gridpilot/testing-support';
|
|
import {
|
|
InMemoryFeedRepository,
|
|
InMemorySocialGraphRepository,
|
|
} from '@gridpilot/social/infrastructure/inmemory/InMemorySocialAndFeed';
|
|
import { DemoImageServiceAdapter } from '@gridpilot/demo-infrastructure';
|
|
|
|
/**
|
|
* Seed data for development
|
|
*/
|
|
/**
|
|
* Driver statistics and ranking data
|
|
*/
|
|
export interface DriverStats {
|
|
driverId: string;
|
|
rating: number;
|
|
totalRaces: number;
|
|
wins: number;
|
|
podiums: number;
|
|
dnfs: number;
|
|
avgFinish: number;
|
|
bestFinish: number;
|
|
worstFinish: number;
|
|
consistency: number;
|
|
overallRank: number;
|
|
percentile: number;
|
|
}
|
|
|
|
/**
|
|
* Mock driver stats with calculated rankings
|
|
*/
|
|
const driverStats: Record<string, DriverStats> = {};
|
|
|
|
function createSeedData(): RacingSeedData {
|
|
const seed = createStaticRacingSeed(42);
|
|
const { drivers } = seed;
|
|
|
|
drivers.forEach((driver, index) => {
|
|
const totalRaces = 40 + index * 5;
|
|
const wins = Math.max(0, Math.floor(totalRaces * 0.2) - index);
|
|
const podiums = Math.max(wins * 2, 0);
|
|
const dnfs = Math.max(0, Math.floor(index / 2));
|
|
const rating = 1500 + index * 25;
|
|
|
|
driverStats[driver.id] = {
|
|
driverId: driver.id,
|
|
rating,
|
|
totalRaces,
|
|
wins,
|
|
podiums,
|
|
dnfs,
|
|
avgFinish: 4,
|
|
bestFinish: 1,
|
|
worstFinish: 20,
|
|
consistency: 80,
|
|
overallRank: index + 1,
|
|
percentile: Math.max(0, 100 - index),
|
|
};
|
|
});
|
|
|
|
return seed;
|
|
}
|
|
|
|
/**
|
|
* DI Container class
|
|
*/
|
|
class DIContainer {
|
|
private static instance: DIContainer;
|
|
|
|
private _driverRepository: IDriverRepository;
|
|
private _leagueRepository: ILeagueRepository;
|
|
private _raceRepository: IRaceRepository;
|
|
private _resultRepository: IResultRepository;
|
|
private _standingRepository: IStandingRepository;
|
|
private _penaltyRepository: IPenaltyRepository;
|
|
private _teamRepository: ITeamRepository;
|
|
private _teamMembershipRepository: ITeamMembershipRepository;
|
|
private _raceRegistrationRepository: IRaceRegistrationRepository;
|
|
private _leagueMembershipRepository: ILeagueMembershipRepository;
|
|
private _feedRepository: IFeedRepository;
|
|
private _socialRepository: ISocialGraphRepository;
|
|
private _imageService: ImageServicePort;
|
|
|
|
// Racing application use-cases / queries
|
|
private _joinLeagueUseCase: JoinLeagueUseCase;
|
|
private _registerForRaceUseCase: RegisterForRaceUseCase;
|
|
private _withdrawFromRaceUseCase: WithdrawFromRaceUseCase;
|
|
private _isDriverRegisteredForRaceQuery: IsDriverRegisteredForRaceQuery;
|
|
private _getRaceRegistrationsQuery: GetRaceRegistrationsQuery;
|
|
private _getLeagueStandingsQuery: GetLeagueStandingsQuery;
|
|
private _getLeagueDriverSeasonStatsQuery: GetLeagueDriverSeasonStatsQuery;
|
|
private _getAllLeaguesWithCapacityQuery: GetAllLeaguesWithCapacityQuery;
|
|
|
|
private _createTeamUseCase: CreateTeamUseCase;
|
|
private _joinTeamUseCase: JoinTeamUseCase;
|
|
private _leaveTeamUseCase: LeaveTeamUseCase;
|
|
private _approveTeamJoinRequestUseCase: ApproveTeamJoinRequestUseCase;
|
|
private _rejectTeamJoinRequestUseCase: RejectTeamJoinRequestUseCase;
|
|
private _updateTeamUseCase: UpdateTeamUseCase;
|
|
private _getAllTeamsQuery: GetAllTeamsQuery;
|
|
private _getTeamDetailsQuery: GetTeamDetailsQuery;
|
|
private _getTeamMembersQuery: GetTeamMembersQuery;
|
|
private _getTeamJoinRequestsQuery: GetTeamJoinRequestsQuery;
|
|
private _getDriverTeamQuery: GetDriverTeamQuery;
|
|
|
|
private constructor() {
|
|
// Create seed data
|
|
const seedData = createSeedData();
|
|
const primaryDriverId = seedData.drivers[0]?.id ?? 'driver-1';
|
|
|
|
// Initialize repositories with seed data
|
|
this._driverRepository = new InMemoryDriverRepository(seedData.drivers);
|
|
this._leagueRepository = new InMemoryLeagueRepository(seedData.leagues);
|
|
this._raceRepository = new InMemoryRaceRepository(seedData.races);
|
|
|
|
// Result repository needs race repository for league-based queries
|
|
this._resultRepository = new InMemoryResultRepository(
|
|
seedData.results,
|
|
this._raceRepository
|
|
);
|
|
|
|
// Standing repository needs all three for recalculation
|
|
this._standingRepository = new InMemoryStandingRepository(
|
|
seedData.standings,
|
|
this._resultRepository,
|
|
this._raceRepository,
|
|
this._leagueRepository
|
|
);
|
|
|
|
// Race registrations (start empty; populated via use-cases)
|
|
this._raceRegistrationRepository = new InMemoryRaceRegistrationRepository();
|
|
|
|
// Penalties (seeded in-memory adapter)
|
|
this._penaltyRepository = new InMemoryPenaltyRepository();
|
|
|
|
// League memberships seeded from static memberships with guaranteed owner roles
|
|
const seededMemberships: LeagueMembership[] = seedData.memberships.map((m) => ({
|
|
leagueId: m.leagueId,
|
|
driverId: m.driverId,
|
|
role: 'member',
|
|
status: 'active',
|
|
joinedAt: new Date(),
|
|
}));
|
|
|
|
// Ensure each league owner has an owner membership
|
|
for (const league of seedData.leagues) {
|
|
const existing = seededMemberships.find(
|
|
(m) => m.leagueId === league.id && m.driverId === league.ownerId,
|
|
);
|
|
if (!existing) {
|
|
seededMemberships.push({
|
|
leagueId: league.id,
|
|
driverId: league.ownerId,
|
|
role: 'owner',
|
|
status: 'active',
|
|
joinedAt: new Date(),
|
|
});
|
|
} else {
|
|
existing.role = 'owner';
|
|
}
|
|
}
|
|
|
|
// Ensure the primary demo driver owns at least one league in memberships
|
|
const hasPrimaryOwnerMembership = seededMemberships.some(
|
|
(m: LeagueMembership) => m.driverId === primaryDriverId && m.role === 'owner',
|
|
);
|
|
if (!hasPrimaryOwnerMembership && seedData.leagues.length > 0) {
|
|
const targetLeague =
|
|
seedData.leagues.find((l) => l.ownerId === primaryDriverId) ??
|
|
seedData.leagues[0];
|
|
|
|
const existingForPrimary = seededMemberships.find(
|
|
(m) => m.leagueId === targetLeague.id && m.driverId === primaryDriverId,
|
|
);
|
|
|
|
if (existingForPrimary) {
|
|
existingForPrimary.role = 'owner';
|
|
} else {
|
|
seededMemberships.push({
|
|
leagueId: targetLeague.id,
|
|
driverId: primaryDriverId,
|
|
role: 'owner',
|
|
status: 'active',
|
|
joinedAt: new Date(),
|
|
});
|
|
}
|
|
}
|
|
|
|
// Seed sample league admins for the primary driver's league (alpha demo)
|
|
const primaryLeagueForAdmins =
|
|
seedData.leagues.find((l) => l.ownerId === primaryDriverId) ??
|
|
seedData.leagues[0];
|
|
|
|
if (primaryLeagueForAdmins) {
|
|
const adminCandidates = seedData.drivers
|
|
.filter((d) => d.id !== primaryLeagueForAdmins.ownerId)
|
|
.slice(0, 2);
|
|
|
|
adminCandidates.forEach((driver) => {
|
|
const existing = seededMemberships.find(
|
|
(m) =>
|
|
m.leagueId === primaryLeagueForAdmins.id && m.driverId === driver.id,
|
|
);
|
|
if (existing) {
|
|
if (existing.role !== 'owner') {
|
|
existing.role = 'admin';
|
|
}
|
|
} else {
|
|
seededMemberships.push({
|
|
leagueId: primaryLeagueForAdmins.id,
|
|
driverId: driver.id,
|
|
role: 'admin',
|
|
status: 'active',
|
|
joinedAt: new Date(),
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Seed a few pending join requests for demo leagues
|
|
const seededJoinRequests: JoinRequest[] = [];
|
|
const demoLeagues = seedData.leagues.slice(0, 2);
|
|
const extraDrivers = seedData.drivers.slice(3, 8);
|
|
|
|
demoLeagues.forEach((league) => {
|
|
extraDrivers.forEach((driver, index) => {
|
|
seededJoinRequests.push({
|
|
id: `join-${league.id}-${driver.id}`,
|
|
leagueId: league.id,
|
|
driverId: driver.id,
|
|
requestedAt: new Date(Date.now() - (index + 1) * 24 * 60 * 60 * 1000),
|
|
message:
|
|
index % 2 === 0
|
|
? 'Would love to race in this series!'
|
|
: 'Looking to join for the upcoming season.',
|
|
});
|
|
});
|
|
});
|
|
|
|
this._leagueMembershipRepository = new InMemoryLeagueMembershipRepository(
|
|
seededMemberships,
|
|
seededJoinRequests,
|
|
);
|
|
|
|
// Team repositories seeded from static memberships/teams
|
|
this._teamRepository = new InMemoryTeamRepository(
|
|
seedData.teams.map((t) => ({
|
|
id: t.id,
|
|
name: t.name,
|
|
tag: t.tag,
|
|
description: t.description,
|
|
ownerId: seedData.drivers[0]?.id ?? 'driver-1',
|
|
leagues: [t.primaryLeagueId],
|
|
createdAt: new Date(),
|
|
})),
|
|
);
|
|
|
|
this._teamMembershipRepository = new InMemoryTeamMembershipRepository(
|
|
seedData.memberships
|
|
.filter((m) => m.teamId)
|
|
.map((m) => ({
|
|
teamId: m.teamId!,
|
|
driverId: m.driverId,
|
|
role: 'driver',
|
|
status: 'active',
|
|
joinedAt: new Date(),
|
|
})),
|
|
);
|
|
|
|
// Application-layer use-cases and queries wired with repositories
|
|
this._joinLeagueUseCase = new JoinLeagueUseCase(this._leagueMembershipRepository);
|
|
this._registerForRaceUseCase = new RegisterForRaceUseCase(
|
|
this._raceRegistrationRepository,
|
|
this._leagueMembershipRepository,
|
|
);
|
|
this._withdrawFromRaceUseCase = new WithdrawFromRaceUseCase(
|
|
this._raceRegistrationRepository,
|
|
);
|
|
this._isDriverRegisteredForRaceQuery = new IsDriverRegisteredForRaceQuery(
|
|
this._raceRegistrationRepository,
|
|
);
|
|
this._getRaceRegistrationsQuery = new GetRaceRegistrationsQuery(
|
|
this._raceRegistrationRepository,
|
|
);
|
|
this._getLeagueStandingsQuery = new GetLeagueStandingsQuery(this._standingRepository);
|
|
|
|
this._getLeagueDriverSeasonStatsQuery = new GetLeagueDriverSeasonStatsQuery(
|
|
this._standingRepository,
|
|
this._resultRepository,
|
|
this._penaltyRepository,
|
|
{
|
|
getRating: (driverId: string) => {
|
|
const stats = driverStats[driverId];
|
|
if (!stats) {
|
|
return { rating: null, ratingChange: null };
|
|
}
|
|
// For alpha we expose current rating and a mock delta
|
|
const baseline = 1500;
|
|
const delta = stats.rating - baseline;
|
|
return {
|
|
rating: stats.rating,
|
|
ratingChange: delta !== 0 ? delta : null,
|
|
};
|
|
},
|
|
},
|
|
);
|
|
|
|
this._getAllLeaguesWithCapacityQuery = new GetAllLeaguesWithCapacityQuery(
|
|
this._leagueRepository,
|
|
this._leagueMembershipRepository,
|
|
);
|
|
|
|
this._createTeamUseCase = new CreateTeamUseCase(
|
|
this._teamRepository,
|
|
this._teamMembershipRepository,
|
|
);
|
|
this._joinTeamUseCase = new JoinTeamUseCase(
|
|
this._teamRepository,
|
|
this._teamMembershipRepository,
|
|
);
|
|
this._leaveTeamUseCase = new LeaveTeamUseCase(this._teamMembershipRepository);
|
|
this._approveTeamJoinRequestUseCase = new ApproveTeamJoinRequestUseCase(
|
|
this._teamMembershipRepository,
|
|
);
|
|
this._rejectTeamJoinRequestUseCase = new RejectTeamJoinRequestUseCase(
|
|
this._teamMembershipRepository,
|
|
);
|
|
this._updateTeamUseCase = new UpdateTeamUseCase(
|
|
this._teamRepository,
|
|
this._teamMembershipRepository,
|
|
);
|
|
this._getAllTeamsQuery = new GetAllTeamsQuery(this._teamRepository);
|
|
this._getTeamDetailsQuery = new GetTeamDetailsQuery(
|
|
this._teamRepository,
|
|
this._teamMembershipRepository,
|
|
);
|
|
this._getTeamMembersQuery = new GetTeamMembersQuery(this._teamMembershipRepository);
|
|
this._getTeamJoinRequestsQuery = new GetTeamJoinRequestsQuery(
|
|
this._teamMembershipRepository,
|
|
);
|
|
this._getDriverTeamQuery = new GetDriverTeamQuery(
|
|
this._teamRepository,
|
|
this._teamMembershipRepository,
|
|
);
|
|
|
|
// Social and feed adapters backed by static seed
|
|
this._feedRepository = new InMemoryFeedRepository(seedData);
|
|
this._socialRepository = new InMemorySocialGraphRepository(seedData);
|
|
|
|
// Image service backed by demo adapter
|
|
this._imageService = new DemoImageServiceAdapter();
|
|
}
|
|
|
|
/**
|
|
* Get singleton instance
|
|
*/
|
|
static getInstance(): DIContainer {
|
|
if (!DIContainer.instance) {
|
|
DIContainer.instance = new DIContainer();
|
|
}
|
|
return DIContainer.instance;
|
|
}
|
|
|
|
/**
|
|
* Reset the container (useful for testing)
|
|
*/
|
|
static reset(): void {
|
|
DIContainer.instance = new DIContainer();
|
|
}
|
|
|
|
/**
|
|
* Repository getters
|
|
*/
|
|
get driverRepository(): IDriverRepository {
|
|
return this._driverRepository;
|
|
}
|
|
|
|
get leagueRepository(): ILeagueRepository {
|
|
return this._leagueRepository;
|
|
}
|
|
|
|
get raceRepository(): IRaceRepository {
|
|
return this._raceRepository;
|
|
}
|
|
|
|
get resultRepository(): IResultRepository {
|
|
return this._resultRepository;
|
|
}
|
|
|
|
get standingRepository(): IStandingRepository {
|
|
return this._standingRepository;
|
|
}
|
|
|
|
get penaltyRepository(): IPenaltyRepository {
|
|
return this._penaltyRepository;
|
|
}
|
|
|
|
get raceRegistrationRepository(): IRaceRegistrationRepository {
|
|
return this._raceRegistrationRepository;
|
|
}
|
|
|
|
get leagueMembershipRepository(): ILeagueMembershipRepository {
|
|
return this._leagueMembershipRepository;
|
|
}
|
|
|
|
get joinLeagueUseCase(): JoinLeagueUseCase {
|
|
return this._joinLeagueUseCase;
|
|
}
|
|
|
|
get registerForRaceUseCase(): RegisterForRaceUseCase {
|
|
return this._registerForRaceUseCase;
|
|
}
|
|
|
|
get withdrawFromRaceUseCase(): WithdrawFromRaceUseCase {
|
|
return this._withdrawFromRaceUseCase;
|
|
}
|
|
|
|
get isDriverRegisteredForRaceQuery(): IsDriverRegisteredForRaceQuery {
|
|
return this._isDriverRegisteredForRaceQuery;
|
|
}
|
|
|
|
get getRaceRegistrationsQuery(): GetRaceRegistrationsQuery {
|
|
return this._getRaceRegistrationsQuery;
|
|
}
|
|
|
|
get getLeagueStandingsQuery(): GetLeagueStandingsQuery {
|
|
return this._getLeagueStandingsQuery;
|
|
}
|
|
|
|
get getLeagueDriverSeasonStatsQuery(): GetLeagueDriverSeasonStatsQuery {
|
|
return this._getLeagueDriverSeasonStatsQuery;
|
|
}
|
|
|
|
get getAllLeaguesWithCapacityQuery(): GetAllLeaguesWithCapacityQuery {
|
|
return this._getAllLeaguesWithCapacityQuery;
|
|
}
|
|
|
|
get createTeamUseCase(): CreateTeamUseCase {
|
|
return this._createTeamUseCase;
|
|
}
|
|
|
|
get joinTeamUseCase(): JoinTeamUseCase {
|
|
return this._joinTeamUseCase;
|
|
}
|
|
|
|
get leaveTeamUseCase(): LeaveTeamUseCase {
|
|
return this._leaveTeamUseCase;
|
|
}
|
|
|
|
get approveTeamJoinRequestUseCase(): ApproveTeamJoinRequestUseCase {
|
|
return this._approveTeamJoinRequestUseCase;
|
|
}
|
|
|
|
get rejectTeamJoinRequestUseCase(): RejectTeamJoinRequestUseCase {
|
|
return this._rejectTeamJoinRequestUseCase;
|
|
}
|
|
|
|
get updateTeamUseCase(): UpdateTeamUseCase {
|
|
return this._updateTeamUseCase;
|
|
}
|
|
|
|
get getAllTeamsQuery(): GetAllTeamsQuery {
|
|
return this._getAllTeamsQuery;
|
|
}
|
|
|
|
get getTeamDetailsQuery(): GetTeamDetailsQuery {
|
|
return this._getTeamDetailsQuery;
|
|
}
|
|
|
|
get getTeamMembersQuery(): GetTeamMembersQuery {
|
|
return this._getTeamMembersQuery;
|
|
}
|
|
|
|
get getTeamJoinRequestsQuery(): GetTeamJoinRequestsQuery {
|
|
return this._getTeamJoinRequestsQuery;
|
|
}
|
|
|
|
get getDriverTeamQuery(): GetDriverTeamQuery {
|
|
return this._getDriverTeamQuery;
|
|
}
|
|
|
|
get teamRepository(): ITeamRepository {
|
|
return this._teamRepository;
|
|
}
|
|
|
|
get teamMembershipRepository(): ITeamMembershipRepository {
|
|
return this._teamMembershipRepository;
|
|
}
|
|
|
|
get feedRepository(): IFeedRepository {
|
|
return this._feedRepository;
|
|
}
|
|
|
|
get socialRepository(): ISocialGraphRepository {
|
|
return this._socialRepository;
|
|
}
|
|
|
|
get imageService(): ImageServicePort {
|
|
return this._imageService;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Exported accessor functions
|
|
*/
|
|
export function getDriverRepository(): IDriverRepository {
|
|
return DIContainer.getInstance().driverRepository;
|
|
}
|
|
|
|
export function getLeagueRepository(): ILeagueRepository {
|
|
return DIContainer.getInstance().leagueRepository;
|
|
}
|
|
|
|
export function getRaceRepository(): IRaceRepository {
|
|
return DIContainer.getInstance().raceRepository;
|
|
}
|
|
|
|
export function getResultRepository(): IResultRepository {
|
|
return DIContainer.getInstance().resultRepository;
|
|
}
|
|
|
|
export function getStandingRepository(): IStandingRepository {
|
|
return DIContainer.getInstance().standingRepository;
|
|
}
|
|
|
|
export function getPenaltyRepository(): IPenaltyRepository {
|
|
return DIContainer.getInstance().penaltyRepository;
|
|
}
|
|
|
|
export function getRaceRegistrationRepository(): IRaceRegistrationRepository {
|
|
return DIContainer.getInstance().raceRegistrationRepository;
|
|
}
|
|
|
|
export function getLeagueMembershipRepository(): ILeagueMembershipRepository {
|
|
return DIContainer.getInstance().leagueMembershipRepository;
|
|
}
|
|
|
|
export function getJoinLeagueUseCase(): JoinLeagueUseCase {
|
|
return DIContainer.getInstance().joinLeagueUseCase;
|
|
}
|
|
|
|
export function getRegisterForRaceUseCase(): RegisterForRaceUseCase {
|
|
return DIContainer.getInstance().registerForRaceUseCase;
|
|
}
|
|
|
|
export function getWithdrawFromRaceUseCase(): WithdrawFromRaceUseCase {
|
|
return DIContainer.getInstance().withdrawFromRaceUseCase;
|
|
}
|
|
|
|
export function getIsDriverRegisteredForRaceQuery(): IsDriverRegisteredForRaceQuery {
|
|
return DIContainer.getInstance().isDriverRegisteredForRaceQuery;
|
|
}
|
|
|
|
export function getGetRaceRegistrationsQuery(): GetRaceRegistrationsQuery {
|
|
return DIContainer.getInstance().getRaceRegistrationsQuery;
|
|
}
|
|
|
|
export function getGetLeagueStandingsQuery(): GetLeagueStandingsQuery {
|
|
return DIContainer.getInstance().getLeagueStandingsQuery;
|
|
}
|
|
|
|
export function getGetLeagueDriverSeasonStatsQuery(): GetLeagueDriverSeasonStatsQuery {
|
|
return DIContainer.getInstance().getLeagueDriverSeasonStatsQuery;
|
|
}
|
|
|
|
export function getGetAllLeaguesWithCapacityQuery(): GetAllLeaguesWithCapacityQuery {
|
|
return DIContainer.getInstance().getAllLeaguesWithCapacityQuery;
|
|
}
|
|
|
|
export function getTeamRepository(): ITeamRepository {
|
|
return DIContainer.getInstance().teamRepository;
|
|
}
|
|
|
|
export function getTeamMembershipRepository(): ITeamMembershipRepository {
|
|
return DIContainer.getInstance().teamMembershipRepository;
|
|
}
|
|
|
|
export function getCreateTeamUseCase(): CreateTeamUseCase {
|
|
return DIContainer.getInstance().createTeamUseCase;
|
|
}
|
|
|
|
export function getJoinTeamUseCase(): JoinTeamUseCase {
|
|
return DIContainer.getInstance().joinTeamUseCase;
|
|
}
|
|
|
|
export function getLeaveTeamUseCase(): LeaveTeamUseCase {
|
|
return DIContainer.getInstance().leaveTeamUseCase;
|
|
}
|
|
|
|
export function getApproveTeamJoinRequestUseCase(): ApproveTeamJoinRequestUseCase {
|
|
return DIContainer.getInstance().approveTeamJoinRequestUseCase;
|
|
}
|
|
|
|
export function getRejectTeamJoinRequestUseCase(): RejectTeamJoinRequestUseCase {
|
|
return DIContainer.getInstance().rejectTeamJoinRequestUseCase;
|
|
}
|
|
|
|
export function getUpdateTeamUseCase(): UpdateTeamUseCase {
|
|
return DIContainer.getInstance().updateTeamUseCase;
|
|
}
|
|
|
|
export function getGetAllTeamsQuery(): GetAllTeamsQuery {
|
|
return DIContainer.getInstance().getAllTeamsQuery;
|
|
}
|
|
|
|
export function getGetTeamDetailsQuery(): GetTeamDetailsQuery {
|
|
return DIContainer.getInstance().getTeamDetailsQuery;
|
|
}
|
|
|
|
export function getGetTeamMembersQuery(): GetTeamMembersQuery {
|
|
return DIContainer.getInstance().getTeamMembersQuery;
|
|
}
|
|
|
|
export function getGetTeamJoinRequestsQuery(): GetTeamJoinRequestsQuery {
|
|
return DIContainer.getInstance().getTeamJoinRequestsQuery;
|
|
}
|
|
|
|
export function getGetDriverTeamQuery(): GetDriverTeamQuery {
|
|
return DIContainer.getInstance().getDriverTeamQuery;
|
|
}
|
|
|
|
export function getFeedRepository(): IFeedRepository {
|
|
return DIContainer.getInstance().feedRepository;
|
|
}
|
|
|
|
export function getSocialRepository(): ISocialGraphRepository {
|
|
return DIContainer.getInstance().socialRepository;
|
|
}
|
|
|
|
export function getImageService(): ImageServicePort {
|
|
return DIContainer.getInstance().imageService;
|
|
}
|
|
|
|
/**
|
|
* Reset function for testing
|
|
*/
|
|
export function resetContainer(): void {
|
|
DIContainer.reset();
|
|
}
|
|
|
|
/**
|
|
* Get driver statistics and rankings
|
|
*/
|
|
export function getDriverStats(driverId: string): DriverStats | null {
|
|
return driverStats[driverId] || null;
|
|
}
|
|
|
|
/**
|
|
* Get all driver rankings sorted by rating
|
|
*/
|
|
export function getAllDriverRankings(): DriverStats[] {
|
|
return Object.values(driverStats).sort((a, b) => b.rating - a.rating);
|
|
}
|
|
|
|
/**
|
|
* Get league-specific rankings for a driver
|
|
*/
|
|
export function getLeagueRankings(driverId: string, leagueId: string): {
|
|
rank: number;
|
|
totalDrivers: number;
|
|
percentile: number;
|
|
} {
|
|
// Mock league rankings (in production, calculate from actual league membership)
|
|
const mockLeagueRanks: Record<string, Record<string, any>> = {
|
|
'league-1': {
|
|
'driver-1': { rank: 1, totalDrivers: 12, percentile: 92 },
|
|
'driver-2': { rank: 2, totalDrivers: 12, percentile: 84 },
|
|
'driver-3': { rank: 4, totalDrivers: 12, percentile: 67 },
|
|
'driver-4': { rank: 5, totalDrivers: 12, percentile: 58 }
|
|
}
|
|
};
|
|
|
|
return mockLeagueRanks[leagueId]?.[driverId] || { rank: 0, totalDrivers: 0, percentile: 0 };
|
|
} |