Files
ontime/server/src/classes/classUtils.js
T
Carlos Valente 9fc154955a Feat/62 logger (#79)
* feat/62-logger request log data in app
* feat/62-logger refact osc integration
* feat/62-logger feedback on osc
* feat/62-logger refact broadcast on triggers
* feat/62-logger log triggers
* feat/62-logger add link to studio
* feat/62-logger replace toasts with logger context
* feat/62-logger style improvements
* feat/62-logger refactor code duplications
* feat/62-logger cleanup and version bump
2021-12-25 19:39:40 +01:00

213 lines
5.9 KiB
JavaScript

/**
* Utility variable: 24 hour in milliseconds .
* @type {number}
*/
export const DAY_TO_MS = 86400000;
/**
* @description handle events that span over midnight
* @param {number} start - When does the event start
* @param {number} end - When does the event end
* @returns {number} normalised time
*/
export const normaliseEndTime = (start, end) =>
end < start ? end + DAY_TO_MS : end;
/**
* @description Sorts an array of objects by given property
* @param {array} arr - array to be sorted
* @param {string} property - property to compare
* @returns {array} copy of array sorted in ascending order
*/
export const sortArrayByProperty = (arr, property) => {
return [...arr].sort((a, b) => {
return a[property] - b[property];
});
};
/**
* @description Replaces placeholder variables in string with given data
* @param {string} str - string to analyse
* @param {object} values - map of variables: values to use
* @returns {string} finished string
*/
export const replacePlaceholder = (str, values) => {
for (let [k, v] of Object.entries(values)) {
str = str.replace(k, v);
}
return str;
};
/**
* @description Used in roll mode, returns selection variables from array
* @param {array} arr - event list
* @param {number} now - time now in millis
* @returns {object} object with selection variables
*/
export const getSelectionByRoll = (arr, now) => {
// Events now
let nowIndex = null; // index of event now
let nowId = null; // id of event now
let publicIndex = null; // index of public event now
let publicTime = -1; // counter:
// Events next
let nextIndex = null; // index of next event
let publicNextIndex = null; // index of next public event
let timeToNext = null; // counter: time for next event
let publicTimeToNext = null; // counter: time for next public event
// current timer
let timers = null;
// Order events by startTime
const orderedEvents = sortArrayByProperty(arr, 'timeStart');
// flags: select first event if several overlapping
let nowFound = false;
// exit early if we are past the events
const lastEvent = orderedEvents[orderedEvents.length - 1];
const lastNormalEnd = normaliseEndTime(
lastEvent.timeStart,
lastEvent.timeEnd
);
if (now > lastNormalEnd) {
return {
nowIndex,
nowId,
publicIndex,
nextIndex,
publicNextIndex,
timers,
timeToNext,
};
}
// loop through events, look for where we should be
for (const e of orderedEvents) {
// When does the event end (handle midnight)
const normalEnd = normaliseEndTime(e.timeStart, e.timeEnd);
if (normalEnd <= now) {
// event ran already
// public event might not be the one running
if (e.isPublic && normalEnd > publicTime) {
publicTime = normalEnd;
publicIndex = arr.findIndex((a) => a.id === e.id);
}
} else if (normalEnd > now && now >= e.timeStart && !nowFound) {
// event is running
// it could also be public
if (e.isPublic) {
publicTime = normalEnd;
publicIndex = arr.findIndex((a) => a.id === e.id);
}
nowIndex = arr.findIndex((a) => a.id === e.id);
nowId = e.id;
// set timers
timers = {
_startedAt: e.timeStart,
_finishAt: e.timeEnd,
duration: normalEnd - e.timeStart,
current: normalEnd - now,
};
nowFound = true;
} else if (normalEnd > now) {
// event will run
// no need to look after found first
if (nextIndex !== null && publicNextIndex !== null) continue;
// look for next events
// check how far the start is from now
const wait = e.timeStart - now;
if (nextIndex == null || wait < timeToNext) {
timeToNext = wait;
nextIndex = arr.findIndex((a) => a.id === e.id);
}
if ((publicNextIndex === null || wait < publicTimeToNext) && e.isPublic) {
publicTimeToNext = wait;
publicNextIndex = arr.findIndex((a) => a.id === e.id);
}
}
}
return {
nowIndex,
nowId,
publicIndex,
nextIndex,
publicNextIndex,
timers,
timeToNext,
};
};
/**
* @description Implements update functions for roll mode
* @param {object} currentTimers
* @param {object} currentTimers.selectedEventId - Id of currently selected event
* @param {object} currentTimers.current - Running timer
* @param {object} currentTimers._finishAt - Expected finish time
* @param {object} currentTimers.clock - time now
* @param {object} currentTimers.secondaryTimer - secondary timer
* @param {object} currentTimers._secondaryTarget - finish time of secondary timer
* @returns {object} object with selection variables
*/
export const updateRoll = (currentTimers) => {
const {
selectedEventId,
current,
_finishAt,
clock,
secondaryTimer,
_secondaryTarget,
} = currentTimers;
// timers
let updatedTimer = current;
let updatedSecondaryTimer = secondaryTimer;
// whether rollLoad should be called
let doRollLoad = false;
// whether runCycle should be called
let isFinished = false;
if (selectedEventId && current >= 0) {
// if we have something selected and a timer, we are running
// this is true because roll never goes into negative times
// update timer
updatedTimer = _finishAt - clock;
if (updatedTimer < 0) {
isFinished = true;
}
} else if (secondaryTimer >= 0) {
// if secondaryTimer is running we are in waiting to roll
// update secondary
updatedSecondaryTimer = _secondaryTarget - clock;
}
// if nothing is running, we need to find out if
// a) we just finished an event (finished was set to true)
// b) we need to look for events
// this could be caused by a secondary timer or event finished
const secondaryRunning =
updatedSecondaryTimer <= 0 && updatedSecondaryTimer != null;
if (isFinished || secondaryRunning) {
// look for events
doRollLoad = true;
}
return { updatedTimer, updatedSecondaryTimer, doRollLoad, isFinished };
};