NamesOnWheel

Reference page · Last updated 2026-05-25

How the random wheel picker works

NamesOnWheel makes one core promise: every spin is uniformly random over your entries. This page explains exactly how that works under the hood, so you can verify the claim yourself.

1. The randomness source

Every spin is decided by window.crypto.getRandomValues, a cryptographically secure random number generator built into every modern browser. The CSPRNG draws entropy from your operating system, which in turn collects it from hardware sources — mouse movements, keyboard timings, hard-drive interrupt timings, microphone noise on supported devices, and dedicated hardware random-number generators on most modern CPUs.

This is the same primitive your browser uses to generate the cryptographic keys for HTTPS sessions, password manager passwords, and one-time login tokens. If it failed, your bank login would also fail.

2. Removing modulo bias with rejection sampling

The most common randomness bug in wheel-spinner code is using random32() % n to pick an index. When n doesn't evenly divide 2³², the lowest indices get a tiny edge — for n = 7, the bias is about 0.000000016% over a single draw, but it compounds over millions.

We avoid this with classical rejection sampling:

const limit = Math.floor(0x100000000 / n) * n;
while (true) {
  const r = randomUint32();
  if (r < limit) return r % n;
  // Re-draw. Expected loops < 2 in the worst case.
}

Result: exactly uniform integer in [0, n) for any n.

3. Weighted picks

For weighted entries (e.g. 'Alice *3'), we sum all weights, draw a uniform float in [0, totalWeight) using 53 bits of CSPRNG entropy, then walk the cumulative weights to find which segment that float lands in:

const r = randomFloat() * totalWeight;
let acc = 0;
for (let i = 0; i < weights.length; i++) {
  acc += weights[i];
  if (r < acc) return i;
}

You can verify this on /fairness by toggling 'Alternating weights' — the result chart matches the declared 1:2 ratio precisely over 100k spins.

4. Spin physics

Once the winner index is chosen, we compute the wheel rotation angle that will land the pointer on that segment. We add a uniform offset within the segment (so the wheel doesn't always stop dead-center on a segment), plus 6 full rotations to give the spin its perceived weight. The animation uses cubic-out easing so the wheel decelerates naturally.

The visual spin doesn't decide the winner — the winner is decided up front by the random source, then the wheel animates to that destination. Importantly, the spin animation is purely cosmetic; the result is final the instant you tap Spin.

5. Verification

Visit /fairness. The page imports the exact same functions used in production and runs them 100,000 times in your browser. The chi-square statistic and p-value tell you whether the distribution is uniform. If it's not, your browser's CSPRNG is broken (which would mean your bank login is also broken — a much bigger problem).

6. What the wheel does NOT do

Frequently asked questions

What random source do you use?
crypto.getRandomValues — the browser's built-in CSPRNG. It draws on hardware entropy (mouse movements, keyboard timings, OS-level entropy pool). The same primitive that browsers use to generate TLS keys and password reset tokens.
What is rejection sampling and why do you use it?
Naive 'r % n' on a 32-bit random integer introduces a tiny bias when n doesn't divide 2^32 evenly — some indices land slightly more often than others. Rejection sampling fixes this: we keep drawing until we get a value below the largest multiple of n, then take that value mod n. Result: exact uniform distribution.
How are weighted entries fair?
We compute the total weight, draw a uniform float in [0, total), then walk the cumulative weights to find which segment that float lands in. Verifiable by setting alternating weights on /fairness and observing exactly the expected ratio.
How are spins not biased toward landing on the same place?
Each spin picks a target segment via the weighted-random function, then chooses a uniform offset within that segment so the wheel lands somewhere within the segment, not at its center. Plus 6+ full rotations of acceleration so the eye can't track which segment is approaching.
Is the wheel deterministic from a known input?
No. The CSPRNG state is opaque and renews continuously. You cannot replay a specific spin from any input you control.
Is the source code available?
Yes — the wheel engine is open source under the MIT license. The /fairness page imports the same modules used in production, so a passing chi-square on /fairness is a chi-square on the real picker.

Related tools