diff --git a/lib/random/random.js b/lib/random/random.js index 8986d47..85794f2 100644 --- a/lib/random/random.js +++ b/lib/random/random.js @@ -8,32 +8,25 @@ const logger = require('../logging') class random { /** * Must be called before any other methods can be called to initialize MersenneTwister - * @param {number|null|undefined} seed - Value to initialize MersenneTwister + * @param {?number} seed - Value to initialize MersenneTwister */ - static init (seed) { - if (seed === null || seed === undefined) { - random.seed = new Date().getTime() - } else { - random.seed = seed + static init (seed = null) { + if (seed === null) { + seed = new Date().getTime() } - random.twister = new MersenneTwister() - random.twister.seed(random.seed) + random.twister.seed(seed) } /** * Returns an integer in [0, limit) (uniform distribution) * @param {number} limit */ - static number (limit) { + static number (limit = 0xffffffff) { if (!random.twister) { throw new Error('random.init must be called first.') } - if (limit === null || limit === undefined) { - limit = 0xffffffff - } - let x = (0x100000000 / limit) >>> 0 let y = (x * limit) >>> 0 let r @@ -151,43 +144,35 @@ class random { throw new TypeError(`random.choose() received non-array type: (${list})`) } - let total = 0 - for (let i = 0; i < list.length; i++) { - total += list[i][0] - } - - let n = random.number(total) - for (let i = 0; i < list.length; i++) { - if (n < list[i][0]) { - if (flat === true) { - return list[i][1] - } else { - return random.pick([list[i][1]]) - } + const expanded = [] + list.forEach(([weight, value]) => { + while (weight--) { + expanded.push(value) } - n = n - list[i][0] - } + }) if (flat) { - return list[0][1] + return random.item(expanded) } - return random.pick([list[0][1]]) + return random.pick(expanded) } /** - * More memory-hungry but hopefully faster than random.choose$flat. - * @param {*} wa + * Return a flattened list of weighted values + * [{w: 1, v: 'foo'}, {w: 1, v: 'bar'}] + * @param {Array} list + * @param {Array} */ - static weighted (wa) { - let a = [] - for (let i = 0; i < wa.length; ++i) { - for (let j = 0; j < wa[i].w; ++j) { - a.push(wa[i].v) + static weighted (list) { + const expanded = [] + list.forEach((item) => { + while (item.w--) { + expanded.push(item.v) } - } + }) - return a + return expanded } static use (obj) { diff --git a/lib/utils/common.js b/lib/utils/common.js index d35f2ef..3e26da8 100644 --- a/lib/utils/common.js +++ b/lib/utils/common.js @@ -1,50 +1,11 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +const entities = new (require('html-entities').XmlEntities)() const jsesc = require('jsesc') const utils = require('../utils') class common extends utils { - /** - * Return stringified object - * @param obj - * @returns {string} - */ - static objToString (obj) { - try { - return `${obj}` - } catch (e) { - return `[${e}]` - } - } - - /** - * Return enumerable properties recursively - * @param obj - * @returns {Array} - */ - static getAllProperties (obj) { - let list = [] - while (obj) { - list = list.concat(Object.getOwnPropertyNames(obj)) - obj = Object.getPrototypeOf(obj) - } - return list - } - - /** - * Return all properties (non-recursive) - * @param obj - * @returns {Array} - */ - static getKeysFromHash (obj) { - let list = [] - for (let p in obj) { - list.push(p) - } - return list - } - /** * Escape and quote a string * @param s - String to be quoted @@ -64,6 +25,19 @@ class common extends utils { } } + /** + * Remove quotes and escape sequence from string + * @param {string} s + * @returns {string} + */ + static unquote (s) { + return s.replace(/\\'/g, '\'') + .replace(/\\"/g, '"') + .replace(/\\0/g, '\0') + .replace(/\\\\/g, '\\') + .replace(/(^['|"])(.*)\1$/gm, '$2') + } + /** * Unicode safe b64 encoding * https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem @@ -75,7 +49,7 @@ class common extends utils { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function toSolidBytes (match, p1) { // noinspection JSCheckFunctionSignatures - return String.fromCharCode('0x' + p1) + return String.fromCharCode(`0x${p1}`) }) ) } else { @@ -99,21 +73,31 @@ class common extends utils { } } + /** + * Escape special characters using HTML entities + * @param {string} str + * @returns {string} + */ + static htmlEscape (str) { + return entities.encode(str) + } + + /** + * Remove HTML entities from string + * @param {string} str + * @returns {string} + */ + static htmlUnescape (str) { + return entities.decode(str) + } + /** * Remove duplicate items from a list * @param {Array} list * @returns {Array} */ static uniqueList (list) { - let tmp = {} - let r = [] - for (let i = 0; i < list.length; i++) { - tmp[list[i]] = list[i] - } - for (let i in tmp) { - r.push(tmp[i]) - } - return r + return list.filter((v, i, a) => a.indexOf(v) === i) } /** diff --git a/lib/utils/script.js b/lib/utils/script.js index 5a9ff80..e711b2b 100644 --- a/lib/utils/script.js +++ b/lib/utils/script.js @@ -80,36 +80,29 @@ class script extends utils { } static offset (s) { - return `(${s} % ${random.range(1, 3)})` - } - - static randListIndex (objName) { - return `${random.number()} % ${o.pick(objName)}.length` + return `(${random.number()} % ${s})` } /** * Wrap command(s) in setInterval, setTimeout, loop or run directly * @param {string|string[]} cmds - Command(s) to be executed - * @returns {string} + * @returns {array} */ static runner (cmds) { cmds = (Array.isArray(cmds)) ? cmds : [cmds] cmds = cmds.filter((i) => i !== undefined) if (cmds.length) { - if (random.chance(50)) { - // Wrap each command in try/catch for use in setInterval, setTimeout, repeater - switch (random.number(3)) { - case 0: - return `setInterval(function () { ${utils.script.safely(cmds)} }, ${random.range(100, 400)} )` - case 1: - return `setTimeout(function () { ${utils.script.safely(cmds)} }, ${random.range(100, 400)} )` - case 2: - let n = random.number(random.number(30)) - return `for (let i = 0; i < ${n}; i++) { ${utils.script.safely(cmds)} }` - } + // Wrap each command in try/catch for use in setInterval, setTimeout, repeater + switch (random.number(50)) { + case 0: + return [`setInterval(function () { ${script.safely(cmds)} }, ${random.range(100, 400)} )`] + case 1: + return [`setTimeout(function () { ${script.safely(cmds)} }, ${random.range(100, 400)} )`] + case 2: + return [`for (let i = 0; i < ${random.number(random.number(30))}; i++) { ${script.safely(cmds)} }`] + default: + return cmds } - - return utils.script.safely(cmds) } } diff --git a/package.json b/package.json index a4e3f0b..c4e4b6d 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,7 @@ "docs": "esdoc", "build": "webpack -p", "watch": "webpack --watch", - "precommit": "yarn lint", - "postinstall": "yarn build", + "prepush": "yarn lint", "release": "np" }, "standard": { @@ -80,6 +79,7 @@ "webpack-cli": "^3.1.0" }, "dependencies": { + "html-entities": "^1.2.1", "jsesc": "^2.5.1" } }