Auto-create athlete in startlist for unrecognized bib numbers
Build & Deploy / build-and-deploy (push) Successful in 45s
Build & Deploy / build-and-deploy (push) Successful in 45s
When a bib number is detected (via OCR or manual entry during review) but not found in the start list, it is now automatically added with the placeholder name "Ukjent #<nr>" instead of being left without a profile_id (which would exclude it from results). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+5
-1
@@ -22,6 +22,7 @@ from profile_db import (
|
||||
clear_startlist,
|
||||
delete_athlete,
|
||||
get_db,
|
||||
get_or_create_athlete,
|
||||
import_startlist_csv,
|
||||
list_athletes,
|
||||
)
|
||||
@@ -213,8 +214,11 @@ class ResolveRequest(BaseModel):
|
||||
|
||||
@app.post("/api/passages/{passage_id}/resolve")
|
||||
async def resolve(passage_id: str, body: ResolveRequest, db=Depends(get_connection)):
|
||||
profile_id = body.profile_id
|
||||
if body.bib_number and not profile_id:
|
||||
profile_id = await get_or_create_athlete(db, body.bib_number)
|
||||
ok = await resolve_passage(db, passage_id,
|
||||
profile_id=body.profile_id,
|
||||
profile_id=profile_id,
|
||||
bib_number=body.bib_number,
|
||||
review_note=body.review_note)
|
||||
if not ok:
|
||||
|
||||
+4
-10
@@ -23,7 +23,7 @@ from watchdog.observers import Observer
|
||||
from exif_parser import ExifError, parse_image
|
||||
from ocr import read_bib
|
||||
from passage_log import log_passage
|
||||
from profile_db import get_athlete_by_bib, init_db
|
||||
from profile_db import get_or_create_athlete, init_db
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -98,11 +98,7 @@ async def process_image(path: Path) -> None:
|
||||
await init_db(db)
|
||||
|
||||
if bib_number and not needs_review:
|
||||
athlete = await get_athlete_by_bib(db, bib_number)
|
||||
if athlete:
|
||||
profile_id = athlete["profile_id"]
|
||||
else:
|
||||
logger.debug("Ukjent startnummer: %s", bib_number)
|
||||
profile_id = await get_or_create_athlete(db, bib_number)
|
||||
|
||||
await log_passage(
|
||||
db,
|
||||
@@ -141,7 +137,7 @@ async def process_image_with_override(
|
||||
EXIF-tid brukes hvis tilgjengelig, ellers nåværende tidspunkt.
|
||||
"""
|
||||
from datetime import datetime, timezone
|
||||
from profile_db import get_athlete_by_bib
|
||||
from profile_db import get_or_create_athlete as _get_or_create
|
||||
|
||||
logger.info("Web-opplasting: %s → stasjon=%s", path.name, station_name)
|
||||
|
||||
@@ -165,9 +161,7 @@ async def process_image_with_override(
|
||||
|
||||
profile_id = None
|
||||
if ocr.digits and not needs_review:
|
||||
athlete = await get_athlete_by_bib(db, ocr.digits)
|
||||
if athlete:
|
||||
profile_id = athlete["profile_id"]
|
||||
profile_id = await _get_or_create(db, ocr.digits)
|
||||
|
||||
await log_passage(
|
||||
db,
|
||||
|
||||
@@ -150,6 +150,14 @@ async def import_startlist_csv(db: aiosqlite.Connection, csv_content: str) -> di
|
||||
return {"imported": imported, "errors": errors}
|
||||
|
||||
|
||||
async def get_or_create_athlete(db: aiosqlite.Connection, bib_number: str) -> str:
|
||||
"""Hent eller opprett utøver basert på startnummer. Returnerer profile_id."""
|
||||
athlete = await get_athlete_by_bib(db, bib_number)
|
||||
if athlete:
|
||||
return athlete["profile_id"]
|
||||
return await upsert_athlete(db, bib_number, f"Ukjent #{bib_number}")
|
||||
|
||||
|
||||
async def get_athlete_by_bib(db: aiosqlite.Connection, bib: str) -> Optional[dict]:
|
||||
async with db.execute(
|
||||
"SELECT * FROM athletes WHERE bib_number = ?", (bib,)
|
||||
|
||||
@@ -122,7 +122,7 @@ function ReviewCard({ passage, athletes, onResolved, onDeleted }) {
|
||||
)}
|
||||
{bib && !matchedAthlete && (
|
||||
<span style={{ fontSize: '0.8rem', color: '#e67e22', marginTop: 2 }}>
|
||||
Startnummer ikke i startliste
|
||||
Ikke i startliste — legges til automatisk
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user