import { OntimeEvent, SupportedEntry, TimeStrategy } from 'ontime-types'; import { generateId, validateEndAction, validateTimerType, validateTimes } from 'ontime-utils'; import { event as eventDef } from '../../models/eventsDefinition.js'; import { makeString } from '../../utils/parserUtils.js'; export function createPatch(originalEvent: OntimeEvent, patchEvent: Partial): OntimeEvent { if (Object.keys(patchEvent).length === 0) { return originalEvent; } const { timeStart, timeEnd, duration, timeStrategy } = validateTimes( patchEvent?.timeStart ?? originalEvent.timeStart, patchEvent?.timeEnd ?? originalEvent.timeEnd, patchEvent?.duration ?? originalEvent.duration, patchEvent?.timeStrategy ?? inferStrategy(patchEvent?.timeEnd, patchEvent?.duration, originalEvent.timeStrategy), ); return { id: originalEvent.id, type: SupportedEntry.Event, title: makeString(patchEvent.title, originalEvent.title), timeStart, timeEnd, duration, timeStrategy, linkStart: typeof patchEvent.linkStart === 'boolean' ? patchEvent.linkStart : originalEvent.linkStart, endAction: validateEndAction(patchEvent.endAction, originalEvent.endAction), timerType: validateTimerType(patchEvent.timerType, originalEvent.timerType), countToEnd: typeof patchEvent.countToEnd === 'boolean' ? patchEvent.countToEnd : originalEvent.countToEnd, isPublic: typeof patchEvent.isPublic === 'boolean' ? patchEvent.isPublic : originalEvent.isPublic, skip: typeof patchEvent.skip === 'boolean' ? patchEvent.skip : originalEvent.skip, note: makeString(patchEvent.note, originalEvent.note), colour: makeString(patchEvent.colour, originalEvent.colour), delay: originalEvent.delay, // is regenerated if timer related data is changed dayOffset: originalEvent.dayOffset, // is regenerated if timer related data is changed gap: originalEvent.gap, // is regenerated if timer related data is changed // short circuit empty string cue: makeString(patchEvent.cue ?? null, originalEvent.cue), parent: originalEvent.parent, revision: originalEvent.revision, timeWarning: patchEvent.timeWarning ?? originalEvent.timeWarning, timeDanger: patchEvent.timeDanger ?? originalEvent.timeDanger, custom: { ...originalEvent.custom, ...patchEvent.custom }, triggers: patchEvent.triggers ?? originalEvent.triggers, }; } /** * @description Enforces formatting for events * @param {object} eventArgs - attributes of event * @param {number} eventIndex - can be a string when we pass the a suggested cue name * @returns {object|null} - formatted object or null in case is invalid */ export const createEvent = (eventArgs: Partial, eventIndex: number | string): OntimeEvent | null => { if (Object.keys(eventArgs).length === 0) { return null; } const cue = typeof eventIndex === 'number' ? String(eventIndex + 1) : eventIndex; const baseEvent = { id: eventArgs?.id ?? generateId(), cue, ...eventDef, }; const event = createPatch(baseEvent, eventArgs); return event; }; /** * Function infers strategy for a patch with only partial timer data * @param end * @param duration * @param fallback * @returns */ function inferStrategy(end: unknown, duration: unknown, fallback: TimeStrategy): TimeStrategy { if (end && !duration) { return TimeStrategy.LockEnd; } if (!end && duration) { return TimeStrategy.LockDuration; } return fallback; }