fascinus/random-ext.js

390 lines
11 KiB
JavaScript

/*!
* random-ext
* https://github.com/bkumar2/random-ext.git
*
* Copyright 2014 Bipul Kumar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function _array(length, elementFunction, args) {
var array = [];
if (length != null) {
for (var i = 0; i < length; ++i) {
array[i] = elementFunction.apply(this, args);
}
} else {
throw "length is required.";
}
return array;
}
function boolean() {
return Math.random() < 0.5;
}
function booleanArray(length) {
return _array(length, boolean);
}
function float(limit, min) {
if (limit != null) {
if (min != null) {
return Math.random() * (limit - min) + min;
} else {
return Math.random() * limit;
}
} else {
throw "max is required.";
}
}
function floatArray(length, limit, min) {
return _array(length, float, [limit, min]);
}
function integer(max, min) {
if (max != null) {
if (min != null) {
if (max < min) {
throw "max [" + max + "] is less than min [" + min + "]";
}
return Math.floor(Math.random() * (max - min + 1)) + min;
} else {
return Math.floor(Math.random() * (max + 1));
}
} else {
throw "max is required.";
}
}
function integerArray(length, max, min) {
return _array(length, integer, [max, min]);
}
function _normalizeRanges(ranges) {
if (randomExt.DEBUG) {
console.log("Normalizing ranges:", ranges);
}
ranges.sort(function (a, b) {
return a[0] - b[0];
});
if (randomExt.DEBUG) {
console.log("sorted ranges:", ranges);
}
for (var i = 0; i < ranges.length - 1; ++i) {
for (var j = i + 1; j < ranges.length; ++j) {
// remove right contained
if (ranges[i][1] >= ranges[j][1]) {
ranges.splice(j, 1);
j--;
}
// fix overlap
else if (ranges[i][1] >= ranges[j][0]) {
ranges[j][0] = ranges[i][1] + 1;
}
if (randomExt.DEBUG) {
console.log("iteration (" + i + "," + j + "):", ranges);
}
}
}
if (randomExt.DEBUG) {
console.log("Normalized ranges:", ranges);
}
}
function _integerFromRanges(ranges) {
_normalizeRanges(ranges);
if (ranges != null) {
var span = 0;
for (var i = 0; i < ranges.length; ++i) {
span += ranges[i][1] - ranges[i][0] + 1;
}
var randomNumber = Math.floor(Math.random() * span);
for (var i = 0; i < ranges.length; ++i) {
randomNumber += ranges[i][0];
if (randomNumber <= ranges[i][1]) {
break;
} else {
randomNumber -= ranges[i][1] + 1;
}
}
return randomNumber;
} else {
throw "ranges is required.";
}
}
function _integerArrayFromRanges(length, ranges) {
var numberArray = [];
if (length != null && ranges != null) {
for (var i = 0; i < length; ++i) {
numberArray[i] = _integerFromRanges(ranges);
}
} else {
throw "length and ranges is required.";
}
return numberArray;
}
function _stringFromRanges(maxLength, minLength, ranges) {
var dString = "";
var length = integer(maxLength, minLength);
var unicodeNumbers = _integerArrayFromRanges(length, ranges);
dString = String.fromCharCode.apply(this, unicodeNumbers);
return dString;
}
function date(endDate, startDate) {
if (endDate == null) {
throw "end date is required.";
}
var endDateTime = endDate.getTime();
var startDateTime = startDate != null ? startDate.getTime() : 0;
return new Date(integer(endDateTime, startDateTime));
}
function dateArray(length, endDate, startDate) {
return _array(length, date, [endDate, startDate]);
}
function string(maxLength, minLength) {
if (randomExt.DEBUG) {
console.log("string maxLength:", maxLength, " minLength:", minLength);
}
return _stringFromRanges(maxLength, minLength, [[32, 126]]);
}
function uString(maxLength, minLength) {
if (randomExt.DEBUG) {
console.log("string maxLength:", maxLength, " minLength:", minLength);
}
return _stringFromRanges(maxLength, minLength, [[1, 9999]]);
}
function stringArray(arrayLength, stringMaxLength, stringMinLength) {
return _array(arrayLength, string, [stringMaxLength, stringMinLength]);
}
function restrictedString(content, maxLength, minLength) {
var ranges = [];
for (var i = 0; i < content.length; ++i) {
var contentType = content[i];
switch (contentType) {
case randomExt.CHAR_TYPE.SPECIAL:
ranges = ranges.concat([
[33, 47],
[58, 64],
[91, 96],
[123, 126],
]);
break;
case randomExt.CHAR_TYPE.SPACE:
ranges = ranges.concat([[32, 32]]);
break;
case randomExt.CHAR_TYPE.NUMERIC:
ranges = ranges.concat([[48, 57]]);
break;
case randomExt.CHAR_TYPE.UPPERCASE:
ranges = ranges.concat([[65, 90]]);
break;
case randomExt.CHAR_TYPE.LOWERCASE:
ranges = ranges.concat([[97, 122]]);
break;
case randomExt.CHAR_TYPE.HEX:
ranges = ranges.concat([
[48, 57],
[97, 102],
]);
break;
default:
if (typeof contentType === "string") {
for (var j = 0; j < contentType.length; ++j) {
ranges = ranges.concat([
[contentType.charCodeAt(j), contentType.charCodeAt(j)],
]);
}
}
}
}
return _stringFromRanges(maxLength, minLength, ranges);
}
function restrictedStringArray(arrayLength, content, stringMaxLength, stringMinLength) {
return _array(arrayLength, restrictedString, [content, stringMaxLength, stringMinLength]);
}
function _fromDescriptor(randomDescriptor) {
var randomValue = null;
if (
randomDescriptor == null ||
!randomDescriptor.shift ||
randomDescriptor.length <= 0 ||
typeof randomDescriptor[0] !== "function"
) {
randomValue = randomDescriptor;
} else {
var randomFunction = randomDescriptor[0];
if (randomDescriptor.length > 1) {
var propertyValueArgs = randomDescriptor.slice(1, randomDescriptor.length);
randomValue = randomFunction.apply(this, propertyValueArgs);
} else {
randomValue = randomFunction();
}
}
return randomValue;
}
function object(template) {
if (randomExt.DEBUG) {
console.log("object template:", template);
}
var newObject = {};
var properties = Object.getOwnPropertyNames(template);
for (var i = 0; i < properties.length; ++i) {
var property = properties[i];
var randomDescriptor = template[property];
newObject[property] = _fromDescriptor(randomDescriptor);
}
return newObject;
}
function objectArray(length, template) {
return _array(length, object, [template]);
}
function stringPattern(pattern, variableDefinition) {
var stringPattern = pattern;
var properties = Object.getOwnPropertyNames(variableDefinition);
var replacedStringArray = new Array();
for (var i = 0; i < stringPattern.length; ++i) {
if (variableDefinition.hasOwnProperty(stringPattern[i])) {
replacedStringArray[i] = _fromDescriptor(variableDefinition[stringPattern[i]]);
} else {
replacedStringArray[i] = stringPattern[i];
}
}
return replacedStringArray.join("");
}
function stringPatternArray(length, pattern, variableDefinition) {
return _array(length, stringPattern, [pattern, variableDefinition]);
}
function pick(array) {
if (array == null) {
throw "input array is null or undefined.";
}
return array[integer(array.length - 1)];
}
function shuffle(array) {
if (array == null) {
throw "input array is null or undefined.";
}
for (var i = 0; i < array.length; ++i) {
var randomIndex = integer(array.length - 1);
var temp = array[randomIndex];
array[randomIndex] = array[i];
array[i] = temp;
}
}
function subArray(array, length) {
// validation
if (array == null) {
throw "input array is null or undefined.";
} else if (length == null) {
throw "input length is null or undefined.";
} else if (array.length < length) {
throw "input length [" + length + "] must not exceed array length [" + array.length + "]";
}
// logic
var copiedArray = array.slice();
shuffle(copiedArray);
return copiedArray.slice(0, length);
}
function splitArray(array, count, ensureEqualSize) {
if (array == null || count == null) {
throw "array and count is required.";
}
if (array.length < count) {
throw "input array length is not sufficient for the split.";
}
var arrayCopy = [...array];
shuffle(arrayCopy);
var outputArrays = [];
for (var i = count, start = 0, remaining = arrayCopy.length; i > 0; --i) {
var nextLength = ensureEqualSize
? Math.ceil(remaining / i)
: i === 1
? remaining
: integer(remaining - i, 1);
var slicedArray = arrayCopy.slice(start, start + nextLength);
remaining -= slicedArray.length;
start += slicedArray.length;
outputArrays.push(slicedArray);
}
return outputArrays;
}
function color() {
return "#".concat(((Math.random() * 0xffffff) << 0).toString(16));
}
function guid() {
return randomExt.stringPattern("xxxxxxxx-xxxx-yxxx-zxxx-xxxxxxxxxxxx", {
x: [randomExt.restrictedString, [randomExt.CHAR_TYPE.HEX], 1, 1],
y: [randomExt.restrictedString, ["12345"], 1, 1],
z: [randomExt.restrictedString, ["89ab"], 1, 1],
});
}
var randomExt = {
boolean: boolean,
booleanArray: booleanArray,
integer: integer,
integerArray: integerArray,
float: float,
floatArray: floatArray,
date: date,
dateArray: dateArray,
string: string,
uString: uString,
stringArray: stringArray,
restrictedString: restrictedString,
restrictedStringArray: restrictedStringArray,
object: object,
objectArray: objectArray,
stringPattern: stringPattern,
stringPatternArray: stringPatternArray,
pick: pick,
shuffle: shuffle,
subArray: subArray,
splitArray: splitArray,
color: color,
guid: guid,
CHAR_TYPE: {
LOWERCASE: 0,
UPPERCASE: 1,
NUMERIC: 2,
SPECIAL: 3,
SPACE: 4,
HEX: 5,
},
DEBUG: false,
};
module.exports = randomExt;