GitHub dává veřejným repozitářům běhouny ubuntu-24.04-arm zadarmo, takže je to jeden řádek do matice. Hodí se pro Raspberry Pi nebo jinou malou pořád zapnutou krabičku, což je rozumnější místo, kde tohle nechat běžet, než notebook, který se každý večer zapíná. x86-64 zůstává doma. Tam jde stavět proti staré glibc a když GitHub vypadne, release má pořád tu platformu, na které to reálně poběží. ARM je výjimka prostě proto, že doma na něm není na čem postavit.
9.7 KiB
Dice Counter
Doprovod k fyzickým kostkám: telefon zapisuje skóre, notebook ukazuje zápisník a hry se pamatují mezi večery.
Hráči se napříč hrami poznávají podle jména — Adam ze středečního večera je ten samý Adam jako z minulého měsíce. Žádné účty, žádná hesla.
Spuštění
Stáhni binárku pro svůj systém z releases:
| Systém | Soubor |
|---|---|
| Linux (x86-64) | kostky-linux-x86_64 |
| Linux (ARM64) | kostky-linux-arm64 |
| macOS (Apple Silicon) | kostky-macos-arm64 |
| macOS (Intel) | kostky-macos-x86_64 |
| Windows (x86-64) | kostky-windows-x86_64.exe |
Nic se neinstaluje — Python, Flask i šablony jsou uvnitř.
Na Linuxu a macOS:
chmod +x kostky-*
./kostky-linux-x86_64
Na Windows stačí na .exe poklepat.
Linuxová binárka je postavená proti glibc 2.17, takže jede prakticky všude.
Než to poprvé pustíš
Binárky nejsou podepsané — podpisové certifikáty stojí tisíce ročně a na počitadlo kostek by to byl nesmysl. Systémy si toho všimnou:
- macOS stažený soubor označí za karanténní a odmítne ho spustit. Buď
značku sundej (
xattr -dr com.apple.quarantine kostky-macos-arm64), nebo soubor stáhni rovnou z terminálu přescurl -LO— tudy se karanténa nenastavuje. - Windows ukáže modré okno SmartScreenu. Další informace → Přesto spustit. Občas si postěžuje i antivirus; u zabalených Python programů je to běžný falešný poplach. Při prvním spuštění se ještě zeptá brána firewall — bez povolení do místní sítě se telefon nepřipojí.
Kdo tomu nechce věřit, ověří si stažený soubor podle přiloženého součtu
(níž) nebo si ho postaví sám — ./build.sh, zdrojáky jsou tady celé.
Ze zdrojáků to je stejně krátké:
uv run web.py
Závislosti si skript nese v hlavičce (PEP 723) a uv je obstará sám.
Server vypíše všechny adresy, na kterých je dostupný:
Kostky v1.1.0
Počitadlo je dostupné na:
→ http://10.186.234.182:8000 místní síť
http://100.91.0.24:8000 přes Tailscale
http://172.17.0.1:8000 virtuální síť
Kterou verzi máš, řekne i kostky --version; visí taky v patičce každé
stránky. Když něco nefunguje, je to první věc, na kterou se zeptám.
Na notebooku otevři /board, naskenuj QR kód telefonem a hraj. Tabule
nabízí i zbylé adresy — když jedna nefunguje, klikni na jinou a QR kód se
přepne na ni. Zastavuje se Ctrl+C.
| Proměnná | K čemu je | Výchozí |
|---|---|---|
DICE_DB |
soubor s databází | podle způsobu spuštění, viz níž |
DICE_PORT |
port | 8000 |
DICE_HOST |
pevná adresa; vypne hledání | hledá se za běhu |
Kde jsou data
Jeden soubor SQLite. Založí se sám při prvním načtení stránky, cestu k němu server vypíše při startu.
| Spuštěno | Databáze |
|---|---|
| binárkou na Linuxu | ~/.local/share/kostky/dice.db |
| binárkou na macOS | ~/Library/Application Support/kostky/dice.db |
| binárkou na Windows | %LOCALAPPDATA%\kostky\dice.db |
| ze zdrojáků | dice.db v pracovním adresáři |
Binárka se při každém spuštění rozbaluje do dočasného adresáře a pouští se odkudkoli, takže relativní cesta by databázi rozsypala po disku — proto napevno domovský adresář. Ze zdrojáků zůstává relativní, ať se dá mít víc sad vedle sebe.
Zálohovat i stěhovat jde prostým zkopírováním souboru; DICE_DB si ho
najde kdekoli.
Schéma má verzi uloženou v PRAGMA user_version a storage.migrate() si
databázi při každém připojení dorovná. Starší soubory z verzí, kdy se verze
schématu ještě nepsala, se poznají podle nuly a orazítkují se. Databázi
založenou novější verzí počitadla appka odmítne otevřít, místo aby ji tiše
rozbila.
Obsluhuje to waitress — čistě pythonní WSGI server, který se zabalí do
binárky stejně snadno jako zbytek. Vestavěný server Flasku by pod úvodní
hlášku vysypal varování, že takhle se to nemá, a měl by pravdu.
Počítá se s domácí sítí — appka nemá přihlašování a kdokoli na stejné WiFi může zapisovat.
Když se telefon nepřipojí
Adresy se hledají při každém načtení tabule, takže přechod z domácí WiFi na hotspot a zpátky si tabule pohlídá sama a načte se znovu.
Zbývají tři důvody, proč se telefon nedostane na notebook:
- Telefon je na mobilních datech, notebook na WiFi. Různé sítě, nepotkají se. Připoj telefon na stejnou WiFi, nebo notebook na hotspot telefonu — to funguje taky.
- Zapnutý hotspot na telefonu shodil jeho WiFi. Většina Androidů to dělá. Pak je řešením připojit na ten hotspot i notebook.
- VPN nebo Tailscale exit node na telefonu posílá veškerý provoz mimo místní síť. V Tailscale to řeší přepínač „Allow local network access"; případně použij tailnet adresu notebooku, ta funguje odkudkoli.
Pravidla
Skóre se zadává ručně po tazích, hází se doopravdy. Tři nulové tahy za sebou
vynulují hráči skóre; indikátor x / xx ukazuje, jak blízko k tomu je.
Vítěz se vyhlašuje až po dokončeném kole, aby měli všichni stejný počet tahů —
při remíze na prvním místě se hraje dál.
Co kde je
| Soubor | Role |
|---|---|
core.py |
pravidla hry, žádný vstup ani výstup |
net.py |
hledání adres, na kterých je počitadlo dostupné |
storage.py |
SQLite: hráči, hry, tahy |
stats.py |
síň slávy a kariérní statistiky |
web.py |
Flask aplikace |
dice.py |
totéž v terminálu, bez ukládání |
console.py |
aby čeština prošla i windowsovou konzolí |
version.py |
která verze to je — z gitu, nebo z binárky |
build.sh, kostky.spec |
stavba binárky |
.gitea/workflows/ |
testy a linuxová binárka doma |
.github/workflows/ |
binárky pro Windows a macOS |
Terminálová verze zůstává funkční jako záloha:
uv run dice.py
Bez uv
Když uv po ruce není, jde to postaru:
python -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python web.py
Na Fedoře stačí i systémové balíčky, pak se nemusí řešit vůbec nic:
sudo dnf install python3-flask python3-qrcode python3-tabulate python3-waitress
python3 web.py
Závislosti
Verze jsou zamčené, aby binárka postavená dnes a za půl roku obsahovala
totéž. Volné seznamy jsou v .in, zamčené v .txt:
| Soubor | K čemu |
|---|---|
requirements.in → .txt |
běh aplikace |
requirements-dev.in → .txt |
+ pytest, pro testy |
requirements-build.in → .txt |
+ PyInstaller, pro stavbu binárky |
Aktualizace je vědomý krok, ne vedlejší efekt toho, že něco vyšlo na PyPI:
for f in requirements requirements-dev requirements-build; do
uv pip compile "$f.in" -o "$f.txt"
done
Verze se píšou ještě jednou v hlavičce PEP 723 na začátku web.py a
dice.py, aby fungovalo uv run web.py. Že se ty dva zápisy shodují, hlídá
tests/test_zavislosti.py — po každém přegenerování je potřeba hlavičky
srovnat.
Vlastní binárka
./build.sh
Verzi si build.sh vezme z git describe, nebo se dá vnutit přes
VERSION=v1.2.3 ./build.sh. Zapíše ji do verze.txt, kostky.spec ji
přibalí a binárka ji pak umí ohlásit i na cizím počítači, kde žádný git není.
Verzi Pythonu, proti kterému se staví, přebíjí PYTHON_VERSION.
Staví se proti samostatnému CPythonu od uv, ne proti systémovému. Ten je
slinkovaný s glibc 2.17; postavené proti Pythonu z Fedory 44 by to chtělo
glibc 2.43 a nešlo by spustit skoro nikde — glibc drží zpětnou kompatibilitu,
ne dopřednou. Nic z hostitele se do binárky nedostane, takže kontejner k tomu
potřeba není. Výsledek je v dist/.
Stejný build.sh staví i na macOS a na Windows (v Git Bash) — jen tam bez
té starosti o glibc. Křížem to nejde: PyInstaller balí do výsledku interpret
a knihovny toho systému, na kterém běží, takže binárku pro každý systém
musí postavit ten systém.
Terminálová verze součástí binárky není; ta se pouští ze zdrojáků.
Jak vznikají releasy
Otagovaný commit spustí stavbu na obou stranách:
| Kde | Co staví | Workflow |
|---|---|---|
| vlastní runner u Gitey | Linux x86-64 | .gitea/workflows/binarka.yml |
| GitHub Actions | Windows, macOS ×2, Linux ARM64 | .github/workflows/binarky.yml |
git tag v1.0.0 && git push origin v1.0.0
GitHub je tu jen půjčená dílna. Repozitář se tam z Gitey zrcadlí (mirror), postavené soubory se posílají zpátky na zdejší release přes Gitea API a projekt má pořád jednu stránku s releasy — tuhle. Linux na x86-64 se na GitHubu schválně nestaví; doma to jde proti staré glibc, a když GitHub vypadne, release má aspoň tu platformu, na které to reálně poběží. ARM64 je výjimka — doma na něm není na čem stavět, a hodí se pro Raspberry Pi nebo jinou malou pořád zapnutou krabičku.
Každá stavba nejdřív projede testy a zkusí hotovou binárku nastartovat, než
ji kamkoli pověsí. Vedle každé visí i .sha256, takže se stažený soubor dá
ověřit:
sha256sum -c kostky-linux-x86_64.sha256 # na macOS: shasum -a 256 -c
Nad pull requesty se Linux staví taky, jen se nikam nevěší.
Testy
uv run --with-requirements requirements.txt --no-project pytest
Nebo z připraveného prostředí prostě pytest.
Nad každým pull requestem a nad main běží .gitea/workflows/testy.yml —
102 testů na Pythonu 3.11, 3.12, 3.13 i 3.14, a k tomu skriptovaná partie
v terminálové verzi, na kterou pytest nesahá.