UNPKG

@antv/data-wizard

Version:
201 lines (200 loc) 7.28 kB
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 };