Files
drk-blutspende-orte/docs/data-model.md
T
Paddy 08232bda9b Add install.sh / run.sh / bundled icon; fully pin requirements
- install.sh: one-time Linux Mint setup (apt, .venv, requirements, .desktop
  entry with absolute paths). Re-runnable.
- run.sh: launches the app from .venv (called by the menu entry).
- icon.png: bundled 256px red-cross launcher/window icon; app prefers it over
  the runtime-drawn fallback (data/icon.png).
- requirements.txt: fully pinned incl. transitive deps, tested on Python 3.12;
  numpy held at 2.2.6 so it installs on Python 3.10 too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 22:16:52 +02:00

3.3 KiB
Raw Blame History

Data model

data/orte.csv

Plain CSV, comma-separated, UTF-8, with a header row. Created automatically with just the header if it does not exist.

Column Type on disk Meaning Notes
date string Assignment date Always stored as YYYY-MM-DD. Input is validated and normalized by parse_date() (accepts YYYY-MM-DD, DD.MM.YYYY, DD.MM.YY, YYYY/MM/DD); invalid input is rejected before saving. Rows written before this change may still hold non-ISO strings.
city string Place name Free text. Used for autocomplete and duplicate detection (trimmed, case-insensitive).
postal_code string German PLZ Optional. Kept as a string so leading zeros survive. Regex elsewhere accepts 45 digits.
lat string Latitude Blank until geocoded. Rounded to 5 dp. Parsed with pd.to_numeric(errors="coerce") when building the map.
lon string Longitude As above.

Every column is read as a string (dtype={"postal_code": str, "lat": str, "lon": str} plus city/date default object). Numeric conversion happens only where needed.

Row identity

There is no ID column. Rows are identified by their pandas DataFrame index, which is reset to 0..n-1 after every delete. UI tables use that index as the Treeview iid.

Implication: a geocode callback that is in flight while the user deletes a different row can land on the wrong row, because indices shift. update_row / _apply_edit_geocode guard against a missing index but not against a reused one. Still open — see improvements.md. The manual lat/lon fields in the edit dialog give a way to correct any row that ends up wrong.

Duplicate detection

find_duplicates flags a queued row when an existing row matches on all three of: date (string-equal), city (trimmed, lower-cased), postal_code (trimmed). It only produces a status-bar hint; duplicates are still written.

Map aggregation

get_map_data groups by (city, lat, lon) and counts rows. Two entries for the same city with different coordinates (e.g. Karlsruhe geocoded once to 76133 and once to 76185) produce two separate markers.

data/karte.html

Regenerated from scratch every time the user opens the map. Safe to delete; it is a build artefact, not data. Should be git-ignored if the project is ever put under version control.

data/backups/

Automatic timestamped copies of orte.csv, named orte-YYYYMMDD-HHMMSS.csv. One is written at startup and one before every change (skipped when nothing changed since the last backup). The newest 20 are kept; older ones are pruned. Git-ignored. To restore, copy a backup over data/orte.csv while the app is closed.

data/app.log

Rotating log file (512 KB × 3 generations). Git-ignored. Records saves, map generation, geocoding failures, and uncaught exceptions.

data/window.json

{"geometry": "<w>x<h>+<x>+<y>"} the window size and position, saved on close and restored on start. Git-ignored, per-machine. Safe to delete (window opens at its default size).

icon.png (repo root) and data/icon.png

icon.png in the repo root is the bundled launcher/window icon (committed). data/icon.png is only a runtime-drawn fallback the app writes if the bundled one is missing — git-ignored.