One home, one light controller, three ways in
A home lighting app: the wall panel, the phone app and an evening schedule all send requests (set a light, dim it, run a scene) to one controller, which runs them and keeps Undo and Redo history for the whole home. Each level starts from the previous level’s finished code, so you can begin at any of them.
The phone app gains scenes: one button that sets several lights at once, “Movie” or “Night”. Its first version sends each of the scene’s requests to the controller in turn. People expect a scene to undo as one press, to show up in history under its name, and to do nothing at all if any part of it is wrong.
Undoing a scene takes as many presses as it has lights, history shows “Set, Set” instead of the scene, and a scene that names a light the home no longer has leaves the home half-changed.
Reproduce Run playScene(home, "Movie", [setLevel("hall", 20), setLevel("garage", 50)]): the home has no garage light, so the scene should be rejected and the hall stay at 80. Today the hall is at 20 and Past says Set. And a scene that works, [setLevel("hall", 20), setLevel("porch", 40)], takes two Undos to put back.
Acceptance criteria A scene is one step in history, labelled with its name. One Undo restores every light it changed to the level that light had when the scene ran; Redo runs the scene again. If any request in the scene is invalid, the scene is rejected and no light changes. A scene that would change nothing is no change: no step, and a pending Redo is kept. A scene can hold any request, including ones it has never seen; earlier levels’ rules still hold. Notes Cases print each step’s result, every light, then Past and Future, as in COMMAND-101. checkFlip is the checker’s own request: it turns a light fully on when it is off, and off otherwise. Some cases put it in a scene. Keep playScene’s name and signature; the checker calls it.