@bazilio-san/af-stream
Version:
Data stream from database table
107 lines • 4.22 kB
JavaScript
import { c, rs } from './utils/color';
import { MILLIS_IN_DAY, MILLIS_IN_HOUR } from './constants';
import { millis2iso } from './utils/utils';
export class VirtualTimeObj {
constructor(options) {
this.locked = false;
this.lastVt = 0;
this.prevVirtualDateNumber = 0;
this.prevVirtualHourNumber = 0;
const { startTime, speed, loopTimeMillis = 0, eventEmitter, echo } = options;
this.options = options;
this.speed = Number(speed) || 1;
this.loopTimeMillis = loopTimeMillis;
this.virtualStartTs = +startTime; // timestamp millis from which to start uploading data
this.loopTimeMillsEnd = loopTimeMillis && (this.virtualStartTs + loopTimeMillis);
this.realStartTs = Date.now();
this.realStartTsLoopSafe = Date.now();
this.loopNumber = 0;
this.ready = false; // flag: all sources are ready to give data
this.isCurrentTime = false; // flag: virtual time has caught up with real time
this.eventEmitter = eventEmitter;
this.debug = echo ? echo.debug.bind(echo) : (m) => {
// eslint-disable-next-line no-console
console.log(m);
};
}
setVirtualNumbers(vt) {
this.lastVt = vt;
const { prevVirtualDateNumber: pvd, prevVirtualHourNumber: pvh } = this;
this.prevVirtualDateNumber = Math.floor(vt / MILLIS_IN_DAY);
if (pvd && pvd < this.prevVirtualDateNumber) {
const payload = {
prevN: pvd,
currN: this.prevVirtualDateNumber,
prevTs: pvd * MILLIS_IN_DAY,
currTs: this.prevVirtualDateNumber * MILLIS_IN_DAY,
};
this.eventEmitter.emit('virtual-date-changed', payload);
}
this.prevVirtualHourNumber = Math.floor(vt / MILLIS_IN_HOUR);
if (pvh && pvh !== this.prevVirtualHourNumber) {
const payload = {
prevN: pvh,
currN: this.prevVirtualHourNumber,
prevHZ: pvh % 24,
currHZ: this.prevVirtualHourNumber % 24,
prevTs: pvh * MILLIS_IN_HOUR,
currTs: this.prevVirtualHourNumber * MILLIS_IN_HOUR,
};
this.eventEmitter.emit('virtual-hour-changed', payload);
}
return vt;
}
lock() {
if (!this.locked) {
this.lastVt = this.getVirtualTs();
this.isCurrentTime = false;
this.locked = true;
}
}
unLock() {
if (this.locked) {
this.locked = false;
this.realStartTs = Date.now() - ((this.lastVt - this.virtualStartTs) / this.speed);
}
}
getVirtualTs() {
if (this.locked) {
return this.setVirtualNumbers(this.lastVt);
}
const now = Date.now();
const { isCurrentTime, virtualStartTs, realStartTs, speed, loopTimeMillis, loopTimeMillsEnd } = this;
if (isCurrentTime) {
return this.setVirtualNumbers(now);
}
let vt = virtualStartTs + (now - realStartTs) * speed;
if (loopTimeMillis && vt >= loopTimeMillsEnd) {
vt = virtualStartTs;
this.realStartTs = now;
this.loopNumber++;
this.debug(`[AF-STREAM]: New cycle from ${this.getString()}`);
this.eventEmitter.emit('virtual-time-loop-back');
return this.setVirtualNumbers(vt);
}
if (vt >= now) {
vt = now;
this.eventEmitter.emit('virtual-time-is-synchronized-with-current');
this.isCurrentTime = true;
}
return this.setVirtualNumbers(vt);
}
setReady() {
this.realStartTs = Date.now();
this.ready = true;
}
getString() {
return `${c}<${millis2iso(this.getVirtualTs())}${this.isCurrentTime ? '*' : ''}>${rs}`;
}
}
let virtualTimeObj;
export const getVirtualTimeObj = (options) => {
if (!virtualTimeObj) {
virtualTimeObj = new VirtualTimeObj(options);
}
return virtualTimeObj;
};
//# sourceMappingURL=VirtualTimeObj.js.map