Move Participant/Group to pydantic and add a saveable/editable Plan model

Participant and Group are now pydantic BaseModels. Group.hosts can form
cycles between groups, so it's kept as a private, non-persisted live list
(set via set_hosts()/add_host()) backed by a serializable host_uuids field,
re-linked via resolve_hosts() after a reload.

A new Plan model (src/tatami/plan.py) bundles groups, the after-party group,
and the event config (course_times, organizer_contacts, info_text,
spreadsheet_id) and supports save()/load() to/from JSON. tatami_masterplan's
__main__ now saves to masterplan.json (PLAN_FILE env var to override) on
first run and loads it on later runs instead of recomputing, so the plan can
be hand-edited (move a member between groups, change a course, fill in
spreadsheet_id) and picked up on rerun without hitting the Routes API again.
spreadsheet_id moves out of .env (GOOGLE_SHEETS_SPREADSHEET_ID) onto the plan
itself, since it's part of the plan rather than a secret.
This commit is contained in:
2026-06-19 16:07:47 +02:00
parent 91dc7729f9
commit 6b0fca0100
12 changed files with 538 additions and 157 deletions
+5 -5
View File
@@ -4,9 +4,9 @@ GOOGLE_MAPS_API_KEY=your-api-key-here
# Optional: export the masterplan to a shared Google Sheet for participants.
# Set up once: create a Google Cloud service account, enable the Google
# Sheets API for its project, download the service account's JSON key, then
# create a blank Google Sheet and share it with the service account's
# client_email (found in the JSON key) as Editor. Leave both unset to skip
# sheet export entirely.
# Sheets API for its project, and download the service account's JSON key.
# Then create a blank Google Sheet, share it with the service account's
# client_email (found in the JSON key) as Editor, and set its id as
# `spreadsheet_id` in the saved masterplan.json (see README) - leave it unset
# there to skip sheet export entirely.
GOOGLE_SHEETS_CREDENTIALS_FILE=service-account.json
GOOGLE_SHEETS_SPREADSHEET_ID=your-spreadsheet-id-here