prereqEval.js Core logic

Evaluates whether a course's prerequisites are satisfied given the current placement state. Returns not just pass/fail but why it fails: missing entirely, or placed in the wrong order.

Parent
Called by
PlannerContext.jsx (for every placed course, on every state change)
Result feeds
prereqViolations Map → CourseCard warning icons, RelationLines SVG

evalPrereqTree algorithm

flowchart TD A["evalPrereqTree(prereqs, placements, SEM_INDEX, semIdx)"] --> B{prereqs node type?} B -->|"and"| C["eval each child"] C --> D{worst result among children?} D -->|all satisfied| R1["return 'satisfied'"] D -->|any 'order'| R2["return 'order'"] D -->|any 'unsatisfied'| R3["return 'unsatisfied'"] B -->|"or"| E["eval each child"] E --> F{best result among children?} F -->|any satisfied| R4["return 'satisfied'"] F -->|any 'order'| R5["return 'order'"] F -->|all 'unsatisfied'| R6["return 'unsatisfied'"] B -->|"leaf course ref"| G{"course in placements?"} G -->|no| R7["return 'unsatisfied'"] G -->|yes| H{"SEM_INDEX[course.semId]\n< semIdx?"} H -->|yes, placed before| R8["return 'satisfied'"] H -->|no, same or after| R9["return 'order'"]
Worst-case propagates up AND; best-case propagates up OR. "order" means placed but too late.

Exported function

evalPrereqTree(prereqs, placements, SEM_INDEX, semesterIdx) → "satisfied" | "order" | "unsatisfied"
Walks the prerequisite tree recursively. For each leaf course reference ({ subject, classId }), checks if it's placed and whether it's in a prior semester.
  • "satisfied": prereq is placed in an earlier semester ✓
  • "order": prereq is placed but in the same or a later semester (ordering violation)
  • "unsatisfied": prereq is not placed at all
AND nodes return the worst child result (unsatisfied > order > satisfied).
OR nodes return the best child result (satisfied > order > unsatisfied).
Returns: "satisfied" | "order" | "unsatisfied"
Parameters: prereqs = prereq tree node, placements = {courseId→semId}, SEM_INDEX = {semId→ordinal}, semesterIdx = ordinal of the course being checked

How PlannerContext uses this

// PlannerContext.jsx — violation computation (simplified)
const violations = new Map();
for (const [courseId, semId] of Object.entries(placements)) {
  const course = courseMap[courseId];
  if (!course?.prereqs) continue;
  const semIdx = SEM_INDEX[semId] ?? 0;
  const result = evalPrereqTree(course.prereqs, placements, SEM_INDEX, semIdx);
  if (result !== 'satisfied') violations.set(courseId, { type: result });
}

This runs after every placement change. The resulting prereqViolations Map is read by CourseCard (warning icons) and RelationLines (draws red lines for violated edges).

Corequisite violations (not in this module)

Corequisite checking is handled inline in PlannerContext — a coreq violation occurs when the required course is not placed in the same semester as the course that requires it. The check is simpler: just look up if placements[coreqId] === placements[courseId].