Classroom Budget Calculator¶
Specification¶
The full specification below is extracted from Chapter 19: Budgeting, Sourcing, and Classroom Logistics.
Type: microsim
**sim-id:** classroom-budget-calculator<br/>
**Library:** p5.js<br/>
**Template:** https://github.com/dmccreary/economics-course/tree/main/docs/sims/opportunity-cost-calculator<br/>
**Status:** Specified
Learning objective: Students will *apply* (Bloom L3: Apply) class size, per-kit price, and bulk discount rate to compute a realistic total project cost and cost per student.
Canvas: 700x420px default, responsive — recompute layout from `windowWidth` in `windowResized()`, stacking the controls above the result panel on screens narrower than 480px.
Layout: a control panel on the left (or top, on narrow screens) and a large result panel on the right (or bottom) showing "Total Cost" and "Cost per Student" as large readable numbers that update live as controls change.
Controls: a `createSlider()` labeled "Number of Students" (range 5-150, default 25); a `createSlider()` labeled "Base Price per Kit ($)" (range 5-300, default 25); a `createCheckbox()` labeled "Order in Bulk (25+ units)"; when checked, a `createSlider()` labeled "Bulk Discount (%)" (range 0-40, default 15) becomes enabled and reduces the effective per-kit price used in the calculation.
Interaction: the result panel recalculates on every control change: `effectivePrice = basePrice * (1 - (bulkEnabled ? discountPercent/100 : 0))`, `totalCost = effectivePrice * numStudents`, `costPerStudent = totalCost / numStudents` (equal to `effectivePrice` but displayed separately for clarity). Crossing the 25-unit bulk-eligible threshold on the "Number of Students" slider while the bulk checkbox is checked visually highlights the discount slider with a colored border and a small label reading "Bulk pricing active," reinforcing that the discount only applies at sufficient volume in a real vendor relationship.
Implementation: p5.js, all calculations performed each `draw()` frame from current control values (cheap enough to recompute continuously rather than caching), values formatted with `nf()` for consistent currency display. Parent all controls to the enclosing `<div>` and reposition them inside `windowResized()`.