mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-17 13:23:35 +00:00
fix(timer): count-to-end events absorb overtime in expected end times
The server computed rundown/group expected end times as `expectedStart + duration`, ignoring `countToEnd`. For a count-to-end last event running in overtime this pushed the projected end far past (or before) its fixed end time, producing nonsensical values (e.g. a negative expected rundown end) and leaving group/flag readouts stuck on "due". It also never broke the link chain after a count-to-end event, unlike the client. A count-to-end event ends at its fixed end time regardless of preceding overtime (matching `getExpectedFinish` for the running timer), so its expected end should pin to the planned end and absorb the accumulated offset. - add shared `getExpectedEnd` helper in ontime-utils that pins count-to-end events to their planned end - use it in `getExpectedTimes` for both rundown and group end - break the `isLinkedToLoaded` chain after a count-to-end event in `loadGroupFlagAndEnd`, mirroring the client metadata logic - delegate the client's `getExpectedTimesFromExtendedEvent` to the shared helper to remove the duplicated formula that caused the drift - add unit and runtime-state tests covering overtime absorption and the chain break Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACGuFWt5aN7Fv3AkYXgxLm
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
MILLIS_PER_MINUTE,
|
||||
MILLIS_PER_SECOND,
|
||||
formatFromMillis,
|
||||
getExpectedEnd,
|
||||
getExpectedStart,
|
||||
} from 'ontime-utils';
|
||||
|
||||
@@ -172,13 +173,15 @@ export function getExpectedTimesFromExtendedEvent(
|
||||
) {
|
||||
if (event === null) return { expectedStart: 0, timeToStart: 0, expectedEnd: 0, plannedEnd: 0 };
|
||||
|
||||
const expectedStartState = {
|
||||
totalGap: event.totalGap,
|
||||
isLinkedToLoaded: event.isLinkedToLoaded,
|
||||
...state,
|
||||
};
|
||||
|
||||
const expectedStart = getExpectedStart(
|
||||
{ timeStart: event.timeStart, delay: event.delay, dayOffset: event.dayOffset },
|
||||
{
|
||||
totalGap: event.totalGap,
|
||||
isLinkedToLoaded: event.isLinkedToLoaded,
|
||||
...state,
|
||||
},
|
||||
expectedStartState,
|
||||
);
|
||||
|
||||
const plannedEnd = event.timeStart + event.duration + event.delay;
|
||||
@@ -186,9 +189,7 @@ export function getExpectedTimesFromExtendedEvent(
|
||||
return {
|
||||
expectedStart,
|
||||
timeToStart: expectedStart - state.clock,
|
||||
expectedEnd: event.countToEnd
|
||||
? Math.max(expectedStart + event.duration, plannedEnd)
|
||||
: expectedStart + event.duration,
|
||||
expectedEnd: getExpectedEnd(event, expectedStartState),
|
||||
plannedEnd,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user