diff --git a/apps/client/src/common/utils/offset.ts b/apps/client/src/common/utils/offset.ts
index 532fae07e..ecaf6f774 100644
--- a/apps/client/src/common/utils/offset.ts
+++ b/apps/client/src/common/utils/offset.ts
@@ -21,5 +21,6 @@ export function getOffsetText(offset: MaybeNumber): string {
export function getOffsetState(offset: MaybeNumber): 'over' | 'under' | 'muted' | null {
if (offset === null) return 'muted';
if (offset === 0) return null;
- return offset < 0 ? 'over' : 'under';
+ // a positive value means that we are in over time aka behind schedule
+ return offset > 0 ? 'over' : 'under';
}
diff --git a/apps/client/src/features/overview/composite/TimeElements.tsx b/apps/client/src/features/overview/composite/TimeElements.tsx
index d8fee75c8..9caaae1f0 100644
--- a/apps/client/src/features/overview/composite/TimeElements.tsx
+++ b/apps/client/src/features/overview/composite/TimeElements.tsx
@@ -167,9 +167,8 @@ export function OffsetOverview() {
const { offset, playback } = useRuntimePlaybackOverview();
const isPlaying = isPlaybackActive(playback);
- const correctedOffset = offset * -1;
const offsetState = getOffsetState(isPlaying ? offset : null);
- const offsetText = getOffsetText(isPlaying ? correctedOffset : null);
+ const offsetText = getOffsetText(isPlaying ? offset : null);
return ;
}
diff --git a/apps/client/src/features/rundown/entry-editor/GroupEditor.tsx b/apps/client/src/features/rundown/entry-editor/GroupEditor.tsx
index 2ed797d76..bfd51d8ee 100644
--- a/apps/client/src/features/rundown/entry-editor/GroupEditor.tsx
+++ b/apps/client/src/features/rundown/entry-editor/GroupEditor.tsx
@@ -50,8 +50,8 @@ export default function GroupEditor({ group }: GroupEditorProps) {
);
const isEditor = window.location.pathname.includes('editor');
- const planOffset = typeof group.targetDuration !== 'number' ? null : group.duration - group.targetDuration;
- const planOffsetLabel = planOffset !== null ? getOffsetState(planOffset * -1) : null;
+ const planOffset = group.targetDuration === null ? null : group.duration - group.targetDuration;
+ const planOffsetLabel = planOffset !== null ? getOffsetState(planOffset) : null;
return (
diff --git a/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx b/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx
index 4db25e537..c558c31da 100644
--- a/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx
+++ b/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx
@@ -10,6 +10,7 @@ import {
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { EntryId, OntimeGroup } from 'ontime-types';
+import { MILLIS_PER_MINUTE } from 'ontime-utils';
import IconButton from '../../../common/components/buttons/IconButton';
import { useContextMenu } from '../../../common/hooks/useContextMenu';
@@ -102,8 +103,11 @@ export default function RundownGroup({ data, hasCursor, collapsed, onCollapse }:
if (offset === 0) {
return [null, 'under'];
}
-
- return [offset < 0 ? `-${formatDuration(offset * -1)}` : `+${formatDuration(offset)}`, getOffsetState(offset * -1)];
+ const absOffset = Math.abs(offset);
+ return [
+ `${offset < 0 ? '-' : '+'}${formatDuration(absOffset, absOffset > 2 * MILLIS_PER_MINUTE)}`,
+ getOffsetState(offset),
+ ];
})();
const dragStyle = {
diff --git a/apps/server/src/services/__tests__/timerUtils.test.ts b/apps/server/src/services/__tests__/timerUtils.test.ts
index 8a6bed563..1496b3b5c 100644
--- a/apps/server/src/services/__tests__/timerUtils.test.ts
+++ b/apps/server/src/services/__tests__/timerUtils.test.ts
@@ -742,7 +742,7 @@ describe('getRuntimeOffset()', () => {
} as RuntimeState;
const { offsetAbs } = getRuntimeOffset(state);
- expect(offsetAbs).toBe(-50);
+ expect(offsetAbs).toBe(50);
});
it('added time subtracts time offset (positive offset)', () => {
@@ -766,7 +766,7 @@ describe('getRuntimeOffset()', () => {
} as RuntimeState;
const { offsetAbs } = getRuntimeOffset(state);
- expect(offsetAbs).toBe(-60);
+ expect(offsetAbs).toBe(60);
});
it('considers running overtime (negative offset)', () => {
@@ -791,7 +791,7 @@ describe('getRuntimeOffset()', () => {
} as RuntimeState;
const { offsetAbs } = getRuntimeOffset(state);
- expect(offsetAbs).toBe(-10);
+ expect(offsetAbs).toBe(10);
});
it('paused time is delayed time (negative offset)', () => {
@@ -817,7 +817,7 @@ describe('getRuntimeOffset()', () => {
} as RuntimeState;
const { offsetAbs } = getRuntimeOffset(state);
- expect(offsetAbs).toBe(-25);
+ expect(offsetAbs).toBe(25);
});
it('offset doesnt exist if we havent started', () => {
@@ -857,46 +857,6 @@ describe('getRuntimeOffset()', () => {
expect(offsetAbs).toBe(0);
});
- it('handles loaded event', () => {
- const state = {
- clock: 79521653,
- eventNow: {
- id: '835242',
- timeStart: 81000000,
- timeEnd: 84600000,
- duration: 3600000,
- timeStrategy: 'lock-duration',
- linkStart: false,
- endAction: 'none',
- timerType: 'count-down',
- delay: 0,
- },
- runtime: {
- selectedEventIndex: 1,
- numEvents: 2,
- offsetAbs: -81000000,
- plannedStart: 77400000,
- plannedEnd: 84600000,
- actualStart: 79443403,
- expectedEnd: null,
- },
- timer: {
- addedTime: 0,
- current: 3600000,
- duration: 3600000,
- elapsed: null,
- expectedFinish: null,
- playback: 'armed',
- secondaryTimer: null,
- startedAt: null,
- },
- _timer: { pausedAt: null },
- } as RuntimeState;
-
- const { offsetAbs } = getRuntimeOffset(state);
- expect(offsetAbs).toBe(81000000 - 79521653); // clock - timestart
- });
-
it('with time-to-end, offsets dont exist if we are not in overtime', () => {
const state = {
clock: 80000000, // 22:13:20
@@ -996,7 +956,7 @@ describe('getRuntimeOffset()', () => {
} as RuntimeState;
const { offsetAbs } = getRuntimeOffset(state);
- expect(offsetAbs).toBe(-400000); // <--- offset is always the overtime
+ expect(offsetAbs).toBe(400000); // <--- offset is always the overtime
});
it('handles time-to-end started after the end time', () => {
@@ -1038,8 +998,8 @@ describe('getRuntimeOffset()', () => {
const updateCurrent = getCurrent(state);
state.timer.current = updateCurrent;
const { offsetAbs } = getRuntimeOffset(state);
- expect(millisToString(offsetAbs)).toBe('-00:16:40');
- expect(offsetAbs).toBe(81000000 - 82000000); // <-- planned end - now
+ expect(millisToString(offsetAbs)).toBe('00:16:40');
+ expect(offsetAbs).toBe(82000000 - 81000000); // <-- now - planned end
});
});
@@ -1089,7 +1049,7 @@ describe('getoffsetRel()', () => {
} as RuntimeState;
const { offsetAbs, offsetRel } = getRuntimeOffset(state);
- expect(offsetAbs).toBe(-50);
+ expect(offsetAbs).toBe(50);
expect(offsetRel).toBe(0);
});
it('relative offset is 0 when starting before the planed time', () => {
@@ -1113,7 +1073,7 @@ describe('getoffsetRel()', () => {
} as RuntimeState;
const { offsetAbs, offsetRel } = getRuntimeOffset(state);
- expect(offsetAbs).toBe(50);
+ expect(offsetAbs).toBe(-50);
expect(offsetRel).toBe(0);
});
});
diff --git a/apps/server/src/services/timerUtils.ts b/apps/server/src/services/timerUtils.ts
index 6d3a41723..ff075f3fb 100644
--- a/apps/server/src/services/timerUtils.ts
+++ b/apps/server/src/services/timerUtils.ts
@@ -109,57 +109,44 @@ export function skippedOutOfEvent(state: RuntimeState, previousTime: number, ski
/**
* Calculates difference between the runtime and the schedule of an event
- * Positive offset is time ahead
- * Negative offset is time delayed
+ * Positive offset is over time / behind schedule
+ * Negative offset is under time / ahead of schedule
*/
export function getRuntimeOffset(state: RuntimeState): { offsetAbs: number; offsetRel: number } {
+ const { eventNow, clock } = state;
+ const { addedTime, current, startedAt } = state.timer;
// nothing to calculate if there are no loaded events or if we havent started
- if (state.eventNow === null || state.runtime.actualStart === null) {
+ if (eventNow === null || startedAt === null) {
return { offsetAbs: 0, offsetRel: 0 };
}
- const { clock } = state;
- const { countToEnd, timeStart } = state.eventNow;
- const { addedTime, current, startedAt } = state.timer;
- const { actualStart, plannedStart } = state.runtime;
+ const { countToEnd, timeStart } = eventNow;
+ const { plannedStart, actualStart } = state.runtime;
// eslint-disable-next-line no-unused-labels -- dev code path
DEV: {
// we know current exists as long as eventNow exists
if (current === null) throw new Error('timerUtils.getRuntimeOffset: state.timer.current must be set');
if (plannedStart === null) throw new Error('timerUtils.getRuntimeOffset: state.runtime.plannedStart must be set');
+ if (actualStart === null) throw new Error('timerUtils.getRuntimeOffset: state.runtime.actualStart must be set');
}
- // if we havent started, but the timer is armed
- // the offset is the difference to the schedule
- if (startedAt === null) {
- return { offsetAbs: timeStart - clock, offsetRel: 0 };
- }
+ // difference between planned event start and actual event start (will be positive if we stared behind )
+ const eventStartOffset = startedAt - timeStart;
- const overtime = Math.min(current, 0);
- // in time-to-end, offset is overtime
+ // how long has the event been running over (is a negative number when in over timer so inverted before adding to offset)
+ const overtime = Math.abs(Math.min(current, 0));
- const startOffset = timeStart - startedAt;
+ // time the playback was paused, the different from now to when we paused is added to the offset TODO: brakes when crossing midnight
const pausedTime = state._timer.pausedAt === null ? 0 : clock - state._timer.pausedAt;
- // startOffset - difference between scheduled start and actual start
- // addedTime - time added by user (negative offset)
- // pausedTime - time the playback was paused (negative offset)
- // overtime - how long the timer has been over-running (negative offset)
- const offset = startOffset - addedTime - pausedTime + overtime;
+ const offsetAbs = eventStartOffset + overtime + pausedTime + addedTime;
- // offset between planned rundown start and actual rundown start
- const rundownStartOffset = actualStart - plannedStart;
+ // the relative offset i the same as the absolute offset but adjusted relative to the actual start time
+ const offsetRel = offsetAbs + plannedStart - actualStart;
- // offset offset relative to the actual rundown start
- const offsetRel = offset + rundownStartOffset;
-
- // in time-to-end, offset is overtime
- if (countToEnd) {
- return { offsetAbs: overtime, offsetRel };
- }
-
- return { offsetAbs: offset, offsetRel };
+ // in case of count to end, the absolute offset is just the overtime
+ return countToEnd ? { offsetAbs: overtime, offsetRel } : { offsetAbs, offsetRel };
}
/**
diff --git a/apps/server/src/stores/__tests__/runtimeState.test.ts b/apps/server/src/stores/__tests__/runtimeState.test.ts
index d7d11b9d6..dbeb61abf 100644
--- a/apps/server/src/stores/__tests__/runtimeState.test.ts
+++ b/apps/server/src/stores/__tests__/runtimeState.test.ts
@@ -67,17 +67,20 @@ beforeAll(() => {
});
describe('mutation on runtimeState', () => {
+ beforeEach(() => {
+ vi.useFakeTimers();
+ vi.setSystemTime('jan 1 00:01');
+ });
afterEach(() => {
vi.clearAllMocks();
+ vi.useRealTimers();
});
describe('playback operations', async () => {
it('refuses if nothing is loaded', async () => {
// force update
- vi.useFakeTimers();
await initRundown(makeRundown({}), {});
vi.runAllTimers();
- vi.useRealTimers();
let success = start(mockState);
expect(success).toBe(false);
@@ -93,10 +96,8 @@ describe('mutation on runtimeState', () => {
order: [mockEvent.id, 'event2'],
});
// force update
- vi.useFakeTimers();
await initRundown(mockRundown, {});
vi.runAllTimers();
- vi.useRealTimers();
const { metadata, rundown } = rundownCache.get();
load(mockEvent, rundown, metadata);
@@ -108,6 +109,7 @@ describe('mutation on runtimeState', () => {
expect(newState.groupNow).toBeNull();
// 2. Start event
+ vi.setSystemTime('jan 1 00:02');
let success = start();
newState = getState();
expect(success).toBe(true);
@@ -117,6 +119,7 @@ describe('mutation on runtimeState', () => {
expect(newState.runtime.actualStart).toBe(newState.clock);
// 3. Pause event
+ vi.setSystemTime('jan 1 00:03');
success = pause();
newState = getState();
expect(success).toBe(true);
@@ -131,6 +134,7 @@ describe('mutation on runtimeState', () => {
expect(success).toBe(false);
// 4. Restart event
+ vi.setSystemTime('jan 1 00:04');
success = start();
newState = getState();
expect(success).toBe(true);
@@ -150,6 +154,7 @@ describe('mutation on runtimeState', () => {
expect(newState._timer.pausedAt).toBeNull();
// 5. Stop event
+ vi.setSystemTime('jan 1 00:05');
success = stop();
newState = getState();
expect(success).toBe(true);
@@ -163,80 +168,81 @@ describe('mutation on runtimeState', () => {
});
expect(newState.runtime.actualStart).toBeNull();
});
+ });
- test('runtime offset', async () => {
- const entries = {
- event1: { ...mockEvent, id: 'event1', timeStart: 0, timeEnd: 1000, duration: 1000, parent: null },
- event2: { ...mockEvent, id: 'event2', timeStart: 1000, timeEnd: 1500, duration: 500, parent: null },
- };
- const mockRundown = makeRundown({ entries, order: ['event1', 'event2'] });
+ test('runtime offset', async () => {
+ const entries = {
+ event1: { ...mockEvent, id: 'event1', timeStart: 0, timeEnd: 1000, duration: 1000, parent: null },
+ event2: { ...mockEvent, id: 'event2', timeStart: 1000, timeEnd: 1500, duration: 500, parent: null },
+ };
+ const mockRundown = makeRundown({ entries, order: ['event1', 'event2'] });
- // force update
- vi.useFakeTimers();
- await initRundown(mockRundown, {});
- vi.runAllTimers();
- vi.useRealTimers();
+ // force update
+ await initRundown(mockRundown, {});
+ vi.runAllTimers();
- const { metadata, rundown } = rundownCache.get();
+ const { metadata, rundown } = rundownCache.get();
- // 1. Load event
- load(entries.event1, rundown, metadata);
- let newState = getState();
- expect(newState.runtime.actualStart).toBeNull();
- expect(newState.runtime.plannedStart).toBe(0);
- expect(newState.runtime.plannedEnd).toBe(1500);
- expect(newState.groupNow).toBeNull();
- expect(newState.runtime.offsetAbs).toBe(0);
+ // 1. Load event
+ vi.setSystemTime('jan 1 00:09');
+ load(entries.event1, rundown, metadata);
+ let newState = getState();
+ expect(newState.runtime.actualStart).toBeNull();
+ expect(newState.runtime.plannedStart).toBe(0);
+ expect(newState.runtime.plannedEnd).toBe(1500);
+ expect(newState.groupNow).toBeNull();
+ expect(newState.runtime.offsetAbs).toBe(0);
- // 2. Start event
- start();
- newState = getState();
- const firstStart = newState.clock;
- if (newState.runtime.offsetAbs === null) {
- throw new Error('Value cannot be null at this stage');
- }
+ // 2. Start event
+ vi.setSystemTime('jan 1 00:10');
+ start();
+ newState = getState();
+ const firstStart = newState.clock;
+ if (newState.runtime.offsetAbs === null) {
+ throw new Error('Value cannot be null at this stage');
+ }
- expect(newState.runtime.actualStart).toBe(newState.clock);
- expect(newState.runtime.offsetAbs).toBe(entries.event1.timeStart - newState.clock);
- expect(newState.runtime.expectedEnd).toBe(entries.event2.timeEnd - newState.runtime.offsetAbs);
+ expect(newState.runtime.actualStart).toBe(newState.clock);
+ expect(newState.runtime.offsetAbs).toBe(newState.clock - entries.event1.timeStart);
+ expect(newState.runtime.expectedEnd).toBe(entries.event2.timeEnd + newState.runtime.offsetAbs);
- // 3. Next event
- load(entries.event2, rundown, metadata);
- start();
+ // 3. Next event
+ vi.setSystemTime('jan 1 00:12');
+ load(entries.event2, rundown, metadata);
+ start();
- newState = getState();
- if (newState.runtime.actualStart === null || newState.runtime.offsetAbs === null) {
- throw new Error('Value cannot be null at this stage');
- }
+ newState = getState();
+ if (newState.runtime.actualStart === null || newState.runtime.offsetAbs === null) {
+ throw new Error('Value cannot be null at this stage');
+ }
- // there is a case where the calculation time overflows the millisecond which makes
- // tests fail
- const forgivingActualStart = Math.abs(newState.runtime.actualStart - firstStart);
- expect(forgivingActualStart).toBeLessThanOrEqual(1);
- // we are over-under, the difference between the schedule and the actual start
- const delayBefore = entries.event2.timeStart - newState.clock;
- expect(newState.runtime.offsetAbs).toBe(delayBefore);
- // finish is the difference between the runtime and the schedule
- expect(newState.runtime.expectedEnd).toBe(entries.event2.timeEnd - newState.runtime.offsetAbs);
- expect(newState.groupNow).toBeNull();
+ // there is a case where the calculation time overflows the millisecond which makes
+ // tests fail
+ const forgivingActualStart = Math.abs(newState.runtime.actualStart - firstStart);
+ expect(forgivingActualStart).toBeLessThanOrEqual(1);
+ // we are over-under, the difference between the schedule and the actual start
+ const delayBefore = newState.clock - entries.event2.timeStart;
+ expect(newState.runtime.offsetAbs).toBe(delayBefore);
+ // finish is the difference between the runtime and the schedule
+ expect(newState.runtime.expectedEnd).toBe(newState.runtime.offsetAbs + entries.event2.timeEnd);
+ expect(newState.groupNow).toBeNull();
- // 4. Add time
- addTime(10);
- newState = getState();
- if (newState.runtime.offsetAbs === null) {
- throw new Error('Value cannot be null at this stage');
- }
+ // 4. Add time
+ addTime(10);
+ newState = getState();
+ if (newState.runtime.offsetAbs === null) {
+ throw new Error('Value cannot be null at this stage');
+ }
- expect(newState.runtime.offsetAbs).toBe(delayBefore - 10);
- expect(newState.runtime.expectedEnd).toBe(entries.event2.timeEnd - newState.runtime.offsetAbs);
+ expect(newState.runtime.offsetAbs).toBe(delayBefore + 10);
+ expect(newState.runtime.expectedEnd).toBe(entries.event2.timeEnd + newState.runtime.offsetAbs);
- // 5. Stop event
- stop();
- newState = getState();
- expect(newState.runtime.actualStart).toBeNull();
- expect(newState.runtime.offsetAbs).toBe(0);
- expect(newState.runtime.expectedEnd).toBeNull();
- });
+ // 5. Stop event
+ stop();
+ newState = getState();
+ expect(newState.runtime.actualStart).toBeNull();
+ expect(newState.runtime.offsetAbs).toBe(0);
+ expect(newState.runtime.expectedEnd).toBeNull();
});
});
@@ -326,7 +332,7 @@ describe('roll mode', () => {
start();
const result = roll(rundown, metadata);
expect(result).toStrictEqual({ eventId: '1', didStart: false });
- expect(getState().runtime.offsetAbs).toBe(1000);
+ expect(getState().runtime.offsetAbs).toBe(-1000);
});
});
@@ -353,18 +359,18 @@ describe('roll mode', () => {
const currentOffset = getState().runtime.offsetAbs;
let result = roll(rundown, metadata, getState().runtime.offsetAbs);
expect(result).toStrictEqual({ eventId: '1', didStart: false });
- // the current offset should be maintain by roll mode whn taking over from play
+ // the current offset should be maintain by roll mode when taking over from play
expect(getState().runtime.offsetAbs).toBe(currentOffset);
vi.setSystemTime('jan 1 00:00:01');
result = roll(rundown, metadata, getState().runtime.offsetAbs);
expect(result).toStrictEqual({ eventId: '2', didStart: true });
- expect(getState().runtime.offsetAbs).toBe(1000);
+ expect(getState().runtime.offsetAbs).toBe(-1000);
vi.setSystemTime('jan 1 00:00:02');
result = roll(rundown, metadata, getState().runtime.offsetAbs);
expect(result).toStrictEqual({ eventId: '3', didStart: true });
- expect(getState().runtime.offsetAbs).toBe(1000);
+ expect(getState().runtime.offsetAbs).toBe(-1000);
vi.useRealTimers();
});
diff --git a/apps/server/src/stores/runtimeState.ts b/apps/server/src/stores/runtimeState.ts
index 8b6d19cb4..3b7c67937 100644
--- a/apps/server/src/stores/runtimeState.ts
+++ b/apps/server/src/stores/runtimeState.ts
@@ -314,7 +314,7 @@ export function updateLoaded(event?: PlayableEvent): string | undefined {
// handle edge cases with roll
if (runtimeState.timer.playback === Playback.Roll) {
- const offsetClock = runtimeState.clock + runtimeState.runtime.offsetAbs;
+ const offsetClock = runtimeState.clock - runtimeState.runtime.offsetAbs;
// if waiting to roll, we update the targets and potentially start the timer
if (runtimeState._timer.secondaryTarget !== null) {
if (runtimeState.eventNow.timeStart < offsetClock && offsetClock < runtimeState.eventNow.timeEnd) {
@@ -391,7 +391,6 @@ export function start(state: RuntimeState = runtimeState): boolean {
state.timer.expectedFinish = getExpectedFinish(state);
state.timer.elapsed = 0;
- // update runtime delays: over - under
if (state.runtime.actualStart === null) {
state.runtime.actualStart = state.clock;
}
@@ -521,7 +520,6 @@ export function update(): UpdateResult {
const { offsetAbs, offsetRel } = getRuntimeOffset(runtimeState);
runtimeState.runtime.offsetAbs = offsetAbs;
runtimeState.runtime.offsetRel = offsetRel;
- // runtimeState.runtime.expectedEnd = getExpectedEnd(runtimeState);
const finishedNow =
Boolean(runtimeState._timer.forceFinish) ||
@@ -596,7 +594,7 @@ export function roll(
runtimeState.timer.expectedFinish = normalisedEndTime;
//account for offset
- const offsetClock = runtimeState.clock + runtimeState.runtime.offsetAbs;
+ const offsetClock = runtimeState.clock - runtimeState.runtime.offsetAbs;
// state catch up
runtimeState.timer.duration = calculateDuration(runtimeState.eventNow.timeStart, normalisedEndTime);
@@ -635,7 +633,7 @@ export function roll(
//account for offset but we only keep it if passed to us
runtimeState.runtime.offsetAbs = offset;
- const offsetClock = runtimeState.clock + runtimeState.runtime.offsetAbs;
+ const offsetClock = runtimeState.clock - runtimeState.runtime.offsetAbs;
const { index, isPending } = loadRoll(rundown, metadata, offsetClock);
diff --git a/packages/types/src/definitions/runtime/Runtime.type.ts b/packages/types/src/definitions/runtime/Runtime.type.ts
index 07d382574..4a0ea88ef 100644
--- a/packages/types/src/definitions/runtime/Runtime.type.ts
+++ b/packages/types/src/definitions/runtime/Runtime.type.ts
@@ -8,7 +8,7 @@ export enum OffsetMode {
export type Runtime = {
selectedEventIndex: MaybeNumber;
numEvents: number;
- offsetAbs: number;
+ offsetAbs: number; // a positive value means that we are in over time aka behind schedule
offsetRel: number;
plannedStart: MaybeNumber;
actualStart: MaybeNumber;
diff --git a/packages/utils/src/date-utils/getExpectedStart.test.ts b/packages/utils/src/date-utils/getExpectedStart.test.ts
index b3906dcf6..30082f87c 100644
--- a/packages/utils/src/date-utils/getExpectedStart.test.ts
+++ b/packages/utils/src/date-utils/getExpectedStart.test.ts
@@ -33,7 +33,7 @@ describe('getExpectedStart()', () => {
const testState = {
currentDay: 0,
totalGap: 0,
- offset: -20,
+ offset: 20,
offsetMode: OffsetMode.Absolute,
actualStart: null,
plannedStart: null,
@@ -52,7 +52,7 @@ describe('getExpectedStart()', () => {
const testState = {
currentDay: 0,
totalGap: 0,
- offset: 10,
+ offset: -10,
offsetMode: OffsetMode.Absolute,
actualStart: null,
plannedStart: null,
@@ -71,7 +71,7 @@ describe('getExpectedStart()', () => {
const testState = {
currentDay: 0,
totalGap: 20,
- offset: -20,
+ offset: 20,
offsetMode: OffsetMode.Absolute,
actualStart: null,
plannedStart: null,
@@ -90,7 +90,7 @@ describe('getExpectedStart()', () => {
const testState = {
currentDay: 0,
totalGap: 10,
- offset: -20,
+ offset: 20,
offsetMode: OffsetMode.Absolute,
actualStart: 0,
plannedStart: 0,
@@ -219,12 +219,12 @@ describe('getExpectedStart()', () => {
expect(getExpectedStart(testEvent, { ...testState, isLinkedToLoaded: true })).toBe(120);
expect(getExpectedStart(testEvent, { ...testState, isLinkedToLoaded: false })).toBe(120);
- testState.offset = 5; // remove 5 with addtime - we are ahead of time
+ testState.offset = -5; // remove 5 with addtime - we are ahead of time
expect(getExpectedStart(testEvent, { ...testState, isLinkedToLoaded: true })).toBe(115);
- expect(getExpectedStart(testEvent, { ...testState, isLinkedToLoaded: false })).toBe(120); // unlocked evets will stay on schedule
+ expect(getExpectedStart(testEvent, { ...testState, isLinkedToLoaded: false })).toBe(120); // unlinked events will stay on schedule
- testState.offset = -5; // add 5 with addtime - we are behind
+ testState.offset = +5; // add 5 with addtime - we are behind
expect(getExpectedStart(testEvent, { ...testState, isLinkedToLoaded: true })).toBe(125);
expect(getExpectedStart(testEvent, { ...testState, isLinkedToLoaded: false })).toBe(125);
diff --git a/packages/utils/src/date-utils/getExpectedStart.ts b/packages/utils/src/date-utils/getExpectedStart.ts
index 5959443e8..7fb9d3395 100644
--- a/packages/utils/src/date-utils/getExpectedStart.ts
+++ b/packages/utils/src/date-utils/getExpectedStart.ts
@@ -43,14 +43,14 @@ export function getExpectedStart(
const scheduledStartTime = normalisedTimeStart + relativeStartOffset;
- const offsetStartTime = scheduledStartTime - offset;
+ const offsetStartTime = scheduledStartTime + offset;
if (isLinkedToLoaded) {
//if we are directly linked back to the loaded event we just follow the offset
return offsetStartTime;
}
- const gapsCanCompensateForOffset = totalGap + offset >= 0;
+ const gapsCanCompensateForOffset = totalGap > offset;
if (gapsCanCompensateForOffset) {
// if we are ahead of schedule or the gap can compensate for the amount we are behind then expect to start at the scheduled time
return scheduledStartTime;