adding block now/next data (#1661)

* adding block now/next data

* add to ui

* add blockNext

* indicate in UI

* fix test

* restore block start at value

* one loop

* stricter null comparison

* test fails

* dev throw if id cant be found

* fix spelling

* revert client stuff

* rename

* add comment
This commit is contained in:
Alex Christoffer Rasmussen
2025-06-26 21:06:20 +02:00
committed by GitHub
parent 6711cdaf4f
commit 063ae69409
11 changed files with 81 additions and 88 deletions
@@ -4,12 +4,10 @@ import type { RuntimeState } from '../runtimeState.js';
const baseState: RuntimeState = {
clock: 0,
currentBlock: {
block: null,
startedAt: null,
},
eventNow: null,
eventNext: null,
blockNow: null,
blockNext: null,
runtime: {
selectedEventIndex: null,
numEvents: 0,
@@ -104,7 +104,7 @@ describe('mutation on runtimeState', () => {
expect(newState.eventNext?.id).toBe('event2');
expect(newState.timer.playback).toBe(Playback.Armed);
expect(newState.clock).not.toBe(666);
expect(newState.currentBlock.block).toBeNull();
expect(newState.blockNow).toBeNull();
// 2. Start event
let success = start();
@@ -184,7 +184,7 @@ describe('mutation on runtimeState', () => {
expect(newState.runtime.actualStart).toBeNull();
expect(newState.runtime.plannedStart).toBe(0);
expect(newState.runtime.plannedEnd).toBe(1500);
expect(newState.currentBlock.block).toBeNull();
expect(newState.blockNow).toBeNull();
expect(newState.runtime.offset).toBe(0);
// 2. Start event
@@ -217,7 +217,7 @@ describe('mutation on runtimeState', () => {
expect(newState.runtime.offset).toBe(delayBefore);
// finish is the difference between the runtime and the schedule
expect(newState.runtime.expectedEnd).toBe(entries.event2.timeEnd - newState.runtime.offset);
expect(newState.currentBlock.block).toBeNull();
expect(newState.blockNow).toBeNull();
// 4. Add time
addTime(10);
@@ -384,17 +384,14 @@ describe('loadBlock', () => {
});
const state = {
currentBlock: {
block: null,
startedAt: 123,
},
blockNow: null,
eventNow: rundown.entries[11],
} as RuntimeState;
} as unknown as RuntimeState;
loadBlock(rundown, state);
expect(state).toMatchObject({
currentBlock: { block: rundown.entries[1], startedAt: null },
blockNow: { id: rundown.entries[1].id, startedAt: null },
eventNow: rundown.entries[11],
});
});
@@ -412,17 +409,14 @@ describe('loadBlock', () => {
});
const state = {
currentBlock: {
block: rundown.entries[1],
startedAt: 123,
},
blockNow: { id: rundown.entries[1].id, startedAt: 123 },
eventNow: rundown.entries[22],
} as RuntimeState;
loadBlock(rundown, state);
expect(state).toMatchObject({
currentBlock: { block: rundown.entries[2], startedAt: null },
blockNow: { id: rundown.entries[2].id, startedAt: null },
eventNow: rundown.entries[22],
});
});
@@ -440,8 +434,8 @@ describe('loadBlock', () => {
});
const state = {
currentBlock: {
block: rundown.entries[1],
blockNow: {
id: rundown.entries[1].id,
startedAt: 123,
},
eventNow: rundown.entries[0],
@@ -450,7 +444,7 @@ describe('loadBlock', () => {
loadBlock(rundown, state);
expect(state).toMatchObject({
currentBlock: { block: null, startedAt: null },
blockNow: null,
eventNow: rundown.entries[0],
});
});
@@ -466,17 +460,13 @@ describe('loadBlock', () => {
});
const state = {
currentBlock: {
block: rundown.entries[0],
startedAt: 123,
},
blockNow: { id: rundown.entries[0].id, startedAt: 123 },
eventNow: rundown.entries[2],
} as RuntimeState;
loadBlock(rundown, state);
expect(state).toMatchObject({
currentBlock: { block: rundown.entries[0], startedAt: 123 },
blockNow: { id: rundown.entries[0].id, startedAt: 123 },
eventNow: rundown.entries[2],
});
});
@@ -491,17 +481,14 @@ describe('loadBlock', () => {
});
const state = {
currentBlock: {
block: null,
startedAt: 123,
},
blockNow: null,
eventNow: rundown.entries[0],
} as RuntimeState;
loadBlock(rundown, state);
expect(state).toMatchObject({
currentBlock: { block: null, startedAt: 123 },
blockNow: null,
eventNow: rundown.entries[0],
});
});
+37 -25
View File
@@ -1,9 +1,9 @@
import {
CurrentBlockState,
BlockState,
isOntimeBlock,
MaybeNumber,
MaybeString,
OffsetMode,
OntimeBlock,
PlayableEvent,
Playback,
Rundown,
@@ -30,8 +30,9 @@ import { getPlayableIndexFromTimedIndex } from '../api-data/rundown/rundown.util
export type RuntimeState = {
clock: number; // realtime clock
blockNow: BlockState | null;
blockNext: BlockState | null;
eventNow: PlayableEvent | null;
currentBlock: CurrentBlockState;
eventNext: PlayableEvent | null;
runtime: Runtime;
timer: TimerState;
@@ -48,7 +49,8 @@ export type RuntimeState = {
const runtimeState: RuntimeState = {
clock: timeNow(),
currentBlock: { ...runtimeStorePlaceholder.currentBlock },
blockNow: null,
blockNext: null,
eventNow: null,
eventNext: null,
runtime: { ...runtimeStorePlaceholder.runtime },
@@ -103,8 +105,8 @@ export function clearState() {
runtimeState.eventNow = null;
runtimeState.eventNext = null;
runtimeState.currentBlock.block = null;
runtimeState.currentBlock.startedAt = null;
runtimeState.blockNow = null;
runtimeState.blockNext = null;
runtimeState.runtime.offset = 0;
runtimeState.runtime.relativeOffset = 0;
@@ -207,8 +209,8 @@ export function load(
runtimeState.runtime.relativeOffset = relativeOffset;
runtimeState.runtime.expectedEnd = getExpectedEnd(runtimeState);
}
if (typeof initialData.blockStartAt === 'number') {
runtimeState.currentBlock.startedAt = initialData.blockStartAt;
if (typeof initialData.blockStartAt === 'number' && runtimeState.blockNow) {
runtimeState.blockNow.startedAt = initialData.blockStartAt;
}
}
return event.id === runtimeState.eventNow?.id;
@@ -249,7 +251,7 @@ export function loadNext(
}
const nowPlayableIndex = getPlayableIndexFromTimedIndex(metadata, eventIndex);
if (nowPlayableIndex === null || nowPlayableIndex > metadata.playableEventOrder.length - 2) {
if (nowPlayableIndex === null || nowPlayableIndex > metadata.playableEventOrder.length - 2) {
// we cound not find the event now or the event now is the last playable event
runtimeState.eventNext = null;
return;
@@ -355,8 +357,8 @@ export function start(state: RuntimeState = runtimeState): boolean {
}
// update block start time
if (state.currentBlock.startedAt === null) {
state.currentBlock.startedAt = state.clock;
if (state.blockNow && state.blockNow.startedAt === null) {
state.blockNow.startedAt = state.clock;
}
state.timer.playback = Playback.Play;
@@ -581,8 +583,8 @@ export function roll(
runtimeState.timer.startedAt = runtimeState.clock;
// update runtime
if (runtimeState.currentBlock.startedAt === null) {
runtimeState.currentBlock.startedAt = runtimeState.clock;
if (runtimeState.blockNow && runtimeState.blockNow.startedAt === null) {
runtimeState.blockNow.startedAt = runtimeState.clock;
}
if (!runtimeState.runtime.actualStart) {
runtimeState.runtime.actualStart = runtimeState.clock;
@@ -645,8 +647,8 @@ export function roll(
// there is something to run, load event
// update runtime
if (runtimeState.currentBlock.startedAt === null) {
runtimeState.currentBlock.startedAt = runtimeState.clock;
if (runtimeState.blockNow && runtimeState.blockNow.startedAt === null) {
runtimeState.blockNow.startedAt = runtimeState.clock;
}
// event will finish on time
@@ -675,28 +677,38 @@ export function roll(
* handle block loading, not for use outside of runtimeState
*/
export function loadBlock(rundown: Rundown, state = runtimeState) {
// we need a loaded event to have a block
if (state.eventNow === null) {
// we need a loaded event to have a block
state.currentBlock.block = null;
state.currentBlock.startedAt = null;
state.blockNow = null;
state.blockNext = null;
return;
}
const currentBlockId = state.eventNow.parent;
// update time only if the block has changed
if (state.currentBlock.block?.id != currentBlockId) {
state.currentBlock.startedAt = null;
// look for potential next block
let foundEventNow = false;
for (const id of rundown.order) {
if (foundEventNow && isOntimeBlock(rundown.entries[id])) {
state.blockNext = { id, startedAt: null }; // the id is set here, the start time is set in other placed that handel starting events
break;
}
if (id === state.eventNow.id) {
foundEventNow = true;
continue;
}
}
// update the block anyway
// not inside a block
if (currentBlockId === null) {
state.currentBlock.block = null;
state.blockNow = null;
return;
}
const currentBlock = rundown.entries[currentBlockId];
state.currentBlock.block = currentBlock as OntimeBlock;
//we went into a new block - and it is different from the one we might have come from
if ((state.blockNow != null && state.blockNow.id != currentBlockId) || state.blockNow == null) {
state.blockNow = { id: currentBlockId, startedAt: null }; // the id is set here, the start time is set in other placed that handel starting events
}
}
export function setOffsetMode(mode: OffsetMode) {