mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-07 00:13:53 +00:00
Time to end (#804)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { dayInMs } from 'ontime-utils';
|
||||
import { OntimeEvent, TimerType } from 'ontime-types';
|
||||
import { EndAction, OntimeEvent, Playback, TimeStrategy, TimerType } from 'ontime-types';
|
||||
|
||||
import {
|
||||
getCurrent,
|
||||
@@ -205,6 +205,10 @@ describe('getExpectedFinish()', () => {
|
||||
_timer: {
|
||||
pausedAt: null,
|
||||
},
|
||||
runtime: {
|
||||
actualStart: 79200000,
|
||||
plannedEnd: 600000,
|
||||
},
|
||||
} as RuntimeState;
|
||||
|
||||
const calculatedFinish = getExpectedFinish(state);
|
||||
@@ -356,6 +360,9 @@ describe('getCurrent()', () => {
|
||||
startedAt: null,
|
||||
finishedAt: null,
|
||||
},
|
||||
runtime: {
|
||||
plannedEnd: null,
|
||||
},
|
||||
_timer: {
|
||||
pausedAt: null,
|
||||
},
|
||||
@@ -378,6 +385,9 @@ describe('getCurrent()', () => {
|
||||
startedAt: 10,
|
||||
finishedAt: null,
|
||||
},
|
||||
runtime: {
|
||||
plannedEnd: 100,
|
||||
},
|
||||
_timer: {
|
||||
pausedAt: null,
|
||||
},
|
||||
@@ -386,6 +396,7 @@ describe('getCurrent()', () => {
|
||||
const current = getCurrent(state);
|
||||
expect(current).toBe(70);
|
||||
});
|
||||
|
||||
it('current time is the time to end + added time', () => {
|
||||
const state = {
|
||||
eventNow: {
|
||||
@@ -399,6 +410,9 @@ describe('getCurrent()', () => {
|
||||
startedAt: 10,
|
||||
finishedAt: null,
|
||||
},
|
||||
runtime: {
|
||||
plannedEnd: 100,
|
||||
},
|
||||
_timer: {
|
||||
pausedAt: null,
|
||||
},
|
||||
@@ -407,9 +421,40 @@ describe('getCurrent()', () => {
|
||||
const current = getCurrent(state);
|
||||
expect(current).toBe(77);
|
||||
});
|
||||
|
||||
it('handles events that start the day after', () => {
|
||||
const state = {
|
||||
eventNow: {
|
||||
timeStart: 60000, // 00:01:00
|
||||
timeEnd: 600000, // 00:10:00
|
||||
timerType: TimerType.TimeToEnd,
|
||||
},
|
||||
clock: 79500000, // 22:05:00
|
||||
timer: {
|
||||
addedTime: 0,
|
||||
duration: Infinity, // not relevant,
|
||||
startedAt: 79200000, // 22:00:00
|
||||
finishedAt: null,
|
||||
},
|
||||
runtime: {
|
||||
plannedStart: 60000, // 00:01:00
|
||||
plannedEnd: 79200000, // 22:00:00
|
||||
},
|
||||
_timer: {
|
||||
pausedAt: null,
|
||||
},
|
||||
} as RuntimeState;
|
||||
|
||||
const current = getCurrent(state);
|
||||
// day - clock + start time
|
||||
const expectedCurrent = dayInMs - 79500000 + 60000;
|
||||
expect(current).toBe(expectedCurrent);
|
||||
});
|
||||
|
||||
it('handles events that finish the day after', () => {
|
||||
const state = {
|
||||
eventNow: {
|
||||
timeStart: 79200000, // 22:00:00
|
||||
timeEnd: 600000, // 00:10:00
|
||||
timerType: TimerType.TimeToEnd,
|
||||
},
|
||||
@@ -420,26 +465,9 @@ describe('getCurrent()', () => {
|
||||
startedAt: 79200000, // 22:00:00
|
||||
finishedAt: null,
|
||||
},
|
||||
_timer: {
|
||||
pausedAt: null,
|
||||
},
|
||||
} as RuntimeState;
|
||||
|
||||
const current = getCurrent(state);
|
||||
expect(current).toBe(600000 + dayInMs - 79500000);
|
||||
});
|
||||
it('does not update ', () => {
|
||||
const state = {
|
||||
eventNow: {
|
||||
timeEnd: 600000, // 00:10:00
|
||||
timerType: TimerType.TimeToEnd,
|
||||
},
|
||||
clock: 79500000, // 22:05:00
|
||||
timer: {
|
||||
addedTime: 0,
|
||||
duration: Infinity, // not relevant,
|
||||
startedAt: 79200000, // 22:00:00
|
||||
finishedAt: null,
|
||||
runtime: {
|
||||
actualStart: 79200000,
|
||||
plannedEnd: 600000,
|
||||
},
|
||||
_timer: {
|
||||
pausedAt: null,
|
||||
@@ -447,7 +475,7 @@ describe('getCurrent()', () => {
|
||||
} as RuntimeState;
|
||||
|
||||
const current = getCurrent(state);
|
||||
expect(current).toBe(600000 + dayInMs - 79500000);
|
||||
expect(current).toBe(dayInMs - 79500000 + 600000);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1548,4 +1576,108 @@ describe('getRuntimeOffset()', () => {
|
||||
const offset = getRuntimeOffset(state);
|
||||
expect(offset).toBe(79521653 - 81000000);
|
||||
});
|
||||
|
||||
it('handles time-to-end', () => {
|
||||
const state = {
|
||||
clock: 80000000, // 22:13:20
|
||||
eventNow: {
|
||||
id: 'd6a2ce',
|
||||
type: 'event',
|
||||
title: '',
|
||||
timeStart: 77400000, // 21:30:00
|
||||
timeEnd: 81000000, // 22:30:00
|
||||
duration: 3600000, // 01:00:00
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
linkStart: null,
|
||||
endAction: EndAction.None,
|
||||
timerType: TimerType.TimeToEnd,
|
||||
isPublic: true,
|
||||
skip: false,
|
||||
note: '',
|
||||
colour: '',
|
||||
cue: '1',
|
||||
revision: 0,
|
||||
timeWarning: 120000,
|
||||
timeDanger: 60000,
|
||||
custom: {},
|
||||
delay: 0,
|
||||
},
|
||||
runtime: {
|
||||
selectedEventIndex: 0,
|
||||
numEvents: 1,
|
||||
offset: null,
|
||||
plannedStart: 77400000, // 21:30:00
|
||||
plannedEnd: 81000000, // 22:30:00
|
||||
actualStart: 78000000, // 21:40:00
|
||||
expectedEnd: 81600000, // 22:40:00
|
||||
},
|
||||
timer: {
|
||||
addedTime: 0,
|
||||
current: 1600000,
|
||||
duration: 3600000,
|
||||
elapsed: 2000000,
|
||||
expectedFinish: 81600000,
|
||||
finishedAt: null,
|
||||
playback: Playback.Play,
|
||||
secondaryTimer: null,
|
||||
startedAt: 78000000,
|
||||
},
|
||||
_timer: { pausedAt: null, secondaryTarget: null, finishedNow: false },
|
||||
} as RuntimeState;
|
||||
|
||||
const offset = getRuntimeOffset(state);
|
||||
expect(offset).toBe(0);
|
||||
});
|
||||
|
||||
it('handles time-to-end with delays', () => {
|
||||
const state = {
|
||||
clock: 82000000, // 22:46:40
|
||||
eventNow: {
|
||||
id: 'd6a2ce',
|
||||
type: 'event',
|
||||
title: '',
|
||||
timeStart: 77400000, // 21:30:00
|
||||
timeEnd: 81000000, // 22:30:00
|
||||
duration: 3600000, // 01:00:00
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
linkStart: null,
|
||||
endAction: EndAction.None,
|
||||
timerType: TimerType.TimeToEnd,
|
||||
isPublic: true,
|
||||
skip: false,
|
||||
note: '',
|
||||
colour: '',
|
||||
cue: '1',
|
||||
revision: 0,
|
||||
timeWarning: 120000,
|
||||
timeDanger: 60000,
|
||||
custom: {},
|
||||
delay: 0,
|
||||
},
|
||||
runtime: {
|
||||
selectedEventIndex: 0,
|
||||
numEvents: 1,
|
||||
offset: null,
|
||||
plannedStart: 77400000, // 21:30:00
|
||||
plannedEnd: 81000000, // 22:30:00
|
||||
actualStart: 78000000, // 21:40:00
|
||||
expectedEnd: 81600000, // 22:40:00
|
||||
},
|
||||
timer: {
|
||||
addedTime: 0,
|
||||
current: -400000,
|
||||
duration: 3600000,
|
||||
elapsed: 4000000,
|
||||
expectedFinish: 81600000,
|
||||
finishedAt: null,
|
||||
playback: Playback.Play,
|
||||
secondaryTimer: null,
|
||||
startedAt: 78000000,
|
||||
},
|
||||
_timer: { pausedAt: null, secondaryTarget: null, finishedNow: false },
|
||||
} as RuntimeState;
|
||||
|
||||
const offset = getRuntimeOffset(state);
|
||||
expect(offset).toBe(-400000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,16 +53,23 @@ export function getExpectedFinish(state: RuntimeState): MaybeNumber {
|
||||
* @param {RuntimeState} state runtime state
|
||||
* @returns {number} current time for timer
|
||||
*/
|
||||
|
||||
export function getCurrent(state: RuntimeState): number {
|
||||
const { startedAt, duration, addedTime } = state.timer;
|
||||
const { timerType, timeEnd } = state.eventNow;
|
||||
const { timerType, timeStart, timeEnd } = state.eventNow;
|
||||
const { pausedAt } = state._timer;
|
||||
const { clock } = state;
|
||||
|
||||
if (timerType === TimerType.TimeToEnd) {
|
||||
const isNextDay = startedAt > timeEnd;
|
||||
const correctDay = isNextDay ? dayInMs : 0;
|
||||
return timeEnd + addedTime + correctDay - clock;
|
||||
const isEventOverMidnight = timeStart > timeEnd;
|
||||
const hasFinishedRundownForToday = state.runtime.plannedEnd && clock > state.runtime.plannedEnd;
|
||||
|
||||
if (hasFinishedRundownForToday && !isEventOverMidnight) {
|
||||
return dayInMs - clock + state.eventNow.timeStart + addedTime;
|
||||
}
|
||||
|
||||
const correctDay = isEventOverMidnight ? dayInMs : 0;
|
||||
return correctDay - clock + timeEnd + addedTime;
|
||||
}
|
||||
|
||||
if (startedAt === null) {
|
||||
@@ -301,8 +308,9 @@ export function getRuntimeOffset(state: RuntimeState): MaybeNumber {
|
||||
if (state.runtime.actualStart === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { clock } = state;
|
||||
const { timeStart } = state.eventNow;
|
||||
const { timeStart, timerType } = state.eventNow;
|
||||
const { addedTime, current, startedAt } = state.timer;
|
||||
|
||||
// if we havent started, the offset is the difference to the schedule
|
||||
@@ -311,6 +319,11 @@ export function getRuntimeOffset(state: RuntimeState): MaybeNumber {
|
||||
}
|
||||
|
||||
const overtime = Math.min(current, 0);
|
||||
// in time-to-end, offset is overtime
|
||||
if (timerType === TimerType.TimeToEnd) {
|
||||
return overtime;
|
||||
}
|
||||
|
||||
const startOffset = startedAt - timeStart;
|
||||
const pausedTime = state._timer.pausedAt === null ? 0 : clock - state._timer.pausedAt;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user