mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-10 18:03:47 +00:00
131 lines
4.0 KiB
TypeScript
131 lines
4.0 KiB
TypeScript
import type { OntimeEvent } from 'ontime-types';
|
|
import { TimeStrategy } from 'ontime-types';
|
|
|
|
import { dayInMs } from '../date-utils/conversionUtils.js';
|
|
import { validateTimeStrategy } from '../validate-events/validateEvent.js';
|
|
|
|
export function getLinkedTimes(
|
|
target: OntimeEvent,
|
|
source: OntimeEvent,
|
|
): { timeStart: number; duration: number; timeEnd: number } {
|
|
const lockEnd = target.timeStrategy === TimeStrategy.LockEnd;
|
|
const lockDuration = target.timeStrategy === TimeStrategy.LockDuration;
|
|
const newStart = source.timeEnd;
|
|
|
|
const timePatch = {
|
|
timeStart: newStart,
|
|
timeEnd: lockEnd ? target.timeEnd : calculateEnd(newStart, target.duration),
|
|
duration: lockDuration ? target.duration : calculateDuration(newStart, target.timeEnd),
|
|
};
|
|
|
|
return timePatch;
|
|
}
|
|
|
|
function inferTimes(
|
|
_start?: unknown,
|
|
_end?: unknown,
|
|
_duration?: unknown,
|
|
): { timeStart: number; duration: number; timeEnd: number; timeStrategy: TimeStrategy } {
|
|
const timeStart = convertToInteger(_start);
|
|
const timeEnd = convertToInteger(_end);
|
|
const duration = convertToInteger(_duration);
|
|
|
|
// TODO: prevent overflow
|
|
|
|
if (_start != null && _end != null) {
|
|
// Case 1. if we have start and end, duration must be derived
|
|
return {
|
|
timeStart,
|
|
duration: calculateDuration(timeStart, timeEnd),
|
|
timeEnd,
|
|
timeStrategy: _duration != null ? TimeStrategy.LockDuration : TimeStrategy.LockEnd,
|
|
};
|
|
}
|
|
|
|
if (_start == null && _end == null) {
|
|
if (_duration == null) {
|
|
// Case 2. no valid times were given
|
|
return { timeStart: 0, duration: 0, timeEnd: 0, timeStrategy: TimeStrategy.LockDuration };
|
|
}
|
|
// Case 3. we have a duration and infer the rest
|
|
return { timeStart, duration, timeEnd: duration, timeStrategy: TimeStrategy.LockDuration };
|
|
}
|
|
|
|
if (_start != null) {
|
|
// Case 5. with only start, we can calculate the rest
|
|
return { timeStart, duration, timeEnd: (timeStart + duration) % dayInMs, timeStrategy: TimeStrategy.LockDuration };
|
|
}
|
|
|
|
if (_end != null) {
|
|
// Case 6. with only end, we can calculate the rest
|
|
return {
|
|
timeStart: timeEnd - duration,
|
|
duration,
|
|
timeEnd,
|
|
timeStrategy: _duration != null ? TimeStrategy.LockDuration : TimeStrategy.LockEnd,
|
|
};
|
|
}
|
|
|
|
// we should have covered all cases
|
|
return { timeStart, duration, timeEnd, timeStrategy: TimeStrategy.LockDuration };
|
|
}
|
|
|
|
/**
|
|
* Ensures the time input variables are valid in relationship to each other
|
|
* Infers values if necessary
|
|
* @param _start
|
|
* @param _end
|
|
* @param _duration
|
|
*/
|
|
export function validateTimes(
|
|
_start?: unknown,
|
|
_end?: unknown,
|
|
_duration?: unknown,
|
|
_strategy?: TimeStrategy,
|
|
): { timeStart: number; duration: number; timeEnd: number; timeStrategy: TimeStrategy } {
|
|
if (_strategy == null) {
|
|
// if no strategy is given we infer it from given parameters
|
|
return inferTimes(_start, _end, _duration);
|
|
}
|
|
|
|
const timeStrategy = validateTimeStrategy(_strategy);
|
|
const timeStart = convertToInteger(_start);
|
|
let timeEnd = convertToInteger(_end);
|
|
let duration = convertToInteger(_duration);
|
|
|
|
if (timeStrategy === TimeStrategy.LockEnd) {
|
|
duration = calculateDuration(timeStart, timeEnd);
|
|
} else {
|
|
timeEnd = calculateEnd(timeStart, duration);
|
|
}
|
|
return { timeStart, duration, timeEnd, timeStrategy };
|
|
}
|
|
|
|
/**
|
|
* @description calculates event duration considering midnight
|
|
* @param {number} timeStart
|
|
* @param {number} timeEnd
|
|
* @returns {number}
|
|
*/
|
|
export function calculateDuration(timeStart: number, timeEnd: number): number {
|
|
// Durations must be positive
|
|
if (timeEnd < timeStart) {
|
|
return timeEnd + dayInMs - timeStart;
|
|
}
|
|
return timeEnd - timeStart;
|
|
}
|
|
|
|
export function calculateEnd(timeStart: number, duration: number): number {
|
|
return (timeStart + duration) % dayInMs;
|
|
}
|
|
|
|
/**
|
|
* Converts a given value to an int, returns 0 otherwise
|
|
* @param value
|
|
* number
|
|
*/
|
|
function convertToInteger(value: unknown): number {
|
|
const result = Number(value);
|
|
return isNaN(result) ? 0 : Math.floor(result);
|
|
}
|