Skip to content

pzkko: virtual, le scommesse sul campionato di calcio inventato - #14

Merged
albertoxpecchini merged 12 commits into
mainfrom
pzkko/virtual
Oct 23, 2026
Merged

albertoxpecchini merged 12 commits into
mainfrom
pzkko/virtual

Conversation

@albertoxpecchini

Copy link
Copy Markdown
Owner

Il nuovo gioco di pzkko.it, games/virtual/, nella stessa finestra degli altri (volantino arancio in fondo al muro, #virtual lo apre subito).

Cosa c'è

  • Un campionato infinito a cicli di cinque minuti allineati all'orologio: quattro minuti di scommesse, un minuto di partita in diretta (90' + recupero in 60 s). Tutto è deciso dall'indice Math.floor(Date.now() / 300000) con un generatore seminato: due schede vedono la stessa partita allo stesso secondo (provato), chi arriva a metà la vede dal punto giusto.
  • Le 40 squadre di A e B 2026/27 coi nomi storpiati (Juvenclub, Inder, Napule, Atalanto, Mantua…), stemmi originali in SVG, cognomi inventati, forza da 1 a 100 presa dalla realtà.
  • Le quote copiano la Serie A vera, i risultati no: quote da bookmaker dalla forza (margine 6,5%, mai sotto 1,05, 1 X 2 al 106,5%), risultato da una Poisson di media fissa 1,35 a squadra che non legge le squadre. Rara la vittoria a tavolino (nebbia, nutrie, blackout).
  • Puntate 1 X 2 e over/under 1,5 · 2,5 · 3,5 · 4,5 con le fiches dei $pzk; la schedina resta nel browser e si paga al fischio finale anche a finestra chiusa.
  • Lo schermino a pixel (un canvas 192 × 120 per un fattore intero, pixel netti anche sul telefono): campo a cinque, omini con le maglie, tifosi, telecamera con inerzia e zoom, rigori da dietro la porta, replay del gol, cartellini, barella, meteo coerente col clima della città e luce dell'ora vera (riflettori di notte). Si ferma a scheda nascosta o finestra chiusa; con prefers-reduced-motion telecamera ferma.
  • Suoni sintetizzati (fischietto, boato, «uuuh» del palo, fiche, vincita), spenti se il suono è spento; nella regia si provano.
  • README aggiornato; tools/pzkko/virtual/prova.mjs simula le partite senza browser.

Come provarlo

cd albertopecchini.it && npm install && npm run dev:pzkko

poi http://localhost:5182/#virtual (anche da telefono sulla rete di casa). Aspettare un ciclo intero: le scommesse si chiudono al minuto 4 del ciclo di 5, la partita dura un minuto, al cambio di ciclo si paga. Due schede aperte devono dire lo stesso punteggio.

La simulazione: node tools/pzkko/virtual/prova.mjs 5000 → nessun errore; correlazione forza ↔ quota dell'1 −0,77 (le quote seguono la forza), forza ↔ differenza gol +0,01 e quota ↔ «la casa vince» 0,00 (i risultati no); con una favorita netta vince la favorita il 38,8%, la sfavorita il 35,7% (chi quadro p = 0,54); gol a squadra media 1,36, varianza 1,37.

Nota: le foto dei volantini per la scena 3D (art/scena/vol*) sono state rifatte solo per il foglio nuovo (su questa macchina mancano i caratteri veri e le altre venivano diverse): al prossimo serranda.mjs rifai sul PC di Alberto si allineano tutte.


Generated by Claude Code

La specifica di Alberto per il nuovo gioco: il campionato infinito a cicli di cinque minuti, le squadre
storpiate, le quote che seguono la forza vera e i risultati a caso, lo schermino da tamagotchi.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015VZM7WrmYAstfLRGvRUqFy
- partita.js: il calendario a cicli di cinque minuti allineati all'orologio (quattro di scommesse, uno di
  diretta), tutto dal seme dell'indice Math.floor(Date.now() / 300000): squadre, quote, meteo, formazioni e la
  cronaca minuto per minuto. Le quote dalla forza vera (gol attesi, due Poisson, margine 6,5%, mai sotto 1,05,
  1 X 2 al 106,5%), il risultato da un altro seme con una Poisson di media fissa 1,35: la sfavorita vince quanto
  la favorita. Una su 120 a tavolino, per nebbia, nutrie o blackout
