Sizing konstanty (seat/standings/guess/totals) presunute do boardTheme.ts a farebne odlisenie tipu v PlayerCircle (nad tip = terakota).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Karta "Dokoncene hry" (%) nahradena dvomi poctami dokoncenych hier
podla toho, ci na niektorom sedadle sedel bot (username "bot:...").
Zaroven oprava serializacie avg_game_duration_minutes -- Postgres
vracia z func.avg Decimal, ktory json.dumps nevie serializovat (500
na /api/admin/stats).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hlavicka GameListu sa na uzkych displejoch nezmestila do jedneho
riadku. Pod sm: breakpointom sa polozky zbalia do dropdownu.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bot doteraz vedel zahodit prvu kartu novej kopky uz po BOT_MOVE_DELAY_SECONDS
(0.8s), zatial co frontend zmetaciu animaciu predoslej kopky prehraval
1650ms -- karta tak "vyletela" uprostred zmetania. _run_bot_turns teraz pri
vedeni novej kopky caka TRICK_SWEEP_SECONDS (1.7s), zhodne s SETTLE_MS+
COLLECT_MS v GameTable.tsx.
_run_bot_turns tiez posielal player_cards PRED game_status (opacne ako
human play_card handler) -- pri prechode do noveho kola tak klient dostal
novu ruku skor, nez vedel, ze zacalo nove kolo, a fixne ju hned zobrazil.
Poradie broadcastov je teraz zhodne s human handlerom.
GameTable/Hand: ruka noveho kola sa zobrazi az po dobehnuti zmetacej
animacie poslednej kopky predchadzajuceho kola (displayedHand + freeze
efekt), a Hand.tsx rezervuje fixny priestor pre karty aj ked je ruka
docasne prazdna, aby layout neposkakoval.
tests/test_bots.py: nulovanie TRICK_SWEEP_SECONDS v setUpClass, aby testy
zostali rychle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hostitel prida na volne sedadlo bota (+ Bot = heuristika, + AI bot =
natrenovana siet) alebo bota odoberie; boti maju vlastnu ikonu a flag
is_bot v rosteroch. Surove ucty bot:<kind>-<n> sa vsade zobrazuju cez
displayName ako "Bot 2" / "AI bot 1" (stol, kopka, tabulky, historia).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Zmetacia animacia doteraz dobehla len na konci kola/serie (dlha pauza) --
mid-round ju hned prerusila dalsia zahrata karta, lebo `finishing` zavisela
na activeCards === 0. Teraz drzi kopku v strede az do konca animacie a
zablokuje hranie karty, kym sa nezmetie; boot-guard zabrani falosnej
animacii pri reconnecte na uz rozohratu hru.
PlayerCircle: ovalne oramovanie mena teraz rastie s dlzkou mena
(fit-content + strop + ellipsis) namiesto pevnej sirky.
api: hra dohrata do konca (4 serie) sa hned vytrati z lobby zoznamu,
namiesto toho aby visela navzdy ako "Začatá"/"Pokračovať" aj ked uz ma
v DB ended_at.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zoznam kol v Standings (herny sidebar aj mobilny panel) pouzival hrubu
systemovu lavicu scrollbaru, ktora nesedela do velvet/gold temy. Novy
.velvet-scroll (index.css) da tenky priehladny track a zlaty polopriehladny
thumb (webkit + Firefox scrollbar-color).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Doteraz sa pri hodeni 4. karty cela kopka na frame stratila (displayedStash
padol na lingeredStash nastaveny az v useEffekte) a nasledne sa vsetky karty
znovu vlietli. Teraz sa previous_stash cita synchronne, takze posledna karta
len pribudne k trom uz leziacim, a potom sa cela kopka odsunie animaciou
smerom k sedadlu, ktore kopku vyhralo (stashWinner podla pravidiel enginu).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Standings.tsx rozdeleny na fixnu hlavicku, scrollovatelny zoznam kol
(overflow-y-auto, na mobile max-h-45vh) a fixne sucty, takze pri viacerych
odohratych kolach je vidno cely priebeh. Dokoncena seria (riadok Sigma) je
teraz klikatelna a zbaluje/rozbaluje svoje kola.
Zaroven zruseny line-through pri neuspesnom tipe v hernom pohlade aj v
detaile hry (History.tsx) -- neuspesny tip sa teraz len zobrazuje tlmenou farbou.
Ucet bez potvrdeneho kodu (auth_token is NULL a totp_last_step == 0)
uz neblokuje meno: opakovany register_account vyda novy secret (stary
QR prestane platit) a login vyhodi RegistrationIncomplete, na ktoru
server odpovie novym QR -- klient sa prepne na registracny tab.
Admin statistiky vykazuju nedokoncene registracie osobitne, Hraci
celkom pocita len potvrdene ucty. Novy event register v analytike.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Linka Na kavu v hlavicke lobby vedie na /donate. QR sa generuje
dynamicky (balicek bysquare) pre presety 1/2/5 EUR alebo vlastnu sumu;
IBAN sa da skopirovat do schranky. Navstevy loguje existujuci
pageview beacon.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Na /auth sa da dostat len plnym loadom stranky (vsetky interne
redirecty nan su REPLACE a beacon ich skipuje) a kazdy plny load uz
posiela event landing. Kazdy riadok /auth by tak mal dvojicku z toho
isteho loadu. Skip na frontende aj v _SKIPPED_PATHS (pokryje aj stare
cache-ovane verzie frontendu). Stare /auth riadky v DB ostavaju.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Navsteva zacinajuca na / (preklik z FB/Messengeru, natukanie domeny)
doteraz nezanechala v page_views ziadny zaznam: / je v skip liste
beaconu a gate redirect na /auth je REPLACE navigacia, takze sa skipli
oba hopy a referrer sa stratil. trackLanding() v main.tsx posle raz za
kazdy plny load stranky pomenovany event landing s document.referrer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pageview beacony uz neposielaju player_id z klienta (nedovereny vstup na
neautentifikovanom endpointe) -- prihlasenie sa eviduje server-side ako
event "login" (aj z registracie), s player_id skutocneho uctu. Admin
dashboard dostal prepinac scope vsetci/prihlaseni, ktory konzistentne
pocita grafy aj tabulky (kazdy login samostatne, navstevnicky den pre
anonymnu navstevnost). PageView.country teraz uklada cely anglicky nazov
krajiny namiesto ISO kodu (potrebna zmena schemy). Pridane sledovanie
klikov na "Pravidla hry" aj z GameList.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Records pageviews (path, referrer, browser/OS/device, IP, GeoIP country) via
a POST /api/track beacon into a new PageView table, and exposes aggregated
daily/breakdown stats behind a token-gated GET /api/admin/stats endpoint with
brute-force lockout. Frontend gets a /admin dashboard (charts + breakdown
tables) built on recharts, with a switchable per-day pageviews chart.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Frontend:
- Dark green/gold "velvet table" visual redesign across the whole app
(Auth, Lobby, GameList, GameTable, History, GameOver, modals), with
Playfair Display/DM Sans typography and a centralized Tailwind palette.
- Desktop game table fit-scales to fill the window; mobile gets
overlapping hand/trick layouts and larger touch-friendly cards.
- Standings sidebar now groups completed rounds by series with a
per-series subtotal row, struck-through tips on missed bids.
- History page rewritten into a scoreboard-style detail view (player
totals beside names, series grouped 2-up on desktop / stacked on
mobile) and gained game names, completed/abandoned status, and a
button to reopen a prematurely-ended game back into the lobby.
Backend:
- Fix started games being deleted from memory (and vanishing from
everyone's lobby) when all players disconnect; only `end_game` tears
down a started game now.
- Fix a crash writing a timezone-aware datetime into the naive
`ended_at` Postgres column.
- Add `reopen_game`/`restore_game` to un-end a prematurely-ended game
from history and resume it from the lobby.
- Let any seated player end an abandoned game once the host is
offline, not just the host, so the game isn't stuck forever.
- Expose SERIES_PER_GAME/ROUNDS_PER_SERIES as named constants on the
engine so the persistence layer derives game-completion rules from
bridzik.py instead of re-encoding them.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- db/ package: async SQLAlchemy engine + Player/Game/Guess models
- api/auth.py: passwordless TOTP login (pyotp), session token via socket auth
- api/history.py: record guesses/points, DB-backed standings, restore
unfinished games on startup, host-only end_game
- api/__init__.py: auth-gated handlers, accounts map, rejoin via account
- frontend: Auth (QR + code) and History pages, resume/end-game in lobby/table
- docker-compose: real PostgreSQL service wired via DATABASE_URL
- tests_history.py for the persistence/auth layer; refresh CLAUDE.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>