Is it fair?
The short answer is yes. The longer one is below, with numbers you can check yourself.
Where the randomness comes from
Every result comes from crypto.getRandomValues, the browser's random generator for cryptography, which draws its randomness from the operating system. Knowing every past result still doesn't let you guess the next.
soom never uses Math.random to decide anything. That one only drives decoration, like the letters spinning on the flip board while you wait, or the slight wobble in the sounds.
Each draw gives a 32-bit number, a whole number from 0 to 4,294,967,295, which is then turned into one of your options. That step is where most random pickers go wrong without noticing.
Modulo bias
The easy way is to divide the random number by the number of options and keep the remainder. But if the count of possible numbers doesn't divide evenly by your options, the first options get an edge. That's modulo bias.
Shrunk down to see it: if the generator gave only 0 to 9 and you had 3 options, remainder 0 comes from 0, 3, 6 and 9, four ways, while remainders 1 and 2 get three each. The first option would get 40% instead of 33.3%.
With real 32-bit numbers the gap is far smaller, but not zero, and it grows as the list gets longer.
How soom fixes it
Rejection sampling: find the largest number that divides evenly by your options, and if the draw lands above it, throw it away and draw again. What's left splits exactly evenly between every option.
In the example above, a 9 is thrown away, leaving 0 to 8, three for each option. In practice it almost never happens: with 3 options, one number in over four billion is thrown away.
// A whole number from 0 to max - 1, each equally likely
function randInt(max) {
const limit = Math.floor(2 ** 32 / max) * max;
let x = random32(); // crypto.getRandomValues
while (x >= limit) x = random32();
return x % max;
}Ordering, teams and several at once
- Ordering uses Fisher–Yates, which picks each position from those still left, so every possible order has the same chance, not just a few swaps.
- Teams shuffle the names the same way, then deal them one by one round the teams, so teams differ by at most one person and who's extra is random too.
- Several at once takes the first ones from the shuffled list, so none repeat.
- Knock-out puts the whole list in order first, then reveals it round by round. The last one left is the result.
The animation doesn't decide
The result is drawn the moment you press, before the wheel turns, before the balls roll and before you scratch. What you see is the reveal of a result that already exists. Pressing or shaking harder changes nothing.
Face-down cards work the same way. Every card was drawn before you chose, so the one you turn has the same chance as the rest.
Ready-made lists with dozens of answers only draw some slots so they stay readable, but the answer is drawn from the whole list. The same goes for your own lists past 12: the wheel leaves slices blank, and every item keeps the same chance.
Why the same thing can come up twice
A fair draw doesn't remember the last one. Five heads in a row has a 1 in 32 chance. Flip in a whole classroom and somebody gets it.
A picker that tries not to repeat itself is the one that isn't random.
How the gift exchange pairs people
The gift exchange is the one place that draws on the server instead of in your browser, so not even the organiser knows who got whom.
The database shuffles the names with a cryptographic random generator (gen_random_bytes), removes bias the same way as above, then checks that nobody got themselves and no kept-apart pair met. If the check fails, it shuffles the whole list again.
Shuffling until the check passes gives every valid pairing the same chance. Nobody is luckier for being on the first line.
The pairs are drawn when the organiser presses draw, but nobody sees them until the organiser presses ready. Releasing a wrong pick changes no pairs and leaks no secret.
Who can change the result
- No server picks the result. The draw happens in your browser, except the gift exchange, which pairs in the database as above.
- Sponsors get their name on screen and on the receipt, and may have answers in the ready-made lists with exactly the same chance as the rest. Discount codes appear only after the result is out. Nobody pays for the result to go their way.
- Your list reaches the server only if you send a short link or save a list while signed in. The privacy notice has the details.