- squadre.js: le quaranta di A e B 2026/27 coi nomi storpiati (Juvenclub, Inder, Napule, Mantua…), colori,
  forza, stemmi originali in SVG e cognomi inventati
- schermo.js: lo schermino a pixel (192 × 120 per un fattore intero, pixelated): il campo a cinque, gli omini con
  le maglie, i tifosi che saltano, la telecamera con inerzia e zoom, i rigori da dietro la porta, il replay del
  gol, i cartellini, la barella, il meteo coerente col clima della città e la luce dell'ora vera
- virtual.js e virtual.css: la finestra come gli altri giochi, le quote stampate, la schedina salvata nel browser
  e pagata al fischio finale anche a finestra chiusa, i $pzk sul tavolo di pzk.js
- tools/pzkko/virtual/prova.mjs: 5.000 partite senza browser, nessun errore (quote ↔ forza −0,77; forza ↔ gol
  +0,01; favorita netta vince il 38,8%, la sfavorita il 35,7%, p = 0,54)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015VZM7WrmYAstfLRGvRUqFy
Il foglio arancio in fondo alla quinta colonna (sul telefono alla prima), col titolo in Bungee e il pallone a
pixel disegnato in SVG (art/virtual/pallone.svg, niente immagini generate); #virtual lo apre subito e il codice si
precarica passando sul foglio. La parete cresce di poco (3355 e 5691 unità), la 404 e la storia rifatte, le foto
del volantino per la scena 3D (solo le sue: le altre non sono state rifatte).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015VZM7WrmYAstfLRGvRUqFy
Il fischietto dell'arbitro, il boato del gol, l'«uuuh» del palo, la fiche posata e la vincita a 8 bit, sintetizzati
come il resto della strada (voci.js), dagli eventi virtual-* (suono.js); si provano dalla regia e da
ascolta.mjs strumenti virtual (rms −26 dBFS, picco −10,6).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015VZM7WrmYAstfLRGvRUqFy
La voce games/virtual/ nell'elenco dei file, la sezione «Virtual» (il calendario, le squadre, le quote vere e i
risultati a caso, lo schermino, i suoni, le prove coi numeri del 23.10) e il suono nella regia.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015VZM7WrmYAstfLRGvRUqFy
@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
albertopecchini.it Ready Ready Preview Oct 23, 2026 2:57pm UTC
bcp Ready Ready Preview Oct 23, 2026 2:57pm UTC
pzkko Ready Ready Preview Oct 23, 2026 2:57pm UTC

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T12:09:47.327100Z d33bad3 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d33bad3f05

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (!grande(e)) continue
e.t = T.fine - 1.4
// i grandi di prima arretrano, a catena, finché stanno a 3,2 s
for (let j = sistemati.length - 1, lim = e.t; j >= 0; j--) { const g = sistemati[j]; if (!grande(g)) continue; if (g.t > lim - 3.2) g.t = lim - 3.2; lim = g.t }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep overflowed events out of halftime

When a dense late-match sequence hits this rollback, it repositions preceding large events without rerunning the halftime exclusion. For example, partita(3836) produces a goal at 29.8s, inside the ripresa overlay (29.5–30.5s); scenaPartita selects the earlier restart event first, so the score changes but that goal's animation and sound are skipped. This also makes node tools/pzkko/virtual/prova.mjs 5000 --da=0 fail its halftime-event check.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corretto in 869fe1b (non ancora pushato): l'arretramento a catena dei grandi eventi ora li riporta prima dell'intervallo se ci finiscono dentro. prova.mjs 5000 --da=0 ora passa (partita 3836 compresa).


Generated by Claude Code

}

function punta(id) {
if (corrente.fase !== 'scommesse') { voce('la partita è in corso: si punta sulla prossima'); return }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recheck the clock before accepting a bet

With prefers-reduced-motion, the render loop refreshes corrente only every 500ms, so a quote can remain enabled after the four-minute betting deadline and this cached-phase check still accepts a click. That records a wager for a game already in progress; consult the current fase() at submission time rather than relying on the last render tick.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corretto in 869fe1b (non ancora pushato): punta() e togli() rileggono fase() dall'orologio vero prima di accettare la puntata, quindi a scommesse chiuse non passa più niente anche col movimento ridotto.


Generated by Claude Code

if (s && Array.isArray(s.ultime)) stato.ultime = s.ultime
} catch {}
}
function salva() { try { localStorage.setItem(CHIAVE, JSON.stringify({ schedina: stato.schedina, ultime: stato.ultime })) } catch {} }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Merge concurrent ticket updates

