/** * Shared randomness helpers. * * `Array.prototype.sort(() => 0.5 - Math.random())` is biased — modern V8 * sorts use Timsort, which compares each element more than once and skews * the resulting permutation. Use `shuffle` for anything user-visible * (quiz options, review topic selection, leaderboards). */ export function shuffle(arr) { const out = [...arr]; for (let i = out.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [out[i], out[j]] = [out[j], out[i]]; } return out; } export function sample(arr, n) { if (n <= 0) return []; if (n >= arr.length) return shuffle(arr); return shuffle(arr).slice(0, n); } export function pickInt(min, maxInclusive) { const lo = Math.ceil(min); const hi = Math.floor(maxInclusive); return lo + Math.floor(Math.random() * (hi - lo + 1)); }