interface Array { lastElement(): T; } // interface BatchContext { // completedBatches: number; // remainingBatches: number; // } // interface ExecutorResult { // updated: A; // makeNextBatch: boolean; // } // interface PredicateBatcherCommon { // initial: A; // persistAccumulator?: boolean; // } // interface Interval { // magnitude: number; // unit: typeof module.exports.TimeUnit; // } // type BatchConverterSync = (batch: I[], context: BatchContext) => O[]; // type BatchConverterAsync = (batch: I[], context: BatchContext) => Promise; // type BatchConverter = BatchConverterSync | BatchConverterAsync; // type BatchHandlerSync = (batch: I[], context: BatchContext) => void; // type BatchHandlerAsync = (batch: I[], context: BatchContext) => Promise; // type BatchHandler = BatchHandlerSync | BatchHandlerAsync; // type BatcherSync = FixedBatcher | PredicateBatcherSync; // type BatcherAsync = PredicateBatcherAsync; // type Batcher = BatcherSync | BatcherAsync; // type FixedBatcher = { batchSize: number } | { batchCount: number, mode?: typeof module.exports.Mode }; // type PredicateBatcherSync = PredicateBatcherCommon & { executor: (element: I, accumulator: A) => ExecutorResult }; // type PredicateBatcherAsync = PredicateBatcherCommon & { executorAsync: (element: I, accumulator: A) => Promise> }; // module.exports.Mode = { // Balanced: 0, // Even: 1 // }; // module.exports.TimeUnit = { // Milliseconds: 0, // Seconds: 1, // Minutes: 2 // }; // module.exports.Assign = function () { // Array.prototype.fixedBatch = function (batcher: FixedBatcher): T[][] { // const batches: T[][] = []; // const length = this.length; // let i = 0; // if ("batchSize" in batcher) { // const { batchSize } = batcher; // while (i < this.length) { // const cap = Math.min(i + batchSize, length); // batches.push(this.slice(i, i = cap)); // } // } else if ("batchCount" in batcher) { // let { batchCount, mode } = batcher; // const resolved = mode || module.exports.Mode.Balanced; // if (batchCount < 1) { // throw new Error("Batch count must be a positive integer!"); // } // if (batchCount === 1) { // return [this]; // } // if (batchCount >= this.length) { // return this.map((element: T) => [element]); // } // let length = this.length; // let size: number; // if (length % batchCount === 0) { // size = Math.floor(length / batchCount); // while (i < length) { // batches.push(this.slice(i, i += size)); // } // } else if (resolved === module.exports.Mode.Balanced) { // while (i < length) { // size = Math.ceil((length - i) / batchCount--); // batches.push(this.slice(i, i += size)); // } // } else { // batchCount--; // size = Math.floor(length / batchCount); // if (length % size === 0) { // size--; // } // while (i < size * batchCount) { // batches.push(this.slice(i, i += size)); // } // batches.push(this.slice(size * batchCount)); // } // } // return batches; // }; // Array.prototype.predicateBatch = function (batcher: PredicateBatcherSync): T[][] { // const batches: T[][] = []; // let batch: T[] = []; // const { executor, initial, persistAccumulator } = batcher; // let accumulator = initial; // for (let element of this) { // const { updated, makeNextBatch } = executor(element, accumulator); // accumulator = updated; // if (!makeNextBatch) { // batch.push(element); // } else { // batches.push(batch); // batch = [element]; // if (!persistAccumulator) { // accumulator = initial; // } // } // } // batches.push(batch); // return batches; // }; // Array.prototype.predicateBatchAsync = async function (batcher: BatcherAsync): Promise { // const batches: T[][] = []; // let batch: T[] = []; // const { executorAsync, initial, persistAccumulator } = batcher; // let accumulator: A = initial; // for (let element of this) { // const { updated, makeNextBatch } = await executorAsync(element, accumulator); // accumulator = updated; // if (!makeNextBatch) { // batch.push(element); // } else { // batches.push(batch); // batch = [element]; // if (!persistAccumulator) { // accumulator = initial; // } // } // } // batches.push(batch); // return batches; // }; // Array.prototype.batch = function (batcher: BatcherSync): T[][] { // if ("executor" in batcher) { // return this.predicateBatch(batcher); // } else { // return this.fixedBatch(batcher); // } // }; // Array.prototype.batchAsync = async function (batcher: Batcher): Promise { // if ("executorAsync" in batcher) { // return this.predicateBatchAsync(batcher); // } else { // return this.batch(batcher); // } // }; // Array.prototype.batchedForEach = function (batcher: BatcherSync, handler: BatchHandlerSync): void { // if (this.length) { // let completed = 0; // const batches = this.batch(batcher); // const quota = batches.length; // for (let batch of batches) { // const context: BatchContext = { // completedBatches: completed, // remainingBatches: quota - completed, // }; // handler(batch, context); // completed++; // } // } // }; // Array.prototype.batchedMap = function (batcher: BatcherSync, handler: BatchConverterSync): O[] { // if (!this.length) { // return []; // } // let collector: O[] = []; // let completed = 0; // const batches = this.batch(batcher); // const quota = batches.length; // for (let batch of batches) { // const context: BatchContext = { // completedBatches: completed, // remainingBatches: quota - completed, // }; // collector.push(...handler(batch, context)); // completed++; // } // return collector; // }; // Array.prototype.batchedForEachAsync = async function (batcher: Batcher, handler: BatchHandler): Promise { // if (this.length) { // let completed = 0; // const batches = await this.batchAsync(batcher); // const quota = batches.length; // for (let batch of batches) { // const context: BatchContext = { // completedBatches: completed, // remainingBatches: quota - completed, // }; // await handler(batch, context); // completed++; // } // } // }; // Array.prototype.batchedMapAsync = async function (batcher: Batcher, handler: BatchConverter): Promise { // if (!this.length) { // return []; // } // let collector: O[] = []; // let completed = 0; // const batches = await this.batchAsync(batcher); // const quota = batches.length; // for (let batch of batches) { // const context: BatchContext = { // completedBatches: completed, // remainingBatches: quota - completed, // }; // collector.push(...(await handler(batch, context))); // completed++; // } // return collector; // }; // Array.prototype.batchedForEachInterval = async function (batcher: Batcher, handler: BatchHandler, interval: Interval): Promise { // if (!this.length) { // return; // } // const batches = await this.batchAsync(batcher); // const quota = batches.length; // return new Promise(async resolve => { // const iterator = batches[Symbol.iterator](); // let completed = 0; // while (true) { // const next = iterator.next(); // await new Promise(resolve => { // setTimeout(async () => { // const batch = next.value; // const context: BatchContext = { // completedBatches: completed, // remainingBatches: quota - completed, // }; // await handler(batch, context); // resolve(); // }, convert(interval)); // }); // if (++completed === quota) { // break; // } // } // resolve(); // }); // }; // Array.prototype.batchedMapInterval = async function (batcher: Batcher, handler: BatchConverter, interval: Interval): Promise { // if (!this.length) { // return []; // } // let collector: O[] = []; // const batches = await this.batchAsync(batcher); // const quota = batches.length; // return new Promise(async resolve => { // const iterator = batches[Symbol.iterator](); // let completed = 0; // while (true) { // const next = iterator.next(); // await new Promise(resolve => { // setTimeout(async () => { // const batch = next.value; // const context: BatchContext = { // completedBatches: completed, // remainingBatches: quota - completed, // }; // collector.push(...(await handler(batch, context))); // resolve(); // }, convert(interval)); // }); // if (++completed === quota) { // resolve(collector); // break; // } // } // }); // }; Array.prototype.lastElement = function () { if (!this.length) { return undefined; } const last: T = this[this.length - 1]; return last; }; // }; // const convert = (interval: Interval) => { // const { magnitude, unit } = interval; // switch (unit) { // default: // case module.exports.TimeUnit.Milliseconds: // return magnitude; // case module.exports.TimeUnit.Seconds: // return magnitude * 1000; // case module.exports.TimeUnit.Minutes: // return magnitude * 1000 * 60; // } // };