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
- Does not call any server. Every spin is local.
- Does not seed from time-of-day or any low-entropy source.
- Does not use Math.random.
- Does not learn from past spins.
- Does not adjust segment placement based on weights or recency.
Frequently asked questions
What random source do you use?
What is rejection sampling and why do you use it?
How are weighted entries fair?
How are spins not biased toward landing on the same place?
Is the wheel deterministic from a known input?
Is the source code available?
Related tools
Pick a random student fairly with a free, ad-free classroom wheel.
Pick a different student each day without bias.
Split a list of names into balanced random teams in seconds.
Pick a fair random number from 1 to 10.
Pick a fair random number from 1 to 100.