Files
ontime/packages/utils/index.ts
T
Claude 5b30f522aa 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
2026-06-20 06:44:06 +00:00

111 lines
3.5 KiB
TypeScript

// runtime utils
export { validatePlayback } from './src/validate-action/validatePlayback.js';
export { isKnownTimerType, validateTimeStrategy } from './src/validate-events/validateEvent.js';
export { calculateDuration, getLinkedTimes, validateTimes } from './src/validate-times/validateTimes.js';
// rundown utils
export { getCueCandidate } from './src/cue-utils/cueUtils.js';
export { generateId } from './src/generate-id/generateId.js';
export {
addToRundown,
getEventWithId,
getFirstEvent,
getFirstEventNormal,
getFirstNormal,
getFirstGroupNormal,
getInsertAfterId,
getLastEvent,
getLastEventNormal,
getLastNormal,
getLastGroupNormal,
getNextGroupNormal,
getNextEvent,
getNextEventNormal,
getNextNormal,
getPreviousEventNormal,
getPreviousNormal,
getPreviousGroupNormal,
resolveInsertParent,
swapEventData,
} from './src/rundown-utils/rundownUtils.js';
export { getFirstRundown } from './src/rundown/rundown.utils.js';
export {
event as eventDef,
group as groupDef,
milestone as milestoneDef,
} from './src/rundown-utils/entryDefinitions.js';
export { createDelay, createEvent, createGroup, createMilestone, makeString } from './src/rundown-utils/entryUtils.js';
// time format utils
export {
dayInMs,
maxDuration,
MILLIS_PER_HOUR,
MILLIS_PER_MINUTE,
MILLIS_PER_SECOND,
millisToSeconds,
secondsInMillis,
} from './src/date-utils/conversionUtils.js';
export { isISO8601, isTimeString } from './src/date-utils/isTimeString.js';
export {
formatFromMillis,
millisToString,
pad,
removeLeadingZero,
removeSeconds,
removeTrailingZero,
} from './src/date-utils/timeFormatting.js';
export { parseUserTime } from './src/date-utils/parseUserTime.js';
export { checkRegex, regex } from './src/regex-utils/checkRegex.js';
export { isColourHex } from './src/regex-utils/isColourHex.js';
export { splitWhitespace } from './src/regex-utils/splitWhitespace.js';
export { customFieldLabelToKey, customKeyFromLabel } from './src/customField-utils/customFieldUtils.js';
// helpers from externals
export { deepmerge } from './src/externals/deepmerge.js';
// array utils
export { deleteAtIndex, insertAtIndex, mergeAtIndex, reorderArray } from './src/common/arrayUtils.js';
// object utils
export { getPropertyFromPath, isObjectEmpty, withoutUndefinedValues, isValueOfEnum } from './src/common/objectUtils.js';
// generic utilities
export { getErrorMessage } from './src/generic/generic.js';
export { obfuscate, unobfuscate } from './src/generic/generic.js';
export { isNumeric } from './src/types/types.js';
// model validation
export { validateEndAction, validateTimerType } from './src/validate-events/validateEvent.js';
// feature business logic
export { getExpectedEnd, getExpectedStart } from './src/date-utils/getExpectedStart.js';
// feature business logic - rundown
export { checkIsNow } from './src/date-utils/checkIsNow.js';
export { checkIsNextDay } from './src/date-utils/checkIsNextDay.js';
export { getTimeFrom } from './src/date-utils/getTimeFrom.js';
export { isNewLatest } from './src/date-utils/isNewLatest.js';
// feature business logic - spreadsheet import
export {
type ImportCustom,
type ImportMap,
type ImportOptions,
defaultImportMap,
isImportMap,
} from './src/feature/spreadsheet-import/spreadsheetImport.js';
export { isPlaybackActive } from './src/playback-utils/playbackstate.js';
//Colour
export {
colourToHex,
cssOrHexToColour,
hexToColour,
isLightColour,
mixColours,
CssColours,
} from './src/colour/colour.utils.js';