ODL Manager

All entries

Draws

A league can now run a random draw: a field of numbers, one or more prizes, and a result anybody can check for themselves afterwards.

It is not a raffle feature, and that is deliberate. The same draw picks a raffle winner, decides who throws first, hands out lanes, splits a squad into teams or runs a giveaway. ODL Manager takes no payment for any of it and never touches entry money — what a league collects from its players is between them and their players, as it always has been.

What it does

Fill the field by hand, or bring a whole list across. Type names against numbers the way a board of tickets works, or import a division's roster, everybody in the league, or a tournament's field. Everybody imported gets a number, and guests come across beside accounts.

Closing is the moment everything turns on. The entries stop changing, the list is published, and so is a fingerprint of it. From then on nobody can be added, removed or moved.

Then draw the prizes, one at a time. Each has its own sealed seed, so the first result gives nothing away about the second.

Watch it as a wheel or a duck race. The page is public and has no sign-in in front of it: paste the link where the league already talks, or share your screen into Discord and press the button while everybody watches.

The interesting part

"The computer picked one" convinces nobody who did not win. Once people have put something into a draw, a result they cannot check is worth very little — so the whole thing is built so that nobody has to trust us at the moment it matters.

Every prize is given a seed when it is created, and the seed's SHA-256 is published immediately. The seed itself stays hidden until that prize is drawn. When it is revealed, anybody can hash it and see it is the seed that was promised.

The winner is then arithmetic. Each number in the field gets a fingerprint:

sha256(seed + ":" + number)

Sort the fingerprints; the smallest wins. That is the whole rule, and it is one command:

printf '%s:%s' "$SEED" "$NUMBER" | shasum -a 256

A field of 3, 7, 12, 28, 41 under seed 0f1e2d3c…e1f0 gives:

28  0627651838f4e579…
 7  21d59c1884c26a2b…
12  26924fe163c125fb…
 3  cf500c59a6c3cf21…
41  f8a5dfeeb556de63…

Number 28 wins, and it wins for everybody who checks. A second prize is drawn the same way from the numbers that have not already won.

The ordering is the part that took the most thought. The seed used to be minted when the draw closed, which sounds early enough — the commitment still went up before anything was drawn. But a seed chosen while the field is already known could, in principle, have been picked because of who was in it. So it is minted when the prize is created instead, before a single entry exists. Every prize carries the count of how full the field was at that moment, and the page says so under each commitment: "Committed 31 Aug 2026, 07:42, before anybody entered." A prize added part-way through says that instead.

Two things that are not what they look like

The wheel is not the draw. The number is picked from the committed seed first, and the wheel is then spun to arrive at it. Spinning something and reading off where it stopped would make the animation the draw, and an animation is not something anybody can check. The duck race is the same mechanism with different pictures — the finishing order is the order the seed produced, which is why a duck who has already won a prize sits out the next race rather than running it.

"You can check it" is not "provably fair". What is true is that the result is recomputable by anybody from the published list, the revealed seed and a hash function, and that the seed was committed before there was anybody to favour. What is not claimed is a certified random number generator or a guarantee of any kind about the numbers themselves. There is one limit worth stating plainly: this app holds each seed between committing to it and revealing it, and while anybody can check a revealed seed against its published hash, nobody can independently verify when that hash went up without a third-party timestamp.