mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-07 19:56:18 -04:00
70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import type { DriverSummaryRound } from '../types'
|
||
|
||
/** One round mapped for the grid-vs-finish chart and results table. */
|
||
export interface RoundDelta {
|
||
round: number // 1-based round index within the completed season
|
||
label: string // short GP label, e.g. "Bahrain"
|
||
grid: number | null
|
||
finish: number | null
|
||
/** grid − finish: positive = places gained on Sunday, null when unknowable. */
|
||
delta: number | null
|
||
points: number
|
||
status: 'classified' | 'dnf' | 'dns' | 'dsq' | 'absent'
|
||
}
|
||
|
||
/** Strip the "Grand Prix" boilerplate so round labels fit chart axes. */
|
||
export function shortGpLabel(meetingName: string): string {
|
||
const short = meetingName
|
||
.replace(/\s*grand prix\s*/i, ' ')
|
||
.replace(/\s+gp\s*$/i, ' ')
|
||
.trim()
|
||
return short || meetingName
|
||
}
|
||
|
||
function roundStatus(r: DriverSummaryRound): RoundDelta['status'] {
|
||
if (r.dns) return 'dns'
|
||
if (r.dsq) return 'dsq'
|
||
if (r.dnf) return 'dnf'
|
||
if (r.race_position <= 0 && r.grid_position <= 0) return 'absent'
|
||
return 'classified'
|
||
}
|
||
|
||
/**
|
||
* Map summary rounds to grid-vs-finish deltas. Positions of 0 mean "no data"
|
||
* (driver absent, pit-lane start, …) and become null; a delta is only computed
|
||
* when both ends are known and the driver actually started the race.
|
||
*/
|
||
export function gridFinishDeltas(rounds: DriverSummaryRound[]): RoundDelta[] {
|
||
return rounds.map((r, i) => {
|
||
const status = roundStatus(r)
|
||
const grid = r.grid_position > 0 ? r.grid_position : null
|
||
const finish = r.race_position > 0 ? r.race_position : null
|
||
const delta =
|
||
grid != null && finish != null && status !== 'dns' && status !== 'absent'
|
||
? grid - finish
|
||
: null
|
||
return {
|
||
round: i + 1,
|
||
label: shortGpLabel(r.meeting_name),
|
||
grid,
|
||
finish,
|
||
delta,
|
||
points: r.points,
|
||
status,
|
||
}
|
||
})
|
||
}
|
||
|
||
/** 'P4' for known positions, '—' when unknown. */
|
||
export function formatPosition(pos: number | null): string {
|
||
return pos != null && pos > 0 ? `P${pos}` : '—'
|
||
}
|
||
|
||
/** '+3' (gained), '−2' (lost), '=' (held), '—' (unknown). */
|
||
export function formatDelta(delta: number | null): string {
|
||
if (delta == null) return '—'
|
||
if (delta > 0) return `+${delta}`
|
||
if (delta < 0) return `−${Math.abs(delta)}`
|
||
return '='
|
||
}
|