V2 fix timer (#304)

This commit is contained in:
Carlos Valente
2023-02-28 19:50:37 +01:00
committed by GitHub
parent 99f4738f4a
commit 3e2626d4f9
9 changed files with 320 additions and 87 deletions
+60 -76
View File
@@ -5,6 +5,8 @@ import { PlaybackService } from './PlaybackService.js';
import { updateRoll } from './rollUtils.js';
import { DAY_TO_MS } from '../utils/time.js';
import { integrationService } from './integration-service/IntegrationService.js';
import { getCurrent, getElapsed, getExpectedFinish } from './timerUtils.js';
import { clock } from './Clock.js';
export class TimerService {
private readonly _interval: NodeJS.Timer;
@@ -12,19 +14,19 @@ export class TimerService {
playback: string;
loadedTimerId: null;
private _pausedInterval: number;
private _pausedAt: number | null;
private _secondaryTarget: number | null;
private pausedTime: number;
private pausedAt: number | null;
private secondaryTarget: number | null;
timer: {
clock: number;
current: number | null;
elapsed: number | null;
clock: number; // realtime clock
current: number | null; // running countdown
elapsed: number | null; // elapsed time in current timer
expectedFinish: number | null;
addedTime: number;
addedTime: number; // time added by user, can be negative
startedAt: number | null;
finishedAt: number | null;
secondaryTimer: number | null;
finishedAt: number | null; // only if timer has already finished
secondaryTimer: number | null; // used for roll mode
selectedEventId: string | null;
duration: number | null;
timerType: TimerType | null;
@@ -40,41 +42,6 @@ export class TimerService {
this._interval = setInterval(() => this.update(), timerConfig?.refresh || 1000);
}
/**
* Get current time in ms from midnight
* @static
* @return {number}
*/
static getCurrentTime() {
const now = new Date();
// extract milliseconds since midnight
let elapsed = now.getHours() * 3600000;
elapsed += now.getMinutes() * 60000;
elapsed += now.getSeconds() * 1000;
elapsed += now.getMilliseconds();
return elapsed;
}
/**
* Returns expected time finish
* @private
*/
_getExpectedFinish() {
if (this.timer.startedAt === null) {
return null;
}
if (this.timer.finishedAt) {
return this.timer.finishedAt;
}
return Math.max(
this.timer.startedAt + this.timer.duration + this._pausedInterval + this.timer.addedTime,
this.timer.startedAt,
);
}
/**
* Clears internal state
* @private
@@ -82,7 +49,7 @@ export class TimerService {
_clear() {
this.playback = 'stop';
this.timer = {
clock: TimerService.getCurrentTime(),
clock: clock.timeNow(),
current: null,
elapsed: null,
expectedFinish: null,
@@ -95,9 +62,9 @@ export class TimerService {
timerType: null,
};
this.loadedTimerId = null;
this._pausedInterval = 0;
this._pausedAt = null;
this._secondaryTarget = null;
this.pausedTime = 0;
this.pausedAt = null;
this.secondaryTarget = null;
}
/**
@@ -127,7 +94,13 @@ export class TimerService {
// this might not be ideal
this.timer.finishedAt = null;
this.timer.expectedFinish = this._getExpectedFinish();
this.timer.expectedFinish = getExpectedFinish(
this.timer.startedAt,
this.timer.finishedAt,
this.timer.duration,
this.pausedTime,
this.timer.addedTime,
);
if (this.timer.startedAt === null) {
this.timer.current = timer.duration;
}
@@ -157,8 +130,8 @@ export class TimerService {
this.timer.current = timer.duration;
this.playback = 'armed';
this.timer.timerType = timer.timerType;
this._pausedInterval = 0;
this._pausedAt = 0;
this.pausedTime = 0;
this.pausedAt = 0;
this._onLoad();
}
@@ -182,19 +155,25 @@ export class TimerService {
return;
}
this.timer.clock = TimerService.getCurrentTime();
this.timer.clock = clock.timeNow();
// add paused time
if (this._pausedInterval) {
this.timer.addedTime += this._pausedInterval;
this._pausedAt = null;
this._pausedInterval = 0;
if (this.pausedTime) {
this.timer.addedTime += this.pausedTime;
this.pausedAt = null;
this.pausedTime = 0;
} else {
this.timer.startedAt = this.timer.clock;
}
this.playback = 'play';
this.timer.expectedFinish = this._getExpectedFinish();
this.timer.expectedFinish = getExpectedFinish(
this.timer.startedAt,
this.timer.finishedAt,
this.timer.duration,
this.pausedTime,
this.timer.addedTime,
);
this._onStart();
}
@@ -214,8 +193,8 @@ export class TimerService {
}
this.playback = 'pause';
this.timer.clock = TimerService.getCurrentTime();
this._pausedAt = this.timer.clock;
this.timer.clock = clock.timeNow();
this.pausedAt = this.timer.clock;
this._onPause();
}
@@ -250,14 +229,12 @@ export class TimerService {
}
this.timer.addedTime += amount;
this.timer.current += amount;
this.timer.elapsed += amount;
// handle edge cases
if (amount < 0 && Math.abs(amount) > this.timer.current) {
if (this.timer.finishedAt === null) {
// if we will make the clock negative
this.timer.finishedAt = TimerService.getCurrentTime();
this.timer.finishedAt = clock.timeNow();
}
} else if (this.timer.current < 0 && this.timer.current + amount > 0) {
// clock will go from negative to positive
@@ -269,7 +246,7 @@ export class TimerService {
}
update() {
this.timer.clock = TimerService.getCurrentTime();
this.timer.clock = clock.timeNow();
if (this.playback === 'roll') {
const tempCurrentTimer = {
@@ -283,7 +260,7 @@ export class TimerService {
clock: this.timer.clock,
secondaryTimer: this.timer.secondaryTimer,
_secondaryTarget: this._secondaryTarget,
_secondaryTarget: this.secondaryTarget,
};
const { updatedTimer, updatedSecondaryTimer, doRollLoad, isFinished } = updateRoll(tempCurrentTimer);
@@ -303,45 +280,52 @@ export class TimerService {
// we only update timer if a timer has been started
if (this.timer.startedAt !== null) {
if (this.playback === 'pause') {
this._pausedInterval = this.timer.clock - this._pausedAt;
this.pausedTime = this.timer.clock - this.pausedAt;
}
this.timer.current =
this.timer.startedAt + this.timer.duration + this.timer.addedTime + this._pausedInterval - this.timer.clock;
this.timer.elapsed = this.timer.duration - this.timer.current;
if (this.playback === 'play' && this.timer.current <= 0 && this.timer.finishedAt === null) {
this.timer.finishedAt = this.timer.clock;
this._onFinish();
} else {
this.timer.finishedAt = null;
this.timer.expectedFinish = getExpectedFinish(
this.timer.startedAt,
this.timer.finishedAt,
this.timer.duration,
this.pausedTime,
this.timer.addedTime,
);
}
this.timer.expectedFinish = this._getExpectedFinish();
this.timer.current = getCurrent(
this.timer.startedAt,
this.timer.duration,
this.timer.addedTime,
this.pausedTime,
this.timer.clock,
);
this.timer.elapsed = getElapsed(this.timer.startedAt, this.timer.clock);
}
}
this._onUpdate();
}
_onUpdate() {
eventStore.set('playback', this.playback);
eventStore.set('timer', this.timer);
integrationService.dispatch(TimerLifeCycle.onUpdate);
}
_onFinish() {
eventStore.set('playback', this.playback);
eventStore.set('timer', this.timer);
integrationService.dispatch(TimerLifeCycle.onFinish);
}
roll(currentEvent, nextEvent, timers) {
this._clear();
this.timer.clock = TimerService.getCurrentTime();
this.timer.clock = clock.timeNow();
if (currentEvent) {
// there is something running, load
this.timer.secondaryTimer = null;
this._secondaryTarget = null;
this.secondaryTarget = null;
this.loadedTimerId = currentEvent.id;
this.timer.startedAt = currentEvent.timeStart;
@@ -351,7 +335,7 @@ export class TimerService {
} else if (nextEvent) {
// nothing now, but something coming up
this.timer.secondaryTimer = nextEvent.timeStart - this.timer.clock;
this._secondaryTarget = nextEvent.timeStart;
this.secondaryTarget = nextEvent.timeStart;
}
this.playback = 'roll';