If Virtual is open in two tabs and both tabs place a bet before the other tab's storage event is processed, each starts from the same schedina snapshot and writes its whole array here. The last write drops the other bet even though pzk.punta() already moved its stake; subsequent reconciliation then settles the surviving selection instead. Merge or serialize updates so simultaneous cross-tab bets cannot overwrite one another.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corretto in 869fe1b (non ancora pushato): punta() e togli() rileggono la schedina da localStorage subito prima di scriverla, come già faceva paga(), così la puntata dell'altra scheda non si perde.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aggiornamento: rileggere prima di scrivere non bastava con due clic nello stesso istante (provato con due schede). In c6fb233 (non ancora pushato) salva() e l'evento storage uniscono le due schedine fiche per fiche (timbro unico per fiche, timbri delle fiches tolte tenuti a parte), così nessuna puntata si perde: 20 clic simultanei da due schede danno 100 $pzk in entrambe, e un «togli» le porta a 95 in entrambe.


Generated by Claude Code

Comment on lines +353 to +354
const f = pzk.inFiches(b.puntata)
const v = f[f.length - 1]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the chip that was actually placed last

A selection aggregates all of its chips into one amount, then this rebuilds that amount in descending denominations and removes the smallest reconstructed chip rather than the last chip placed. For example, placing 1 and then 500 on the same outcome yields 501, and togli refunds 1 instead of the last 500; preserve placement order or avoid aggregating the chips.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corretto in 7a3ffba (non ancora pushato): ogni fiche si salva come [valore, timbro] nell'ordine in cui è posata, e «togli» ritira l'ultima posata su qualunque quota (provato: 1 sull'1, 5 sulla X, 500 sull'1, poi tre «togli» restituiscono 500, 5, 1).


Generated by Claude Code

games/virtual/schedina.js: le puntate nel browser (pzkko-virtual), il tavolo dei $pzk, «togli», il pagamento, le
partite scadute e l'unione fra schede (fiches [valore, timbro], «tolte») escono da virtual.js, senza cambiare
comportamento, così l'app del cercapersone usa la stessa schedina. Una copia per pagina: le interfacce si avvisano con
ascolta(), le altre schede via storage. In più «vista» sulle puntate pagate, per il pallino del cercapersone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015VZM7WrmYAstfLRGvRUqFy
Alberto: «il gioco dovrebbe essere anche dentro al cercapersone: fai app sul cercapersone». telefono/app/virtual.js:
la stessa partita del gioco grande sullo stesso schermino a pixel (partita.js, schermo.js), il tabellone col conto alla
rovescia e i cartellini, le quote 1 X 2 e over/under, le fiches, la schedina con gli esiti, il tasto «gioco grande»;
scommesse e pagamenti dalla stessa schedina della finestra (schedina.js) e dagli stessi $pzk. Sullo schermo largo lo
schermino a sinistra e il banco a destra, sul cellulare in colonna. Il pallino: le vincite non viste o le scommesse
aperte che chiudono entro un minuto; in chat il comando «virtual». La piastrella (art/chat-app2/app-virtual.webp) è
disegnata a mano in SVG da tools/pzkko/virtual/icona.mjs, da rigenerare con gpt-image-2 (foglio chat-app2 in
fogli-chat.js).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015VZM7WrmYAstfLRGvRUqFy
Conflitti in chat/icone.js e telefono/telefono.css: tenute tutte e due le aggiunte
(chat-app2 per virtual, chat-miniera per la miniera; gli stili .t-vi-* e .t-mn-*).
L'app virtual usa anche telefono/ricordi.js (la schedina resta dov'era) e i numeri
corti di games/pzk.js nel saldo.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015VZM7WrmYAstfLRGvRUqFy

This branch was successfully deployed

6 active deployments
Production – albertopecchini.it — 9c4bd42b Deployed Oct 23, 2026 by vercel[bot]
Production – pzkko — 9c4bd42b Deployed Oct 23, 2026 by vercel[bot]
Production – bcp — 9c4bd42b Deployed Oct 23, 2026 by vercel[bot]
Preview – pzkko — 9c4bd42b Deployed Oct 23, 2026 by vercel[bot]
Preview – albertopecchini.it — 9c4bd42b Deployed Oct 23, 2026 by vercel[bot]
Preview – bcp — 9c4bd42b Deployed Oct 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants