Cooperative Multitasking Timeline Simulator¶
Specification¶
The full specification below is extracted from Chapter 8: Adding an OLED Display and Expressive Behaviors.
Type: interactive-timeline
**sim-id:** cooperative-multitasking-timeline<br/>
**Library:** vis-timeline<br/>
**Template:** https://github.com/dmccreary/learning-micropython/tree/main/docs/sims/blocking-vs-nonblocking<br/>
**Status:** Specified
Learning objective: Students will *compare* (Bloom L4: Analyze) how blocking `sleep_ms()` code versus non-blocking, `ticks_ms()`-based code affects a robot's ability to respond to a sensor event while a melody is playing.
Canvas: 700x420px, responsive -- vis-timeline's container is set to `width: 100%` with the timeline instance's `redraw()` called inside a debounced `window.onresize` handler.
Layout: two stacked vis-timeline rows sharing one time axis, labeled "Blocking Code" and "Non-Blocking Code." Each row shows the same buzzer melody as three colored timeline blocks (one per note) and a single "Obstacle appears" event marker placed at the same timestamp on both rows, roughly halfway through the second note.
Controls: a "Play Simulation" button that animates a moving playhead across both timeline rows in sync; a `createSlider()`-equivalent HTML range input labeled "Obstacle Timing" that lets students drag the obstacle-event marker to a different point along the melody and re-run the comparison.
Interaction: as the playhead crosses the obstacle marker, the Non-Blocking row immediately shows a green "Reacted!" flag appearing right at that timestamp, while the Blocking row's reaction flag only appears once the current note block finishes playing -- visibly later -- with a small duration label showing exactly how many milliseconds of delayed reaction that gap represents. Clicking any timeline block (via vis-timeline's `click` event) opens an infobox with the underlying code line it represents, drawn from the surrounding chapter's two code examples.
Implementation: vis-timeline for the dual synchronized rows; playhead animation driven by `requestAnimationFrame` advancing a shared simulated-time variable, with reaction-flag placement computed as "next non-blocking loop pass" (near-instant) for the bottom row versus "end of current sleep_ms call" for the top row, both derived from the melody's note-duration data.