Støtte for flere bibs per bilde, EXIF-metadata og zoom i gjennomgang
Build & Deploy / build-and-deploy (push) Successful in 46s

- OCR: ny read_all_bibs() returnerer alle unike startnumre (≥2 sifre) per bilde
- Ingest: oppretter én passering per bib (ikke bare beste), ingen bib → needs_review
- image_tagger.py: skriv/les bib-metadata som JSON i EXIF UserComment (piexif)
- Ingest + resolve: tagger bildefilen med bibs automatisk og ved manuell bekreftelse
- API: POST /api/passages/{id}/reanalyze — re-kjør OCR på eksisterende bilde
- API: POST /api/passages/{id}/resolve oppdaterer nå EXIF med bekreftet bib
- races: ny kolonne bib_filter_enabled (med automatisk migrering) + per-løp toggle
- ReviewPage: Re-analyser-knapp og klikk-for-zoom med scroll/drag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-22 09:00:24 +01:00
parent 018f84efd8
commit 45f7a77171
8 changed files with 526 additions and 128 deletions
+21 -10
View File
@@ -11,12 +11,13 @@ import aiosqlite
async def init_race_tables(db: aiosqlite.Connection) -> None:
await db.executescript("""
CREATE TABLE IF NOT EXISTS races (
race_id TEXT PRIMARY KEY,
name TEXT NOT NULL,
date TEXT,
description TEXT,
is_active INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
race_id TEXT PRIMARY KEY,
name TEXT NOT NULL,
date TEXT,
description TEXT,
is_active INTEGER NOT NULL DEFAULT 0,
bib_filter_enabled INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS stations (
@@ -34,6 +35,14 @@ async def init_race_tables(db: aiosqlite.Connection) -> None:
CREATE INDEX IF NOT EXISTS idx_stations_race ON stations(race_id, station_order);
""")
# Migrering: legg til kolonne for eksisterende databaser
try:
await db.execute(
"ALTER TABLE races ADD COLUMN bib_filter_enabled INTEGER NOT NULL DEFAULT 0"
)
await db.commit()
except Exception:
pass # Kolonnen finnes allerede
await db.commit()
@@ -44,11 +53,12 @@ async def create_race(
name: str,
date: Optional[str] = None,
description: Optional[str] = None,
bib_filter_enabled: bool = False,
) -> dict:
race_id = str(uuid.uuid4())
await db.execute(
"INSERT INTO races (race_id, name, date, description) VALUES (?, ?, ?, ?)",
(race_id, name, date, description),
"INSERT INTO races (race_id, name, date, description, bib_filter_enabled) VALUES (?, ?, ?, ?, ?)",
(race_id, name, date, description, int(bib_filter_enabled)),
)
# Sett som aktivt hvis det er første løpet
async with db.execute("SELECT COUNT(*) FROM races") as cur:
@@ -86,10 +96,11 @@ async def update_race(
name: str,
date: Optional[str],
description: Optional[str],
bib_filter_enabled: bool = False,
) -> bool:
cur = await db.execute(
"UPDATE races SET name = ?, date = ?, description = ? WHERE race_id = ?",
(name, date, description, race_id),
"UPDATE races SET name = ?, date = ?, description = ?, bib_filter_enabled = ? WHERE race_id = ?",
(name, date, description, int(bib_filter_enabled), race_id),
)
await db.commit()
return cur.rowcount > 0