import { RaceResultDTO } from '@/lib/types/generated/RaceResultDTO'; import { FinishDisplay } from '../display-objects/FinishDisplay'; export class RaceResultViewModel { driverId!: string; driverName!: string; avatarUrl!: string; position!: number; startPosition!: number; incidents!: number; fastestLap!: number; positionChange!: number; isPodium!: boolean; isClean!: boolean; constructor(dto: RaceResultDTO) { Object.assign(this, dto); } /** UI-specific: Display for position change */ get positionChangeDisplay(): string { if (this.positionChange > 0) return `+${this.positionChange}`; if (this.positionChange < 0) return `${this.positionChange}`; return '0'; } /** UI-specific: Color for position change */ get positionChangeColor(): string { if (this.positionChange > 0) return 'green'; if (this.positionChange < 0) return 'red'; return 'gray'; } /** UI-specific: Whether this is the winner */ get isWinner(): boolean { return this.position === 1; } /** UI-specific: Whether has fastest lap */ get hasFastestLap(): boolean { return this.fastestLap > 0; } /** UI-specific: Badge for position */ get positionBadge(): string { return FinishDisplay.format(this.position); } /** UI-specific: Color for incidents badge */ get incidentsBadgeColor(): string { if (this.incidents === 0) return 'green'; if (this.incidents <= 2) return 'yellow'; return 'red'; } /** UI-specific: Formatted lap time */ get lapTimeFormatted(): string { if (this.fastestLap <= 0) return '--:--.---'; const minutes = Math.floor(this.fastestLap / 60); const seconds = Math.floor(this.fastestLap % 60); const milliseconds = Math.floor((this.fastestLap % 1) * 1000); return `${minutes}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(3, '0')}`; } /** Required by ResultsTable */ getPositionChange(): number { return this.positionChange; } get formattedPosition(): string { return FinishDisplay.format(this.position); } get formattedStartPosition(): string { return FinishDisplay.format(this.startPosition); } get formattedIncidents(): string { return `${this.incidents}x incidents`; } get formattedPositionsGained(): string | undefined { if (this.position < this.startPosition) { return `+${this.startPosition - this.position} positions`; } return undefined; } // Note: The generated DTO doesn't have id or raceId // These will need to be added when the OpenAPI spec is updated id: string = ''; raceId: string = ''; }