refactor: fix delay positioning in gaps

This commit is contained in:
Carlos Valente
2025-04-13 10:59:06 +02:00
committed by Carlos Valente
parent 68175cfa3b
commit 030c8f897f
2 changed files with 78 additions and 0 deletions
@@ -170,6 +170,73 @@ describe('generate()', () => {
expect(initResult.totalDuration).toBe(dayInMs + MILLIS_PER_HOUR); // day + last end - first start
});
it('maintains delays over gaps', () => {
const rundown = makeRundown({
order: ['1', 'delay', '2'],
entries: {
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
delay: makeOntimeDelay({ id: 'delay', duration: 500 }),
'2': makeOntimeEvent({ id: '2', timeStart: 500, timeEnd: 600, duration: 100 }),
},
});
const initResult = generate(rundown, {});
expect(initResult.entries['2']).toMatchObject({
gap: 400,
delay: 500,
});
expect(initResult.totalDelay).toBe(500);
expect(initResult.totalDuration).toBe(600);
});
it('maintains delays over gaps when there are cumulative delays', () => {
const rundown = makeRundown({
order: ['delay1', '1', 'delay2', '2'],
entries: {
delay1: makeOntimeDelay({ id: 'delay', duration: 100 }),
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
delay2: makeOntimeDelay({ id: 'delay', duration: 300 }),
'2': makeOntimeEvent({ id: '2', timeStart: 300, timeEnd: 400, duration: 100 }),
},
});
const initResult = generate(rundown, {});
expect(initResult.entries['1']).toMatchObject({
gap: 0,
delay: 100,
});
expect(initResult.entries['2']).toMatchObject({
gap: 200,
delay: 300, // first delay was fully absorbed
});
expect(initResult.totalDelay).toBe(300);
expect(initResult.totalDuration).toBe(400);
});
it('handles negative delays on gaps', () => {
const rundown = makeRundown({
order: ['delay1', '1', 'delay2', '2'],
entries: {
delay1: makeOntimeDelay({ id: 'delay', duration: -100 }),
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
delay2: makeOntimeDelay({ id: 'delay', duration: -300 }),
'2': makeOntimeEvent({ id: '2', timeStart: 300, timeEnd: 400, duration: 100 }),
},
});
const initResult = generate(rundown, {});
expect(initResult.entries['1']).toMatchObject({
gap: 0,
delay: -100,
});
expect(initResult.entries['2']).toMatchObject({
gap: 200,
delay: -400,
});
expect(initResult.totalDelay).toBe(-400);
expect(initResult.totalDuration).toBe(400);
});
it('handles negative delays', () => {
const rundown = makeRundown({
order: ['1', 'delay', '2', 'block', '3', 'another-block', '4'],
@@ -144,6 +144,7 @@ export type ProcessedRundownMetadata = RundownMetadata & {
order: EntryId[];
previousEvent: PlayableEvent | null; // The playableEvent from the previous iteration
latestEvent: PlayableEvent | null; // The playableEvent most forwards in time processed so far
previousEntry: OntimeEntry | null; // The entry processed in the previous iteration
};
export function makeRundownMetadata(customFields: CustomFields, customFieldChangelog: Record<string, string>) {
@@ -163,6 +164,7 @@ export function makeRundownMetadata(customFields: CustomFields, customFieldChang
order: [],
previousEvent: null,
latestEvent: null,
previousEntry: null,
};
function process<T extends OntimeEntry>(
@@ -252,8 +254,16 @@ function processEntry<T extends OntimeEntry>(
// remove eventual gaps from the accumulated delay
// we only affect positive delays (time forwards)
if (processedData.totalDelay > 0 && currentEntry.gap > 0) {
let correctedDelay = 0;
// we need to separate the delay that is accumulated from one that may exist after the gap
if (isOntimeDelay(processedData.previousEntry)) {
correctedDelay = processedData.previousEntry.duration;
processedData.totalDelay -= correctedDelay;
}
processedData.totalDelay = Math.max(processedData.totalDelay - currentEntry.gap, 0);
processedData.totalDelay += correctedDelay;
}
// current event delay is the current accumulated delay
currentEntry.delay = processedData.totalDelay;
@@ -275,6 +285,7 @@ function processEntry<T extends OntimeEntry>(
processedData.order.push(currentEntry.id);
}
processedData.entries[currentEntry.id] = currentEntry;
processedData.previousEntry = currentEntry;
return { processedData, processedEntry: currentEntry };
}