- Python 88%
- HTML 9.6%
- CSS 2%
- Dockerfile 0.2%
- Shell 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Manager-handleiding in het Nederlands naast de deelnemers-handleiding: aanmelden, het overzicht (inzendingen, publiceren, yearly standing), inzending beoordelen (aandachtspunten als observaties, beslissen in de QSO-tabel, bewerken met verplichte reden, acties, EDI), publiceren als goedkeuren, het NLC-rapport, cross-log controle en de Dutch Locator Reference. Zes screenshots van de echte managerpagina's. Demo-inzending PD9MODE/PA9TEST; geen echte persoonsgegevens in beeld. |
||
| .agents/tasks | ||
| alembic | ||
| app | ||
| docs | ||
| example formats | ||
| tests | ||
| .dockerignore | ||
| .gitignore | ||
| alembic.ini | ||
| CONTEXT.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| pyproject.toml | ||
| README.md | ||
VRZA Locator Contest Robot
Server-rendered FastAPI + Jinja2 web application for the VRZA Locator Contest, backed by PostgreSQL and packaged with Docker Compose. Entrants upload a contest log (EDI / Cabrillo / ADIF), preview the parsed result and provisional Monthly Score, then submit; a Contest Manager logs in to review Entries, adjudicate Flags, and manage the Submission Window. Interface is bilingual (Dutch default, English selectable).
Run with Docker
docker compose up
That builds the web image, starts Postgres, and on web start the container entrypoint runs, in order:
alembic upgrade head— applies the database schema.python -m app.bootstrap— idempotent seed: the initial Contest Manager, the current Contest Year with its 12 Monthly Contests (each on the 2nd Tuesday of the month), and the provisional Dutch Locator Reference.uvicorn app.main:app— serves the app on http://localhost:8000.
Both steps 1 and 2 are idempotent, so recreating the web container is safe.
Configuration (environment)
Set these in the environment (or a .env file read by Docker Compose) before
docker compose up. Defaults are development-only — override them for any real
deployment.
| Variable | Purpose | Default |
|---|---|---|
SECRET_KEY |
Signs the web session cookie | dev-insecure-change-me |
MANAGER_USERNAME |
Initial Contest Manager username (bootstrap) | manager |
MANAGER_PASSWORD |
Initial Contest Manager password (bootstrap) | changeme |
SMTP_HOST |
SMTP server for confirmation email; empty = .eml file backend |
(empty) |
SMTP_PORT |
SMTP port | 25 |
SMTP_USER / SMTP_PASSWORD |
SMTP credentials (optional) | (empty) |
SMTP_FROM |
From address on confirmation email | contestrobot@localhost |
DATABASE_URL |
SQLAlchemy/psycopg DB URL | points at the db service |
DATA_PATH |
In-container path for raw logs + outbox | /data/app |
When SMTP_HOST is empty the confirmation email is written as an .eml file
under ./data/app/outbox/ instead of being sent.
Manual migration / seed fallback
The entrypoint runs these automatically; run them by hand only if needed:
docker compose run --rm web alembic upgrade head
docker compose run --rm web python -m app.bootstrap
Generating and distributing documents
The Contest Manager produces three documents from the manager UI (all routes
sit under /manager and require a logged-in manager, so none is reachable
publicly):
- Summary Sheet — the reglement voorblad for one Entry, including the
private operator name, full address and the signed Declaration. Open an Entry
from the dashboard and follow the Summary Sheet link; the page is an HTML
view with a print/download-to-PDF export (use the browser's print-to-PDF, or
the
.pdfdownload link which serves the same printable HTML as an attachment). Because it carries private fields, distribute a Summary Sheet only to the entrant it belongs to or to the adjudicators. - Monthly results — the per-Section ranking for a Monthly Contest, with public-safe fields only (callsign, Section, afdeling, Monthly Score, multiplier total). From the dashboard follow the Monthly results link for a contest. There is an HTML view and a CSV download. This document is safe to publish.
- Yearly standing — the per-Section standing for a Contest Year (best 11 of 12 Monthly Scores, with a participation count), reached via the Yearly standing link. Public-safe; safe to publish.
The Dutch Locator Reference ships provisional (needs_review=True) pending
the authoritative list; the manager can curate it in-app at
/manager/reference.
Backup
All persistent state lives in host bind mounts — the containers are stateless (ADR D11):
./data/db/— the PostgreSQL data directory../data/app/— raw uploaded logs and generated confirmation.emlfiles.
./data/ is the single backup target. Back up that directory (with the
stack stopped, or via a database dump for a consistent snapshot) and you have
everything. docker compose down leaves ./data/ intact; recreating the web
container preserves all data.
Snelstart voor de Contest Manager (NL)
- Start de stack met
docker compose up. - Stel vóór de eerste start
MANAGER_USERNAMEenMANAGER_PASSWORDin; de eerste start maakt dat beheerdersaccount automatisch aan. - Ga naar http://localhost:8000/manager/login en log in.
- De taal staat standaard op Nederlands; schakel rechtsboven naar English.
- Documenten maken (alles onder
/manager, alleen voor de ingelogde manager):- Summary Sheet: open een Entry en volg de Summary Sheet-link. Dit
voorblad bevat privégegevens (naam, adres, Declaration); deel het alleen
met de betreffende entrant of de jury. Downloaden/afdrukken naar PDF via de
browser of de
.pdf-link. - Monthly results: volg bij een Monthly Contest de Monthly results-link. Alleen publieke velden (callsign, Section, afdeling, Monthly Score, multipliers). HTML én CSV; veilig te publiceren.
- Yearly standing: de Yearly standing-link toont de stand per Section (beste 11 van 12 Monthly Scores plus deelname). Veilig te publiceren.
- Summary Sheet: open een Entry en volg de Summary Sheet-link. Dit
voorblad bevat privégegevens (naam, adres, Declaration); deel het alleen
met de betreffende entrant of de jury. Downloaden/afdrukken naar PDF via de
browser of de
- De Dutch Locator Reference is voorlopig (
needs_review=True) totdat de definitieve lijst er is; beheer hem in de app via/manager/reference. - Back-up = de map
./data/(database én geüploade logs). Meer hoeft niet.
Development
python -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/python -m pytest tests -q
Live-database checks (Alembic, Postgres) run inside the web container; the host test suite uses an in-memory SQLite fixture.