Files
casino/cmd/arcade/static/index.html
drjones 2a2a1db8de feat: playable arcade — rooms, identity, client, deployment
Round length is now bounded: the multiplier follows a hyperbolic curve
diverging at 60s, replacing an exponential one where a 275x crash point
produced a two-and-a-half minute round.

Fixes seed reveal, which silently failed every round because pgx cannot
encode a fixed-size byte array as bytea.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 15:34:52 +00:00

142 lines
4.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Quantum Arcade</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<!-- Ornate background filigree, drawn once as an SVG pattern and tiled. -->
<svg class="filigree" aria-hidden="true">
<defs>
<pattern id="orn" width="120" height="120" patternUnits="userSpaceOnUse">
<g fill="none" stroke="currentColor" stroke-width="0.6">
<circle cx="60" cy="60" r="46"/>
<circle cx="60" cy="60" r="30"/>
<circle cx="60" cy="60" r="14"/>
<path d="M60 0 L60 120 M0 60 L120 60"/>
<path d="M17 17 L103 103 M103 17 L17 103"/>
<path d="M60 14 q26 22 0 46 q-26-24 0-46"/>
<path d="M14 60 q22 26 46 0 q-24-26-46 0"/>
</g>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#orn)"/>
</svg>
<header class="topbar">
<div class="brand">QUANTUM<span>ARCADE</span></div>
<div class="balance" id="balance-wrap" hidden>
<span class="label">balance</span>
<span class="value" id="balance"></span>
</div>
<button class="sound" id="sound-toggle" title="Ambient sound"></button>
</header>
<!-- Sign-in: a nickname and nothing else. -->
<section class="panel center" id="signin">
<h1>Enter the arcade</h1>
<p class="muted">
No account, no email, no password. Your device generates a key that
<em>is</em> your identity. Keep the device, keep the balance.
</p>
<input id="nickname" maxlength="20" placeholder="pick a name" autocomplete="off">
<button class="primary" id="enter">Enter</button>
<p class="fineprint" id="keynote"></p>
</section>
<main id="app" hidden>
<nav class="tabs">
<button class="tab active" data-view="crash">Crash</button>
<button class="tab" data-view="scratch">Scratchers</button>
<button class="tab" data-view="wallet">Wallet</button>
<button class="tab" data-view="verify">Verify</button>
</nav>
<!-- ============ CRASH ============ -->
<section class="view" id="view-crash">
<div class="gamepick" id="gamepick"></div>
<div class="stage">
<canvas id="canvas"></canvas>
<div class="readout">
<div class="multiplier" id="multiplier">1.00×</div>
<div class="state" id="state">connecting…</div>
</div>
</div>
<div class="controls">
<div class="stakerow">
<button class="chip" data-stake="1000">1</button>
<button class="chip" data-stake="5000">5</button>
<button class="chip" data-stake="25000">25</button>
<button class="chip" data-stake="100000">100</button>
<span class="unit">sats</span>
</div>
<button class="primary big" id="action">Place bet</button>
<div class="hint" id="hint"></div>
</div>
<div class="players" id="players"></div>
<details class="proof">
<summary>Fairness for this round</summary>
<div class="kv"><span>commitment</span><code id="commitment"></code></div>
<div class="kv"><span>revealed seed</span><code id="revealed">sealed until the round ends</code></div>
<p class="muted small">
The commitment is published before betting opens. The crash point is
derived from that seed combined with every player's key — so it cannot
be chosen after seeing who joined.
</p>
</details>
</section>
<!-- ============ SCRATCH ============ -->
<section class="view" id="view-scratch" hidden>
<div id="tickets"></div>
</section>
<!-- ============ WALLET ============ -->
<section class="view" id="view-wallet" hidden>
<div class="card">
<h2>Your key</h2>
<p class="muted small">Share this so friends can send you sats.</p>
<code class="pubkey" id="pubkey"></code>
<button id="copykey">Copy</button>
</div>
<div class="card">
<h2>Send sats</h2>
<input id="to-key" placeholder="recipient key" autocomplete="off">
<input id="send-amt" type="number" min="1" placeholder="amount in sats">
<button class="primary" id="send">Send</button>
<div class="hint" id="send-hint"></div>
</div>
<div class="card">
<h2>Every change to your balance</h2>
<div id="history" class="history"></div>
</div>
</section>
<!-- ============ VERIFY ============ -->
<section class="view" id="view-verify" hidden>
<div class="card">
<h2>Check any round</h2>
<p class="muted small">
Enter a round number. Your phone recomputes the outcome from the
published seeds — it does not take the server's word for anything.
</p>
<input id="verify-id" type="number" min="1" placeholder="round number">
<button class="primary" id="do-verify">Verify</button>
<div id="verify-out" class="verify-out"></div>
</div>
</section>
</main>
<script src="/app.js"></script>
</body>
</html>