fix v2 roll timer (#363)

* fix: roll update skips elapsed time

* refactor: remove unused data

* style: fix style in roll state
This commit is contained in:
Carlos Valente
2023-04-26 22:02:04 +02:00
committed by GitHub
parent 40d389acc9
commit 4bceae65ab
7 changed files with 24 additions and 106 deletions
@@ -1,10 +1,11 @@
import { ReactNode, useMemo } from 'react'; import { ReactNode, useMemo } from 'react';
import { Playback, TitleBlock } from 'ontime-types'; import { Playback, TitleBlock } from 'ontime-types';
import { useStore } from 'zustand';
import useEventData from '../../common/hooks-query/useEventData'; import useEventData from '../../common/hooks-query/useEventData';
import useRundown from '../../common/hooks-query/useRundown'; import useRundown from '../../common/hooks-query/useRundown';
import useViewSettings from '../../common/hooks-query/useViewSettings'; import useViewSettings from '../../common/hooks-query/useViewSettings';
import { useRuntimeStore } from '../../common/stores/runtime'; import { runtime } from '../../common/stores/runtime';
import { useViewOptionsStore } from '../../common/stores/viewOptions'; import { useViewOptionsStore } from '../../common/stores/viewOptions';
export type TitleManager = TitleBlock & { showNow: boolean; showNext: boolean }; export type TitleManager = TitleBlock & { showNow: boolean; showNext: boolean };
@@ -27,7 +28,7 @@ const withData = (Component: ReactNode) => {
}, [eventsData]); }, [eventsData]);
// websocket data // websocket data
const data = useRuntimeStore(); const data = useStore(runtime);
const { timer, titles, titlesPublic, publicMessage, timerMessage, lowerMessage, playback, onAir } = data; const { timer, titles, titlesPublic, publicMessage, timerMessage, lowerMessage, playback, onAir } = data;
const publicSelectedId = data.loaded.selectedPublicEventId; const publicSelectedId = data.loaded.selectedPublicEventId;
const selectedId = data.loaded.selectedEventId; const selectedId = data.loaded.selectedEventId;
@@ -90,7 +90,7 @@ export default function Countdown(props: CountdownProps) {
return null; return null;
} }
const standby = time.playback !== Playback.Play && selectedId === follow?.id; const standby = time.playback !== Playback.Play && time.playback !== Playback.Roll && selectedId === follow?.id;
const isRunningFinished = time.finished && runningMessage === TimerMessage.running; const isRunningFinished = time.finished && runningMessage === TimerMessage.running;
const isSelected = runningMessage === TimerMessage.running; const isSelected = runningMessage === TimerMessage.running;
const delayedTimerStyles = delay > 0 ? 'aux-timers__value--delayed' : ''; const delayedTimerStyles = delay > 0 ? 'aux-timers__value--delayed' : '';
@@ -152,8 +152,10 @@ export class EventLoader {
return null; return null;
} }
const { nowIndex, timers, timeToNext, nextEvent, nextPublicEvent, currentEvent, currentPublicEvent } = const { nowIndex, timeToNext, nextEvent, nextPublicEvent, currentEvent, currentPublicEvent } = getRollTimers(
getRollTimers(timedEvents, timeNow); timedEvents,
timeNow,
);
this.loadedEvent = currentEvent; this.loadedEvent = currentEvent;
this.loaded.selectedEventIndex = nowIndex; this.loaded.selectedEventIndex = nowIndex;
@@ -166,7 +168,7 @@ export class EventLoader {
this._loadThisTitles(nextEvent, 'next-private'); this._loadThisTitles(nextEvent, 'next-private');
this._loadThisTitles(nextPublicEvent, 'next-public'); this._loadThisTitles(nextPublicEvent, 'next-public');
return { currentEvent, nextEvent, timeToNext, timers }; return { currentEvent, nextEvent, timeToNext };
} }
/** /**
+2 -2
View File
@@ -197,14 +197,14 @@ export class PlaybackService {
return; return;
} }
const { currentEvent, nextEvent, timers } = rollTimers; const { currentEvent, nextEvent } = rollTimers;
if (!currentEvent && !nextEvent) { if (!currentEvent && !nextEvent) {
logger.warning('SERVER', 'Roll: no events found'); logger.warning('SERVER', 'Roll: no events found');
PlaybackService.stop(); PlaybackService.stop();
return; return;
} }
eventTimer.roll(currentEvent, nextEvent, timers); eventTimer.roll(currentEvent, nextEvent);
const newState = eventTimer.playback; const newState = eventTimer.playback;
logger.info('PLAYBACK', `Play Mode ${newState.toUpperCase()}`); logger.info('PLAYBACK', `Play Mode ${newState.toUpperCase()}`);
+6 -17
View File
@@ -8,16 +8,6 @@ import { integrationService } from './integration-service/IntegrationService.js'
import { getCurrent, getElapsed, getExpectedFinish } from './timerUtils.js'; import { getCurrent, getElapsed, getExpectedFinish } from './timerUtils.js';
import { clock } from './Clock.js'; import { clock } from './Clock.js';
/**
* Aux type
*/
type Timer = {
_startedAt: number;
_finishAt: number;
duration: number;
current: number;
};
export class TimerService { export class TimerService {
private readonly _interval: NodeJS.Timer; private readonly _interval: NodeJS.Timer;
@@ -274,6 +264,7 @@ export class TimerService {
this.timer.current = updatedTimer; this.timer.current = updatedTimer;
this.timer.secondaryTimer = updatedSecondaryTimer; this.timer.secondaryTimer = updatedSecondaryTimer;
this.timer.elapsed = getElapsed(this.timer.startedAt, this.timer.clock);
if (isFinished) { if (isFinished) {
this.timer.selectedEventId = null; this.timer.selectedEventId = null;
@@ -344,9 +335,8 @@ export class TimerService {
* Loads roll information into timer service * Loads roll information into timer service
* @param {OntimeEvent | null} currentEvent -- both current event and next event cant be null * @param {OntimeEvent | null} currentEvent -- both current event and next event cant be null
* @param {OntimeEvent | null} nextEvent -- both current event and next event cant be null * @param {OntimeEvent | null} nextEvent -- both current event and next event cant be null
* @param {Timer} timers
*/ */
roll(currentEvent: OntimeEvent | null, nextEvent: OntimeEvent | null, timers: Timer) { roll(currentEvent: OntimeEvent | null, nextEvent: OntimeEvent | null) {
this._clear(); this._clear();
this.timer.clock = clock.timeNow(); this.timer.clock = clock.timeNow();
@@ -355,11 +345,11 @@ export class TimerService {
this.timer.secondaryTimer = null; this.timer.secondaryTimer = null;
this.secondaryTarget = null; this.secondaryTarget = null;
this.loadedTimerId = currentEvent.id; // when we load a timer in roll, we do the same things as before
// but also pre-populate some data as to the running state
this.load(currentEvent);
this.timer.startedAt = currentEvent.timeStart; this.timer.startedAt = currentEvent.timeStart;
this.timer.expectedFinish = currentEvent.timeEnd; this.timer.expectedFinish = currentEvent.timeEnd;
this.timer.duration = timers.duration;
this.timer.current = timers.current;
} else if (nextEvent) { } else if (nextEvent) {
// account for day after // account for day after
const nextStart = nextEvent.timeStart < this.timer.clock ? nextEvent.timeStart + DAY_TO_MS : nextEvent.timeStart; const nextStart = nextEvent.timeStart < this.timer.clock ? nextEvent.timeStart + DAY_TO_MS : nextEvent.timeStart;
@@ -367,14 +357,13 @@ export class TimerService {
this.timer.secondaryTimer = nextStart - this.timer.clock; this.timer.secondaryTimer = nextStart - this.timer.clock;
this.secondaryTarget = nextStart; this.secondaryTarget = nextStart;
} }
this.playback = Playback.Roll; this.playback = Playback.Roll;
this._onRoll(); this._onRoll();
this.update(); this.update();
} }
_onRoll() { _onRoll() {
this._onLoad(); eventStore.set('playback', this.playback);
} }
shutdown() { shutdown() {
@@ -1,4 +1,10 @@
import { DAY_TO_MS, getRollTimers, normaliseEndTime, sortArrayByProperty, updateRoll } from '../rollUtils.ts'; import {
DAY_TO_MS,
getRollTimers,
normaliseEndTime,
sortArrayByProperty,
updateRoll,
} from '../rollUtils.ts';
// test sortArrayByProperty() // test sortArrayByProperty()
describe('sort simple arrays of objects', () => { describe('sort simple arrays of objects', () => {
@@ -96,7 +102,6 @@ describe('test that roll loads selection in right order', () => {
publicIndex: null, publicIndex: null,
nextIndex: 0, nextIndex: 0,
publicNextIndex: 4, publicNextIndex: 4,
timers: null,
timeToNext: 5, timeToNext: 5,
nextEvent: eventlist[0], nextEvent: eventlist[0],
nextPublicEvent: eventlist[4], nextPublicEvent: eventlist[4],
@@ -116,12 +121,6 @@ describe('test that roll loads selection in right order', () => {
publicIndex: null, publicIndex: null,
nextIndex: 1, nextIndex: 1,
publicNextIndex: 4, publicNextIndex: 4,
timers: {
_startedAt: eventlist[0].timeStart,
_finishAt: eventlist[0].timeEnd,
current: 5,
duration: eventlist[0].timeEnd - eventlist[0].timeStart,
},
timeToNext: 5, timeToNext: 5,
nextEvent: eventlist[1], nextEvent: eventlist[1],
nextPublicEvent: eventlist[4], nextPublicEvent: eventlist[4],
@@ -141,12 +140,6 @@ describe('test that roll loads selection in right order', () => {
publicIndex: null, publicIndex: null,
nextIndex: 2, nextIndex: 2,
publicNextIndex: 4, publicNextIndex: 4,
timers: {
_startedAt: eventlist[1].timeStart,
_finishAt: eventlist[1].timeEnd,
current: 5,
duration: eventlist[1].timeEnd - eventlist[1].timeStart,
},
timeToNext: 5, timeToNext: 5,
nextEvent: eventlist[2], nextEvent: eventlist[2],
nextPublicEvent: eventlist[4], nextPublicEvent: eventlist[4],
@@ -166,12 +159,6 @@ describe('test that roll loads selection in right order', () => {
publicIndex: null, publicIndex: null,
nextIndex: 3, nextIndex: 3,
publicNextIndex: 4, publicNextIndex: 4,
timers: {
_startedAt: eventlist[2].timeStart,
_finishAt: eventlist[2].timeEnd,
current: 10,
duration: eventlist[2].timeEnd - eventlist[2].timeStart,
},
timeToNext: 10, timeToNext: 10,
nextEvent: eventlist[3], nextEvent: eventlist[3],
nextPublicEvent: eventlist[4], nextPublicEvent: eventlist[4],
@@ -191,12 +178,6 @@ describe('test that roll loads selection in right order', () => {
publicIndex: 4, publicIndex: 4,
nextIndex: 5, nextIndex: 5,
publicNextIndex: 6, publicNextIndex: 6,
timers: {
_startedAt: eventlist[4].timeStart,
_finishAt: eventlist[4].timeEnd,
current: 1,
duration: eventlist[4].timeEnd - eventlist[4].timeStart,
},
timeToNext: 1, timeToNext: 1,
nextEvent: eventlist[5], nextEvent: eventlist[5],
nextPublicEvent: eventlist[6], nextPublicEvent: eventlist[6],
@@ -216,12 +197,6 @@ describe('test that roll loads selection in right order', () => {
publicIndex: 6, publicIndex: 6,
nextIndex: 7, nextIndex: 7,
publicNextIndex: null, publicNextIndex: null,
timers: {
_startedAt: eventlist[6].timeStart,
_finishAt: eventlist[6].timeEnd,
current: 7,
duration: eventlist[6].timeEnd - eventlist[6].timeStart,
},
timeToNext: 7, timeToNext: 7,
nextEvent: eventlist[7], nextEvent: eventlist[7],
nextPublicEvent: null, nextPublicEvent: null,
@@ -241,12 +216,6 @@ describe('test that roll loads selection in right order', () => {
publicIndex: 6, publicIndex: 6,
nextIndex: null, nextIndex: null,
publicNextIndex: null, publicNextIndex: null,
timers: {
_startedAt: eventlist[7].timeStart,
_finishAt: eventlist[7].timeEnd,
current: 5,
duration: eventlist[7].timeEnd - eventlist[7].timeStart,
},
timeToNext: null, timeToNext: null,
nextEvent: null, nextEvent: null,
nextPublicEvent: null, nextPublicEvent: null,
@@ -266,7 +235,6 @@ describe('test that roll loads selection in right order', () => {
publicIndex: null, publicIndex: null,
nextIndex: 0, nextIndex: 0,
publicNextIndex: 4, publicNextIndex: 4,
timers: null,
timeToNext: DAY_TO_MS - now + eventlist[0].timeStart, timeToNext: DAY_TO_MS - now + eventlist[0].timeStart,
nextEvent: eventlist[0], nextEvent: eventlist[0],
nextPublicEvent: eventlist[4], nextPublicEvent: eventlist[4],
@@ -294,7 +262,6 @@ describe('test that roll loads selection in right order', () => {
publicIndex: null, publicIndex: null,
nextIndex: 0, nextIndex: 0,
publicNextIndex: 0, publicNextIndex: 0,
timers: null,
timeToNext: DAY_TO_MS - now + singleEventList[0].timeStart, timeToNext: DAY_TO_MS - now + singleEventList[0].timeStart,
nextEvent: singleEventList[0], nextEvent: singleEventList[0],
nextPublicEvent: singleEventList[0], nextPublicEvent: singleEventList[0],
@@ -337,7 +304,6 @@ describe('test that roll behaviour with overlapping times', () => {
publicIndex: null, publicIndex: null,
nextIndex: 0, nextIndex: 0,
publicNextIndex: 1, publicNextIndex: 1,
timers: null,
timeToNext: 10, timeToNext: 10,
nextEvent: eventlist[0], nextEvent: eventlist[0],
nextPublicEvent: eventlist[1], nextPublicEvent: eventlist[1],
@@ -357,12 +323,6 @@ describe('test that roll behaviour with overlapping times', () => {
publicIndex: 1, publicIndex: 1,
nextIndex: 2, nextIndex: 2,
publicNextIndex: null, publicNextIndex: null,
timers: {
_startedAt: eventlist[1].timeStart,
_finishAt: eventlist[1].timeEnd,
current: 10,
duration: eventlist[1].timeEnd - eventlist[1].timeStart,
},
timeToNext: 0, timeToNext: 0,
nextEvent: eventlist[2], nextEvent: eventlist[2],
nextPublicEvent: null, nextPublicEvent: null,
@@ -382,12 +342,6 @@ describe('test that roll behaviour with overlapping times', () => {
publicIndex: 1, publicIndex: 1,
nextIndex: 2, nextIndex: 2,
publicNextIndex: null, publicNextIndex: null,
timers: {
_startedAt: eventlist[1].timeStart,
_finishAt: eventlist[1].timeEnd,
current: 5,
duration: eventlist[1].timeEnd - eventlist[1].timeStart,
},
timeToNext: -5, timeToNext: -5,
nextEvent: eventlist[2], nextEvent: eventlist[2],
nextPublicEvent: null, nextPublicEvent: null,
@@ -407,12 +361,6 @@ describe('test that roll behaviour with overlapping times', () => {
publicIndex: 1, publicIndex: 1,
nextIndex: null, nextIndex: null,
publicNextIndex: null, publicNextIndex: null,
timers: {
_startedAt: eventlist[2].timeStart,
_finishAt: eventlist[2].timeEnd,
current: 10,
duration: eventlist[2].timeEnd - eventlist[2].timeStart,
},
timeToNext: null, timeToNext: null,
nextEvent: null, nextEvent: null,
nextPublicEvent: null, nextPublicEvent: null,
@@ -432,12 +380,6 @@ describe('test that roll behaviour with overlapping times', () => {
publicIndex: 1, publicIndex: 1,
nextIndex: null, nextIndex: null,
publicNextIndex: null, publicNextIndex: null,
timers: {
_startedAt: eventlist[2].timeStart,
_finishAt: eventlist[2].timeEnd,
current: 5,
duration: eventlist[2].timeEnd - eventlist[2].timeStart,
},
timeToNext: null, timeToNext: null,
nextEvent: null, nextEvent: null,
nextPublicEvent: null, nextPublicEvent: null,
@@ -468,12 +410,6 @@ describe('test that roll behaviour multi day event edge cases', () => {
publicIndex: null, publicIndex: null,
nextIndex: null, nextIndex: null,
publicNextIndex: null, publicNextIndex: null,
timers: {
_startedAt: eventlist[0].timeStart,
_finishAt: eventlist[0].timeEnd,
current: eventlist[0].timeEnd + DAY_TO_MS - now,
duration: DAY_TO_MS - eventlist[0].timeStart + eventlist[0].timeEnd,
},
timeToNext: null, timeToNext: null,
nextEvent: null, nextEvent: null,
nextPublicEvent: null, nextPublicEvent: null,
@@ -501,7 +437,6 @@ describe('test that roll behaviour multi day event edge cases', () => {
publicIndex: null, publicIndex: null,
nextIndex: 0, nextIndex: 0,
publicNextIndex: null, publicNextIndex: null,
timers: null,
timeToNext: eventlist[0].timeStart - now, timeToNext: eventlist[0].timeStart - now,
nextEvent: eventlist[0], nextEvent: eventlist[0],
nextPublicEvent: null, nextPublicEvent: null,
-9
View File
@@ -44,7 +44,6 @@ export const getRollTimers = (rundown: OntimeEvent[], timeNow: number) => {
let publicNextIndex: number | null = null; // index of next public event let publicNextIndex: number | null = null; // index of next public event
let timeToNext: number | null = null; // counter: time for next event let timeToNext: number | null = null; // counter: time for next event
let publicTimeToNext: number | null = null; // counter: time for next public event let publicTimeToNext: number | null = null; // counter: time for next public event
let timers: Timer | null = null;
const orderedEvents = sortArrayByProperty(rundown, 'timeStart'); const orderedEvents = sortArrayByProperty(rundown, 'timeStart');
const lastEvent = orderedEvents[orderedEvents.length - 1]; const lastEvent = orderedEvents[orderedEvents.length - 1];
@@ -104,13 +103,6 @@ export const getRollTimers = (rundown: OntimeEvent[], timeNow: number) => {
currentEvent = event; currentEvent = event;
nowIndex = rundown.findIndex((rundownEvent) => rundownEvent.id === event.id); nowIndex = rundown.findIndex((rundownEvent) => rundownEvent.id === event.id);
nowId = event.id; nowId = event.id;
timers = {
_startedAt: event.timeStart,
_finishAt: event.timeEnd,
duration: normalEnd - event.timeStart,
current: normalEnd - timeNow,
};
nowFound = true; nowFound = true;
// it could also be public // it could also be public
@@ -156,7 +148,6 @@ export const getRollTimers = (rundown: OntimeEvent[], timeNow: number) => {
publicIndex, publicIndex,
nextIndex, nextIndex,
publicNextIndex, publicNextIndex,
timers,
timeToNext, timeToNext,
nextEvent, nextEvent,
nextPublicEvent, nextPublicEvent,