Overview
The Master Schedule Optimizer reads your school's current schedule and student course requests directly from Aeries exports and uses a mathematical constraint solver to build a new master schedule that fills as many student requests as possible — while respecting your constraints. No AI or machine learning is involved.
Upload two files, answer a short configuration wizard, and the system produces an optimized schedule ready to load back into Aeries.
The Two Input Files
The Master Schedule export from Aeries. Contains every section — section number, period, teacher, course, room, and enrollment cap.
The Student Subject Selections export. Lists every course request each student has made for the upcoming school year.
The Workflow at a Glance
After reviewing results you can bump section capacities, assign teachers to high-demand courses, or adjust any constraint and re-run the optimizer without re-uploading your files.
1 Upload Files
The home page is where every session begins. Upload both Aeries export files to start the analysis. Both .xlsx and .csv formats are accepted.
.xlsx or .csv
.xlsx or .csv
- ①The MST / SMS file is your current Aeries master schedule. Use the Aeries Query tool (Pages → Query → New) and run the query shown on the upload page to export all required columns, including credit and day-of-week flags:
LIST MST CRS TCH MST.SC MST.SE MST.PD MST.BL MST.SM MST.DY MST.CN MST.TN MST.RM MST.MX MST.TS TCH.TE CRS.CO CRS.LO CRS.HI MST.CR MST.MM MST.MT MST.MW MST.MR MST.MF CRS.S1 MST.SG MST.TM MST.CG IF STG = "" - ②The SSS file contains student course requests. Export from Scheduling → Student Requests → Export.
- ③Do not manually edit either file before uploading — column names must match Aeries exactly or the parser will fail.
Period Setup
After your files are analyzed you move through the 5-step workflow. Step 3 is the Configuration Wizard — a single scrollable page with numbered sections. A navy sidebar on the left shows your progress and lets you jump between sections.
Section 1 — Period Configuration lets you confirm which periods are part of the standard school day. The system auto-detects standard vs. outlier periods from your MST data.
Periods shown in blue are active (checked). Gray buttons are outlier periods. The optimizer only moves and places students in checked periods — sections in unchecked periods stay exactly where they are.
Section Locks
Section 2 — Pin / Lock Specific Sections — tells the optimizer which sections must not be moved. Outlier-period sections are locked by default. Standard-period sections are unlocked by default.
Click the ∨ chevron on any period row to expand it and see individual sections. Toggle each section's lock state by clicking its checkbox.
Teacher Loads
Section 3 — Teacher Section Load — is a read-only reference panel. It flags any teachers whose current section count is above the standard load for your school, so you're aware of anomalies before the optimizer runs. No action is required here.
Click the › chevron to expand a teacher's section list. This step is informational — if a teacher is overloaded, address it through staffing decisions outside the optimizer before the final export.
Resolve Missing Courses
Section 4 — Resolve Missing Courses — lists every course that appears in student SSS requests but has no sections in the current MST. You must choose an action for each course before you can run the optimizer.
The Four Options
| Option | What it does | When to use |
|---|---|---|
| Create Sections | The optimizer builds new sections and places students into them. You choose how many sections and which periods to allow, and optionally a preferred teacher (existing teacher or a New Hire reserved in the 99001+ range), grade level range (Low/High — blank defaults to 9–12), and classroom size (Max capacity — blank uses the wizard's class-cap default). | Course is being offered but isn't in the MST yet. |
| Map to Existing | Requests for this course are treated as requests for a different, existing course. | Course was renamed or renumbered in Aeries. |
| Exclude | Requests are ignored — students requesting this course won't be scheduled for it. | Course is not being offered; requests were submitted in error. |
| Hold Period | Creates a placeholder section pinned to a specific period. | Course is planned but teacher isn't confirmed yet. |
Solver Settings
Section 5 — Solver Settings — lets you tune how the optimizer runs. The defaults work well for most schools. Only adjust these if you have a specific reason to.
| Setting | What it controls | Default |
|---|---|---|
| Solver Time Limit | Maximum seconds the solver runs. Longer = potentially better result, but slower. | 120s |
| Target Fill Rate | The solver pushes to exceed this rate. Set above your current fill rate to drive improvement. | 75% |
| Auto-add Threshold | A new section is auto-added when SSS demand exceeds current capacity by more than this many students. Set to 0 to always scale; set high to disable. | 15 |
| Period Rearrangement | Allows the optimizer to move unlocked sections to different periods to improve student fit. Teachers' full section groups move together. | On ✓ |
| Course Priority Weights | High-priority (10×) courses are scheduled before low-priority (1×) when there are conflicts. Overall fill rate % is unaffected — weights determine who wins ties. | All high |
Term-Orphan Prevention
A term orphan is a student whose final schedule fills some term slots but not all of them. The classic example is a student who ends up enrolled in Fall classes but has no Spring class, or — in a quarter school — a student with classes in Q1, Q2, Q4 but nothing in Q3. Term-orphan prevention is a soft solver preference that nudges the optimizer toward complete-term coverage.
How it works
The solver reviews each student whose requested courses reach more than one term slot. For each such student, it adds a penalty when their assigned schedule covers some slots but not all. The penalty is shaped to be:
- Strong enough to deter half-coverage when the solver has freedom to choose — same-teacher and same-period options the optimizer would normally explore now also factor in slot completeness.
- Soft — never blocks a feasible schedule. A student request fulfillment (the primary objective) always outweighs the orphan penalty.
- Scoped to your data — only fires for students whose request list reaches multiple slots. A student who legitimately requested only Fall courses (e.g. a part-time enrollment) is left alone.
What slots count
The slot vocabulary is determined automatically from your MST's Semester column. The optimizer detects whether you run a standard (F/S/Y), quarter (1/2/3/4), or trimester (T1/T2/T3) schedule and uses the matching slot set:
| Term system | Slot set | Year-long coverage |
|---|---|---|
| Standard | fall, spring | A Y course covers both |
| Quarter | fall_q1, fall_q2, spring_q3, spring_q4 | A Y course covers all four |
| Trimester | T1, T2, T3 | A Y course covers all three |
Toggle
Term-orphan prevention is on by default. You can turn it off in Step 5 — Solver Settings. Look for the checkbox labeled "Prevent term-orphan student schedules".
Teacher term-orphan diagnostic
The same logic also runs for teachers — but as a diagnostic, not a constraint. The optimizer can't reassign sections between teachers (that's MST data), so a teacher with only Fall sections is a data-quality issue with the MST itself, not something the solver can fix. The diagnostic is computed post-solve and recorded with your session. A console log line summarizes the top offender:
Term-orphan diagnostic: 3 teacher(s) have partial term coverage. Top offender: T#7 (filled=['fall'], missing=['spring'])
UI display of the full list is planned for a future release.
Term-Balance Auto-Clone (Heuristic)
The term-balance heuristic is a behind-the-scenes step that runs before the solver. It scans every (teacher, period) cell and asks: "does this cell run all year?" If a cell holds only Fall sections — and the highest-demand course in that cell crosses a threshold — the heuristic auto-clones that section into Spring so the cell covers both halves of the year. Same idea for quarter and trimester schools.
When does it fire?
For a clone to spawn, all of these must be true:
- The cell has a real teacher assigned (not Unassigned / Holding Tank).
- The cell's combined semester slots don't already cover the full year.
- The highest-demand course in the cell exceeds the dynamic threshold:
threshold = max(30, 75th percentile of demand_by_course)
The percentile component adapts to the school's demand distribution — at a small school the 75th percentile may be 18, at a large school it may be 60. The flat 30 floor protects against tiny datasets. - The course is NOT already named in an explicit Buddy Pair. If you've declared a Buddy Pair for the course, the heuristic backs off — the Buddy Pair's soft same-teacher preference takes over instead. This prevents two systems from double-spawning into the same cell.
Toggle
The heuristic is on by default. You can turn it off in Step 5 — Solver Settings. Look for the checkbox labeled "Auto-clone for term balance (heuristic)" next to the term-orphan prevention checkbox.
Reviewing clones after a solve
Every clone the heuristic spawns appears in the Schedule Changes tab on the results page under Buddy-Class Auto-Clones. Each row shows the new section number, course, teacher, period, term, and demand. If a specific clone shouldn't have spawned, hide it via Step 2 (Locked Sections / pin-lock search) and re-run.
Staff Changes
Staff Changes is an optional wizard section shown with a ✓ checkmark in the sidebar (not a numbered step). Use it if teachers are departing or new teachers are joining before the schedule is finalized.
Click Staff Changes in the wizard sidebar to expand it. Select "Yes, there are changes" to reveal two lists — one for departing teachers (their sections will be released) and one for new teachers (assign them courses). If there are no changes, leave it at the default "No changes."
Ready to Run
Once all wizard sections show a green ✅ in the sidebar, the footer bar shows ✓ All sections complete — ready to optimize! and the Save & Run Optimizer → button becomes active. Click it to save your settings and launch the solver.
Holding Tank
Holding Tank is the wizard's cleanup step for non-academic placeholder sections — Teacher Aides, Study Hall, Office Aide, X-prefix course codes, and similar courses that don't represent real instructional time. These sections inflate teacher loads and confuse the cluster grouping the optimizer uses, so they should be normalized before the solver runs.
How candidates are detected
The wizard scans your MST for courses that match either of two signals:
- Title keyword. The course title contains any of: TA, Aide, Assistant, Study Hall, Study Skills, Prep, Office, Roll, Tutorial, Homeroom, Advisory, Lunch.
- Many teachers. The course is taught by an unusually large number of distinct teachers (default threshold: 10).
Each candidate is rated Very Likely (both signals match) or Likely (one signal matches) so you can sort by certainty.
Three actions per course
| Action | What it does | When to use |
|---|---|---|
| Consolidate | Removes all existing sections of this course, then injects one unassigned section per standard period with a very high seat capacity (999). Students requesting this course flow into whichever consolidated section has room. | Frees teachers from non-academic loads while preserving every student request. |
| Drop | Removes all sections of this course from the MST entirely. Student requests for the course remain on file and surface as unmet demand on the results page. | The course is truly junk and you don't want to allocate any seats for it. |
| Leave (default) | No change. Sections stay assigned to teachers exactly as in the original MST. | The default — every candidate stays untouched until you opt in to Consolidate or Drop on the rows where it makes sense. |
How to use the step
- Open the wizard and scroll down to Step 6 — Holding Tank Courses (or click Holding Tank in the sidebar).
- Each detected course shows the confidence badge, course number and title, and the section/teacher/request counts.
- Pick an action per course by clicking the colored pill (Consolidate / Drop / Leave). Defaults are pre-set to Leave — change only the rows you actually want to act on.
- Use the Apply to all buttons at the top to mass-assign an action across every detected course.
- Continue with the rest of the wizard. Your decisions are saved when you click Save & Run Optimizer.
Section Clusters
Section Clusters is the wizard's control over how the optimizer groups and moves sections during the period-rearrangement pass. A cluster is the set of sections a single teacher runs in one period — for example, all five Math classes Mr. Smith teaches in Period 2 form one cluster. Sections within a cluster always move together: if the optimizer decides to relocate any section in a cluster to a different period, the entire cluster moves with it.
How clusters are built
- One cluster per (Teacher, Period) pair, regardless of semester or block.
- Mixed Fall/Spring sections that the same teacher runs in the same period are merged into one cluster. This keeps a teacher's period whole even when the courses change between semesters.
- Single-section clusters are hidden from the list. If a teacher only runs one section in a period, there is nothing to lock together — that section moves on its own and doesn't need to be displayed here. The same applies to unassigned (Teacher# 0) sections, including consolidated Holding Tank sections.
- Sections in outlier periods (anything outside the standard period set you confirmed in Step 1) are excluded — they are frozen in place by other rules.
Live updates from Holding Tank decisions
The cluster list reacts immediately when you change a Holding Tank choice. If you mark a course as Drop or Consolidate, every section of that course virtually leaves its cluster — and if a cluster falls to a single remaining section, the row hides. Switching the same course back to Leave brings the cluster back into view if it goes above one section again.
This means you can configure Holding Tank first, scroll down to Section Clusters, and trust that what you see is what the optimizer will work with.
Filter and sort
- Search box — filter by teacher name, course title, or period number. If a match lives inside the collapsed "more teachers" accordion (see below), the accordion auto-expands so you can see the hit.
- Mixed-semester only — show only the clusters that contain both Fall and Spring sections.
- Sort dropdown — order the visible clusters by:
- Sections (most → fewest) — default
- Sections (fewest → most)
- Teacher A–Z
Top 5 teachers, rest in an accordion
To keep the cluster step scannable on large schedules, only the top 5 teachers (ranked by total section count across all their clusters) appear in the main list. Everyone else is tucked into a collapsed accordion at the bottom labeled "Show N more teachers (M clusters)". Click it to expand the full list. The accordion is collapsed by default and auto-expands when a filter hit lands inside it — so search still works across every teacher.
Default state: Locked
Every auto-built cluster starts locked — pinned to its current period. The optimizer's period-rearrangement pass will not move any locked cluster. This is a conservative default that preserves your existing teacher arrangements unless you explicitly opt into movement.
Operations
| Action | What it does |
|---|---|
| Lock | Pins a cluster to its current period. The optimizer will not move it during Pass 2. |
| Unlock | Releases the pin. The optimizer is free to move the cluster to a different period if doing so improves student request fulfillment. Unlocking also reveals per-section chips with an X to drop individual sections. |
| Drop a single section (X chip) | Only available when the cluster is unlocked. Click the small X next to a section chip to drop that one section from the schedule. The chip strikes through and the X becomes a restore arrow; click again to undo. This is the same effect as Step 2 → Drop, just scoped to one section inside a cluster. |
| Lock all / Unlock all | Bulk operation across every real-teacher cluster. Singletons are skipped (they always move). |
| Reset to auto | Discards your edits and reverts every cluster to its system-generated default state. |
How to use the step
- Open the wizard and scroll to Step 7 — Section Clusters (or click Section Clusters in the sidebar).
- Each cluster shows the teacher name, the period, the section count, and a summary of the courses inside it. The lock icon on the left indicates current state.
- Use the filter input to search by teacher name, course, or period. Tick Mixed-semester only to see just the clusters that contain both Fall and Spring sections.
- Click the lock icon on any row to toggle that cluster between Locked and Unlocked, or use the bulk buttons at the top.
- Continue with the rest of the wizard. Cluster decisions are saved when you click Save & Run Optimizer.
Manually adding a section (Step 2)
Step 2 (Section Locks) also exposes a small form for adding a section that does not exist in the MST yet — for example, a class you forgot to enter into Aeries before exporting. The form takes:
- Course Number — any course code, e.g.
P730. New courses (not in the MST) are accepted; the optimizer creates a virtual section. - Period — any period present in the MST.
- Semester / Term — only the semester values that already appear in your MST are offered. For a standard semester school you'll see Fall, Spring, and Year-long. For a quarter school you'll see Quarter 1–4. For a trimester school, Trimester 1–3. The default is Year-long when available.
- Teacher — pick from the existing teacher list, or + New Teacher (TBD) if the position is unfilled.
Manually-added sections behave like real sections from the MST after they're added: they participate in clusters, the term-balancing heuristic, and Pass-2 movement (unless you lock them).
Buddy Pairs
Buddy Pairs tell the optimizer which two courses should share a teacher. The classic cases are a yearlong sequence split across Fall/Spring (the same teacher continues with the same students into the next half) and a course paired with a back-to-back support class (kids walk from English into English Support next period). Step 8 of the wizard auto-detects candidates and lets you accept or reject each one.
Two pair types
| Type | Pattern | Example |
|---|---|---|
| Term | Course A in Fall pairs with Course B in Spring (or vice versa). Same teacher continues with the same students. | E101 (F) → E101 (S) continuation, or WHIST A (F) → WHIST B (S) rollover |
| Period | Course A in Period N pairs with Course B in Period N+1 of the same day. Same teacher, students flow class-to-class. | M101 (P3) → M101L (P4) Algebra + Algebra Support |
How candidates are detected
The wizard scans your MST and SSS files for several signals:
- Same course in both terms. If Course X has Fall sections and Spring sections, it's a term-buddy candidate.
- Shared teacher. A teacher who runs both halves of the candidate pair adds confidence.
- Student rollover. Half or more of the students in Course A also appear in Course B (computed from SSS).
- Same teacher consecutive periods. A teacher runs Course A in Period N and a different Course B in Period N+1 — period-buddy candidate.
- Support keyword. Course B's title contains Support, Lab, Extension, Tutorial, Intervention, Workshop, or Study — strong period-buddy hint.
Candidates matching two or more signals are rated Very Likely; one signal is Likely.
How to use the step
- Open the wizard and scroll to Step 8 — Buddy Pairs (or click Buddy Pairs in the sidebar).
- Switch between the Term Buddies and Period Buddies tabs to review each kind. The Period Buddies tab gets a stronger visual treatment in the tab nav so it doesn't get lost beside the default-open Term tab.
- For each candidate, click Accept if you want the optimizer to treat the pair as bound (soft preference: solver tries to give them the same teacher), or Reject to skip it.
- First-load default: every Very Likely candidate (term or period) is pre-set to Accept; everything else is pre-set to Reject. Tweak rows as needed. Once you save the wizard, your explicit decisions persist and the auto-default is not re-applied on later visits.
- Use the bulk buttons at the top to Accept all, Reject all, or Accept very-likely only in one click.
- Weak period-buddy pairs in an accordion. Period-buddy candidates whose only signal is same teacher, consecutive periods (no support keyword, no student rollover) are tucked into a collapsed accordion at the bottom of the Period Buddies tab — labeled "Show N weaker pairs". Click to expand if you want to review them; they default to Reject like any other Likely candidate.
- Continue with the rest of the wizard. Accepted pairs are saved when you click Save & Run Optimizer.
Adding a manual buddy pair
Some pairs the auto-detector won't catch — for example, a pair you just decided to enforce, or a pair where the student rollover hasn't shown up yet because Spring requests aren't in the SSS. Use the Add buddy pair button on the right side of the bulk action row.
- Click Add buddy pair. An inline form appears.
- Pick the type — Term buddy for Fall→Spring continuation, Period buddy for back-to-back classes.
- Type Course A. The dropdown autocompletes from your MST course catalog. Course B defaults to Course A for term-continuation, but you can change it.
- Pick the semesters (term-buddy) or periods (period-buddy). Period B defaults to Period A + 1.
- Click Add & accept. Your new pair appears at the top of the matching tab with a Manual badge, already set to Accept.
Manual pairs are persisted with your session like any auto-detected pair. The Accept very-likely only bulk button leaves them alone — they're already accepted by default.
How the solver uses accepted pairs
For every accepted pair, the solver gives a small objective bonus to assignments where the same teacher runs both halves of the pair for the same student. The bonus is shaped so:
- It strongly prefers same-teacher when there's a tie or close-to-tie (the pair almost always binds when there's a feasible same-teacher option).
- It never sacrifices a student request fulfillment to satisfy a pair (fulfillment outweighs every secondary objective by design).
- If no teacher runs both halves of a pair (or capacity is too tight), the pair simply lands on different teachers and the schedule still completes.
Team Buddies
Team Buddies bind a student's enrollments across N teamed courses to a single cohort. They live in the Buddy Pairs wizard step on a third tab labeled Team Buddies (imported). Unlike Term and Period buddies — which preference same teacher — team buddies are about same student cohort. The teachers can be the same person, a related team, or completely different people; what matters is that every student tagged to Team 100 stays in Team 100's section of every teamed course they take.
The two MST columns
| Column | Aeries field | What you put in it |
|---|---|---|
| TmCrsGrp | MST.CG |
A short letter or label (e.g. "A") assigned to every section of every course that should be teamed. All English / Math / Science sections for a 9th-grade SLC, for example, get TmCrsGrp = "A". |
| Team# | MST.TM |
An integer (e.g. 100, 101, 102) identifying a specific cohort within the group. All sections belonging to one cohort share the same Team#. Different cohorts of the same group get different Team#s. |
How to tag sections
- Open the section's row in Aeries → SMS → Master Schedule.
- Set TmCrsGrp to a single letter shared by every section that should team together (e.g. all 9th-grade SLC sections get
"A"). - Set Team# to a unique number per cohort. Every section of one cohort uses the same number. If the SLC has three cohorts of ~30 students each, assign 100, 101, 102 across the three parallel sets of sections.
- Leave both columns blank/0 on every section that shouldn't team — electives, PE, Lunch, etc. These sections allow free mixed enrollment.
- Re-export the MST with the updated query (the query block on the upload page already includes
MST.SG MST.TM MST.CG) and re-upload to the optimizer.
Worked example
A 9th-grade SLC with three cohorts of English / Math / Science:
| Section | Course | Period | TmCrsGrp | Team# |
|---|---|---|---|---|
| 1001 | E101 | 1 | A | 100 |
| 1002 | M101 | 2 | A | 100 |
| 1003 | S101 | 3 | A | 100 |
| 1004 | E101 | 2 | A | 101 |
| 1005 | M101 | 3 | A | 101 |
| 1006 | S101 | 1 | A | 101 |
| 1007 | E101 | 3 | A | 102 |
| 1008 | M101 | 1 | A | 102 |
| 1009 | S101 | 2 | A | 102 |
| 1010 | PE01 | 5 | — | 0 |
A student requesting E101 + M101 + S101 will be routed into one of {100, 101, 102} for all three courses. The PE section is untagged so any student can land there regardless of cohort.
How the solver uses team buddies
For every accepted team group, the solver pays a strong soft penalty (default weight 50) per cohort-mismatch unit in a student's placement. The math:
- For each student × each unordered pair of teamed courses they request × each cohort, the solver compares "did I land in this cohort for course A?" with "did I land in this cohort for course B?". A mismatch costs 50.
- A clean same-cohort placement costs 0.
- A true cross-cohort split for one student in a 2-course pair costs 2 × 50 = 100 (one mismatch on each cohort).
- Request fulfillment is weighted 1000, so the solver will never sacrifice a student's request to satisfy a team binding. Teams bind whenever the solver has freedom to choose, but degrade gracefully when capacity gets tight.
Partial-request students
If a student requests only some of the team's courses (say English and Math but not Science), the binding still applies to the subset: the student is routed into one cohort for English and the same cohort for Math, but is free to land anywhere for Science (since they aren't requesting it).
The wizard UI
- Open Step 8 (Buddy Pairs) and click the Team Buddies (imported) tab on the right side of the tab nav.
- Each detected group renders as a card showing the TmCrsGrp letter, the list of teamed courses, the list of cohort numbers, and the number of students affected.
- Click "Show cohort breakdown" on any card to expand a grid of Team# × Course showing how many sections each cohort has of each course. An em-dash (—) in a cell means that cohort is missing a section for that course — the solver can't bind students to a missing cell.
- First-load default: every detected group is accepted. Untick the row to disable a group. Once saved, your decisions persist on later visits.
Silent skip rules
Some tagging patterns produce nothing the solver can act on:
- A TmCrsGrp letter used on only one course — no other course to route to. Skipped silently.
- A TmCrsGrp letter used on only one cohort (one distinct Team#) — no alternative cohort to route between. Skipped silently.
- Sections with a blank TmCrsGrp or Team# = 0 are unteamed. Both columns must be populated for a section to count.
Results Page
After the optimizer finishes, you are taken to the Results page. This page has a top header bar with key stats and export buttons, followed by a row of tabs — each giving a different view of the optimized schedule.
Header Stats
The four KPI numbers in the blue header update every time you re-run the optimizer. Requests Satisfied % is the primary metric. Student Requests Filled shows the raw count vs. total. Students Fully Scheduled counts students where every single request was placed. Solve Time shows how long the solver ran.
The badge next to the title shows the solver's final status: OPTIMAL means OR-Tools found the mathematically best solution; FEASIBLE means it found a valid solution that may improve with more time — try increasing the solver time limit in wizard settings and re-running.
Export Buttons
| Button | Format | Use for… |
|---|---|---|
| Excel Workbook | Formatted .xlsx (5 sheets) | Visual review and sharing with administrators |
| Aeries SQL Export | DELETE + INSERT SQL script | Direct import into Aeries SIS by a DBA or IT administrator |
Overview Tab
The Overview tab is the landing tab on the Results page. It shows aggregate statistics about the optimized schedule in a card-and-chart layout — no row-level data.
What Each Card and Chart Shows
| Card / Chart | Meaning |
|---|---|
| Request Fill Rate | Percentage of all student course requests assigned to a section. This is the primary optimization target. |
| Fully Scheduled | Students where every single request was fulfilled, shown as both a percentage and a raw count. |
| Empty Sections | Sections that exist in the schedule but had zero students assigned. Candidates for removal or consolidation. |
| At/Over Capacity | Sections where assigned enrollment meets or exceeds the section maximum. These may need a capacity bump or an added section. |
| Fill Rate Distribution | Doughnut chart breaking down sections by enrollment band: 0%, 1–25%, 26–50%, 51–75%, 76–99%, 100%+. |
| Student Satisfaction Breakdown | Bar chart grouping students by how many of their requests were filled: 100% (fully scheduled), 75–99%, 50–74%, and <50%. |
| Enrollment by Period | Grouped bar chart showing total Assigned enrollment vs. total Capacity for every period. Useful for spotting periods that are heavily under-utilized or over-booked. |
| Sections Below 50% Fill Rate | Warning table listing every section where enrollment is under 50% of its maximum. Columns: Section#, Period, Course#, Title, Teacher, Max, Assigned, Fill Rate. These sections are prime candidates for consolidation or period reassignment. |
| Staffing Comparison — Unique Teachers per Period | Table showing how many distinct teachers are active each period in the Original vs. Optimized schedule, with a Delta column. A negative delta means the optimizer consolidated teachers out of that period; a positive delta means it spread teachers into it. The "All Periods" row shows the net change across all periods. |
Sections Tab
The Sections tab shows the complete optimized master schedule — every section, its teacher, its period, its room, and how many students are enrolled. This is the closest view to what will be imported into Aeries.
Reading the Table
| Column | Description |
|---|---|
| SECTION# | Section number from the Aeries SMS extract. Auto-scaled sections added by the optimizer show a NEW badge. |
| P | The period this section is placed in. |
| COURSE# | Aeries course number. |
| TITLE | Course name. Auto-scaled sections show "(Auto-Scaled)" appended. |
| TEACHER | Teacher name. "Unassigned" indicates a virtual section with no teacher yet — use Staffing Gaps to assign one. |
| ROOM | Room number from the original extract. |
| MAX | Section capacity (maximum seats) from the original Aeries data. |
| ASSIGNED | Students the optimizer placed in this section. Red text = zero or very low enrollment. |
| FILL RATE | ASSIGNED ÷ MAX shown as a color-coded progress bar and percentage. |
| CHANGE | Net change in enrollment vs. the original MST. Green = more students placed, red = fewer. A dash means no change. |
Filtering and Searching
Use the filter box to search by course number, title, or teacher name. The All Periods dropdown narrows the table to a single period.
Students Tab
The Students tab shows only the students with unfilled requests — fully scheduled students are not listed here. The tab count badge (e.g., Students 160) tells you at a glance how many students have at least one unfilled course.
Failure Reason Cards
The four cards at the top summarize why requests went unfilled across all students:
| Reason | Meaning | Recommended Action |
|---|---|---|
| Period Conflict | Every section of the course is in a period already occupied by another of the student's placed courses. | Add a parallel section in a different period via Staffing Gaps. |
| Section Full | A section existed in a free period but all its seats were taken by other students. | Increase the section Max (capacity bump) or add a second section. |
| No Sections | The course appears in SSS requests but has no sections in the active schedule at all. | Use the Missing Course wizard action to create sections. |
| Solver Anomaly | A valid placement existed but the solver didn't make it — usually due to time limit pressure. | Re-run with a longer solver timeout. |
Filtering
Click the Period Conflict or Section Full filter pills to narrow the table to only students with that failure type. Use the Filter by Student# box to jump directly to a specific student.
Fix It Button
Rows where all missed requests are Section Full show a green ⚡ Fix it button. Clicking it pre-loads a capacity bump for that section into the wizard so you can immediately re-run without navigating to Staffing Gaps manually.
Student Detail Modal
Click any student row to open a full-schedule diagnostic modal showing every request, which section was assigned (or why it wasn't), and the failure category for each unfilled course.
Courses Tab
The Courses tab aggregates results by course — showing how many sections exist, total seat capacity, how many students were assigned, and the overall fill rate. Use this tab to identify courses that are over- or under-served.
Column Reference
| Column | Description |
|---|---|
| COURSE# | Aeries course number. |
| TITLE | Course name. |
| SECTIONS | Number of sections in the optimized schedule for this course. |
| CAPACITY | Combined maximum seats across all sections of this course. |
| ASSIGNED | Total students placed into this course by the optimizer. |
| FILL RATE | ASSIGNED ÷ CAPACITY as a percentage with color-coded bar. |
What to Look For
Sort by FILL RATE ascending to find the most under-served courses — prime candidates for adding sections. High ASSIGNED numbers with low FILL RATE typically means demand exceeds capacity and period conflicts are blocking students.
Staffing Gaps Tab
The Staffing Gaps tab is an action tab — not just a report. It uses a two-panel Staffing Gap Matchmaker layout to connect available teachers with high-demand courses. The tab badge count shows the total number of stranded course-student combinations needing attention.
Left Panel — Available Teachers
Shows every teacher who has at least one period where all their sections had zero enrollment (meaning students were not placed there). Each teacher card shows:
- Which periods are open (blue badges)
- Their currently active sections
- The zero-enrollment sections that freed up those periods
Right Panel — High-Demand Stranded Courses
Shows courses ranked by the number of students who could not be scheduled — sorted by unmet demand. Each course card shows:
- Total stranded students and the failure breakdown (period-conflict vs. section-full)
- Best period — the period where the most free students exist
- Free students by period — how many students have that period open
- Assign to: teacher-period pill buttons — click any pill to pre-load that teacher/period/course as a manual section in the wizard
After Assigning
Clicking a teacher-period pill immediately pre-loads the assignment into the wizard as a manual section. Re-run the optimizer to see the updated fill rate with the new section included.
Schedule Changes Tab
The Schedule Changes tab shows the impact of the optimizer's period rearrangement (Pass 2). It has four KPI cards at the top followed by two detail tables: Period Changes (sections that moved) and Auto-Added Sections (sections created to meet demand).
KPI Cards
| Card | Meaning |
|---|---|
| Pass 1 Rate | Fill rate achieved with original fixed periods, before any period rearrangement. This is the baseline the optimizer started from. |
| Final Rate | Fill rate after period rearrangement (Pass 2) and re-solve (Pass 3). This is the number shown in the main header. |
| Improvement | The gain from period rearrangement alone — Final Rate minus Pass 1 Rate. A positive value confirms rearrangement helped. |
| Sections Moved | Total number of sections whose period changed during Pass 2. |
Period Changes Table
Lists every section the optimizer moved, showing Section#, Course, Teacher, the original period (FROM PERIOD), and the new period (TO PERIOD). Use this to verify no locked sections were moved unexpectedly. If you see an unwanted move, go back to the wizard and lock that section before re-running.
Auto-Added Sections Table
Lists virtual sections the optimizer created because SSS student demand exceeded the existing section capacity by more than the auto-add threshold. Columns:
| Column | Meaning |
|---|---|
| SSS DEMAND | Total student requests for this course from the SSS file. |
| ORIGINAL CAPACITY | Total seats that existed before auto-scaling. |
| OVERFLOW | Demand minus original capacity — the gap the optimizer needed to fill. |
| CAP ADDED | Seats added by the new virtual section(s). Virtual sections show "Unassigned" as teacher — assign a real teacher via Staffing Gaps. |
Capacity Quick-Fix
The Capacity Quick-Fix feature appears in the Sections tab when a section has significantly low enrollment relative to its capacity — usually indicating that a period conflict is blocking students from accessing it. Quick-Fix lets you increase the section's enrollment cap or change its period without re-running the full optimizer.
When to Use It
Use Capacity Quick-Fix when you see a single section with very low enrollment (e.g., 5 students in a 30-seat class) and you know there are students who want it but are blocked by a period conflict. Bumping the cap rarely helps in this case — moving the section to a less-contested period is more effective.
Re-running the Optimizer
You can re-run the optimizer at any time without re-uploading your files. Your original MST/SMS and SSS data is preserved in the session, and your wizard constraints are saved automatically.
Re-run Workflows
| Scenario | Recommended Steps |
|---|---|
| You added a teacher in Staffing Gaps and want to see the impact | Click Re-run Optimizer → in the toast notification, or navigate to the wizard and click Save & Run Optimizer. |
| Fill rate is low and you want to try a longer solver time | Open the wizard → Solver Settings → increase the time limit → Save & Run Optimizer. |
| A section moved unexpectedly — you want to lock it and re-run | Open the wizard → Section Locks → check the section to lock it → Save & Run Optimizer. |
| You want to start completely fresh | Return to the home page and upload new files. This creates a new session with no preserved constraints. |
Tips & Troubleshooting
Common Issues
| Issue | Likely Cause | Fix |
|---|---|---|
| Fill rate is below 70% | Too few sections for high-demand courses, or period conflicts are widespread | Check Staffing Gaps tab → assign additional teachers → re-run. Also try enabling Period Rearrangement in Solver Settings. |
| Solver status is FEASIBLE, not OPTIMAL | The time limit was reached before the solver found the best solution | Increase solver time limit in wizard → Solver Settings → re-run. |
| A course appears in SSS but not in the Sections tab | The course number in SSS was not mapped in the Missing Courses wizard step | Return to wizard → Missing Courses → confirm or map the course number → re-run. |
| A section you locked still moved periods | The lock was not saved before the last run, or Period Rearrangement moved a different section that you expected to stay | Open wizard → Section Locks → verify the correct sections are checked → re-run. |
| File upload shows a parse error | The CSV has trailing commas, extra blank rows, or BOM characters from Excel export | Open the CSV in a text editor, remove trailing content, and re-save as UTF-8 CSV before uploading. |
Best Practices
Start each scheduling cycle by uploading fresh exports from Aeries — never reuse an export from a prior year. Lock only the sections that are truly immovable (e.g., a teacher who can only teach a specific period due to a contract constraint). The more flexibility you give the optimizer, the higher the fill rate will be.
Run the optimizer first with default settings to get a baseline fill rate. Then iteratively improve: check the Staffing Gaps tab, add a section, re-run, and compare the new fill rate. Repeat until diminishing returns.