# Reference patch — 02-happy-hour

The answer key for how the reference absorbs this change, and the thing that makes
`budget.json` reproducible. **Never shipped to the candidate.**

1. **Add** `PromotionalPricing.java` (in this directory) to `reference/src/`. New file, so
   `measureChange` charges nothing for it.
2. **Change one line** in `reference/src/MachineFactory.java`, in `standard()`:

   ```diff
   -                new ListPricing(),
   +                new PromotionalPricing(new ListPricing()),
   ```

`ListPricing` is decorated, not deleted. The shelf prices are still the shelf prices and the
promotion is expressed as what it is — an adjustment on top — so ending the promotion is the same
one line in reverse and the rack never moves.

Measured: `reference_diff = 2` (1 added, 1 removed, one file touched), so
`diff_budget = max(3, 2 + ceil(2/2)) = 3`.

The curveball suite (8 tests) is green after the patch.

**The base suite is deliberately not expected to stay green here.** Five of its sixteen tests
assert the old tariff — the exact price of the chips, the change owed on a dollar, the size of the
shortfall, and the one sale the thin float cannot change — and replacing the tariff is precisely
what the requirement asked for. Nothing else in it moves: stock, states, refusal types, the tray
and the coin return are all still green.

## Where the requirement landed, and where it did not

`VendingMachine` was not opened. That is the measurement: the class that runs the sale, validates
the state, empties the escrow and refuses five different ways has no opinion about prices, so a
tariff change cannot reach it.

The two seams that made it a one-liner:

- **`PricingPolicy` separates "the price on the label" from "what the till charges."** They are
  equal today, which is exactly why collapsing them is tempting. `slot.priceMinor()` read at the
  point of sale would have put the discount arithmetic, the rounding rule and the free-slot
  exception inside `select()`, alongside the funds check it changes the meaning of — and there
  would then be nowhere to put "the shelf label still says 65", because there would only be one
  number.
- **`MachineFactory` owns the wiring**, so choosing a tariff is a line of construction rather than
  an edit to behaviour. Had `VendingMachine` carried a convenience constructor supplying its own
  defaults, this line would have been inside the class under test.

The free water is the part worth checking in a candidate's design, because it is where a
plausible shortcut breaks. A price of zero has to flow through untouched: the funds check must be
`inserted < price` and not `inserted == 0`, and change of zero must not be mistaken for change the
machine cannot make. In the reference both fall out for free — `0 <= 0` passes, and
`ChangeMaker.compose(0, …)` returns an empty list rather than an empty `Optional`. No new state,
no new branch, and no new transition: `IDLE + SELECT` was already a legal row in the table
precisely because the state machine has no business knowing what things cost.
