From b2054fbef249c764735e0f05c3a88107db805e24 Mon Sep 17 00:00:00 2001 From: urielch Date: Mon, 4 Mar 2024 14:55:32 +0100 Subject: [PATCH 1/9] lint code + fix missing dep --- .gitignore | 4 +++- lib/hasard/abstract.js | 2 +- package.json | 1 + test/index.js | 2 +- test/issues.js | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 373c5df..5e9efa0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules package-lock.json -.DS_Store \ No newline at end of file +.DS_Store +.nyc_output +pnpm-lock.yaml diff --git a/lib/hasard/abstract.js b/lib/hasard/abstract.js index 4826253..c1da4d7 100644 --- a/lib/hasard/abstract.js +++ b/lib/hasard/abstract.js @@ -1,4 +1,4 @@ -const HasardReadableStream = require('../helpers/readable-stream.js'); +const HasardReadableStream = require('../helpers/readable-stream'); class AbstractHasard { constructor(...args) { diff --git a/package.json b/package.json index ff92e74..1f449ea 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "homepage": "https://github.com/piercus/hasard#readme", "devDependencies": { "ava": "^1.2.1", + "nyc": "^15.1.0", "semantic-release": "^15.13.3", "xo": "^0.24.0" } diff --git a/test/index.js b/test/index.js index 0e5cdd3..493671b 100644 --- a/test/index.js +++ b/test/index.js @@ -1,8 +1,8 @@ /* eslint no-new: "off" */ /* eslint ava/prefer-async-await: "off" */ const test = require('ava'); -const testDistribution = require('./helpers/test-distribution'); const hasard = require('..'); +const testDistribution = require('./helpers/test-distribution'); test('hasard.Value(Array.)', t => { const values = ['white', 'yellow']; diff --git a/test/issues.js b/test/issues.js index 2e41d93..11258bb 100644 --- a/test/issues.js +++ b/test/issues.js @@ -1,8 +1,8 @@ /* eslint no-new: "off" */ /* eslint ava/prefer-async-await: "off" */ const test = require('ava'); -const testDistribution = require('./helpers/test-distribution'); const hasard = require('..'); +const testDistribution = require('./helpers/test-distribution'); test('Avoid duplication of randomly selected value (#3)', t => { const choices = ['a', 'b', 'c']; From 210cca5dcfb1c229e706884716b497b26ba0d871 Mon Sep 17 00:00:00 2001 From: urielch Date: Mon, 4 Mar 2024 15:30:30 +0100 Subject: [PATCH 2/9] upgrate to test --- examples/random-object-generator.js | 12 +- examples/random-usa-users.js | 24 +-- index.js | 12 +- lib/hasard/abstract.js | 65 ++++---- lib/hasard/array.js | 52 +++--- lib/hasard/boolean.js | 20 +-- lib/hasard/function.js | 24 ++- lib/hasard/integer.js | 36 ++-- lib/hasard/matrix.js | 18 +- lib/hasard/number.js | 46 +++--- lib/hasard/object.js | 38 ++--- lib/hasard/reference.js | 48 +++--- lib/hasard/string.js | 6 +- lib/hasard/value.js | 43 ++--- lib/helpers/readable-stream.js | 10 +- lib/helpers/recursive-each.js | 10 +- lib/helpers/reshape.js | 28 ++-- lib/operators.js | 24 +-- package.json | 16 +- test/helpers/test-distribution.js | 11 +- test/index.js | 248 +++++++++++++--------------- test/issues.js | 14 +- 22 files changed, 391 insertions(+), 414 deletions(-) diff --git a/examples/random-object-generator.js b/examples/random-object-generator.js index 71ecbbf..d40bb99 100644 --- a/examples/random-object-generator.js +++ b/examples/random-object-generator.js @@ -1,4 +1,4 @@ -const h = require('..'); +const h = require('../index.js'); const randomValue = h.value(); @@ -6,19 +6,19 @@ const randomInteger = h.integer({type: 'poisson', lambda: 4}); const randomString = h.string({ size: h.add(randomInteger, 5), - value: h.value('abcdefghijklmnopkrstuvw'.split('')) + value: h.value('abcdefghijklmnopkrstuvw'.split('')), }); const randomNumber = h.number([0, 100]); const randomKeys = h.array({ size: randomInteger, - value: randomString + value: randomString, }); const randomObject = h.object( randomKeys, - randomValue + randomValue, ); randomValue.set({ @@ -26,8 +26,8 @@ randomValue.set({ randomString, randomObject, randomNumber, - randomInteger - ] + randomInteger, + ], }); console.log(JSON.stringify(randomObject.run(1), null, 2)); diff --git a/examples/random-usa-users.js b/examples/random-usa-users.js index 48528ee..540dbc8 100644 --- a/examples/random-usa-users.js +++ b/examples/random-usa-users.js @@ -1,4 +1,4 @@ -const h = require('..'); +const h = require('../index.js'); const givenNames = ['Veronica', 'Mercedes', @@ -252,7 +252,7 @@ const streets = [ ' Briarwood Drive', ' 2nd Avenue', ' Park Place', - ' Taylor Street' + ' Taylor Street', ]; const cityState = ['Warner, NH', @@ -315,18 +315,10 @@ const domainName = h.reference(h.value(domains)); const location = h.reference(h.value(cityState)); const street = h.reference(h.value(streets)); -const eMail = h.fn((a, b, c) => { - return a + '.' + b + '@invalid' + c; -}); -const preferredName = h.fn((a, b) => { - return a + '_' + b; -}); -const locality = h.fn(a => { - return (a.split(',')[0].trim()); -}); -const region = h.fn(a => { - return (a.split(',')[1].trim()); -}); +const eMail = h.fn((a, b, c) => a + '.' + b + '@invalid' + c); +const preferredName = h.fn((a, b) => a + '_' + b); +const locality = h.fn(a => (a.split(',')[0].trim())); +const region = h.fn(a => (a.split(',')[1].trim())); // User object /* eslint camelcase: ["error", {properties: "never"}] */ @@ -335,9 +327,9 @@ const user = h.object({ family_name: lastName, email: eMail(firstName, lastName, domainName), preferred_username: preferredName(firstName, lastName), - street: h.add(h.integer(100, 65535), street), + street: h.add(h.integer(100, 65_535), street), locality: locality(location), - region: region(location) + region: region(location), }); // Generate 10 random users and print to console diff --git a/index.js b/index.js index 397264e..af7e5be 100644 --- a/index.js +++ b/index.js @@ -12,13 +12,13 @@ const cstrs = { String: require('./lib/hasard/string'), Boolean: require('./lib/hasard/boolean'), Reference: require('./lib/hasard/reference'), - Function + Function, }; const shortcuts = {}; -Object.keys(cstrs).forEach(key => { +for (const key of Object.keys(cstrs)) { shortcuts[key.toLowerCase()] = cstrs[key].build.bind(cstrs[key], this); -}); +} const helpers = { isHasard: Abstract.isHasard, @@ -26,7 +26,7 @@ const helpers = { int: shortcuts.integer, num: shortcuts.number, str: shortcuts.string, - ref: shortcuts.reference + ref: shortcuts.reference, }; const methods = function (hasardContext) { @@ -37,9 +37,9 @@ class Hasard { constructor(prng = Math.random.bind(Math)) { this.prng = prng; const meths = methods(this); - Object.keys(meths).forEach(m => { + for (const m of Object.keys(meths)) { this[m] = meths[m].bind(this); - }); + } } } diff --git a/lib/hasard/abstract.js b/lib/hasard/abstract.js index c1da4d7..2e1b91b 100644 --- a/lib/hasard/abstract.js +++ b/lib/hasard/abstract.js @@ -1,38 +1,38 @@ const HasardReadableStream = require('../helpers/readable-stream'); class AbstractHasard { - constructor(...args) { + constructor(...arguments_) { this._hasard = true; - if (args.length === 0) { + if (arguments_.length === 0) { return; } - this.set(...args); + this.set(...arguments_); } - set(opts) { + set(options) { this._set = true; - this._opts = opts; - const all = this.getOpts(opts); + this._opts = options; + const all = this.getOpts(options); this._unresolved = {}; this._resolved = {}; - if (opts && (typeof (opts.prng) === 'function')) { - this._prng = opts.prng.bind(opts); + if (options && (typeof (options.prng) === 'function')) { + this._prng = options.prng.bind(options); } - this._contextName = opts && opts.contextName; - Object.keys(all).forEach(k => { + this._contextName = options && options.contextName; + for (const k of Object.keys(all)) { if (AbstractHasard.isHasard(all[k])) { this._unresolved[k] = all[k]; } else { this.check(k, all[k]); this._resolved[k] = all[k]; } - }); + } } - static build(hasardContext, ...args) { - const instance = new this(...args); + static build(hasardContext, ...arguments_) { + const instance = new this(...arguments_); if (hasardContext && hasardContext.prng) { hasardContext._prng = hasardContext.prng; } @@ -52,58 +52,59 @@ class AbstractHasard { return Promise.resolve(this.run(n)); } - stream(number, runOpts) { + stream(number, runOptions) { return new HasardReadableStream({ hasardInstance: this, number, - runOpts + runOpts: runOptions, }); } - resolve(unresolved, runOpts) { + resolve(unresolved, runOptions) { const ctxt = {}; - if (typeof (unresolved) === 'undefined') { + if ((unresolved) === undefined) { throw (new TypeError('This instance of hasard has not been set properly')); } - Object.keys(unresolved).forEach(k => { - ctxt[k] = unresolved[k].runOnce(runOpts); + for (const k of Object.keys(unresolved)) { + ctxt[k] = unresolved[k].runOnce(runOptions); this.check(k, ctxt[k]); - }); + } + return ctxt; } - _runOnce(runOpts) { - const ctxt = Object.assign({}, this.resolve(this._unresolved, runOpts), this._resolved); + _runOnce(runOptions) { + const ctxt = Object.assign({}, this.resolve(this._unresolved, runOptions), this._resolved); - const res = this.generate(ctxt, runOpts); - if (this._contextName && runOpts.refs && runOpts.refs[this._contextName]) { - delete runOpts.refs[this._contextName]; + const res = this.generate(ctxt, runOptions); + if (this._contextName && runOptions.refs && runOptions.refs[this._contextName]) { + delete runOptions.refs[this._contextName]; } return res; } - run(n, runOpts) { + run(n, runOptions) { const res = []; for (let i = 0; i < n; i++) { - res.push(this.runOnce(runOpts)); + res.push(this.runOnce(runOptions)); } return res; } - runOnce(runOpts = {}) { - return this._runOnce(runOpts); + runOnce(runOptions = {}) { + return this._runOnce(runOptions); } generate() { throw (new Error('override me')); } - getOpts(opts) { - delete opts.prng; - return opts; + getOpts(options) { + delete options.prng; + return options; } check() { diff --git a/lib/hasard/array.js b/lib/hasard/array.js index 20fc234..2ddcba6 100644 --- a/lib/hasard/array.js +++ b/lib/hasard/array.js @@ -2,78 +2,76 @@ const AbstractHasard = require('./abstract'); class ArrayHasard extends AbstractHasard { check(key, value) { - if (key === 'values' && value !== null && typeof (value) !== 'undefined') { - if (!Array.isArray(value)) { - throw (new TypeError(`${key} ${value} must be an array`)); - } + if (key === 'values' && value !== null && (value) !== undefined && !Array.isArray(value)) { + throw (new TypeError(`${key} ${value} must be an array`)); } } - resolve(unresolved, runOpts) { + resolve(unresolved, runOptions) { // Do not resolve "value" here, it will be resolved in generate const overrideUnresolved = Object.assign({}, unresolved); delete overrideUnresolved.value; - return Object.assign(super.resolve(overrideUnresolved, runOpts), {value: unresolved.value}); + return Object.assign(super.resolve(overrideUnresolved, runOptions), {value: unresolved.value}); } - getOpts(opts) { + getOpts(options) { let values = null; let size; let value; let randomOrder; - if (Array.isArray(opts)) { - values = opts; + if (Array.isArray(options)) { + values = options; size = values.length; value = null; randomOrder = false; } else { - size = opts.size; - values = opts.values; - value = opts.value; - randomOrder = opts.randomOrder; + size = options.size; + values = options.values; + value = options.value; + randomOrder = options.randomOrder; } return { size, value, values, - randomOrder + randomOrder, }; } - generate(ctx, runOpts) { - if (ArrayHasard.isHasard(ctx.value)) { - return new Array(ctx.size).fill(1).map(() => ctx.value.runOnce(runOpts)); + generate(context, runOptions) { + if (ArrayHasard.isHasard(context.value)) { + return new Array(context.size).fill(1).map(() => context.value.runOnce(runOptions)); } - if (ctx.values) { + if (context.values) { let newValues; - if (typeof (ctx.size) === 'number' || ctx.randomOrder) { - const size = typeof (ctx.size) === 'number' ? ctx.size : ctx.values.length; + if (typeof (context.size) === 'number' || context.randomOrder) { + const size = typeof (context.size) === 'number' ? context.size : context.values.length; - if (size > ctx.values.length) { - throw (new Error(`Cannot pick ${size} elements in ${ctx.values.length}-size array`)); + if (size > context.values.length) { + throw (new Error(`Cannot pick ${size} elements in ${context.values.length}-size array`)); } - let selectedObjs = ctx.values + let selectedObjs = context.values .map((v, i) => ({strength: this.prng(), value: v, index: i})) .sort((a, b) => a.strength - b.strength) .slice(0, size); - if (!ctx.randomOrder) { + if (!context.randomOrder) { selectedObjs = selectedObjs.sort((a, b) => a.index - b.index); } newValues = selectedObjs.map(({value}) => value); } else { - newValues = ctx.values; + newValues = context.values; } return newValues.map(v => { if (ArrayHasard.isHasard(v)) { - const res = v.runOnce(runOpts); + const res = v.runOnce(runOptions); return res; } @@ -81,7 +79,7 @@ class ArrayHasard extends AbstractHasard { }); } - return new Array(ctx.size).fill(1).map(() => ctx.value); + return new Array(context.size).fill(1).map(() => context.value); } } diff --git a/lib/hasard/boolean.js b/lib/hasard/boolean.js index 846990f..6dab6f6 100644 --- a/lib/hasard/boolean.js +++ b/lib/hasard/boolean.js @@ -1,13 +1,13 @@ const AbstractHasard = require('./abstract'); class BooleanHasard extends AbstractHasard { - constructor(...args) { - super(...args); - if (args.length === 0) { - return this.set(0.5); + constructor(...arguments_) { + super(...arguments_); + if (arguments_.length === 0) { + this.set(0.5); + } else { + this.set(...arguments_); } - - this.set(...args); } check(key, value) { @@ -24,16 +24,16 @@ class BooleanHasard extends AbstractHasard { getOpts(prob = 0.5) { return { - prob + prob, }; } - generate(ctx) { - if (typeof (ctx.prob) !== 'number') { + generate(context) { + if (typeof (context.prob) !== 'number') { return (this.prng() > 0.5); } - return (this.prng() < ctx.prob); + return (this.prng() < context.prob); } } diff --git a/lib/hasard/function.js b/lib/hasard/function.js index 3bd765c..d5c4b55 100644 --- a/lib/hasard/function.js +++ b/lib/hasard/function.js @@ -3,33 +3,29 @@ const RandomArray = require('./array'); class FunctionHasard extends AbstractHasard { check(key, value) { - if (key === 'fn') { - if (typeof (value) !== 'function') { - throw (new TypeError(`${key} ${value} must be a function`)); - } + if (key === 'fn' && typeof (value) !== 'function') { + throw (new TypeError(`${key} ${value} must be a function`)); } - if (key === 'args') { - if (value && !Array.isArray(value)) { - throw (new TypeError(`${key} ${value} must be an array`)); - } + if (key === 'args' && value && !Array.isArray(value)) { + throw (new TypeError(`${key} ${value} must be an array`)); } } getOpts({args, fn}) { return { args, - fn + fn, }; } - generate(ctx) { - return ctx.fn(...ctx.args); + generate(context) { + return context.fn(...context.args); } - static build(hasardContext, fn) { - return function (...args) { - const f = new FunctionHasard({args: new RandomArray(args), fn}); + static build(hasardContext, function_) { + return function (...arguments_) { + const f = new FunctionHasard({args: new RandomArray(arguments_), fn: function_}); if (hasardContext && hasardContext.prng) { f._prng = hasardContext.prng; } diff --git a/lib/hasard/integer.js b/lib/hasard/integer.js index 2f5f4c4..f5a33f8 100644 --- a/lib/hasard/integer.js +++ b/lib/hasard/integer.js @@ -1,20 +1,18 @@ -const AbstractHasard = require('./abstract'); +const AbstractHasard = require('./abstract.js'); class IntegerHasard extends AbstractHasard { check(key, value) { - if (key === 'start' || key === 'end') { - if (Math.floor(value) !== value) { - throw (new TypeError(`${key} (${value}) must be an integer`)); - } + if ((key === 'start' || key === 'end') && Math.floor(value) !== value) { + throw (new TypeError(`${key} (${value}) must be an integer`)); } - if (key === 'type' && ['poisson', 'uniform'].indexOf(value) === -1) { + if (key === 'type' && !['poisson', 'uniform'].includes(value)) { throw (new TypeError(`${key} ${value} is invalid`)); } } set(start, end) { - if (typeof (end) === 'undefined') { + if ((end) === undefined) { super.set(start); } else if (typeof (end) === 'number' || this.constructor.isHasard(end)) { super.set([start, end]); @@ -23,27 +21,27 @@ class IntegerHasard extends AbstractHasard { } } - getOpts(opts) { - if (Array.isArray(opts)) { - if (opts.length !== 2) { - throw (new TypeError(`${opts} must be a length-2 array`)); + getOpts(options) { + if (Array.isArray(options)) { + if (options.length !== 2) { + throw (new TypeError(`${options} must be a length-2 array`)); } - const start = opts[0]; - const end = opts[1]; + const start = options[0]; + const end = options[1]; return { start, end, - type: 'uniform' + type: 'uniform', }; } - return opts; + return options; } - generate(ctx) { - if (ctx.type === 'poisson') { - const l = Math.exp(-ctx.lambda); + generate(context) { + if (context.type === 'poisson') { + const l = Math.exp(-context.lambda); let p = 1; let k = 0; @@ -55,7 +53,7 @@ class IntegerHasard extends AbstractHasard { return k - 1; } - return Math.floor(ctx.start + (this.prng() * (ctx.end + 1 - ctx.start))); + return Math.floor(context.start + (this.prng() * (context.end + 1 - context.start))); } } diff --git a/lib/hasard/matrix.js b/lib/hasard/matrix.js index f83b27e..1ce7abf 100644 --- a/lib/hasard/matrix.js +++ b/lib/hasard/matrix.js @@ -21,23 +21,23 @@ class MatrixHasard extends ArrayHasard { throw (new Error(`${key} (${value}) should not be empty`)); } - value.forEach(v => { + for (const v of value) { if (Math.floor(v) !== v) { throw (new Error(`${key} (${v}) must be an integer`)); } - }); + } } } - getOpts(opts) { - return Object.assign({}, super.getOpts(opts), {shape: opts.shape}); + getOpts(options) { + return Object.assign({}, super.getOpts(options), {shape: options.shape}); } - generate(ctx, runOpts) { - const size = fact(ctx.shape); - const ctx2 = Object.assign({}, ctx, {size}); - const resArray = super.generate(ctx2, runOpts); - return reshape(resArray, [size], ctx.shape); + generate(context, runOptions) { + const size = fact(context.shape); + const context2 = Object.assign({}, context, {size}); + const resArray = super.generate(context2, runOptions); + return reshape(resArray, [size], context.shape); } } diff --git a/lib/hasard/number.js b/lib/hasard/number.js index b2fca20..f3094b1 100644 --- a/lib/hasard/number.js +++ b/lib/hasard/number.js @@ -1,20 +1,18 @@ -const AbstractHasard = require('./abstract'); +const AbstractHasard = require('./abstract.js'); class NumberHasard extends AbstractHasard { check(key, value) { - if (key === 'start' || key === 'end') { - if (typeof (value) !== 'number') { - throw (new TypeError(`${key} (${value}) must be a number`)); - } + if ((key === 'start' || key === 'end') && typeof (value) !== 'number') { + throw (new TypeError(`${key} (${value}) must be a number`)); } - if (key === 'type' && ['normal', 'uniform', 'truncated-normal'].indexOf(value) === -1) { + if (key === 'type' && !['normal', 'uniform', 'truncated-normal'].includes(value)) { throw (new TypeError(`${key} ${value} is invalid`)); } } set(start, end) { - if (typeof (end) === 'undefined') { + if ((end) === undefined) { super.set(start); } else if (typeof (end) === 'number' || this.constructor.isHasard(end)) { super.set([start, end]); @@ -23,21 +21,21 @@ class NumberHasard extends AbstractHasard { } } - getOpts(opts) { - let res = opts; + getOpts(options) { + let res = options; - if (Array.isArray(opts)) { - if (opts.length !== 2) { + if (Array.isArray(options)) { + if (options.length !== 2) { throw (new TypeError('invalid array, range array length must be 2')); } res = { type: 'uniform', - start: opts[0], - end: opts[1] + start: options[0], + end: options[1], }; } else { - res = opts; + res = options; } return res; @@ -61,20 +59,20 @@ class NumberHasard extends AbstractHasard { return mean + (std * Math.sqrt(-2 * Math.log(s) / s) * v1); } - generate(ctx) { - if (ctx.type === 'uniform') { - return ctx.start + (this.prng() * (ctx.end - ctx.start)); + generate(context) { + if (context.type === 'uniform') { + return context.start + (this.prng() * (context.end - context.start)); } - if (ctx.type === 'normal') { - const mean = ctx.mean || 0; - const std = ctx.std || 1; + if (context.type === 'normal') { + const mean = context.mean || 0; + const std = context.std || 1; return this._pickNormalNumber(mean, std); } - if (ctx.type === 'truncated-normal') { - const mean = ctx.mean || 0; - const std = ctx.std || 1; + if (context.type === 'truncated-normal') { + const mean = context.mean || 0; + const std = context.std || 1; let n; do { n = this._pickNormalNumber(mean, std); @@ -83,7 +81,7 @@ class NumberHasard extends AbstractHasard { return n; } - throw (new Error(`type ${ctx.type} is invalid`)); + throw (new Error(`type ${context.type} is invalid`)); } } diff --git a/lib/hasard/object.js b/lib/hasard/object.js index 9c25329..d9f3b61 100644 --- a/lib/hasard/object.js +++ b/lib/hasard/object.js @@ -3,7 +3,7 @@ const AbstractHasard = require('./abstract'); class ObjectHasard extends AbstractHasard { set(keys, value) { if (ObjectHasard.isHasard(keys) || Array.isArray(keys)) { - if (typeof (value) === 'undefined') { + if ((value) === undefined) { throw (new TypeError('h.object(keys, value) should have a value param')); } @@ -16,13 +16,13 @@ class ObjectHasard extends AbstractHasard { } check(key, value) { - if (key === '__hasardKeys' && value !== null && typeof (value) !== 'undefined') { + if (key === '__hasardKeys' && value !== null && (value) !== undefined) { const k = 'keys'; if (!Array.isArray(value)) { throw (new TypeError(`${k} ${value} must be an array`)); } - value.forEach((v, index) => { + for (const [index, v] of value.entries()) { // Check unicity if (value.indexOf(v) !== index) { throw (new TypeError(`keys must be unique (${k}[${index}] '${v}' is duplicated)`)); @@ -32,43 +32,39 @@ class ObjectHasard extends AbstractHasard { if (typeof (v) !== 'string') { throw (new TypeError(`keys must be string array (${k}[${index}] '${v}' should be a string)`)); } - }); + } } } - getOpts(opts) { - const res = Object.assign({}, opts, {__hasardKeys: opts.__hasardKeys, __hasardValue: opts.__hasardValue}); + getOpts(options) { + const res = Object.assign({}, options, {__hasardKeys: options.__hasardKeys, __hasardValue: options.__hasardValue}); return res; } - resolve(unresolved, runOpts) { + resolve(unresolved, runOptions) { // Do not resolve "value" here, it will be resolved in generate const overrideUnresolved = Object.assign({}, unresolved); delete overrideUnresolved.__hasardValue; - const res = Object.assign(super.resolve(overrideUnresolved, runOpts), {__hasardValue: unresolved.__hasardValue}); + const res = Object.assign(super.resolve(overrideUnresolved, runOptions), {__hasardValue: unresolved.__hasardValue}); return res; } - generate(ctx, runOpts) { - if (ctx.__hasardKeys) { + generate(context, runOptions) { + if (context.__hasardKeys) { // Console.log('here', ctx, this.constructor.isHasard(ctx.__hasardValue), ctx.__hasardValue) - let values; - if (this.constructor.isHasard(ctx.__hasardValue)) { - values = ctx.__hasardValue.run(ctx.__hasardKeys.length, runOpts); - } else { - values = new Array(ctx.__hasardKeys.length).fill(ctx.__hasardValue); - } + const values = this.constructor.isHasard(context.__hasardValue) ? context.__hasardValue.run(context.__hasardKeys.length, runOptions) : Array.from({length: context.__hasardKeys.length}).fill(context.__hasardValue); const res = {}; - ctx.__hasardKeys.forEach((k, index) => { + for (const [index, k] of context.__hasardKeys.entries()) { res[k] = values[index]; - }); + } + return res; } - delete ctx.__hasardKeys; - delete ctx.__hasardValue; - return ctx; + delete context.__hasardKeys; + delete context.__hasardValue; + return context; } } diff --git a/lib/hasard/reference.js b/lib/hasard/reference.js index 8300297..cd29aa0 100644 --- a/lib/hasard/reference.js +++ b/lib/hasard/reference.js @@ -3,68 +3,64 @@ const RandomString = require('./string'); const RandomValue = require('./value'); class ReferenceHasard extends AbstractHasard { - resolve(unresolved, runOpts) { + resolve(unresolved, runOptions) { // Do not resolve "source" here, it will be resolved in generate const overrideUnresolved = Object.assign({}, unresolved); delete overrideUnresolved.source; - return Object.assign(super.resolve(overrideUnresolved, runOpts), {source: unresolved.source}); + return Object.assign(super.resolve(overrideUnresolved, runOptions), {source: unresolved.source}); } - generate({id, context, source}, runOpts) { + generate({id, context, source}, runOptions) { if (!this.constructor.isHasard(source)) { return source; } - const ctx = typeof (context) === 'string' ? context : 'global'; + const context_ = typeof (context) === 'string' ? context : 'global'; - if (!runOpts.refs || !runOpts.refs[ctx] || typeof (runOpts.refs[ctx][id]) === 'undefined') { - const res = source.runOnce(runOpts); - if (!runOpts.refs) { - runOpts.refs = {}; - } + if (!runOptions.refs || !runOptions.refs[context_] || (runOptions.refs[context_][id]) === undefined) { + const res = source.runOnce(runOptions); + runOptions.refs ||= {}; - if (!runOpts.refs[ctx]) { - runOpts.refs[ctx] = {}; + if (!runOptions.refs[context_]) { + runOptions.refs[context_] = {}; } - runOpts.refs[ctx][id] = res; + runOptions.refs[context_][id] = res; return res; } - return runOpts.refs[ctx][id]; + return runOptions.refs[context_][id]; } check(key, value) { - if (key === 'context' && value !== null && typeof (value) !== 'undefined') { - if (typeof (value) !== 'string') { - throw (new TypeError(`${key} (${value}) must be a string`)); - } + if (key === 'context' && value !== null && (value) !== undefined && typeof (value) !== 'string') { + throw (new TypeError(`${key} (${value}) must be a string`)); } } - getOpts(opts) { + getOpts(options) { const randomString = new RandomString({ value: new RandomValue('0123456789ABCDEF'.split('')), - size: 16 + size: 16, }); let source; let context; - if (AbstractHasard.isHasard(opts)) { - source = opts; + if (AbstractHasard.isHasard(options)) { + source = options; context = null; - } else if (typeof (opts) === 'object') { - source = opts.source; - context = opts.context; + } else if (typeof (options) === 'object') { + source = options.source; + context = options.context; } else { - source = opts; + source = options; context = null; } return { source, context, - id: randomString.runOnce() + id: randomString.runOnce(), }; } } diff --git a/lib/hasard/string.js b/lib/hasard/string.js index ee70e0d..39a12e5 100644 --- a/lib/hasard/string.js +++ b/lib/hasard/string.js @@ -1,8 +1,8 @@ -const ArrayHasard = require('./array'); +const ArrayHasard = require('./array.js'); class StringHasard extends ArrayHasard { - generate(ctx, runOpts) { - return super.generate(ctx, runOpts).join(''); + generate(context, runOptions) { + return super.generate(context, runOptions).join(''); } } diff --git a/lib/hasard/value.js b/lib/hasard/value.js index ec34e1b..5dfc0c1 100644 --- a/lib/hasard/value.js +++ b/lib/hasard/value.js @@ -1,13 +1,14 @@ -const AbstractHasard = require('./abstract'); +const AbstractHasard = require('./abstract.js'); const getRanges = function (array) { - const res = []; + const result = []; let current = 0; - array.forEach(v => { - res.push([current, current + v]); + for (const v of array) { + result.push([current, current + v]); current += v; - }); - return res; + } + + return result; }; class ValueHasard extends AbstractHasard { @@ -21,39 +22,39 @@ class ValueHasard extends AbstractHasard { } } - getOpts(opts) { + getOpts(options) { let choices; - if (Array.isArray(opts)) { - choices = opts; - } else if (AbstractHasard.isHasard(opts)) { - choices = opts; + if (Array.isArray(options)) { + choices = options; + } else if (AbstractHasard.isHasard(options)) { + choices = options; } else { - choices = opts.choices; + choices = options.choices; } - const {weights} = opts; + const {weights} = options; return { choices, - weights + weights, }; } - generate(ctx) { + generate(context) { let choice; - if (ctx.weights) { - if (!Array.isArray(ctx.choices)) { + if (context.weights) { + if (!Array.isArray(context.choices)) { throw (new TypeError('choices must be defined in h.value')); } - const ranges = getRanges(ctx.weights); + const ranges = getRanges(context.weights); const v = this.prng(); - const {index} = ranges.map((value, index) => ({value, index})).filter(({value}) => (value[0] <= v && v < value[1]))[0]; - choice = ctx.choices[index]; + const {index} = ranges.map((value, index) => ({value, index})).find(({value}) => (value[0] <= v && v < value[1])); + choice = context.choices[index]; } else { - choice = ctx.choices[Math.floor(this.prng() * ctx.choices.length)]; + choice = context.choices[Math.floor(this.prng() * context.choices.length)]; } if (this.constructor.isHasard(choice)) { diff --git a/lib/helpers/readable-stream.js b/lib/helpers/readable-stream.js index 17c527e..95e5683 100644 --- a/lib/helpers/readable-stream.js +++ b/lib/helpers/readable-stream.js @@ -1,4 +1,4 @@ -const {Readable} = require('stream'); +const {Readable} = require('node:stream'); class HasardReadableStream extends Readable { constructor(options) { @@ -7,7 +7,7 @@ class HasardReadableStream extends Readable { const { hasardInstance, number, - runOpts + runOpts, } = options; this._hasardInstance = hasardInstance; @@ -18,9 +18,9 @@ class HasardReadableStream extends Readable { _read() { setImmediate(() => { - const res = this._hasardInstance.runOnce(this._runOpts); - const obj = Object.assign({}, res, {index: this._curr}); - this.push(obj); + const result = this._hasardInstance.runOnce(this._runOpts); + const object = Object.assign({}, result, {index: this._curr}); + this.push(object); this._curr++; if (this._curr === this._end) { this.push(null); diff --git a/lib/helpers/recursive-each.js b/lib/helpers/recursive-each.js index 420735a..5aa0e85 100644 --- a/lib/helpers/recursive-each.js +++ b/lib/helpers/recursive-each.js @@ -1,11 +1,11 @@ -const recursiveEach = function (array, inShape, fn, index = 0) { +const recursiveEach = function (array, inShape, function_, index = 0) { if (Array.isArray(array) && inShape.length > 0) { const size = array.length; - array.forEach((item, indexLocal) => { - recursiveEach(item, inShape.slice(1), fn, (index * size) + indexLocal); - }); + for (const [indexLocal, item] of array.entries()) { + recursiveEach(item, inShape.slice(1), function_, (index * size) + indexLocal); + } } else { - fn(array, index); + function_(array, index); } }; diff --git a/lib/helpers/reshape.js b/lib/helpers/reshape.js index 3808c78..c323b32 100644 --- a/lib/helpers/reshape.js +++ b/lib/helpers/reshape.js @@ -1,26 +1,26 @@ -const recursiveEach = require('./recursive-each'); +const recursiveEach = require('./recursive-each.js'); -module.exports = function (arr, inShape, outShape) { - const newArr = []; +module.exports = function (array, inShape, outShape) { + const newArray = []; const reverseShape = outShape.concat([]).reverse(); - recursiveEach(arr, inShape, (item, index) => { + recursiveEach(array, inShape, (item, index) => { let remIndex = index; const indexes = []; - reverseShape.forEach(s => { + for (const s of reverseShape) { const previousRem = remIndex; remIndex = Math.floor(remIndex / s); indexes.unshift(previousRem - (remIndex * s)); - }); - let current = newArr; - indexes.slice(0, -1).forEach(index => { - if (!current[index]) { - current[index] = []; - } + } + + let current = newArray; + for (const index of indexes.slice(0, -1)) { + current[index] ||= []; current = current[index]; - }); - current[indexes[indexes.length - 1]] = item; + } + + current[indexes.at(-1)] = item; }); - return newArr; + return newArray; }; diff --git a/lib/operators.js b/lib/operators.js index 06529b3..fd667b8 100644 --- a/lib/operators.js +++ b/lib/operators.js @@ -1,17 +1,17 @@ -const Hfunction = require('./hasard/function'); +const Hfunction = require('./hasard/function.js'); module.exports = function (hasardContext) { - const fn = Hfunction.build.bind(Hfunction, hasardContext); + const function_ = Hfunction.build.bind(Hfunction, hasardContext); return { - multiply: fn((...args) => args.reduce((a, b) => a * b, 1)), - divide: fn((a, b) => a / b), - add: fn((...args) => args.reduce((a, b) => a + b)), - substract: fn((a, b) => a - b), - if: fn((condition, iftrue, iffalse) => condition ? iftrue : iffalse), - round: fn(n => Math.round(n)), - ceil: fn(n => Math.ceil(n)), - floor: fn(n => Math.floor(n)), - concat: fn((a, b) => a.concat(b)), - getProperty: fn((key, obj) => obj[key]) + multiply: function_((...arguments_) => arguments_.reduce((a, b) => a * b, 1)), + divide: function_((a, b) => a / b), + add: function_((...arguments_) => arguments_.reduce((a, b) => a + b)), + substract: function_((a, b) => a - b), + if: function_((condition, iftrue, iffalse) => condition ? iftrue : iffalse), + round: function_(n => Math.round(n)), + ceil: function_(n => Math.ceil(n)), + floor: function_(n => Math.floor(n)), + concat: function_((a, b) => a.concat(b)), + getProperty: function_((key, object) => object[key]), }; }; diff --git a/package.json b/package.json index 1f449ea..c00f8cd 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "index.js", "scripts": { "lint": "xo", + "fmt": "xo --fix", "test": "nyc ava test/*", "semantic-release": "semantic-release", "report-coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov" @@ -51,9 +52,18 @@ }, "homepage": "https://github.com/piercus/hasard#readme", "devDependencies": { - "ava": "^1.2.1", + "ava": "^6.1.2", "nyc": "^15.1.0", - "semantic-release": "^15.13.3", - "xo": "^0.24.0" + "semantic-release": "^23.0.2", + "xo": "^0.57.0" + }, + "xo": { + "rules": { + "unicorn/no-new-array": 0, + "unicorn/prevent-abbreviations": 0, + "logical-assignment-operators": 0, + "unicorn/prefer-module": 0, + "import/extensions": 0 + } } } diff --git a/test/helpers/test-distribution.js b/test/helpers/test-distribution.js index e38c7f4..5bcbecc 100644 --- a/test/helpers/test-distribution.js +++ b/test/helpers/test-distribution.js @@ -1,12 +1,13 @@ module.exports = function (t, actualHasard, individualExpectation, globalExpectation = null) { const n = 1000; - return actualHasard.runAsync(n).then(res => { - t.is(res.length, n); - res.forEach(a => { + return actualHasard.runAsync(n).then(result => { + t.is(result.length, n); + for (const a of result) { individualExpectation(t, a); - }); + } + if (globalExpectation) { - globalExpectation(t, res); + globalExpectation(t, result); } }); }; diff --git a/test/index.js b/test/index.js index 493671b..c877651 100644 --- a/test/index.js +++ b/test/index.js @@ -16,10 +16,10 @@ test('hasard.Value(Array.)', t => { const counts = values.map(s => as.filter(v => v === s).length / as.length); const average = 1 / values.length; const threshold = 1 / Math.sqrt(as.length); - counts.forEach(c => { + for (const c of counts) { t.true(Math.abs(c - average) < threshold); - }); - } + } + }, ); }); @@ -35,43 +35,43 @@ test('hasard.Boolean(Number)', t => { const counts = [true, false].map(s => as.filter(v => v === s).length / as.length); const expected = [p, 1 - p]; const threshold = 1 / Math.sqrt(as.length); - counts.forEach((c, index) => { + for (const [index, c] of counts.entries()) { t.true(Math.abs(c - expected[index]) < threshold); - }); - } + } + }, ); }); test('hasard.Value(Object)', t => { - const opts = { + const options = { choices: ['white', 'yellow'], - weights: [0.75, 0.25] + weights: [0.75, 0.25], }; return testDistribution(t, - new hasard.Value(opts), + new hasard.Value(options), (t, a) => { - t.not(opts.choices.indexOf(a), -1); + t.not(options.choices.indexOf(a), -1); }, (t, as) => { - const counts = opts.choices.map(s => as.filter(v => v === s).length / as.length); - const expected = opts.weights; + const counts = options.choices.map(s => as.filter(v => v === s).length / as.length); + const expected = options.weights; const threshold = 1 / Math.sqrt(as.length); - counts.forEach((c, index) => { + for (const [index, c] of counts.entries()) { t.true(Math.abs(c - expected[index]) < threshold); - }); - } + } + }, ); }); test('hasard.Number(Array.)', t => { t.throws(() => { new hasard.Number([1]); - }, 'invalid array, range array length must be 2'); + }, {instanceOf: TypeError, message: 'invalid array, range array length must be 2'}); t.throws(() => { new hasard.Number([0, 1, 2]); - }, 'invalid array, range array length must be 2'); + }, {instanceOf: TypeError, message: 'invalid array, range array length must be 2'}); const range = [10, 15]; const splits = [10, 11, 12, 13, 14]; @@ -87,10 +87,10 @@ test('hasard.Number(Array.)', t => { const counts = splits.map(n => as.filter(v => n <= v && v < n + 1).length / as.length); const average = 1 / counts.length; const threshold = 1 / Math.sqrt(as.length); - counts.forEach(c => { + for (const c of counts) { t.true(Math.abs(c - average) < threshold); - }); - } + } + }, ); }); @@ -109,10 +109,10 @@ test('hasard.Number(start, end)', t => { const counts = splits.map(n => as.filter(v => n <= v && v < n + 1).length / as.length); const average = 1 / counts.length; const threshold = 1 / Math.sqrt(as.length); - counts.forEach(c => { + for (const c of counts) { t.true(Math.abs(c - average) < threshold); - }); - } + } + }, ); }); @@ -120,7 +120,7 @@ test('hasard.Number(Object)', t => { const uniform = { type: 'uniform', start: 22, - end: 22.2 + end: 22.2, }; return testDistribution(t, @@ -132,22 +132,20 @@ test('hasard.Number(Object)', t => { }, (t, as) => { const nSplit = 5; - const splits = new Array(nSplit).fill(1).map((_, index) => { - return ((uniform.end - uniform.start) * index / nSplit) + uniform.start; - }); + const splits = Array.from({length: nSplit}).fill(1).map((_, index) => ((uniform.end - uniform.start) * index / nSplit) + uniform.start); const step = splits[1] - splits[0]; const counts = splits.map(n => as.filter(v => n <= v && v < n + step).length / as.length); const average = 1 / counts.length; const threshold = 1 / Math.sqrt(as.length); - counts.forEach(c => { - t.true(Math.abs(c - average) < threshold); - }); - } + for (const c of counts) { + t.true(Math.abs(c - average) < threshold); // TODO: can failed?? + } + }, ).then(() => { const normal = { type: 'normal', mean: -2, - std: 3 + std: 3, }; return testDistribution(t, @@ -162,7 +160,7 @@ test('hasard.Number(Object)', t => { const threshold = 100 / Math.sqrt(as.length); t.true(Math.abs(normal.mean - average) < threshold); t.true(Math.abs(variance - (normal.std * normal.std)) < threshold); - } + }, ); }) .then(() => { @@ -171,7 +169,7 @@ test('hasard.Number(Object)', t => { const truncatedNormal = { type: 'truncated-normal', mean, - std + std, }; return testDistribution(t, @@ -188,7 +186,7 @@ test('hasard.Number(Object)', t => { const threshold = 100 / Math.sqrt(as.length); t.true(Math.abs(truncatedNormal.mean - average) < threshold); t.true(Math.abs(variance - (truncatedNormal.std * truncatedNormal.std)) < threshold); - } + }, ); }); }); @@ -196,19 +194,19 @@ test('hasard.Number(Object)', t => { test('hasard.Integer([start, end])', t => { t.throws(() => { new hasard.Integer([1]); - }, '1 must be a length-2 array'); + }, {instanceOf: Error, message: '1 must be a length-2 array'}); t.throws(() => { new hasard.Integer([0, 1, 2]); - }, '0,1,2 must be a length-2 array'); + }, {instanceOf: Error, message: '0,1,2 must be a length-2 array'}); t.throws(() => { new hasard.Integer([0.1, 3]); - }, 'start (0.1) must be an integer'); + }, {instanceOf: Error, message: 'start (0.1) must be an integer'}); t.throws(() => { new hasard.Integer([0, 3.1]); - }, 'end (3.1) must be an integer'); + }, {instanceOf: Error, message: 'end (3.1) must be an integer'}); const range = [10, 15]; @@ -221,14 +219,14 @@ test('hasard.Integer([start, end])', t => { t.true(a <= range[1]); }, (t, as) => { - const values = new Array(range[1] - range[0] + 1).fill(1).map((_, i) => i + range[0]); + const values = Array.from({length: range[1] - range[0] + 1}).fill(1).map((_, i) => i + range[0]); const counts = values.map(n => as.filter(v => v === n).length / as.length); const average = 1 / values.length; const threshold = 1 / Math.sqrt(as.length); - counts.forEach(c => { + for (const c of counts) { t.true(Math.abs(c - average) < threshold); - }); - } + } + }, ); }); @@ -244,21 +242,21 @@ test('hasard.Integer(start, end)', t => { t.true(a <= range[1]); }, (t, as) => { - const values = new Array(range[1] - range[0] + 1).fill(1).map((_, i) => i + range[0]); + const values = Array.from({length: range[1] - range[0] + 1}).fill(1).map((_, i) => i + range[0]); const counts = values.map(n => as.filter(v => v === n).length / as.length); const average = 1 / values.length; const threshold = 1 / Math.sqrt(as.length); - counts.forEach(c => { + for (const c of counts) { t.true(Math.abs(c - average) < threshold); - }); - } + } + }, ); }); test('hasard.Integer({type, ...})', t => { const poisson = { type: 'poisson', - lambda: 3 + lambda: 3, }; return testDistribution(t, @@ -272,7 +270,7 @@ test('hasard.Integer({type, ...})', t => { const average = sum / as.length; const threshold = 100 / Math.sqrt(as.length); t.true(Math.abs(poisson.lambda - average) < threshold); - } + }, ); }); @@ -288,10 +286,10 @@ test('hasard.String({value, size})', t => { t.is(typeof (a), 'string'); t.true(a.length >= range[0]); t.true(a.length <= range[1]); - a.split('').forEach(c => { + for (const c of a.split('')) { t.not(chars.indexOf(c), -1); - }); - } + } + }, ); }); @@ -307,10 +305,10 @@ test('hasard.Array({value, size})', t => { t.is(typeof (a), 'object'); t.true(a.length >= range[0]); t.true(a.length <= range[1]); - a.forEach(c => { + for (const c of a) { t.not(chars.indexOf(c), -1); - }); - } + } + }, ); }); @@ -324,16 +322,14 @@ test('hasard.Array(>)', t => { (t, a) => { t.is(typeof (a), 'object'); t.is(a.length, 3); - a.forEach(c => { + for (const c of a) { t.not(chars.indexOf(c), -1); - }); + } }, (t, as) => { - const allSame = as.filter(a => { - return (a[0] === a[1]) && (a[1] === a[2]); - }); + const allSame = as.filter(a => (a[0] === a[1]) && (a[1] === a[2])); t.true(allSame.length < as.length / 2); - } + }, ); }); @@ -348,12 +344,10 @@ test('hasard.Array({values, randomOrder})', t => { t.is(a.length, 26); }, (t, as) => { - const shuffled = as.filter(a => { - return a.join('') !== string; - }); + const shuffled = as.filter(a => a.join('') !== string); const threshold = 100 / Math.sqrt(as.length); t.true(Math.abs((shuffled.length / as.length) - 0.5) < threshold); - } + }, ); }); @@ -364,43 +358,44 @@ test('hasard.Array({values, size})', t => { t.throws(() => { (new hasard.Array({values, size: 32})).runOnce(); - }, 'Cannot pick 32 elements in 26-size array'); + }, {instanceOf: Error, message: 'Cannot pick 32 elements in 26-size array'}); return testDistribution(t, new hasard.Array({values, size}), (t, a) => { t.is(typeof (a), 'object'); t.is(a.length, size); - a.forEach((c, index) => { + for (const [index, c] of a.entries()) { t.not(values.indexOf(c), -1); // Test unicity t.is(a.indexOf(c), index); - }); + } + // Order is still the same t.is(a.sort(), a); - } + }, ); }); test('hasard.Object(Object)', t => { const keys = { color1: ['white', 'yellow'], - color2: ['black', 'grey'] + color2: ['black', 'grey'], }; - const opts = {}; + const options = {}; - Object.keys(keys).forEach(k => { - opts[k] = new hasard.Value(keys[k]); - }); + for (const k of Object.keys(keys)) { + options[k] = new hasard.Value(keys[k]); + } return testDistribution(t, - new hasard.Object(opts), + new hasard.Object(options), (t, a) => { - Object.keys(keys).forEach(k => { + for (const k of Object.keys(keys)) { t.not(keys[k].indexOf(a[k]), -1); - }); - } + } + }, ); }); @@ -410,33 +405,34 @@ test('hasard.Object(Hasard.>, Hasard)', t => { new hasard.Value(['+33', '+32', '+1']), new hasard.String({ value: new hasard.Value(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']), - size: 10 - }) + size: 10, + }), ), - size: 10 + size: 10, }); const value = hasard.add( new hasard.Value(['Mr ', 'M ']), new hasard.Value(['Thomas ', 'Nicolas ', 'Julien ', 'Quentin ', 'Maxime ']), - new hasard.Value(['DURAND', 'DUBOIS', 'LEFEBVRE', 'MOREAU', 'MOREL', 'FOURNIER']) + new hasard.Value(['DURAND', 'DUBOIS', 'LEFEBVRE', 'MOREAU', 'MOREL', 'FOURNIER']), ); t.throws(() => { (new hasard.Object(['a', 'a', 'c'], new hasard.Value(['d', 'e', 'f']))); - }, 'keys must be unique (keys[1] \'a\' is duplicated)'); + }, + {instanceOf: TypeError, message: 'keys must be unique (keys[1] \'a\' is duplicated)'}); t.throws(() => { (new hasard.Object(['a', {b: 'b'}], new hasard.Value(['d', 'e', 'f']))).runOnce(); - }, 'keys must be string array (keys[1] \'[object Object]\' should be a string)'); + }, {instanceOf: TypeError, message: 'keys must be string array (keys[1] \'[object Object]\' should be a string)'}); return testDistribution(t, new hasard.Object( keys, - value + value, ), (t, a) => { t.is(Object.keys(a).length, 10); - } + }, ); }); @@ -445,12 +441,12 @@ test('hasard.Matrix(Object)', t => { const shapeValues = [5, 10]; const values = [0, 255]; - const opts = { + const options = { value: new hasard.Integer(values), shape: new hasard.Array({ value: new hasard.Integer(shapeValues), - size: new hasard.Integer(shapeSize) - }) + size: new hasard.Integer(shapeSize), + }), }; const testSameSize = function (a, t) { @@ -458,10 +454,10 @@ test('hasard.Matrix(Object)', t => { t.fail(); } else if (Array.isArray(a[0])) { const size = a[0].length; - a.forEach(b => { + for (const b of a) { t.is(b.length, size); testSameSize(b, t); - }); + } } }; @@ -478,28 +474,28 @@ test('hasard.Matrix(Object)', t => { }; return testDistribution(t, - new hasard.Matrix(opts), + new hasard.Matrix(options), (t, a) => { t.true(Array.isArray(a)); testSameSize(a, t); const shape = getShape(a); t.true(shape.length >= shapeSize[0]); t.true(shape.length <= shapeSize[1]); - shape.forEach(s => { + for (const s of shape) { t.true(s >= shapeValues[0]); t.true(s <= shapeValues[1]); - }); - } + } + }, ); }); test('hasard.Matrix({value: Hasard.})', t => { - const opts = { + const options = { value: new hasard.Array({ value: new hasard.Integer([5, 10]), - size: 3 + size: 3, }), - shape: [5, 10] + shape: [5, 10], }; const getShape = function (a) { @@ -515,11 +511,11 @@ test('hasard.Matrix({value: Hasard.})', t => { }; return testDistribution(t, - new hasard.Matrix(opts), + new hasard.Matrix(options), (t, a) => { const shape = getShape(a); t.deepEqual(shape, [5, 10, 3]); - } + }, ); }); @@ -533,75 +529,69 @@ test('hasard.Reference() with hasard.Array()', t => { (t, a) => { t.is(typeof (a), 'object'); t.is(a.length, 3); - a.forEach(c => { + for (const c of a) { t.not(chars.indexOf(c), -1); - }); + } }, (t, as) => { - const allSame = as.filter(a => { - return (a[0] === a[1]) && (a[1] === a[2]); - }); + const allSame = as.filter(a => (a[0] === a[1]) && (a[1] === a[2])); t.is(allSame.length, as.length); const first = as[0]; - const sameAsFirst = as.filter(a => { - return (a[0] === first[0]); - }); + const sameAsFirst = as.filter(a => (a[0] === first[0])); t.true(sameAsFirst.length < as.length / 2); - } + }, ); }); test('hasard.Reference() with context and contextName', t => { const int = new hasard.Integer([0, 255]); - const ref = new hasard.Reference({source: int, context: 'color'}); + const reference = new hasard.Reference({source: int, context: 'color'}); const color = new hasard.Array({ values: [ - ref, - ref, - ref + reference, + reference, + reference, ], - contextName: 'color' + contextName: 'color', }); const size = 10; const colors = new hasard.Array({ value: color, - size + size, }); return testDistribution(t, colors, (t, a) => { - a.forEach(color => { + for (const color of a) { // Console.log(color) t.is(typeof (color[0]), 'number'); t.is(color[0], color[1]); t.is(color[0], color[2]); - }); + } t.true(a.filter(color => a[0][0] === color[0]).length < size / 3); - } + }, ); }); test('hasard.fn(Function)', t => { - const refA = new hasard.Reference(new hasard.Number([0, 1])); - const refB = new hasard.Reference(new hasard.Number([0, 1])); + const referenceA = new hasard.Reference(new hasard.Number([0, 1])); + const referenceB = new hasard.Reference(new hasard.Number([0, 1])); - const addHasard = hasard.fn((a, b) => { - return a + b; - }); + const addHasard = hasard.fn((a, b) => a + b); - const obj = new hasard.Object({ - a: refA, - b: refB, - sum: addHasard(refA, refB) + const object = new hasard.Object({ + a: referenceA, + b: referenceB, + sum: addHasard(referenceA, referenceB), }); return testDistribution(t, - obj, + object, (t, {a, b, sum}) => { t.is(a + b, sum); - } + }, ); }); diff --git a/test/issues.js b/test/issues.js index 11258bb..bf86de1 100644 --- a/test/issues.js +++ b/test/issues.js @@ -7,24 +7,24 @@ const testDistribution = require('./helpers/test-distribution'); test('Avoid duplication of randomly selected value (#3)', t => { const choices = ['a', 'b', 'c']; const random1 = hasard.value(choices); - const ref1 = hasard.reference(random1); + const reference1 = hasard.reference(random1); - const antiChoicesFn = hasard.fn(a => { + const antiChoicesFunction = hasard.fn(a => { const index = choices.indexOf(a); const remaining = choices.slice(0, index).concat(choices.slice(index + 1)); return remaining; }); const differentValues = hasard.array([ - ref1, - hasard.value(antiChoicesFn(ref1)) + reference1, + hasard.value(antiChoicesFunction(reference1)), ]); return testDistribution(t, differentValues, (t, a) => { t.not(a[0], a[1]); - } + }, ); }); @@ -33,7 +33,7 @@ test('hasard.Array({values, size: h.integer}) (#8)', t => { const values = string.split(''); const v = hasard.array({ values, - size: hasard.integer(0, 3) + size: hasard.integer(0, 3), }); return testDistribution(t, v, @@ -41,6 +41,6 @@ test('hasard.Array({values, size: h.integer}) (#8)', t => { t.is(typeof (a), 'object'); t.true(a.length >= 0); t.true(a.length <= 3); - } + }, ); }); From 35d72ea74c8a681dc984047e3e74384a60fec6ff Mon Sep 17 00:00:00 2001 From: urielch Date: Tue, 5 Mar 2024 06:47:00 +0100 Subject: [PATCH 3/9] update TODO comment --- test/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/index.js b/test/index.js index c877651..c5abf60 100644 --- a/test/index.js +++ b/test/index.js @@ -138,7 +138,7 @@ test('hasard.Number(Object)', t => { const average = 1 / counts.length; const threshold = 1 / Math.sqrt(as.length); for (const c of counts) { - t.true(Math.abs(c - average) < threshold); // TODO: can failed?? + t.true(Math.abs(c - average) < threshold); // TODO: change this test failed randomly } }, ).then(() => { @@ -224,7 +224,7 @@ test('hasard.Integer([start, end])', t => { const average = 1 / values.length; const threshold = 1 / Math.sqrt(as.length); for (const c of counts) { - t.true(Math.abs(c - average) < threshold); + t.true(Math.abs(c - average) < threshold); // TODO: change this test failed randomly } }, ); From 3210a0f9eb6cf45f7d45e3ac31ba5cc2a391cc73 Mon Sep 17 00:00:00 2001 From: urielch Date: Tue, 5 Mar 2024 07:09:40 +0100 Subject: [PATCH 4/9] convert to esmodule --- test/index.js | 128 ++++++++++++++++++++++++------------------------- test/issues.js | 20 ++++---- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/test/index.js b/test/index.js index c5abf60..f93a3db 100644 --- a/test/index.js +++ b/test/index.js @@ -1,14 +1,14 @@ /* eslint no-new: "off" */ /* eslint ava/prefer-async-await: "off" */ -const test = require('ava'); -const hasard = require('..'); -const testDistribution = require('./helpers/test-distribution'); +import test from 'ava'; +import { Value, Boolean, Number, Integer, String, Array as _Array, Object as _Object, array, add, Matrix, Reference, fn } from '..'; +import testDistribution from './helpers/test-distribution'; test('hasard.Value(Array.)', t => { const values = ['white', 'yellow']; return testDistribution(t, - new hasard.Value(values), + new Value(values), (t, a) => { t.not(values.indexOf(a), -1); }, @@ -27,7 +27,7 @@ test('hasard.Boolean(Number)', t => { const p = 0.2; return testDistribution(t, - new hasard.Boolean(p), + new Boolean(p), (t, a) => { t.is(typeof (a), 'boolean'); }, @@ -49,7 +49,7 @@ test('hasard.Value(Object)', t => { }; return testDistribution(t, - new hasard.Value(options), + new Value(options), (t, a) => { t.not(options.choices.indexOf(a), -1); }, @@ -66,18 +66,18 @@ test('hasard.Value(Object)', t => { test('hasard.Number(Array.)', t => { t.throws(() => { - new hasard.Number([1]); + new Number([1]); }, {instanceOf: TypeError, message: 'invalid array, range array length must be 2'}); t.throws(() => { - new hasard.Number([0, 1, 2]); + new Number([0, 1, 2]); }, {instanceOf: TypeError, message: 'invalid array, range array length must be 2'}); const range = [10, 15]; const splits = [10, 11, 12, 13, 14]; return testDistribution(t, - new hasard.Number(range), + new Number(range), (t, a) => { t.is(typeof (a), 'number'); t.true(a >= range[0]); @@ -99,7 +99,7 @@ test('hasard.Number(start, end)', t => { const splits = [10, 11, 12, 13, 14]; return testDistribution(t, - new hasard.Number(range[0], range[1]), + new Number(range[0], range[1]), (t, a) => { t.is(typeof (a), 'number'); t.true(a >= range[0]); @@ -124,7 +124,7 @@ test('hasard.Number(Object)', t => { }; return testDistribution(t, - new hasard.Number(uniform), + new Number(uniform), (t, a) => { t.is(typeof (a), 'number'); t.true(a >= uniform.start); @@ -149,7 +149,7 @@ test('hasard.Number(Object)', t => { }; return testDistribution(t, - new hasard.Number(normal), + new Number(normal), (t, a) => { t.is(typeof (a), 'number'); }, @@ -173,7 +173,7 @@ test('hasard.Number(Object)', t => { }; return testDistribution(t, - new hasard.Number(truncatedNormal), + new Number(truncatedNormal), (t, a) => { t.is(typeof (a), 'number'); t.true(a >= mean - (2 * std)); @@ -193,25 +193,25 @@ test('hasard.Number(Object)', t => { test('hasard.Integer([start, end])', t => { t.throws(() => { - new hasard.Integer([1]); + new Integer([1]); }, {instanceOf: Error, message: '1 must be a length-2 array'}); t.throws(() => { - new hasard.Integer([0, 1, 2]); + new Integer([0, 1, 2]); }, {instanceOf: Error, message: '0,1,2 must be a length-2 array'}); t.throws(() => { - new hasard.Integer([0.1, 3]); + new Integer([0.1, 3]); }, {instanceOf: Error, message: 'start (0.1) must be an integer'}); t.throws(() => { - new hasard.Integer([0, 3.1]); + new Integer([0, 3.1]); }, {instanceOf: Error, message: 'end (3.1) must be an integer'}); const range = [10, 15]; return testDistribution(t, - new hasard.Integer(range), + new Integer(range), (t, a) => { t.is(typeof (a), 'number'); t.is(a, Math.floor(a)); @@ -234,7 +234,7 @@ test('hasard.Integer(start, end)', t => { const range = [10, 15]; return testDistribution(t, - new hasard.Integer(range[0], range[1]), + new Integer(range[0], range[1]), (t, a) => { t.is(typeof (a), 'number'); t.is(a, Math.floor(a)); @@ -260,7 +260,7 @@ test('hasard.Integer({type, ...})', t => { }; return testDistribution(t, - new hasard.Integer(poisson), + new Integer(poisson), (t, a) => { t.is(typeof (a), 'number'); t.true(a >= 0); @@ -277,11 +277,11 @@ test('hasard.Integer({type, ...})', t => { test('hasard.String({value, size})', t => { const range = [5, 10]; const chars = ['a', 'b', 'c', 'd']; - const value = new hasard.Value(chars); - const size = new hasard.Integer(range); + const value = new Value(chars); + const size = new Integer(range); return testDistribution(t, - new hasard.String({value, size}), + new String({value, size}), (t, a) => { t.is(typeof (a), 'string'); t.true(a.length >= range[0]); @@ -296,11 +296,11 @@ test('hasard.String({value, size})', t => { test('hasard.Array({value, size})', t => { const range = [5, 10]; const chars = ['a', 'b', 'c', 'd']; - const value = new hasard.Value(chars); - const size = new hasard.Integer(range); + const value = new Value(chars); + const size = new Integer(range); return testDistribution(t, - new hasard.Array({value, size}), + new _Array({value, size}), (t, a) => { t.is(typeof (a), 'object'); t.true(a.length >= range[0]); @@ -314,11 +314,11 @@ test('hasard.Array({value, size})', t => { test('hasard.Array(>)', t => { const chars = ['a', 'b', 'c', 'd']; - const haz = new hasard.Value(chars); + const haz = new Value(chars); const values = [haz, haz, haz]; return testDistribution(t, - new hasard.Array(values), + new _Array(values), (t, a) => { t.is(typeof (a), 'object'); t.is(a.length, 3); @@ -336,10 +336,10 @@ test('hasard.Array(>)', t => { test('hasard.Array({values, randomOrder})', t => { const string = 'abcdefghijklmnopqrstuvwxyz'; const values = string.split(''); - const shuffle = new hasard.Boolean(); + const shuffle = new Boolean(); return testDistribution(t, - new hasard.Array({values, shuffle}), + new _Array({values, shuffle}), (t, a) => { t.is(a.length, 26); }, @@ -357,11 +357,11 @@ test('hasard.Array({values, size})', t => { const size = 15; t.throws(() => { - (new hasard.Array({values, size: 32})).runOnce(); + (new _Array({values, size: 32})).runOnce(); }, {instanceOf: Error, message: 'Cannot pick 32 elements in 26-size array'}); return testDistribution(t, - new hasard.Array({values, size}), + new _Array({values, size}), (t, a) => { t.is(typeof (a), 'object'); t.is(a.length, size); @@ -386,11 +386,11 @@ test('hasard.Object(Object)', t => { const options = {}; for (const k of Object.keys(keys)) { - options[k] = new hasard.Value(keys[k]); + options[k] = new Value(keys[k]); } return testDistribution(t, - new hasard.Object(options), + new _Object(options), (t, a) => { for (const k of Object.keys(keys)) { t.not(keys[k].indexOf(a[k]), -1); @@ -400,33 +400,33 @@ test('hasard.Object(Object)', t => { }); test('hasard.Object(Hasard.>, Hasard)', t => { - const keys = hasard.array({ - value: hasard.add( - new hasard.Value(['+33', '+32', '+1']), - new hasard.String({ - value: new hasard.Value(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']), + const keys = array({ + value: add( + new Value(['+33', '+32', '+1']), + new String({ + value: new Value(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']), size: 10, }), ), size: 10, }); - const value = hasard.add( - new hasard.Value(['Mr ', 'M ']), - new hasard.Value(['Thomas ', 'Nicolas ', 'Julien ', 'Quentin ', 'Maxime ']), - new hasard.Value(['DURAND', 'DUBOIS', 'LEFEBVRE', 'MOREAU', 'MOREL', 'FOURNIER']), + const value = add( + new Value(['Mr ', 'M ']), + new Value(['Thomas ', 'Nicolas ', 'Julien ', 'Quentin ', 'Maxime ']), + new Value(['DURAND', 'DUBOIS', 'LEFEBVRE', 'MOREAU', 'MOREL', 'FOURNIER']), ); t.throws(() => { - (new hasard.Object(['a', 'a', 'c'], new hasard.Value(['d', 'e', 'f']))); + (new _Object(['a', 'a', 'c'], new Value(['d', 'e', 'f']))); }, {instanceOf: TypeError, message: 'keys must be unique (keys[1] \'a\' is duplicated)'}); t.throws(() => { - (new hasard.Object(['a', {b: 'b'}], new hasard.Value(['d', 'e', 'f']))).runOnce(); + (new _Object(['a', {b: 'b'}], new Value(['d', 'e', 'f']))).runOnce(); }, {instanceOf: TypeError, message: 'keys must be string array (keys[1] \'[object Object]\' should be a string)'}); return testDistribution(t, - new hasard.Object( + new _Object( keys, value, ), @@ -442,10 +442,10 @@ test('hasard.Matrix(Object)', t => { const values = [0, 255]; const options = { - value: new hasard.Integer(values), - shape: new hasard.Array({ - value: new hasard.Integer(shapeValues), - size: new hasard.Integer(shapeSize), + value: new Integer(values), + shape: new _Array({ + value: new Integer(shapeValues), + size: new Integer(shapeSize), }), }; @@ -474,7 +474,7 @@ test('hasard.Matrix(Object)', t => { }; return testDistribution(t, - new hasard.Matrix(options), + new Matrix(options), (t, a) => { t.true(Array.isArray(a)); testSameSize(a, t); @@ -491,8 +491,8 @@ test('hasard.Matrix(Object)', t => { test('hasard.Matrix({value: Hasard.})', t => { const options = { - value: new hasard.Array({ - value: new hasard.Integer([5, 10]), + value: new _Array({ + value: new Integer([5, 10]), size: 3, }), shape: [5, 10], @@ -511,7 +511,7 @@ test('hasard.Matrix({value: Hasard.})', t => { }; return testDistribution(t, - new hasard.Matrix(options), + new Matrix(options), (t, a) => { const shape = getShape(a); t.deepEqual(shape, [5, 10, 3]); @@ -521,11 +521,11 @@ test('hasard.Matrix({value: Hasard.})', t => { test('hasard.Reference() with hasard.Array()', t => { const chars = ['a', 'b', 'c', 'd']; - const haz = new hasard.Reference(new hasard.Value(chars)); + const haz = new Reference(new Value(chars)); const values = [haz, haz, haz]; return testDistribution(t, - new hasard.Array(values), + new _Array(values), (t, a) => { t.is(typeof (a), 'object'); t.is(a.length, 3); @@ -544,10 +544,10 @@ test('hasard.Reference() with hasard.Array()', t => { }); test('hasard.Reference() with context and contextName', t => { - const int = new hasard.Integer([0, 255]); - const reference = new hasard.Reference({source: int, context: 'color'}); + const int = new Integer([0, 255]); + const reference = new Reference({source: int, context: 'color'}); - const color = new hasard.Array({ + const color = new _Array({ values: [ reference, reference, @@ -556,7 +556,7 @@ test('hasard.Reference() with context and contextName', t => { contextName: 'color', }); const size = 10; - const colors = new hasard.Array({ + const colors = new _Array({ value: color, size, }); @@ -577,12 +577,12 @@ test('hasard.Reference() with context and contextName', t => { }); test('hasard.fn(Function)', t => { - const referenceA = new hasard.Reference(new hasard.Number([0, 1])); - const referenceB = new hasard.Reference(new hasard.Number([0, 1])); + const referenceA = new Reference(new Number([0, 1])); + const referenceB = new Reference(new Number([0, 1])); - const addHasard = hasard.fn((a, b) => a + b); + const addHasard = fn((a, b) => a + b); - const object = new hasard.Object({ + const object = new _Object({ a: referenceA, b: referenceB, sum: addHasard(referenceA, referenceB), diff --git a/test/issues.js b/test/issues.js index bf86de1..7d2c654 100644 --- a/test/issues.js +++ b/test/issues.js @@ -1,23 +1,23 @@ /* eslint no-new: "off" */ /* eslint ava/prefer-async-await: "off" */ -const test = require('ava'); -const hasard = require('..'); -const testDistribution = require('./helpers/test-distribution'); +import test from 'ava'; +import { value, reference, fn, array, integer } from '..'; +import testDistribution from './helpers/test-distribution'; test('Avoid duplication of randomly selected value (#3)', t => { const choices = ['a', 'b', 'c']; - const random1 = hasard.value(choices); - const reference1 = hasard.reference(random1); + const random1 = value(choices); + const reference1 = reference(random1); - const antiChoicesFunction = hasard.fn(a => { + const antiChoicesFunction = fn(a => { const index = choices.indexOf(a); const remaining = choices.slice(0, index).concat(choices.slice(index + 1)); return remaining; }); - const differentValues = hasard.array([ + const differentValues = array([ reference1, - hasard.value(antiChoicesFunction(reference1)), + value(antiChoicesFunction(reference1)), ]); return testDistribution(t, @@ -31,9 +31,9 @@ test('Avoid duplication of randomly selected value (#3)', t => { test('hasard.Array({values, size: h.integer}) (#8)', t => { const string = 'abcdefghijklmnopqrstuvwxyz'; const values = string.split(''); - const v = hasard.array({ + const v = array({ values, - size: hasard.integer(0, 3), + size: integer(0, 3), }); return testDistribution(t, v, From 1a234cc6b8dc0cd5c8ee8108c26520304909bfdb Mon Sep 17 00:00:00 2001 From: urielch Date: Tue, 5 Mar 2024 09:06:36 +0100 Subject: [PATCH 5/9] converted to ESM --- examples/random-object-generator.js | 2 +- examples/random-usa-users.js | 2 +- index.js | 101 +++++++++++++++++++++++----- lib/hasard/abstract.js | 4 +- lib/hasard/array.js | 4 +- lib/hasard/boolean.js | 4 +- lib/hasard/function.js | 6 +- lib/hasard/integer.js | 4 +- lib/hasard/matrix.js | 6 +- lib/hasard/number.js | 4 +- lib/hasard/object.js | 4 +- lib/hasard/reference.js | 8 +-- lib/hasard/string.js | 4 +- lib/hasard/value.js | 5 +- lib/helpers/readable-stream.js | 4 +- lib/helpers/recursive-each.js | 2 +- lib/helpers/reshape.js | 6 +- lib/operators.js | 9 +-- package.json | 2 +- test/helpers/test-distribution.js | 4 +- test/index.js | 36 +++++----- test/issues.js | 18 ++--- 22 files changed, 155 insertions(+), 84 deletions(-) diff --git a/examples/random-object-generator.js b/examples/random-object-generator.js index d40bb99..c720ab5 100644 --- a/examples/random-object-generator.js +++ b/examples/random-object-generator.js @@ -1,4 +1,4 @@ -const h = require('../index.js'); +import * as h from '../index.js'; const randomValue = h.value(); diff --git a/examples/random-usa-users.js b/examples/random-usa-users.js index 540dbc8..d2d3bbc 100644 --- a/examples/random-usa-users.js +++ b/examples/random-usa-users.js @@ -1,4 +1,4 @@ -const h = require('../index.js'); +import * as h from '../index.js'; const givenNames = ['Veronica', 'Mercedes', diff --git a/index.js b/index.js index af7e5be..d1a5c01 100644 --- a/index.js +++ b/index.js @@ -1,27 +1,39 @@ -const Abstract = require('./lib/hasard/abstract'); -const Function = require('./lib/hasard/function'); -const operators = require('./lib/operators'); +import AbstractHasard from './lib/hasard/abstract.js'; +import operators from './lib/operators.js'; +import HasardInteger from './lib/hasard/integer.js'; +import HasardValue from './lib/hasard/value.js'; +import HasardArray from './lib/hasard/array.js'; +import HasardObject from './lib/hasard/object.js'; +import HasardNumber from './lib/hasard/number.js'; +import HasardMatrix from './lib/hasard/matrix.js'; +import HasardString from './lib/hasard/string.js'; +import HasardBoolean from './lib/hasard/boolean.js'; +import HasardReference from './lib/hasard/reference.js'; +import HasardFunction from './lib/hasard/function.js'; const cstrs = { - Integer: require('./lib/hasard/integer'), - Value: require('./lib/hasard/value'), - Array: require('./lib/hasard/array'), - Object: require('./lib/hasard/object'), - Number: require('./lib/hasard/number'), - Matrix: require('./lib/hasard/matrix'), - String: require('./lib/hasard/string'), - Boolean: require('./lib/hasard/boolean'), - Reference: require('./lib/hasard/reference'), - Function, + Integer: HasardInteger, + Value: HasardValue, + Array: HasardArray, + Object: HasardObject, + Number: HasardNumber, + Matrix: HasardMatrix, + String: HasardString, + Boolean: HasardBoolean, + Reference: HasardReference, + Function: HasardFunction, }; +/** + * Lowercaed version of cstrs + */ const shortcuts = {}; for (const key of Object.keys(cstrs)) { shortcuts[key.toLowerCase()] = cstrs[key].build.bind(cstrs[key], this); } const helpers = { - isHasard: Abstract.isHasard, + isHasard: AbstractHasard.isHasard, fn: shortcuts.function, int: shortcuts.integer, num: shortcuts.number, @@ -30,10 +42,13 @@ const helpers = { }; const methods = function (hasardContext) { - return Object.assign({}, cstrs, shortcuts, operators(hasardContext), helpers); + // Return Object.assign({}, cstrs, shortcuts, operators(hasardContext), helpers); + return { + ...cstrs, ...shortcuts, ...operators(hasardContext), ...helpers, + }; }; -class Hasard { +export class Hasard { constructor(prng = Math.random.bind(Math)) { this.prng = prng; const meths = methods(this); @@ -43,4 +58,56 @@ class Hasard { } } -module.exports = Object.assign(Hasard, methods(null)); +const HasardLib = {...Hasard, ...methods(null)}; + +// Exports from operators.js +export const multiply = HasardLib.multiply; +export const divide = HasardLib.divide; +export const add = HasardLib.add; +export const substract = HasardLib.substract; +// Can not export symbol 'if' +// export const if = HasardLib.if; +export const round = HasardLib.round; +export const ceil = HasardLib.ceil; +export const floor = HasardLib.floor; +export const concat = HasardLib.concat; +export const getProperty = HasardLib.getProperty; +// End of exports from operators.js + +// exports from helpers +export const isHasard = HasardLib.isHasard; +export const fn = HasardLib.fn; +export const int = HasardLib.int; +export const num = HasardLib.num; +export const str = HasardLib.str; +export const ref = HasardLib.ref; +// End of exports from helpers + +// export from cstrs +export const Integer = HasardLib.Integer; +export const Value = HasardLib.Value; +export const Array = HasardLib.Array; +// Export const Object = HasardLib.Object; +export const Number = HasardLib.Number; +export const Matrix = HasardLib.Matrix; +export const String = HasardLib.String; +export const Boolean = HasardLib.Boolean; +export const Reference = HasardLib.Reference; +export const Function = HasardLib.Function; +// End of export from cstrs + +// export from lowercased cstrs +export const integer = HasardLib.Integer; +export const value = HasardLib.Value; +export const array = HasardLib.Array; +export const object = HasardLib.Object; +export const number = HasardLib.Number; +export const matrix = HasardLib.Matrix; +export const string = HasardLib.String; +export const boolean = HasardLib.Boolean; +export const reference = HasardLib.Reference; +// Export const function = HasardLib.Function; +// end of export from lowercased cstrs + +// export default +export default HasardLib; diff --git a/lib/hasard/abstract.js b/lib/hasard/abstract.js index 2e1b91b..9d0728e 100644 --- a/lib/hasard/abstract.js +++ b/lib/hasard/abstract.js @@ -1,4 +1,4 @@ -const HasardReadableStream = require('../helpers/readable-stream'); +import HasardReadableStream from '../helpers/readable-stream.js'; class AbstractHasard { constructor(...arguments_) { @@ -112,4 +112,4 @@ class AbstractHasard { } } -module.exports = AbstractHasard; +export default AbstractHasard; diff --git a/lib/hasard/array.js b/lib/hasard/array.js index 2ddcba6..627b40d 100644 --- a/lib/hasard/array.js +++ b/lib/hasard/array.js @@ -1,4 +1,4 @@ -const AbstractHasard = require('./abstract'); +import AbstractHasard from './abstract.js'; class ArrayHasard extends AbstractHasard { check(key, value) { @@ -83,4 +83,4 @@ class ArrayHasard extends AbstractHasard { } } -module.exports = ArrayHasard; +export default ArrayHasard; diff --git a/lib/hasard/boolean.js b/lib/hasard/boolean.js index 6dab6f6..00ddf08 100644 --- a/lib/hasard/boolean.js +++ b/lib/hasard/boolean.js @@ -1,4 +1,4 @@ -const AbstractHasard = require('./abstract'); +import AbstractHasard from './abstract.js'; class BooleanHasard extends AbstractHasard { constructor(...arguments_) { @@ -37,4 +37,4 @@ class BooleanHasard extends AbstractHasard { } } -module.exports = BooleanHasard; +export default BooleanHasard; diff --git a/lib/hasard/function.js b/lib/hasard/function.js index d5c4b55..e8222b2 100644 --- a/lib/hasard/function.js +++ b/lib/hasard/function.js @@ -1,5 +1,5 @@ -const AbstractHasard = require('./abstract'); -const RandomArray = require('./array'); +import AbstractHasard from './abstract.js'; +import RandomArray from './array.js'; class FunctionHasard extends AbstractHasard { check(key, value) { @@ -35,4 +35,4 @@ class FunctionHasard extends AbstractHasard { } } -module.exports = FunctionHasard; +export default FunctionHasard; diff --git a/lib/hasard/integer.js b/lib/hasard/integer.js index f5a33f8..909a3f6 100644 --- a/lib/hasard/integer.js +++ b/lib/hasard/integer.js @@ -1,4 +1,4 @@ -const AbstractHasard = require('./abstract.js'); +import AbstractHasard from './abstract.js'; class IntegerHasard extends AbstractHasard { check(key, value) { @@ -57,4 +57,4 @@ class IntegerHasard extends AbstractHasard { } } -module.exports = IntegerHasard; +export default IntegerHasard; diff --git a/lib/hasard/matrix.js b/lib/hasard/matrix.js index 1ce7abf..407d505 100644 --- a/lib/hasard/matrix.js +++ b/lib/hasard/matrix.js @@ -1,5 +1,5 @@ -const reshape = require('../helpers/reshape'); -const ArrayHasard = require('./array'); +import reshape from '../helpers/reshape.js'; +import ArrayHasard from './array.js'; const fact = function (array) { if (array.length === 0) { @@ -41,4 +41,4 @@ class MatrixHasard extends ArrayHasard { } } -module.exports = MatrixHasard; +export default MatrixHasard; diff --git a/lib/hasard/number.js b/lib/hasard/number.js index f3094b1..b91818d 100644 --- a/lib/hasard/number.js +++ b/lib/hasard/number.js @@ -1,4 +1,4 @@ -const AbstractHasard = require('./abstract.js'); +import AbstractHasard from './abstract.js'; class NumberHasard extends AbstractHasard { check(key, value) { @@ -85,4 +85,4 @@ class NumberHasard extends AbstractHasard { } } -module.exports = NumberHasard; +export default NumberHasard; diff --git a/lib/hasard/object.js b/lib/hasard/object.js index d9f3b61..3934a1a 100644 --- a/lib/hasard/object.js +++ b/lib/hasard/object.js @@ -1,4 +1,4 @@ -const AbstractHasard = require('./abstract'); +import AbstractHasard from './abstract.js'; class ObjectHasard extends AbstractHasard { set(keys, value) { @@ -68,4 +68,4 @@ class ObjectHasard extends AbstractHasard { } } -module.exports = ObjectHasard; +export default ObjectHasard; diff --git a/lib/hasard/reference.js b/lib/hasard/reference.js index cd29aa0..807a278 100644 --- a/lib/hasard/reference.js +++ b/lib/hasard/reference.js @@ -1,6 +1,6 @@ -const AbstractHasard = require('./abstract'); -const RandomString = require('./string'); -const RandomValue = require('./value'); +import AbstractHasard from './abstract.js'; +import RandomString from './string.js'; +import RandomValue from './value.js'; class ReferenceHasard extends AbstractHasard { resolve(unresolved, runOptions) { @@ -65,4 +65,4 @@ class ReferenceHasard extends AbstractHasard { } } -module.exports = ReferenceHasard; +export default ReferenceHasard; diff --git a/lib/hasard/string.js b/lib/hasard/string.js index 39a12e5..7871f44 100644 --- a/lib/hasard/string.js +++ b/lib/hasard/string.js @@ -1,4 +1,4 @@ -const ArrayHasard = require('./array.js'); +import ArrayHasard from './array.js'; class StringHasard extends ArrayHasard { generate(context, runOptions) { @@ -6,4 +6,4 @@ class StringHasard extends ArrayHasard { } } -module.exports = StringHasard; +export default StringHasard; diff --git a/lib/hasard/value.js b/lib/hasard/value.js index 5dfc0c1..2020f22 100644 --- a/lib/hasard/value.js +++ b/lib/hasard/value.js @@ -1,4 +1,5 @@ -const AbstractHasard = require('./abstract.js'); +import AbstractHasard from './abstract.js'; +// Const { isHasard } = AbstractHasard; const getRanges = function (array) { const result = []; @@ -65,4 +66,4 @@ class ValueHasard extends AbstractHasard { } } -module.exports = ValueHasard; +export default ValueHasard; diff --git a/lib/helpers/readable-stream.js b/lib/helpers/readable-stream.js index 95e5683..a88fec6 100644 --- a/lib/helpers/readable-stream.js +++ b/lib/helpers/readable-stream.js @@ -1,4 +1,4 @@ -const {Readable} = require('node:stream'); +import {Readable} from 'node:stream'; class HasardReadableStream extends Readable { constructor(options) { @@ -29,4 +29,4 @@ class HasardReadableStream extends Readable { } } -module.exports = HasardReadableStream; +export default HasardReadableStream; diff --git a/lib/helpers/recursive-each.js b/lib/helpers/recursive-each.js index 5aa0e85..297b1eb 100644 --- a/lib/helpers/recursive-each.js +++ b/lib/helpers/recursive-each.js @@ -9,4 +9,4 @@ const recursiveEach = function (array, inShape, function_, index = 0) { } }; -module.exports = recursiveEach; +export default recursiveEach; diff --git a/lib/helpers/reshape.js b/lib/helpers/reshape.js index c323b32..b6ffaaf 100644 --- a/lib/helpers/reshape.js +++ b/lib/helpers/reshape.js @@ -1,6 +1,6 @@ -const recursiveEach = require('./recursive-each.js'); +import recursiveEach from './recursive-each.js'; -module.exports = function (array, inShape, outShape) { +export default function reshape(array, inShape, outShape) { const newArray = []; const reverseShape = outShape.concat([]).reverse(); recursiveEach(array, inShape, (item, index) => { @@ -23,4 +23,4 @@ module.exports = function (array, inShape, outShape) { current[indexes.at(-1)] = item; }); return newArray; -}; +} diff --git a/lib/operators.js b/lib/operators.js index fd667b8..e4030d1 100644 --- a/lib/operators.js +++ b/lib/operators.js @@ -1,7 +1,8 @@ -const Hfunction = require('./hasard/function.js'); +import Hfunction from './hasard/function.js'; -module.exports = function (hasardContext) { - const function_ = Hfunction.build.bind(Hfunction, hasardContext); +const {build} = Hfunction; +export default function operators(hasardContext) { + const function_ = build.bind(Hfunction, hasardContext); return { multiply: function_((...arguments_) => arguments_.reduce((a, b) => a * b, 1)), divide: function_((a, b) => a / b), @@ -14,4 +15,4 @@ module.exports = function (hasardContext) { concat: function_((a, b) => a.concat(b)), getProperty: function_((key, object) => object[key]), }; -}; +} diff --git a/package.json b/package.json index c00f8cd..2ea49f2 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "description": "Random variables and random nested objects manipulation in javascript", "main": "index.js", + "type": "module", "scripts": { "lint": "xo", "fmt": "xo --fix", @@ -62,7 +63,6 @@ "unicorn/no-new-array": 0, "unicorn/prevent-abbreviations": 0, "logical-assignment-operators": 0, - "unicorn/prefer-module": 0, "import/extensions": 0 } } diff --git a/test/helpers/test-distribution.js b/test/helpers/test-distribution.js index 5bcbecc..f130985 100644 --- a/test/helpers/test-distribution.js +++ b/test/helpers/test-distribution.js @@ -1,4 +1,4 @@ -module.exports = function (t, actualHasard, individualExpectation, globalExpectation = null) { +export default function testDistribution(t, actualHasard, individualExpectation, globalExpectation = null) { const n = 1000; return actualHasard.runAsync(n).then(result => { t.is(result.length, n); @@ -10,4 +10,4 @@ module.exports = function (t, actualHasard, individualExpectation, globalExpecta globalExpectation(t, result); } }); -}; +} diff --git a/test/index.js b/test/index.js index f93a3db..b759b23 100644 --- a/test/index.js +++ b/test/index.js @@ -1,8 +1,10 @@ /* eslint no-new: "off" */ /* eslint ava/prefer-async-await: "off" */ import test from 'ava'; -import { Value, Boolean, Number, Integer, String, Array as _Array, Object as _Object, array, add, Matrix, Reference, fn } from '..'; -import testDistribution from './helpers/test-distribution'; +import h, { + Value, Boolean, Number, Integer, String, Array as _Array, add, Matrix, Reference, fn, +} from '../index.js'; +import testDistribution from './helpers/test-distribution.js'; test('hasard.Value(Array.)', t => { const values = ['white', 'yellow']; @@ -17,7 +19,7 @@ test('hasard.Value(Array.)', t => { const average = 1 / values.length; const threshold = 1 / Math.sqrt(as.length); for (const c of counts) { - t.true(Math.abs(c - average) < threshold); + t.true(Math.abs(c - average) < threshold); // TODO: change this test failed randomly L 22 } }, ); @@ -138,7 +140,7 @@ test('hasard.Number(Object)', t => { const average = 1 / counts.length; const threshold = 1 / Math.sqrt(as.length); for (const c of counts) { - t.true(Math.abs(c - average) < threshold); // TODO: change this test failed randomly + t.true(Math.abs(c - average) < threshold); // TODO: change this test failed randomly L143 } }, ).then(() => { @@ -194,19 +196,19 @@ test('hasard.Number(Object)', t => { test('hasard.Integer([start, end])', t => { t.throws(() => { new Integer([1]); - }, {instanceOf: Error, message: '1 must be a length-2 array'}); + }, {instanceOf: Error, message: '1 must be a length-2 array'}); t.throws(() => { new Integer([0, 1, 2]); - }, {instanceOf: Error, message: '0,1,2 must be a length-2 array'}); + }, {instanceOf: Error, message: '0,1,2 must be a length-2 array'}); t.throws(() => { new Integer([0.1, 3]); - }, {instanceOf: Error, message: 'start (0.1) must be an integer'}); + }, {instanceOf: Error, message: 'start (0.1) must be an integer'}); t.throws(() => { new Integer([0, 3.1]); - }, {instanceOf: Error, message: 'end (3.1) must be an integer'}); + }, {instanceOf: Error, message: 'end (3.1) must be an integer'}); const range = [10, 15]; @@ -224,7 +226,7 @@ test('hasard.Integer([start, end])', t => { const average = 1 / values.length; const threshold = 1 / Math.sqrt(as.length); for (const c of counts) { - t.true(Math.abs(c - average) < threshold); // TODO: change this test failed randomly + t.true(Math.abs(c - average) < threshold); // TODO: change this test failed randomly L 229 } }, ); @@ -247,7 +249,7 @@ test('hasard.Integer(start, end)', t => { const average = 1 / values.length; const threshold = 1 / Math.sqrt(as.length); for (const c of counts) { - t.true(Math.abs(c - average) < threshold); + t.true(Math.abs(c - average) < threshold); // TODO: change this test failed randomly L 252 } }, ); @@ -390,7 +392,7 @@ test('hasard.Object(Object)', t => { } return testDistribution(t, - new _Object(options), + new h.Object(options), (t, a) => { for (const k of Object.keys(keys)) { t.not(keys[k].indexOf(a[k]), -1); @@ -400,7 +402,7 @@ test('hasard.Object(Object)', t => { }); test('hasard.Object(Hasard.>, Hasard)', t => { - const keys = array({ + const keys = h.array({ value: add( new Value(['+33', '+32', '+1']), new String({ @@ -418,15 +420,15 @@ test('hasard.Object(Hasard.>, Hasard)', t => { ); t.throws(() => { - (new _Object(['a', 'a', 'c'], new Value(['d', 'e', 'f']))); - }, + (new h.Object(['a', 'a', 'c'], new Value(['d', 'e', 'f']))); + }, {instanceOf: TypeError, message: 'keys must be unique (keys[1] \'a\' is duplicated)'}); t.throws(() => { - (new _Object(['a', {b: 'b'}], new Value(['d', 'e', 'f']))).runOnce(); + (new h.Object(['a', {b: 'b'}], new Value(['d', 'e', 'f']))).runOnce(); }, {instanceOf: TypeError, message: 'keys must be string array (keys[1] \'[object Object]\' should be a string)'}); return testDistribution(t, - new _Object( + new h.Object( keys, value, ), @@ -582,7 +584,7 @@ test('hasard.fn(Function)', t => { const addHasard = fn((a, b) => a + b); - const object = new _Object({ + const object = new h.Object({ a: referenceA, b: referenceB, sum: addHasard(referenceA, referenceB), diff --git a/test/issues.js b/test/issues.js index 7d2c654..00caa77 100644 --- a/test/issues.js +++ b/test/issues.js @@ -1,23 +1,23 @@ /* eslint no-new: "off" */ /* eslint ava/prefer-async-await: "off" */ import test from 'ava'; -import { value, reference, fn, array, integer } from '..'; -import testDistribution from './helpers/test-distribution'; +import h from '../index.js'; // { value, reference, fn, array, integer, } from +import testDistribution from './helpers/test-distribution.js'; test('Avoid duplication of randomly selected value (#3)', t => { const choices = ['a', 'b', 'c']; - const random1 = value(choices); - const reference1 = reference(random1); + const random1 = h.value(choices); + const reference1 = h.reference(random1); - const antiChoicesFunction = fn(a => { + const antiChoicesFunction = h.fn(a => { const index = choices.indexOf(a); const remaining = choices.slice(0, index).concat(choices.slice(index + 1)); return remaining; }); - const differentValues = array([ + const differentValues = h.array([ reference1, - value(antiChoicesFunction(reference1)), + h.value(antiChoicesFunction(reference1)), ]); return testDistribution(t, @@ -31,9 +31,9 @@ test('Avoid duplication of randomly selected value (#3)', t => { test('hasard.Array({values, size: h.integer}) (#8)', t => { const string = 'abcdefghijklmnopqrstuvwxyz'; const values = string.split(''); - const v = array({ + const v = h.array({ values, - size: integer(0, 3), + size: h.integer(0, 3), }); return testDistribution(t, v, From 1c0056bee120c68b4840a7d158a790b0e10b1b59 Mon Sep 17 00:00:00 2001 From: urielch Date: Tue, 5 Mar 2024 09:12:31 +0100 Subject: [PATCH 6/9] applay some xo rules --- index.js | 70 ++++++++++++++++++++--------------------- lib/hasard/array.js | 8 ++--- lib/hasard/object.js | 6 ++-- lib/hasard/reference.js | 6 ++-- package.json | 3 +- 5 files changed, 46 insertions(+), 47 deletions(-) diff --git a/index.js b/index.js index d1a5c01..a3e3642 100644 --- a/index.js +++ b/index.js @@ -58,56 +58,56 @@ export class Hasard { } } -const HasardLib = {...Hasard, ...methods(null)}; +const HasardLibrary = {...Hasard, ...methods(null)}; // Exports from operators.js -export const multiply = HasardLib.multiply; -export const divide = HasardLib.divide; -export const add = HasardLib.add; -export const substract = HasardLib.substract; +export const multiply = HasardLibrary.multiply; +export const divide = HasardLibrary.divide; +export const add = HasardLibrary.add; +export const substract = HasardLibrary.substract; // Can not export symbol 'if' // export const if = HasardLib.if; -export const round = HasardLib.round; -export const ceil = HasardLib.ceil; -export const floor = HasardLib.floor; -export const concat = HasardLib.concat; -export const getProperty = HasardLib.getProperty; +export const round = HasardLibrary.round; +export const ceil = HasardLibrary.ceil; +export const floor = HasardLibrary.floor; +export const concat = HasardLibrary.concat; +export const getProperty = HasardLibrary.getProperty; // End of exports from operators.js // exports from helpers -export const isHasard = HasardLib.isHasard; -export const fn = HasardLib.fn; -export const int = HasardLib.int; -export const num = HasardLib.num; -export const str = HasardLib.str; -export const ref = HasardLib.ref; +export const isHasard = HasardLibrary.isHasard; +export const fn = HasardLibrary.fn; +export const int = HasardLibrary.int; +export const num = HasardLibrary.num; +export const str = HasardLibrary.str; +export const ref = HasardLibrary.ref; // End of exports from helpers // export from cstrs -export const Integer = HasardLib.Integer; -export const Value = HasardLib.Value; -export const Array = HasardLib.Array; +export const Integer = HasardLibrary.Integer; +export const Value = HasardLibrary.Value; +export const Array = HasardLibrary.Array; // Export const Object = HasardLib.Object; -export const Number = HasardLib.Number; -export const Matrix = HasardLib.Matrix; -export const String = HasardLib.String; -export const Boolean = HasardLib.Boolean; -export const Reference = HasardLib.Reference; -export const Function = HasardLib.Function; +export const Number = HasardLibrary.Number; +export const Matrix = HasardLibrary.Matrix; +export const String = HasardLibrary.String; +export const Boolean = HasardLibrary.Boolean; +export const Reference = HasardLibrary.Reference; +export const Function = HasardLibrary.Function; // End of export from cstrs // export from lowercased cstrs -export const integer = HasardLib.Integer; -export const value = HasardLib.Value; -export const array = HasardLib.Array; -export const object = HasardLib.Object; -export const number = HasardLib.Number; -export const matrix = HasardLib.Matrix; -export const string = HasardLib.String; -export const boolean = HasardLib.Boolean; -export const reference = HasardLib.Reference; +export const integer = HasardLibrary.Integer; +export const value = HasardLibrary.Value; +export const array = HasardLibrary.Array; +export const object = HasardLibrary.Object; +export const number = HasardLibrary.Number; +export const matrix = HasardLibrary.Matrix; +export const string = HasardLibrary.String; +export const boolean = HasardLibrary.Boolean; +export const reference = HasardLibrary.Reference; // Export const function = HasardLib.Function; // end of export from lowercased cstrs // export default -export default HasardLib; +export default HasardLibrary; diff --git a/lib/hasard/array.js b/lib/hasard/array.js index 627b40d..a7c54b3 100644 --- a/lib/hasard/array.js +++ b/lib/hasard/array.js @@ -69,13 +69,13 @@ class ArrayHasard extends AbstractHasard { newValues = context.values; } - return newValues.map(v => { - if (ArrayHasard.isHasard(v)) { - const res = v.runOnce(runOptions); + return newValues.map(value => { + if (ArrayHasard.isHasard(value)) { + const res = value.runOnce(runOptions); return res; } - return v; + return value; }); } diff --git a/lib/hasard/object.js b/lib/hasard/object.js index 3934a1a..688692a 100644 --- a/lib/hasard/object.js +++ b/lib/hasard/object.js @@ -37,13 +37,13 @@ class ObjectHasard extends AbstractHasard { } getOpts(options) { - const res = Object.assign({}, options, {__hasardKeys: options.__hasardKeys, __hasardValue: options.__hasardValue}); - return res; + const result = {...options, __hasardKeys: options.__hasardKeys, __hasardValue: options.__hasardValue}; + return result; } resolve(unresolved, runOptions) { // Do not resolve "value" here, it will be resolved in generate - const overrideUnresolved = Object.assign({}, unresolved); + const overrideUnresolved = {...unresolved}; delete overrideUnresolved.__hasardValue; const res = Object.assign(super.resolve(overrideUnresolved, runOptions), {__hasardValue: unresolved.__hasardValue}); return res; diff --git a/lib/hasard/reference.js b/lib/hasard/reference.js index 807a278..976fcdb 100644 --- a/lib/hasard/reference.js +++ b/lib/hasard/reference.js @@ -19,15 +19,15 @@ class ReferenceHasard extends AbstractHasard { const context_ = typeof (context) === 'string' ? context : 'global'; if (!runOptions.refs || !runOptions.refs[context_] || (runOptions.refs[context_][id]) === undefined) { - const res = source.runOnce(runOptions); + const result = source.runOnce(runOptions); runOptions.refs ||= {}; if (!runOptions.refs[context_]) { runOptions.refs[context_] = {}; } - runOptions.refs[context_][id] = res; - return res; + runOptions.refs[context_][id] = result; + return result; } return runOptions.refs[context_][id]; diff --git a/package.json b/package.json index 2ea49f2..4edf8e1 100644 --- a/package.json +++ b/package.json @@ -62,8 +62,7 @@ "rules": { "unicorn/no-new-array": 0, "unicorn/prevent-abbreviations": 0, - "logical-assignment-operators": 0, - "import/extensions": 0 + "logical-assignment-operators": 0 } } } From c7c9f1a782b5c674cbbec0533aeaf5db8424d6eb Mon Sep 17 00:00:00 2001 From: urielch Date: Tue, 5 Mar 2024 09:59:10 +0100 Subject: [PATCH 7/9] improve imports --- examples/random-object-generator.js | 2 +- examples/random-usa-users.js | 2 +- lib/hasard/abstract.js | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/random-object-generator.js b/examples/random-object-generator.js index c720ab5..5242f80 100644 --- a/examples/random-object-generator.js +++ b/examples/random-object-generator.js @@ -1,4 +1,4 @@ -import * as h from '../index.js'; +import h from '../index.js'; const randomValue = h.value(); diff --git a/examples/random-usa-users.js b/examples/random-usa-users.js index d2d3bbc..4789c69 100644 --- a/examples/random-usa-users.js +++ b/examples/random-usa-users.js @@ -1,4 +1,4 @@ -import * as h from '../index.js'; +import h from '../index.js'; const givenNames = ['Veronica', 'Mercedes', diff --git a/lib/hasard/abstract.js b/lib/hasard/abstract.js index 9d0728e..5c8a33d 100644 --- a/lib/hasard/abstract.js +++ b/lib/hasard/abstract.js @@ -98,7 +98,7 @@ class AbstractHasard { return this._runOnce(runOptions); } - generate() { + generate(_ctxt, _runOptions) { throw (new Error('override me')); } @@ -107,7 +107,8 @@ class AbstractHasard { return options; } - check() { + // abstract + check(..._values) { // Do nothing, override me to do sthg } } From c81e0e7b707b2c069547b319740420198980a147 Mon Sep 17 00:00:00 2001 From: urielch Date: Tue, 5 Mar 2024 10:00:26 +0100 Subject: [PATCH 8/9] use static isHasard directly not using constructor. --- lib/hasard/integer.js | 2 +- lib/hasard/number.js | 2 +- lib/hasard/object.js | 2 +- lib/hasard/reference.js | 13 ++++++++++++- lib/hasard/value.js | 14 ++++++++++++-- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/hasard/integer.js b/lib/hasard/integer.js index 909a3f6..9d75b31 100644 --- a/lib/hasard/integer.js +++ b/lib/hasard/integer.js @@ -14,7 +14,7 @@ class IntegerHasard extends AbstractHasard { set(start, end) { if ((end) === undefined) { super.set(start); - } else if (typeof (end) === 'number' || this.constructor.isHasard(end)) { + } else if (typeof (end) === 'number' || AbstractHasard.isHasard(end)) { super.set([start, end]); } else { throw (new Error(`second argument ${end} is not valid`)); diff --git a/lib/hasard/number.js b/lib/hasard/number.js index b91818d..463f437 100644 --- a/lib/hasard/number.js +++ b/lib/hasard/number.js @@ -14,7 +14,7 @@ class NumberHasard extends AbstractHasard { set(start, end) { if ((end) === undefined) { super.set(start); - } else if (typeof (end) === 'number' || this.constructor.isHasard(end)) { + } else if (typeof (end) === 'number' || AbstractHasard.isHasard(end)) { super.set([start, end]); } else { throw (new Error(`second argument ${end} is not valid`)); diff --git a/lib/hasard/object.js b/lib/hasard/object.js index 688692a..426e81c 100644 --- a/lib/hasard/object.js +++ b/lib/hasard/object.js @@ -52,7 +52,7 @@ class ObjectHasard extends AbstractHasard { generate(context, runOptions) { if (context.__hasardKeys) { // Console.log('here', ctx, this.constructor.isHasard(ctx.__hasardValue), ctx.__hasardValue) - const values = this.constructor.isHasard(context.__hasardValue) ? context.__hasardValue.run(context.__hasardKeys.length, runOptions) : Array.from({length: context.__hasardKeys.length}).fill(context.__hasardValue); + const values = AbstractHasard.isHasard(context.__hasardValue) ? context.__hasardValue.run(context.__hasardKeys.length, runOptions) : Array.from({length: context.__hasardKeys.length}).fill(context.__hasardValue); const res = {}; for (const [index, k] of context.__hasardKeys.entries()) { diff --git a/lib/hasard/reference.js b/lib/hasard/reference.js index 976fcdb..148a6fc 100644 --- a/lib/hasard/reference.js +++ b/lib/hasard/reference.js @@ -3,6 +3,10 @@ import RandomString from './string.js'; import RandomValue from './value.js'; class ReferenceHasard extends AbstractHasard { + /** + * @param {{ source?: any; }} unresolved + * @param {any} runOptions + */ resolve(unresolved, runOptions) { // Do not resolve "source" here, it will be resolved in generate const overrideUnresolved = Object.assign({}, unresolved); @@ -12,7 +16,7 @@ class ReferenceHasard extends AbstractHasard { } generate({id, context, source}, runOptions) { - if (!this.constructor.isHasard(source)) { + if (!AbstractHasard.isHasard(source)) { return source; } @@ -33,12 +37,19 @@ class ReferenceHasard extends AbstractHasard { return runOptions.refs[context_][id]; } + /** + * @param {string} key + * @param {null} value + */ check(key, value) { if (key === 'context' && value !== null && (value) !== undefined && typeof (value) !== 'string') { throw (new TypeError(`${key} (${value}) must be a string`)); } } + /** + * @param {{ source: any; context: any; }} options + */ getOpts(options) { const randomString = new RandomString({ value: new RandomValue('0123456789ABCDEF'.split('')), diff --git a/lib/hasard/value.js b/lib/hasard/value.js index 2020f22..166fc34 100644 --- a/lib/hasard/value.js +++ b/lib/hasard/value.js @@ -1,7 +1,7 @@ import AbstractHasard from './abstract.js'; // Const { isHasard } = AbstractHasard; -const getRanges = function (array) { +const getRanges = function (/** @type {any} */ array) { const result = []; let current = 0; for (const v of array) { @@ -13,6 +13,10 @@ const getRanges = function (array) { }; class ValueHasard extends AbstractHasard { + /** + * @param {string} key + * @param {any[]} value + */ check(key, value) { if (key === 'weights' && Array.isArray(value)) { const sum = value.reduce((a, b) => a + b, 0); @@ -23,6 +27,9 @@ class ValueHasard extends AbstractHasard { } } + /** + * @param {{ choices?: any; weights?: any; }} options + */ getOpts(options) { let choices; @@ -42,6 +49,9 @@ class ValueHasard extends AbstractHasard { }; } + /** + * @param {{ weights?: any; choices?: any; }} context + */ generate(context) { let choice; @@ -58,7 +68,7 @@ class ValueHasard extends AbstractHasard { choice = context.choices[Math.floor(this.prng() * context.choices.length)]; } - if (this.constructor.isHasard(choice)) { + if (AbstractHasard.isHasard(choice)) { return choice.runOnce(); } From 67230de7fb59e2c2b9775aa3d850d616c9119207 Mon Sep 17 00:00:00 2001 From: urielch Date: Tue, 5 Mar 2024 10:00:40 +0100 Subject: [PATCH 9/9] typo in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6967c77..65ad045 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ console.log(value); You can customize the [Pseudorandom number generator](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) which is `Math.random` by default. ```javascript -const n = h.value({choices: ['white', 'yellow'], prng: <custom prng>}) +const n = h.value({choices: ['white', 'yellow'], prng: }) ``` ## Basic types @@ -351,7 +351,7 @@ Example of use const refA = h.reference(h.number(0, 1)); const refB = h.reference(h.number(0, 1)); -const addHasard = h.fn((a, b) => { +const addHasard = h.fn((a, b) => { return a + b; });