refactor: normalise data (#756)

* chore: remove legal from bundle

* refactor: create normalised dataset

* refactor: cuesheet uses flat rundown

* refactor: multi-selection

* refactor: prevent stale data on server restart

* refactor: increase ID size

* chore: instrument operation

* chore: update csv tests

* fix: resolve directory to test-db (#758)
This commit is contained in:
Carlos Valente
2024-02-03 21:43:17 +01:00
committed by GitHub
parent 47a519bac1
commit 1890fc49d7
62 changed files with 1838 additions and 3341 deletions
@@ -1,6 +1,6 @@
import { OntimeRundown, SupportedEvent } from 'ontime-types';
import { OntimeEvent, OntimeRundown, SupportedEvent } from 'ontime-types';
import { getNext, getNextEvent, getPrevious, getPreviousEvent } from './rundownUtils';
import { getNext, getNextEvent, getPrevious, getPreviousEvent, swapEventData } from './rundownUtils';
describe('getNext()', () => {
it('returns the next event of type event', () => {
@@ -149,3 +149,43 @@ describe('getPreviousEvent()', () => {
expect(previousIndex).toBe(null);
});
});
describe('swapEventData', () => {
it('swaps some data between two events', () => {
const eventA = {
id: '1',
cue: 'A',
timeStart: 1,
timeEnd: 1,
duration: 1,
delay: 1,
} as OntimeEvent;
const eventB = {
id: '2',
cue: 'B',
timeStart: 2,
timeEnd: 2,
duration: 2,
delay: 2,
} as OntimeEvent;
const { newA, newB } = swapEventData(eventA, eventB);
expect(newA).toMatchObject({
id: '1',
cue: 'B',
timeStart: 1,
timeEnd: 1,
duration: 1,
delay: 1,
});
expect(newB).toMatchObject({
id: '2',
cue: 'A',
timeStart: 2,
timeEnd: 2,
duration: 2,
delay: 2,
});
});
});
+185 -33
View File
@@ -1,4 +1,4 @@
import { isOntimeEvent, OntimeEvent, OntimeRundown, OntimeRundownEntry } from 'ontime-types';
import { isOntimeEvent, NormalisedRundown, OntimeEvent, OntimeRundown, OntimeRundownEntry } from 'ontime-types';
/**
* Gets first event in rundown, if it exists
@@ -9,6 +9,17 @@ export function getFirst(rundown: OntimeRundownEntry[]) {
return rundown.length ? rundown[0] : null;
}
/**
* Gets first event in a normalised rundown, if it exists
* @param rundown
* @param order
* @returns
*/
export function getFirstNormal(rundown: NormalisedRundown, order: string[]) {
const firstId = order[0];
return rundown[firstId] ?? null;
}
/**
* Gets first scheduled event in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
@@ -27,6 +38,34 @@ export function getFirstEvent(rundown: OntimeRundownEntry[]): {
return { firstEvent: null, firstIndex: null };
}
/**
* Gets first scheduled event in a normalised rundown, if it exists
* @param rundown
* @param order
* @returns
*/
export function getFirstEventNormal(
rundown: NormalisedRundown,
order: string[],
): {
firstEvent: OntimeEvent | null;
firstIndex: number | null;
} {
for (let i = 0; i < order.length; i++) {
const firstId = order[i];
const firstEvent = rundown[firstId];
if (isOntimeEvent(firstEvent)) {
return { firstEvent, firstIndex: i };
}
}
return { firstEvent: null, firstIndex: null };
}
/**
* Gets last scheduled event in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @return {{ firstEvent: OntimeEvent | null; firstIndex: number | null } }
*/
export function getLastEvent(rundown: OntimeRundown): {
lastEvent: OntimeEvent | null;
lastIndex: number | null;
@@ -45,7 +84,34 @@ export function getLastEvent(rundown: OntimeRundown): {
}
/**
* Gets next event in rundown, if it exists
* Gets last scheduled event in a normalised rundown, if it exists
* @param rundown
* @param order
* @return {{ firstEvent: OntimeEvent | null; firstIndex: number | null } }
*/
export function getLastEventNormal(
rundown: NormalisedRundown,
order: string[],
): {
lastEvent: OntimeEvent | null;
lastIndex: number | null;
} {
if (order.length < 1) {
return { lastEvent: null, lastIndex: null };
}
for (let i = order.length - 1; i > 0; i--) {
const lastId = order[i];
const lastEvent = rundown[lastId];
if (isOntimeEvent(lastEvent)) {
return { lastEvent, lastIndex: i };
}
}
return { lastEvent: null, lastIndex: null };
}
/**
* Gets next entry in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @param {string} currentId
* @return {{ nextEvent: OntimeRundownEntry | null; nextIndex: number | null } }
@@ -64,6 +130,29 @@ export function getNext(
}
}
/**
* Gets next entry in rundown, if it exists
* @param rundown
* @param order
* @param currentId
* @returns
*/
export function getNextNormal(
rundown: NormalisedRundown,
order: string[],
currentId: string,
): { nextEvent: OntimeRundownEntry | null; nextIndex: number | null } {
const index = order.findIndex((id) => id === currentId);
if (index !== -1 && index + 1 < order.length) {
const nextIndex = index + 1;
const nextId = order[nextIndex];
const nextEvent = rundown[nextId];
return { nextEvent, nextIndex };
} else {
return { nextEvent: null, nextIndex: null };
}
}
/**
* Gets next scheduled event in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
@@ -89,7 +178,34 @@ export function getNextEvent(
}
/**
* Gets previous event in rundown, if it exists
* Gets next scheduled event in a normalised rundown, if it exists
* @param rundown
* @param order
* @param {string} currentId
* @return {{ nextEvent: OntimeEvent | null; nextIndex: number | null } }
*/
export function getNextEventNormal(
rundown: NormalisedRundown,
order: string[],
currentId: string,
): { nextEvent: OntimeEvent | null; nextIndex: number | null } {
const index = order.findIndex((id) => id === currentId);
if (index < 0) {
return { nextEvent: null, nextIndex: null };
}
for (let i = index + 1; i < order.length; i++) {
const nextId = order[i];
const nextEvent = rundown[nextId];
if (isOntimeEvent(nextEvent)) {
return { nextEvent, nextIndex: i };
}
}
return { nextEvent: null, nextIndex: null };
}
/**
* Gets previous entry in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
* @param {string} currentId
* @return {{ previousEvent: OntimeRundownEntry | null; previousIndex: number | null } }
@@ -108,6 +224,29 @@ export function getPrevious(
}
}
/**
* Gets previous entry in a nornalised rundown, if it exists
* @param rundown
* @param order
* @param {string} currentId
* @return {{ previousEvent: OntimeRundownEntry | null; previousIndex: number | null } }
*/
export function getPreviousNormal(
rundown: NormalisedRundown,
order: string[],
currentId: string,
): { previousEvent: OntimeRundownEntry | null; previousIndex: number | null } {
const index = order.findIndex((id) => id === currentId);
if (index !== -1 && index - 1 >= 0) {
const previousIndex = index - 1;
const previousId = order[previousIndex];
const previousEvent = rundown[previousId];
return { previousEvent, previousIndex };
} else {
return { previousEvent: null, previousIndex: null };
}
}
/**
* Gets previous scheduled event in rundown, if it exists
* @param {OntimeRundownEntry[]} rundown
@@ -132,41 +271,54 @@ export function getPreviousEvent(
}
/**
* @description swaps two OntimeEvents in the rundown
* @param {OntimeRundown} rundown
* @param {number} fromEventIndex
* @param {number} toEventIndex
* @returns {OntimeRundown}
* Gets previous scheduled event in a normalised rundown, if it exists
* @param rundown
* @param order
* @param {string} currentId
* @return {{ previousEvent: OntimeRundownEntry | null; previousIndex: number | null } }
*/
export const swapOntimeEvents = (
rundown: OntimeRundown,
fromEventIndex: number,
toEventIndex: number,
): OntimeRundown => {
const updatedRundown = [...rundown];
if (fromEventIndex < 0 || toEventIndex < 0) {
throw new Error('ID not found at index');
export function getPreviousEventNormal(
rundown: NormalisedRundown,
order: string[],
currentId: string,
): { previousEvent: OntimeEvent | null; previousIndex: number | null } {
const index = order.findIndex((id) => id === currentId);
if (index < 0) {
return { previousEvent: null, previousIndex: null };
}
for (let i = index - 1; i >= 0; i--) {
const previousId = order[i];
const previousEvent = rundown[previousId];
if (isOntimeEvent(previousEvent)) {
return { previousEvent, previousIndex: i };
}
}
return { previousEvent: null, previousIndex: null };
}
const fromEvent = updatedRundown.at(fromEventIndex) as OntimeEvent;
const toEvent = updatedRundown.at(toEventIndex) as OntimeEvent;
updatedRundown[fromEventIndex] = {
...toEvent,
timeStart: fromEvent.timeStart,
timeEnd: fromEvent.timeEnd,
duration: fromEvent.duration,
delay: fromEvent.delay,
/**
* @description swaps two OntimeEvents in the rundown
* @param {OntimeEvent} eventA
* @param {OntimeEvent} eventB
*/
export const swapEventData = (eventA: OntimeEvent, eventB: OntimeEvent): { newA: OntimeEvent; newB: OntimeEvent } => {
const newA = {
...eventB,
id: eventA.id,
timeStart: eventA.timeStart,
timeEnd: eventA.timeEnd,
duration: eventA.duration,
delay: eventA.delay,
};
updatedRundown[toEventIndex] = {
...fromEvent,
timeStart: toEvent.timeStart,
timeEnd: toEvent.timeEnd,
duration: toEvent.duration,
delay: toEvent.delay,
const newB = {
...eventA,
id: eventB.id,
timeStart: eventB.timeStart,
timeEnd: eventB.timeEnd,
duration: eventB.duration,
delay: eventB.delay,
};
return updatedRundown;
return { newA, newB };
};