# File Format

A `.yoromaps` file is a single SQLite database containing everything needed for offline maps and routing.

## Overview

The file contains five tables:

| Table      | Purpose                              |
|------------|--------------------------------------|
| `metadata` | Key-value store for database info    |
| `tiles`    | MBTiles-compatible tile storage      |
| `nodes`    | Road graph intersections (vertices)  |
| `edges`    | Road graph segments (edges)          |
| `pois`     | Points of interest                   |

## Schema

### metadata

Stores database-level information as key-value pairs.

```sql
CREATE TABLE metadata (
    key   TEXT PRIMARY KEY,
    value TEXT
);
```

Standard keys:

| Key              | Example value              | Description                     |
|------------------|----------------------------|---------------------------------|
| `schema_version` | `1`                        | Schema version number           |
| `country`        | `ML`                       | ISO country code                |
| `country_name`   | `Mali`                     | Full country name               |
| `bbox`           | `-12.5,10.0,4.5,25.0`     | Bounding box (lon_min,lat_min,lon_max,lat_max) |
| `graph_nodes`    | `142857`                   | Number of nodes in the graph    |
| `graph_edges`    | `187432`                   | Number of edges in the graph    |
| `tiles_count`    | `45230`                    | Number of tiles stored          |
| `format`         | `png`                      | Tile image format               |

### tiles

MBTiles-compatible tile storage using the TMS (flipped Y) coordinate scheme.

```sql
CREATE TABLE tiles (
    zoom_level  INTEGER NOT NULL,
    tile_column INTEGER NOT NULL,
    tile_row    INTEGER NOT NULL,
    tile_data   BLOB NOT NULL,
    PRIMARY KEY (zoom_level, tile_column, tile_row)
);
```

- `zoom_level` — Zoom level (typically 6-14).
- `tile_column` — X coordinate (column).
- `tile_row` — Y coordinate in TMS scheme (flipped from standard XYZ).
- `tile_data` — PNG image data.

!!! note
    The `get_tile()` function accepts standard XYZ coordinates and handles the TMS conversion internally.

### nodes

Road graph intersections (vertices).

```sql
CREATE TABLE nodes (
    id  INTEGER PRIMARY KEY,
    lat REAL NOT NULL,
    lon REAL NOT NULL
);
```

Node IDs correspond to OSM node IDs, so the same intersection has the same ID across different builds from the same OSM data.

### edges

Road graph segments connecting two nodes.

```sql
CREATE TABLE edges (
    id         INTEGER PRIMARY KEY AUTOINCREMENT,
    from_node  INTEGER NOT NULL REFERENCES nodes(id),
    to_node    INTEGER NOT NULL REFERENCES nodes(id),
    distance_m REAL NOT NULL,
    duration_s REAL NOT NULL,
    road_type  TEXT NOT NULL DEFAULT 'road',
    oneway     INTEGER NOT NULL DEFAULT 0,
    name       TEXT DEFAULT ''
);
```

- `distance_m` — Segment length in meters (haversine distance).
- `duration_s` — Estimated travel time in seconds, based on road type speed.
- `road_type` — OSM highway type (e.g., `primary`, `residential`, `track`).
- `oneway` — `1` if this edge is one-way, `0` if bidirectional.
- `name` — Street name from OSM (may be empty).

Indexes:

```sql
CREATE INDEX idx_edges_from ON edges(from_node);
CREATE INDEX idx_edges_to ON edges(to_node);
```

### pois

Points of interest extracted from OSM or added manually.

```sql
CREATE TABLE pois (
    id         INTEGER PRIMARY KEY AUTOINCREMENT,
    lat        REAL NOT NULL,
    lon        REAL NOT NULL,
    yoro_code  TEXT NOT NULL DEFAULT '',
    name       TEXT NOT NULL,
    category   TEXT NOT NULL DEFAULT 'other',
    source     TEXT NOT NULL DEFAULT 'local',
    osm_id     INTEGER,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
```

Indexes:

```sql
CREATE INDEX idx_pois_yoro ON pois(yoro_code);
CREATE INDEX idx_pois_category ON pois(category);
```

## SQLite pragmas

When opening a `.yoromaps` file, the following pragmas are set for performance:

```sql
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = ON;
```

## Direct access

You can query a `.yoromaps` file directly with any SQLite client:

```bash
sqlite3 mali.yoromaps "SELECT COUNT(*) FROM nodes;"
sqlite3 mali.yoromaps "SELECT key, value FROM metadata;"
sqlite3 mali.yoromaps "SELECT COUNT(*) FROM tiles;"
```

Or from Python:

```python
import sqlite3

conn = sqlite3.connect("mali.yoromaps")
conn.row_factory = sqlite3.Row

for row in conn.execute("SELECT key, value FROM metadata"):
    print(f"{row['key']}: {row['value']}")
```

## Compatibility

The `.yoromaps` format is plain SQLite, so it works with:

- Any SQLite client or library
- Django (via the built-in SQLite backend)
- DB Browser for SQLite (for visual inspection)
- Any language with SQLite bindings
