mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-15 04:13:47 +00:00
89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
import { Rundown, EntryId, isOntimeDelay, isOntimeEvent, OntimeEvent } from 'ontime-types';
|
|
import { deleteAtIndex } from 'ontime-utils';
|
|
|
|
/**
|
|
* Applies delay from given event ID, deletes the delay event after
|
|
* Mutates the given rundown
|
|
* @throws if event ID not found or is not a delay
|
|
*/
|
|
export function apply(delayId: EntryId, rundown: Rundown): Rundown {
|
|
const delayEvent = rundown.entries[delayId];
|
|
|
|
if (!delayEvent || !isOntimeDelay(delayEvent)) {
|
|
throw new Error('Given delay ID not found');
|
|
}
|
|
|
|
const delayIndex = rundown.order.findIndex((entryId) => entryId === delayId);
|
|
|
|
// if the delay is empty, or the last element
|
|
// we can just delete it with no further operations
|
|
if (delayEvent.duration === 0 || delayIndex === rundown.order.length - 1) {
|
|
delete rundown.entries[delayId];
|
|
rundown.order = deleteAtIndex(delayIndex, rundown.order);
|
|
return rundown;
|
|
}
|
|
|
|
/**
|
|
* We apply the delay to the rundown
|
|
* This logic is mostly in sync with rundownCache.generate
|
|
* The difference is that here it will become part of the schedule,
|
|
* so we cant leave the work for the generate function
|
|
*/
|
|
let delayValue = delayEvent.duration;
|
|
let lastEntry: OntimeEvent | null = null;
|
|
let isFirstEvent = true;
|
|
|
|
for (let i = delayIndex + 1; i < rundown.order.length; i++) {
|
|
const currentId = rundown.order[i];
|
|
const currentEntry = rundown.entries[currentId];
|
|
|
|
// we don't do operation on other event types
|
|
if (!isOntimeEvent(currentEntry)) {
|
|
continue;
|
|
}
|
|
|
|
// we need to remove the link in the first event to maintain the gap
|
|
let shouldUnlink = isFirstEvent;
|
|
isFirstEvent = false;
|
|
|
|
// if the event is not linked, we try and maintain gaps
|
|
if (lastEntry !== null) {
|
|
// when applying negative delays, we need to unlink the event
|
|
// if the previous event was fully consumed by the delay
|
|
if (currentEntry.linkStart && delayValue < 0 && lastEntry.timeStart + delayValue < 0) {
|
|
shouldUnlink = true;
|
|
}
|
|
|
|
if (currentEntry.gap > 0) {
|
|
delayValue = Math.max(delayValue - currentEntry.gap, 0);
|
|
}
|
|
|
|
if (delayValue === 0) {
|
|
// we can bail from continuing if there are no further delays to apply
|
|
break;
|
|
}
|
|
}
|
|
|
|
// save the current entry before making mutations on its values
|
|
lastEntry = { ...currentEntry };
|
|
|
|
if (shouldUnlink) {
|
|
currentEntry.linkStart = null;
|
|
shouldUnlink = false;
|
|
}
|
|
|
|
// event times move up by the delay value
|
|
// we dont update the delay value since we would need to iterate through the entire dataset
|
|
// this is handled by the rundownCache.generate function
|
|
currentEntry.timeStart = Math.max(0, currentEntry.timeStart + delayValue);
|
|
currentEntry.timeEnd = Math.max(currentEntry.duration, currentEntry.timeEnd + delayValue);
|
|
currentEntry.revision += 1;
|
|
}
|
|
|
|
delete rundown.entries[delayId];
|
|
rundown.order = deleteAtIndex(delayIndex, rundown.order);
|
|
rundown.revision += 1;
|
|
|
|
return rundown;
|
|
}
|