forked from eros/curltastic
Replace constant-rate velocity rotate with ω0 spin + v_lat curl. Path samples are (x, y, theta); client time is index/SAMPLE_RATE_HZ. Ultraworked with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <sisyphus@ohmyopencode>
70 lines
1.9 KiB
TypeScript
70 lines
1.9 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
hogTrimStartIndex,
|
|
sampleTime,
|
|
trimPathToStartAtHogLine,
|
|
velocityToWeight,
|
|
weightToVelocity,
|
|
} from './game-helpers'
|
|
import { SAMPLE_RATE_HZ } from './protocol'
|
|
|
|
describe('trimPathToStartAtHogLine', () => {
|
|
it('trims path at the first hog-line crossing and preserves theta', () => {
|
|
// (x, y, theta) — time is derived from index after trim
|
|
const path: [number, number, number][] = [
|
|
[0, 2, 0.1],
|
|
[0, 20, 0.2],
|
|
[0, 21.5, 0.3],
|
|
[0, 30, 0.4],
|
|
]
|
|
const trimmed = trimPathToStartAtHogLine(path)
|
|
expect(trimmed[0][1]).toBe(20)
|
|
expect(trimmed[0][2]).toBe(0.2)
|
|
expect(trimmed[trimmed.length - 1][2]).toBe(0.4)
|
|
expect(trimmed).toHaveLength(3)
|
|
})
|
|
|
|
it('returns full path when hog line is never reached', () => {
|
|
const path: [number, number, number][] = [
|
|
[0, 2, 0],
|
|
[0, 10, 0.5],
|
|
]
|
|
expect(trimPathToStartAtHogLine(path)).toEqual(path)
|
|
})
|
|
})
|
|
|
|
describe('sampleTime', () => {
|
|
it('is index / SAMPLE_RATE_HZ', () => {
|
|
expect(sampleTime(0)).toBe(0)
|
|
expect(sampleTime(SAMPLE_RATE_HZ)).toBe(1)
|
|
expect(sampleTime(1)).toBeCloseTo(1 / SAMPLE_RATE_HZ)
|
|
})
|
|
})
|
|
|
|
describe('hogTrimStartIndex', () => {
|
|
it('returns index just before hog crossing', () => {
|
|
const path: [number, number, number][] = [
|
|
[0, 2, 0],
|
|
[0, 20, 0],
|
|
[0, 21.5, 0],
|
|
]
|
|
expect(hogTrimStartIndex(path)).toBe(1)
|
|
})
|
|
})
|
|
|
|
describe('velocity ↔ weight', () => {
|
|
it('maps endpoints correctly', () => {
|
|
expect(velocityToWeight(3.0)).toBe(1)
|
|
expect(velocityToWeight(6.45)).toBe(10)
|
|
expect(weightToVelocity(1)).toBe(3.0)
|
|
expect(weightToVelocity(10)).toBe(6.45)
|
|
})
|
|
|
|
it('clamps out-of-range inputs', () => {
|
|
expect(velocityToWeight(2.5)).toBe(1)
|
|
expect(velocityToWeight(7.0)).toBe(10)
|
|
expect(weightToVelocity(0)).toBe(3.0)
|
|
expect(weightToVelocity(11)).toBe(6.45)
|
|
})
|
|
})
|