hasard

1.6.1 • Public • Published

Build Status

codecov

Installation

npm install hasard

Description

Random variables and random nested objects manipulation in javascript

Inspired by :

Features:

  • Generate basic types randomly (string, number, boolean, integer)
  • Nested random object (array, object, matrix)
  • Use distribution to generate numbers (normal, uniform, truncated-normal) and integers (poisson, uniform)
  • Add reference + context to fix a random variable value in a local context
  • Easy-to-use common operators on random variable (add, substract, divide, multiply, round, ceil, floor)
  • Create custom operators
  • Change the Pseudorandom number generator
  • Stream API

Simple Usage

const h = require('hasard');
 
const v = h.object({
    color: h.value(['white', 'yellow']), // randomly choose between 2 values
    size: h.integer(10, 20) // randomly choose an integer between 10 and 20
});
 
const values = v.run(3);
console.log(values);
// [{color: 'white', size: 12}, {color: 'yellow', size: 18}, {color: 'yellow', size: 17}]
 
const value = v.runOnce();
console.log(value);
// {color: 'white', size: 13}

Prng

You can customize the Pseudorandom number generator which is Math.random by default.

const n = h.value({choices: ['white', 'yellow'], prng: <custom prng>})

Basic types

h.value

h.value(Array.<Hasard> | Hasard.<Array>)

const v = h.value(['white', 'yellow']);

h.value({choices: Array.<Hasard> | Hasard.<Array>, weights}) -> Hasard

const v = h.value({
    choices: ['white', 'yellow'],
    weights: [0.75, 0.25]
});

h.boolean

h.boolean({Hasard.<Number>} probability) -> Hasard.<Boolean>

const v = h.boolean(0.2); // will be true 20% of the time

h.boolean({prob: Hasard.<Number>}) -> Hasard.<Boolean>

const v = h.boolean({prob: 0.3}); // will be true 30% of the time

h.number

h.number({Hasard.<Number>} start, {Hasard.<Number>} end) -> Hasard.<Number>

const v = h.number(0, 1);

h.number([{Hasard.<Number>} start, {Hasard.<Number>} end]) -> Hasard.<Number>

const v = h.number([0, 1]);

h.number({type: String, ...}) -> Hasard.<Number>

Available distribution for numbers are

  • normal
  • uniform
  • truncated-normal

Please Open an issue if you need another distribution

const v = h.number({
    type: 'uniform',
    start: 0,
    end: 1
});
const v = h.number({
    type: 'normal',
    mean: -2,
    std: 3
});

h.integer

h.integer({Hasard.<Integer>} start,{Hasard.<Integer>} end) -> Hasard.<Integer>

const v = h.integer(0, 10);

h.integer([{Hasard.<Integer>} start,{Hasard.<Integer>} end]) -> Hasard.<Integer>

const v = h.integer([0, 10]);

h.integer({type: String, ...}) -> Hasard.<Integer>

For now, the only available distribution for integer is poisson, please Open an issue

const v = h.integer({
    type: 'poisson',
    lambda: 3
});

h.string

h.string({value: Hasard, size: Hasard.<integer>}) -> Hasard.<String>

const v = h.string({
    value: h.value(["a", "b", "c", "d"]),
    size: h.integer([5, 10])
});

h.array

h.array({value: Hasard, size: Hasard.<Integer>}) -> Hasard.<Array>

const v = h.array({
    value: h.integer([0, 255]),
    size: h.integer([5, 10]),
});

h.array(Array.<Hasard>) -> Hasard.<Array>

const v = h.array([
    h.integer([0, 255]),
    h.integer([0, 255]),
    h.integer([0, 255])
]);

h.array({values: Array.<Hasard>, size: Hasard.<Integer>, randomOrder: Hasard.<Boolean>}) -> Hasard.<Array>

// pick 5 digits in a randomOrder
const v = h.array({
    values: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    size: 5,
    randomOrder: true
});

