Download scripts/scansione.html from amogaddy/neuronal: direct link, hf CLI and curl.
- Browser
- Download file 8.36 kB
-
https://huggingface.co/spaces/amogaddy/neuronal/resolve/main/scripts/scansione.html
- Command line
-
hf download hf://spaces/amogaddy/neuronal/scripts/scansione.html
-
curl -L -o scansione.html https://huggingface.co/spaces/amogaddy/neuronal/resolve/main/scripts/scansione.html
8.36 kB
| <html lang="it"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>Scansione dei livelli</title> | |
| <style> | |
| :root { | |
| --bg: #0b0f14; --panel: #131a22; --line: #24303c; --text: #e6edf3; --muted: #8b9aa9; | |
| --accent: #3ddc97; --warn: #f2c14e; --bad: #ef6461; --run: #5aa9ff; | |
| } | |
| @media (prefers-color-scheme: light) { | |
| :root:not([data-theme="dark"]) { --bg: #f4f6f8; --panel: #fff; --line: #d8dee4; --text: #1b2733; --muted: #5f6f7e; --accent: #1f9d68; --warn: #b7791f; --bad: #c53030; --run: #2b6cb0; } | |
| } | |
| * { box-sizing: border-box; } | |
| body { margin: 0; background: var(--bg); color: var(--text); font: 15px/1.5 system-ui, "Segoe UI", sans-serif; } | |
| main { max-width: 980px; margin: 0 auto; padding: 24px 16px 48px; } | |
| h1 { font-size: 22px; margin: 0 0 4px; letter-spacing: .02em; } | |
| .sub { color: var(--muted); margin: 0 0 20px; } | |
| .card { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 16px; margin-bottom: 16px; } | |
| .row { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; justify-content: space-between; } | |
| .msg { font-weight: 600; } | |
| .bar { height: 10px; background: var(--line); border-radius: 6px; overflow: hidden; margin: 12px 0 6px; } | |
| .bar > i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .4s; } | |
| .bar.q > i { background: var(--run); } | |
| .nums { display: flex; gap: 20px; flex-wrap: wrap; color: var(--muted); font-size: 13px; } | |
| .nums b { color: var(--text); font-variant-numeric: tabular-nums; } | |
| .grid { display: grid; grid-template-columns: repeat(16, 1fr); gap: 5px; } | |
| .cell { aspect-ratio: 1; border-radius: 6px; background: var(--line); display: flex; align-items: center; justify-content: center; | |
| font-size: 11px; color: var(--muted); position: relative; } | |
| .cell.done { color: #0b0f14; font-weight: 700; } | |
| .cell.skip { opacity: .35; } | |
| .cell.now { outline: 2px solid var(--run); color: var(--text); animation: pulso 1.1s ease-in-out infinite; } | |
| @keyframes pulso { 50% { outline-color: transparent; } } | |
| .legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12px; color: var(--muted); margin-top: 10px; } | |
| .legend span::before { content: ""; display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; background: var(--c); } | |
| table { width: 100%; border-collapse: collapse; font-size: 14px; } | |
| th, td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line); } | |
| th { color: var(--muted); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .05em; } | |
| td.n { font-variant-numeric: tabular-nums; } | |
| td.ex { color: var(--muted); max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } | |
| .mini { display: inline-block; height: 8px; border-radius: 4px; vertical-align: middle; } | |
| button { font: inherit; background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: 8px; padding: 8px 14px; cursor: pointer; } | |
| button:hover:not(:disabled) { border-color: var(--bad); color: var(--bad); } | |
| button:disabled { opacity: .5; cursor: default; } | |
| .note { color: var(--muted); font-size: 13px; } | |
| .good { color: var(--accent); } | |
| </style> | |
| </head> | |
| <body> | |
| <main> | |
| <h1>Scansione dei livelli</h1> | |
| <p class="sub">Spegne un livello alla volta del cervello e misura quanto cambiano le risposte. Tutto sul tuo computer.</p> | |
| <section class="card"> | |
| <div class="row"> | |
| <div class="msg" id="msg">Avvio…</div> | |
| <button id="stop" type="button">Ferma (salva il lavoro)</button> | |
| </div> | |
| <div class="bar"><i id="bar-tot"></i></div> | |
| <div class="nums"> | |
| <span>Livelli <b id="n-fatti">0</b> / <b id="n-tot">0</b></span> | |
| <span>Trascorso <b id="t-trasc">0 s</b></span> | |
| <span>Mancano circa <b id="t-manca">—</b></span> | |
| <span>Livello <b id="n-liv">—</b></span> | |
| </div> | |
| <div class="bar q"><i id="bar-q"></i></div> | |
| <div class="nums"><span>Domanda <b id="n-q">0</b> / <b id="n-qt">0</b></span></div> | |
| </section> | |
| <section class="card"> | |
| <div class="grid" id="grid"></div> | |
| <div class="legend"> | |
| <span style="--c:var(--accent)">si può togliere (≥ 0.90)</span> | |
| <span style="--c:var(--warn)">costa un po' (0.60–0.90)</span> | |
| <span style="--c:var(--bad)">importante (< 0.60)</span> | |
| <span style="--c:var(--run)">in corso</span> | |
| </div> | |
| </section> | |
| <section class="card"> | |
| <table> | |
| <thead><tr><th>Livello</th><th>Punteggio</th><th></th><th>Identiche</th><th>Prima risposta senza il livello</th></tr></thead> | |
| <tbody id="tab"></tbody> | |
| </table> | |
| <p class="note" id="esito"></p> | |
| <p class="note" id="nota">Qui si spegne solo la parte FFN del livello. Togliere il livello intero (anche l'attenzione) costa uguale o di più: | |
| la tabella è un limite ottimistico, da riverificare su un modello davvero accorciato.</p> | |
| </section> | |
| </main> | |
| <script> | |
| const $ = (id) => document.getElementById(id); | |
| const fmt = (s) => s == null ? '—' : s < 60 ? `${Math.round(s)} s` : s < 3600 ? `${Math.floor(s / 60)} min ${String(Math.round(s % 60)).padStart(2, '0')} s` : `${Math.floor(s / 3600)} h ${String(Math.floor(s % 3600 / 60)).padStart(2, '0')} min`; | |
| const colore = (p) => p >= 0.9 ? 'var(--accent)' : p >= 0.6 ? 'var(--warn)' : 'var(--bad)'; | |
| function disegna(s) { | |
| $('msg').textContent = s.messaggio; | |
| const fatti = s.tutti.filter((l) => String(l) in s.livelli).length; | |
| $('n-fatti').textContent = fatti; $('n-tot').textContent = s.tutti.length; | |
| $('bar-tot').style.width = (s.tutti.length ? 100 * fatti / s.tutti.length : 0) + '%'; | |
| $('t-trasc').textContent = fmt(s.trascorso); | |
| $('t-manca').textContent = s.fase === 'scansione' ? fmt(s.mancano) : '—'; | |
| $('n-liv').textContent = s.livello == null ? '—' : s.livello; | |
| $('n-q').textContent = s.domanda; $('n-qt').textContent = s.domande; | |
| $('bar-q').style.width = (s.domande ? 100 * s.domanda / s.domande : 0) + '%'; | |
| $('stop').disabled = s.finito || s.ferma || s.fase === 'finito' || s.fase === 'fermato' || s.fase === 'errore'; | |
| const grid = $('grid'); | |
| const celle = Array.from({ length: 64 }, (_, i) => i); | |
| if (grid.children.length !== 64) { | |
| grid.replaceChildren(...celle.map((i) => { const d = document.createElement('div'); d.textContent = i; return d; })); | |
| } | |
| celle.forEach((i) => { | |
| const c = grid.children[i], r = s.livelli[String(i)], inLista = s.tutti.includes(i); | |
| c.className = 'cell' + (r ? ' done' : '') + (!inLista ? ' skip' : '') + (s.livello === i ? ' now' : ''); | |
| c.style.background = r ? colore(r.punteggio) : ''; | |
| c.title = r ? `livello ${i}: punteggio ${r.punteggio.toFixed(2)}` : `livello ${i}`; | |
| }); | |
| const righe = Object.entries(s.livelli).sort((a, b) => b[1].punteggio - a[1].punteggio); | |
| $('tab').replaceChildren(...righe.map(([l, r]) => { | |
| const tr = document.createElement('tr'); | |
| const cella = (t, cls) => { const td = document.createElement('td'); if (cls) td.className = cls; td.textContent = t; return td; }; | |
| const barra = document.createElement('td'); | |
| const m = document.createElement('i'); m.className = 'mini'; m.style.width = Math.round(r.punteggio * 90) + 'px'; m.style.background = colore(r.punteggio); | |
| barra.append(m); | |
| tr.append(cella(l, 'n'), cella(r.punteggio.toFixed(2), 'n'), barra, cella(`${r.identiche} / ${s.domande}`, 'n'), cella(r.esempio || '', 'ex')); | |
| return tr; | |
| })); | |
| if (s.fase === 'finito') { | |
| const ok = righe.filter(([, r]) => r.punteggio >= 0.9).map(([l]) => Number(l)).sort((a, b) => a - b); | |
| $('esito').innerHTML = `<b class="good">Candidati da togliere (≥ 0.90):</b> ${ok.length ? ok.join(', ') : 'nessuno'}.`; | |
| } | |
| } | |
| async function giro() { | |
| try { disegna(await (await fetch('/stato.json', { cache: 'no-store' })).json()); } | |
| catch { $('msg').textContent = 'La scansione si è chiusa. L\'ultimo risultato è nel file state/scansione-ablazione.json.'; $('stop').disabled = true; } | |
| setTimeout(giro, 1000); | |
| } | |
| $('stop').onclick = () => { $('stop').disabled = true; fetch('/ferma', { method: 'POST' }); }; | |
| giro(); | |
| </script> | |
| </body> | |
| </html> | |