UNPKG

@naturalcycles/js-lib

Version:

Standard library for universal (browser + Node.js) javascript

86 lines (85 loc) 2.58 kB
import { _average, _percentile, _percentiles } from './math.util.js'; /** * Implements a "round-robin" Stack ("first-in last-out" aka FILO) with a limited size. * Like an array of a fixed size. When it runs out of space - it starts writing on top of itself * from index 0. * * */ export class Stack { size; constructor(size) { this.size = size; } /** * Index of a slot to get written TO next. * Currently this slot contains OLDEST item (if any). */ nextIndex = 0; items = []; push(item) { this.items[this.nextIndex] = item; this.nextIndex = this.nextIndex === this.size - 1 ? 0 : this.nextIndex + 1; return this; } /** * Fill (overwrite) the whole Stack (all its items) with the passed `item`. */ fill(item) { for (let i = 0; i < this.size; i++) { this.items[i] = item; } return this; } /** * Returns last items in the right order. * Unlike raw `items` property that returns "items buffer" as-is (not ordered properly). */ get itemsOrdered() { if (this.items.length < this.size) { // Buffer is not filled yet, just return it as-is return this.items; } // Buffer was filled and started to "overwrite itself", will need to return 2 slices return [...this.items.slice(this.nextIndex), ...this.items.slice(0, this.nextIndex)]; } } /** * Fixed-size FILO stack of Numbers. * Has convenience stat methods, e.g percentile, avg, etc. */ export class NumberStack extends Stack { avg() { // _assert(this.items.length, 'NumberStack.avg cannot be called on empty stack') return _average(this.items); } /** * Returns null if Stack is empty. */ avgOrNull() { return this.items.length === 0 ? null : _average(this.items); } median() { return _percentile(this.items, 50); } medianOrNull() { return this.items.length === 0 ? null : _percentile(this.items, 50); } /** * `pc` is a number from 0 to 100 inclusive. */ percentile(pc) { // _assert(this.items.length, 'NumberStack.percentile cannot be called on empty stack') return _percentile(this.items, pc); } /** * `pc` is a number from 0 to 100 inclusive. * Returns null if Stack is empty. */ percentileOrNull(pc) { return this.items.length === 0 ? null : _percentile(this.items, pc); } percentiles(pcs) { return _percentiles(this.items, pcs); } }