h.object

h.object(Object.<String, Hasard>) -> Hasard.<Object>

const obj = h.object({
    color1 : h.value(['white', 'yellow']),
    color2 : h.value(['black', 'grey'])
});

h.object(Hasard.<Array.>, Hasard) -> Hasard.<Object>

const phoneNumber = 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']),
            size: 9 // 9 digits in phone numbers
        })
    ),
    size : 5 // 5 keys
});
 
const fullName = hasard.add(
    new hasard.Value(['Mr ', '']),
    new hasard.Value(['Thomas ', 'Nicolas ', 'Julien ', 'Quentin ', 'Maxime ']),
    new hasard.Value(['DURAND', 'DUBOIS', 'LEFEBVRE', 'MOREAU', 'MOREL', 'FOURNIER'])
);
 
const randomPhoneDirectory = h.object(phoneNumber, fullName);
 
randomPhoneDirectory.run(2) // run 2 times
//
// { 
//   '+33236972292': 'M Julien FOURNIER',
//   '+1833509762': 'Mr Quentin DURAND',
//   '+33210149263': 'Mr Maxime MOREAU',
//   '+1807872258': 'Mr Julien DURAND',
//   '+32215961607': 'M Julien DUBOIS'
// }
// 
// { 
//   '+32067043361': 'Mr Nicolas MOREL',
//   '+33898861064': 'Mr Thomas DURAND',
//   '+33730685919': 'Mr Nicolas MOREL',
//   '+33723780566': 'M Nicolas FOURNIER',
//   '+33515400984': 'Mr Quentin DUBOIS'
// }

h.matrix

h.matrix({value: Hasard, shape: Hasard.<Array.<Integer>>}) -> Hasard.<Matrix>

create matrix with a specific shape

const v = h.matrix({
    value: h.integer([0, 255]),
    shape: [128, 128, 3]
});

create random matrix with random values and random size

const v = h.matrix({
    value: h.integer([0, 255]),
    shape: h.array({
        value: h.integer([5, 10]),
        size: h.integer([1, 4])
    })
});

h.reference

h.reference(Hasard) -> Hasard

A reference is generated only once per objet per run.

Let's take an example of how it can be used

const value = h.integer([0, 255]);
const v = h.array([
    value,
    value,
    value
]);
 
v.run(2);
// all values are randomized independently
// [[22, 128, 54], [250, 134, 12]]
 
const ref = h.reference(h.Integer([0, 255]));
const v = h.array([
    ref,
    ref,
    ref
]);
 
v.run(2);
// reference is reused inside the same run
// [[72, 72, 72], [114, 114, 114]]

h.reference({source: Hasard, context: Hasard.<String>}) -> Hasard

When defined with a context, the reference is related to a context. You can define a context with any Hasard tool, by using {contextName: &lt;name of the context&gt;}

 
// we will create a grey image in RGB so R = G = B
const ref = h.reference({
    source: h.Integer([0, 255]),
    context: 'pixel'
});
 
// Here we need to use the form h.array({values, contextName})
const pixel = h.array({
    values: [
        ref,
        ref,
        ref
    ],
    contextName: 'pixel'
});
 
const img = h.matrix({
    value: pixel,
    shape: [2,2]
})
 
v.run(2);
// reference is reused inside the same pixel
// [
//   [[[12, 12, 12],[145, 145, 145]],[[251, 251, 251],[88, 88, 88]]], // first run,
//   [[[212, 212, 212],[2, 2, 2]],[[78, 78, 78],[130, 130, 130]]] // second run,
//]

Helpers

h.isHasard(Any) -> Boolean

Check if the object is an instance of the hasard library

const value = h.integer([0, 255]);
 
h.isHasard(value); // true
h.isHasard([0, 255]); // false

h.fn(Function(Any, ...)) -> Function(Hasard.<Any>, ...)

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) =&gt; {
    return a + b;
});
 
