Code review: „Předělej mapu parkování podle oblastí” (63105d3)
Code review: „Předělej mapu parkování podle oblastí” (63105d3)
Větev codex/parkovani-oblasti, 11 souborů, +1538 −142. PR na GitHubu zatím
neexistuje, review je proti commitu.
Kolo 1 — 2026-08-02 17:35. Stav: dvě blokační připomínky, čtyři doporučené, čtyři drobnosti. Celkově je změna dobře postavená: párování přes kód ZSJ místo pořadí řádků je správná reakce na doloženou chybu v podkladech, generátor je reprodukovatelný a testy dávají smysl. Blokační výhrady míří na to, co uvidí čtenář na mapě, ne na architekturu.
Kolo 2 — 2026-08-02 18:20, commit 2f2a3a5. Obě blokační připomínky
vypořádány, review uzavřeno. Vypořádány jsou i všechny čtyři doporučené
a všechny čtyři drobnosti; podrobnosti a způsob ověření jsou v sekci
Kolo 2 na konci. Přibyly tři nové drobnosti
(M5–M7), žádná není blokační.
Blokační
B1 — Šedé ulice nemá legenda
js/parkovani.js, vyrazBarevUlic(): úsek bez obsazenosti se kreslí #9aa4ab.
Takových je 198 z 927 úseků (21 %), tedy 91 z 239 ulic — jde o ulice
s nulovou legální kapacitou. Oblastní vrstva má pro týž jev vlastní barvu
i řádek legendy („vozidla, ale 0 legálních stání”), uliční vrstva nic. Čtenář
šedou přečte jako „bez problému” nebo „bez dat”, přitom znamená pravý opak:
auta tam stojí, legální stání tam nejsou žádná.
Náprava: přidat do legendy řádek pro uliční šedou (stačí zobrazovat jen tehdy, když je uliční vrstva viditelná, tj. nad zoom 14,5 a mimo metriku Obyvatele).
B2 — Počty vozidel v oblastech nejsou z repa doložitelné
data/parkovani-oblasti.json obsahuje 20 ručně přepsaných řádků tabulky 3.1.
Ta v repu není v žádné strojově čitelné podobě a tools/test_parkovani.mjs
kontroluje součty proti konstantám zapsaným v testu — kruhová kontrola, která
přepis nezachytí.
Kapacity sedí na jiný zdroj přesně (agregace data/parkovani.json po ZSJ dává
5164 legálních a 7426 technických míst, tedy 1:1). Počty vozidel ale u dvou ZSJ
výrazně nesedí na agregaci surových dat z data celoplošné brandýs public.xlsx:
| ZSJ | v commitu (noc) | agregace xlsx po ZSJ | rozdíl |
|---|---|---|---|
| Zahradní město | 158 | 34,5 | 4,6× |
| U nádraží | 1285 | 1152,5 | +11 % |
U Zahradního města jde rozdíl přesně na vrub dvou dělených řádků tabulkové
přílohy (729-1, 729-2, Rozmarýnova: noc 86 + 37 = 123). To jsou řádky z té
části podkladu, o níž docs/parkovani-kontrola-codex.md v tomtéž repu dokládá,
že hodnoty OA patří jinému úseku (poziční spojení dvou různě seřazených
seznamů). Dopad na výstup je viditelný: 158/159 míst je 99 % obsazenost (žlutá
třída), 34,5/159 je 22 % (nejsvětlejší zelená) — čtyři třídy legendy rozdíl.
Nejde nutně o chybu, tabulka 3.1 může mít vlastní, správnější podklad. Ale
.impeccable.md, přidaný stejným commitem, si v bodě 5 sám ukládá, že „čísla
musí být reprodukovatelná ze zdrojových dat”, a tady to neplatí.
Náprava (stačí jedna z variant):
- přiložit tabulku 3.1 jako CSV/JSON do repa a testovat vstup proti ní;
- nebo u obou dotčených oblastí přiznat nejistotu v detailu oblasti a poznámku
zapsat i do
data/parkovani-oblasti.json.
Doporučené
D1 — Test neváže výstup na aktuální vstup
test_parkovani.mjs porovnává geojson s konstantami, ne se vstupním JSON.
Úprava nazev, populacniZsj nebo vzájemně se rušících hodnot bez regenerace
projde zeleně. Doporučuji porovnat per-ZSJ mistaLegalni, mistaTechnicka,
vozidlaNoc/Den mezi parkovani-oblasti.json a parkovani-oblasti.geojson.
D2 — Uliční vrstva ukazuje hodnoty jiné oblasti, než v níž leží
Uliční data jsou agregovaná na celou ulici, oblastní na ZSJ. Geometrickým testem (střed úseku v polygonu ZSJ) leží ve „své” ZSJ jen část úseků: Před obchvatem 97 %, Vrábí 99 %, ale Na Zápské 41 %, Průmyslový obvod 20 %, U Záp a U Proboštského rybníka 0 %. Na mapě tak nad zelenou oblastí leží červené ulice a naopak. Popup to zmiňuje poslední větou; zvážil bych to říct dřív a výrazněji, nebo uliční detail omezit na vybranou oblast.
D3 — Choropleth přeceňuje neobydlené plochy
U Proboštského rybníka (18 obyvatel, 17 vozidel, 0 legálních stání) je fialově přes celou oboru a při běžném zoomu vizuálně dominuje mapě víc než Spořilov, kde chybí 294 stání. Zvážit ztlumení výplně u oblastí s malou populací nebo šrafu místo plné barvy.
D4 — Kontrast a velikost písma v panelu
.pk-graf-metodika má #98a2a8 na bílé = 2,6:1 při 10,5 px, tedy pod WCAG
AA (4,5:1). Popisky v panelu jdou až na 9,5 px (.pk-detail-kicker,
.pk-stitek); u webu pro veřejnost bych nešel pod 12 px.
Drobnosti
- M1
tools/parkovani-oblasti.py,nacti_populaci(): tvrdá kontrola součtu 19029 shodí generátor i po legitimní aktualizaci RÚIAN. Doplnit do hlášky, co má člověk udělat. - M2 Selže-li
pridejParkovani()až poaddSource, další zapnutí režimu skončí na „source already exists”. Uklidit zdroj vcatch. - M3
vyrazBarev()používá['to-number', ['get', pole]];nullse změní na 0, tedy na nejpříznivější třídu. Dnes taková oblast v datech není (case ošetříbez_pruzkumuinulova_kapacita), ale pojistka chybí. - M4
.impeccable.mdje konfigurace nástroje v kořeni veřejného repa; spíš patří dodocs/nebo do.gitignore.
Co jsem ověřil
node doprava/tools/test_parkovani.mjs— prochází.python3 doprava/tools/parkovani-oblasti.py— regenerace je bit-identická s commitnutým geojsonem (prázdnýgit diff).- Všech 24 kódů ZSJ odpovídá číselníku ČSÚ (dotaz na RSO_2021_2 podle
KOD_OBEC='538094'), včetně netriviálních mapování K Toušeni → Královice, Před obchvatem → Před dálnicí, U kostela → Stará Boleslav-historické jádro. - Názvy v
populacniZsjsedí namhd-brandys/addr_pop.csv(24 ZSJ, 19 029 obyvatel). - Kapacity: agregace tabulkové přílohy po ZSJ dává přesně hodnoty v commitu u všech 20 oblastí.
- V prohlížeči (lokální build): načtení bez chyb konzole, přepínání všech tří metrik, výběr z žebříčku i bodového grafu, přiblížení na uliční vrstvu, přepínání režimů Živě / Simulace / Parkování tam a zpět — bez výjimek. Souhrn 103,4 %, Spořilov 214,4 % a +294 vozidel sedí na data.
- Ošetření souběhu v
app.js(sdílený promise + kontrolastav.rezimpoawait) je správné, dvojímuaddSourcebrání.
Kolo 2 — vypořádání v 2f2a3a5
Commit „Vypořádej připomínky k mapě parkování”, 9 souborů, +176 −38.
Blokační — obě vyřešeny
B1 (šedé ulice) — vyřešeno. Přibyla vrstva parkovani-ulice-nulova
(fialová čárkovaná, filtr kapacitaZakonna == 0), parkovani-ulice-linie
dostala doplňkový filtr > 0 a legenda dostala sekci „Uliční detail při tomto
přiblížení”, která se objeví jen nad zoomem 14,5 a překresluje se na zoomend.
Ověřeno: všech 198 dříve šedých úseků má kapacitaZakonna == 0, novou
vrstvu tedy pokrývá filtr beze zbytku a šedá už na uliční vrstvě nevznikne
(úseků s kapacitou > 0 a chybějící obsazeností je 0). Oba filtry jsem
vyhodnotil proti @maplibre/maplibre-gl-style-spec — doplňují se bez překryvu
i mezery.
B2 (nedoložitelné počty vozidel) — vyřešeno zvolením druhé nabídnuté
varianty: U nádraží a Zahradní město mají v datech spolehlivostVozidel:
"nejista" a poznamkaDat s konkrétním číselným rozdílem i odkazem na dělené
řádky 729-1/729-2, v detailu oblasti se zobrazí štítek „nejistá data”
a žlutý blok s vysvětlením. Test kontroluje, že příznak nese právě tato dvě
ZSJ a že poznámka není prázdná.
Doporučené — všechny čtyři vyřešeny
- D1 — test nově porovnává per-ZSJ
nazev,populacniZsj, kapacity i vozidla mezi vstupním JSON a výstupním geojsonem. Ověřeno experimentem: změna názvu Vrábí bez regenerace shodí test hláškouVýstup neodpovídá vstupu: 009105.nazev(data i test jsem vrátil zpět). - D2 — popup uličního detailu má upozornění hned pod názvem: „Souhrn platí pro celou ulici a nemusí odpovídat barvě oblasti pod ní.”
- D3 — oblasti pod 100 obyvatel mají
fill-opacity0,38 a čárkovaný obrys. Ověřeno vyhodnocením výrazu: U Proboštského rybníka (18 obyvatel) → 0,38, Spořilov (1 805) → 0,66. - D4 —
.pk-graf-metodikaje nyní#596974/11,5 px, tj. 5,68:1 místo 2,6:1. Přeměřil jsem i ostatní nové kombinace: 5,5–7,8:1, všechny nad AA. Nejmenší text v panelu stoupl z 9,5 px na 10,5–11,5 px; pod 12 px zůstaly jen popisky os SVG grafu (9–9,5 px), tam je kontrast 5,7:1.
Drobnosti — všechny čtyři vyřešeny
- M1 — konstanta
OCEKAVANY_POCET_OBYVATELa hláška říká, co udělat. - M2 —
uklidParkovaciVrstvy()vcatchodstraní vrstvy i zdroje,interakceNastavenabrání dvojí registraci posluchačů. - M3 —
vyrazBarevOblasti()má case pronull. Ověřeno vyhodnocením: změřená oblast sobsazenostNoc == nulldá#9aa4ab, ne nejsvětlejší třídu. - M4 —
.impeccable.mdpřesunut dodoprava/docs/design-context.md.
Nové drobnosti z tohoto kola
- M5 — podmínka pro legendu uličního detailu testuje jen viditelnost,
metriku a zoom, ne existenci vrstvy. Když se
parkovani-mapa.geojsonnenačte (nactiGeojson(…, false)vrátínull, vrstvy nevzniknou), legenda bude popisovat neexistující ulice — a to zároveň se stavovou hláškou, že se uliční detail nepodařilo načíst. PřidatmapaInstance?.getLayer('parkovani-ulice-linie'). - M6 — štítek „nejistá data” v detailu nahrazuje štítek „priorita” (ternární operátor). Dnes se ta dvě označení nepřekrývají, kdyby ale ano, priorita zmizí beze stopy.
- M7 — legenda uličního detailu nabízí řádek „obsazenost nelze spočítat” pro šedou, která po B1 v datech nevzniká ani jednou. Neškodné, ale zbytečné.
Ověřeno
node doprava/tools/test_parkovani.mjs prochází, regenerace generátorem je
bit-identická s commitnutým geojsonem, výrazy a filtry MapLibre jsou validní
podle style-spec a vyhodnocují se podle očekávání.
Vizuální kontrolu v prohlížeči jsem tentokrát nedokončil: aplikace uvízne na
čekání na mapa.isStyleLoaded(), protože se v prohlížeči nestahuje mapový styl
z CARTO CDN (žádné požadavky na dlaždice, WebGL v pořádku). Chová se tak stejně
na cf447a8 i na 2f2a3a5, nejde tedy o regresi tohoto commitu, ale o stav
prostředí. Legendu uličního detailu a štítek nejistoty jsem proto ověřil jen
z kódu a z vyhodnocení výrazů, ne na živé mapě.