Files
Bill Ballou 9e00901179 Implement EMBA Specialization Solver web app
Full React+TypeScript app with LP-based optimization engine,
drag-and-drop specialization ranking (with touch/arrow support),
course selection UI, results dashboard with decision tree, and
two optimization modes (maximize-count, priority-order).
2026-02-28 20:43:00 -05:00

6.9 KiB

1. Project Setup

  • 1.1 Scaffold Vite + React + TypeScript project with npm create vite@latest
  • 1.2 Install dependencies: javascript-lp-solver, @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities
  • 1.3 Install dev dependencies: vitest for unit testing, agent-browser for interactive UI verification
  • 1.4 Run agent-browser install to set up Chromium for headless browser automation
  • 1.5 Configure Vite and TypeScript settings, verify dev server runs

2. Data Layer

  • 2.1 Define TypeScript types: ElectiveSet, Course, Specialization, MarkerType ('standard' | 'S1' | 'S2'), Qualification
  • 2.2 Create src/data/specializations.ts with all 14 specializations (id, name, abbreviation, requiredCourseId)
  • 2.3 Create src/data/electiveSets.ts with all 12 elective sets (id, name, term, courseIds)
  • 2.4 Create src/data/courses.ts with all 46 courses (id, name, setId, qualifications array with specId and marker type), transcribed from SPECIALIZATION_EVALUATION.md
  • 2.5 Create src/data/lookups.ts with derived indexes: coursesBySet, specsByCourse, coursesBySpec (computed once at module load)
  • 2.6 Write data validation tests: verify 46 courses, 12 sets, 14 specs, 10 S1 markers, 7 S2 markers, 4 required course gates, and per-specialization "across sets" counts match the reachability table

3. Optimization Engine — Core

  • 3.1 Implement checkFeasibility(selectedCourses, targetSpecs, s2Choice?) — builds LP model and returns feasible/infeasible with allocation details
  • 3.2 Implement preFilterCandidates(selectedCourses, openSets) — removes specs missing required courses, returns candidate list
  • 3.3 Implement enumerateS2Choices(selectedCourses) — returns array of S2 course options (including null) for Strategy enumeration
  • 3.4 Implement computeUpperBounds(selectedCourses, openSets) — upper-bound credit potential per spec ignoring sharing
  • 3.5 Write unit tests for LP feasibility: feasible allocations, infeasible allocations, required course gating, S2 constraint enforcement

4. Optimization Engine — Modes

  • 4.1 Implement maximizeCount(selectedCourses, ranking, openSets) — enumerate subsets size 3→0, check feasibility, pick best priority score
  • 4.2 Implement priorityOrder(selectedCourses, ranking, openSets) — iterate specs in rank order, greedily add if feasible
  • 4.3 Implement determineStatuses(selectedCourses, openSets, achieved) — assign achieved/achievable/missing_required/unreachable per spec
  • 4.4 Write unit tests for both modes: verify correct achieved sets, priority tie-breaking, status determination, edge cases (no pins, all pins)

5. Decision Tree — Web Worker

  • 5.1 Create src/workers/decisionTree.worker.ts — receives selected courses + ranking + mode, computes ceiling per open set per course choice
  • 5.2 Implement ceiling computation with early termination (stop at 3-spec ceiling)
  • 5.3 Implement impact ordering: compute variance in ceiling outcomes per open set, sort descending (chronological tiebreak)
  • 5.4 Implement progressive messaging: worker posts results per open set as each completes
  • 5.5 Implement fallback: skip enumeration when 10+ sets are open, return upper-bound reachability only
  • 5.6 Write unit tests for ceiling computation and impact ordering logic (testable without worker wrapper)

6. State Management

  • 6.1 Define app state type: { ranking: string[], mode: 'maximize-count' | 'priority-order', pinnedCourses: Record<string, string | null> }
  • 6.2 Implement useReducer with actions: reorder, setMode, pinCourse, unpinCourse
  • 6.3 Implement localStorage persistence: save on state change, restore on load, fallback to defaults on parse error
  • 6.4 Implement derived computation: useMemo for upper bounds + LP optimization on pinned courses (main thread)
  • 6.5 Implement Web Worker integration: debounced 300ms dispatch to decision tree worker, progressive state updates from worker messages

7. UI — Specialization Ranking

  • 7.1 Build SpecializationRanking component: vertical sortable list of 14 specializations using @dnd-kit/sortable

  • 7.2 Add drag handle, visual drag feedback (elevated/semi-transparent item, drop indicator)

  • 7.3 Add keyboard reordering support via @dnd-kit accessibility features

  • 7.4 Build ModeToggle component: two-option toggle with brief descriptions for Maximize Count and Priority Order

  • 7.5 Verify with agent-browser: snapshot ranking list shows 14 specializations, drag reorder works, mode toggle switches active state

8. UI — Course Selection

  • 8.1 Build CourseSelection component: 12 elective sets grouped by term (Spring/Summer/Fall sections)

  • 8.2 Build ElectiveSet component: shows set name, list of courses as selectable options, pin/unpin interaction

  • 8.3 Implement visual state indication: open sets (dashed border, all courses shown) vs pinned sets (selected course prominent, unpin control)

  • 8.4 Verify with agent-browser: snapshot shows 12 sets grouped by term, pin a course and confirm set updates to pinned state, unpin and confirm it reverts

9. UI — Results Dashboard

  • 9.1 Build ResultsDashboard component: displays 14 specializations in priority rank order with status badges (achieved/achievable/missing_required/unreachable)

  • 9.2 Build credit progress display: progress bar toward 9-credit threshold, show allocated vs potential credits

  • 9.3 Build expandable allocation breakdown for achieved specializations: list contributing courses and credit amounts

  • 9.4 Build DecisionTree component: open sets ordered by impact, each showing course choices with ceiling outcomes

  • 9.5 Add loading states for decision tree: show upper-bound fallback while Web Worker computes, progressive update as results arrive

  • 9.6 Build mode comparison display: when modes disagree, show both outcomes with explanation

  • 9.7 Build mutual exclusion warnings: highlight SBI/E&I conflict in Spring Set 4, and other required-course conflicts

  • 9.8 Verify with agent-browser: pin several courses, snapshot results dashboard to confirm status badges, credit progress, and allocation breakdown render correctly

10. App Layout & Integration

  • 10.1 Build App component layout: specialization ranking panel, course selection panel, results dashboard panel
  • 10.2 Wire state management to all components: ranking changes, pins, mode toggle all trigger recalculation
  • 10.3 Verify end-to-end flow: rank specs → pin courses → see results → explore decision tree
  • 10.4 Add basic CSS styling: clean layout, status colors, responsive enough for desktop/tablet
  • 10.5 Full agent-browser walkthrough: open app, reorder specializations, toggle mode, pin courses across multiple sets, verify results dashboard shows correct achieved/achievable statuses, explore decision tree, take final screenshot