core/ Pure logic
Seven modules of pure domain logic. None import React, call fetch(), or touch localStorage. Every function takes inputs and returns outputs. This makes them trivially testable in Node without a DOM.
Parent
Consumed by
PlannerContext.jsx (exclusively)
Rule
No React, no I/O, no side effects — pure functions only
Children
module (~500 lines)
gradRequirements.js
Validates placed courses against a Major2 requirement tree. The most algorithmically complex module.
module (~80 lines)
prereqEval.js
Evaluates whether a course's prerequisites are met. Returns satisfied / order-violation / missing.
module (~120 lines)
courseModel.js
Normalizes raw catalog JSON into internal course objects. Extracts prereq/coreq edges. Hashes subject colors.
module (~80 lines)
semGrid.js
Generates semester grids from cohort dates. Computes SEM_INDEX, SEM_NEXT, SEM_PREV lookup maps.
module (~200 lines)
planModel.js
Plan display helpers: SH totals, ordered course lists, edge lookups. Also: async PDF export via browser print.
constants + theme tokens
constants.js + themes.js
Global compile-time constants (colors, labels, templates) and CSS variable token sets for each theme.
Inter-module dependencies
graph TD
GR["gradRequirements.js"]
PE["prereqEval.js"]
CM["courseModel.js"]
SG["semGrid.js"]
PM["planModel.js"]
TH["themes.js"]
CO["constants.js"]
GR -->|"uses NUPATH_LABELS"| CO
CM -->|"uses SUBJECT_PALETTE"| CO
SG -->|"uses SEMESTER_TYPES"| CO
PM -->|"calls loadMajor (via param)"| GR
TH -.->|"token values from"| CO
style CO fill:#fff8c5,stroke:#9a6700
constants.js is the only internal dependency. All other modules are independent of each other.
How PlannerContext uses core
PlannerContext is the only file that imports from core/. It calls these functions during:
| Event | Core function called |
|---|---|
| Courses loaded | normalizeCourse() for each, buildCourseMap() |
| Entry/grad dates change | buildCohortSemesters(), deriveSemMaps() |
| Any placement change | evalPrereqTree() for all placed courses → violations |
| User selects major | allocateMajorWithElectives(), getNuPathCoverage() |
| Course selected | getConnections() → SVG line positions |
| PDF export triggered | exportReport() |