bali-component-framework
Version:
This library provides a JavaScript based implementation of the Bali Nebula™ Component Framework.
116 lines (98 loc) • 4.15 kB
JavaScript
/************************************************************************
* Copyright (c) Crater Dog Technologies(TM). All Rights Reserved. *
************************************************************************
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. *
* *
* This code is free software; you can redistribute it and/or modify it *
* under the terms of The MIT License (MIT), as published by the Open *
* Source Initiative. (See http://opensource.org/licenses/MIT) *
************************************************************************/
;
/**
* This class provides cryptographically secure random value generation.
*/
const crypto = require('crypto');
const Decoder = require('./Decoder').Decoder;
// PRIVATE CONSTANTS
const MAXIMUM_INTEGER = 4294967296; // unsigned
// PUBLIC FUNCTIONS
/**
* This function returns a new random number generator.
*
* An optional debug argument may be specified that controls the level of debugging that
* should be applied during execution. The allowed levels are as follows:
* <pre>
* 0: no debugging is applied (this is the default value and has the best performance)
* 1: log any exceptions to console.error before throwing them
* 2: perform argument validation checks on each call (poor performance)
* 3: log interesting arguments, states and results to console.log
* </pre>
*
* @returns {Generator} The new generator.
*/
const Generator = function(debug) {
this.debug = debug || 0;
return this;
};
Generator.prototype.constructor = Generator;
exports.Generator = Generator;
/**
* This method returns a binary string of the specified size containing
* randomly generated bytes.
*
* @param {Number} numberOfBytes The number of bytes in the desired binary string.
* @return {Buffer} A data buffer containing random bytes.
*/
Generator.prototype.generateBytes = function(numberOfBytes) {
try {
const buffer = crypto.randomBytes(numberOfBytes);
return buffer;
} catch (cause) {
const exception = Error('There was not enough system entropy to generate random bytes.');
if (debug > 0) console.error(exception);
throw exception;
}
};
/**
* This method returns a random integer in the range -2147483648..2147483647.
*
* @return {Number} The random integer.
*/
Generator.prototype.generateInteger = function() {
const decoder = new Decoder(0, this.debug);
const integer = decoder.bytesToInteger(this.generateBytes(4));
return integer;
};
/**
* This method returns a random index in the range in the range 1..length.
*
* @param {Number} length The length of the collection being indexed.
* @return {Number} The random ordinal index.
*/
Generator.prototype.generateIndex = function(length) {
const randomInteger = (this.generateInteger() + MAXIMUM_INTEGER) % MAXIMUM_INTEGER; // in range 0..MAX
const index = (randomInteger % length) + 1; // in range 1..length for ordinal based indexing
return index;
};
/**
* This method returns a random probability in the range in the range 0..1.
*
* @return {Number} The random probability.
*/
Generator.prototype.generateProbability = function() {
const randomInteger = (this.generateInteger() + MAXIMUM_INTEGER) % MAXIMUM_INTEGER; // in range 0..MAX
const probability = randomInteger / MAXIMUM_INTEGER; // in range 0..1
return probability;
};
/**
* This method returns the result of a weighted coin toss. A probability of
* zero will always return false and a probability of one will always return true.
*
* @param {Number} weight The probability that the toss will return true [0.0..1.0].
* @return {Boolean} The result of the coin toss.
*/
Generator.prototype.flipCoin = function(weight) {
const randomInteger = (this.generateInteger() + MAXIMUM_INTEGER) % MAXIMUM_INTEGER; // in range 0..MAX
const toss = randomInteger / (MAXIMUM_INTEGER - 1); // convert to range [0.0..1.0)
return toss < weight; // true: [0.0..probability) and false: [probability..1.0]
};