From 2bc3edf8e56c623466abcb76f610cf103bbcd775 Mon Sep 17 00:00:00 2001 From: Androz2091 Date: Tue, 26 May 2020 17:52:19 +0200 Subject: [PATCH] collection rewrite --- utils/collection.ts | 249 ++++++++------------------------------------ utils/utils.ts | 4 + 2 files changed, 48 insertions(+), 205 deletions(-) diff --git a/utils/collection.ts b/utils/collection.ts index e23a107cf..98d4cf96f 100644 --- a/utils/collection.ts +++ b/utils/collection.ts @@ -1,239 +1,78 @@ -class Collection extends Map { - private _array!: V[] | null; - public static readonly default: typeof Collection = Collection; - public ["constructor"]: typeof Collection; +import { chooseRandom } from "./utils.ts"; - public constructor(entries?: ReadonlyArray | null) { - super(entries); - - Object.defineProperty( - this, - "_array", - { value: null, writable: true, configurable: true }, - ); - - Object.defineProperty( - this, - "_keyArray", - { value: null, writable: true, configurable: true }, - ); +export default class Collection extends Map { + array() { + return [...this.values()]; } - public get(key: K): V | undefined { - return super.get(key); + first() { + return this.values().next().value; } - public set(key: K, value: V): this { - this._array = null; - return super.set(key, value); + last() { + return [...this.values()][this.size - 1]; } - public has(key: K): boolean { - return super.has(key); + random() { + return chooseRandom([...this.values()]); } - public delete(key: K): boolean { - this._array = null; - return super.delete(key); - } - - public clear(): void { - return super.clear(); - } - - public array(): V[] { - if (!this._array || this._array.length !== this.size) { - this._array = [...this.values()]; + find(callback: (value: V, key: K) => boolean) { + for (const key of this.keys()) { + const value = this.get(key)!; + if (callback(value, key)) return value; } - return this._array; + // If nothing matched + return; } - public first(): V | undefined; - public first(amount: number): V[]; - public first(amount?: number): V | V[] | undefined { - if (typeof amount === "undefined") return this.values().next().value; - if (amount < 0) return this.last(amount * -1); - amount = Math.min(this.size, amount); - const iter = this.values(); - return Array.from({ length: amount }, (): V => iter.next().value); + filter(callback: (value: V, key: K) => boolean) { + const relevant = new Collection(); + this.forEach((value, key) => { + if (callback(value, key)) relevant.set(key, value); + }); + + return relevant; } - public last(): V | undefined; - public last(amount: number): V[]; - public last(amount?: number): V | V[] | undefined { - const arr = this.array(); - if (typeof amount === "undefined") return arr[arr.length - 1]; - if (amount < 0) return this.first(amount * -1); - if (!amount) return []; - return arr.slice(-amount); - } - - public random(): V; - public random(amount: number): V[]; - public random(amount?: number): V | V[] { - let arr = this.array(); - if ( - typeof amount === "undefined" - ) { - return arr[Math.floor(Math.random() * arr.length)]; - } - if (arr.length === 0 || !amount) return []; - arr = arr.slice(); - return Array.from( - { length: amount }, - (): V => arr.splice(Math.floor(Math.random() * arr.length), 1)[0], - ); - } - - public find( - fn: (value: V, key: K, collection: this) => boolean, - ): V | undefined; - public find( - fn: (this: T, value: V, key: K, collection: this) => boolean, - thisArg: T, - ): V | undefined; - public find( - fn: (value: V, key: K, collection: this) => boolean, - thisArg?: unknown, - ): V | undefined { - if (typeof thisArg !== "undefined") fn = fn.bind(thisArg); - for (const [key, val] of this) { - if (fn(val, key, this)) return val; - } - return undefined; - } - - public filter(fn: (value: V, key: K, collection: this) => boolean): this; - public filter( - fn: (this: T, value: V, key: K, collection: this) => boolean, - thisArg: T, - ): this; - public filter( - fn: (value: V, key: K, collection: this) => boolean, - thisArg?: unknown, - ): this { - if (typeof thisArg !== "undefined") fn = fn.bind(thisArg); - const results = new this.constructor[Symbol.species]() as this; - for (const [key, val] of this) { - if (fn(val, key, this)) results.set(key, val); + map(callback: (value: V, key: K) => T) { + const results = []; + for (const key of this.keys()) { + const value = this.get(key)!; + results.push(callback(value, key)); } return results; } - public map(fn: (value: V, key: K, collection: this) => T): T[]; - public map( - fn: (this: This, value: V, key: K, collection: this) => T, - thisArg: This, - ): T[]; - public map( - fn: (value: V, key: K, collection: this) => T, - thisArg?: unknown, - ): T[] { - if (typeof thisArg !== "undefined") fn = fn.bind(thisArg); - const iter = this.entries(); - return Array.from({ length: this.size }, (): T => { - const [key, value] = iter.next().value; - return fn(value, key, this); - }); - } - - public some(fn: (value: V, key: K, collection: this) => boolean): boolean; - public some( - fn: (this: T, value: V, key: K, collection: this) => boolean, - thisArg: T, - ): boolean; - public some( - fn: (value: V, key: K, collection: this) => boolean, - thisArg?: unknown, - ): boolean { - if (typeof thisArg !== "undefined") fn = fn.bind(thisArg); - for (const [key, val] of this) { - if (fn(val, key, this)) return true; + some(callback: (value: V, key: K) => boolean) { + for (const key of this.keys()) { + const value = this.get(key)!; + if (callback(value, key)) return true; } + return false; } - public every(fn: (value: V, key: K, collection: this) => boolean): boolean; - public every( - fn: (this: T, value: V, key: K, collection: this) => boolean, - thisArg: T, - ): boolean; - public every( - fn: (value: V, key: K, collection: this) => boolean, - thisArg?: unknown, - ): boolean { - if (typeof thisArg !== "undefined") fn = fn.bind(thisArg); - for (const [key, val] of this) { - if (!fn(val, key, this)) return false; + every(callback: (value: V, key: K) => boolean) { + for (const key of this.keys()) { + const value = this.get(key)!; + if (!callback(value, key)) return false; } + return true; } - public reduce( - fn: (accumulator: T, value: V, key: K, collection: this) => T, + reduce( + callback: (accumulator: T, value: V, key: K) => T, initialValue?: T, ): T { - let accumulator!: T; + let accumulator: T = initialValue!; - if (typeof initialValue !== "undefined") { - accumulator = initialValue; - for (const [key, val] of this) { - accumulator = fn(accumulator, val, key, this); - } - return accumulator; - } - let first = true; - for (const [key, val] of this) { - if (first) { - accumulator = val as unknown as T; - first = false; - continue; - } - accumulator = fn(accumulator, val, key, this); - } - - // No items iterated. - if (first) { - throw new TypeError("Reduce of empty collection with no initial value"); + for (const key of this.keys()) { + const value = this.get(key)!; + accumulator = callback(accumulator, value, key); } return accumulator; } - - public each(fn: (value: V, key: K, collection: this) => void): this; - public each( - fn: (this: T, value: V, key: K, collection: this) => void, - thisArg: T, - ): this; - public each( - fn: (value: V, key: K, collection: this) => void, - thisArg?: unknown, - ): this { - this.forEach(fn as (value: V, key: K, map: Map) => void, thisArg); - return this; - } - - public sort( - compareFunction: ( - firstValue: V, - secondValue: V, - firstKey: K, - secondKey: K, - ) => number = (x, y): number => Number(x > y) || Number(x === y) - 1, - ): this { - const entries = [...this.entries()]; - entries.sort((a, b): number => compareFunction(a[1], b[1], a[0], b[0])); - - // Perform clean-up - super.clear(); - this._array = null; - - // Set the new entries - for (const [k, v] of entries) { - super.set(k, v); - } - return this; - } } - -export default Collection; diff --git a/utils/utils.ts b/utils/utils.ts index 6dd3098a0..e3b5f4cca 100644 --- a/utils/utils.ts +++ b/utils/utils.ts @@ -13,3 +13,7 @@ export function editBotsStatus( ) { sendGatewayCommand("EDIT_BOTS_STATUS", { status, game: { name, type } }); } + +export function chooseRandom(array: T[]) { + return array[Math.floor(Math.random() * array.length)]; +}