# Návod pro AI agenty: připojení dat do DatovéMapy

Tento dokument je určený AI agentům, kteří připravují data pro portál DatováMapa. Poskytovatelem může být kdokoli, kdo má data s polohou. Popisuje cíl, postup, pravidla a kritéria hotové práce. Člověk, který agenta řídí, najde srozumitelnější verzi v [průvodci pro poskytovatele](https://datovamapa.cz/dokumentace/pro-poskytovatele.md).

## Cíl

Zveřejnit na HTTPS:

1. **manifest** – JSON podle [schématu manifestu](https://datovamapa.cz/schema/0.1/manifest.json),
2. pro každou datovou sadu **zdroj dat** – GeoJSON soubor nebo endpoint podle [schématu dat](https://datovamapa.cz/schema/0.1/data.json) a [OpenAPI kontraktu poskytovatele](https://datovamapa.cz/schema/0.1/poskytovatel-openapi.json), případně existující rastrové dlaždice / WMS,

tak, aby [validátor](https://datovamapa.cz/dokumentace/api.md#validator) vrátil `"valid": true` a co nejméně varování.

## Co si načíst

| Zdroj | Proč |
|---|---|
| [llms.txt](https://datovamapa.cz/llms.txt) | rozcestník celé dokumentace |
| [Protokol 0.1](https://datovamapa.cz/dokumentace/protokol.md) | normativní specifikace – při nejasnosti platí ta |
| [JSON Schema manifestu](https://datovamapa.cz/schema/0.1/manifest.json), [dat](https://datovamapa.cz/schema/0.1/data.json) | přesné typy, limity a popisy polí |
| [OpenAPI poskytovatele](https://datovamapa.cz/schema/0.1/poskytovatel-openapi.json) | kontrakt endpointu, lze z něj generovat server |
| [manifest-kompletni.json](https://datovamapa.cz/priklady/manifest-kompletni.json), [manifest-minimalni.json](https://datovamapa.cz/priklady/manifest-minimalni.json) | platné vzory |
| [data-body.json](https://datovamapa.cz/priklady/data-body.json), [data-plochy.json](https://datovamapa.cz/priklady/data-plochy.json) | platné vzory odpovědí |
| [Katalog](https://datovamapa.cz/zdroje.md) | co už v portálu je – nevytvářejte duplicity, inspirujte se klíčovými slovy |

Pokud umíte používat MCP, připojte se k serveru `https://datovamapa.cz/mcp` (Streamable HTTP, bez autentizace). Nástroje `dokumentace`, `schema`, `priklad`, `validovat_manifest`, `validovat_data` a `katalog` pokrývají vše v tomto návodu. Viz [MCP server](https://datovamapa.cz/dokumentace/api.md#mcp-server).

## Postup

### 1. Inventura dat

Zjistěte, jaká prostorová data poskytovatel má: databáze (PostGIS, MS SQL), GIS soubory (SHP, GPKG, KML, CSV se souřadnicemi), existující API, WMS/WMTS služby. U každého zdroje zjistěte:

- typ geometrie (body / linie / plochy),
- souřadnicový systém (v Česku často **S-JTSK, EPSG:5514** – nutno převést),
- počet objektů a jak často se mění,
- licenci a kdo ji může schválit,
- zda obsahuje **osobní údaje** (jména, rodná čísla, adresy fyzických osob, SPZ…).

### 2. Návrh datových sad

- Jedna sada = jeden druh objektů s jedním způsobem zobrazení. Kontejnery a hlukovou mapu dejte do dvou sad.
- `id` sady i poskytovatele: malá písmena bez diakritiky, číslice, pomlčky (`kontejnery-na-odpad`). Po zveřejnění ho neměňte – je součástí odkazů.
- Volba zdroje:

| Situace | `source` |
|---|---|
| do ~2 000 objektů, mění se nejvýš denně | statický soubor, `"type": "geojson", "mode": "full"` |
| více objektů nebo živá data | endpoint, `"mode": "bbox"`, nastavte `coverage.bbox` a u velkých sad `coverage.minZoom` |
| už existuje WMS / XYZ dlaždice | `"type": "raster"` se šablonou `{bbox-epsg-3857}` nebo `{z}/{x}/{y}`; doplňte `presentation.legend` (barvy a popisky z legendy služby, např. ArcGIS `…/MapServer/legend?f=json` nebo WMS `GetLegendGraphic`) |

### 3. Převod dat

- Souřadnice **WGS84 (EPSG:4326), pořadí `[lon, lat]`**. Pro Česko je to zhruba `[15, 50]`, nikoli `[50, 15]`.
- Zaokrouhlete na 6 desetinných míst (≈ 10 cm), zbytek jen zvětšuje odpověď.
- Polygony musí mít uzavřené prstence (první bod = poslední).
- Každý objekt by měl mít stabilní `id`.
- Vlastnosti (`properties`) jako jednoduché hodnoty – řetězce, čísla, booleany, data v ISO 8601. Žádné HTML.
- Čísla jako čísla (`1100`), ne řetězce (`"1100 l"`); jednotku dejte do `fields[].unit`.

Převod GIS souboru do GeoJSON:

```bash
ogr2ogr -f GeoJSON -t_srs EPSG:4326 -lco RFC7946=YES -lco COORDINATE_PRECISION=6 lavicky.geojson vstup.shp
```

Převod souřadnic v Pythonu:

```python
from pyproj import Transformer

to_wgs84 = Transformer.from_crs("EPSG:5514", "EPSG:4326", always_xy=True)
lon, lat = to_wgs84.transform(x_sjtsk, y_sjtsk)  # always_xy=True vrací [lon, lat]
```

### 4. Manifest

Vyplňte nejen povinná pole, ale i ta, která rozhodují o tom, zda data někdo najde:

- `description` – 1–2 věty: co data obsahují, odkud jsou, jak jsou aktuální.
- `keywords` – 5–15 slov a synonym v češtině, včetně hovorových tvarů (`popelnice` vedle `kontejner`).
- `useCases` – k čemu data pomáhají: `stavba`, `bydleni`, `koupe-pozemku`, `zemedelstvi`, `investice`, `doprava`, `turistika`, `podnikani`, `verejna-sprava`. Podle nich asistent portálu vybírá data k zadání typu „chci stavět v obci X“.
- `category` – jedna z: `uzemi`, `priroda`, `voda`, `rizika`, `energie`, `doprava`, `spolecnost`, `ekonomika`, `infrastruktura`.
- `fields` – každá vlastnost, kterou má uživatel vidět: `label`, `type`, `unit`. Jednu označte `primary` (nadpis v detailu).
- `license` – název a text atribuce. **Licenci si nevymýšlejte**; pokud ji nevíte, zeptejte se člověka.
- `temporal.updated`, `temporal.frequency` – aktuálnost dat.
- `temporal.param` – u dat v čase (nehody, měření, události): klíč parametru typu `range` s roky (`min`/`max` = první a poslední rok), kterým uživatel volí období. Odpověď k tomu má posílat `dm.timeline` s počty po letech (u hodnot v čase, jako je počet obyvatel, místo toho souhrnný `dm.chart`), viz [časový filtr](https://datovamapa.cz/dokumentace/protokol.md#casovy-filtr).
- **Vývoj v čase** – zjistěte, zda mají objekty hodnotu za více období (stavy po letech, měření, ceny). Pokud ano, posílejte ji vždy u každého objektu v `dm.chart`; je-li smyslem sady změna, barvěte podle trendu. Viz [vývoj v čase a trend](https://datovamapa.cz/dokumentace/protokol.md#vyvoj-v-case-a-trend).

### 5. Vizualizace

| Geometrie | Vhodný typ | Poznámka |
|---|---|---|
| body, desítky až stovky | `circle` | barva podle kategorie (`categorical`), popisek přes `label` |
| body, tisíce | `circle` s `cluster` nebo `heatmap` | heatmapa jen pro hustotu, neukazuje jednotlivé objekty |
| linie | `line` | šířka může záviset na hodnotě |
| plochy s hodnotou | `fill` + `interpolate` nebo `step` | kartogram; `opacity` 0.4–0.6, aby byl vidět podklad |
| body nebo plochy, jejichž hodnota se mění v čase | `circle` / `fill` + `color: { "type": "trend" }` | jde-li o změnu (roste / klesá); řada hodnot v `dm.chart` u každého objektu, trend dopočítá portál |
| plochy bez hodnoty | `fill` s jednou barvou | |

Pravidla: barvy hex; kategorie max. ~8 barev; pro hodnoty použijte postupnou škálu od světlé po tmavou; `field` v prezentaci musí odpovídat vlastnosti v datech (a ve `fields`, s číselným typem u `interpolate`/`step`). Má-li hodnota objektu historii, pošlete ji v `dm.chart` při jakékoli prezentaci – i u kartogramu s výběrem roku (zvolený rok v `highlight`).

### 6. Endpoint (jen u `mode: "bbox"` nebo živých dat)

Implementujte `GET` podle [OpenAPI kontraktu](https://datovamapa.cz/schema/0.1/poskytovatel-openapi.json):

- query `bbox=minLon,minLat,maxLon,maxLat` – vraťte objekty, které výřez protínají,
- `zoom` – celé číslo; při malém přiblížení můžete vracet agregace,
- `limit` – nevracejte víc objektů; když je ořežete, nastavte `dm.truncated: true` a `dm.total`,
- vlastní parametry z `params` (rozsah `od,do`, více hodnot `a,b,c`),
- `Content-Type: application/geo+json` nebo `application/json`, HTTPS, odpověď do 1 s,
- neznámé query parametry ignorujte (`lang`, `protocol`, `cursor` můžete pominout).

CORS není potřeba – portál se ptá ze serveru.

Python (FastAPI + PostGIS):

```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/datovamapa/kontejnery")
def kontejnery(bbox: str | None = None, zoom: int | None = None, limit: int = 5000, druh: str | None = None):
    west, south, east, north = map(float, bbox.split(",")) if bbox else (-180, -90, 180, 90)
    druhy = druh.split(",") if druh else None
    rows = db.fetch_all(
        """
        SELECT id, druh, objem, vyvoz::text, ST_AsGeoJSON(geom, 6)::json AS geometry
        FROM kontejnery
        WHERE geom && ST_MakeEnvelope(%s, %s, %s, %s, 4326)
          AND (%s::text[] IS NULL OR druh = ANY(%s))
        LIMIT %s
        """,
        (west, south, east, north, druhy, druhy, limit + 1),
    )
    features = [
        {"type": "Feature", "id": r["id"], "geometry": r["geometry"],
         "properties": {"druh": r["druh"], "objem": r["objem"], "vyvoz": r["vyvoz"]}}
        for r in rows[:limit]
    ]
    return {"type": "FeatureCollection", "features": features, "dm": {"truncated": len(rows) > limit, "ttl": 3600}}
```

TypeScript (Cloudflare Worker / Node, data v paměti):

```ts
// KONTEJNERY: pole GeoJSON Feature s body, načtené při startu (z databáze nebo souboru).
declare const KONTEJNERY: { type: "Feature"; id: number; geometry: { type: "Point"; coordinates: [number, number] }; properties: Record<string, unknown> }[];

export default {
  async fetch(request: Request): Promise<Response> {
    const url = new URL(request.url);
    const [west, south, east, north] = (url.searchParams.get("bbox") ?? "-180,-90,180,90").split(",").map(Number);
    const limit = Math.min(Number(url.searchParams.get("limit")) || 5000, 5000);
    const inside = KONTEJNERY.filter(({ geometry: { coordinates: [lon, lat] } }) =>
      lon >= west && lon <= east && lat >= south && lat <= north);
    return Response.json(
      { type: "FeatureCollection", features: inside.slice(0, limit), dm: { total: inside.length, truncated: inside.length > limit } },
      { headers: { "Content-Type": "application/geo+json", "Cache-Control": "public, max-age=300" } },
    );
  },
};
```

### 7. Validace

Opakujte, dokud nejsou chyby, a projděte každé varování (opravte, nebo vědomě ponechte a zdůvodněte):

```bash
# manifest (bez zveřejnění)
curl -sX POST https://datovamapa.cz/api/validovat -H 'Content-Type: application/json' --data @manifest.json
# data proti konkrétní sadě
curl -sX POST https://datovamapa.cz/api/validovat -H 'Content-Type: application/json' \
  --data "{\"data\": $(cat lavicky.geojson), \"dataset\": $(jq '.datasets[0]' manifest.json)}"
# živý test zveřejněného manifestu a všech zdrojů
curl -s 'https://datovamapa.cz/api/validovat?manifestUrl=https://www.obec-priklad.cz/datovamapa/manifest.json'
```

Odpověď: `{ valid, summary, errors: [{ path, code, message, hint? }], warnings: [...] }`, u živého testu navíc `datasets[]` s dotazem, dobou odezvy a počtem objektů. Význam kódů je v [API portálu](https://datovamapa.cz/dokumentace/api.md#kody-nalezu).

### 8. Předání člověku

Na závěr shrňte:

- URL manifestu a seznam sad (id, název, typ zdroje, počet objektů),
- výsledek živého testu (`summary`, zbylá varování a proč zůstala),
- co musí člověk potvrdit: **licenci a atribuci**, že data neobsahují osobní údaje, kontakt pro portál,
- jak data aktualizovat (skript, cron, zdroj pravdy).

Až člověk potvrdí licenci a obsah, zaregistrujte manifest: `POST https://datovamapa.cz/api/registrace` s `{ "manifestUrl": "…" }` nebo MCP nástroj `registrovat_poskytovatele`. Data budou dostupná jako neschválená (s varováním, mimo katalog), dokud je provozovatel neschválí. Po každé změně manifestu čekají na nové schválení. Podrobnosti: [registrace](https://datovamapa.cz/dokumentace/pro-poskytovatele.md#5-registrace).

## Pravidla

- **Nezveřejňujte osobní údaje** (GDPR). Při pochybnosti data agregujte nebo vynechte a zeptejte se.
- Nevymýšlejte licenci, zdroj ani aktuálnost dat.
- Do `properties` ani `dm` nevkládejte HTML; portál vše zobrazuje jako text.
- Do URL nedávejte tajné klíče – manifest je veřejný.
- Neměňte `provider.id` ani `dataset.id` po zveřejnění.
- Klíče `bbox`, `zoom`, `limit`, `cursor`, `lang`, `protocol` nepoužívejte pro vlastní parametry.
- Max. 5 000 objektů a 15 MB na odpověď, odpověď do 10 s (cílem je do 1 s).

## Kritéria hotové práce

- [ ] Manifest je dostupný na HTTPS a živý test validátoru vrací `"valid": true`.
- [ ] Každá sada má `description`, `keywords`, `useCases`, `category` a (u GeoJSON) `fields`.
- [ ] Licence a atribuce jsou potvrzené člověkem.
- [ ] Souřadnice jsou WGS84 `[lon, lat]`, žádné varování `prohozene_souradnice` ani `mimo_pokryti`.
- [ ] Žádná sada nevrací v testu 0 objektů (`prazdna_odpoved`), pokud to není záměr.
- [ ] Objekty, které mají hodnotu za více období, posílají `dm.chart` (žádné `chybi_graf_vyvoje` ani `trend_bez_grafu`).
- [ ] Odezva endpointů je pod 3 s (`pomala_odpoved`).
- [ ] Data neobsahují osobní údaje.
- [ ] Je popsané, jak se data aktualizují.

## Zadání pro agenta (ke zkopírování)

Člověk může svému agentovi dát tento text:

```text
Připrav naše prostorová data pro portál DatováMapa (https://datovamapa.cz).
Postupuj podle návodu https://datovamapa.cz/dokumentace/pro-ai-agenty.md
(rozcestník dokumentace: https://datovamapa.cz/llms.txt, MCP server: https://datovamapa.cz/mcp).
Zdroje dat: <popiš databáze, soubory, služby>.
Kam zveřejnit: <web / server / repozitář>.
Licence: <např. CC BY 4.0, atribuce „© Obec Příklad“> – jinou si nevymýšlej.
Hotovo je, když živý test validátoru vrací valid: true a projdeš kritéria hotové práce.
Na konci mi předej shrnutí podle kroku 8.
```
