1. すべての結果は暗号学的乱数から
Spinvoltaは、最新のブラウザとOSに組み込まれた暗号学的に安全な乱数生成器crypto.getRandomValues()で結果を決めます。暗号鍵の生成にも使われる乱数源です。何かを決めるためにMath.random()を使うことはありません(紙吹雪が飛ぶ方向のような純粋な装飾にだけ使います)。
2. 剰余による偏りなし
32ビットの乱数は、たとえば7つの選択肢に必ずしも均等に分けられません。4,294,967,296は7の倍数ではないため、単純なnumber % 7では一部の選択肢がわずかに当たりやすくなります。Spinvoltaは棄却サンプリングを使います。範囲の上端の割り切れない部分に入った数は捨てて、新しく引き直します。これで選択肢がいくつあっても、どれも完全に同じ確率になります。
3. 重みは正確
重み付きモードでは、1、2.5、0.125のような重みを共通のスケールで整数に変換し、正確に合計します。合計に対する1回の一様な抽選で当選が決まるので、重み2の項目は重み1のちょうど2倍当たりやすく、ルーレットのマスの大きさがその正確な確率を表します。
4. 重複なしの複数当選
複数当選、チーム分け、順番決め、トランプのシャッフル、プレゼント抽選では、偏りのないフィッシャー–イェーツ法(同じく棄却サンプリング付き)を使うので、当選の並びや組み合わせはどれも同じ確率です。
5. 結果が先、アニメーションは後
「回す」を押した瞬間、ルーレットが動く前に当選が決まります。その後ソルバーが動き——ため、速さ、回転数、最後のゆらぎ——を計算し、当選マスの中、端から離れたランダムな位置にぴたりと止めます。強いフリック、長い回転、手動ストップで変わるのは見た目だけ。自動テストで何千回ものランダムな回転を確認し、アニメーションが必ず事前に決まった結果に止まり、隣のマスにずれないことを確かめています。
6. プレゼント抽選とルームのための証明可能な公平抽選
プレゼント抽選(や信頼が大事なあらゆる抽選)では、私たちやホストを信用しなくて済むよう、さらに一歩進みます。
- 抽選前に、ブラウザが応募リストと設定を固定し、リスト・設定・秘密のシードのSHA-256ハッシュであるフィンガープリントを公開します。サーバーは受け取った時刻を記録します。
- フィンガープリントには、drand League of Entropy乱数ビーコンの将来のラウンドが指定されます。これは世界中の独立した組織が3秒ごとに生成する公開値で、誰も予測も選択もできません。
- そのラウンドが公開されると、フィンガープリント、ビーコン値、シードから当選者が計算されます。
- 証明ページにはすべてが表示されます。誰でも検証を押せば、ビーコンの暗号署名の確認も含めて、自分のブラウザで再計算できます。
リストを固定した時点でビーコン値は存在しないので、ホストは当選者を選べません。私たちも、フィンガープリントが固定される前にシードを見ることはなく、drandも管理していないので選べません。ビーコンに接続できない場合は、そのことを明示したコミット・リビール方式の抽選に切り替わります。
7. 統計的にテスト済み
テストスイートでは、変更のたびに数十万回のシミュレーション抽選に対してカイ二乗適合度検定を行い、フルテストでは100万回以上を検定しています。一様選択、重み付き選択、シャッフル、複数当選の各位置が対象です。公平性テストページでご自身でも試せます。
証明できないこと
日常の回転では、ブラウザで動いているコードが私たちの説明どおりのものだと信頼していただく必要があります。コードはすべてあなたの端末で動き、ブラウザの開発者ツールで確認できます。賞品や公開抽選など重要な場面では、誰も信用しなくて済む証明可能な公平抽選をお使いください。
よくある質問
ルーレットに細工はできますか?
アニメーションではできません。結果が先に公平に決まり、動きはそれを見せるように計算されます。確率を変えられるのは重み付きモードだけで、その場合は「重み付きルーレット」バッジが表示され、マスの大きさも確率どおりに描かれます。
同じ名前が2回続けて出たのはなぜ?
本物のランダムには連続があるからです。10項目なら、同じ項目が2回続くのは10%の確率です。各項目を1回ずつにしたいなら勝ち抜けモードを使ってください。
drandとは?
drandは、独立した大学・企業・団体からなるLeague of Entropyが運営する分散型の乱数ビーコンです。数秒ごとに、検証可能な新しい乱数を公開しています。