refactor: roll mode

* chore: escalate stack trace to console

* refactor: event finding in roll

* docs: initial roll specification

* refactor: call to roll

* refactor: normalise index

* refactor: roll into next event

* refactor: hot reload on waiting to roll

* refactor: wait to roll next
This commit is contained in:
Carlos Valente
2024-08-04 21:34:01 +02:00
committed by GitHub
parent 3012d73285
commit da11ef64c2
21 changed files with 1093 additions and 982 deletions
@@ -0,0 +1,29 @@
import { checkIsNow } from './checkIsNow';
import { MILLIS_PER_HOUR } from './conversionUtils';
describe('checkIsNow()', () => {
test('should return true if now is between timeStart and timeEnd', () => {
const timeStart = 9;
const timeEnd = 16;
const now = 10;
expect(checkIsNow(timeStart, timeEnd, now)).toBe(true);
});
test('should return false if now is before start', () => {
const timeStart = 9;
const timeEnd = 16;
const now = 8;
expect(checkIsNow(timeStart, timeEnd, now)).toBe(false);
});
test('should return false if now is after end', () => {
const timeStart = 9;
const timeEnd = 16;
const now = 20;
expect(checkIsNow(timeStart, timeEnd, now)).toBe(false);
});
test('should return true accounting for events that roll over midnight', () => {
expect(checkIsNow(22 * MILLIS_PER_HOUR, 8 * MILLIS_PER_HOUR, 23 * MILLIS_PER_HOUR)).toBe(true);
});
});
@@ -0,0 +1,9 @@
import { dayInMs } from './conversionUtils.js';
/**
* Utility function checks whether a given event should be playing now
*/
export function checkIsNow(timeStart: number, timeEnd: number, clock: number): boolean {
const normalisedEnd = timeEnd < timeStart ? timeEnd + dayInMs : timeEnd;
return timeStart <= clock && clock <= normalisedEnd;
}
@@ -3,7 +3,6 @@ import { SupportedEvent } from 'ontime-types';
import {
filterPlayable,
filterTimedEvents,
getLastEvent,
getLastNormal,
getNext,
@@ -300,24 +299,19 @@ describe('getLastEvent', () => {
});
});
describe('filter event', () => {
const eventA = { id: 'a', type: SupportedEvent.Event } as OntimeEvent;
const eventB = { id: 'b', skip: true, type: SupportedEvent.Event } as OntimeEvent;
const testRundown = [
eventA,
eventB,
{ id: 'c', type: SupportedEvent.Delay },
{ id: 'd', type: SupportedEvent.Block },
];
describe('filterPlayable()', () => {
test('should return an array with only playable events', () => {
const eventA = { id: 'a', type: SupportedEvent.Event } as OntimeEvent;
const eventB = { id: 'b', skip: true, type: SupportedEvent.Event } as OntimeEvent;
const testRundown = [
eventA,
eventB,
{ id: 'c', type: SupportedEvent.Delay },
{ id: 'd', type: SupportedEvent.Block },
];
test('filterPlayable', () => {
const result = filterPlayable(testRundown as unknown as OntimeRundown);
expect(result).toMatchObject([eventA]);
});
test('filterTimedEvents', () => {
const result = filterTimedEvents(testRundown as unknown as OntimeRundown);
expect(result).toMatchObject([eventA, eventB]);
});
});
});
@@ -1,14 +1,19 @@
import type { NormalisedRundown, OntimeBlock, OntimeEvent, OntimeRundown, OntimeRundownEntry } from 'ontime-types';
import { isOntimeBlock, isOntimeEvent } from 'ontime-types';
import type {
NormalisedRundown,
OntimeBlock,
OntimeEvent,
OntimeRundown,
OntimeRundownEntry,
PlayableEvent,
} from 'ontime-types';
import { isOntimeBlock, isOntimeEvent, isPlayableEvent } from 'ontime-types';
type IndexAndEntry = { entry: OntimeRundownEntry | null; index: number | null };
/**
* Gets first event in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @return {OntimeRundownEntry | null}
*/
export function getFirst(rundown: OntimeRundownEntry[]) {
export function getFirst(rundown: OntimeRundown) {
return rundown.length ? rundown[0] : null;
}
@@ -25,16 +30,14 @@ export function getFirstNormal(rundown: NormalisedRundown, order: string[]) {
/**
* Gets first scheduled event in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @return {{ firstEvent: OntimeEvent | null; firstIndex: number | null } }
*/
export function getFirstEvent(rundown: OntimeRundownEntry[]): {
firstEvent: OntimeEvent | null;
export function getFirstEvent(rundown: OntimeRundown): {
firstEvent: PlayableEvent | null;
firstIndex: number | null;
} {
for (let i = 0; i < rundown.length; i++) {
const firstEvent = rundown[i];
if (isOntimeEvent(firstEvent) && !firstEvent.skip) {
if (isOntimeEvent(firstEvent) && isPlayableEvent(firstEvent)) {
return { firstEvent, firstIndex: i };
}
}
@@ -43,21 +46,18 @@ export function getFirstEvent(rundown: OntimeRundownEntry[]): {
/**
* Gets first scheduled event in a normalised rundown, if it exists
* @param rundown
* @param order
* @returns
*/
export function getFirstEventNormal(
rundown: NormalisedRundown,
order: string[],
): {
firstEvent: OntimeEvent | null;
firstEvent: PlayableEvent | null;
firstIndex: number | null;
} {
for (let i = 0; i < order.length; i++) {
const firstId = order[i];
const firstEvent = rundown[firstId];
if (isOntimeEvent(firstEvent) && !firstEvent.skip) {
if (isOntimeEvent(firstEvent) && isPlayableEvent(firstEvent)) {
return { firstEvent, firstIndex: i };
}
}
@@ -66,9 +66,6 @@ export function getFirstEventNormal(
/**
* Gets last event in a normalised rundown, if it exists
* @param rundown
* @param order
* @returns
*/
export function getLastNormal(rundown: NormalisedRundown, order: string[]): OntimeRundownEntry | null {
const lastId = order.at(-1);
@@ -80,11 +77,9 @@ export function getLastNormal(rundown: NormalisedRundown, order: string[]): Onti
/**
* Gets last scheduled event in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @return {{ firstEvent: OntimeEvent | null; firstIndex: number | null } }
*/
export function getLastEvent(rundown: OntimeRundown): {
lastEvent: OntimeEvent | null;
lastEvent: PlayableEvent | null;
lastIndex: number | null;
} {
if (rundown.length < 1) {
@@ -93,7 +88,7 @@ export function getLastEvent(rundown: OntimeRundown): {
for (let i = rundown.length - 1; i >= 0; i--) {
const lastEvent = rundown.at(i);
if (isOntimeEvent(lastEvent) && !lastEvent.skip) {
if (isOntimeEvent(lastEvent) && isPlayableEvent(lastEvent)) {
return { lastEvent, lastIndex: i };
}
}
@@ -102,9 +97,6 @@ export function getLastEvent(rundown: OntimeRundown): {
/**
* Gets last scheduled event in a normalised rundown, if it exists
* @param rundown
* @param order
* @return {{ firstEvent: OntimeEvent | null; firstIndex: number | null } }
*/
export function getLastEventNormal(
rundown: NormalisedRundown,
@@ -129,12 +121,9 @@ export function getLastEventNormal(
/**
* Gets next entry in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @param {string} currentId
* @return {{ nextEvent: OntimeRundownEntry | null; nextIndex: number | null } }
*/
export function getNext(
rundown: OntimeRundownEntry[],
rundown: OntimeRundown,
currentId: string,
): { nextEvent: OntimeRundownEntry | null; nextIndex: number | null } {
const index = rundown.findIndex((event) => event.id === currentId);
@@ -149,10 +138,6 @@ export function getNext(
/**
* Gets next entry in rundown, if it exists
* @param rundown
* @param order
* @param currentId
* @returns
*/
export function getNextNormal(rundown: NormalisedRundown, order: string[], currentId: string): IndexAndEntry {
const currentIndex = order.findIndex((id) => id === currentId);
@@ -168,12 +153,9 @@ export function getNextNormal(rundown: NormalisedRundown, order: string[], curre
/**
* Gets next scheduled event in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @param {string} currentId
* @return {{ nextEvent: OntimeEvent | null; nextIndex: number | null } }
*/
export function getNextEvent(
rundown: OntimeRundownEntry[],
rundown: OntimeRundown,
currentId: string,
): { nextEvent: OntimeEvent | null; nextIndex: number | null } {
const index = rundown.findIndex((event) => event.id === currentId);
@@ -192,10 +174,6 @@ export function getNextEvent(
/**
* Gets next scheduled event in a normalised rundown, if it exists
* @param rundown
* @param order
* @param {string} currentId
* @return {{ nextEvent: OntimeEvent | null; nextIndex: number | null } }
*/
export function getNextEventNormal(
rundown: NormalisedRundown,
@@ -219,10 +197,8 @@ export function getNextEventNormal(
/**
* Gets previous entry in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @param {string} currentId
*/
export function getPrevious(rundown: OntimeRundownEntry[], currentId: string): IndexAndEntry {
export function getPrevious(rundown: OntimeRundown, currentId: string): IndexAndEntry {
const currentIndex = rundown.findIndex((event) => event.id === currentId);
if (currentIndex !== -1 && currentIndex - 1 >= 0) {
const index = currentIndex - 1;
@@ -235,9 +211,6 @@ export function getPrevious(rundown: OntimeRundownEntry[], currentId: string): I
/**
* Gets previous entry in a nornalised rundown, if it exists
* @param rundown
* @param order
* @param {string} currentId
*/
export function getPreviousNormal(rundown: NormalisedRundown, order: string[], currentId: string): IndexAndEntry {
const currentIndex = order.findIndex((id) => id === currentId);
@@ -253,12 +226,9 @@ export function getPreviousNormal(rundown: NormalisedRundown, order: string[], c
/**
* Gets previous scheduled event in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @param {string} currentId
* @return {{ previousEvent: OntimeRundownEntry | null; previousIndex: number | null } }
*/
export function getPreviousEvent(
rundown: OntimeRundownEntry[],
rundown: OntimeRundown,
currentId: string,
): { previousEvent: OntimeEvent | null; previousIndex: number | null } {
const index = rundown.findIndex((event) => event.id === currentId);
@@ -302,8 +272,6 @@ export function getPreviousEventNormal(
/**
* @description swaps two OntimeEvents in the rundown
* @param {OntimeEvent} eventA
* @param {OntimeEvent} eventB
*/
export const swapEventData = (eventA: OntimeEvent, eventB: OntimeEvent): { newA: OntimeEvent; newB: OntimeEvent } => {
const newA = {
@@ -333,10 +301,6 @@ export function getEventWithId(rundown: OntimeRundown, id: string): OntimeRundow
/**
* Gets relevant block element for a given ID
* @param rundown
* @param order
* @param {string} currentId
* @return {OntimeBlock | null}
*/
export function getRelevantBlock(rundown: OntimeRundown, currentId: string): OntimeBlock | null {
let inBlock = false;
@@ -357,16 +321,14 @@ export function getRelevantBlock(rundown: OntimeRundown, currentId: string): Ont
}
/**
* returns all events that can be loaded
* @return {array}
* filters a rundown to timed events
*/
export function filterPlayable(rundown: OntimeRundown): OntimeEvent[] {
return rundown.filter((event) => isOntimeEvent(event) && !event.skip) as OntimeEvent[];
export function filterPlayable(rundown: OntimeRundown): PlayableEvent[] {
return rundown.filter((event) => isOntimeEvent(event) && !event.skip) as PlayableEvent[];
}
/**
* returns all events of type OntimeEvent
* @return {array}
* filters a rundown to events that can be played
*/
export function filterTimedEvents(rundown: OntimeRundown): OntimeEvent[] {
return rundown.filter((event) => isOntimeEvent(event)) as OntimeEvent[];