// Pure mapping helpers for the time-scale slider (v0.9.2) — no game logic, unit-testable // in node. The slider has 7 discrete positions on a power-of-two ladder: // 1× → 2× → 4× → 8× → 16× → 32× → 64×, so each step doubles the speed (matching // POST /api/sim's clamp range [1, 64]). export const TIME_SCALES = [1, 2, 4, 8, 16, 32, 64] as const; export const MIN_SCALE: number = TIME_SCALES[0]; export const MAX_SCALE: number = TIME_SCALES[TIME_SCALES.length - 1]; const clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v)); // t → scale: the position maps to the nearest ladder step. Exact at the endpoints: // sliderToScale(0) === 1, sliderToScale(1) === 64. export function sliderToScale(t: number): number { const tt = clamp(Number.isFinite(t) ? t : 0, 0, 1); return TIME_SCALES[clamp(Math.round(tt * (TIME_SCALES.length - 1)), 0, TIME_SCALES.length - 1)]; } // scale → t: the nearest ladder position by log2 distance. Exact at the endpoints: // scaleToSlider(1) === 0, scaleToSlider(64) === 1; round-trips every value in TIME_SCALES. export function scaleToSlider(scale: number): number { const s = clamp(Number.isFinite(scale) ? scale : MIN_SCALE, MIN_SCALE, MAX_SCALE); return Math.log2(s) / Math.log2(MAX_SCALE); }