# Tehtud töö ajalugu

## 2026-08-12 — Süsteemi tervisekontroll (ohmu + hetzner)

**Leitud seis:** ohmu jooksis uusimat koodi (f08c1f6), kuid **hetzner oli vanal** (ae86558, image 10:57) — puudusid f08c1f6 täiendused (PDF-vahemälu, gravity fallback, run_municipality etapp 0, preprocess manifest-parandus, web-demo-kood). Andmed olid hetzneril käsitsi kopeeritud ja ajakohased. Syncthing-kaust oli samuti maha jäänud (f08c1f6 tehti otse /data/docker-i, mitte Syncthing kaudu).

**Parandatud:**
1. **hetzner**: `git pull` f08c1f6 (stash/pop data käsitsimuudatuste üle), image rebuild, stack deploy → kõik kihid 200, raport 200, kaitstud 403, `_report_cache` olemas.
2. **Syncthing-kaust** (arendusalus): kõik versioonitud koodifailid sünkroonitud /data/docker-ist → Syncthing, diff 0.
3. **Obsidian**: teadlikud kustutused (Etnomath, Zotero, ReadItLater) + Andmeallikad/ajalugu committitud (`aa68c5b`).

**Kokkuvõte:** mõlemad serverid nüüd f08c1f6-l, Syncthing ajakohane, Obsidian pushitud.

## 2026-08-11 — Väljapääsupunktide isoleeritud komponendi jaotus parandatud

**Probleem:** VAL_0101 rühm (isoleeritud komponent, 2 väljapääsu) näitas mõlemal väljapääsul "ADS aadresse 3" (kokku 6), kuigi rühmas on 5 aadressi. Põhjus: `gravity_exit_analysis.py` jagas isoleeritud komponendi rahvastiku **võrdselt** kõigi komponendi väljapääsude vahel (`/ n_exits`) → iga sõlme pop_ads jagunes 50/50 → mõlemale 5.5 (= 2.5 aadressi, ümardatud üles 3-ni).

**Parandus:** isoleeritud sõlme rahvastik omistatakse tema **best_exit**-ile (§5 juba arvutatud, kõik sõlmed `local_nodes_reached`-s). Tulemus VAL_0101:
- 846244516 → pop_ads=4.4 (2 aadressi)
- 846244647 → pop_ads=6.6 (3 aadressi)

ADS-summa konserveeritud igas vallas (Valga 9066, Otepää 6813, Tõrva 4752, Võru 12452). Vastavus `_node_exit`-iga (teelõigu `exit`, reisitee). Kõik 4 valda ümber arvutatud (gravity + export), geojson-id uuendatud, deploy ohmu + hetzner (gogs ab99ca9).

## 2026-08-11 — ADS-egress-omistus teelõikudele (algne allikas)

**Probleem:** teelõigu `ads_addr` oli BFS-alampuu koond (aadressid mis liiguvad läbi lõigu väljapääsuni), mitte egress. Linnagridis (Valga linn) jäid lõigud 0-ks: Talve tänava sõlmedel olid aadressid olemas, kuid BFS-puu ei jõudnud nendeni, sest tee väljapääsuni läbis teise väljapääsu sõlmi → `parent=None`, 11.3% ADS-rahvastikust kadus.

**Lahendus (2 osa):**
1. **Egress-omistus** (`building_population.py`): uus `_assign_ads_to_segments` — iga unikaalne ADS-aadress → üks teelõik (lõigu tipp lähim → sõlme incidenetsed lõigud; tipp liiga kaugel → STRtree `nearest`, ≤300m). Väljund: `{prefix}_ads_segments.csv`. Fallback katab KÕIK omistamata aadressid (KÜ-ta + KÜ-d ilma teekontaktita — linnas jookseb tee mööda kinnistu piiri). STRtree `query(punkt)` ei tööta (punkti bbox degenereerub) → `nearest`.
2. **BFS-parandus** (`export_qgis.py`): BFS ekspandeerib KÕIK naabersõlmed (mitte ainult sama väljapääsu), varajane lõpetus; post-order läbib kõik külastatud sõlmed (marsruudi vahesõlmed annavad 0). Kadunud sõlmede arv 0, `trip_length_m` kõigil lõikudel.

`ads_addr` lõigul = egress (sellet lõigult väljuvad aadressid). Talve lõik 2270746560–2270746562: `ads_addr=4`, `trips_ads=17.6`. Tulemused: Valga 2291/4119, Otepää 2315/3093, Tõrva 1514/2159, Võru 3950/5658 lõiku/aadressi. Popup-tekst täpsustatud ("ADS aadresse (väljub sellet lõigult)").

## 2026-08-09 — Linnuke: ADS-aadressidega teelõigud

- Uus menüü linnuke "**ADS-aadressidega teelõigud**" (`ads_addr_color`) — kuvab lõigud, kus unikaalseid ADS-aadresse > 0.
- Heleroheline (`#2ecc71`), **kõige ülemine kiht** kohalikel teedel (lisatud viimasena), menüüs **viimasena**.
- Legend uuendatud. Deploy: ohmu + hetzner (gogs 70f2232).

## 2026-08-09 — ADS-omistamine: hoonele lähim sõlm KÜ-tee kontaktkomponendis

- **Probleem:** aadressid Marinurme ja Kungla läksid valele teelõigule. Marinurme hoone (637553,6405407) lähim sõlm 846244561 (~49m, tupik), aga aadress läks sõlmele 846244692 (~164m). Kungla hoone lähim 13645879022 (~12m, tupik), aga aadress läks 13645879020.
- **Põhjus:** `_assign_ads_unique` valis **lõikumispunkti (KÜ∩tee) lähima otspunkti**, mitte **hoonele lähima sõlme**. Suur KÜ (Kungla 107275 m²) lõikub 28 teega — lõikumispunktid on hajutatud, valiti vale sõlm.
- **Parandus:** aadress omistatakse **hoonele lähimale sõlmele, mis on ühendatud KÜ-tee kontaktisõlmedega** (samas kohaliku võrgustiku komponendis). Säilitab Loigu→Kungla paranduse (õige komponent), valib õige (hoonele lähima) sõlme.
- **Tulemus:** Marinurme → 846244561 (tupik), Kungla → 13645879022 (tupik), mõlemad `ads_addr=1`. Valla ADS-summa püsis (Valga 9066).
- Deploy: ohmu + hetzner (gogs 0eed5d8).

## 2026-08-09 — Teelõikudele ADS aadresse (ads_addr)

- **Eesmärk:** teelõigu popup-isse unikaalsete ADS-aadresside arv — mitu aadressi liigub läbi selle lõigu väljapääsuni. Võimaldab kontrollida kohaliku teede võrku ja tuvastada, millisele teelõigule aadressandmed käivad.
- **Teostus:** `export_qgis.py` BFS-puu post-order arvutab `_edge_addr_ads` = lõigu valgala sõlmede unikaalsed ADS-aadressid (`pop_ads / 2.2`), sama all-or-nothing loogikaga nagu trips. `local_roads.ads_addr`.
- **Popup:** teelõigule rida "ADS aadresse" (kui > 0).
- **Katvus:** Valga 4370, Otepää 4320, Tõrva 2848, Võru 7692 lõiku aadressidega. Näide: ads_addr=3 ↔ trips_ads=13.2 (3 × 2.2 × 2.0 ✓).
- Deploy: ohmu + hetzner (gogs d92cb2c).

## 2026-08-09 — Andmeallikate nimekiri (korrektne andmekasutus)

