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).
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:
vitestfor unit testing,agent-browserfor interactive UI verification - 1.4 Run
agent-browser installto 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.tswith all 14 specializations (id, name, abbreviation, requiredCourseId) - 2.3 Create
src/data/electiveSets.tswith all 12 elective sets (id, name, term, courseIds) - 2.4 Create
src/data/courses.tswith all 46 courses (id, name, setId, qualifications array with specId and marker type), transcribed from SPECIALIZATION_EVALUATION.md - 2.5 Create
src/data/lookups.tswith 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
useReducerwith 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:
useMemofor 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
SpecializationRankingcomponent: 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
ModeTogglecomponent: 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
CourseSelectioncomponent: 12 elective sets grouped by term (Spring/Summer/Fall sections) -
8.2 Build
ElectiveSetcomponent: 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
ResultsDashboardcomponent: 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
DecisionTreecomponent: 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
Appcomponent 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