mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-08 08:53:51 +00:00
fix: roll loads events that cross midnight
This commit is contained in:
committed by
Carlos Valente
parent
358ad79ae4
commit
155cf48a17
@@ -709,6 +709,44 @@ describe('loadRoll() test that roll behaviour multi day event edge cases', () =>
|
||||
expect(state).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it('should recognise a playing event where its schedule spans over midnight, even with previous events', async () => {
|
||||
vi.useFakeTimers();
|
||||
await initRundown(
|
||||
makeRundown({
|
||||
order: ['1', '2'],
|
||||
entries: {
|
||||
'1': {
|
||||
...mockEvent,
|
||||
id: '1',
|
||||
timeStart: 10 * MILLIS_PER_HOUR,
|
||||
timeEnd: 11 * MILLIS_PER_HOUR,
|
||||
duration: 1 * MILLIS_PER_HOUR,
|
||||
},
|
||||
'2': {
|
||||
...mockEvent,
|
||||
id: '2',
|
||||
timeStart: 11 * MILLIS_PER_HOUR,
|
||||
timeEnd: 2 * MILLIS_PER_HOUR,
|
||||
duration: 14 * MILLIS_PER_HOUR
|
||||
},
|
||||
},
|
||||
}),
|
||||
{},
|
||||
);
|
||||
vi.runAllTimers();
|
||||
vi.useRealTimers();
|
||||
|
||||
const { rundown, metadata } = rundownCache.get();
|
||||
const now = 1 * MILLIS_PER_HOUR;
|
||||
const expected = {
|
||||
event: rundown.entries['2'],
|
||||
index: 1,
|
||||
};
|
||||
|
||||
const state = loadRoll(rundown, metadata, now);
|
||||
expect(state).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it('if the start time is the day after end time, and both are later than now', async () => {
|
||||
vi.useFakeTimers();
|
||||
await initRundown(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { dayInMs } from 'ontime-utils';
|
||||
import { checkIsNow, dayInMs } from 'ontime-utils';
|
||||
import { MaybeNumber, PlayableEvent, Rundown } from 'ontime-types';
|
||||
|
||||
import { normaliseEndTime } from './timerUtils.js';
|
||||
@@ -36,11 +36,6 @@ export function loadRoll(
|
||||
continue;
|
||||
}
|
||||
|
||||
// we check if event crosses midnight
|
||||
if (event.timeStart > event.timeEnd) {
|
||||
daySpan++;
|
||||
}
|
||||
|
||||
const correctedDays = dayInMs * daySpan;
|
||||
const correctedStart = event.timeStart + correctedDays;
|
||||
const correctedEnd = event.timeEnd + correctedDays;
|
||||
@@ -49,13 +44,18 @@ export function loadRoll(
|
||||
* there are 3 possible states for an event
|
||||
* 1. event is already finished
|
||||
* 2. event is running
|
||||
* 3. event is in the future
|
||||
* 3. event is running (midnight edge case)
|
||||
* 4. event is in the future
|
||||
*/
|
||||
|
||||
// 1. event is already finished
|
||||
// when does the event end (handle midnight)
|
||||
const normalEnd = normaliseEndTime(correctedStart, correctedEnd);
|
||||
if (normalEnd <= timeNow) {
|
||||
// keep track of day progress
|
||||
if (event.timeStart > event.timeEnd) {
|
||||
daySpan++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -66,8 +66,25 @@ export function loadRoll(
|
||||
return { event, index: getTimedIndexFromPlayableIndex(metadata, i) };
|
||||
}
|
||||
|
||||
// 3. event will run in the future
|
||||
// we set the isPending flag to indicate that the event is currently playing
|
||||
// 3. check if an overnight event that comes later is currently playing
|
||||
for (let j = i + 1; j < metadata.playableEventOrder.length; j++) {
|
||||
const futureEventId = metadata.playableEventOrder[j];
|
||||
if (!futureEventId) continue;
|
||||
|
||||
const futureEvent = rundown.entries[futureEventId] as PlayableEvent;
|
||||
if (!futureEvent || futureEvent.duration === 0) continue;
|
||||
|
||||
const crossesMidnight = futureEvent.timeStart > futureEvent.timeEnd;
|
||||
if (!crossesMidnight) continue;
|
||||
|
||||
// check if timeNow is inside this overnight event
|
||||
const isRunning = checkIsNow(futureEvent.timeStart, futureEvent.timeEnd, timeNow);
|
||||
if (isRunning) {
|
||||
return { event: futureEvent, index: getTimedIndexFromPlayableIndex(metadata, j) };
|
||||
}
|
||||
}
|
||||
|
||||
// 4. event will run in the future
|
||||
return { event, index: getTimedIndexFromPlayableIndex(metadata, i), isPending: true };
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,18 @@ describe('checkIsNow()', () => {
|
||||
});
|
||||
|
||||
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);
|
||||
const timeStart = 22 * MILLIS_PER_HOUR;
|
||||
const timeEnd = 8 * MILLIS_PER_HOUR;
|
||||
const now = 23 * MILLIS_PER_HOUR;
|
||||
|
||||
expect(checkIsNow(timeStart, timeEnd, now)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true accounting for events that roll over midnight (2)', () => {
|
||||
const timeStart = 22 * MILLIS_PER_HOUR;
|
||||
const timeEnd = 8 * MILLIS_PER_HOUR;
|
||||
const now = 1 * MILLIS_PER_HOUR;
|
||||
|
||||
expect(checkIsNow(timeStart, timeEnd, now)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
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;
|
||||
if (timeEnd < timeStart) {
|
||||
// overnight event: clock is either after start OR before end
|
||||
return clock >= timeStart || clock <= timeEnd;
|
||||
}
|
||||
return timeStart <= clock && clock <= timeEnd;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user