chore: organise delay and rundown utils (#749)

This commit is contained in:
Carlos Valente
2024-01-30 21:26:37 +01:00
committed by GitHub
parent 6a5020424b
commit ec8952be56
10 changed files with 149 additions and 158 deletions
@@ -34,7 +34,7 @@ import { httpIntegration } from '../services/integration-service/HttpIntegration
import { logger } from '../classes/Logger.js';
import { deleteAllEvents, notifyChanges } from '../services/rundown-service/RundownService.js';
import { runtimeCacheStore } from '../stores/cachingStore.js';
import { delayedRundownCacheKey } from '../services/rundown-service/delayedRundown.utils.js';
import { delayedRundownCacheKey } from '../services/rundown-service/rundownCache.js';
import { integrationService } from '../services/integration-service/IntegrationService.js';
import { getProjectFiles } from '../utils/getFileListFromFolder.js';
import { configService } from '../services/ConfigService.js';
@@ -13,7 +13,7 @@ import {
reorderEvent,
swapEvents,
} from '../services/rundown-service/RundownService.js';
import { getDelayedRundown, getRundownCache } from '../services/rundown-service/delayedRundown.utils.js';
import { getDelayedRundown, getRundownCache } from '../services/rundown-service/rundownCache.js';
// Create controller for GET request to '/events'
// Returns -
-41
View File
@@ -1,41 +0,0 @@
import { isOntimeBlock, isOntimeDelay, isOntimeEvent, OntimeRundown } from 'ontime-types';
import { deleteAtIndex } from '../utils/arrayUtils.js';
export function _applyDelay(eventId: string, rundown: OntimeRundown): OntimeRundown {
const delayIndex = rundown.findIndex((event) => event.id === eventId);
const delayEvent = rundown.at(delayIndex);
if (!delayEvent) {
throw new Error('Given event ID not found');
}
if (!isOntimeDelay(delayEvent)) {
throw new Error('Given event ID is not a delay');
}
const updatedRundown = [...rundown];
const delayValue = delayEvent.duration;
if (delayValue === 0 || delayIndex === rundown.length - 1) {
// nothing to apply
return updatedRundown;
}
for (let i = delayIndex + 1; i < rundown.length; i++) {
const currentEvent = updatedRundown[i];
if (isOntimeBlock(currentEvent)) {
break;
} else if (isOntimeEvent(currentEvent)) {
currentEvent.timeStart = Math.max(0, currentEvent.timeStart + delayValue);
currentEvent.timeEnd = Math.max(currentEvent.duration, currentEvent.timeEnd + delayValue);
if (currentEvent.delay) {
currentEvent.delay = currentEvent.delay - delayValue;
}
currentEvent.revision += 1;
}
}
return deleteAtIndex(delayIndex, updatedRundown);
}
@@ -10,7 +10,6 @@ import {
import { generateId, getCueCandidate } from 'ontime-utils';
import { DataProvider } from '../../classes/data-provider/DataProvider.js';
import { block as blockDef, delay as delayDef } from '../../models/eventsDefinition.js';
import { MAX_EVENTS } from '../../settings.js';
import { EventLoader } from '../../classes/event-loader/EventLoader.js';
import { sendRefetch } from '../../adapters/websocketAux.js';
import { runtimeCacheStore } from '../../stores/cachingStore.js';
@@ -24,7 +23,7 @@ import {
cachedReorder,
cachedSwap,
delayedRundownCacheKey,
} from './delayedRundown.utils.js';
} from './rundownCache.js';
import { logger } from '../../classes/Logger.js';
import { createEvent } from '../../utils/parser.js';
import { stateMutations } from '../../state.js';
@@ -44,11 +43,6 @@ export function forceReset() {
* @return {unknown[]}
*/
export async function addEvent(eventData: Partial<OntimeEvent> | Partial<OntimeDelay> | Partial<OntimeBlock>) {
const numEvents = DataProvider.getRundownLength();
if (numEvents > MAX_EVENTS) {
throw new Error(`Reached limit number of ${MAX_EVENTS} events`);
}
let newEvent: Partial<OntimeBaseEvent> = {};
const id = generateId();
@@ -1,5 +1,5 @@
import { OntimeBlock, OntimeDelay, OntimeEvent, OntimeRundown, SupportedEvent } from 'ontime-types';
import { _applyDelay } from '../delayUtils.js';
import { applyDelay } from '../delayUtils.js';
describe('_applyDelay() ', () => {
describe('in a rundown without the delay field, persisted rundown', () => {
@@ -20,7 +20,7 @@ describe('_applyDelay() ', () => {
{ id: '5', type: SupportedEvent.Event, timeStart: 0, timeEnd: 10, duration: 10, revision: 1 } as OntimeEvent,
];
const updatedRundown = _applyDelay(delayId, testRundown);
const updatedRundown = applyDelay(delayId, testRundown);
expect(updatedRundown).toStrictEqual(expected);
});
it('applies negative delays', () => {
@@ -40,7 +40,7 @@ describe('_applyDelay() ', () => {
{ id: '5', type: SupportedEvent.Event, timeStart: 0, timeEnd: 10, duration: 10, revision: 1 } as OntimeEvent,
];
const updatedRundown = _applyDelay(delayId, testRundown);
const updatedRundown = applyDelay(delayId, testRundown);
expect(updatedRundown).toStrictEqual(expected);
});
it('maintains constant duration', () => {
@@ -56,7 +56,7 @@ describe('_applyDelay() ', () => {
{ id: '3', type: SupportedEvent.Event, timeStart: 0, timeEnd: 20, duration: 20, revision: 2 } as OntimeEvent,
];
const updatedRundown = _applyDelay(delayId, testRundown);
const updatedRundown = applyDelay(delayId, testRundown);
expect(updatedRundown).toStrictEqual(expected);
});
});
@@ -126,7 +126,7 @@ describe('_applyDelay() ', () => {
} as OntimeEvent,
];
const updatedRundown = _applyDelay(delayId, testRundown);
const updatedRundown = applyDelay(delayId, testRundown);
expect(updatedRundown).toStrictEqual(expected);
});
it('applies negative delays', () => {
@@ -194,7 +194,7 @@ describe('_applyDelay() ', () => {
} as OntimeEvent,
];
const updatedRundown = _applyDelay(delayId, testRundown);
const updatedRundown = applyDelay(delayId, testRundown);
expect(updatedRundown).toStrictEqual(expected);
});
it('maintains constant duration', () => {
@@ -242,7 +242,7 @@ describe('_applyDelay() ', () => {
} as OntimeEvent,
];
const updatedRundown = _applyDelay(delayId, testRundown);
const updatedRundown = applyDelay(delayId, testRundown);
expect(updatedRundown).toStrictEqual(expected);
});
});
@@ -1,6 +1,6 @@
import { EndAction, OntimeEvent, OntimeRundown, SupportedEvent, TimerType } from 'ontime-types';
import { calculateRuntimeDelays, calculateRuntimeDelaysFrom, getDelayAt } from '../delayedRundown.utils.js';
import { calculateRuntimeDelays, getDelayAt, calculateRuntimeDelaysFrom } from '../delayUtils.js';
describe('calculateRuntimeDelays', () => {
it('calculates all delays in a given rundown', () => {
@@ -0,0 +1,135 @@
import { OntimeRundown, isOntimeDelay, isOntimeBlock, isOntimeEvent } from 'ontime-types';
import { deleteAtIndex } from '../../utils/arrayUtils.js';
/**
* Calculates all delays in a given rundown
* @param rundown
*/
export function calculateRuntimeDelays(rundown: OntimeRundown) {
let accumulatedDelay = 0;
const updatedRundown = [...rundown];
for (const [index, event] of updatedRundown.entries()) {
if (isOntimeDelay(event)) {
accumulatedDelay += event.duration;
} else if (isOntimeBlock(event)) {
accumulatedDelay = 0;
} else if (isOntimeEvent(event)) {
updatedRundown[index] = {
...event,
delay: accumulatedDelay,
};
}
}
return updatedRundown;
}
/**
* Calculate delays in rundown from a given index
* @param eventIndex
* @param rundown
*/
export function calculateRuntimeDelaysFromIndex(eventIndex: number, rundown: OntimeRundown) {
if (eventIndex === -1) {
throw new Error('ID not found at index');
}
let accumulatedDelay = getDelayAt(eventIndex, rundown);
const updatedRundown = [...rundown];
for (let i = eventIndex; i < rundown.length; i++) {
const event = rundown[i];
if (isOntimeDelay(event)) {
accumulatedDelay += event.duration;
} else if (isOntimeBlock(event)) {
if (i === eventIndex) {
accumulatedDelay = 0;
} else {
break;
}
} else if (isOntimeEvent(event)) {
updatedRundown[i] = {
...event,
delay: accumulatedDelay,
};
}
}
return updatedRundown;
}
/**
* Calculate delays in rundown from an event with given id
* @param eventId
* @param rundown
*/
export function calculateRuntimeDelaysFrom(eventId: string, rundown: OntimeRundown) {
const index = rundown.findIndex((event) => event.id === eventId);
return calculateRuntimeDelaysFromIndex(index, rundown);
}
/**
* Calculates delay to an event at a given index
* @param eventIndex
* @param rundown
*/
export function getDelayAt(eventIndex: number, rundown: OntimeRundown): number {
if (eventIndex < 1) {
return 0;
}
// we need to check the event before
const event = rundown[eventIndex - 1];
if (isOntimeDelay(event)) {
return event.duration + getDelayAt(eventIndex - 1, rundown);
} else if (isOntimeBlock(event)) {
return 0;
} else if (isOntimeEvent(event)) {
return event.delay ?? 0;
}
return 0;
}
/**
* Applies delay from given event ID, deletes the delay event after
* @param eventId
* @param rundown
* @returns
*/
export function applyDelay(eventId: string, rundown: OntimeRundown): OntimeRundown {
const delayIndex = rundown.findIndex((event) => event.id === eventId);
const delayEvent = rundown.at(delayIndex);
if (!delayEvent) {
throw new Error('Given event ID not found');
}
if (!isOntimeDelay(delayEvent)) {
throw new Error('Given event ID is not a delay');
}
const updatedRundown = [...rundown];
const delayValue = delayEvent.duration;
if (delayValue === 0 || delayIndex === rundown.length - 1) {
// nothing to apply
return updatedRundown;
}
for (let i = delayIndex + 1; i < rundown.length; i++) {
const currentEvent = updatedRundown[i];
if (isOntimeBlock(currentEvent)) {
break;
} else if (isOntimeEvent(currentEvent)) {
currentEvent.timeStart = Math.max(0, currentEvent.timeStart + delayValue);
currentEvent.timeEnd = Math.max(currentEvent.duration, currentEvent.timeEnd + delayValue);
if (currentEvent.delay) {
currentEvent.delay = currentEvent.delay - delayValue;
}
currentEvent.revision += 1;
}
}
return deleteAtIndex(delayIndex, updatedRundown);
}
@@ -15,8 +15,8 @@ import { DataProvider } from '../../classes/data-provider/DataProvider.js';
import { getCached, runtimeCacheStore } from '../../stores/cachingStore.js';
import { isProduction } from '../../setup.js';
import { deleteAtIndex, insertAtIndex, reorderArray } from '../../utils/arrayUtils.js';
import { _applyDelay } from '../delayUtils.js';
import { createPatch } from '../../utils/parser.js';
import { applyDelay, calculateRuntimeDelays, calculateRuntimeDelaysFromIndex, getDelayAt } from './delayUtils.js';
/**
* Keep incremental revision number of rundown for runtime
@@ -275,10 +275,10 @@ export async function cachedSwap(fromEventId: string, toEventId: string) {
export async function cachedApplyDelay(eventId: string) {
// update persisted rundown
const rundown: OntimeRundown = DataProvider.getRundown();
const persistedRundown = _applyDelay(eventId, rundown);
const persistedRundown = applyDelay(eventId, rundown);
const delayedRundown = getDelayedRundown();
const cachedRundown = _applyDelay(eventId, delayedRundown);
const cachedRundown = applyDelay(eventId, delayedRundown);
// update
runtimeCacheStore.setCached(delayedRundownCacheKey, cachedRundown);
@@ -286,92 +286,3 @@ export async function cachedApplyDelay(eventId: string) {
rundownRevision++;
}
/**
* Calculates all delays in a given rundown
* @param rundown
*/
export function calculateRuntimeDelays(rundown: OntimeRundown) {
let accumulatedDelay = 0;
const updatedRundown = [...rundown];
for (const [index, event] of updatedRundown.entries()) {
if (isOntimeDelay(event)) {
accumulatedDelay += event.duration;
} else if (isOntimeBlock(event)) {
accumulatedDelay = 0;
} else if (isOntimeEvent(event)) {
updatedRundown[index] = {
...event,
delay: accumulatedDelay,
};
}
}
return updatedRundown;
}
/**
* Calculate delays in rundown from a given index
* @param eventIndex
* @param rundown
*/
export function calculateRuntimeDelaysFromIndex(eventIndex: number, rundown: OntimeRundown) {
if (eventIndex === -1) {
throw new Error('ID not found at index');
}
let accumulatedDelay = getDelayAt(eventIndex, rundown);
const updatedRundown = [...rundown];
for (let i = eventIndex; i < rundown.length; i++) {
const event = rundown[i];
if (isOntimeDelay(event)) {
accumulatedDelay += event.duration;
} else if (isOntimeBlock(event)) {
if (i === eventIndex) {
accumulatedDelay = 0;
} else {
break;
}
} else if (isOntimeEvent(event)) {
updatedRundown[i] = {
...event,
delay: accumulatedDelay,
};
}
}
return updatedRundown;
}
/**
* Calculate delays in rundown from an event with given id
* @param eventId
* @param rundown
*/
export function calculateRuntimeDelaysFrom(eventId: string, rundown: OntimeRundown) {
const index = rundown.findIndex((event) => event.id === eventId);
return calculateRuntimeDelaysFromIndex(index, rundown);
}
/**
* Calculates delay to an event at a given index
* @param eventIndex
* @param rundown
*/
export function getDelayAt(eventIndex: number, rundown: OntimeRundown): number {
if (eventIndex < 1) {
return 0;
}
// we need to check the event before
const event = rundown[eventIndex - 1];
if (isOntimeDelay(event)) {
return event.duration + getDelayAt(eventIndex - 1, rundown);
} else if (isOntimeBlock(event)) {
return 0;
} else if (isOntimeEvent(event)) {
return event.delay ?? 0;
}
return 0;
}
-1
View File
@@ -1 +0,0 @@
export const MAX_EVENTS = 32768;
-7
View File
@@ -22,7 +22,6 @@ import {
import { block as blockDef, delay as delayDef } from '../models/eventsDefinition.js';
import { dbModel } from '../models/dataModel.js';
import { createEvent } from './parser.js';
import { MAX_EVENTS } from '../settings.js';
/**
* Parse events array of an entry
@@ -38,12 +37,6 @@ export const parseRundown = (data: Partial<DatabaseModel>): OntimeRundown => {
let eventIndex = 0;
const ids = [];
for (const event of data.rundown) {
// cap number of events
if (rundown.length >= MAX_EVENTS) {
console.log(`ERROR: Reached limit number of ${MAX_EVENTS} events`);
break;
}
// double check unique ids
if (ids.includes(event?.id)) {
console.log('ERROR: ID collision on import, skipping');