145 lines
4.0 KiB
TypeScript
145 lines
4.0 KiB
TypeScript
import type { IRaceRepository } from '../../domain/repositories/IRaceRepository';
|
|
import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository';
|
|
import type { IResultRepository } from '../../domain/repositories/IResultRepository';
|
|
import type { IDriverRepository } from '../../domain/repositories/IDriverRepository';
|
|
import type { IPenaltyRepository } from '../../domain/repositories/IPenaltyRepository';
|
|
import type {
|
|
IRaceResultsDetailPresenter,
|
|
RaceResultsDetailViewModel,
|
|
RaceResultsPenaltySummaryViewModel,
|
|
} from '../presenters/IRaceResultsDetailPresenter';
|
|
import type { League } from '../../domain/entities/League';
|
|
import type { Result } from '../../domain/entities/Result';
|
|
import type { Driver } from '../../domain/entities/Driver';
|
|
import type { Penalty } from '../../domain/entities/Penalty';
|
|
|
|
export interface GetRaceResultsDetailParams {
|
|
raceId: string;
|
|
driverId?: string;
|
|
}
|
|
|
|
function buildPointsSystem(league: League | null): Record<number, number> {
|
|
if (!league) return {};
|
|
|
|
const pointsSystems: Record<string, Record<number, number>> = {
|
|
'f1-2024': {
|
|
1: 25,
|
|
2: 18,
|
|
3: 15,
|
|
4: 12,
|
|
5: 10,
|
|
6: 8,
|
|
7: 6,
|
|
8: 4,
|
|
9: 2,
|
|
10: 1,
|
|
},
|
|
indycar: {
|
|
1: 50,
|
|
2: 40,
|
|
3: 35,
|
|
4: 32,
|
|
5: 30,
|
|
6: 28,
|
|
7: 26,
|
|
8: 24,
|
|
9: 22,
|
|
10: 20,
|
|
11: 19,
|
|
12: 18,
|
|
13: 17,
|
|
14: 16,
|
|
15: 15,
|
|
},
|
|
};
|
|
|
|
return (
|
|
league.settings.customPoints ||
|
|
pointsSystems[league.settings.pointsSystem] ||
|
|
pointsSystems['f1-2024']
|
|
);
|
|
}
|
|
|
|
function getFastestLapTime(results: Result[]): number | undefined {
|
|
if (results.length === 0) return undefined;
|
|
return Math.min(...results.map((r) => r.fastestLap));
|
|
}
|
|
|
|
function mapPenaltySummary(penalties: Penalty[]): RaceResultsPenaltySummaryViewModel[] {
|
|
return penalties.map((p) => ({
|
|
driverId: p.driverId,
|
|
type: p.type,
|
|
value: p.value,
|
|
}));
|
|
}
|
|
|
|
export class GetRaceResultsDetailUseCase {
|
|
constructor(
|
|
private readonly raceRepository: IRaceRepository,
|
|
private readonly leagueRepository: ILeagueRepository,
|
|
private readonly resultRepository: IResultRepository,
|
|
private readonly driverRepository: IDriverRepository,
|
|
private readonly penaltyRepository: IPenaltyRepository,
|
|
public readonly presenter: IRaceResultsDetailPresenter,
|
|
) {}
|
|
|
|
async execute(params: GetRaceResultsDetailParams): Promise<void> {
|
|
const { raceId, driverId } = params;
|
|
|
|
const race = await this.raceRepository.findById(raceId);
|
|
|
|
if (!race) {
|
|
const errorViewModel: RaceResultsDetailViewModel = {
|
|
race: null,
|
|
league: null,
|
|
results: [],
|
|
drivers: [],
|
|
penalties: [],
|
|
pointsSystem: {},
|
|
fastestLapTime: undefined,
|
|
currentDriverId: driverId,
|
|
error: 'Race not found',
|
|
};
|
|
this.presenter.present(errorViewModel);
|
|
return;
|
|
}
|
|
|
|
const [league, results, drivers, penalties] = await Promise.all([
|
|
this.leagueRepository.findById(race.leagueId),
|
|
this.resultRepository.findByRaceId(raceId),
|
|
this.driverRepository.findAll(),
|
|
this.penaltyRepository.findByRaceId(raceId),
|
|
]);
|
|
|
|
const effectiveCurrentDriverId =
|
|
driverId || (drivers.length > 0 ? drivers[0]!.id : undefined);
|
|
|
|
const pointsSystem = buildPointsSystem(league as League | null);
|
|
const fastestLapTime = getFastestLapTime(results);
|
|
const penaltySummary = mapPenaltySummary(penalties);
|
|
|
|
const viewModel: RaceResultsDetailViewModel = {
|
|
race: {
|
|
id: race.id,
|
|
leagueId: race.leagueId,
|
|
track: race.track,
|
|
scheduledAt: race.scheduledAt,
|
|
status: race.status,
|
|
},
|
|
league: league
|
|
? {
|
|
id: league.id,
|
|
name: league.name,
|
|
}
|
|
: null,
|
|
results,
|
|
drivers,
|
|
penalties: penaltySummary,
|
|
pointsSystem,
|
|
fastestLapTime,
|
|
currentDriverId: effectiveCurrentDriverId,
|
|
};
|
|
|
|
this.presenter.present(viewModel);
|
|
}
|
|
} |