Losowanie odbywa się w czterech krokach i żaden z nich nie zależy od animacji. Najpierw przeglądarka losuje 32-bitową liczbę całkowitą z crypto.getRandomValues(), czyli z generatora zasilanego entropią systemu operacyjnego — tego samego, którym generuje się klucze szyfrujące i hasła. Potem liczba jest zamieniana na numer segmentu, następnie wyliczany jest kąt obrotu, a dopiero na końcu uruchamiana jest animacja. Zwycięzca jest więc znany, zanim koło ruszy: kręcenie to wyłącznie oprawa.
- 1. losuj wartość v z przedziału [0, 4 294 967 296)
- 2. jeśli v ≥ 4 294 967 292 (dla 6 pozycji) — losuj ponownie
- 3. indeks = v mod 6
- 4. obróć koło o 5–8 pełnych obrotów + kąt do środka segmentu
Krok drugi to sedno uczciwości. Zakres liczby 32-bitowej ma 4 294 967 296 wartości, a 4 294 967 296 mod 6 = 4 — czterech wartości nie da się rozdzielić po równo między sześć pozycji. Gdyby użyć zwykłego dzielenia z resztą, cztery najwyższe wartości (od 4 294 967 292 wzwyż) dołożyłyby dodatkową szansę pierwszym czterem pozycjom. Dlatego te wartości odrzucamy i losujemy od nowa (rejection sampling). Odchylenie byłoby rzędu jednej miliardowej i nikt nie zauważyłby go gołym okiem — ale strona, która obiecuje równe szanse, powinna je faktycznie liczyć, a nie tylko deklarować.
Geometria jest prosta: przy sześciu pozycjach każdy segment zajmuje 360° / 6 = 60°, więc segment numer 3 (indeks 2) rozciąga się od 120° do 180°, a jego środek wypada na 150°. Wskaźnik stoi nieruchomo na godzinie 12, dlatego koło musi zatrzymać się w położeniu 360° − 150° = 210° (modulo 360°). Do tego dokładamy 5–8 pełnych obrotów oraz niewielkie odchylenie wewnątrz segmentu, żeby wskaźnik nigdy nie zatrzymał się dokładnie na granicy dwóch pozycji. Kolejne zakręcenia liczą kąt od bieżącego położenia koła, a nie od zera — inaczej po pierwszym losowaniu koło zatrzymywałoby się obok właściwego segmentu.
Animacja trwa 4 sekundy i korzysta z krzywej cubic-bezier(0.15, 0.85, 0.35, 1): szybki start i długie wytracanie prędkości, tak jak w fizycznym kole. Jeśli w systemie masz włączoną opcję ograniczenia animacji (prefers-reduced-motion), koło ustawia się od razu na wyniku, a nazwa zwycięzcy jest ogłaszana w obszarze aria-live="polite", więc czytnik ekranu odczyta ją bez czekania na animację.
Uczciwość rozkładu jest sprawdzana testem: 60 000 losowań na sześciu segmentach musi umieścić każdy segment w przedziale 9700–10 300 trafień (wartość oczekiwana 10 000, odchylenie standardowe około 91). Ten sam zestaw testów sprawdza przypadki brzegowe odrzucania wartości oraz to, że przy wagach 1 i 3 pozycja z wagą 3 dostaje 75% obwodu.