mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-18 05:34:09 +00:00
Fix/roll titles (#33)
Roll is now calculated with awareness of public and backstage titles Style improvements on providing feedback on roll mode
This commit is contained in:
@@ -43,7 +43,7 @@ More documentation available [here](https://cpvalente.gitbook.io/ontime/)
|
|||||||
- [x] Ability to differentiate between backstage and public data
|
- [x] Ability to differentiate between backstage and public data
|
||||||
- [x] Manage delays workflow
|
- [x] Manage delays workflow
|
||||||
- [x] OSC Control and Feedback
|
- [x] OSC Control and Feedback
|
||||||
- [x] Roll mode: run independently from system clock
|
- [x] Roll mode: run independently using the system clock
|
||||||
|
|
||||||
## Unopinionated
|
## Unopinionated
|
||||||
We are not interested in forcing workflows and have made ontime so it is flexible to whichever way you would like to work.
|
We are not interested in forcing workflows and have made ontime so it is flexible to whichever way you would like to work.
|
||||||
@@ -80,8 +80,6 @@ This will be receiving attention as we near v1 release
|
|||||||
- [ ] App appears visually broken: Please ensure that windows settings have no display zoom (it is 125% by default)
|
- [ ] App appears visually broken: Please ensure that windows settings have no display zoom (it is 125% by default)
|
||||||
- [ ] app needs improvement on handling zoomed interfaces
|
- [ ] app needs improvement on handling zoomed interfaces
|
||||||
- [ ] Very long titles might cause interface to shift
|
- [ ] Very long titles might cause interface to shift
|
||||||
#### Roll
|
|
||||||
- [ ] Roll feature does not understand difference between public and backstage titles
|
|
||||||
|
|
||||||
# Help
|
# Help
|
||||||
Help is underway! ... and can be viewed [here](https://cpvalente.gitbook.io/ontime/)
|
Help is underway! ... and can be viewed [here](https://cpvalente.gitbook.io/ontime/)
|
||||||
|
|||||||
@@ -18,10 +18,9 @@ export default function Info() {
|
|||||||
noteNext: '',
|
noteNext: '',
|
||||||
});
|
});
|
||||||
const [selected, setSelected] = useState('No events');
|
const [selected, setSelected] = useState('No events');
|
||||||
|
const [playback, setPlayback] = useState(null);
|
||||||
const logData = [];
|
const logData = [];
|
||||||
|
|
||||||
console.log(`titles`, titles);
|
|
||||||
|
|
||||||
// handle incoming messages
|
// handle incoming messages
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (socket == null) return;
|
if (socket == null) return;
|
||||||
@@ -34,6 +33,11 @@ export default function Info() {
|
|||||||
setTitles(data);
|
setTitles(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle playstate
|
||||||
|
socket.on('playstate', (data) => {
|
||||||
|
setPlayback(data);
|
||||||
|
});
|
||||||
|
|
||||||
// Ask for selection data
|
// Ask for selection data
|
||||||
socket.emit('get-selected');
|
socket.emit('get-selected');
|
||||||
|
|
||||||
@@ -53,6 +57,7 @@ export default function Info() {
|
|||||||
return () => {
|
return () => {
|
||||||
socket.off('titles');
|
socket.off('titles');
|
||||||
socket.off('selected');
|
socket.off('selected');
|
||||||
|
socket.off('playstate');
|
||||||
};
|
};
|
||||||
}, [socket]);
|
}, [socket]);
|
||||||
|
|
||||||
@@ -80,8 +85,8 @@ export default function Info() {
|
|||||||
</div>
|
</div>
|
||||||
{/* <InfoLogger logData={logData} /> */}
|
{/* <InfoLogger logData={logData} /> */}
|
||||||
<InfoNif />
|
<InfoNif />
|
||||||
<InfoTitle title={'Now'} data={titlesNow} />
|
<InfoTitle title={'Now'} data={titlesNow} roll={playback === 'roll'} />
|
||||||
<InfoTitle title={'Next'} data={titlesNext} />
|
<InfoTitle title={'Next'} data={titlesNext} roll={playback === 'roll'} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header,
|
||||||
|
.headerRoll {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
@@ -24,6 +25,14 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerRoll {
|
||||||
|
color: #2b6cb0;
|
||||||
|
}
|
||||||
|
|
||||||
.labelContainer {
|
.labelContainer {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import style from './Info.module.css';
|
|||||||
export default function InfoTitle(props) {
|
export default function InfoTitle(props) {
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(false);
|
||||||
|
|
||||||
const { title, data } = props;
|
const { title, data, roll } = props;
|
||||||
|
|
||||||
const noTitl = data.title == null || data.title === '';
|
const noTitl = data.title == null || data.title === '';
|
||||||
const noPres = data.presenter == null || data.presenter === '';
|
const noPres = data.presenter == null || data.presenter === '';
|
||||||
@@ -15,7 +15,7 @@ export default function InfoTitle(props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={style.container}>
|
<div className={style.container}>
|
||||||
<div className={style.header}>
|
<div className={roll ? style.headerRoll : style.header}>
|
||||||
{title}
|
{title}
|
||||||
<Icon
|
<Icon
|
||||||
className={collapsed ? style.moreCollapsed : style.moreExpanded}
|
className={collapsed ? style.moreCollapsed : style.moreExpanded}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ontime",
|
"name": "ontime",
|
||||||
"version": "0.1.3",
|
"version": "0.1.4",
|
||||||
"author": "Carlos Valente",
|
"author": "Carlos Valente",
|
||||||
"description": "Time keeping for live events",
|
"description": "Time keeping for live events",
|
||||||
"repository": "https://github.com/cpvalente/ontime",
|
"repository": "https://github.com/cpvalente/ontime",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Timer } from './Timer.js';
|
import { Timer } from './Timer.js';
|
||||||
import { Server } from 'socket.io';
|
import { Server } from 'socket.io';
|
||||||
|
import { getSelectionByRoll } from './classUtils.js';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EventTimer adds functions specific to APP
|
* EventTimer adds functions specific to APP
|
||||||
@@ -825,7 +826,7 @@ export class EventTimer extends Timer {
|
|||||||
noteNext: null,
|
noteNext: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.publicTitles = {
|
this.titlesPublic = {
|
||||||
titleNow: null,
|
titleNow: null,
|
||||||
subtitleNow: null,
|
subtitleNow: null,
|
||||||
presenterNow: null,
|
presenterNow: null,
|
||||||
@@ -961,83 +962,78 @@ export class EventTimer extends Timer {
|
|||||||
const now = this._getCurrentTime();
|
const now = this._getCurrentTime();
|
||||||
|
|
||||||
// maybe roll has already been loaded
|
// maybe roll has already been loaded
|
||||||
if (this.secondaryTimer == null) {
|
if (this.secondaryTimer === null) {
|
||||||
this._resetTimers(true);
|
this._resetTimers(true);
|
||||||
this._resetSelection();
|
this._resetSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
let foundNow = null;
|
const {
|
||||||
let nextIndex = null;
|
nowIndex,
|
||||||
let nextStart = null;
|
nowId,
|
||||||
|
publicIndex,
|
||||||
// loop through events, look for where we should be
|
nextIndex,
|
||||||
for (const [index, e] of this._eventlist.entries()) {
|
publicNextIndex,
|
||||||
if (!foundNow) {
|
timers,
|
||||||
let normalEnd = e.timeEnd;
|
timeToNext,
|
||||||
|
} = getSelectionByRoll(this._eventlist, now);
|
||||||
// handle midnight
|
|
||||||
if (normalEnd < e.timeStart) {
|
|
||||||
normalEnd += this.DAYMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.timeStart <= now && now < normalEnd) {
|
|
||||||
// set flag
|
|
||||||
foundNow = true;
|
|
||||||
|
|
||||||
// set timers
|
|
||||||
this.secondaryTimer = null;
|
|
||||||
this._secondaryTarget = null;
|
|
||||||
|
|
||||||
this._startedAt = e.timeStart;
|
|
||||||
this._finishAt = normalEnd;
|
|
||||||
this.duration = normalEnd - e.timeStart;
|
|
||||||
this.current = normalEnd - now;
|
|
||||||
|
|
||||||
// set selection
|
|
||||||
this.selectedEventId = e.id;
|
|
||||||
this.selectedEventIndex = index;
|
|
||||||
|
|
||||||
// set titles
|
|
||||||
this._loadTitlesNow();
|
|
||||||
|
|
||||||
// skip this entry for next
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// check how far the start is from now
|
|
||||||
let wait = e.timeStart - now;
|
|
||||||
if (wait > 0) {
|
|
||||||
if (nextStart == null || wait < nextStart) {
|
|
||||||
nextStart = wait;
|
|
||||||
nextIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// nothing to play, unload
|
// nothing to play, unload
|
||||||
if (foundNow == null && nextIndex == null) {
|
if (nowIndex === null && nextIndex === null) {
|
||||||
this.unload();
|
this.unload();
|
||||||
console.log('Roll: no events found');
|
console.log('Roll: no events found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we found something to play next
|
// there is something running, load
|
||||||
if (nextIndex != null) {
|
if (nowIndex !== null) {
|
||||||
const e = this._eventlist[nextIndex];
|
// clear secondary timers
|
||||||
this._loadThisTitles(e, 'next');
|
this.secondaryTimer = null;
|
||||||
|
this._secondaryTarget = null;
|
||||||
|
|
||||||
if (foundNow == null) {
|
// set timers
|
||||||
|
this._startedAt = timers._startedAt;
|
||||||
|
this._finishAt = timers._finishAt;
|
||||||
|
this.duration = timers.duration;
|
||||||
|
this.current = timers.current;
|
||||||
|
|
||||||
|
// set selection
|
||||||
|
this.selectedEventId = nowId;
|
||||||
|
this.selectedEventIndex = nowIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// found something to run next
|
||||||
|
if (nextIndex != null) {
|
||||||
|
// Set running timers
|
||||||
|
if (nowIndex === null) {
|
||||||
// only warn the first time
|
// only warn the first time
|
||||||
if (this.secondaryTimer == null)
|
if (this.secondaryTimer === null)
|
||||||
console.log('Roll: waiting for event start');
|
console.log('Roll: waiting for event start');
|
||||||
|
|
||||||
// reset running timer
|
// reset running timer
|
||||||
|
// ??? should this not have been reset?
|
||||||
this.current = null;
|
this.current = null;
|
||||||
|
|
||||||
// timer counts to nextStart
|
// timer counts to next event
|
||||||
this.secondaryTimer = nextStart;
|
this.secondaryTimer = timeToNext;
|
||||||
this._secondaryTarget = e.timeStart;
|
this._secondaryTarget = this._eventlist[nextIndex].timeStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TITLES: Load next private
|
||||||
|
this._loadThisTitles(this._eventlist[nextIndex], 'next-private');
|
||||||
|
}
|
||||||
|
|
||||||
|
// TITLES: Load next public
|
||||||
|
if (publicNextIndex !== null) {
|
||||||
|
this._loadThisTitles(this._eventlist[publicNextIndex], 'next-public');
|
||||||
|
}
|
||||||
|
|
||||||
|
// TITLES: Load now private
|
||||||
|
if (nowIndex !== null) {
|
||||||
|
this._loadThisTitles(this._eventlist[nowIndex], 'now-private');
|
||||||
|
}
|
||||||
|
// TITLES: Load now public
|
||||||
|
if (publicIndex !== null) {
|
||||||
|
this._loadThisTitles(this._eventlist[publicIndex], 'now-public');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,244 @@
|
|||||||
|
import { getSelectionByRoll, sortArrayByProperty } from '../classUtils.js';
|
||||||
|
|
||||||
|
// test sortArrayByProperty()
|
||||||
|
describe('sort simple arrays of objects', () => {
|
||||||
|
it('sort array 1-5', () => {
|
||||||
|
const arr1 = [
|
||||||
|
{ timeStart: 1 },
|
||||||
|
{ timeStart: 5 },
|
||||||
|
{ timeStart: 3 },
|
||||||
|
{ timeStart: 2 },
|
||||||
|
{ timeStart: 4 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const arr1Expected = [
|
||||||
|
{ timeStart: 1 },
|
||||||
|
{ timeStart: 2 },
|
||||||
|
{ timeStart: 3 },
|
||||||
|
{ timeStart: 4 },
|
||||||
|
{ timeStart: 5 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const sorted = sortArrayByProperty(arr1, 'timeStart');
|
||||||
|
expect(sorted).toStrictEqual(arr1Expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sort array 1-5 with null', () => {
|
||||||
|
const arr1 = [
|
||||||
|
{ timeStart: 1 },
|
||||||
|
{ timeStart: 5 },
|
||||||
|
{ timeStart: 3 },
|
||||||
|
{ timeStart: 2 },
|
||||||
|
{ timeStart: 4 },
|
||||||
|
{ timeStart: null },
|
||||||
|
];
|
||||||
|
|
||||||
|
const arr1Expected = [
|
||||||
|
{ timeStart: null },
|
||||||
|
{ timeStart: 1 },
|
||||||
|
{ timeStart: 2 },
|
||||||
|
{ timeStart: 3 },
|
||||||
|
{ timeStart: 4 },
|
||||||
|
{ timeStart: 5 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const sorted = sortArrayByProperty(arr1, 'timeStart');
|
||||||
|
expect(sorted).toStrictEqual(arr1Expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// test getSelectionByRoll()
|
||||||
|
describe('test that roll loads selection in right order', () => {
|
||||||
|
const eventlist = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
timeStart: 0,
|
||||||
|
timeEnd: 10,
|
||||||
|
isPublic: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
timeStart: 10,
|
||||||
|
timeEnd: 20,
|
||||||
|
isPublic: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
timeStart: 20,
|
||||||
|
timeEnd: 30,
|
||||||
|
isPublic: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
timeStart: 30,
|
||||||
|
timeEnd: 40,
|
||||||
|
isPublic: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
timeStart: 40,
|
||||||
|
timeEnd: 50,
|
||||||
|
isPublic: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
timeStart: 50,
|
||||||
|
timeEnd: 60,
|
||||||
|
isPublic: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
timeStart: 60,
|
||||||
|
timeEnd: 70,
|
||||||
|
isPublic: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
timeStart: 70,
|
||||||
|
timeEnd: 80,
|
||||||
|
isPublic: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
it('if timer is at 0', () => {
|
||||||
|
const now = 0;
|
||||||
|
const expected = {
|
||||||
|
nowIndex: 0,
|
||||||
|
nowId: 1,
|
||||||
|
publicIndex: null,
|
||||||
|
nextIndex: 1,
|
||||||
|
publicNextIndex: 1,
|
||||||
|
timers: {
|
||||||
|
_finishAt: 10,
|
||||||
|
_startedAt: 0,
|
||||||
|
current: 10,
|
||||||
|
duration: 10,
|
||||||
|
},
|
||||||
|
timeToNext: 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = getSelectionByRoll(eventlist, now);
|
||||||
|
expect(state).toStrictEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('if timer is at 15', () => {
|
||||||
|
const now = 15;
|
||||||
|
const expected = {
|
||||||
|
nowIndex: 1,
|
||||||
|
nowId: 2,
|
||||||
|
publicIndex: 1,
|
||||||
|
nextIndex: 2,
|
||||||
|
publicNextIndex: 4,
|
||||||
|
timers: {
|
||||||
|
_finishAt: 20,
|
||||||
|
_startedAt: 10,
|
||||||
|
current: 5,
|
||||||
|
duration: 10,
|
||||||
|
},
|
||||||
|
timeToNext: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = getSelectionByRoll(eventlist, now);
|
||||||
|
expect(state).toStrictEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('if timer is at 20', () => {
|
||||||
|
const now = 20;
|
||||||
|
const expected = {
|
||||||
|
nowIndex: 2,
|
||||||
|
nowId: 3,
|
||||||
|
publicIndex: 1,
|
||||||
|
nextIndex: 3,
|
||||||
|
publicNextIndex: 4,
|
||||||
|
timers: {
|
||||||
|
_startedAt: 20,
|
||||||
|
_finishAt: 30,
|
||||||
|
current: 10,
|
||||||
|
duration: 10,
|
||||||
|
},
|
||||||
|
timeToNext: 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = getSelectionByRoll(eventlist, now);
|
||||||
|
expect(state).toStrictEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('if timer is at 49', () => {
|
||||||
|
const now = 49;
|
||||||
|
const expected = {
|
||||||
|
nowIndex: 4,
|
||||||
|
nowId: 5,
|
||||||
|
publicIndex: 4,
|
||||||
|
nextIndex: 5,
|
||||||
|
publicNextIndex: 6,
|
||||||
|
timers: {
|
||||||
|
_startedAt: 40,
|
||||||
|
_finishAt: 50,
|
||||||
|
current: 1,
|
||||||
|
duration: 10,
|
||||||
|
},
|
||||||
|
timeToNext: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = getSelectionByRoll(eventlist, now);
|
||||||
|
expect(state).toStrictEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('if timer is at 63', () => {
|
||||||
|
const now = 63;
|
||||||
|
const expected = {
|
||||||
|
nowIndex: 6,
|
||||||
|
nowId: 7,
|
||||||
|
publicIndex: 6,
|
||||||
|
nextIndex: 7,
|
||||||
|
publicNextIndex: null,
|
||||||
|
timers: {
|
||||||
|
_startedAt: 60,
|
||||||
|
_finishAt: 70,
|
||||||
|
current: 7,
|
||||||
|
duration: 10,
|
||||||
|
},
|
||||||
|
timeToNext: 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = getSelectionByRoll(eventlist, now);
|
||||||
|
expect(state).toStrictEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('if timer is at 75', () => {
|
||||||
|
const now = 75;
|
||||||
|
const expected = {
|
||||||
|
nowIndex: 7,
|
||||||
|
nowId: 8,
|
||||||
|
publicIndex: 6,
|
||||||
|
nextIndex: null,
|
||||||
|
publicNextIndex: null,
|
||||||
|
timers: {
|
||||||
|
_startedAt: 70,
|
||||||
|
_finishAt: 80,
|
||||||
|
current: 5,
|
||||||
|
duration: 10,
|
||||||
|
},
|
||||||
|
timeToNext: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = getSelectionByRoll(eventlist, now);
|
||||||
|
expect(state).toStrictEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('if timer is at 100', () => {
|
||||||
|
const now = 100;
|
||||||
|
const expected = {
|
||||||
|
nowIndex: null,
|
||||||
|
nowId: null,
|
||||||
|
publicIndex: null,
|
||||||
|
nextIndex: null,
|
||||||
|
publicNextIndex: null,
|
||||||
|
timers: null,
|
||||||
|
timeToNext: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = getSelectionByRoll(eventlist, now);
|
||||||
|
expect(state).toStrictEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
/**
|
||||||
|
* @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 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');
|
||||||
|
|
||||||
|
// exit early if we are past the events
|
||||||
|
const lastEventEnd = orderedEvents[orderedEvents.length - 1].timeEnd;
|
||||||
|
if (now > lastEventEnd) {
|
||||||
|
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 =
|
||||||
|
e.timeEnd < e.timeStart ? (e.timeEnd += this.DAYMS) : 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) {
|
||||||
|
// 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: normalEnd,
|
||||||
|
duration: normalEnd - e.timeStart,
|
||||||
|
current: normalEnd - now,
|
||||||
|
};
|
||||||
|
} 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 (wait > 0) {
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user