早押し判定
このページでは、クモノスが早押し順をどのように決めているかと、その精度をどう考えるべきかをまとめています。特に「精密な早押しクイズに使えるか」を判断したい方向けの内容です。
結論
クモノスは、各プレイヤー端末の押下時刻をブラウザ側で取得し、WebSocket でサーバーへ送って順位を決める方式です。 オンライン運用や、一般的なイベント運営で使う早押しとしては十分実用的ですが、専用ハードウェアの早押し機のように「数ミリ秒単位で厳密保証された判定」を目的とした設計ではありません。
どのタイミングを使って判定しているか
プレイヤー画面でボタンが押されると、その端末はブラウザの高精度タイマーを使って押下時刻を作り、サーバー時刻へ補正した値を送信します。 サーバー側ではその値をそのまま採用するのではなく、受信時刻との差が不自然に大きくないかを確認し、妥当な範囲なら押下時刻を、そうでなければサーバー受信時刻を使います。
- クライアント側の押下時刻は `performance.timeOrigin + performance.now()` を基準に生成し、定期的な時刻同期でサーバー時刻へ寄せています。
- サーバーは受信時刻も同時に記録し、最終的には 判定用時刻 と 受信時刻 の両方を保持します。
- 順位はまず判定用時刻の早い順、同値なら受信時刻の早い順で決まります。
時刻同期の考え方
クモノスは WebSocket 接続後に Ping / Pong を複数回送り、クライアントとサーバーの時刻差を推定します。 その中で最も RTT が小さかった結果を使って補正するため、回線が安定しているほど押下時刻は実際の押下に近づきます。
- 接続直後は 0ms、80ms、160ms の 3 回で同期を行います。
- その後も 5 秒ごとに再同期します。
- クライアントからは、押下時刻に加えて、その時点での最良 RTT もサーバーへ送っています。
受理される押下時刻の範囲
クライアントが送った押下時刻は、サーバー受信時刻との差が一定範囲内にある場合だけ採用されます。 この許容幅は固定ではなく、最新の最良 RTT をもとに自動調整されます。
- 許容幅はおおむね RTT の半分 + 10ms を基準に計算されます。
- ただし下限は 30ms、上限は 200ms に制限されています。
- RTT 情報が取れない場合は、120ms を暫定値として使います。
- この範囲を外れた押下時刻は信用せず、サーバー受信時刻で並べ替えます。
同時押しへの扱い
最初の押下が入った直後、クモノスは 20ms の短い回収ウィンドウを設けています。 その間に届いた押下をまとめて受け付けてから先着を確定するため、ほぼ同時の入力でも押下時刻順に整列しやすくしています。
- 最初の押下を受けると、20ms の収集時間が始まります。
- この間に届いた押下をいったんすべて `buzzOrder` に積みます。
- 収集終了後に最も早い人を回答者として確定します。
判定精度に影響する要素
- 端末性能 により、ボタンイベントがブラウザへ届くまでの遅れが変わります。
- ブラウザ差 により、タップ処理や描画負荷の影響が変わります。
- 通信品質 が悪いと、時刻同期の精度と受信時刻の安定性が下がります。
- 無線 LAN 環境 では、同じ会場内でも端末ごとに遅延の揺れが出ます。
- スマホ特有の省電力制御 やバックグラウンド処理制限も、挙動に影響する可能性があります。
どの用途に向いているか
- イベント会場や配信で使う、実用的なオンライン早押し。
- 多少の通信差を許容しつつ、多人数を手軽に参加させたい企画。
- MOD や表示演出を含めて、進行全体を一体で管理したい用途。
どの用途には慎重になるべきか
- 公式戦レベルで、数 ms 単位の先着差を厳密に競いたい用途。
- 端末や回線条件を統一できず、厳密な公平性を最重要視する大会用途。
- 専用早押し機と同等のハードウェア保証を前提にした運用。
精密な早押しをしたい場合の考え方
「かなり精密にやりたいが、専用機までは使わない」という場合は、同一ネットワーク・同系統端末・同一ブラウザで揃えるだけでも差はかなり減らせます。 一方で、クモノスはネットワーク越しの Web アプリである以上、端末イベント処理と通信遅延の揺れを完全には消せません。
- 同一会場の安定した LAN を使う。
- できるだけ同じ種類の端末とブラウザを使う。
- 本番前に同時押しテストを複数回行い、体感差を確認する。
- 厳密性が最優先なら、専用ハードウェア方式を検討する。