From 467b59537575707381d62dcc5ee8d16ee2690045 Mon Sep 17 00:00:00 2001 From: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:42:28 +0100 Subject: [PATCH] fix: issue where a end time can be overflowing (#761) --- apps/client/package.json | 2 +- .../composite/EventEditorTimes.tsx | 5 +- .../composite/EventBlockTimers.tsx | 4 +- apps/electron/package.json | 2 +- apps/server/package.json | 2 +- .../src/services/__tests__/rollUtils.test.ts | 70 +++++++++++++++++++ apps/server/src/services/rollUtils.ts | 3 +- package.json | 2 +- .../src/validate-events/validateEvent.test.ts | 11 +++ .../src/validate-events/validateEvent.ts | 6 +- 10 files changed, 94 insertions(+), 13 deletions(-) diff --git a/apps/client/package.json b/apps/client/package.json index 212d522c8..cdfbb1a77 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -1,6 +1,6 @@ { "name": "ontime-ui", - "version": "2.28.12", + "version": "2.28.13", "private": true, "dependencies": { "@chakra-ui/react": "^2.7.0", diff --git a/apps/client/src/features/event-editor/composite/EventEditorTimes.tsx b/apps/client/src/features/event-editor/composite/EventEditorTimes.tsx index fdb612e94..e3e895a14 100644 --- a/apps/client/src/features/event-editor/composite/EventEditorTimes.tsx +++ b/apps/client/src/features/event-editor/composite/EventEditorTimes.tsx @@ -1,7 +1,7 @@ import { memo } from 'react'; import { Select, Switch } from '@chakra-ui/react'; import { EndAction, OntimeEvent, TimerType } from 'ontime-types'; -import { calculateDuration, millisToString } from 'ontime-utils'; +import { calculateDuration, dayInMs, millisToString } from 'ontime-utils'; import TimeInput from '../../../common/components/input/time-input/TimeInput'; import { useEventAction } from '../../../common/hooks/useEventAction'; @@ -28,14 +28,13 @@ const EventEditorTimes = (props: EventEditorTimesProps) => { const { eventId, timeStart, timeEnd, duration, delay, isPublic, endAction, timerType } = props; const { updateEvent } = useEventAction(); - const handleSubmit = (field: TimeActions, value: number | string | boolean) => { const newEventData: Partial = { id: eventId }; switch (field) { case 'durationOverride': { // duration defines timeEnd newEventData.duration = value as number; - newEventData.timeEnd = timeStart + (value as number); + newEventData.timeEnd = timeStart + ((value as number) % dayInMs); break; } case 'timeStart': { diff --git a/apps/client/src/features/rundown/event-block/composite/EventBlockTimers.tsx b/apps/client/src/features/rundown/event-block/composite/EventBlockTimers.tsx index 44d0e06dc..a6d40f17e 100644 --- a/apps/client/src/features/rundown/event-block/composite/EventBlockTimers.tsx +++ b/apps/client/src/features/rundown/event-block/composite/EventBlockTimers.tsx @@ -1,6 +1,6 @@ import { memo } from 'react'; import { OntimeEvent } from 'ontime-types'; -import { calculateDuration, millisToString } from 'ontime-utils'; +import { calculateDuration, dayInMs, millisToString } from 'ontime-utils'; import TimeInput from '../../../../common/components/input/time-input/TimeInput'; import { useEventAction } from '../../../../common/hooks/useEventAction'; @@ -29,7 +29,7 @@ const EventBlockTimers = (props: EventBlockTimerProps) => { case 'durationOverride': { // duration defines timeEnd newEventData.duration = value; - newEventData.timeEnd = timeStart + value; + newEventData.timeEnd = timeStart + ((value as number) % dayInMs); break; } case 'timeStart': { diff --git a/apps/electron/package.json b/apps/electron/package.json index 63d2a17ba..889274863 100644 --- a/apps/electron/package.json +++ b/apps/electron/package.json @@ -1,6 +1,6 @@ { "name": "ontime", - "version": "2.28.12", + "version": "2.28.13", "author": "Carlos Valente", "description": "Time keeping for live events", "repository": "https://github.com/cpvalente/ontime", diff --git a/apps/server/package.json b/apps/server/package.json index 05288d081..2e07f5abc 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -2,7 +2,7 @@ "name": "ontime-server", "type": "module", "main": "src/index.ts", - "version": "2.28.12", + "version": "2.28.13", "exports": "./src/index.js", "dependencies": { "@googleapis/sheets": "^5.0.5", diff --git a/apps/server/src/services/__tests__/rollUtils.test.ts b/apps/server/src/services/__tests__/rollUtils.test.ts index 329ece996..9d3559831 100644 --- a/apps/server/src/services/__tests__/rollUtils.test.ts +++ b/apps/server/src/services/__tests__/rollUtils.test.ts @@ -528,6 +528,76 @@ describe('test that roll behaviour multi day event edge cases', () => { }); }); +// test getRollTimers() on issue #757 +describe('it handles timeEnd over day', () => { + it('ignores events with timeEnd larger than a day', () => { + const testRundown = [ + { + title: 'Setup', + subtitle: '', + presenter: '', + note: 'BMA, Nebelfluid, Shooter, Akkus, UHF11, Getränke, Kaffee, Strom, ELA, Text für Holger', + endAction: 'play-next', + timerType: 'count-down', + timeStart: 66600000, + timeEnd: 68400000, + duration: 1800000, + isPublic: false, + skip: false, + colour: '#2fa9e5', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: 'event', + revision: 0, + cue: 'PRE', + id: 'b2f8d', + }, + { + title: 'Künstliche Intelligenz', + subtitle: ' -> Vorstellung Maske', + presenter: 'Engel und Teufel', + note: 'Melli Kleben! Sofa', + endAction: 'play-next', + timerType: 'count-down', + timeStart: 86100000, + // timeEnd: 1020000, <--- this would have been equivalent + timeEnd: 87420000, + duration: 1320000, + isPublic: true, + skip: false, + colour: '#a8ec31', + user0: 'UHF1 Melli (Korsett)', + user1: 'UHF2 Reinhold (unter Flügel)', + user2: 'UHF3 Oli (Sport-Unterhose Rechts)', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: 'event', + revision: 0, + cue: '16', + id: '8b970', + }, + ]; + + const timeNow = 64488675; // 17:55-something + + const timers = getRollTimers(testRundown as OntimeEvent[], timeNow); + expect(timers.currentEvent).toBeNull(); + }); +}); + // test normaliseEndTime() on issue #58 test('test typical scenarios', () => { const t1 = { diff --git a/apps/server/src/services/rollUtils.ts b/apps/server/src/services/rollUtils.ts index 98a6feac2..99a113084 100644 --- a/apps/server/src/services/rollUtils.ts +++ b/apps/server/src/services/rollUtils.ts @@ -79,7 +79,8 @@ export const getRollTimers = (rundown: OntimeEvent[], timeNow: number) => { const normalEnd = normaliseEndTime(event.timeStart, event.timeEnd); const hasNotEnded = normalEnd > timeNow; - const isFromDayBefore = normalEnd > dayInMs && timeNow < event.timeEnd; + // TODO: we will likely want a better solution than the modulus here + const isFromDayBefore = normalEnd > dayInMs && timeNow < event.timeEnd % dayInMs; const hasStarted = isFromDayBefore || timeNow >= event.timeStart; if (normalEnd <= timeNow) { diff --git a/package.json b/package.json index ac2464b50..3873a7458 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ontime", - "version": "2.28.12", + "version": "2.28.13", "description": "Time keeping for live events", "keywords": [ "lightdev", diff --git a/packages/utils/src/validate-events/validateEvent.test.ts b/packages/utils/src/validate-events/validateEvent.test.ts index 76eca2c99..89374184c 100644 --- a/packages/utils/src/validate-events/validateEvent.test.ts +++ b/packages/utils/src/validate-events/validateEvent.test.ts @@ -93,6 +93,17 @@ describe('validateTimes()', () => { expect(timeEnd).toBe(10); expect(duration).toBe(10); }); + + it('ensures values dont overflow dayMs', () => { + const start = 86100000; + const endOverDay = 87420000; + const durationNormal = 1320000; + + const { timeStart, timeEnd, duration } = validateTimes(start, endOverDay, durationNormal); + expect(timeStart).toBe(start); + expect(timeEnd).toBe(1020000); + expect(duration).toBe(durationNormal); + }); }); describe('calculateDuration()', () => { diff --git a/packages/utils/src/validate-events/validateEvent.ts b/packages/utils/src/validate-events/validateEvent.ts index 0f07edc66..75827affa 100644 --- a/packages/utils/src/validate-events/validateEvent.ts +++ b/packages/utils/src/validate-events/validateEvent.ts @@ -52,9 +52,9 @@ function convertToInteger(value: unknown): number { * @param _duration */ export function validateTimes(_start?: unknown, _end?: unknown, _duration?: unknown) { - const timeStart = convertToInteger(_start); - const timeEnd = convertToInteger(_end); - const duration = convertToInteger(_duration); + const timeStart = convertToInteger(_start) % dayInMs; + const timeEnd = convertToInteger(_end) % dayInMs; + const duration = convertToInteger(_duration) % dayInMs; if (_start != null && _end != null) { // Case 1. if we have start and end, duration must be derived