mirror of
https://github.com/cpvalente/ontime.git
synced 2026-07-26 10:38:55 +00:00
refactor: declare timer phase
This commit is contained in:
committed by
Carlos Valente
parent
a53d354b16
commit
fd2eee32aa
@@ -1,5 +1,5 @@
|
||||
import isEqual from 'react-fast-compare';
|
||||
import { Playback, RuntimeStore, SimpleDirection, SimplePlayback } from 'ontime-types';
|
||||
import { Playback, RuntimeStore, SimpleDirection, SimplePlayback, TimerPhase } from 'ontime-types';
|
||||
import { createWithEqualityFn, useStoreWithEqualityFn } from 'zustand/traditional';
|
||||
|
||||
export const runtimeStorePlaceholder: RuntimeStore = {
|
||||
@@ -11,6 +11,7 @@ export const runtimeStorePlaceholder: RuntimeStore = {
|
||||
elapsed: null,
|
||||
expectedFinish: null,
|
||||
finishedAt: null,
|
||||
phase: TimerPhase.None,
|
||||
playback: Playback.Stop,
|
||||
secondaryTimer: null,
|
||||
startedAt: null,
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { MILLIS_PER_HOUR, dayInMs, millisToString } from 'ontime-utils';
|
||||
import { EndAction, OntimeEvent, Playback, TimeStrategy, TimerType } from 'ontime-types';
|
||||
import { EndAction, OntimeEvent, Playback, TimeStrategy, TimerPhase, TimerType } from 'ontime-types';
|
||||
|
||||
import {
|
||||
getCurrent,
|
||||
getExpectedFinish,
|
||||
getRollTimers,
|
||||
getRuntimeOffset,
|
||||
getTimerPhase,
|
||||
getTotalDuration,
|
||||
normaliseEndTime,
|
||||
skippedOutOfEvent,
|
||||
@@ -1756,3 +1757,97 @@ describe('getTotalDuration()', () => {
|
||||
expect(millisToString(duration)).toBe('62:00:00');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTimerPhase()', () => {
|
||||
it('should be None if the timer is not running', () => {
|
||||
const state = {
|
||||
timer: {
|
||||
addedTime: 0,
|
||||
current: null,
|
||||
duration: null,
|
||||
elapsed: null,
|
||||
expectedFinish: null,
|
||||
finishedAt: null,
|
||||
playback: Playback.Stop,
|
||||
phase: TimerPhase.None,
|
||||
secondaryTimer: null,
|
||||
startedAt: null,
|
||||
},
|
||||
} as RuntimeState;
|
||||
|
||||
const phase = getTimerPhase(state);
|
||||
expect(phase).toBe(TimerPhase.None);
|
||||
});
|
||||
|
||||
it('can be negative', () => {
|
||||
const state = {
|
||||
timer: {
|
||||
addedTime: 0,
|
||||
current: -50,
|
||||
duration: 1000,
|
||||
playback: Playback.Play,
|
||||
},
|
||||
eventNow: {
|
||||
timeDanger: 100,
|
||||
timeWarning: 200,
|
||||
},
|
||||
} as RuntimeState;
|
||||
|
||||
const phase = getTimerPhase(state);
|
||||
expect(phase).toBe(TimerPhase.Negative);
|
||||
});
|
||||
|
||||
it('can be danger', () => {
|
||||
const state = {
|
||||
timer: {
|
||||
addedTime: 0,
|
||||
current: 0,
|
||||
duration: 1000,
|
||||
playback: Playback.Play,
|
||||
},
|
||||
eventNow: {
|
||||
timeDanger: 100,
|
||||
timeWarning: 200,
|
||||
},
|
||||
} as RuntimeState;
|
||||
|
||||
const phase = getTimerPhase(state);
|
||||
expect(phase).toBe(TimerPhase.Danger);
|
||||
});
|
||||
|
||||
it('can be warning', () => {
|
||||
const state = {
|
||||
timer: {
|
||||
addedTime: 0,
|
||||
current: 150,
|
||||
duration: 1000,
|
||||
playback: Playback.Play,
|
||||
},
|
||||
eventNow: {
|
||||
timeDanger: 100,
|
||||
timeWarning: 200,
|
||||
},
|
||||
} as RuntimeState;
|
||||
|
||||
const phase = getTimerPhase(state);
|
||||
expect(phase).toBe(TimerPhase.Warning);
|
||||
});
|
||||
|
||||
it('it default if the timer is playing and there is none of the above', () => {
|
||||
const state = {
|
||||
timer: {
|
||||
addedTime: 0,
|
||||
current: 250,
|
||||
duration: 1000,
|
||||
playback: Playback.Play,
|
||||
},
|
||||
eventNow: {
|
||||
timeDanger: 100,
|
||||
timeWarning: 200,
|
||||
},
|
||||
} as RuntimeState;
|
||||
|
||||
const phase = getTimerPhase(state);
|
||||
expect(phase).toBe(TimerPhase.Default);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MaybeNumber, MaybeString, OntimeEvent, TimerType } from 'ontime-types';
|
||||
import { MaybeNumber, MaybeString, OntimeEvent, Playback, TimerPhase, TimerType } from 'ontime-types';
|
||||
import { dayInMs } from 'ontime-utils';
|
||||
import { RuntimeState } from '../stores/runtimeState.js';
|
||||
import { timerConfig } from '../config/config.js';
|
||||
@@ -361,3 +361,43 @@ export function getExpectedEnd(state: RuntimeState): MaybeNumber {
|
||||
}
|
||||
return state.runtime.plannedEnd - state.runtime.offset + state._timer.totalDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility checks whether the playback is considered to be active
|
||||
* @param state
|
||||
* @returns
|
||||
*/
|
||||
function isPlaybackActive(state: RuntimeState): boolean {
|
||||
return (
|
||||
state.timer.playback === Playback.Play ||
|
||||
state.timer.playback === Playback.Pause ||
|
||||
state.timer.playback === Playback.Roll
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks running timer to see which phase it currently is in
|
||||
* @param state
|
||||
*/
|
||||
export function getTimerPhase(state: RuntimeState): TimerPhase {
|
||||
if (!isPlaybackActive(state)) {
|
||||
return TimerPhase.None;
|
||||
}
|
||||
|
||||
const current = state.timer.current;
|
||||
if (current < 0) {
|
||||
return TimerPhase.Negative;
|
||||
}
|
||||
|
||||
const danger = state.eventNow.timeDanger;
|
||||
if (current <= danger) {
|
||||
return TimerPhase.Danger;
|
||||
}
|
||||
|
||||
const warning = state.eventNow.timeWarning;
|
||||
if (current <= warning) {
|
||||
return TimerPhase.Warning;
|
||||
}
|
||||
|
||||
return TimerPhase.Default;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MaybeNumber, OntimeEvent, Playback, Runtime, TimerState, TimerType } from 'ontime-types';
|
||||
import { MaybeNumber, OntimeEvent, Playback, Runtime, TimerPhase, TimerState, TimerType } from 'ontime-types';
|
||||
import { calculateDuration, dayInMs } from 'ontime-utils';
|
||||
|
||||
import { clock } from '../services/Clock.js';
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
getExpectedFinish,
|
||||
getRollTimers,
|
||||
getRuntimeOffset,
|
||||
getTimerPhase,
|
||||
skippedOutOfEvent,
|
||||
updateRoll,
|
||||
} from '../services/timerUtils.js';
|
||||
@@ -32,6 +33,7 @@ const initialTimer: TimerState = {
|
||||
elapsed: null,
|
||||
expectedFinish: null, // TODO: expected finish could account for midnight, we cleanup in the clients
|
||||
finishedAt: null,
|
||||
phase: TimerPhase.None,
|
||||
playback: Playback.Stop,
|
||||
secondaryTimer: null,
|
||||
startedAt: null,
|
||||
@@ -300,6 +302,10 @@ export function start(state: RuntimeState = runtimeState): boolean {
|
||||
state.runtime.actualStart = state.clock;
|
||||
}
|
||||
|
||||
// update timer phase
|
||||
runtimeState.timer.phase = getTimerPhase(runtimeState);
|
||||
|
||||
// update offset
|
||||
state.runtime.offset = getRuntimeOffset(state);
|
||||
state.runtime.expectedEnd = state.runtime.plannedEnd - state.runtime.offset;
|
||||
|
||||
@@ -387,6 +393,9 @@ export function update(): UpdateResult {
|
||||
runtimeState.timer.duration = runtimeState.timer.current;
|
||||
}
|
||||
|
||||
// update timer phase
|
||||
runtimeState.timer.phase = getTimerPhase(runtimeState);
|
||||
|
||||
// update offset
|
||||
runtimeState.runtime.offset = getRuntimeOffset(runtimeState);
|
||||
runtimeState.runtime.expectedEnd = getExpectedEnd(runtimeState);
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import type { MaybeNumber } from '../../index.js';
|
||||
import type { Playback } from './Playback.type.js';
|
||||
|
||||
export enum TimerPhase {
|
||||
None = 'none',
|
||||
Default = 'default',
|
||||
Warning = 'warning',
|
||||
Danger = 'danger',
|
||||
Negative = 'negative',
|
||||
}
|
||||
|
||||
export type TimerState = {
|
||||
addedTime: number; // time added by user, can be negative
|
||||
current: MaybeNumber; // running countdown
|
||||
@@ -8,6 +16,7 @@ export type TimerState = {
|
||||
elapsed: MaybeNumber; // elapsed time in current timer
|
||||
expectedFinish: MaybeNumber; // time we expect timer to finish
|
||||
finishedAt: MaybeNumber; // only if timer has already finished
|
||||
phase: TimerPhase;
|
||||
playback: Playback;
|
||||
secondaryTimer: MaybeNumber; // used for roll mode
|
||||
startedAt: MaybeNumber; // only if timer has already started
|
||||
|
||||
@@ -60,7 +60,7 @@ export type { Message, TimerMessage, MessageState } from './definitions/runtime/
|
||||
|
||||
export type { Runtime } from './definitions/runtime/Runtime.type.js';
|
||||
export type { RuntimeStore } from './definitions/runtime/RuntimeStore.type.js';
|
||||
export type { TimerState } from './definitions/runtime/TimerState.type.js';
|
||||
export { type TimerState, TimerPhase } from './definitions/runtime/TimerState.type.js';
|
||||
|
||||
// ---> Extra Timer
|
||||
export { type SimpleTimerState, SimplePlayback, SimpleDirection } from './definitions/runtime/AuxTimer.type.js';
|
||||
|
||||
Reference in New Issue
Block a user