const obj = h.object({
    a: refA,
    b: refB,
    sum: addHasard(refA, refB)
});

Shortcuts

Hasard provides shortcuts for most common operations

h.add(Hasard.<Number>, Hasard.<Number>, ...) -> Hasard.<Number>

const refA = h.reference(h.number(0, 1));
const refB = h.reference(h.number(0, 1));
 
const obj = h.object({
    a: refA,
    b: refB,
    sum: h.add(refA, refB)
});

h.add(Hasard.<String>, Hasard.<String>, ...) -> Hasard.<String>

const a = h.value(['M. ', 'Mme ']);
const b = h.value(['DUPONT', 'DURANT']);
 
h.add(a, b).run(2)
// ['M. DUPONT', 'M. DURANT']

h.substract(Hasard.<Number>, Hasard.<Number>) -> Hasard.<Number>

const refA = h.reference(h.number(0, 1));
const refB = h.reference(h.number(0, 1));
 
const obj = h.object({
    a: refA,
    b: refB,
    diff: h.substract(refA, refB)
});

h.multiply(Hasard.<Number>, Hasard.<Number>) -> Hasard.<Number>

const refA = h.reference(h.number(0, 1));
const refB = h.reference(h.number(0, 1));
 
const obj = h.object({
    a: refA,
    b: refB,
    mul: h.multiply(refA, refB)
});

h.divide(Hasard.<Number>, Hasard.<Number>) -> Hasard.<Number>

const refA = h.reference(h.number(0, 1));
const refB = h.reference(h.number(1, 2));
 
const obj = h.object({
    a: refA,
    b: refB,
    ratio: h.divide(refA, refB)
});

h.if(Hasard.<Boolean>, Hasard, Hasard) -> Hasard

const test = h.boolean(0.5);
const poisson = h.reference(h.integer({type: 'poisson', lambda: '3'}));
 
const signedPoisson = h.multiply(h.if(test, -1, 1), poisson)

h.round(Hasard.<Number>) -> Hasard.<Integer>

const int = h.round(h.number(0, 10));

h.floor(Hasard.<Number>) -> Hasard.<Integer>

const int = h.floor(h.number(0, 10));

h.ceil(Hasard.<Number>) -> Hasard.<Integer>

const int = h.ceil(h.number(0, 10));

h.concat(Hasard.<Array>, Hasard.<Array>) -> Hasard.<Array>

const int = h.concat([1,2], h.array({value: h.integer([0, 10]), size: 3}));

h.getProperty(Hasard.<Number>, Hasard.<Object> | Hasard.<Array>) -> Hasard

const int = h.getProperty(0, h.array({value: h.integer([0, 10]), size: 3}));

Nested randomness

Using set method, object properties can be set afterward

Generate a random nested Object

const randomValue = h.value();
 
const randomInteger = h.integer({type: 'poisson', lambda: 4});
 
const randomString = h.string({
    size: h.add(randomInteger, 5),
    value: h.value('abcdefghijklmnopkrstuvw'.split(''))
});
 
const randomNumber = h.number(0, 100);
 
const randomKeys = h.array({
    size: randomInteger,
    value: randomString
});
 
const randomObject = h.object(
    randomKeys,
    randomValue
);
 
randomValue.set({
    choices: [
        randomString,
        randomObject,
        randomNumber,
        randomInteger
    ]
});
 
console.log(randomObject.run(1));

Stream API

const h = require('hasard');
 
const v = h.object({
    color: h.value(['white', 'yellow']), // randomly choose between 2 values
    size: h.integer(10, 20) // randomly choose an integer between 10 and 20
});
 
const streamValue = v.stream(3);
 
streamValue.on('data', d => {
    console.log(d);
})

Package Sidebar

Install

npm i hasard

Weekly Downloads

12

Version

1.6.1

License

MIT

Unpacked Size

229 kB

Total Files

31

Last publish

Collaborators

  • piercus