Stridetober 🍂 Walk it
Oct 4 – Oct 31. Most total steps is crowned THE OCTOBER STEP CHAMPION on November 1 — top three split the pot 50/30/20.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Webová aplikace na zapisování volejbalových statistik. Zápas se zapisuje živě z telefonu nebo tabletu na lavičce, statistiky se pak dají filtrovat a vyexportovat.
Statické stránky bez buildu, data v Supabase, nasazení přes Vercel.
index.html zapisovatelská appka — struktura stránky a modaly
app.js logika zápisu (bez závislostí)
divak.html / divak.js divácká stránka, jen pro čtení
sdilene.js pravidla a klíče společné oběma stránkám
style.css styly
supabase/migrations/ schéma databáze — jediný zdroj pravdy
supabase/README.md práce s databází, zabezpečení, zapisovatelé
tests/ testy v prohlížeči
gh_issues.py pomůcka na zakládání issues z ISSUES.md
sdilene.js drží to, co si obě stránky nesmí počítat každá po svém: co je
bod, jak jdou posty po zónách, jak se z logu skládají výměny. Kdyby si to
divácká stránka spočítala vlastní cestou, jednou se rozejdou a nepozná se,
která má pravdu.
Aplikace záměrně nemá žádné knihovny ani build krok: index.html se dá otevřít
rovnou a app.js je jeden soubor, ve kterém se dá hledat. Přihlášení proti
Supabase Auth je proto napsané ručně místo supabase-js.
python3 -m http.server 8000
a otevřít http://localhost:8000. Aplikace se připojí k produkční databázi —
klíče jsou v sdilene.js:1-2. Pro vlastní instanci viz supabase/README.md.
Čtení je veřejné, zapisovat může jen uživatel zapsaný v vb_zapisovatele.
Anon klíč v app.js je publishable a veřejný být má; autorizace stojí na RLS
policy, ne na jeho utajení. Podrobnosti a postup přidání zapisovatele jsou
v supabase/README.md.
Bez přihlášení appka všechno ukáže, ale nepustí zapisovat — nahoře svítí lišta „jen pro čtení".
Seznam zápasů ukazuje probíhající zápas, nejbližší plánovaný a poslední dokončené. Klik na řádek (nebo Enter) otevře zápas rovnou v Live.
V záložce Live se vybere zápas a přidají hráčky do sestavy. Klepnutí na počítadlo přidá akci, dlouhý stisk nebo pravé tlačítko ji vezme zpět.
Nahoře je přepínač setu. Počítadla ukazují vždy jen právě zvolený set; tečka u čísla znamená, že v tom setu už něco zapsaného je. Vybraný set si appka pamatuje pro každý zápas zvlášť, takže reload uprostřed třetího setu neshodí zápis zpátky do prvního.
První řádek tabulky je souhrn týmu — součet každého sloupce za celou sestavu. Čísla sedí pod svými sloupci, takže není co si splést. Tlačítko v prvním sloupci přepíná mezi právě zapisovaným setem a celým zápasem.
Tabulka ve Statistikách má u servisu, příjmu i útoku vedle výborných a chyb i počet pokusů — jmenovatel toho procenta vedle. Bez něj se nepozná, že 100 % jsou dvě podání a 60 % dvacet.
Přehození balonu soupeři má u útoku vlastní kolonku ~ (volný míč).
Rozhoduje úmysl, ne rychlost: ulití přes blok je útok (chce to spadnout),
volný míč je přiznání, že se zakončit nedá. Proto je stranou útočných
pokusů, procenta i součtu „Celkem" — jinak by tým, který hodně přehazuje,
měl uměle horší útok. Volný míč od soupeře se nezapisuje a pozor na
záměnu s polem: pole je vybraný balon po útoku, ne příjem volného míče.
Pole má tři tlačítka a každé znamená něco jiného: / vybraný balon po
útoku (obrana), − balon spadl (ztracený bod, počítá se do skóre jako
každé minus) a ~ zvednutý volný míč od soupeře. Bez toho rozdělení
byla obrana smíchaná s volnými míči a vycházela líp, než jaká byla.
U obrany se nepočítá kolik, ale co z toho: konverze z obrany je podíl rozeher s vybraným balonem, které skončily naším bodem. Je v pruhu u hřiště (za set) a v profilu hráčky (kostka a druhé číslo u sloupce Pole). Počet obran sám o sobě měří hlavně to, kolikrát do nás soupeř útočil. Pozor na dvě věci: není to zásluha jen obránkyně (po obraně ještě někdo nahrává a zakončuje) a po hráčkách je vzorek malý — při dvaceti obranách je nepřesnost kolem ±20 procentních bodů.
Ve Statistikách se sety sčítají. Filtrem „set" se dají rozpadnout zpátky. Pozor: zápasy z doby před zavedením setů (#32) mají všechno pod 1. setem, takže u nich rozpad nic neřekne.
Time-out se bere klepnutím na dlaždici v panelu u hřiště, dlouhý stisk ho vrátí — stejné gesto jako u počítadel. Starší přerušení (i to pět výměn zpátky) se opraví nebo smaže v průběhu setu: klepnutím na jeho řádek. U time-outu jde přepsat stav i to, čí byl, u soupeřova střídání čísla na dresech, u našeho se dá vrátit i hráčka zpátky do své zóny. Stav rozhoduje o tom, kam se přerušení v průběhu zařadí, takže se tím srovná i time-out zapsaný o výměnu později.
Zapisovat může víc lidí najednou; posílají se přírůstky, ne celé řádky, takže se zápisy nepřebíjejí. Čísla z druhého zařízení se dorovnají zhruba do deseti sekund.
Tlačítko 📊 u zápasu otevře souhrn: kostky s klíčovými čísly, tabulku po setech (skóre, side-out, breaky, útok, příjem, obrana, chyby), hráčky podle bilance a pár vět, co z čísel plyne.
Postřehy jsou schválně jen konstatování, ne rady — appka vidí čísla, ne zápas. Každý má práh a minimální vzorek, takže se neukáže věta postavená na třech výměnách. „Soupeř uhrál 45 bodů, z toho 31 z našich chyb (69 %)" je fakt; co s tím, ví trenér líp než appka.
Nad spočítanými postřehy může být psaný rozbor — text od člověka (nebo od asistenta, který se podívá na čísla). To, co pravidla neumí: porovnat dva zápasy, odhadnout sílu soupeře, posoudit, jestli se riziko na servisu vyplatilo. Píše se tlačítkem „✏️ Napsat rozbor" a nese podpis, aby bylo na první pohled poznat, co je spočítané a co je něčí výklad.
Poslední blok je „Čemu nevěřit": co appka o svých vlastních číslech ví, že nesedí — smíchaná obrana s volnými míči, příjem zapsaný jen u části výměn, sety bez zadaného prvního podání, skóre rozcházející se s Výsledkem. A když se počítadla rozejdou s logem, radši se procento neřekne, než aby vyšlo „300 %".
Tým patří sezóně, ve které vznikl, a v jiné se nenabízí. Členství hráček je tím pádem vázané na sezónu taky — ve správě týmu se nabízejí jen hráčky ze soupisky té sezóny. Do nové sezóny se tým nepřenáší, založí se znovu.
Číslo patří týmu, ne hráčce. Jedna hráčka hraje ve víc týmech a ne všude má stejné číslo; dokud bylo číslo jen na hráčce, nesla si ho všude s sebou a ve třech týmech tím vznikly dvojice se stejným číslem.
V kartotéce se vede obvyklé číslo a ve správě týmu ho jde přebít. Prázdné políčko znamená „platí obvyklé", takže se vyplňují jen výjimky:
číslo v týmu = vb_hraci_tymy.cislo, když je zadané
= vb_hraci.cislo jinak
Bez týmu — profil hráčky přes sezóny, kartotéka, statistiky bez filtru na tým — platí obvyklé číslo. Žádné jedno správné tam totiž není, protože se míchají hráčky z více týmů.
Dvě stejná čísla v jednom týmu se nezakazují, jen se na ně ve správě týmu upozorní: při přepisování čísel kolize na chvíli vznikne vždycky. Zakázat ji by znamenalo nutit zapisovatele hledat, kdo číslo drží, než ho může dát někomu jinému.
Hráčku jde smazat jen dokud nemá zaznamenané akce — cizí klíč ve
vb_statistiky má ON DELETE CASCADE, takže smazání by vzalo i její čísla.
Jakmile něco odehraje, nabízí se místo toho archivace: zmizí ze soupisky,
sestav i správy týmů, ale statistiky zůstanou a v Archivu jde kdykoli obnovit.
divak.html ukazuje stav, postavení a průběh akcí lidem v hale. Jen
koukání: žádné přihlášení, žádné zapisování, umí jedinou HTTP metodu (GET).
Adresa je jedna pro celou halu. Bez parametru je to seznam zápasů —
nahoře rozehraný, pod ním odehrané od nejnovějšího; ?zapas=30 je detail
a &prubeh=1 celý průběh setu. Seznam se ptá při každé obnově, takže se po
ukončení zápasu srovná sám a mezi zápasy řekne „teď se nehraje". Počítá se
s telefonem; varianta pro velkou obrazovku zatím není.
Za sítí stojí šestka soupeře, když ji zapisovatel zadal — jen čísla z dresů, nic jiného o něm nevedeme. Zadává se jednou za set a jejich rotace se dál dopočítává z logu výměn (rotuje ten, kdo získal podání), takže to zapisovatele nestojí žádné další klikání. Bez zadané šestky se druhá strana sítě vůbec neukáže.
Data se dotahují po 5 s, když zápas běží, jinak po 30 s; schovaná záložka nestahuje nic. Tahá se jen jeden zápas, ne celá databáze jako v appce. Když spojení vázne, stránka to napíše — zamrzlé číslo bez varování je horší než přiznaná pauza.
Rozdílu mezi počítadly a logem výměn si divák nemusí všímat: stav se bere z počítadel (zdroj pravdy), průběh z logu jako doplněk.
Testy jedou v Chromiu přes Playwright a Supabase mají odchycené, takže nesahají na produkční data — ověřuje se, co aplikace odeslala.
npm i playwright # jednorázově
python3 -m http.server 8099 &
node tests/live-stats.test.mjs # zapisovatelská appka
node tests/divak.test.mjs # divácká stránka
Volitelně APP_URL (jiná adresa) a CHROMIUM_PATH (jiné Chromium).
Testy nečekají na hodiny, ale na stav: po každé akci se počká, až appka
nemá nevyřízený zápis, doběhne poslední požadavek a dojede rotace (klid()
v tests/live-stats.test.mjs). Pevné pauzy stály 145 ze 175 vteřin běhu;
po přepsání je to 45. Novou kontrolu proto nepsat s waitForTimeout —
jediná zbylá pauza je dlouhý stisk, který je opravdu o čase.
V CI testy neběží; Vercel dělá jen nasazení, takže je před změnou v app.js,
divak.js nebo sdilene.js potřeba pustit je ručně. Změna v sdilene.js se
dotýká obou stránek, tam je nutné pustit oba soubory.
Push do main nasadí Vercel sám. Změny schématu se nasazují zvlášť, viz
supabase/README.md — a když se mění obojí, je pořadí důležité: nejdřív
nasadit aplikaci, pak utáhnout databázi, ať nevznikne chvíle, kdy nasazená
verze neumí to, co už databáze vyžaduje.