mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-25 08:59:13 +00:00
fix: issue where a end time can be overflowing (#761)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ontime-ui",
|
"name": "ontime-ui",
|
||||||
"version": "2.28.12",
|
"version": "2.28.13",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^2.7.0",
|
"@chakra-ui/react": "^2.7.0",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { Select, Switch } from '@chakra-ui/react';
|
import { Select, Switch } from '@chakra-ui/react';
|
||||||
import { EndAction, OntimeEvent, TimerType } from 'ontime-types';
|
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 TimeInput from '../../../common/components/input/time-input/TimeInput';
|
||||||
import { useEventAction } from '../../../common/hooks/useEventAction';
|
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 { eventId, timeStart, timeEnd, duration, delay, isPublic, endAction, timerType } = props;
|
||||||
const { updateEvent } = useEventAction();
|
const { updateEvent } = useEventAction();
|
||||||
|
|
||||||
|
|
||||||
const handleSubmit = (field: TimeActions, value: number | string | boolean) => {
|
const handleSubmit = (field: TimeActions, value: number | string | boolean) => {
|
||||||
const newEventData: Partial<OntimeEvent> = { id: eventId };
|
const newEventData: Partial<OntimeEvent> = { id: eventId };
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case 'durationOverride': {
|
case 'durationOverride': {
|
||||||
// duration defines timeEnd
|
// duration defines timeEnd
|
||||||
newEventData.duration = value as number;
|
newEventData.duration = value as number;
|
||||||
newEventData.timeEnd = timeStart + (value as number);
|
newEventData.timeEnd = timeStart + ((value as number) % dayInMs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'timeStart': {
|
case 'timeStart': {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { OntimeEvent } from 'ontime-types';
|
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 TimeInput from '../../../../common/components/input/time-input/TimeInput';
|
||||||
import { useEventAction } from '../../../../common/hooks/useEventAction';
|
import { useEventAction } from '../../../../common/hooks/useEventAction';
|
||||||
@@ -29,7 +29,7 @@ const EventBlockTimers = (props: EventBlockTimerProps) => {
|
|||||||
case 'durationOverride': {
|
case 'durationOverride': {
|
||||||
// duration defines timeEnd
|
// duration defines timeEnd
|
||||||
newEventData.duration = value;
|
newEventData.duration = value;
|
||||||
newEventData.timeEnd = timeStart + value;
|
newEventData.timeEnd = timeStart + ((value as number) % dayInMs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'timeStart': {
|
case 'timeStart': {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ontime",
|
"name": "ontime",
|
||||||
"version": "2.28.12",
|
"version": "2.28.13",
|
||||||
"author": "Carlos Valente",
|
"author": "Carlos Valente",
|
||||||
"description": "Time keeping for live events",
|
"description": "Time keeping for live events",
|
||||||
"repository": "https://github.com/cpvalente/ontime",
|
"repository": "https://github.com/cpvalente/ontime",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "ontime-server",
|
"name": "ontime-server",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"version": "2.28.12",
|
"version": "2.28.13",
|
||||||
"exports": "./src/index.js",
|
"exports": "./src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@googleapis/sheets": "^5.0.5",
|
"@googleapis/sheets": "^5.0.5",
|
||||||
|
|||||||
@@ -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 normaliseEndTime() on issue #58
|
||||||
test('test typical scenarios', () => {
|
test('test typical scenarios', () => {
|
||||||
const t1 = {
|
const t1 = {
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ export const getRollTimers = (rundown: OntimeEvent[], timeNow: number) => {
|
|||||||
const normalEnd = normaliseEndTime(event.timeStart, event.timeEnd);
|
const normalEnd = normaliseEndTime(event.timeStart, event.timeEnd);
|
||||||
|
|
||||||
const hasNotEnded = normalEnd > timeNow;
|
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;
|
const hasStarted = isFromDayBefore || timeNow >= event.timeStart;
|
||||||
|
|
||||||
if (normalEnd <= timeNow) {
|
if (normalEnd <= timeNow) {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ontime",
|
"name": "ontime",
|
||||||
"version": "2.28.12",
|
"version": "2.28.13",
|
||||||
"description": "Time keeping for live events",
|
"description": "Time keeping for live events",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"lightdev",
|
"lightdev",
|
||||||
|
|||||||
@@ -93,6 +93,17 @@ describe('validateTimes()', () => {
|
|||||||
expect(timeEnd).toBe(10);
|
expect(timeEnd).toBe(10);
|
||||||
expect(duration).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()', () => {
|
describe('calculateDuration()', () => {
|
||||||
|
|||||||
@@ -52,9 +52,9 @@ function convertToInteger(value: unknown): number {
|
|||||||
* @param _duration
|
* @param _duration
|
||||||
*/
|
*/
|
||||||
export function validateTimes(_start?: unknown, _end?: unknown, _duration?: unknown) {
|
export function validateTimes(_start?: unknown, _end?: unknown, _duration?: unknown) {
|
||||||
const timeStart = convertToInteger(_start);
|
const timeStart = convertToInteger(_start) % dayInMs;
|
||||||
const timeEnd = convertToInteger(_end);
|
const timeEnd = convertToInteger(_end) % dayInMs;
|
||||||
const duration = convertToInteger(_duration);
|
const duration = convertToInteger(_duration) % dayInMs;
|
||||||
|
|
||||||
if (_start != null && _end != null) {
|
if (_start != null && _end != null) {
|
||||||
// Case 1. if we have start and end, duration must be derived
|
// Case 1. if we have start and end, duration must be derived
|
||||||
|
|||||||
Reference in New Issue
Block a user