mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-08 04:06:18 -04:00
72 lines
2.5 KiB
TypeScript
72 lines
2.5 KiB
TypeScript
|
|
import { describe, expect, it } from 'vitest'
|
||
|
|
import {
|
||
|
|
INTERVAL_DRS_MAX_SECONDS,
|
||
|
|
INTERVAL_UNDERCUT_MAX_SECONDS,
|
||
|
|
INTERVAL_UNDERCUT_MIN_SECONDS,
|
||
|
|
MAX_POINTS_PER_ROUND,
|
||
|
|
TYRE_CLIFF_LAPS,
|
||
|
|
intervalMeaning,
|
||
|
|
pointsGapMeaning,
|
||
|
|
tyreAgeMeaning,
|
||
|
|
} from '../lib/meaning'
|
||
|
|
|
||
|
|
describe('intervalMeaning', () => {
|
||
|
|
it('returns DRS range below the threshold', () => {
|
||
|
|
expect(intervalMeaning(0.4)?.caption).toBe('DRS range')
|
||
|
|
expect(intervalMeaning(INTERVAL_DRS_MAX_SECONDS - 0.01)?.caption).toBe('DRS range')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('returns undercut window in the middle band', () => {
|
||
|
|
expect(intervalMeaning(INTERVAL_UNDERCUT_MIN_SECONDS)?.caption).toBe('undercut window')
|
||
|
|
expect(intervalMeaning(2.0)?.caption).toBe('undercut window')
|
||
|
|
expect(intervalMeaning(INTERVAL_UNDERCUT_MAX_SECONDS)?.caption).toBe('undercut window')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('returns null outside known bands', () => {
|
||
|
|
expect(intervalMeaning(INTERVAL_UNDERCUT_MAX_SECONDS + 0.5)).toBeNull()
|
||
|
|
expect(intervalMeaning(10)).toBeNull()
|
||
|
|
expect(intervalMeaning(null)).toBeNull()
|
||
|
|
expect(intervalMeaning(undefined)).toBeNull()
|
||
|
|
expect(intervalMeaning(-1)).toBeNull()
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
describe('tyreAgeMeaning', () => {
|
||
|
|
it('labels fresh, mid-life, and laps-to-cliff for SOFT', () => {
|
||
|
|
const cliff = TYRE_CLIFF_LAPS.SOFT
|
||
|
|
expect(tyreAgeMeaning('SOFT', 2)?.caption).toBe('fresh')
|
||
|
|
expect(tyreAgeMeaning('SOFT', Math.ceil(cliff * 0.5))?.caption).toBe('mid-life')
|
||
|
|
expect(tyreAgeMeaning('SOFT', cliff - 2)?.caption).toBe('~2 laps to cliff')
|
||
|
|
expect(tyreAgeMeaning('SOFT', cliff + 5)?.caption).toBe('past cliff')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('handles unknown compounds with defaults', () => {
|
||
|
|
expect(tyreAgeMeaning('UNKNOWN', 3)?.caption).toBe('fresh')
|
||
|
|
expect(tyreAgeMeaning(undefined, 3)?.caption).toBe('fresh')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('returns null for invalid age', () => {
|
||
|
|
expect(tyreAgeMeaning('MEDIUM', null)).toBeNull()
|
||
|
|
expect(tyreAgeMeaning('MEDIUM', -1)).toBeNull()
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
describe('pointsGapMeaning', () => {
|
||
|
|
it('computes catchable pts/round', () => {
|
||
|
|
const result = pointsGapMeaning(40, 4, 'VER')
|
||
|
|
expect(result?.caption).toBe('~10 pts/round')
|
||
|
|
expect(result?.title).toContain('VER')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('marks uncatchable gaps', () => {
|
||
|
|
const max = 3 * MAX_POINTS_PER_ROUND
|
||
|
|
expect(pointsGapMeaning(max + 1, 3, 'VER')?.caption).toBe('out of reach')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('returns null for leader or invalid input', () => {
|
||
|
|
expect(pointsGapMeaning(0, 4)).toBeNull()
|
||
|
|
expect(pointsGapMeaning(10, 0)).toBeNull()
|
||
|
|
expect(pointsGapMeaning(null, 4)).toBeNull()
|
||
|
|
})
|
||
|
|
})
|