mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-08 04:06:18 -04:00
feat(#24): Rivalry compare view
Implemented by claude via .agents/dev dispatch.
This commit is contained in:
61
frontend/src/lib/rivalry.ts
Normal file
61
frontend/src/lib/rivalry.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
// Pure helpers for the championship rivalry compare view.
|
||||
|
||||
/** One round that counted toward the head-to-head tally. */
|
||||
export interface H2HRound {
|
||||
round: number // 1-based season round
|
||||
label: string
|
||||
posA: number
|
||||
posB: number
|
||||
winner: 'a' | 'b'
|
||||
}
|
||||
|
||||
export interface H2HTally {
|
||||
a: number
|
||||
b: number
|
||||
/** Rounds counted in the tally, in season order. */
|
||||
rounds: H2HRound[]
|
||||
/** Rounds skipped because either driver had no finishing position. */
|
||||
skipped: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-round points gap (a − b) across the rounds both cumulative series
|
||||
* cover. Positive values mean driver A is ahead.
|
||||
*/
|
||||
export function gapSeries(a: number[], b: number[]): number[] {
|
||||
const n = Math.min(a.length, b.length)
|
||||
const out: number[] = []
|
||||
for (let i = 0; i < n; i++) out.push(a[i] - b[i])
|
||||
return out
|
||||
}
|
||||
|
||||
/**
|
||||
* Race head-to-head: per round, the lower finishing position wins. Rounds
|
||||
* where either driver has no position (0 / missing) are skipped from the
|
||||
* tally, as are equal positions (defensive — races can't tie).
|
||||
*/
|
||||
export function h2hTally(posA: number[], posB: number[], labels: string[]): H2HTally {
|
||||
const n = Math.max(posA.length, posB.length)
|
||||
const rounds: H2HRound[] = []
|
||||
let a = 0
|
||||
let b = 0
|
||||
let skipped = 0
|
||||
for (let i = 0; i < n; i++) {
|
||||
const pa = posA[i] ?? 0
|
||||
const pb = posB[i] ?? 0
|
||||
if (pa <= 0 || pb <= 0 || pa === pb) {
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
const winner = pa < pb ? 'a' : 'b'
|
||||
if (winner === 'a') a++
|
||||
else b++
|
||||
rounds.push({ round: i + 1, label: labels[i] ?? `R${i + 1}`, posA: pa, posB: pb, winner })
|
||||
}
|
||||
return { a, b, rounds, skipped }
|
||||
}
|
||||
|
||||
/** Last n counted rounds of a tally, for the mini strip. */
|
||||
export function lastRounds(tally: H2HTally, n: number): H2HRound[] {
|
||||
return tally.rounds.slice(-n)
|
||||
}
|
||||
Reference in New Issue
Block a user