UNPKG

@naturalcycles/js-lib

Version:

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

83 lines (82 loc) 2.58 kB
import { _average, _percentile, _percentiles, _range } from '../index'; /** * 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 { constructor(size) { this.size = size; /** * Index of a slot to get written TO next. * Currently this slot contains OLDEST item (if any). */ this.nextIndex = 0; this.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) { _range(this.size).forEach(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); } }