This project creates the Imagination Day schedule from two Google Sheets:
- the student form responses
- the course catalog
It writes the results into a separate output workbook, lets teachers make manual edits there, and then generates the final PDFs for student lanyards and class rosters.
This is meant to be run locally on one computer by one volunteer.
- Python 3.10 or newer
- access to the student response spreadsheet
- access to the course catalog spreadsheet
- a Google Cloud project with the Google Sheets API enabled
- an OAuth desktop app downloaded as
credentials.json
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtCreate a Google Cloud project and do all of the following:
- Enable the Google Sheets API.
- Configure the OAuth consent screen.
- Create an OAuth client of type
Desktop app. - Download the client JSON file.
- Save that file in this folder as
credentials.json.
Notes:
credentials.jsonshould stay local. Do not commit it to git.- On the first successful run, the script will also create
token.json. token.jsonshould also stay local. Do not commit it to git.
Copy the example:
cp config.example.json config.jsonOr generate a starter file:
python scheduler.py init-configFill in these required values:
student_responses_urlcatalog_url
Leave output_workbook_url as null the first time you run the script. The script will create the output workbook for you and save that URL back into config.json.
If you want a step-by-step local UI instead of raw commands, run:
streamlit run streamlit_app.pyWhat the wizard does:
- lets you edit and save
config.json - shows whether
credentials.jsonandtoken.jsonare present - runs the same workflow buttons in order:
- validate
- generate draft schedule
- refresh final reports
- generate PDFs
- shows the latest logs from each step
- links to the output workbook once it exists
Notes:
- the wizard still uses the same local files and Google Sheets access as the CLI
- on the first successful run, Google OAuth will open in your browser and create
token.json - teachers still make manual edits in
5 Final Schedule (Edit Here)inside the output workbook
These values may need to change each year:
student_responses_urlcatalog_urlsession_aliasesgrade_lunch_assignmentstime_blockspdf_output_dir
Important:
session_aliasesis only for cases where the student form name does not exactly match the catalog name.grade_lunch_assignmentsmust match the real lunch plan for that year.- The values in
config.example.jsonare examples, not guaranteed yearly defaults.
Use this exact order each year.
python scheduler.py validateWhat this does:
- reads the student response sheet
- reads the course catalog sheet
- creates the output workbook if needed
- writes validation results into the output workbook
What to check:
- open the output workbook
- read
3 Validation Issues - fix every row marked
ERRORbefore continuing
If validation stops with fatal issues, do not run the scheduler yet.
python scheduler.py runOr compare the current greedy scheduler against the CP-SAT solver before writing any tabs:
python scheduler.py benchmarkTo generate the draft with the CP-SAT solver instead of the default greedy heuristic:
python scheduler.py run --algorithm cp-satWhat this does:
- assigns lunch first by grade
- assigns classes based on student rankings and session availability
- writes a draft schedule to the output workbook
- populates helper tabs teachers can use during manual cleanup
What benchmark does:
- reads the same student and catalog sheets used by
run - computes schedule quality metrics for one or more algorithms
- prints a JSON comparison so you can compare preference satisfaction, gaps, and seat utilization before switching algorithms
What to check:
4 Draft Schedule (Do Not Edit)5 Final Schedule (Edit Here)6 Waitlist7 Students With Gaps8 Session Rosters9 Teacher View
Important:
5 Final Schedule (Edit Here)is the only tab teachers should edit.- If
5 Final Schedule (Edit Here)was empty, the script will copy the draft into it automatically. - There is no manual copy/paste step on the first run.
Teachers should work only in:
5 Final Schedule (Edit Here)
They may use these tabs while making decisions:
6 Waitlist7 Students With Gaps8 Session Rosters9 Teacher View
All other tabs are protected on purpose.
python scheduler.py refresh-finalWhat this does:
- rereads
5 Final Schedule (Edit Here) - rebuilds the waitlist, gaps, roster, and teacher tabs from the edited final schedule
- checks that final schedules still reference valid catalog sessions
Run this after teachers finish editing and any time you want the helper tabs to match the current final schedule.
python scheduler.py printablesWhat this does:
- refreshes the final report tabs again
- generates the final PDFs from
5 Final Schedule (Edit Here)
Files created:
attendee_schedule.pdfclass_rosters.pdf
These files are written to the folder set by pdf_output_dir in config.json.
The script creates and manages these tabs:
1 Instructions2 Run Status3 Validation Issues4 Draft Schedule (Do Not Edit)5 Final Schedule (Edit Here)6 Waitlist7 Students With Gaps8 Session Rosters9 Teacher View10 Catalog Snapshot
Meaning of the main tabs:
4 Draft Schedule (Do Not Edit)is the machine-generated draft.5 Final Schedule (Edit Here)is the teacher-edited final version.6 Waitlistshows students who wanted a session but could not be placed.7 Students With Gapsshows students with one or more blank periods.8 Session Rostersshows who is assigned to each session.9 Teacher Viewgives a teacher-friendly schedule view.
Files you edit:
config.json
Files you provide and keep local:
credentials.json
Files the script creates and keeps local:
token.jsonattendee_schedule.pdfclass_rosters.pdf
Do not commit config.json, credentials.json, or token.json to git.
- Run only one scheduler command at a time.
- Use the same Google account each time unless you intentionally want a different owner/editor for the output workbook.
- The script will not overwrite
5 Final Schedule (Edit Here)if it already contains edited data. - PDFs are always generated from
5 Final Schedule (Edit Here), not from the draft tab. - Lunch is assigned automatically before other classes, based on
grade_lunch_assignments.
If the schedule does not look right, check these first:
3 Validation Issuessession_aliasesinconfig.jsongrade_lunch_assignmentsinconfig.json- the session names and periods in the catalog sheet
Common causes:
- a session name in the student form does not exactly match the catalog
- lunch assignments are wrong for the current year
- the catalog does not mark the correct periods for a session
- the output workbook is from an older test run