Source: ihnyc-games/infra/d1/schema.sql
Tables
events
- id (TEXT, PK)
- title (TEXT)
- sport (TEXT)
- description (TEXT)
- location (TEXT)
- start_at (TEXT)
- end_at (TEXT)
- capacity (INTEGER)
- form_url (TEXT)
- source_label (TEXT)
- created_at (TEXT)
results
- id (TEXT, PK)
- event_id (TEXT, FK → events.id)
- building (TEXT: north|south)
- floor_number (INTEGER)
- placement (INTEGER)
- points (INTEGER)
- medal (TEXT: gold|silver|bronze|NULL)
- created_at (TEXT)
import_runs
- id (TEXT, PK)
- created_at (TEXT)
- rows_read (INTEGER)
- inserted (INTEGER)
- skipped (INTEGER)
- errors_json (TEXT)
signup_submissions
- id (TEXT, PK)
- import_run_id (TEXT, FK → import_runs.id)
- name (TEXT)
- email (TEXT)
- room (TEXT)
- building (TEXT: north|south|NULL)
- floor_number (INTEGER)
- response_at (TEXT)
- raw_json (TEXT)
- created_at (TEXT)
submission_event_choices
- id (TEXT, PK)
- submission_id (TEXT, FK → signup_submissions.id)
- event_id (TEXT, FK → events.id)
- source_label (TEXT)
- created_at (TEXT)
Import matching rules
- Parse choices from “Which event(s) do you want to participate in?” only.
- Strip day/time from choices (keep the sport name).
- Ignore “Any other sports/games you’d like to play?”
- Match by exact
events.source_labelor exactevents.title. - If no exact match, fallback to prefix match on
events.title. - On import, keep only the latest submission per room (older rows are deleted).
- Roster signup counts are computed on distinct submissions (not event choice rows).
- Room parsing strips notes and uses the first alphanumeric token for building/floor inference.
- All raw submissions are stored, even if mapping fails.
Indexes
- events(start_at)
- results(event_id), results(floor_number)
- import_runs(created_at)
- signup_submissions(name, room, floor_number)
- submission_event_choices(submission_id, event_id)