- **Eesmärk:** kaardile/tutvustuslehele/raportile andmeallikate nimekiri, et andmekasutus oleks korrektne (OSM ODbL, riiklikud registrid).
- **Lisatud (3 kohta):**
  - **`web/tutvustus.html`** — uus "Andmeallikad" sektsioon (OSM ODbL, Maa- ja Ruumiamet ADS + kataster, Ehitisregister, Rahvastikuregister, Transpordiamet Teeregister + liiklusloendus) + jaluses atributsioon
  - **`web/index.html`** — sidebar "Andmed:" rida (allikad + © OpenStreetMap'i kaastöötajad)
  - **`report.py`** — PDF-raporti lõppu "5. Andmeallikad" jaotis (lisa `small` stiil)
- Deploy: ohmu + hetzner (gogs a065bbe), kontrollitud kõik kolm.

## 2026-08-09 — Kasutuse fallback: Riigiomand (kõik klassid) → avalik

- **Probleem:** Riigiomandistee (track, nt 846244467–846244256) oli ilma kasutuseta. Varasem fallback jättis Riigiomand + kohalik klass määramata (metsateed/RMK hüpotees), aga kasutaja loogika: riigimaa tee on avalik.
- **Parandus:** fallback nüüd — **Riigiomand (kõik klassid) → avalik**, mitte ainult riigitee klassid. Lepingukihi `metsatee` jääb prioriteediks (kui olemas).
- **Tulemus:** Riigiomand ilma kasutuseta = 0 kõigis valdades (Valga 6399, Otepää 3088, Tõrva 4864, Võru 16721 lõiku said avalik). Kasutaja näide 846244467–846244256: `kasutus=avalik` ✓, `trip_kat=mitteavalik` (reisi teel on eramaa mitteavalikke lõike — õige).
- **Lõplik fallback:** Munitsipaalomand → avalik; **Riigiomand → avalik**; Eraomand → mitteavalik; omanditeta → määramata.
- Deploy: ohmu + hetzner (gogs 0b85b6e).

## 2026-08-09 — Popup mõisted: Lõigu kasutus vs Reisi kasutus

- **Küsimus:** lõik 846244478–846244256 (Riigiomand, kasutus avalik) näitas "Reisi kasutus: mitteavalik".
- **Selgitus:** `Lõigu kasutus` on konkreetse lõigu oma (Riigiomand → avalik ✓). `Reisi kasutus (kogu teel)` on **koond kogu reisitee** kohta väljapääsuni — 1671m reis kulgeb läbi **eramaal asuva** lõigu (846244411–846244439 jt, Eraomand → mitteavalik). Mõisted on erinevad: üks on selle lõigu oma, teine kogu reisi tee.
- **Parandus:** popup-i sildid selgemad — "Lõigu kasutus", "Reisi kasutus (kogu teel)", "Reisiteel eri lõikude kasutused" + sidebar selgitus.
- Deploy: ohmu + hetzner (gogs 3985361).

## 2026-08-09 — Kasutuse fallback: Eraomand → mitteavalik

- **Parandus:** kui teel on `omand_kat=Eraomand` (eratee) ja kasutus puudub → **mitteavalik**. Eeldus: kui registrisse ilmub hiljem "avalik" märge, muudab andmevärskendus selle automaatselt.
- **Fallback loogika (lõplik):**
  - Munitsipaalomand → avalik
  - Riigiomand + riigitee klass → avalik
  - **Eraomand → mitteavalik**
  - Riigiomand + kohalik klass (track/unclassified) → määramata (metsateed/RMK)
  - Omandiks `omand_kat`, fallback `omand` (teeregister) kui kataster puudub
- **`omand_kat=None` kontroll:** Valga 4, Otepää 74, Tõrva 4, Võru 0 lõiku (kõik ilma omandita — jäävad määramata). Need on valdavalt riigimaa kohalikud teed.
- **Reisi kasutus (`trip_kat`) arvutatud** fallbacki järel: Valga mitteavalik 24909, avalik 11081, metsatee 5175.
- Deploy: ohmu + hetzner (gogs 97ca80a).

## 2026-08-09 — Kasutuse fallback omandi järgi (munitsipaalomand → avalik)

- **Probleem:** tee 11844603940–11844603939 (Munitsipaalomand) oli ilma kasutusotstarbeta — `kasutus`/`trip_kat`/`trip_kasutus` määramata. Põhjus: kasutus tuli ainult teeregistri lepingukihist, mis ei katanud kõiki teid. **5513 munitsipaalomandiga lõiku (54%) jäid ilma.**
- **Parandus (`export_qgis.py`):** kasutuse fallback omandi järgi (kui leping puudub):
  - **Munitsipaalomand → avalik** (KOV teed on avaliku kasutusega)
  - **Riigiomand + riigitee klass (trunk/primary/secondary/tertiary) → avalik** (riigimaanteed avalikud)
  - Riigiomand + kohalik klass (track/unclassified) → ei puutu (metsateed/RMK)
- Reisikoondi arvutus liigutati **pärast** omand_kat sidumist ja fallbacki — kasutab uuendatud kasutust.
- **Tulemus:** kõik munitsipaalomandisteed kasutusega (0 ilma). Valga: local 5513 + major 4728 lõiku said "avalik". Kasutaja näide nüüd `kasutus=avalik, trip_kat=avalik`.
- Deploy: ohmu + hetzner (gogs 141cb55).

## 2026-08-09 — Popup: Lõigu pikkus + Reisi kasutus

- Kohaliku tee popup-ile lisatud:
  - **Lõigu pikkus** (`length_m`) — meetritäpsusega
  - **Reisi kasutus** (`trip_kat`) — koondkategooria (avalik/metsatee/mitteavalik)
  - (olemasolevad: Reisi pikkus väljapääsuni, Reisiteel kasutus)
- Deploy: ohmu + hetzner (gogs 6c8d613).

## 2026-08-09 — is_deadend parandus + Reisitee kasutusvärv

- **Probleem:** lõik 869309244–2393808303 (VAL_0009) näitas märkeid "väljapääsu lõik, tupik" korraga. Põhjus: `is_deadend` loogika luges riigitee ristmiku otsa (degree 1 kohalikus graafis) tupikuks, kuigi tee jätkub riigiteele.
- **Parandus:** `is_deadend` = otspunkt degree 1 **JA ei ole väljapääs (riigitee sõlm)**. Tulemus: Valga 4246→2388 tupikut, kasutaja näide nüüd `deadend=0, exit=1` (õige). Jäänud 66 deadend+exit on lühikesed oksad (8-176m), kus üks ots riigiteel ja teine tupik — loogiline.
- **Uus linnuke "Reisitee kasutus (värv)":** overlay-kiht `trip_color` värvib kohalikud teed reisitee kasutuse koondkategooria (`trip_kat`) järgi — avalik roheline, metsatee oranž, mitteavalik punane (sarnaselt omandivärvile). Legend uuendatud.
- **`trip_kat` tuletus:** reisi kasutuskoondist; nullipikkuse reisiga lõikudele (väljapääsu lõik ise) kasutatakse lõigu enda kasutust — mõlemad suunad ühtsed.
- **trip_kat jaotus (Valga):** avalik 19763, mitteavalik 7646, metsatee 6200.
- Deploy: ohmu + hetzner (gogs 00cbde4, 39c9025).

## 2026-08-09 — Popup jäänuk eemaldatud (tripNote)

- **Probleem:** kohaliku tee popup-i all oli jäänuk "— reisiteel on metsatee/piiratud kasutusega" iga `trip_kasutus` olemasolu korral — isegi siis, kui reisiteel oli ainult "avalik" (nt ID 12065213289–12065213290, trip_kasutus="avalik" näitas valet metsatee/mitteavalik märkust).
- **Parandus:** `tripNote` muutuja eemaldatud popup-ist. "Reisiteel kasutus" rida juba näitab konkreetset väärtust — lisamärkus oli lohakas ja vale igale juhule.
- Deploy: ohmu + hetzner (gogs c38a7f5).

## 2026-08-09 — Liikluse overlay-kihtide popup

- **Küsimus:** kas `Riigiteede liiklus (AKÖL)` ja `Kohalik liiklus (kaudne)` annavad ainult värvi või mõjutavad popup infot.
- **Analüüs:** overlay-kihid (`major_traffic`/`local_traffic`) kasutavad **sama allikat** kui põhiteed (`addTrafficOverlay`), ainult eri värviga. Popup info (akol/trips) tuleb põhikihtidelt `major_roads`/`local_roads` (alati atribuutidena). `pickFeature` prioriteediloendis on põhiteed, seega tavaliselt näitab popup õiget teed.
- **Puudus leitud:** kui põhitee on välja lülitatud aga liikluskiht peal, tabab klikk overlay-kihti → `POPUPS`-is puudub → tühi popup.
- **Parandus (`openPopup`):** overlay-kihtide (`major_traffic`/`local_traffic`/`omand_color`/`omand_color_major`) popup kasutab põhitee popup-i (sama allikas = samad atribuudid). Nüüd töötab ka põhitee väljalülitatuna.
- Deploy: ohmu + hetzner (gogs cdb3fa7).

## 2026-08-09 — Popup mõistete täpsustus + Väljapääs (ID)

- **Popup täiendus (local_roads):** lisatud rida **"Väljapääs (ID)"** (`exit` = lähim väljapääsupunkt, kohaliku tee + riigitee ristmik) reisi pikkuse kõrvale — et tuvastada, millise väljapääsupunktini reis kulgeb.
- **Mõistete täpsustus:**
  - "Reis läbib" → **"Reisiteel kasutus"**: loetelu teekasutuslepingu režiimidest (avalik/metsatee/mitteavalik) reisi teel väljapääsuni. Näide "metsatee,mitteavalik" = reis kulgeb läbi metsatee- ja piiratud kasutusega lõikude.
  - "Reisi pikkus" → **"Reisi pikkus väljapääsuni"** (selgem).
  - **"Märked: läbib lepingulõike" (`is_agreement`) eemaldatud** — oli ülearune: koodis `is_agreement = int(bool(_kas_vals))` ja `trip_kasutus` täidetud samal tingimusel (kontroll: 0 erinevust 42090 lõigust). Popup näitab nüüd ainult `trip_kasutus` (konkreetne info).
- Sidebar-i "Mida siin näed?" selgitus täiendatud uute mõistetega.
- Deploy: ohmu + hetzner (gogs 1b39833), kontrollitud mõlemas.

## 2026-08-09 — simplify=False: degree-2 sõlmed eraldi lõikudeks

- **Probleem:** OSMnx vaikimisi `simplify=True` liidab degree-2 vahesõlmed üheks servaks. Tee 13645879022–13645879019 (100m, OSM-is 4 node: 22→21→20→19) kuvati 1 lõiguna, mistõttu `is_deadend`/`is_exit` märked olid valed (kogu lõik sai mõlemad, kuigi tupik on ainult ots 22 ja väljapääs ainult ots 19).
- **Parandus:** kõik graafi laadimised (`export_qgis`, `gravity`, `building_population`, `valga_analysis`, `valga_population_analysis`) nüüd `simplify=False` — iga degree-2 sõlm oma lõiguna.
- **Gravity optimeerimine:** `exit_distances` arvutati kõigi ~2000 exit-i vahel (aeglane, Võru 40+ min). Kuna gravity jaotus kehtib ainult põhikomponendis, arvutatakse nüüd ainult main-exitide (~21-71) vahel → **40 min → ~1 min**.
- **Tulemus:** tee 13645879022–13645879019 = 3 lõiku: 22-21 (18m, tupik), 21-20 (33m, vahepealne), 20-19 (49m, väljapääs). Märked täpsed.
- **Lõikude arvud:** Valga 42090, Otepää 52620, Tõrva 33795, Võru 110243 (varem 6779/7107/5370/14999 — ~6-7× rohkem).
- Deploy: ohmu + hetzner (gogs b2d9c43), kontrollitud mõlemas.

## 2026-08-09 — Vahemälu parandus (no-cache päised)

- **Probleem:** tabaline brauser näitas vanu popup-andmeid, kuigi private-brauser oli korras. Põhjus: FastAPI serveeris `index.html`/GeoJSON-id `ETag`/`Last-Modified` vahemäluga, brauser ei küsinud uuesti.
- **Parandus (`server.py`):** kõik lehed (`/`, `/tutvustus`), kihtide geojson-id, PDF-raport ja hinnapakkumine saavad `Cache-Control: no-cache, no-store, must-revalidate` — brauser kontrollib alati uuesti.
- **Kasutajapoolne:** Ctrl+F5 / DevTools "Disable cache" / private aken.
- Deploy: ohmu + hetzner (gogs af377fe), mõlemas kinnitatud `cache-control` päis.

## 2026-08-09 — Kasutaja uuringu loogika lisamine (QGIS + pgRouting vaade)

- **Uuriti kasutaja käsitsi tehtud uuringut** (QGIS `valga valla teed.qgz` + hetzneri postgres `valga_vald` skeem): `teed`/`links`/`nodes` pgRouting-vormingus, `aadressid` (punkt+link+kinnistu geomeetria), `maaomand`, `eraomand_*`, `link_exit_distance` (iga lõigu reisitee väljapääsuni Dijkstra-ga, koos omandi/kasutuse/aadresside/rahvaarvu koondiga).
- **Lisati meie skriptidesse (andmed meie allikatest):**
  1. **`is_deadend`** (tupikteed) + **`is_exit`** (väljapääsu lõik) — `export_qgis.py`, OSM-võrgust (aste=1, otspunkt riigiteel). Valga: 3466 tupikut / 2090 väljapääsu lõiku.
  2. **Reisitee** (`trip_length_m`) — BFS-puu vanemate ahela pikkus lõiguni väljapääsust. Kõik 6779 lõiku.
  3. **Reisi kasutuskoond** (`trip_kasutus`, `is_agreement`) — kas reis väljapääsuni läbib metsateed/mitteavalikku (teekasutuslepingu loogika). Valga: 3088 lõiku läbib lepingulõike.
  4. **ADS aadress-kinnistu link** (`ads_ky` veerg `node_population.csv`-s) — aadressi KÜ tunnus sõlme kohta (853/3693 Valgas).
- **Popup täiendus:** local_roads näitab "Reis läbib", "Reisi pikkus", "Märked (tupik/väljapääs/leping)".
- **Tulemused (is_agreement):** Valga 3088, Otepää 3094, Tõrva 3862, Võru 6761 lõiku.
- Deploy: ohmu + hetzner (gogs 1e8448a).

## 2026-08-09 — Teekasutuslepingud (kasutus) teedele

- **Allikas:** Teeregister WFS `ms:n_alusdokumendid_ja_lepingud` — teekasutuslepingud.
- **Kasutusrežiim täiendab omandisuhteid:** `avalik` (KOV haldusakt), `metsatee` (RMK — võib olla ka eramaal!), `mitteavalik` (eramaa piiratud juurdepääs).
- **Uus `pipeline/teeregister_leping.py`** — WFS-laadimine (bbox miny,minx,maxy,maxx + paging 500), salvestab `{prefix}_teeregister_leping.gpkg`. Parandatud: `_val` (tekst) eelistatakse `_xv` (kood) kohale.
- **`export_qgis.py`:** spatial join lepingulõikudest → `local_roads` + `major_roads` atribuut **`kasutus`**. Teedevõrku ei muudeta.
- **Popup:** "Kasutus: avalik / metsatee / mitteavalik" (omandi kõrvale, mõlemad teekihid).
- **Katvus (kohalikud lõigud):** Valga 3766/6779 (avalik 2990, metsatee 504, mitteavalik 264), Otepää 4242/7107, Tõrva 3063/5370, Võru 7479/14999.
- **Uurimisväärtus:** metsatee+Eraomand juhtumid (nt Valga 1377634760-9074024489) — RMK metsateed eramaal.
- Deploy: ohmu + hetzner (gogs 069896f), `.env` .gitignore-sse (token ei leki).

## 2026-08-07 — Avalik/kaistud mudel + token + logimine

- **Eesmärk:** avalikkus näeb ainult Valga valla andmeid; Otepää/Võru/Tõrva on kaitstud.
- **Mudel:** `municipalities.py` lisatud `public` märge — Valga `public: True`, teised `False`. Manifest kannab `access: public|protected`.
- **Server (`server.py`):**
  - `ATLAS_ACCESS_TOKEN` keskkonnamuutuja (deploy-konfigis `.env`/stack-env) — demo-kood kaitstud valdadele
  - `_check_access`: avalikud vallad vabalt; kaitstud nõuavad koodi (`?token=` või `X-Access-Token` päis), muidu 403
  - Kaitse endpoiintidel: `/api/maps/{vald}`, `/api/maps/{vald}/{layer}`, `/api/report.pdf`
  - **Logimine:** iga andmepäring `data/logs/access.log` (JSONL): aeg, IP (X-Forwarded-For), vald, kiht, staatus, UA, kas koodiga. Tokenit ennast ei logita.
- **Frontend:** rippmenüüs kaitstud vallad `(kaitstud)`, lukustatud; sidebar-is "Demo-kood" sisend — õige kood avab need (token localStorage-s). Tutvustusleht: Valga `avalik`, teised `kaitstud 🔒`.
- **Test:** Valga 200 ilma koodita, Otepää/Võru/Tõrva 403 ilma / 200 koodiga (mõlemas serveris).
- **Token:** `1-GoRZebxS-0bRyElTzsYEHDsYyF5WWQ` (ohmu `.env`, hetzner stack-env). Deploy: gogs `8ed1c82`.

## 2026-08-07 — A: Tõrva vald (4. referents)

- **Tõrva vald analüüsitud** täisahelaga: ADS hooned + KÜ + kataster (7610 KÜ) + building_population (kalibreeritud 5 777) + gravity + export + preprocess.
- **Tulemused:** 861 väljapääsupunkti, 5 370 kohalikku lõiku, 67 kriitilist lõiku, lõksus 299. Rahvastiku variandid: addr 6 004, res 7 386, ads 4 679. Peamine kalibreeritud = 5 777 (täpne).
- **Parandus `report.py`:** tolerantne puuduvatele joonistele (overview/pop_analysis) — Tõrva raport ei kukuks, kui joonis puudub. `torva_overview.png` loodi `valga_analysis.py` refined-fallbakiga.
- Tõrva on nüüd 4. `valmis` vald atlases (Valga, Otepää, Võru, Tõrva). Deploy: ohmu + hetzner (gogs 512354b), raport 1354984 bytes mõlemas.
- Referentsileht näitab Tõrva (uue valla lisanud).

## 2026-08-07 — D: asustuskonteksti filter (suvilad välistatud)

- **Probleem:** `res`-variant (aadressiga + ilma aadressita yes-hooned 50–200 m²) ülehinnas Otepääl/Võrus (suvilad kuurort/metsas): res = 15 308 / 26 311 vs tegelik 6 225 / 10 310.
- **Parandus:** `building_population.py` — ilma aadressita `yes`-hoone loetakse elamuks **vaid siis, kui see asub aadressiga elamu lähedal (≤300 m, asustuskontekst: küla/taluõu)**. Üksikult metsas asuvad suvilad välistatakse (cKDTree kauguskontroll).
- **Tulemused:**
  | Vald | res enne | res pärast | mõju |
  |------|----------|-----------|------|
  | Valga | 23 732 | **18 738** | −21% (aadressikate puudulik — ilma aadressita elamud säilivad) |
  | Otepää | 15 308 | **9 383** | −39% |
  | Võru | 26 311 | **14 845** | −44% |
- Valga res-extra (ilma aadressita elamud küla juures): 6 384 → 1 393. Peamine `population` on endiselt kalibreeritud ametliku arvuga (Valga 14 813, Otepää 6 225, Võru 10 310).
- Deploy: ohmu + hetzner (gogs ffac882), kontrollitud pop 14 813 mõlemas.

## 2026-08-07 — KOV presentatsioon: referentsileht + raportite täiendus

- **Referentsileht `/tutvustus`** (atlas.see1.ee): 3 demo valda (Valga/Otepää/Võru) kaartidega — elanikud (kalibreeritud), väljapääsud, kriitilised lõigud, lõksus jääv elanikkond; meetod, valideerimine (Spearman 0.32–0.38), hinnad. Kaardil link "tutvustus ↗", kaart toetab `?vald=<id>` (tutvustusleht avab õige valla).
- **Raporti täiendus:** `Tabel 2 — Liikluskoormus`: 10 kõige koormatud kohalikku lõiku (kaudne päeva sõidud) + 10 liiklustandaimat riigitee lõiku (AKÖL) + omand. Andmed `{prefix}_traffic.csv` (genereerib preprocess_web.py gpkg-st).
- **Demo-stsenaarium + kontaktid:** `07_Müük/Demo stsenaarium ja kontaktid.md` — 5-min demo struktuur, olulised sõnumid, Q&A, kontaktide raamistik.
- Deploy: ohmu + hetzner (gogs 8bf6b44, 80c488c), kõik kontrollitud.

## 2026-08-06 — Popup: katastriüksused CLICK_PRIORITY-s (kinnistule klõps)

- **Probleem:** Otepää vallas Kesknurme/Karumäe kinnistutele klõpsates näitas popup "Otepää vald" (valla piir), mitte katastri infot. Paljudel teistel kinnistutel näitas õigesti.
- **Uurimine:** andmetes oli kinnistutel info olemas (Eraomand, sihtotstarve). Põhjus veebirakenduses: `CLICK_PRIORITY` loendist puudus `katastriuksused` — kinnistul, kus pole teed/väljapääsu, langes `pickFeature` fallbackina `feats[0]`-le (suur boundary polügoon → "Otepää vald"). Teedega kinnistud näitasid õigesti, sest teed on prioriteedis enne boundary'd.
- **Parandus:** `web/index.html` — `CLICK_PRIORITY` lisatud `katastriuksused` enne `boundary`. Image rebuild mõlemas serveris (koodimuudatus), deploy ohmu + hetzner (gogs 931097d).
- **Kõrvalleid:** valla bbox-filtrisse jääb 1043 teiste valdade kinnistut (valla piiri välised) — teadmiseks, ei muudetud.

## 2026-08-06 — Omandi sidumine kõigi katastriüksustega (eramaa kajastub)

- **Probleem:** kasutaja märkas, et tee 10103476998–10103490195 (Otepää, track) all olev maa on eramaa (Kalda, KÜ 60802:002:1030, Eraomand), aga see ei kajastu katastriinfos. Ka teistel erateedel puudus katastriomand.
- **Uurimine:** tee kulgeb 423 m üle Kalda eramaa (MAATULUNDUSMAA) ja 39 m üle TRANSPORDIMAA (Priipalu-Kuigatsi tee). Otepääl oli 1058 lõiku teeregistri `omand=Eraomand` aga `omand_kat=None` — põhjus: `export_qgis.py` sidus omandi **ainult TRANSPORDIMAA** sihtotstarbega katastriüksustelt, eramaa (teed ümbritsevad KÜ-d) jäi arvestamata.
- **Parandus (export_qgis.py §4):**
  1. Omandi sidumine nüüd **kõikidest** katastriüksustest (mitte ainult TRANSPORDIMAA) — teede all olev eramaa kajastub.
  2. Omand valitakse **lõikumispikkuse summa** järgi (levinum/tegelik osa), mitte KÜ-de arvu loenduse järgi. Kuna sjoin lähtestab indeksi, säilitatakse algne indeks `_oid` veeruna (samuti teeregistri omandi sidumises — oli sama indeksi viga).
- **Tulemus:** Kalda tee mõlemad suunad nüüd `omand_kat=Eraomand` (eramaa). Otepää: Eraomand 5001 lõiku, Munitsipaalomand 1545, Riigiomand 451. Kõigil 3 valla teedel on nüüd katastriomand (varasem `omand_kat=None` kadus).
- **Deploy:** ohmu (8074) + hetzner (atlas.see1.ee) uuendatud, gogs commit dc49bd5.

## 2026-08-04 — Veebiatlas + esimesed vallad

- **F0:** Veebiatlase algversioon `liiklusatlas` (FastAPI + MapLibre GL + PDF-raport)
  - `preprocess_web.py` — gpkg → GeoJSON kihid
  - `server.py` — API `/api/maps/*`, `/api/report.pdf`
  - `report.py` — A4 PDF (reportlab)
  - `web/index.html` — MapLibre kaart
  - Gogs repo `ardo/liiklusatlas` loodud
  - Deploy: ohmu (dev, 8074) + hetzner (prod, `atlas.see1.ee`, traefik + Let's Encrypt)
  - DNS: A-kirje lisatud; AAAA eemaldatud (hetzner IPv6 katki)
- **F1:** Valla valija (79 KOV-i), legend, KOV-selgitused; mitme valla andmestruktuur
  - `municipalities.py` — 79 KOV-i register
  - API `/api/municipalities`, `/api/maps/{vald}/{layer}`
- **F2:** Üldistatud pipeline + Otepää vald
  - 4 analüüsiskripti üldistatud (`--place`/`--prefix`)
  - `run_municipality.py` — orkestreerija
  - Otepää vald analüüsitud (2. vald)
  - Raport valla parameetriga (`?vald=`)
- **F2b:** Võru vald (3. vald) + pipeline parandused
  - `--results-dir` — väljund `liiklussagedus/results/` (mitte pipeline/results)
  - gravity-le `--skip-plot` tugi
  - pipeline cache/data `.gitignore`-isse
- **Obsidian:** `Doktoritöö/Liiklussageduse kaudne hindamine/` loodud — struktureeritud märkmed metoodika ja tulemuste kohta
- **Parandused (veebiatlas):** valla-spetsiifilised rühmakoodid (`VAL_`, `OTE_`, `VOR_` — mitte `VLG_`), `_pop_` failinimede ühtlustamine (population kirjutas `{prefix}_catchment.csv`, tarbijad otsisid `{prefix}_pop_catchment.csv` → väljapääsupunktide andmed puudusid Otepääl/Võrus), popup-id näitavad õiget valla nime + null-kaitse
- **Ühtne gravitatsioonipõhine süsteem:** väljapääsupunktide rahvastik/liikumised arvutatakse nüüd gravitatsioonimudeliga (mitte ainult lähim-jaotusega):
  - `valga_population_analysis.py` kirjutab `{prefix}_pop_node_population.csv` (sõlme-taseme rahvastik)
  - `gravity_exit_analysis.py` §9 loeb selle, liidab iga sõlme rahvastiku selle gravitatsioonipõhise parima väljapääsupunkti alla → `{prefix}_gravity_exit_population.csv` (`gravity_population`, `gravity_trips`, `nearest_population` võrdluseks)
  - `export_qgis.py` määrab `pop_catch`/`daily_trips` gravitatsiooniväärtustega
  - Popup näitab "Elanikke (gravitatsioon)" + lähim-jaotuse võrdluse
  - Tulemus: suuremad keskused tõmbavad rahvastikku (nt Valga suurim väljapääs: gravity 1 682 vs nearest 83)
- **Pehme gravity-jaotus (nulli parandus):** hard-assignment (iga sõlm AINULT parimasse väljapääsu) jättis väiksed põhikomponendi punktid tühjaks (Valga 57/71, Otepää 27/28, Võru 28/36 pop=0). Asendatud probabilistliku jaotusega:
  - `weight(e) = (pop_e + 1) / (impédance/1000)²` — iga sõlme rahvastik jaotatakse kõigi väljapääsupunktide vahel proportsionaalselt
  - Nüüd kõik põhikomponendi punktid saavad mitte-null gravity-rahvastiku
- **ID-d popupides:** teedel `osm_u–osm_v`, väljapääsupunktidel `id` (exit_node) — vigade kontrollimiseks
- **OSM-hooned rahvastiku proksina (WorldPop asendus):** WorldPop-i 5 km omistamisraadius "imeb" linna rahvastikku põlluteede sõlmedesse (Otepää sõlm 281707587 sai 40.5 elanikku, kuigi teedegrupil OTE_0141 pole maju). Uus meetod:
  - `pipeline/building_population.py` — aadressiga hooned (eluruumid) → lähim tee sõlm (max 300 m), 2.2 inimest/hoone, korterelamu 12
  - Tulemus: OTE_0141 → 0 elanikku, OTE_0005 → 1 279 (Sihva, maju on), sõlm 281707587 → 0
  - Valla kogurahvastik realistlik: Valga 17 348, Otepää 6 607, Võru 9 622
- **Kahte rahvastiku varianti (VAL_0193 juhtum):** Valga grupp VAL_0193 (teeharud riigitee "Puurina" küljes) — sõlmede lähedal `building=yes` hooned ilma aadressita:
  - `pop` (aadressiga) = 0 — Valgas aadressikate puudulik
  - `pop_all` = 26.4 elanikku, 53 sõitu
  - Lahendus: arvutatakse mõlemad variandid läbi kogu ahela (building_population → gravity shares → export → veeb). Popup näitab mõlemat, kui erinevad.
  - Tulemused: Valga addr 17 348 / all 30 895; Otepää 6 607 / 22 714; Võru 9 622 / 40 579
  - **Kalibreerimine KOV tegelike andmetega on järgmine samm** (all ülehinnab suvilate tõttu, addr alahindab ilma aadressita maju)
- **Kombineeritud rahvastik (res):** aadressiga + ilma aadressita `building=yes` hooned 50–200m² (EPSG:3301 pindala). Kuna `all` on tugevalt ülehinnatud ja `addr` on valla tasandil täpseim:
  - Popup: "Elanikke (aadressiga)" peamine + "Elanikke (sh ilma aadressita)" (res) lisainfo
  - VAL_0193: addr=0, res=13.2 elanikku/26 sõitu — ilma aadressita elamud kaetud
  - Valla kogurahvastik: Valga addr 17 346 / res 23 716; Otepää 6 610 / 15 309; Võru 9 622 / 26 311
  - **Uurimismärkus:** privaatsuslävi (alla 4=0) EI ole põhjus — WorldPop on määritud, Statistikaamet kasutab cell key't. Otepääl on 7951 ilma aadressita hoonet (suvilad) — pindala üksi ei erista; asustuskonteksti kalibreerimine KOV andmetega on tuleviku samm
- **ADS-i (riiklik aadressiregister) integreerimine:** `pipeline/ads_buildings.py` laeb Maa- ja Ruumiameti ADS-i WFS-ist (`aks.geoportaal.ee/aks-ogc`, kiht `ads_hoone_a`) kõik valla hooned — **kõik aadressiga** (Valga 17 452 vs OSM 14 728):
  - `population_ads` = ADS-i hooned (võrdluseks, ülehinnatud — kõrvalhooned/suvilad)
  - Peamiseks jääb **OSM-addr** (valla tasandil täpne: Valga 17 346, Otepää 6 610, Võru 9 622)
  - VAL_0193: OSM-addr 0, **ADS 22** — riiklik register kinnitab maju; popup näitab "ADS (kõik hooned)" võrdluseks
  - Uurimine: 96% OSM aadressita hoonetest <100m ADS-hoonest; EHR-i sihtotstarve (`ehr_kood`) on tuleviku täpsustus eluhoonete eristamiseks
- **ADS-i parandus (unikaalsed aadressid):** VAL_0193 väljapääsupunktide ümber oli ADS-is 22 hoonet, aga ainult ~5 **unikaalset aadressi** (taluõus elamu + mitu kõrvalhoonet samal aadressil). **Aadress on liikumiste aluseks, mitte hoonete arv.** Parandus: `_assign_unique` loeb iga sõlme jaoks unikaalseid aadresse. Tulemus: VAL_0193 ADS 22 → 4.4 elanikku; Valga ADS 25 562 → 13 031; Otepää 20 165 → 9 910; Võru 37 450 → 17 304
- **Kalibreerimine Rahvastikuregistri ametliku rahvaarvuga:** kasutaja idee "elanikud proportsionaalselt eluruumi aadressidele" rakendatud:
  - `--official-pop` parameeter building_population.py-s; `skaala = ametlik / OSM-addr hooned`
  - Ametlikud arvud: Valga 14 813, Otepää 6 225, Tõrva 5 777 (2026), Võru 10 310 (2024)
  - Tulemus: valla kogurahvastik = ametlik arv, jaotus proportsionaalne aadressitihedusega
  - Popup korrastatud: "ADS (kõik hooned)" → "ADS (aadressid)", eemaldatud segav "Lähim-jaotus"
- **Uuritud ametlikku rahvastikuinfot:** Statistikaamet RV0291U (valla rahvaarv), REL2021 "Leibkonnad ja perekonnad". **Leibkonnad ja ruutstatistika (1km/100m) on tulevikuplaan** — leibkonna-põhine liikumine (kogu pere sõidab koos linna) on teaduslikult põhjendatud lähenemine
- **Arenduse töövoog:** kogu skriptide käitamine ja testimine toimub `ohmu`-l (võimas arvuti), chat käib lokaalselt; ohmu-l tehtud muudatused jõuavad Syncthing-iga tagasi lokaalsesse git-reposse

## Tehtud otsused ja õppetunnid

- **Väljundi asukoht:** pipeline skriptid peavad kirjutama `liiklussagedus/results/`, sest `preprocess_web.py` otsib sealt — kinnitada `--results-dir` igas etapis
- **Failinimede konventsioon:** `valga_population_analysis.py` kirjutab `{prefix}_pop_*.csv` (prefiks saab `_pop`-lõpu), gravity/export otsivad sama mustrit. Valga töötas juhuslikult (ajalooline prefiks `valga_pop`); ühtlustada uute valdadega
- **gpkg-otsing:** `preprocess_web.py` leidis `voru_qgis.gpkg` ka `voru-linn` jaoks — klapp ainult täpse nimega + `-vald` sufiksi erandiga, mitte `-linn` päisega
- **WorldPop alahindab hõreasustust:** elanike arv catchment'is on tunduvalt väiksem tegelikust — vajab validatsiooni/kalibreerimist
- **Gravitatsioon `switched` = 0:** madala tihedusega valdades ei muuda gravitatsioonikorrektsioon valikuid — tuleb uurida, kas alpha on liiga väike või on see geograafiline reaalsus
- **AAAA kirje:** ei tohi lisada, kui server kuulab ainult IPv4-l

## Tuleviku sammud

- [ ] Teaduskirjanduse kogumine (n8n)
- [ ] Valideerimine riigiteede loendustega
- [ ] Põhiartikli koostamine (3 valda)
- [ ] Müügipaketi ettevalmistus
- **Katastriüksuse (KÜ) põhine ADS-omistamine:** kasutaja idee aadress kanname sellele teedevõrgule, kus kataster teega kokku puutub, mitte kauguse järgi rakendatud:
  - Uus pipeline/ads_ky.py — AKS WFS kiht aks:ads_ky (KÜ tunnus orig_tunnus, taisaadress), sama teenus mis ADS-hooned
  - Iga ADS-hoone → KÜ (ruumiline); KÜ-tee lõikumiskoha lähim sõlm; fallback kauguspõhine
  - Lahendas Loigu juhtumi: elamu 356m teest, aga KÜ puutub teega → aadress jõuab õigele väljapääsule
  - Tulemused (üks aadress = üks kord): Valga 12 438, Otepää 9 163, Võru 15 607 (varem 13 031 / 9 910 / 17 304)
- **ADS-i täpsusparandused (2026-08, teine voor):**
  - **KÜ-tee otspunkti omistamine:** aadress omistatakse lõikuva tee otspunktile (u/v), mitte geomeetriliselt lähimale suvalisele sõlmele. Parandas 73 valet omistust — nt Loigu (KÜ 0740) läks ekslikult Kungla sõlmele 13645879022, väljapääs näitas 4.4. Nüüd läheb Loigu õigesse komponenti (846244516), Kungla väljapääs 13645879019 näitab 2.2 (1 talu).
  - **EE+ehr filter:** loendatakse AINULT ehitisregistris olevad elamud (adob_liik=EE JA ehr_kood olemas). Välistab mitteeluruumid (kirik, laut, ait, suvila) — Valga 1 289 aadressi.
  - Tulemused (ADS, EE+ehr + KÜ): Valga 8 978, Otepää 6 733, Võru 12 044 (varem 12 438 / 9 163 / 15 607)
- **ADS-i topeltloenduse parandus (2026-08):** kasutaja märkas, et VAL_0193/VAL_0532 piirkonnas on ADS-arvud kahtlased. Uurimine: isoleeritud komponendi 2 väljapääsu (846244516, 846244647) poolitamine 5.5+5.5 on õige (kogusumma 11.0 = 5 aadressi, mõlemad legitiimsed väljapääsud). AGA leiti tõeline topeltloendus: `_unique_addrs` fallback luges ühte aadressi mitu korda, kui selle hooned olid eri sõlmede lähedal (nt Männi tn 5 4×). Parandus: üks aadress = lähim sõlm + globaalne dedup. Mõju: Valga 8 978→8 956, Otepää 6 733→6 720, Võru 12 044→12 039.
- **Dev/prod andmelõhe parandus (2026-08):** ohmu dev-server näitas vanu andmeid (13645879019: pop_ads 4.4), prod uusi (2.2). Põhjus: andmed on image'i sees ja `docker-compose up -d` ilma `--build`-ita ei ehitanud uuesti. Lahendus: `data/` bind-mount mõlemas serveris (`./data:/app/liiklusatlas/data`) — uuendamisel piisab `git pull` + restart. README uuendatud. Kasutaja kinnitas, et 2.2 el + 4.4 sõitu (Kungla) on õige loogika (ei muudeta 1 sõiduks).
- **Popup täiendus (2026-08):** väljapääsupunkti popup näitab nüüd eraldi "ADS aadresse" (aadresside arv = pop_ads/2.2) ja "ADS elanikke" (pop_ads, 1 kümnendkoht + sõidud). Varem näitas ühte ümardatud arvu ("ADS (aadressid): 2"), mis oli eksitav — 1 aadress andis 2 (ümardatud 2.2 elanikku). Nüüd: Kungla ID 13645879019 → "ADS aadresse: 1, ADS elanikke: 2.2 (4 sõitu)" — võimaldab kontrollida aadresside/eluruumide arvu.
- **KOV presentatsioon: raport + hinnapakkumine (2026-08):**
  - **Kriitilised teelõigud uue meetodiga:** gravity_exit_analysis.py arvutab nüüd sild-servad (nx.bridges) ja lõksus jääva rahvastiku — eraldi veerud trapped_population (kalibreeritud) ja trapped_ads (ADS EE+ehr). CSV: {prefix}_pop_critical_edges.csv, joonis {prefix}_critical_edges.png (kaart + tulpdiagramm). Tulemused: Valga 194 lõiku (lõksus 1638 / ADS 557), Otepää 58 (458/147), Võru 159 (1127/730).
  - **report.py üldistamine:** prefiksipõhine, lisatud kokkuvõtteleht (rahvaarv kalibreeritud, väljapääsud, ADS, kriitilised lõigud) + ADS-veerg tabelis. Kokkuvõte kasutab kalibreeritud gravity_andmeid (14 814).
  - **Hinnapakkumise mall:** uus pipeline/offer.py → data/report/hinnapakkumine.pdf, serveeritakse /api/offer.pdf. 07_Müük uuendatud.
  - Kõik 3 valla raportid + hinnapakkumine saadaval atlas.see1.ee/api/report.pdf?vald=... ja /api/offer.pdf
- **Raporti failinimed valla prefiksiga (2026-08):** data/report/{vald}/ kaustades olid kõik failid valga_* nimega (preprocess_web.py standardiseeris valga_* alla). Parandus: failid on nüüd {prefix}_* (nt otepaa_overview.png, voru_pop_critical_edges.csv), report.py tuletab prefiksi raporti kausta nimest (_prefix_for). Dev/prod ühtsed, kõik 3 valla raportid genereeruvad.
- **Valideerimine 2025. aasta riigiteede loendustega (2026-08):**
  - Laeti Transpordiameti 2025. aasta liiklusloendus (4564 homogeenset lõiku, AKÖL)
  - Sidumine: väljapääsupunkt ↔ lähim riigitee serv (ref) + piki-tee kaugus → õige loenduslõik
  - Tulemused: kõrvalmaanteed Spearman 0.316 / log-log 0.337; tugimaanteed 0.302/0.322; teisaldatav loendus 0.379/0.387
  - Põhimaanteed negatiivne (-0.587) — läbisõit/transit, mida kaudne meetod ei hõlma (piirang)
  - Järeldus: meetod hindab hästi **suhtelist lokaalset** koormust; absoluutne tase vajab kalibreerimist
  - Failid: `liiklussagedus/results/validation/loendus_2025.csv`, `validation_2025.csv`, joonis `validation_2025.png`
- **Liiklussageduse visualiseerimine veebirakenduses (2026-08):**
  - **Kohalikud teed:** igale lõigule lisatud kaudne koormus (`exit_trips` = tema parima väljapääsu päeva sõidud, `trips_per_km`) — värv/laius trips järgi (hõre → tihe)
  - **Riigiteed:** igale lõigule lisatud loenduse AKÖL (`ref`-matching loendus_2025.csv-ga) — värv loenduse järgi (hõre → tihe), popup näitab sõidukit/ööp
  - Legend uuendatud: "Riigiteed (loendus)" + "Kohalikud teed (kaudne koormus)"
  - Teostus: export_qgis.py lisab `ref` major_roads'ile, `exit_trips`/`trips_per_km` local_roads'ile; preprocess_web.py ATTR_MAP; web/index.html STYLE + popup + legend
  - Katvus: Valga 5215/6779 local lõiku trips-iga, 2255/2477 major lõiku AKÖL-iga; Otepää/Võru analoogselt
- **Liiklusvisualiseerimise parandus (2026-08):** kasutaja märkas, et uus värviskeem "kustutas" hõredad teed (helehall valgel taustal). Parandus: taastati algne tee-värviskeem (riigiteed klassi järgi, kohalikud teed impedantsi järgi) — teed jäävad alati nähtavaks. Liiklus kuvatakse nüüd **overlay-kihina** tee peal (local_traffic/major_traffic): riigiteedel loenduse AKÖL (sinine kate), kohalikel teedel kaudne trips (punane kate). Legend ja checkboxid uuendatud. Andmed (trips/akol atribuudid) on tee kihis olemas ja popup näitab neid.
- **Teede omandisuhe teeregistrist (2026-08):**
  - Allikas: Teeregistri avalik WFS (https://teeregister.mnt.ee/290424/wfs), kiht ms:n_omand (teede omandisuhted)
  - Uus pipeline/teeregister_omand.py — laadib omandilõigud bbox-i kaupa (tee_number, om_omand_val, geomeetria)
  - export_qgis.py: spatial join (intersects) teeregistri omandilõikudest meie teedele → atribuut 'omand' (Riigiomand/Eraomand/Munitsipaalomand/Avalik-õiguslik/Segaomand)
  - Teedevõrku EI muudeta — ainult omand atribuut lisatud; popup näitab omandit
  - Katvus: Valga local 3762/6779, major 1907/2477; Otepää local 4242/7107, major 2037/2617; Võru local 7479/14999, major 3231/4539
- **Katastriüksused kaardil + teede omandivärv (2026-08):**
  - **Uurimistulemus:** Maa-ameti katastriüksused on **avaandmed** (litsents, uuenevad igal ööl), allalaaditavad maakonna kaupa GPKG/SHP/JSON (s3.pilw.io). Atribuudid: tunnus, l_aadress, **siht1 (sihtotstarve: TRANSPORDIMAA = teede maa)**, **omvorm (omandivorm: Eraomand/Riigiomand/Munitsipaalomand/Segaomand)**, pindala.
  - **Uurimisobjekt:** TRANSPORDIMAA + Eraomand = **erateed**. Valgas 169 KÜ eraomandis (nt "Roobe-Kimma tee"). Kataster on täielikum omandiallikas kui teeregister (Valga 4874 vs 3762 lõiku).
  - **Teostus:** uus pipeline/kataster_laadimine.py (maakonna GPKG laadimine, bbox-filter); export_qgis.py lisab teedele omand_kat (spatial join TRANSPORDIMAA) + katastriüksuste kiht gpkg-sse; preprocess_web ATTR_MAP; web/index.html uued linnukesed "Katastriüksused" ja "Teede omandivärv" (eratee punane, riigitee sinine, munitsipaal roheline) + popup.
  - **Erateed (lõigud/pikkus):** Valga 102/29.4 km, Otepää 194/53.1 km, Võru 278/86.0 km.
- **Katastriüksuste omandipõhine värviskeem (2026-08):** katastriüksused värvitud omandivormi järgi — riigiomand sinine, KOV (munitsipaal) roheline, eraomand punane, segaomand lilla, kinnistamata eraomand oranž, avalik-õiguslik türkiis, teadmata/tühi hall. Läbipaistvad täidised (teed jäävad nähtavaks), legend uuendatud. Omandiväärtused: Eraomand, Riigiomand, Munitsipaalomand, Omandi ulatus selgitamisel, Segaomand, Kinnistamata eraomand, Avalik-õiguslik omand, Reformimata maal asuv.
- **Lõigukoormuse parandus (all-or-nothing, 2026-08):** kasutaja märkas, et VAL_0032 ja VAL_0039 näitasid kaardil suurt 'päeva sõidu' arvu. Uurimine: export_qgis.py omistas igale kohaliku tee lõigule KOGU väljapääsupunkti trips-arvu (nt 174), mitte proportsionaalset osa → 134× üleloendus. Parandus: iga lõigu koormus = nende sõlmede trips-arv, kelle teekond väljapääsuni läbib just seda lõiku (BFS-puu, post-order summa). Tulemus: VAL_0032 → 0 (tööstusala, elanikke pole), VAL_0039 (Sireli/Looduse elamutänavad) → max 34 trips; Valga lõikude summa 29 993 ≈ väljapääsupunktide 29 632. Suurimad koormused nüüd elamutänavatel (Herne 192, Heina 154, Koidu 139).
- **Major_roads värvisüsteemi parandus (2026-08):** kasutaja märkas, et kolm secondary teed (Otepää) on eri värvi — punane, lilla, kollane. Uurimine: (1) 281701578–281864449 on `secondary_link`, mis polnud match-loendis → langes fallback-värvile #e91e63 (punane); (2) 281726553–2629675775 (secondary, AKÖL 1426) sai sinise major_traffic overlay-katte, mis segunes kollase baasvärviga lillaks. Parandus: (1) lisatud kõik *_link tüübid baasklassi värvi alla (secondary_link→#ffb74d jne), (2) major_traffic ja local_traffic overlay'd nüüd solid-värvid (läbipaistmatud), mis asendavad baasvärvi, mitte ei segune. Iga riigitee on nüüd kas klassivärvi või liiklusvärvi, ühtne loogika.
- **Linnukeste + omandivärvi parandus (2026-08):** (1) linnukesed ei töötanud alglaadimisel — loadMunicipality lisas kihid ilma checkboxi olekut arvestamata (nt Kohalike teede rühmad märkimata aga kuvati). Lisatud applyCheckboxes(), mis rakendab checkboxi oleku pärast kihi lisamist. (2) OTE_0005 lõik 11149625980–415514401 jäi ilma omandivärvita: asub MAATULUNDUSMAA katastriüksusel (Aakre metskond 49), mitte TRANSPORDIMAA-l → omand_kat=None. Parandus: omandivärv kasutab omand_kat fallbackiga omand (teeregister) → nüüd Riigiomand sinine. Otepääl 1228 lõiku said nii värvikatte.
- **Haavatavusanalüüs kõikidele väljapääsupunktidele (2026-08):** varem hõlmas haavatavusanalüüs ainult TOP 30 WorldPop-põhist väljapääsu (pop_pop_vulnerability.csv vanast valga_population_analysis.py-st), ülejäänud kuvati 'tavalistena'. Parandus: (1) gravity_exit_analysis.py arvutab nüüd haavatavuse kõikidele põhikomponendi väljapääsudele kalibreeritud rahvaarvuga (Dijkstra detour); (2) isoleeritud komponendid elanikega (ainus väljapääs — lõksu jäämine) märgitakse samuti haavatavaks. Kaart: haavatav punane (detour>0 või isoleeritud+pop). Tulemused: Valga 71 detour + 356 isoleeritud+pop = 427/1048 haavatavat; Otepää 28+466=494/1123; Võru 36+707=743/2007.
- **Menüü kihtide eraldamine (2026-08):** "Riigiteed (maantee-klass)" ja "Kohalikud teed" on nüüd omaette linnukesed, mis kuvavad ainult klassivärvi (ilma liikluseta). Liiklus on eraldi linnukestega: "Riigiteede liiklus (AKÖL)" ja "Kohalik liiklus (kaudne)", vaikimisi välja lülitatud. Legendi värvid vastavad solid-värvidele.
- **Kohalikud teed ühtne klassivärv (2026-08):** kasutaja märkas, et kolm kohalikku teed (Otepää OTE_0011) olid erinevat värvi — põhjus: local_roads põhivärv kasutas impedance (kaugus väljapääsuni) gradienti (0→#f6c177, 40+→#b4637a). Parandus: kõik kohalikud teed on nüüd ühtset värvi #f6c177; impedance jääb andmetesse/popup-i, ei määra enam värvi. Liiklus (local_traffic) jääb eraldi linnukese taha.
- **Riigiteede ja kohalike teede värvide eristamine (2026-08):** kohalikud teed olid oranžid (#f6c177), mis sarnanesid riigiteede sekundaar/tersiaalsete värvidega (#ffb74d/#ffd54f). Muudetud kohalikud teed sinakashalliks (#7c8ea0) — selgelt eristuvad. Menüüsse lisatud värvitähised iga linnukese ette (samad värvid kui kaardil).

## 2026-08-11 — Veebirakenduse parandused ja täiendused (UI, serveri vahemälu, pipeline)

**Demo-koodi avamise viga (kriitiline) [web/index.html]:** `btn-access` handler luges sisestatud koodi (`val`), kuid saatis valideerimispäringu ilma koodita (`apiFetch(api/maps/...)` ilma `X-Access-Token` päiseta) → server vastas alati 403 → esmakordne avamine ebaõnnestus ka õige koodiga. Parandatud: päring saadab nüüd `X-Access-Token: <sisestatud kood>`. Tühi sisestus hoiatab.

**Tugevam kihiladu [web/index.html]:**
- `loadMunicipality` kontrollib nüüd **manifesti** (`munis[].layers`) ja laeb ainult olemasolevad kihid — puuduv kiht ei murra enam kogu valla laadimist; lisatud try/catch + veateade.
- `addLayer` viskab selge vea 404 korral; arvutab piirid (`layerBounds`) laadimisel, et `fitTo` ei sõltuks MapLibre sisemisest `_data`-st.
- `local_groups` popup talub puuduvaid `length_km`/`edges` (null → „—") — varem krahhis `.toFixed(1)`.

**Serveripoolne PDF-vahemälu [server.py]:** raport ehitatakse uuesti ainult siis, kui sisendfailide mtime muutus (`_report_cache`). Mitmekordse päringu korral (sama valla raport korduvalt) jääb CPU-aeg kokku; brauserile läheb ikka `no-cache`. Kontrollitud: esimene ehitamine 0.86 s, vahemälust 0.80 s.

**Pipeline [run_municipality.py]:** lisatud etapp 0 — puuduvate andmeallikate automaatne laadimine (ADS hooned, KÜ, kataster `--maakond`, teeregister omand+lepingud); `--refresh-data` sunnib uuesti; `--skip-legacy` jätab vana WorldPop-etapi vahele. `building_population.py --official-pop` jookseb pärast legacyt ja kirjutab tänapäevase sõlme-rahvastiku. Valla-→maakonna kaart (MAKOND) katastri laadimiseks.

**Gravity fallback [gravity_exit_analysis.py]:** uutel valdadel puudub WorldPop `_pop_catchment.csv` → vanasti kõik väljapääsud tõmbejõuta (uniform). Nüüd tuletatakse tõmbejõud hoonepõhisest sõlme-rahvastikust (`_pop_node_population.csv`) lähim-väljapääsu jaotusega (`exit_gravity` α-log).

**BFS-optimeerimine [export_qgis.py]:** `queue.pop(0)` (O(n)) → `collections.deque.popleft()` (O(1)). Suurtel võrkudel märkimisväärne kiirenemine.

**.gitignore:** `data/` → `data/logs/` (andmefailid lähevad git'i kaasa; ainult külastajate loginid jäävad maha, privaatsus).

**README:** dokum. uue valla lisamise töövoog (andmeallikate automaatlaadimine, `--skip-legacy`, git data/ kaasa).
