Spaces:
Runtime error
Runtime error
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>FlowTwin — Crowd Race Control</title> | |
| <link rel="preconnect" href=""> | |
| <link rel="stylesheet" href="css/app.css"> | |
| <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='6' fill='%230a0d12'/><path d='M6 22 L14 10 L18 16 L26 6' stroke='%23e10600' stroke-width='3' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>"> | |
| </head> | |
| <body> | |
| <header class="topbar"> | |
| <div class="brand"> | |
| <div class="brand-mark" aria-hidden="true"><span></span><span></span><span></span></div> | |
| <div class="brand-text"> | |
| <strong>FLOWTWIN</strong> | |
| <span>Crowd Race Control</span> | |
| </div> | |
| </div> | |
| <nav class="scenario-switch" id="scenario-switch" aria-label="Scenario"></nav> | |
| <div class="topbar-right"> | |
| <div class="status-chip" id="phase-chip"> | |
| <label>Phase</label><strong id="phase-label">—</strong> | |
| </div> | |
| <div class="status-chip clock"> | |
| <label>Event clock</label><strong id="clock">T+00:00</strong> | |
| </div> | |
| <div class="transport"> | |
| <button class="btn-icon" id="btn-play" title="Play / pause" aria-label="Play or pause"> | |
| <svg viewBox="0 0 16 16" class="ico-play" aria-hidden="true"><path d="M4 2.5 13 8l-9 5.5z"/></svg> | |
| <svg viewBox="0 0 16 16" class="ico-pause" aria-hidden="true"><path d="M4 2.5h3v11H4zM9 2.5h3v11H9z"/></svg> | |
| </button> | |
| <div class="speed-group" id="speed-group" role="group" aria-label="Simulation speed"></div> | |
| </div> | |
| <button class="btn-ghost sm" id="btn-perception" title="Hugging Face crowd perception">Perception</button> | |
| <div class="status-chip conn" id="conn-chip" title="Live state stream"> | |
| <span class="dot" id="conn-dot"></span><strong id="conn-label">offline</strong> | |
| </div> | |
| </div> | |
| </header> | |
| <main class="layout"> | |
| <!-- ───────────────────────── left rail ───────────────────────── --> | |
| <aside class="rail rail-left" id="rail-left"> | |
| <section class="panel" id="briefing-panel"> | |
| <header class="panel-head"> | |
| <h2>Scenario</h2> | |
| <span class="tag" id="venue-kind">—</span> | |
| </header> | |
| <div class="panel-body"> | |
| <h3 class="scenario-name" id="scenario-name">—</h3> | |
| <p class="scenario-headline" id="scenario-headline"></p> | |
| <ul class="briefing" id="briefing-list"></ul> | |
| <dl class="kv" id="run-config"></dl> | |
| </div> | |
| </section> | |
| <section class="panel" id="whatif-panel"> | |
| <header class="panel-head"> | |
| <h2>What-if</h2> | |
| <button class="btn-ghost sm" id="btn-reset-whatif">Reset</button> | |
| </header> | |
| <div class="panel-body"> | |
| <div class="field"> | |
| <label for="in-crowd">Attendance <output id="out-crowd"></output></label> | |
| <input type="range" id="in-crowd" min="5000" max="120000" step="1000"> | |
| </div> | |
| <div class="field"> | |
| <label for="in-ramp">Departure window <output id="out-ramp"></output></label> | |
| <input type="range" id="in-ramp" min="180" max="2400" step="60"> | |
| </div> | |
| <div class="field"> | |
| <label for="in-compliance">Reroute compliance <output id="out-compliance"></output></label> | |
| <input type="range" id="in-compliance" min="20" max="120" step="5"> | |
| </div> | |
| <div class="field" id="capacity-field"> | |
| <label for="in-capacity"><span id="capacity-label">Exit capacity</span> <output id="out-capacity"></output></label> | |
| <input type="range" id="in-capacity" min="20" max="150" step="5"> | |
| </div> | |
| <div class="field"> | |
| <label for="in-seed">Random seed</label> | |
| <div class="seed-row"> | |
| <input type="number" id="in-seed" step="1"> | |
| <button class="btn-ghost sm" id="btn-reseed" title="New seed">↻</button> | |
| </div> | |
| </div> | |
| <div class="field"> | |
| <label for="in-policy">Baseline routing</label> | |
| <select id="in-policy"> | |
| <option value="shortest_path">Shortest path</option> | |
| <option value="static_assignment">Static assignment</option> | |
| <option value="flowtwin_adaptive">FlowTwin adaptive</option> | |
| </select> | |
| </div> | |
| <button class="btn-primary block" id="btn-run">Run simulation</button> | |
| <p class="hint" id="whatif-hint">Every run is reproducible from its seed and configuration.</p> | |
| </div> | |
| </section> | |
| <section class="panel" id="timeline-panel"> | |
| <header class="panel-head"><h2>Event timeline</h2></header> | |
| <div class="panel-body"> | |
| <ol class="timeline" id="timeline-list"></ol> | |
| </div> | |
| </section> | |
| <section class="panel" id="provenance-panel" hidden> | |
| <header class="panel-head"> | |
| <h2>Evidence & assumptions</h2> | |
| <span class="tag warn">Reconstruction</span> | |
| </header> | |
| <div class="panel-body"> | |
| <p class="disclaimer" id="prov-disclaimer"></p> | |
| <div class="prov-group"> | |
| <h4><span class="pill fact">Documented</span></h4> | |
| <ul class="prov-list" id="prov-facts"></ul> | |
| </div> | |
| <div class="prov-group"> | |
| <h4><span class="pill assume">Modelled</span></h4> | |
| <ul class="prov-list" id="prov-assumptions"></ul> | |
| </div> | |
| </div> | |
| </section> | |
| </aside> | |
| <!-- ───────────────────────── centre: the map ───────────────────────── --> | |
| <section class="stage"> | |
| <div class="map-shell"> | |
| <canvas id="map" aria-label="Venue digital twin"></canvas> | |
| <div class="map-overlay map-title"> | |
| <strong id="venue-name">—</strong> | |
| <span id="venue-subtitle"></span> | |
| </div> | |
| <div class="map-overlay map-layers" id="layer-toggles" role="group" aria-label="Map layers"></div> | |
| <div class="map-overlay map-legend"> | |
| <div class="legend-row" id="legend-density"></div> | |
| <div class="legend-note">Mean corridor density · p/m²</div> | |
| </div> | |
| <div class="map-overlay map-scale" id="map-scale"><span></span><label>100 m</label></div> | |
| <div class="tooltip" id="map-tooltip" hidden></div> | |
| <div class="map-flash" id="map-flash" hidden></div> | |
| <div class="map-empty" id="map-empty"> | |
| <h3>No simulation running</h3> | |
| <p>Choose a scenario and press <strong>Run simulation</strong>.</p> | |
| </div> | |
| </div> | |
| <div class="metrics-strip" id="metrics-strip"></div> | |
| </section> | |
| <!-- ───────────────────────── right rail ───────────────────────── --> | |
| <aside class="rail rail-right"> | |
| <section class="panel alerts-panel"> | |
| <header class="panel-head"> | |
| <h2>Alerts</h2> | |
| <span class="tag" id="alert-count">0</span> | |
| </header> | |
| <div class="panel-body tight" id="alerts-list"> | |
| <p class="empty">Network nominal.</p> | |
| </div> | |
| </section> | |
| <section class="panel prediction-panel"> | |
| <header class="panel-head"> | |
| <h2>Prediction</h2> | |
| <span class="tag" id="pred-source" title="">—</span> | |
| </header> | |
| <div class="panel-body tight"> | |
| <div id="prediction-list"></div> | |
| <button class="btn-ghost block sm" id="btn-pred-detail">Model accuracy</button> | |
| </div> | |
| </section> | |
| <section class="panel strategy-panel"> | |
| <header class="panel-head"> | |
| <h2>Strategy</h2> | |
| <span class="tag" id="strategy-state">idle</span> | |
| </header> | |
| <div class="panel-body"> | |
| <button class="btn-primary block" id="btn-simulate">Simulate strategies</button> | |
| <p class="hint" id="strategy-hint"> | |
| Clones the current crowd state, applies each candidate to an identical | |
| copy and simulates forward. | |
| </p> | |
| <div id="recommendation-card"></div> | |
| </div> | |
| </section> | |
| </aside> | |
| </main> | |
| <!-- ───────────────────────── strategy drawer ───────────────────────── --> | |
| <section class="drawer" id="drawer" hidden aria-label="Strategy simulator"> | |
| <header class="drawer-head"> | |
| <div> | |
| <h2>Strategy simulator</h2> | |
| <p id="drawer-sub"></p> | |
| </div> | |
| <div class="drawer-actions"> | |
| <button class="btn-ghost sm" id="btn-drawer-collapse">Hide</button> | |
| </div> | |
| </header> | |
| <div class="drawer-body"> | |
| <div class="drawer-col drawer-table"> | |
| <table class="strategy-table" id="strategy-table"> | |
| <thead></thead> | |
| <tbody></tbody> | |
| </table> | |
| <p class="table-note" id="table-note"></p> | |
| </div> | |
| <div class="drawer-col drawer-why"> | |
| <h3>Why this strategy?</h3> | |
| <div id="why-panel"></div> | |
| </div> | |
| <div class="drawer-col drawer-chart"> | |
| <h3>Projected density at the bottleneck</h3> | |
| <canvas id="strategy-chart"></canvas> | |
| <div class="chart-legend" id="chart-legend"></div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ───────────────────────── modal ───────────────────────── --> | |
| <div class="modal-backdrop" id="modal" hidden> | |
| <div class="modal-card" role="dialog" aria-modal="true" aria-labelledby="modal-title"> | |
| <header><h2 id="modal-title">—</h2><button class="btn-icon" id="modal-close" aria-label="Close">✕</button></header> | |
| <div class="modal-body" id="modal-body"></div> | |
| </div> | |
| </div> | |
| <div class="toasts" id="toasts" aria-live="polite"></div> | |
| <script type="module" src="js/app.js"></script> | |
| </body> | |
| </html> | |