Update EventOccurrence parsing to use EventOccurrenceParseGroup for improved data structure
This commit refactors the EventOccurrence parsing logic to utilize the EventOccurrenceParseGroup class, enhancing the organization of parsed occurrences by grouping them based on event definitions and optional section levels. The changes include updates to the EventOccurrenceParseResult, EventOccurrenceParser, and EventOccurrenceParserService to accommodate the new grouping structure. Additionally, tests are modified to reflect these changes, ensuring that the parsing functionality remains intact and accurate. This refactor improves data handling and aligns with the overall architecture of the application.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
---
|
||||
created: 2026-03-30
|
||||
description: Extract a multi-day Google Sheets schedule grid into event-occurrence import text for the web app.
|
||||
---
|
||||
|
||||
# Import event schedule from Google Sheets
|
||||
|
||||
This repo includes a console tool that reads a **public** Google Sheet (with grid data and cell formatting), interprets each tab as one calendar day, and writes **plain text** in the same format as the legacy PDF-derived files consumed by **Calendar → Import Event Occurrences** (`/calendar/event-occurrences/import`).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **Google Cloud API key** with the **Google Sheets API** enabled.
|
||||
2. The spreadsheet must be readable with that key (typically **File → Share → Anyone with the link** *Viewer*, or share explicitly as needed for your key type).
|
||||
3. A **mapping JSON** file that lists each tab title and the calendar **month/day** for that tab (see sample under `docs/notes/`).
|
||||
|
||||
## Expected grid layout
|
||||
|
||||
- **Row 1:** Column `B` onward = **location** names (column `A` may be blank or a label).
|
||||
- **Column A (from row 2 down):** **Start time** for each row (e.g. `9:00 AM`, `9:00 a.m.`). The tool infers **slot length** from consecutive times and uses the next row’s time as the **end** of a block when cells span multiple rows.
|
||||
- **Data cells:** Event title (required for a block) and/or **non-white background** (treated as part of the same block as adjacent cells with the same text + color). **Merged cells** are expanded so the anchor value applies to the whole merge.
|
||||
|
||||
## Default section header
|
||||
|
||||
Output uses **`General Schedule`** as the section header unless you override it in mapping. That matches grids where each cell is its own schedule item (conference-style). If every line should belong to a specific competition event, set `sectionHeader` for that tab to something like `Biotechnology - MS` (must fuzzy-match an event in your database when importing).
|
||||
|
||||
Under **General Schedule**, the parser assigns occurrences to the **General Schedule** event type in the app (see `EventDefinitionResolver` / `EventDefinition.GeneralSchedule`).
|
||||
|
||||
## Grouping into competition events (PDF-style sections)
|
||||
|
||||
If you set **`eventDefinitionsCsv`** in the mapping JSON (or pass **`--events-csv`**), the tool loads event names from the CSV **`Event`** column and, when possible, rewrites output like the state schedule text:
|
||||
|
||||
- Section header: **`{Event Name} - MS`** or **`{Event Name} - HS`**
|
||||
- Occurrence lines under that section use **activity text only** (the tool drops the leading `MS`/`HS` and the repeated event name so lines read like the PDF, e.g. `On-Site Preliminary Exam …` not `MS Cybersecurity On-Site …`).
|
||||
- Only rows whose cell text has a **leading** `MS `, `HS `, `MS/`, or `HS/` prefix (after normalization) are grouped; the remainder is fuzzy-matched to an event (see `OccurrenceEventMatcher`).
|
||||
- **`MS/HS …`** combined rows → **General Schedule** (no single section).
|
||||
- Unmatched lines (opening session, meet-the-candidates, help desk, etc.) stay under a final **`General Schedule`** block.
|
||||
|
||||
Use **`--no-group-by-event`** to force the old “one General Schedule per sheet” layout.
|
||||
|
||||
## Site-wide rows (e.g. CURFEW)
|
||||
|
||||
If the same label appears across **every location column** for the same time (typical for **CURFEW**), the tool emits **one line per date and time** with **no location**. Built-in: `CURFEW` (case-insensitive). Optional mapping field **`siteWideEventNames`** adds more titles (e.g. `["Fire drill"]`).
|
||||
|
||||
## Run the tool
|
||||
|
||||
From the repository root:
|
||||
|
||||
```powershell
|
||||
$env:GOOGLE_SHEETS_API_KEY = "<your-api-key>"
|
||||
|
||||
dotnet run --project tools/GoogleSheetsScheduleImport/GoogleSheetsScheduleImport.csproj -- `
|
||||
--sheet-url "https://docs.google.com/spreadsheets/d/<spreadsheetId>/edit" `
|
||||
--mapping path/to/mapping.json `
|
||||
--output path/to/event-times.txt
|
||||
```
|
||||
|
||||
Optional flags:
|
||||
|
||||
| Flag | Purpose |
|
||||
|------|--------|
|
||||
| `--year 2026` | Year for date validation (also in mapping file). |
|
||||
| `--tabs "Day 1,Day 2"` | Only these tab titles (exact match). |
|
||||
| `--events-csv path\to\Event Definitions.csv` | Load event names for stricter parser validation (`Event` column). |
|
||||
| `--strict` | Exit code `1` if the built-in parser reports errors or parses zero occurrences. |
|
||||
|
||||
The tool always runs a **parser round-trip** on the generated text and prints errors/issues to the console.
|
||||
|
||||
## Import into the app
|
||||
|
||||
1. Open **Import Event Occurrences** in the web app.
|
||||
2. Paste the contents of the generated `.txt` file.
|
||||
3. **Parse**, review results, then **Save to Database** as usual.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **403 / access denied:** Confirm the sheet is visible to the API key and Sheets API is enabled.
|
||||
- **Wrong durations:** Ensure time labels in column A are consistent; the tool infers slot length from the most common delta between consecutive rows.
|
||||
- **Parser issues on import:** Use `--events-csv` pointing at your chapter’s event definitions export; fix `sectionHeader` in mapping if items should sit under a specific `Event Name - MS/HS` section.
|
||||
@@ -0,0 +1,163 @@
|
||||
# THURSDAY 4/9
|
||||
General Schedule
|
||||
Registration April 9 3 p.m. - 7 p.m. CCC Lobby (outside of Banquet Rooms)
|
||||
FCCLA/TSA Store April 9 3 p.m. - 7 p.m. Meeting Room 1
|
||||
MS/HS Prompt Releases (Virtual via App) April 9 6 p.m. - 9 p.m. Banquet Room E
|
||||
MS/HS Event Turn-In April 9 6 p.m. - 9 p.m. Banquet Room G
|
||||
HS Testing Room April 9 6 p.m. - 9 p.m. Banquet Room H
|
||||
MS Testing Room April 9 6 p.m. - 9 p.m. Banquet Room I
|
||||
MEMCO Meeting April 9 6 p.m. - 7 p.m. Banquet Room J
|
||||
MS/HS Time Sign-Ups (Virtual via App) April 9 6:30 p.m. - 7:30 p.m. Banquet Room F
|
||||
Coordinators Meeting April 9 7 p.m. - 8 p.m. Banquet Room J
|
||||
SOT Candidates Meeting April 9 8 p.m. - 9:30 p.m. Banquet Room J
|
||||
CURFEW April 9 11 p.m. - 12:30 a.m.
|
||||
|
||||
# FRIDAY 4/10
|
||||
CAD foundations - MS
|
||||
HS 2D CAD Architecture/ HS 3D CAD Engineering On-Site Challenge April 10 10:30 a.m. - 4:30 p.m. Banquet Room G
|
||||
Career Prep - MS
|
||||
Semifinals Interviews April 10 1 p.m. - 3 p.m. Meeting Room 10
|
||||
Challenging Technology Issues - HS
|
||||
Debating Technological Issues Prelims Pre-Debate Meeting April 10 10 a.m. - 10:30 a.m. Meeting Room 6
|
||||
Debating Technological Issues Prelims Presentation Room (Heat 1) April 10 1 p.m. - 5 p.m. Meeting Room 4
|
||||
Debating Technological Issues Prelims Presentation Room (Heat 2) April 10 1 p.m. - 5 p.m. Meeting Room 5
|
||||
Challenging Technology Issues - MS
|
||||
Leadership Strategies Holding Room April 10 10:30 a.m. - 4 p.m. Meeting Room 7
|
||||
Prelims Presentation Room April 10 10:30 a.m. - 1 p.m. Meeting Room 8
|
||||
Coding - HS
|
||||
Extemporaneous Speech/Debating Technological Issues Holding Room Room April 10 10 a.m. - 5 p.m. Meeting Room 3
|
||||
Data Science & Analytics - HS
|
||||
"Quarterfinals" Presentation April 10 12:30 p.m. - 5 p.m. Meeting Room 9
|
||||
Digital Photography - MS
|
||||
Semifinals Challenge April 10 10 a.m. - 1 p.m. Meeting Room 19
|
||||
Semifinals Interviews April 10 3 p.m. - 4 p.m. Meeting Room 16
|
||||
Electrical Applications - MS
|
||||
Semifinals Challenge April 10 2 p.m. - 3:30 p.m. Meeting Room 19
|
||||
Forensic Technology - HS
|
||||
Future Technology and Engineering Teacher Semifinals Presentations April 10 10 a.m. - 1 p.m. Meeting Room 18
|
||||
Leadership Strategies - MS
|
||||
Prelims Presentation Room April 10 1:30 p.m. - 4 p.m. Meeting Room 8
|
||||
Mass Production - HS
|
||||
Digital Video Production Semifinals Interviews April 10 10 a.m. - 12 p.m. Meeting Room 17
|
||||
Music Production Semifinals Interviews April 10 12:30 p.m. - 2:30 p.m. Meeting Room 17
|
||||
Prepared Speech - HS
|
||||
Extemporaneous Speech Presentation Room (Heat 1) April 10 10 a.m. - 12:30 p.m. Meeting Room 4
|
||||
Extemporaneous Speech Presentation Room (Heat 2) April 10 10 a.m. - 12:30 p.m. Meeting Room 5
|
||||
Prepared Presentation Prelims Presentation April 10 10 a.m. - 3:30 p.m. Meeting Room 21
|
||||
Prepared Speech - MS
|
||||
Prelims Presentation Room April 10 10:30 a.m. - 12:30 p.m. Meeting Room 10
|
||||
System Control Technology - MS
|
||||
HS System Control Technology On-Site Challenge April 10 10 a.m. - 2 p.m. Banquet Room F
|
||||
Tech Bowl - HS
|
||||
Photographic Tech Semifinals Prompt Release April 10 11 a.m. - 12 p.m. Meeting Room 6
|
||||
Video Game Design - MS
|
||||
Semifinals Interviews April 10 12:30 p.m. - 2:30 p.m. Meeting Room 16
|
||||
Website Design - MS
|
||||
Semifinals Interviews April 10 10 a.m. - 12 p.m. Meeting Room 16
|
||||
General Schedule
|
||||
FCCLA/TSA Store April 10 8 a.m. - 4 p.m. Meeting Room 1
|
||||
MS Static Event Turn-In April 10 8 a.m. - 9 a.m. Exhibit Hall C
|
||||
HS Static Event Turn-In April 10 8 a.m. - 9 a.m. Exhibit Hall C
|
||||
Opening Session April 10 9 a.m. - 10 a.m. Exhibit Hall A
|
||||
TECHSPO April 10 10 a.m. - 4 p.m. Main Hallway
|
||||
Help Desk April 10 10 a.m. - 5 p.m. CCC Lobby (outside of Banquet Rooms)
|
||||
Help Desk April 10 10 a.m. - 5 p.m. CCC Lobby (outside of Banquet Rooms)
|
||||
Advisor Meeting April 10 10 a.m. - 11 a.m. Banquet Room E
|
||||
HS Software Development Semifinals Presentations April 10 10 a.m. - 12 p.m. Meeting Room 9
|
||||
MS/HS Open Viewing Events April 10 10 a.m. - 5 p.m. Exhibit Hall B
|
||||
MS/HS Open Viewing Events April 10 10 a.m. - 5 p.m. Exhibit Hall B
|
||||
MS/HS Closed Viewing Events April 10 10 a.m. - 5 p.m. Exhibit Hall C
|
||||
MS/HS Closed Viewing Events April 10 10 a.m. - 5 p.m. Exhibit Hall C
|
||||
Workshop April 10 11:30 a.m. - 1:30 p.m. Banquet Room E
|
||||
HS STEM Mass Media Semifinals Press Conference April 10 12:30 p.m. - 3:30 p.m. Meeting Room 6
|
||||
TSA Meet the Candidates April 10 1:30 p.m. - 2:30 p.m. Main Hallway
|
||||
HS Animatronics Presentations/ Interviews April 10 1:30 p.m. - 4:30 p.m. Meeting Room 18
|
||||
Workshop April 10 2:30 p.m. - 4:30 p.m. Banquet Room E
|
||||
HS VR Semifinals Interviews April 10 2:30 p.m. - 4:30 p.m. Banquet Room F
|
||||
Community Service Video Seminfinal Interviews April 10 3 p.m. - 4 p.m. Meeting Room 17
|
||||
TSA Meet the Candidates April 10 4:30 p.m. - 5:30 p.m. Main Hallway
|
||||
TSA Meet the Candidates April 10 4:30 p.m. - 5:30 p.m. Main Hallway
|
||||
(no title) April 10 4:30 p.m. - 5:30 p.m. Banquet Room E
|
||||
Dance/Game Night April 10 8 p.m. - 9:30 p.m. Exhibit Hall D
|
||||
Dance/Game Night April 10 8 p.m. - 9:30 p.m. Exhibit Hall D
|
||||
(no title) April 10 10 p.m. - 11 p.m. Banquet Room E
|
||||
CURFEW April 10 11 p.m. - 12:30 a.m.
|
||||
|
||||
# SATURDAY 4/11
|
||||
Challenging Technology Issues - HS
|
||||
Debating Technological Issues Semifinals Pre-Debate Meeting April 11 9:30 a.m. - 10 a.m. Meeting Room 7
|
||||
Debating Technological Issues Semifinals Presentation Room April 11 10:30 a.m. - 12:30 p.m. Meeting Room 8
|
||||
Challenging Technology Issues - MS
|
||||
Semifinals Holding Room April 11 9:30 a.m. - 11 a.m. Meeting Room 9
|
||||
Semifinals Presentation Room April 11 9:30 a.m. - 11 a.m. Meeting Room 10
|
||||
Chapter Team - HS
|
||||
Semifinals Presentation April 11 1:30 p.m. - 3:30 p.m. Meeting Room 16
|
||||
Chapter Team - MS
|
||||
Semifinals Presentation April 11 11:30 a.m. - 1 p.m. Meeting Room 16
|
||||
Children's Stories - HS
|
||||
Semifinals Interviews April 11 9:30 a.m. - 12:30 p.m. Meeting Room 18
|
||||
Children's Stories - MS
|
||||
Semifinals Interviews April 11 1 p.m. - 4 p.m. Meeting Room 18
|
||||
Coding - HS
|
||||
Semifinals Challenge April 11 9:30 a.m. - 12 p.m. Meeting Room 19
|
||||
Debating Technological Issues Semifinals Holding Room April 11 10:30 a.m. - 12:30 p.m. Meeting Room 7
|
||||
Extemporaneous Speech Semifinals Holding Room April 11 1 p.m. - 2:30 p.m. Meeting Room 7
|
||||
Coding - MS
|
||||
Semifinals Challenge April 11 12:30 p.m. - 3 p.m. Meeting Room 19
|
||||
Cybersecurity - MS
|
||||
Seminals Presentations April 11 3:30 p.m. - 4:30 p.m. Meeting Room 19
|
||||
Data Science & Analytics - HS
|
||||
Forensic Science Written Analysis Room April 11 9:30 a.m. - 2:30 p.m. Meeting Room 5
|
||||
Semifinals Challenge April 11 3 p.m. - 5 p.m. Meeting Room 6
|
||||
Data Science & Analytics - MS
|
||||
Data Science and Analytics Presentations April 11 3 p.m. - 4:30 p.m. Meeting Room 4
|
||||
Data Science and Analytics Preparation Room April 11 3 p.m. - 4:30 p.m. Meeting Room 5
|
||||
Forensic Technology - HS
|
||||
Photographic Technology Semifinals Interviews April 11 3 p.m. - 5 p.m. Meeting Room 7
|
||||
Forensic Technology - MS
|
||||
Semifinals Presentation Room April 11 1:30 p.m. - 4:30 p.m. Meeting Room 9
|
||||
Leadership Strategies - MS
|
||||
Semifinals Holding Room April 11 11:30 a.m. - 1 p.m. Meeting Room 9
|
||||
Semifinals Presentation Room April 11 11:30 a.m. - 1 p.m. Meeting Room 10
|
||||
Medical Technology - HS
|
||||
Fashion Design and Technology Semifinals Presentation/ Interviews April 11 2:30 p.m. - 4:30 p.m. Meeting Room 17
|
||||
Prepared Speech - HS
|
||||
Extemporaneous Speech Semifinals Presentation Room April 11 1 p.m. - 2:30 p.m. Meeting Room 8
|
||||
Prepared Presentation Semifinals Presentation Room April 11 3 p.m. - 5 p.m. Meeting Room 8
|
||||
Prepared Speech - MS
|
||||
Semifinals Presentation Room April 11 1:30 p.m. - 3 p.m. Meeting Room 10
|
||||
Promotional Marketing - HS
|
||||
Promotional Design Semifinals Challenge April 11 11:30 a.m. - 2:30 p.m. Meeting Room 6
|
||||
Promotional Marketing - MS
|
||||
Semifinals Challenge April 11 9:30 a.m. - 11 a.m. Meeting Room 6
|
||||
STEM Animation - MS
|
||||
Semifinals Interviews April 11 9:30 a.m. - 11 a.m. Meeting Room 16
|
||||
Tech Bowl - MS
|
||||
HS Technology Bowl Semifinals Bracket Play April 11 9 a.m. - 5 p.m. Banquet Rooms G
|
||||
HS Technology Bowl Semifinals Holding Room April 11 9 a.m. - 5 p.m. Banquet Rooms H
|
||||
Video Game Design - HS
|
||||
Semifinals Interviews April 11 12 p.m. - 2 p.m. Meeting Room 17
|
||||
Website Design - HS
|
||||
Webmaster Semifinals Interviews April 11 9:30 a.m. - 11:30 a.m. Meeting Room 17
|
||||
General Schedule
|
||||
Voting Delegate Meeting April 11 8 a.m. - 9 a.m. Banquet Room F
|
||||
Help Desk April 11 9 a.m. - 5 p.m. CCC Lobby (outside of Banquet Rooms)
|
||||
Help Desk April 11 9 a.m. - 5 p.m. CCC Lobby (outside of Banquet Rooms)
|
||||
Tennessee TSA Store April 11 9 a.m. - 4 p.m. Meeting Room 1
|
||||
HS Forensic Science CSI April 11 9:30 a.m. - 2:30 p.m. Meeting Room 4
|
||||
MS/HS Open Viewing Events April 11 9:30 a.m. - 4:30 p.m. Exhibit Hall B
|
||||
MS/HS Open Viewing Events April 11 9:30 a.m. - 4:30 p.m. Exhibit Hall B
|
||||
MS/HS Closed Viewing Events April 11 9:30 a.m. - 4:30 p.m. Exhibit Hall C
|
||||
MS/HS Closed Viewing Events April 11 9:30 a.m. - 4:30 p.m. Exhibit Hall C
|
||||
TECHSPO April 11 10 a.m. - 4 p.m. Main Hallway
|
||||
MS/HS Static Event Pick-Up April 11 5 p.m. - 5:30 p.m. Exhibit Hall C
|
||||
MS/HS Static Event Pick-Up April 11 5 p.m. - 5:30 p.m. Exhibit Hall C
|
||||
General Session 2: Business Meeting April 11 5:30 p.m. - 6:30 p.m. Exhibit Hall A
|
||||
Senior Social April 11 8:30 p.m. - 9:30 p.m. Banquet Room F
|
||||
Chapter Officer Meeting April 11 8:30 p.m. - 9 p.m. Banquet Rooms G
|
||||
CURFEW April 11 11 p.m. - 12:30 a.m.
|
||||
|
||||
# SUNDAY 4/12
|
||||
General Schedule
|
||||
General Session 3: Awards Ceremony April 12 8:30 a.m. - 12 p.m. Exhibit Hall A
|
||||
New SOT Pictures April 12 12 p.m. - 12:30 p.m. Exhibit Hall A
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"year": 2026,
|
||||
"defaultSectionHeader": "General Schedule",
|
||||
"sheets": [
|
||||
{
|
||||
"title": "Wednesday",
|
||||
"month": "April",
|
||||
"day": 2,
|
||||
"sectionHeader": null
|
||||
},
|
||||
{
|
||||
"title": "Thursday",
|
||||
"month": "April",
|
||||
"day": 3
|
||||
},
|
||||
{
|
||||
"title": "Friday",
|
||||
"month": "April",
|
||||
"day": 4,
|
||||
"sectionHeader": "General Schedule"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"year": 2026,
|
||||
"eventDefinitionsCsv": "../../Tests/Parsers/TestInput/2024 Event Definitions.csv",
|
||||
"defaultSectionHeader": "General Schedule",
|
||||
"sheets": [
|
||||
{
|
||||
"title": "THURSDAY 4/9",
|
||||
"month": "April",
|
||||
"day": 9
|
||||
},
|
||||
{
|
||||
"title": "FRIDAY 4/10",
|
||||
"month": "April",
|
||||
"day": 10
|
||||
},
|
||||
{
|
||||
"title": "SATURDAY 4/11",
|
||||
"month": "April",
|
||||
"day": 11
|
||||
},
|
||||
{
|
||||
"title": "SUNDAY 4/12",
|
||||
"month": "April",
|
||||
"day": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user