Generating Lifeguard Stand Rotations with Even Break Distribution
Rotation Grid builds a timed stand-rotation schedule from the guards on shift and the stations that are open. It distributes breaks evenly through the cycle, guarantees that every guard covers every position over a full rotation, and can rebuild the remainder of the shift from the current time when a guard goes down — without altering the blocks already worked. It is a single-file, offline tool [1].
The problem
A rotation written by hand tends to bunch breaks toward the end of the cycle, leave one guard in the deep-water stand three blocks running, or quietly drop a station when someone leaves early. Redoing it mid-shift on paper means recomputing every remaining block by hand while the current one is already running. Rotation Grid makes the schedule a function of two lists — who is in and which stations are open — so a change to either regenerates a correct grid immediately.
How it works
Guards and stations are entered as chips. Tapping a chip toggles it out (struck through) without deleting it, so tomorrow's roster is a couple of taps from today's; the ✕ on a chip deletes it for good. The shift start, end, and rotation interval (10/15/20/30 minutes) sit above. A live status line shows, before anything is generated, the number of break slots per block and the maximum consecutive time any guard spends in a stand — the policy check — updating as chips are toggled.
Build grid generates the full schedule from shift start. The grid highlights the current block, dims completed blocks, and can be printed: a print stylesheet strips the interface down to a bordered black-on-white table for the wall. Copy from now exports only the remaining blocks, sized for a DigiQuatics staff alert; Copy full grid exports the whole thing.
The math
Coverage
For N guards there are N positions: the M open stations plus N − M break slots. At row r of the cycle, the guard in slot i occupies position (i - r) mod N. Because the offset advances by one each block, every guard passes through every position exactly once over a full cycle — coverage is provably fair rather than eyeballed.
guard at slot i, row r → position (i - r) mod N
Break distribution
Breaks are spread through the cycle with a Bresenham-style test rather than clustered at the end. Walking the N positions, a break slot is placed at position i whenever the running count of breaks ticks over:
place a break at i when floor((i+1)·B / N) > floor(i·B / N)
where B is the number of break slots. This is the same integer-only distribution a line-drawing algorithm uses to space pixels evenly.
Mid-shift rebuild
Rebuild from now freezes every block that has already completed (its start plus the interval is at or before the current time), then regenerates only the future blocks with the currently active roster. Removing a guard clears them from all future blocks while the completed history stays intact; superseded blocks are tinted so the record shows what the plan was before the change.
Editing the config
The default station list is the one constant at the top of the <script> block:
const DEFAULT_STATIONS = ["Comp North","Comp South","Comp Deep","Instructional","Splash Pad"];
Everything else — guards, edited stations, shift times, interval, and the last generated grid — is entered in the interface and persisted to localStorage (rotationgrid.v1). The seed list only matters on first run or after a storage reset.
Limitations
- Coverage is position-agnostic. The algorithm guarantees each guard rotates through every open station, but it does not know that a given stand is certification-gated or that a particular guard should not be placed in deep water. It rotates people through stations uniformly; the head guard still owns those judgments.
- It needs at least as many guards as open stations. Fewer guards than stations blocks generation with a banner naming how many stations to close; equal guards and stations warns that there are zero break slots.
- Breaks are distributed by count and spacing, not by individual fatigue or meal-break law. The maximum-consecutive readout is the tool's contribution to that judgment; the policy decision is the operator's.
- The grid is a plan, not attendance. It does not track who actually took which stand.