73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
|
import type {
|
|
GetRaceResultsDetailResult,
|
|
GetRaceResultsDetailErrorCode,
|
|
} from '@core/racing/application/use-cases/GetRaceResultsDetailUseCase';
|
|
import type { IImageServicePort } from '@core/racing/application/ports/IImageServicePort';
|
|
import type { RaceResultsDetailDTO } from '../dtos/RaceResultsDetailDTO';
|
|
import type { RaceResultDTO } from '../dtos/RaceResultDTO';
|
|
|
|
export type GetRaceResultsDetailResponseModel = RaceResultsDetailDTO;
|
|
|
|
export type GetRaceResultsDetailApplicationError = ApplicationErrorCode<
|
|
GetRaceResultsDetailErrorCode,
|
|
{ message: string }
|
|
>;
|
|
|
|
export class RaceResultsDetailPresenter {
|
|
private result: GetRaceResultsDetailResult | null = null;
|
|
|
|
constructor(private readonly imageService: IImageServicePort) {}
|
|
|
|
present(result: GetRaceResultsDetailResult): void {
|
|
this.result = result;
|
|
}
|
|
|
|
async getResponseModel(): Promise<GetRaceResultsDetailResponseModel | null> {
|
|
if (!this.result) {
|
|
return null;
|
|
}
|
|
|
|
const output = this.result;
|
|
|
|
const driverMap = new Map(output.drivers.map(driver => [driver.id, driver]));
|
|
|
|
const results: RaceResultDTO[] = await Promise.all(
|
|
output.results.map(async singleResult => {
|
|
const driver = driverMap.get(singleResult.driverId.toString());
|
|
if (!driver) {
|
|
throw new Error(`Driver not found for result: ${singleResult.driverId}`);
|
|
}
|
|
|
|
const avatarUrl = this.imageService.getDriverAvatar(driver.id);
|
|
|
|
return {
|
|
driverId: singleResult.driverId.toString(),
|
|
driverName: driver.name.toString(),
|
|
avatarUrl,
|
|
position: singleResult.position.toNumber(),
|
|
startPosition: singleResult.startPosition.toNumber(),
|
|
incidents: singleResult.incidents.toNumber(),
|
|
fastestLap: singleResult.fastestLap.toNumber(),
|
|
positionChange: singleResult.getPositionChange(),
|
|
isPodium: singleResult.isPodium(),
|
|
isClean: singleResult.isClean(),
|
|
} as RaceResultDTO;
|
|
}),
|
|
);
|
|
|
|
return {
|
|
raceId: output.race.id,
|
|
track: output.race.track,
|
|
results,
|
|
} as RaceResultsDetailDTO;
|
|
}
|
|
|
|
get viewModel(): Promise<GetRaceResultsDetailResponseModel> {
|
|
return this.getResponseModel().then(model => {
|
|
if (!model) throw new Error('Presenter not presented');
|
|
return model;
|
|
});
|
|
}
|
|
}
|