86 lines
1.5 KiB
TypeScript
86 lines
1.5 KiB
TypeScript
"use strict";
|
|
// License: MIT
|
|
|
|
const NUM_VALUES = 20;
|
|
|
|
class Sequence {
|
|
protected readonly values: Uint32Array;
|
|
|
|
protected fill: number;
|
|
|
|
protected full: boolean;
|
|
|
|
constructor() {
|
|
this.values = new Uint32Array(NUM_VALUES);
|
|
}
|
|
|
|
get validValues() {
|
|
return this.full ? this.values : this.values.slice(0, this.fill);
|
|
}
|
|
|
|
get current() {
|
|
return this.fill ? this.values[this.fill - 1] : 0;
|
|
}
|
|
|
|
|
|
clear() {
|
|
this.fill = 0;
|
|
this.full = false;
|
|
}
|
|
|
|
add(value: number) {
|
|
if (!this.full) {
|
|
this.values[this.fill++] = value;
|
|
this.full = this.fill === NUM_VALUES;
|
|
}
|
|
else {
|
|
this.values.copyWithin(0, 1);
|
|
this.values[NUM_VALUES - 1] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class Stats extends Sequence {
|
|
public readonly avgs: Sequence;
|
|
|
|
public avg: number;
|
|
|
|
private lastTime: number;
|
|
|
|
constructor() {
|
|
super();
|
|
this.avgs = new Sequence();
|
|
this.clear();
|
|
Object.seal(this);
|
|
}
|
|
|
|
clear() {
|
|
super.clear();
|
|
this.avgs.clear();
|
|
this.avg = 0;
|
|
this.lastTime = 0;
|
|
}
|
|
|
|
add(value: number) {
|
|
const now = Date.now();
|
|
if (this.lastTime) {
|
|
const diff = now - this.lastTime;
|
|
value = (value / diff * 1000) | 0;
|
|
}
|
|
this.lastTime = now;
|
|
|
|
super.add(value);
|
|
|
|
const valid = this.validValues;
|
|
const cavg = valid.reduce((p, c) => p + c, 0) / valid.length;
|
|
if (this.avg < 1000) {
|
|
this.avg = cavg;
|
|
}
|
|
else {
|
|
// eslint-disable-next-line no-magic-numbers
|
|
this.avg = this.avg * 0.85 + cavg * 0.15;
|
|
}
|
|
this.avgs.add(this.avg);
|
|
}
|
|
}
|