4b80fac500
Fixes the bug where a specialization could show "Achievable" while no per-set ceiling cell surfaces a path to it. Reproduction: pin SP2=Business of Health & Medical Care, SP4=Foundations of Fintech, SP5=Corporate Finance, SE1=GIE; rank HCR first. Healthcare showed Achievable but every ceiling cell excluded HCR. Root cause: computeCeiling used strict > on count alone, so the first equal-count combination found won permanently and HCR-including outcomes were never recorded. Changes: - Replace per-(set, choice) computeCeiling loop with a single full-tree searchDecisionTree DFS. Both the per-set ceiling table and a new ranked top-K plan list (default K=10) are populated from one enumeration. - Comparison rule everywhere is (count desc, priority score desc, deterministic-tiebreak). priorityScore extracted from optimizer.ts into a shared priority.ts module used by both call sites. - Heuristic enumeration ordering: select the first reachable ranked spec as priorityTarget; reorder DFS children at every level so target- qualifying courses are tried first. High-priority outcomes surface in early iterations instead of being blocked by less-relevant equal-count results. - Bounded search: terminate on saturation (top-K stable for 500 iterations) or hard cap (10000 iterations); set partial=true if cap hit. Mitigates the worst-case enumeration cost. - Worker protocol: tagged-union response with topKUpdate, choiceUpdate (per-cell, replaces per-set setComplete), and allComplete events. - App state adds topPlans/topPlansPartial slices and an adoptPlan action that pins a plan's full course assignment in one click. Also fixes loadState's stale "ranking.length !== 14" check (now uses SPECIALIZATIONS.length so HCR-era saved state restores correctly). - New TopPlans component renders the ranked list with adopt buttons, placed above CourseSelection in the right column. - 17 new tests in searchDecisionTree.test.ts covering priority scoring, bounded ranked list, comparison rule, target selection, the user's reproduction scenario, streaming monotonicity, saturation termination, and a performance smoke test (< 5s for the 8-open-set case). - Existing decisionTree.test.ts: one test amended for per-cell streaming semantics; remaining 3 unchanged and passing.
83 lines
7.0 KiB
Markdown
83 lines
7.0 KiB
Markdown
# Changelog
|
|
|
|
## v1.3.0 — 2026-05-09
|
|
|
|
### Changes
|
|
|
|
- **Top Plans panel** — new ranked list of up to 10 complete course plans, each showing the achieved specializations and the courses to pin. An "Adopt plan" button pins all of a plan's courses in one click. Updates progressively as the search finds better outcomes.
|
|
- **Priority-aware decision tree** — fixes the bug where a specialization could show "Achievable" without any per-set ceiling cell surfacing it. The decision-tree search now compares enumerated combinations by `(count desc, priority score desc)` and reorders DFS children so courses qualifying for the user's first reachable ranked spec are tried first, surfacing high-priority outcomes early.
|
|
- **Bounded search with saturation termination** — search stops when the top-K stabilizes (default 500 stable iterations) or when the iteration cap (10000) is hit; partial results are flagged in the UI.
|
|
- **Per-cell streaming** — the worker now emits per-cell ceiling updates instead of per-set rollups, so the per-set table refines progressively rather than appearing in coarse chunks.
|
|
|
|
## v1.2.2 — 2026-05-09
|
|
|
|
### Changes
|
|
|
|
- **Healthcare specialization (HCR)** — added 15th specialization, Healthcare; qualifies via The Business of Health & Medical Care (Spring Set 2), Analytics & Machine Learning for Managers (Spring Set 3), Digital Marketing Strategy in Practice (Summer Set 2), and Managing Change (Fall Set 1); 10 total credits available, no required course gate
|
|
- **Course rename** — "Social Media and Mobile Technology" renamed to "Digital Marketing Strategy in Practice"; description replaced with new MSKCC-anchored content covering digital strategy and agentic AI; instructor cleared pending confirmation
|
|
- **Cancellations (Approach B)** — switched from delete-and-replace to flagging cancelled courses with `cancelled: true`. "Customer Insights" (Spring Set 5) is now marked cancelled. "Managing Growing Companies" reappears in Summer Set 2 as a cancelled placeholder per the J27 sheet
|
|
- **Reachability test** — `data.test.ts` now excludes cancelled courses when counting per-spec set reachability, so future cancellations are caught by an obvious assertion failure
|
|
|
|
## v1.2.1 — 2026-03-27
|
|
|
|
### Bug Fixes
|
|
|
|
- **Achievable status accuracy** — specializations marked "Achievable" are now verified via LP feasibility check against already-achieved specs; previously, a specialization could show "Achievable" based on raw credit potential while actually being infeasible due to credit sharing with higher-priority achieved specializations
|
|
|
|
## v1.2.0 — 2026-03-27
|
|
|
|
### Changes
|
|
|
|
- **Course info popovers** — each course now has an info icon that opens a popover showing the course description, instructor(s), and specialization tags, extracted from the J27 Electives PDF; opens on hover (desktop) or tap (mobile), with smart positioning that flips above when near the bottom of the viewport
|
|
- **Page title and favicon** — updated browser tab from "app" with Vite icon to "EMBA Specialization Solver" with a graduation cap favicon in NYU Stern purple
|
|
- **Viewport-fitted layout** — desktop layout now fits within the viewable area without page-level scrolling; each pane scrolls independently
|
|
|
|
## v1.1.1 — 2026-03-27
|
|
|
|
### Changes
|
|
|
|
- **Course replacement** — replaced cancelled "Managing Growing Companies" with new course "Innovation and Design" in Summer Elective Set 2; qualifies for Brand Management, Entrepreneurship and Innovation, Marketing, and Strategy (S2)
|
|
|
|
## v1.1.0 — 2026-03-13
|
|
|
|
### Changes
|
|
|
|
- **Cancelled course support** — "Managing Growing Companies" (Summer Elective Set 2) is marked as cancelled and rendered with strikethrough, greyed-out styling, and a "(Cancelled)" label; it is excluded from solver computations and decision tree enumeration
|
|
- **Duplicate course prevention** — courses that appear in multiple elective sets (e.g., "Global Immersion Experience II" in Spring Set 1 and Summer Set 1, "The Financial Services Industry" in Spring Set 2 and Fall Set 4) are now linked; selecting one automatically disables and excludes its duplicate from selection and solver calculations, shown with an "(Already selected)" label
|
|
- **Credit bar tick marks** — specialization progress bars now display light vertical tick marks at 2.5-credit intervals for visual scale reference, layered above bar fills with the 9.0 threshold marker remaining visually distinct
|
|
|
|
## v1.0.0 — 2026-02-28
|
|
|
|
Initial release of the EMBA Specialization Solver.
|
|
|
|
### Features
|
|
|
|
- **Optimization engine** — LP-based credit allocation solver with two modes:
|
|
- **Maximize Count** — finds the largest feasible set of specializations, using ranking as tiebreaker
|
|
- **Priority Order** — greedily adds specializations in user-ranked order
|
|
- **Course selection UI** — select one course per elective set across 12 sets (Spring, Summer, Fall terms)
|
|
- **Drag-and-drop specialization ranking** — reorder the 14 specializations by priority with touch and keyboard support
|
|
- **Decision tree analysis** — Web Worker enumerates remaining course combinations to compute ceiling outcomes per choice
|
|
- **Status tracking** — each specialization classified as achieved, achievable, missing required course, or unreachable
|
|
- **Mode comparison** — displays what the alternative optimization mode would produce
|
|
- **Credit bars and allocation breakdowns** — visual progress toward the 9-credit threshold with expandable per-course detail
|
|
- **Credit legend** — collapsible explainer for bars, badges, and limits
|
|
- **Required course labels** — courses that are prerequisites for a specialization show "Required for ..." labels
|
|
- **Algorithm explanations** — clear descriptions of how each optimization mode works
|
|
- **Skeleton loading** — placeholder UI while decision tree analysis runs
|
|
- **Auto-expand achieved specializations** — achieved specs show their credit breakdown by default
|
|
- **Responsive layout** — two-panel grid on desktop/tablet, single-column on mobile
|
|
- **Mobile floating banners** — top banner summarizes specialization statuses, bottom banner shows selection progress (N/12); both appear via IntersectionObserver and scroll to their sections on tap
|
|
- **CSS transitions and animations** — cross-fade course pin/unpin, credit bar width changes, status badge color transitions, expand/collapse panels, mode toggle switching, flash on status changes; all respect `prefers-reduced-motion`
|
|
- **State persistence** — rankings and selections saved to localStorage
|
|
- **Docker deployment** — multi-stage Dockerfile (Node 22 build → Nginx Alpine serve) with Docker Compose, gzip compression, SPA fallback routing, immutable cache headers for hashed assets, configurable port (default 8080)
|
|
- **Full test suite** — data integrity, feasibility solver, optimizer, and decision tree tests via Vitest
|
|
|
|
### Constraints Modeled
|
|
|
|
- Credit non-duplication (2.5 credits per course shared across specializations)
|
|
- Maximum 3 specializations (30 total credits, 9 required each)
|
|
- Required course prerequisites for 4 specializations
|
|
- Strategy S1/S2 tier system (at most 1 S2 course contributes to Strategy)
|
|
- Mutual exclusion from same-set conflicts
|