# Population data used by Population Split

The game uses real gridded estimates of residential population, not invented
city weights or a uniform country population. Values represent the **2020
epoch** of the European Commission Joint Research Centre's **GHS-POP R2023A**
dataset. They are modelled estimates, not a live population counter or exact
census counts for the displayed boundaries.

## Sources and reuse

- Population: Schiavina M., Freire S., Carioli A., MacManus K. (2023),
  *GHS-POP R2023A — GHS population grid multitemporal (1975–2030)*,
  European Commission, Joint Research Centre.
  DOI: <https://doi.org/10.2905/2FF68A52-5B5B-4A22-8F40-C41DA8332CFE>.
- Documentation: <https://human-settlement.emergency.copernicus.eu/ghs_pop2023.php>.
- Population source data: 30-arcsecond (~1 km at equator) WGS84 global
  Cloud Optimized GeoTIFF, fetched from JRC's public AWS mirror on 2026-10-16.
- Population reuse: **Creative Commons Attribution 4.0 International**,
  <https://creativecommons.org/licenses/by/4.0/>. These game grids are adapted
  subsets: cropped, masked, spatially summed, and rounded.
- Country outlines and city coordinates: **Natural Earth**, 1:10 million,
  public domain, <https://www.naturalearthdata.com/about/terms-of-use/>.
  Boundaries follow Natural Earth's de facto representation. The input
  GeoJSONs are pinned to Git commit
  `ca96624a56bd078437bca8184e78163e5039ad19`.
- Exact source URLs, byte counts and SHA-256 hashes: `provenance.json`.

Suggested visible attribution: **Population: GHSL/JRC 2020 (CC BY 4.0), adapted.
Maps: Natural Earth. Estimates; regional scope varies.** Link the source and
license, and make each map's `scope` accessible in the data/methodology page.

## Data contract

`catalog.json` lists regions and lightweight metadata. Each region's `file`
points to a JSON document containing:

| Key | Meaning |
| --- | --- |
| `bbox` | `[west, south, east, north]` in longitude/latitude degrees. |
| `aspect` | Display width/height ratio, with longitude scaled by cosine of midpoint latitude. |
| `outline` | Array of polygon rings; each point is `[x,y]` normalized to the bounding box. Holes are included with opposite orientation. Use even-odd fill. |
| `context` | Nearby non-scoring country outlines in the same coordinate system, clipped to 13% padding. Coordinates may be outside 0–1. |
| `cells` | Flat `[x,y,population,x,y,population,...]` array; coordinates are cell centers; only positive cells are exported. |
| `cellSize` | Normalized `[width,height]` shared by every exported cell in this region. |
| `gridSize` | Number of columns and rows of the underlying regular grid. |
| `population`, `totalPopulation` | Identical, equal to the sum of all integer population weights. |
| `cities` | Major city labels from Natural Earth, with names and normalized coordinates. Intended for the reveal. |
| `gridKm` | Approximate cell width and height in kilometres at the map's midpoint latitude. |
| `scope` | Which territories or islands are included/excluded; the count uses exactly this scope. |
| `year`, `source`, `sourceUrl`, `license`, `provenance` | Attribution, epoch and processing details. |

Normalization is `x=(longitude-west)/(east-west)` and
`y=(north-latitude)/(north-south)`. A renderer preserves the `aspect` ratio.
The normalized map and the scoring grid therefore share one coordinate system.

## Processing and accuracy

The build script reads original, unsimplified Natural Earth country polygons,
selects the documented regional scope, and includes GHSL native raster cells
whose **centers** lie inside those polygons. Negative/no-data values are zero.
It then **sums** native population counts into fixed rectangular blocks and
rounds to integer persons, correcting rounding so the region total is preserved
to the nearest person. Urban and rural counts both come from the same GHSL grid.
Only the outlines used for drawing are simplified. Coastlines, borders, island
selection and source-model differences affect totals; they need not match an
official national headline total.

Small and medium countries have roughly 4–10 km game cells. Large countries
use roughly 15–26 km cells to keep each map below 500 KB and support smooth
mobile play. During scoring, compute the exact rectangle fraction on each side
of the submitted line and multiply by the cell's population. This avoids
abrupt jumps as a line moves between cell centers, but assumes population is
uniform **inside each aggregate cell**. Game results remain approximate.

The heatmap should be clipped to `outline`. An aggregate cell containing a
populated coastline may have its geometric center just outside the land.

Great Britain includes the Hebrides, Orkney and Shetland, while excluding
Northern Ireland and distant western Atlantic islands such as Rockall. Brazil
includes the mainland and islands within 0.8 geographic degrees of the mainland
outline (including coastal and river islands); remote Atlantic islands such as
Fernando de Noronha and Trindade are excluded. These scope choices avoid distant
tiny islands shrinking the playable map. Exact scope descriptions are also
recorded in each region, the catalog and `provenance.json`.

## Rebuild

Install Python dependencies `numpy`, `rasterio` and `shapely`, then run:

```sh
python scripts/data-build.py --cache /tmp/population-split-source-cache
```

The source COG is about 425 MB and is cached outside the deployed site.
The build emits only compact per-region grids, catalog metadata and provenance.
Use `--regions france japan` for a partial rebuild. Partial rebuilds update the
selected regions' catalog entries and preserve the other entries. Run
`python scripts/data-verify.py` afterwards.
