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).
86 lines
6.9 KiB
Markdown
86 lines
6.9 KiB
Markdown
## 1. Project Setup
|
|
|
|
- [x] 1.1 Scaffold Vite + React + TypeScript project with `npm create vite@latest`
|
|
- [x] 1.2 Install dependencies: `javascript-lp-solver`, `@dnd-kit/core`, `@dnd-kit/sortable`, `@dnd-kit/utilities`
|
|
- [x] 1.3 Install dev dependencies: `vitest` for unit testing, `agent-browser` for interactive UI verification
|
|
- [x] 1.4 Run `agent-browser install` to set up Chromium for headless browser automation
|
|
- [x] 1.5 Configure Vite and TypeScript settings, verify dev server runs
|
|
|
|
## 2. Data Layer
|
|
|
|
- [x] 2.1 Define TypeScript types: `ElectiveSet`, `Course`, `Specialization`, `MarkerType` ('standard' | 'S1' | 'S2'), `Qualification`
|
|
- [x] 2.2 Create `src/data/specializations.ts` with all 14 specializations (id, name, abbreviation, requiredCourseId)
|
|
- [x] 2.3 Create `src/data/electiveSets.ts` with all 12 elective sets (id, name, term, courseIds)
|
|
- [x] 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
|
|
- [x] 2.5 Create `src/data/lookups.ts` with derived indexes: coursesBySet, specsByCourse, coursesBySpec (computed once at module load)
|
|
- [x] 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
|
|
|
|
- [x] 3.1 Implement `checkFeasibility(selectedCourses, targetSpecs, s2Choice?)` — builds LP model and returns feasible/infeasible with allocation details
|
|
- [x] 3.2 Implement `preFilterCandidates(selectedCourses, openSets)` — removes specs missing required courses, returns candidate list
|
|
- [x] 3.3 Implement `enumerateS2Choices(selectedCourses)` — returns array of S2 course options (including null) for Strategy enumeration
|
|
- [x] 3.4 Implement `computeUpperBounds(selectedCourses, openSets)` — upper-bound credit potential per spec ignoring sharing
|
|
- [x] 3.5 Write unit tests for LP feasibility: feasible allocations, infeasible allocations, required course gating, S2 constraint enforcement
|
|
|
|
## 4. Optimization Engine — Modes
|
|
|
|
- [x] 4.1 Implement `maximizeCount(selectedCourses, ranking, openSets)` — enumerate subsets size 3→0, check feasibility, pick best priority score
|
|
- [x] 4.2 Implement `priorityOrder(selectedCourses, ranking, openSets)` — iterate specs in rank order, greedily add if feasible
|
|
- [x] 4.3 Implement `determineStatuses(selectedCourses, openSets, achieved)` — assign achieved/achievable/missing_required/unreachable per spec
|
|
- [x] 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
|
|
|
|
- [x] 5.1 Create `src/workers/decisionTree.worker.ts` — receives selected courses + ranking + mode, computes ceiling per open set per course choice
|
|
- [x] 5.2 Implement ceiling computation with early termination (stop at 3-spec ceiling)
|
|
- [x] 5.3 Implement impact ordering: compute variance in ceiling outcomes per open set, sort descending (chronological tiebreak)
|
|
- [x] 5.4 Implement progressive messaging: worker posts results per open set as each completes
|
|
- [x] 5.5 Implement fallback: skip enumeration when 10+ sets are open, return upper-bound reachability only
|
|
- [x] 5.6 Write unit tests for ceiling computation and impact ordering logic (testable without worker wrapper)
|
|
|
|
## 6. State Management
|
|
|
|
- [x] 6.1 Define app state type: `{ ranking: string[], mode: 'maximize-count' | 'priority-order', pinnedCourses: Record<string, string | null> }`
|
|
- [x] 6.2 Implement `useReducer` with actions: `reorder`, `setMode`, `pinCourse`, `unpinCourse`
|
|
- [x] 6.3 Implement localStorage persistence: save on state change, restore on load, fallback to defaults on parse error
|
|
- [x] 6.4 Implement derived computation: `useMemo` for upper bounds + LP optimization on pinned courses (main thread)
|
|
- [x] 6.5 Implement Web Worker integration: debounced 300ms dispatch to decision tree worker, progressive state updates from worker messages
|
|
|
|
## 7. UI — Specialization Ranking
|
|
|
|
- [x] 7.1 Build `SpecializationRanking` component: vertical sortable list of 14 specializations using @dnd-kit/sortable
|
|
- [x] 7.2 Add drag handle, visual drag feedback (elevated/semi-transparent item, drop indicator)
|
|
- [x] 7.3 Add keyboard reordering support via @dnd-kit accessibility features
|
|
- [x] 7.4 Build `ModeToggle` component: two-option toggle with brief descriptions for Maximize Count and Priority Order
|
|
|
|
- [x] 7.5 Verify with agent-browser: snapshot ranking list shows 14 specializations, drag reorder works, mode toggle switches active state
|
|
|
|
## 8. UI — Course Selection
|
|
|
|
- [x] 8.1 Build `CourseSelection` component: 12 elective sets grouped by term (Spring/Summer/Fall sections)
|
|
- [x] 8.2 Build `ElectiveSet` component: shows set name, list of courses as selectable options, pin/unpin interaction
|
|
- [x] 8.3 Implement visual state indication: open sets (dashed border, all courses shown) vs pinned sets (selected course prominent, unpin control)
|
|
|
|
- [x] 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
|
|
|
|
- [x] 9.1 Build `ResultsDashboard` component: displays 14 specializations in priority rank order with status badges (achieved/achievable/missing_required/unreachable)
|
|
- [x] 9.2 Build credit progress display: progress bar toward 9-credit threshold, show allocated vs potential credits
|
|
- [x] 9.3 Build expandable allocation breakdown for achieved specializations: list contributing courses and credit amounts
|
|
- [x] 9.4 Build `DecisionTree` component: open sets ordered by impact, each showing course choices with ceiling outcomes
|
|
- [x] 9.5 Add loading states for decision tree: show upper-bound fallback while Web Worker computes, progressive update as results arrive
|
|
- [x] 9.6 Build mode comparison display: when modes disagree, show both outcomes with explanation
|
|
- [x] 9.7 Build mutual exclusion warnings: highlight SBI/E&I conflict in Spring Set 4, and other required-course conflicts
|
|
|
|
- [x] 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
|
|
|
|
- [x] 10.1 Build `App` component layout: specialization ranking panel, course selection panel, results dashboard panel
|
|
- [x] 10.2 Wire state management to all components: ranking changes, pins, mode toggle all trigger recalculation
|
|
- [x] 10.3 Verify end-to-end flow: rank specs → pin courses → see results → explore decision tree
|
|
- [x] 10.4 Add basic CSS styling: clean layout, status colors, responsive enough for desktop/tablet
|
|
- [x] 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
|