@antv/data-wizard
Version:
A js/ts library for data processing
201 lines (200 loc) • 7.28 kB
JavaScript
import MersenneTwister from 'mersenne-twister';
import RandExp from 'randexp';
import { assert, range } from '../utils';
import { initOptions, MAX_INT, MIN_INT } from './utils';
function isFunction(target) {
return typeof target === 'function';
}
/**
* Basic(bool int float regexp) Generater
* basic generator for bool int float regexp
* @public
*/
var BasicRandom = /** @class */ (function () {
function BasicRandom(seed) {
// if user has provided a function, use that as the generator
if (isFunction(seed)) {
this.random = seed;
}
else {
// If no generator function was provided, use MT
// If seed is undefined, create a random number as seed to avoid the case that timestamps are the same.
this.seed = seed || new Date().getTime() + +("" + Math.random()).slice(2);
this.mt = new MersenneTwister(this.seed);
this.random = this.mt.random.bind(this.mt);
}
}
/**
* extends class's prototype
* @param options - methods
*
* @example
* ```javascript
* BasiceRandom.mixin({
* percent() {
* return `${this.float({ min: 0, max: 100, fixed: 2 })}%`;
* },
* });
*
* const R = new Random();
* R.percent(); // '10.12%'
* R.n(R.percent, 2) // ['12.10%', '25.22%']
* ```
*/
BasicRandom.mixin = function (options) {
for (var i = 0; i < Object.keys(options || {}).length; i += 1) {
var key = Object.keys(options)[i];
var value = options[key];
this.prototype[key] = value;
}
};
/**
* Return a random boolean value (true or false).
* @param options - options
*/
BasicRandom.prototype.boolean = function (options) {
var likelihood = initOptions({ likelihood: 50 }, options).likelihood;
assert(likelihood >= 0 && likelihood <= 100, 'Likelihood accepts values from 0 to 100.');
return this.random() > likelihood / 100;
};
/**
* Reture a random integer
* @param options - options
*/
BasicRandom.prototype.integer = function (options) {
var _a = initOptions({ min: MIN_INT, max: MAX_INT }, options), max = _a.max, min = _a.min;
assert(min <= max, 'Min cannot be greater than Max.');
return Math.floor(this.random() * (max - min + 1) + min);
};
/**
* Genarate a float / double number
*
* @param options -
*/
BasicRandom.prototype.float = function (options) {
if (options === void 0) { options = {}; }
var opts = initOptions({ fixed: 4 }, options);
var base = Math.pow(10, opts.fixed);
var max = MAX_INT / base;
var min = -max;
assert(!opts.min || !opts.fixed || opts.min >= min, "Min specified is out of range with fixed. Min should be, at least, " + min);
assert(!opts.max || !opts.fixed || opts.max <= max, "Max specified is out of range with fixed. Max should be, at most, " + max);
var optss = initOptions({ min: min, max: max }, opts);
var num = this.integer({ min: optss.min * base, max: optss.max * base });
var numFixed = (num / base).toFixed(opts.fixed);
return Number.parseFloat(numFixed);
};
/**
* generate an integer number
* @param options -
*/
BasicRandom.prototype.natural = function (options) {
if (options === void 0) { options = {}; }
var opts = initOptions({ min: 0, max: MAX_INT }, options);
assert(opts.min >= 0, 'Min cannot be less than zero.');
return this.integer(opts);
};
/**
* Given an array, pick a random element and return it
* @param array - The array to process
*
*/
BasicRandom.prototype.pickone = function (array) {
assert(array.length !== 0, 'Cannot pickone() from an empty array');
return array[this.natural({ max: array.length - 1 })];
};
/**
* Given an array, pick some random elements and return them in a new array
* @param array - the array to process
* @param count - the counts to pick
*/
BasicRandom.prototype.pickset = function (array, count) {
if (count === void 0) { count = 1; }
if (count === 0)
return [];
assert(array.length !== 0, 'Cannot pickset() from an empty array');
assert(count >= 0, 'Count must be a positive number');
if (count === 1) {
return [this.pickone(array)];
}
var arr = array.slice(0);
var end = arr.length;
return this.n(function gen() {
end -= 1;
var index = this.natural({ max: end });
var value = arr[index];
arr[index] = arr[end];
return value;
}, Math.min(end, count));
};
/**
* Given an array, scramble the order and return it.
* @param array - the array to process
* @public
*/
BasicRandom.prototype.shuffle = function (array) {
var newArray = [];
var j = 0;
var length = array.length;
var sourceIndexes = range(length);
var lastSourceIndex = length - 1;
var selectedSourceIndex;
for (var i = 0; i < length; i += 1) {
// Pick a random index from the array
selectedSourceIndex = this.natural({ max: lastSourceIndex });
j = sourceIndexes[selectedSourceIndex];
// Add it to the new array
newArray[i] = array[j];
// Mark the source index as used
sourceIndexes[selectedSourceIndex] = sourceIndexes[lastSourceIndex];
lastSourceIndex -= 1;
}
return newArray;
};
/**
* Provide any function that generates random stuff (usually another generate function)
* and a number and n() will generate an array of items with a length matching the length you specified.
* @param generator - the generator
* @param length - the length
* @param params - the generator's params
*
* @example
* ```javascript
* const R = new Random();
* R.n(R.natural, 10, { min: 0, max: 100 }); // ten numbers which arn between 0 and 100
* ```
*/
BasicRandom.prototype.n = function (generator, length) {
if (length === void 0) { length = 1; }
var params = [];
for (var _i = 2; _i < arguments.length; _i++) {
params[_i - 2] = arguments[_i];
}
assert(typeof generator === 'function', 'The first argument must be a function.');
var i = length;
var arr = [];
// Providing a negative count should result in a noop.
i = Math.max(0, i);
for (; i > 0; i -= 1) {
arr.push(generator.apply(this, params));
}
return arr;
};
/**
* Generate a string which match regexp
*
* @example
* ```javascript
* new Random().randexp('\\d{4}-\\d{8}');
* ```
*
* @param source - regexp or source of regexp
* @param flag - flag(only support `i`)
*/
BasicRandom.prototype.randexp = function (source, flag) {
var rand = new RandExp(source, flag);
return rand.gen();
};
return BasicRandom;
}());
export { BasicRandom };