Lighting cue stack
MediumOnline Assessment
Simulate the cue stack of a theatre lighting console.
The rig has channels dimmer channels, numbered from 1, each at a level from 0 to 100. All start at 0, and the console starts before cue 1 (the "blackout", cue 0). cues[i] = [fade, changes] is cue i + 1: changes lists [channel, level] pairs, and fade is how many ticks the lights take to get there.
Tracking. A cue's *target* is the previous cue's target with that cue's changes applied. A channel a cue does not mention keeps whatever the cues before it set. The target of cue 0 is all zeros.
Fades. GO moves to the next cue and BACK to the previous one; either starts a fade from the levels the lights show *right now* (which may be partway through an earlier fade) to the new cue's target, over fade ticks. GO uses the fade of the cue it moves to; BACK uses the fade of the cue it leaves. A new fade replaces any fade in progress. GO on the last cue and BACK on cue 0 do nothing. A fade of 0 ticks arrives immediately.
After e ticks of a d-tick fade, a channel that started at a and is heading to b shows a + (b - a) * e / d, with the fractional part dropped toward a (never past the target; for example 33.3 becomes 33 and a decrease of 16.5 becomes 16). Once e >= d it shows b.
Commands: "WAIT n" lets n ticks pass. "SNAP" finishes the fade in progress immediately. "READ" records the current levels of all channels in order.
Input: channels, cues and commands as above.
Output: a list with one entry per READ (in order), each a list of the channels levels.
Example 1
- Input:
- [3,[[4,[[1,100],[2,50]]],[2,[[1,0],[3,80]]]],["GO","WAIT 2","READ","WAIT 2","READ","GO","WAIT 1","READ","WAIT 5","READ"]]
- Output:
- [[50,25,0],[100,50,0],[50,50,40],[0,50,80]]
- Explanation
- GO starts cue 1, a 4-tick fade to [100, 50, 0]. Two ticks in, it is halfway: [50, 25, 0]. After 4 ticks it has arrived. The second GO starts cue 2 (2 ticks) toward [0, 50, 80]; after one tick every channel is halfway between where it was and where it is going: [50, 50, 40].
Example 2
- Input:
- [2,[[3,[[1,100]]],[6,[[1,40],[2,100]]]],["GO","WAIT 1","GO","WAIT 2","READ","BACK","WAIT 3","READ","SNAP","READ"]]
- Output:
- [[35,33],[67,17],[100,0]]
- Explanation
- After 1 tick of cue 1 channel 1 is 33 (33.3 rounds toward the start, 0). Starting cue 2 (6 ticks) from the live levels [33, 0] toward [40, 100]: after 2 ticks channel 1 is 33 + 2 = 35 and channel 2 is 33, so [35, 33]. BACK returns to cue 1 using the fade time of the cue being left, 6: from [35, 33] toward [100, 0], after 3 ticks channel 1 is 35 + 32 = 67 and channel 2 is 33 - 16 = 17. SNAP jumps to [100, 0].
Example 3
- Input:
- [2,[[0,[[1,60],[2,30]]],[0,[[2,90]]],[0,[[1,0]]]],["GO","GO","GO","READ","GO","READ","BACK","READ","BACK","BACK","READ","BACK","READ"]]
- Output:
- [[0,90],[0,90],[60,90],[0,0],[0,0]]
- Explanation
- Cue 3 only mentions channel 1, so channel 2 keeps the 90 set by cue 2: [0, 90]. GO at the end of the list does nothing. BACK to cue 2 restores channel 1 to the value that cue 1 set, 60, while channel 2 stays 90. Two BACKs more reach the blackout before cue 1, and a BACK there does nothing.
Constraints
1 <= channels <= 80 <= cues.length <= 30; each cue is[fade, changes]with0 <= fade <= 100, and each change is[channel, level]with1 <= channel <= channels,0 <= level <= 100; a channel appears at most once in a cue0 <= commands.length <= 300; each command is"GO","BACK","SNAP","READ"or"WAIT n"with0 <= n <= 100