/* * For C# functions that use "params string[] rest" type arguments (where you can either pass in an array, * or keep passing in additional function arguments that will be placed into an array) * this function can be called, and given the "arguments" value as the first param, and the number of 'base' * function arguments as the second param, and it will return the aggregated array */ function restArgs(args, numArgs) { var ret = []; if (args.length == numArgs + 1 && Array.isArray(args[numArgs])) { ret = args[numArgs]; } else { ret = Array.apply(null, args).slice(numArgs); } return ret; } Object.defineProperty(Object.prototype, 'addRange', { enumerable: false, value: function(more) { for (var key of Object.keys(more)) { this[key] = more[key]; } } }); Object.defineProperty(Object.prototype, 'containsKey', { enumerable: false, value: function(key) { if (this[key] !== undefined) { return true; } return false; } }); // handy dandy function that SHOULD ALREADY EXIST IN THE ARRAY object, but doesn't because JAVASCRIPT HATES DEVELOPERS Object.defineProperty(Array.prototype, 'remove', { enumerable: false, value: function(elem) { var index = this.indexOf(elem); if (index != -1) { this.splice(index, 1); return true; } return false; } }); Object.defineProperty(Array.prototype, 'contains', { enumerable: false, value: function(elem) { return this.indexOf(elem) != -1; } }); Object.defineProperty(Array.prototype, 'any', { enumerable: false, value: function(func) { return this.some(func || function(x) { return x }); } }); Object.defineProperty(Array.prototype, 'getRandomElement', { enumerable: false, value: function() { return this.length == 0 ? null : this[Math.floor(Engine.Utils.randomDouble() * this.length)]; } }); Object.defineProperty(Array.prototype, 'last', { enumerable: false, value: function(func) { return this[this.length - 1]; } }); Object.defineProperty(Array.prototype, 'firstOrDefault', { enumerable: false, value: function(filter /*optional*/) { if (filter !== undefined && typeof filter === "function") { for (var i = 0; i < this.length; i++) { if (filter(this[i])) return this[i]; } return null; } return this.length == 0 ? null : this[0]; } }); Object.defineProperty(Array.prototype, 'lastOrDefault', { enumerable: false, value: function(filter /*optional*/) { if (filter !== undefined && typeof filter === "function") { for (var i = this.length - 1; i >= 0; i--) { if (filter(this[i])) return this[i]; } return null; } return this.length == 0 ? null : this[this.length - 1]; } }); Object.defineProperty(Array.prototype, 'flatten', { enumerable: false, value: function() { var ret = []; for (var i of this) { if (Array.isArray(i)) { for (var j of i) { ret.push(j); } } else { ret.push(i); } } return ret; } }); Object.defineProperty(Array.prototype, 'average', { enumerable: false, value: function(func) { if (this.length == 0) return undefined; var sum = 0; for (var i in this) { sum += (func === undefined) ? this[i] : func(this[i]); } return sum / this.length; } }); Object.defineProperty(Array.prototype, 'all', { enumerable: false, value: function(func) { for (var i = 0; i < this.length; i++) { if (!func(this[i])) return false; } return true; } }); Object.defineProperty(Array.prototype, 'none', { enumerable: false, value: function(func) { for (var i = 0; i < this.length; i++) { if (func(this[i])) return false; } return true; } }); Object.defineProperty(Array.prototype, 'max', { enumerable: false, value: function(func) { var max = Number.MIN_VALUE; if (this.length == 0) return 0; if (func === undefined) func = (v) => { return v;} for (var i = 0; i < this.length; i++) { var val = func(this[i]); if (val > max) max = val; } return max; } }); Object.defineProperty(Array.prototype, 'maxItem', { enumerable: false, value: function(func) { var max = Number.MIN_VALUE; var maxIndex = 0; if (this.length == 0) return null; if (func === undefined) func = (v) => { return v;} for (var i = 0; i < this.length; i++) { var val = func(this[i]); if (val > max) { maxIndex = i; max = val; } } return this[maxIndex]; } }); Object.defineProperty(Array.prototype, 'min', { enumerable: false, value: function(func) { var min = Number.MAX_VALUE; if (this.length == 0) return 0; if (func === undefined) func = (v) => { return v;} for (var i = 0; i < this.length; i++) { var val = func(this[i]); if (val < min) min = val; } return min; } }); Object.defineProperty(Array.prototype, 'sum', { enumerable: false, value: function(func) { var sum = 0; for (var i = 0; i < this.length; i++) { sum += func(this[i]); } return sum; } }); Object.defineProperty(Array.prototype, 'addRange', { enumerable: false, value: function(more) { if (Array.isArray(more)) { for (var i = 0; i < more.length; i++) { this.push(more[i]); } } else if (more instanceof Set) { this.addRange(more.values); } } }); Object.defineProperty(Array.prototype, 'removeRange', { enumerable: false, value: function(remove) { if (Array.isArray(remove)) { for (var i = 0; i < remove.length; i++) { var index = this.indexOf(remove[i]); if (index != -1) { this.splice(index, 1); } } } else if (remove instanceof Set) { this.removeRange(remove.values); } } }); String.prototype.replaceAll = function(search, replacement) { var target = this; return target.split(search).join(replacement); }; String.prototype.effectKey = function() { var target = this; return target.split(",")[0]; }; String.prototype.toCamelCase = function(firstUpper) { var target = this; if (firstUpper === undefined) firstUpper = true; var result = target.replace(/(?:^\w|[A-Z]|\b\w)/g, function(letter, index) { return index == 0 && !firstUpper ? letter.toLowerCase() : letter.toUpperCase(); }).replace(/\s+/g, ''); return result; }; String.prototype.toUnderlineCase = function(search, replacement) { var target = this; var toUnderlineCaseReg = /[^A-Z0-9][A-Z0-9]/g; return target.replace(toUnderlineCaseReg, match => [match.slice(0, 1), "_", match.slice(1)].join('')).toLowerCase(); }; Object.defineProperty(Array.prototype, 'distinct', { enumerable: false, value: function() { return this.filter((value, index, self) => self.indexOf(value) === index); } }); Object.defineProperty(Array.prototype, 'sortNum', { enumerable: false, value: function() { return this.sort((a, b) => a - b); } }); Number.isNumeric = function(n) { return !isNaN(parseFloat(n)) && isFinite(n); } Math.clamp = function(value, min, max) { return Math.min(Math.max(value, min), max); }; function isNumeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); } var CircularQueueStatics = {}; CircularQueueStatics.SizeMode = { Add:0, Mult:1 } class CircularQueue { constructor(startSize, sizeMode, increase) { if (startSize === undefined) startSize = 0; if (sizeMode === undefined) { sizeMode = CircularQueueStatics.SizeMode.Mult; increase = 2; } if (increase === undefined) { increase = 2; if (sizeMode == CircularQueueStatics.SizeMode.Add) increase = 50; } startSize = Math.max(0, startSize); this.startSize = this.startSize; this.backing = new Array(startSize); this.sizeMode = sizeMode; this.increase = increase; this.start = 0; this.end = 0; } get length() { return (this.end + this.backing.length - this.start) % this.backing.length; } enqueue(v) { if (this.length == this.backing.length) { var newSize = this.backing.length + 1; if (this.sizeMode == CircularQueueStatics.SizeMode.Add) { newSize = Math.max(newSize, this.backing.length + this.increase); } if (this.sizeMode == CircularQueueStatics.SizeMode.Mult) { newSize = Math.max(newSize, Math.ceil(this.backing.length * this.increase)); } var sizeIncrease = newSize - this.backing.length; var newBacking = new Array(newSize); if (this.end >= this.start) { for (var i = this.start; i < this.end; i++) { newBacking[i] = this.backing[i]; } } else { for (var i = this.start; i < this.backing.length; i++) { newBacking[i + sizeIncrease] = this.backing[i]; } for (var i = 0; i < this.end; i++) { newBacking[i] = this.backing[i]; } } this.backing = newBacking; } this.backing[this.end] = v; this.end = (this.end + 1) % this.backing.length; } dequeue() { if (this.length == 0) return undefined; var ret = this.backing[this.start]; this.start = (this.start + 1) % this.backing.length; return ret; } pop() { if (this.length == 0) return undefined; var ret = this.backing[this.end]; this.end = (this.end - 1 + this.backing.length) % this.backing.length; return ret; } clear(resetBackingSize) { if (resetBackingSize === undefined) resetBackingSize = false; if (typeof resetBackingSize == "boolean") { if (resetBackingSize) { this.backing = new Array(this.startSize); } } if (typeof resetBackingSize == "number") { this.startSize = Math.max(0, resetBackingSize); this.backing = new Array(this.startSize); } this.start = 0; this.end = 0; } get(index) { if (index < 0) return undefined; if (index >= this.length) return undefined; index = (this.start + index) % this.backing.length; return this.backing[index]; } }