pip-webui
Version:
HTML5 UI for LOB applications
1,316 lines (1,120 loc) • 290 kB
JavaScript
// Chance.js 1.0.3
// http://chancejs.com
// (c) 2013 Victor Quinn
// Chance may be freely distributed or modified under the MIT license.
(function () {
// Constants
var MAX_INT = 9007199254740992;
var MIN_INT = -MAX_INT;
var NUMBERS = '0123456789';
var CHARS_LOWER = 'abcdefghijklmnopqrstuvwxyz';
var CHARS_UPPER = CHARS_LOWER.toUpperCase();
var HEX_POOL = NUMBERS + "abcdef";
// Cached array helpers
var slice = Array.prototype.slice;
// Constructor
function Chance (seed) {
if (!(this instanceof Chance)) {
return seed == null ? new Chance() : new Chance(seed);
}
// if user has provided a function, use that as the generator
if (typeof seed === 'function') {
this.random = seed;
return this;
}
if (arguments.length) {
// set a starting value of zero so we can add to it
this.seed = 0;
}
// otherwise, leave this.seed blank so that MT will receive a blank
for (var i = 0; i < arguments.length; i++) {
var seedling = 0;
if (Object.prototype.toString.call(arguments[i]) === '[object String]') {
for (var j = 0; j < arguments[i].length; j++) {
// create a numeric hash for each argument, add to seedling
var hash = 0;
for (var k = 0; k < arguments[i].length; k++) {
hash = arguments[i].charCodeAt(k) + (hash << 6) + (hash << 16) - hash;
}
seedling += hash;
}
} else {
seedling = arguments[i];
}
this.seed += (arguments.length - i) * seedling;
}
// If no generator function was provided, use our MT
this.mt = this.mersenne_twister(this.seed);
this.bimd5 = this.blueimp_md5();
this.random = function () {
return this.mt.random(this.seed);
};
return this;
}
Chance.prototype.VERSION = "1.0.3";
// Random helper functions
function initOptions(options, defaults) {
options || (options = {});
if (defaults) {
for (var i in defaults) {
if (typeof options[i] === 'undefined') {
options[i] = defaults[i];
}
}
}
return options;
}
function testRange(test, errorMessage) {
if (test) {
throw new RangeError(errorMessage);
}
}
/**
* Encode the input string with Base64.
*/
var base64 = function() {
throw new Error('No Base64 encoder available.');
};
// Select proper Base64 encoder.
(function determineBase64Encoder() {
if (typeof btoa === 'function') {
base64 = btoa;
} else if (typeof Buffer === 'function') {
base64 = function(input) {
return new Buffer(input).toString('base64');
};
}
})();
// -- Basics --
/**
* Return a random bool, either true or false
*
* @param {Object} [options={ likelihood: 50 }] alter the likelihood of
* receiving a true or false value back.
* @throws {RangeError} if the likelihood is out of bounds
* @returns {Bool} either true or false
*/
Chance.prototype.bool = function (options) {
// likelihood of success (true)
options = initOptions(options, {likelihood : 50});
// Note, we could get some minor perf optimizations by checking range
// prior to initializing defaults, but that makes code a bit messier
// and the check more complicated as we have to check existence of
// the object then existence of the key before checking constraints.
// Since the options initialization should be minor computationally,
// decision made for code cleanliness intentionally. This is mentioned
// here as it's the first occurrence, will not be mentioned again.
testRange(
options.likelihood < 0 || options.likelihood > 100,
"Chance: Likelihood accepts values from 0 to 100."
);
return this.random() * 100 < options.likelihood;
};
/**
* Return a random character.
*
* @param {Object} [options={}] can specify a character pool, only alpha,
* only symbols, and casing (lower or upper)
* @returns {String} a single random character
* @throws {RangeError} Can only specify alpha or symbols, not both
*/
Chance.prototype.character = function (options) {
options = initOptions(options);
testRange(
options.alpha && options.symbols,
"Chance: Cannot specify both alpha and symbols."
);
var symbols = "!@#$%^&*()[]",
letters, pool;
if (options.casing === 'lower') {
letters = CHARS_LOWER;
} else if (options.casing === 'upper') {
letters = CHARS_UPPER;
} else {
letters = CHARS_LOWER + CHARS_UPPER;
}
if (options.pool) {
pool = options.pool;
} else if (options.alpha) {
pool = letters;
} else if (options.symbols) {
pool = symbols;
} else {
pool = letters + NUMBERS + symbols;
}
return pool.charAt(this.natural({max: (pool.length - 1)}));
};
// Note, wanted to use "float" or "double" but those are both JS reserved words.
// Note, fixed means N OR LESS digits after the decimal. This because
// It could be 14.9000 but in JavaScript, when this is cast as a number,
// the trailing zeroes are dropped. Left to the consumer if trailing zeroes are
// needed
/**
* Return a random floating point number
*
* @param {Object} [options={}] can specify a fixed precision, min, max
* @returns {Number} a single floating point number
* @throws {RangeError} Can only specify fixed or precision, not both. Also
* min cannot be greater than max
*/
Chance.prototype.floating = function (options) {
options = initOptions(options, {fixed : 4});
testRange(
options.fixed && options.precision,
"Chance: Cannot specify both fixed and precision."
);
var num;
var fixed = Math.pow(10, options.fixed);
var max = MAX_INT / fixed;
var min = -max;
testRange(
options.min && options.fixed && options.min < min,
"Chance: Min specified is out of range with fixed. Min should be, at least, " + min
);
testRange(
options.max && options.fixed && options.max > max,
"Chance: Max specified is out of range with fixed. Max should be, at most, " + max
);
options = initOptions(options, { min : min, max : max });
// Todo - Make this work!
// options.precision = (typeof options.precision !== "undefined") ? options.precision : false;
num = this.integer({min: options.min * fixed, max: options.max * fixed});
var num_fixed = (num / fixed).toFixed(options.fixed);
return parseFloat(num_fixed);
};
/**
* Return a random integer
*
* NOTE the max and min are INCLUDED in the range. So:
* chance.integer({min: 1, max: 3});
* would return either 1, 2, or 3.
*
* @param {Object} [options={}] can specify a min and/or max
* @returns {Number} a single random integer number
* @throws {RangeError} min cannot be greater than max
*/
Chance.prototype.integer = function (options) {
// 9007199254740992 (2^53) is the max integer number in JavaScript
// See: http://vq.io/132sa2j
options = initOptions(options, {min: MIN_INT, max: MAX_INT});
testRange(options.min > options.max, "Chance: Min cannot be greater than Max.");
return Math.floor(this.random() * (options.max - options.min + 1) + options.min);
};
/**
* Return a random natural
*
* NOTE the max and min are INCLUDED in the range. So:
* chance.natural({min: 1, max: 3});
* would return either 1, 2, or 3.
*
* @param {Object} [options={}] can specify a min and/or max
* @returns {Number} a single random integer number
* @throws {RangeError} min cannot be greater than max
*/
Chance.prototype.natural = function (options) {
options = initOptions(options, {min: 0, max: MAX_INT});
testRange(options.min < 0, "Chance: Min cannot be less than zero.");
return this.integer(options);
};
/**
* Return a random string
*
* @param {Object} [options={}] can specify a length
* @returns {String} a string of random length
* @throws {RangeError} length cannot be less than zero
*/
Chance.prototype.string = function (options) {
options = initOptions(options, { length: this.natural({min: 5, max: 20}) });
testRange(options.length < 0, "Chance: Length cannot be less than zero.");
var length = options.length,
text = this.n(this.character, length, options);
return text.join("");
};
// -- End Basics --
// -- Helpers --
Chance.prototype.capitalize = function (word) {
return word.charAt(0).toUpperCase() + word.substr(1);
};
Chance.prototype.mixin = function (obj) {
for (var func_name in obj) {
Chance.prototype[func_name] = obj[func_name];
}
return this;
};
/**
* Given a function that generates something random and a number of items to generate,
* return an array of items where none repeat.
*
* @param {Function} fn the function that generates something random
* @param {Number} num number of terms to generate
* @param {Object} options any options to pass on to the generator function
* @returns {Array} an array of length `num` with every item generated by `fn` and unique
*
* There can be more parameters after these. All additional parameters are provided to the given function
*/
Chance.prototype.unique = function(fn, num, options) {
testRange(
typeof fn !== "function",
"Chance: The first argument must be a function."
);
var comparator = function(arr, val) { return arr.indexOf(val) !== -1; };
if (options) {
comparator = options.comparator || comparator;
}
var arr = [], count = 0, result, MAX_DUPLICATES = num * 50, params = slice.call(arguments, 2);
while (arr.length < num) {
var clonedParams = JSON.parse(JSON.stringify(params));
result = fn.apply(this, clonedParams);
if (!comparator(arr, result)) {
arr.push(result);
// reset count when unique found
count = 0;
}
if (++count > MAX_DUPLICATES) {
throw new RangeError("Chance: num is likely too large for sample set");
}
}
return arr;
};
/**
* Gives an array of n random terms
*
* @param {Function} fn the function that generates something random
* @param {Number} n number of terms to generate
* @returns {Array} an array of length `n` with items generated by `fn`
*
* There can be more parameters after these. All additional parameters are provided to the given function
*/
Chance.prototype.n = function(fn, n) {
testRange(
typeof fn !== "function",
"Chance: The first argument must be a function."
);
if (typeof n === 'undefined') {
n = 1;
}
var i = n, arr = [], params = slice.call(arguments, 2);
// Providing a negative count should result in a noop.
i = Math.max( 0, i );
for (null; i--; null) {
arr.push(fn.apply(this, params));
}
return arr;
};
// H/T to SO for this one: http://vq.io/OtUrZ5
Chance.prototype.pad = function (number, width, pad) {
// Default pad to 0 if none provided
pad = pad || '0';
// Convert number to a string
number = number + '';
return number.length >= width ? number : new Array(width - number.length + 1).join(pad) + number;
};
// DEPRECATED on 2015-10-01
Chance.prototype.pick = function (arr, count) {
if (arr.length === 0) {
throw new RangeError("Chance: Cannot pick() from an empty array");
}
if (!count || count === 1) {
return arr[this.natural({max: arr.length - 1})];
} else {
return this.shuffle(arr).slice(0, count);
}
};
// Given an array, returns a single random element
Chance.prototype.pickone = function (arr) {
if (arr.length === 0) {
throw new RangeError("Chance: Cannot pickone() from an empty array");
}
return arr[this.natural({max: arr.length - 1})];
};
// Given an array, returns a random set with 'count' elements
Chance.prototype.pickset = function (arr, count) {
if (count === 0) {
return [];
}
if (arr.length === 0) {
throw new RangeError("Chance: Cannot pickset() from an empty array");
}
if (count < 0) {
throw new RangeError("Chance: count must be positive number");
}
if (!count || count === 1) {
return [ this.pickone(arr) ];
} else {
return this.shuffle(arr).slice(0, count);
}
};
Chance.prototype.shuffle = function (arr) {
var old_array = arr.slice(0),
new_array = [],
j = 0,
length = Number(old_array.length);
for (var i = 0; i < length; i++) {
// Pick a random index from the array
j = this.natural({max: old_array.length - 1});
// Add it to the new array
new_array[i] = old_array[j];
// Remove that element from the original array
old_array.splice(j, 1);
}
return new_array;
};
// Returns a single item from an array with relative weighting of odds
Chance.prototype.weighted = function (arr, weights, trim) {
if (arr.length !== weights.length) {
throw new RangeError("Chance: length of array and weights must match");
}
// scan weights array and sum valid entries
var sum = 0;
var val;
for (var weightIndex = 0; weightIndex < weights.length; ++weightIndex) {
val = weights[weightIndex];
if (val > 0) {
sum += val;
}
}
if (sum === 0) {
throw new RangeError("Chance: no valid entries in array weights");
}
// select a value within range
var selected = this.random() * sum;
// find array entry corresponding to selected value
var total = 0;
var lastGoodIdx = -1;
var chosenIdx;
for (weightIndex = 0; weightIndex < weights.length; ++weightIndex) {
val = weights[weightIndex];
total += val;
if (val > 0) {
if (selected <= total) {
chosenIdx = weightIndex;
break;
}
lastGoodIdx = weightIndex;
}
// handle any possible rounding error comparison to ensure something is picked
if (weightIndex === (weights.length - 1)) {
chosenIdx = lastGoodIdx;
}
}
var chosen = arr[chosenIdx];
trim = (typeof trim === 'undefined') ? false : trim;
if (trim) {
arr.splice(chosenIdx, 1);
weights.splice(chosenIdx, 1);
}
return chosen;
};
// -- End Helpers --
// -- Text --
Chance.prototype.paragraph = function (options) {
options = initOptions(options);
var sentences = options.sentences || this.natural({min: 3, max: 7}),
sentence_array = this.n(this.sentence, sentences);
return sentence_array.join(' ');
};
// Could get smarter about this than generating random words and
// chaining them together. Such as: http://vq.io/1a5ceOh
Chance.prototype.sentence = function (options) {
options = initOptions(options);
var words = options.words || this.natural({min: 12, max: 18}),
punctuation = options.punctuation,
text, word_array = this.n(this.word, words);
text = word_array.join(' ');
// Capitalize first letter of sentence
text = this.capitalize(text);
// Make sure punctuation has a usable value
if (punctuation !== false && !/^[\.\?;!:]$/.test(punctuation)) {
punctuation = '.';
}
// Add punctuation mark
if (punctuation) {
text += punctuation;
}
return text;
};
Chance.prototype.syllable = function (options) {
options = initOptions(options);
var length = options.length || this.natural({min: 2, max: 3}),
consonants = 'bcdfghjklmnprstvwz', // consonants except hard to speak ones
vowels = 'aeiou', // vowels
all = consonants + vowels, // all
text = '',
chr;
// I'm sure there's a more elegant way to do this, but this works
// decently well.
for (var i = 0; i < length; i++) {
if (i === 0) {
// First character can be anything
chr = this.character({pool: all});
} else if (consonants.indexOf(chr) === -1) {
// Last character was a vowel, now we want a consonant
chr = this.character({pool: consonants});
} else {
// Last character was a consonant, now we want a vowel
chr = this.character({pool: vowels});
}
text += chr;
}
if (options.capitalize) {
text = this.capitalize(text);
}
return text;
};
Chance.prototype.word = function (options) {
options = initOptions(options);
testRange(
options.syllables && options.length,
"Chance: Cannot specify both syllables AND length."
);
var syllables = options.syllables || this.natural({min: 1, max: 3}),
text = '';
if (options.length) {
// Either bound word by length
do {
text += this.syllable();
} while (text.length < options.length);
text = text.substring(0, options.length);
} else {
// Or by number of syllables
for (var i = 0; i < syllables; i++) {
text += this.syllable();
}
}
if (options.capitalize) {
text = this.capitalize(text);
}
return text;
};
// -- End Text --
// -- Person --
Chance.prototype.age = function (options) {
options = initOptions(options);
var ageRange;
switch (options.type) {
case 'child':
ageRange = {min: 1, max: 12};
break;
case 'teen':
ageRange = {min: 13, max: 19};
break;
case 'adult':
ageRange = {min: 18, max: 65};
break;
case 'senior':
ageRange = {min: 65, max: 100};
break;
case 'all':
ageRange = {min: 1, max: 100};
break;
default:
ageRange = {min: 18, max: 65};
break;
}
return this.natural(ageRange);
};
Chance.prototype.birthday = function (options) {
options = initOptions(options, {
year: (new Date().getFullYear() - this.age(options))
});
return this.date(options);
};
// CPF; ID to identify taxpayers in Brazil
Chance.prototype.cpf = function () {
var n = this.n(this.natural, 9, { max: 9 });
var d1 = n[8]*2+n[7]*3+n[6]*4+n[5]*5+n[4]*6+n[3]*7+n[2]*8+n[1]*9+n[0]*10;
d1 = 11 - (d1 % 11);
if (d1>=10) {
d1 = 0;
}
var d2 = d1*2+n[8]*3+n[7]*4+n[6]*5+n[5]*6+n[4]*7+n[3]*8+n[2]*9+n[1]*10+n[0]*11;
d2 = 11 - (d2 % 11);
if (d2>=10) {
d2 = 0;
}
return ''+n[0]+n[1]+n[2]+'.'+n[3]+n[4]+n[5]+'.'+n[6]+n[7]+n[8]+'-'+d1+d2;
};
// CNPJ: ID to identify companies in Brazil
Chance.prototype.cnpj = function () {
var n = this.n(this.natural, 12, { max: 12 });
var d1 = n[11]*2+n[10]*3+n[9]*4+n[8]*5+n[7]*6+n[6]*7+n[5]*8+n[4]*9+n[3]*2+n[2]*3+n[1]*4+n[0]*5;
d1 = 11 - (d1 % 11);
if (d1<2) {
d1 = 0;
}
var d2 = d1*2+n[11]*3+n[10]*4+n[9]*5+n[8]*6+n[7]*7+n[6]*8+n[5]*9+n[4]*2+n[3]*3+n[2]*4+n[1]*5+n[0]*6;
d2 = 11 - (d2 % 11);
if (d2<2) {
d2 = 0;
}
return ''+n[0]+n[1]+'.'+n[2]+n[3]+n[4]+'.'+n[5]+n[6]+n[7]+'/'+n[8]+n[9]+n[10]+n[11]+'-'+d1+d2;
};
Chance.prototype.first = function (options) {
options = initOptions(options, {gender: this.gender(), nationality: 'en'});
return this.pick(this.get("firstNames")[options.gender.toLowerCase()][options.nationality.toLowerCase()]);
};
Chance.prototype.gender = function () {
return this.pick(['Male', 'Female']);
};
Chance.prototype.last = function (options) {
options = initOptions(options, {nationality: 'en'});
return this.pick(this.get("lastNames")[options.nationality.toLowerCase()]);
};
Chance.prototype.israelId=function(){
var x=this.string({pool: '0123456789',length:8});
var y=0;
for (var i=0;i<x.length;i++){
var thisDigit= x[i] * (i/2===parseInt(i/2) ? 1 : 2);
thisDigit=this.pad(thisDigit,2).toString();
thisDigit=parseInt(thisDigit[0]) + parseInt(thisDigit[1]);
y=y+thisDigit;
}
x=x+(10-parseInt(y.toString().slice(-1))).toString().slice(-1);
return x;
};
Chance.prototype.mrz = function (options) {
var checkDigit = function (input) {
var alpha = "<ABCDEFGHIJKLMNOPQRSTUVWXYXZ".split(''),
multipliers = [ 7, 3, 1 ],
runningTotal = 0;
if (typeof input !== 'string') {
input = input.toString();
}
input.split('').forEach(function(character, idx) {
var pos = alpha.indexOf(character);
if(pos !== -1) {
character = pos === 0 ? 0 : pos + 9;
} else {
character = parseInt(character, 10);
}
character *= multipliers[idx % multipliers.length];
runningTotal += character;
});
return runningTotal % 10;
};
var generate = function (opts) {
var pad = function (length) {
return new Array(length + 1).join('<');
};
var number = [ 'P<',
opts.issuer,
opts.last.toUpperCase(),
'<<',
opts.first.toUpperCase(),
pad(39 - (opts.last.length + opts.first.length + 2)),
opts.passportNumber,
checkDigit(opts.passportNumber),
opts.nationality,
opts.dob,
checkDigit(opts.dob),
opts.gender,
opts.expiry,
checkDigit(opts.expiry),
pad(14),
checkDigit(pad(14)) ].join('');
return number +
(checkDigit(number.substr(44, 10) +
number.substr(57, 7) +
number.substr(65, 7)));
};
var that = this;
options = initOptions(options, {
first: this.first(),
last: this.last(),
passportNumber: this.integer({min: 100000000, max: 999999999}),
dob: (function () {
var date = that.birthday({type: 'adult'});
return [date.getFullYear().toString().substr(2),
that.pad(date.getMonth() + 1, 2),
that.pad(date.getDate(), 2)].join('');
}()),
expiry: (function () {
var date = new Date();
return [(date.getFullYear() + 5).toString().substr(2),
that.pad(date.getMonth() + 1, 2),
that.pad(date.getDate(), 2)].join('');
}()),
gender: this.gender() === 'Female' ? 'F': 'M',
issuer: 'GBR',
nationality: 'GBR'
});
return generate (options);
};
Chance.prototype.name = function (options) {
options = initOptions(options);
var first = this.first(options),
last = this.last(options),
name;
if (options.middle) {
name = first + ' ' + this.first(options) + ' ' + last;
} else if (options.middle_initial) {
name = first + ' ' + this.character({alpha: true, casing: 'upper'}) + '. ' + last;
} else {
name = first + ' ' + last;
}
if (options.prefix) {
name = this.prefix(options) + ' ' + name;
}
if (options.suffix) {
name = name + ' ' + this.suffix(options);
}
return name;
};
// Return the list of available name prefixes based on supplied gender.
// @todo introduce internationalization
Chance.prototype.name_prefixes = function (gender) {
gender = gender || "all";
gender = gender.toLowerCase();
var prefixes = [
{ name: 'Doctor', abbreviation: 'Dr.' }
];
if (gender === "male" || gender === "all") {
prefixes.push({ name: 'Mister', abbreviation: 'Mr.' });
}
if (gender === "female" || gender === "all") {
prefixes.push({ name: 'Miss', abbreviation: 'Miss' });
prefixes.push({ name: 'Misses', abbreviation: 'Mrs.' });
}
return prefixes;
};
// Alias for name_prefix
Chance.prototype.prefix = function (options) {
return this.name_prefix(options);
};
Chance.prototype.name_prefix = function (options) {
options = initOptions(options, { gender: "all" });
return options.full ?
this.pick(this.name_prefixes(options.gender)).name :
this.pick(this.name_prefixes(options.gender)).abbreviation;
};
Chance.prototype.ssn = function (options) {
options = initOptions(options, {ssnFour: false, dashes: true});
var ssn_pool = "1234567890",
ssn,
dash = options.dashes ? '-' : '';
if(!options.ssnFour) {
ssn = this.string({pool: ssn_pool, length: 3}) + dash +
this.string({pool: ssn_pool, length: 2}) + dash +
this.string({pool: ssn_pool, length: 4});
} else {
ssn = this.string({pool: ssn_pool, length: 4});
}
return ssn;
};
// Return the list of available name suffixes
// @todo introduce internationalization
Chance.prototype.name_suffixes = function () {
var suffixes = [
{ name: 'Doctor of Osteopathic Medicine', abbreviation: 'D.O.' },
{ name: 'Doctor of Philosophy', abbreviation: 'Ph.D.' },
{ name: 'Esquire', abbreviation: 'Esq.' },
{ name: 'Junior', abbreviation: 'Jr.' },
{ name: 'Juris Doctor', abbreviation: 'J.D.' },
{ name: 'Master of Arts', abbreviation: 'M.A.' },
{ name: 'Master of Business Administration', abbreviation: 'M.B.A.' },
{ name: 'Master of Science', abbreviation: 'M.S.' },
{ name: 'Medical Doctor', abbreviation: 'M.D.' },
{ name: 'Senior', abbreviation: 'Sr.' },
{ name: 'The Third', abbreviation: 'III' },
{ name: 'The Fourth', abbreviation: 'IV' },
{ name: 'Bachelor of Engineering', abbreviation: 'B.E' },
{ name: 'Bachelor of Technology', abbreviation: 'B.TECH' }
];
return suffixes;
};
// Alias for name_suffix
Chance.prototype.suffix = function (options) {
return this.name_suffix(options);
};
Chance.prototype.name_suffix = function (options) {
options = initOptions(options);
return options.full ?
this.pick(this.name_suffixes()).name :
this.pick(this.name_suffixes()).abbreviation;
};
Chance.prototype.nationalities = function () {
return this.get("nationalities");
};
// Generate random nationality based on json list
Chance.prototype.nationality = function () {
var nationality = this.pick(this.nationalities());
return nationality.name;
};
// -- End Person --
// -- Mobile --
// Android GCM Registration ID
Chance.prototype.android_id = function () {
return "APA91" + this.string({ pool: "0123456789abcefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_", length: 178 });
};
// Apple Push Token
Chance.prototype.apple_token = function () {
return this.string({ pool: "abcdef1234567890", length: 64 });
};
// Windows Phone 8 ANID2
Chance.prototype.wp8_anid2 = function () {
return base64( this.hash( { length : 32 } ) );
};
// Windows Phone 7 ANID
Chance.prototype.wp7_anid = function () {
return 'A=' + this.guid().replace(/-/g, '').toUpperCase() + '&E=' + this.hash({ length:3 }) + '&W=' + this.integer({ min:0, max:9 });
};
// BlackBerry Device PIN
Chance.prototype.bb_pin = function () {
return this.hash({ length: 8 });
};
// -- End Mobile --
// -- Web --
Chance.prototype.avatar = function (options) {
var url = null;
var URL_BASE = '//www.gravatar.com/avatar/';
var PROTOCOLS = {
http: 'http',
https: 'https'
};
var FILE_TYPES = {
bmp: 'bmp',
gif: 'gif',
jpg: 'jpg',
png: 'png'
};
var FALLBACKS = {
'404': '404', // Return 404 if not found
mm: 'mm', // Mystery man
identicon: 'identicon', // Geometric pattern based on hash
monsterid: 'monsterid', // A generated monster icon
wavatar: 'wavatar', // A generated face
retro: 'retro', // 8-bit icon
blank: 'blank' // A transparent png
};
var RATINGS = {
g: 'g',
pg: 'pg',
r: 'r',
x: 'x'
};
var opts = {
protocol: null,
email: null,
fileExtension: null,
size: null,
fallback: null,
rating: null
};
if (!options) {
// Set to a random email
opts.email = this.email();
options = {};
}
else if (typeof options === 'string') {
opts.email = options;
options = {};
}
else if (typeof options !== 'object') {
return null;
}
else if (options.constructor === 'Array') {
return null;
}
opts = initOptions(options, opts);
if (!opts.email) {
// Set to a random email
opts.email = this.email();
}
// Safe checking for params
opts.protocol = PROTOCOLS[opts.protocol] ? opts.protocol + ':' : '';
opts.size = parseInt(opts.size, 0) ? opts.size : '';
opts.rating = RATINGS[opts.rating] ? opts.rating : '';
opts.fallback = FALLBACKS[opts.fallback] ? opts.fallback : '';
opts.fileExtension = FILE_TYPES[opts.fileExtension] ? opts.fileExtension : '';
url =
opts.protocol +
URL_BASE +
this.bimd5.md5(opts.email) +
(opts.fileExtension ? '.' + opts.fileExtension : '') +
(opts.size || opts.rating || opts.fallback ? '?' : '') +
(opts.size ? '&s=' + opts.size.toString() : '') +
(opts.rating ? '&r=' + opts.rating : '') +
(opts.fallback ? '&d=' + opts.fallback : '')
;
return url;
};
/**
* #Description:
* ===============================================
* Generate random color value base on color type:
* -> hex
* -> rgb
* -> rgba
* -> 0x
* -> named color
*
* #Examples:
* ===============================================
* * Geerate random hex color
* chance.color() => '#79c157' / 'rgb(110,52,164)' / '0x67ae0b' / '#e2e2e2' / '#29CFA7'
*
* * Generate Hex based color value
* chance.color({format: 'hex'}) => '#d67118'
*
* * Generate simple rgb value
* chance.color({format: 'rgb'}) => 'rgb(110,52,164)'
*
* * Generate Ox based color value
* chance.color({format: '0x'}) => '0x67ae0b'
*
* * Generate graiscale based value
* chance.color({grayscale: true}) => '#e2e2e2'
*
* * Return valide color name
* chance.color({format: 'name'}) => 'red'
*
* * Make color uppercase
* chance.color({casing: 'upper'}) => '#29CFA7'
*
* @param [object] options
* @return [string] color value
*/
Chance.prototype.color = function (options) {
function gray(value, delimiter) {
return [value, value, value].join(delimiter || '');
}
function rgb(hasAlpha) {
var rgbValue = (hasAlpha) ? 'rgba' : 'rgb';
var alphaChanal = (hasAlpha) ? (',' + this.floating({min:0, max:1})) : "";
var colorValue = (isGrayscale) ? (gray(this.natural({max: 255}), ',')) : (this.natural({max: 255}) + ',' + this.natural({max: 255}) + ',' + this.natural({max: 255}));
return rgbValue + '(' + colorValue + alphaChanal + ')';
}
function hex(start, end, withHash) {
var simbol = (withHash) ? "#" : "";
var expression = (isGrayscale ? gray(this.hash({length: start})) : this.hash({length: end}));
return simbol + expression;
}
options = initOptions(options, {
format: this.pick(['hex', 'shorthex', 'rgb', 'rgba', '0x', 'name']),
grayscale: false,
casing: 'lower'
});
var isGrayscale = options.grayscale;
var colorValue;
if (options.format === 'hex') {
colorValue = hex.call(this, 2, 6, true);
}
else if (options.format === 'shorthex') {
colorValue = hex.call(this, 1, 3, true);
}
else if (options.format === 'rgb') {
colorValue = rgb.call(this, false);
}
else if (options.format === 'rgba') {
colorValue = rgb.call(this, true);
}
else if (options.format === '0x') {
colorValue = '0x' + hex.call(this, 2, 6);
}
else if(options.format === 'name') {
return this.pick(this.get("colorNames"));
}
else {
throw new RangeError('Invalid format provided. Please provide one of "hex", "shorthex", "rgb", "rgba", "0x" or "name".');
}
if (options.casing === 'upper' ) {
colorValue = colorValue.toUpperCase();
}
return colorValue;
};
Chance.prototype.domain = function (options) {
options = initOptions(options);
return this.word() + '.' + (options.tld || this.tld());
};
Chance.prototype.email = function (options) {
options = initOptions(options);
return this.word({length: options.length}) + '@' + (options.domain || this.domain());
};
Chance.prototype.fbid = function () {
return parseInt('10000' + this.natural({max: 100000000000}), 10);
};
Chance.prototype.google_analytics = function () {
var account = this.pad(this.natural({max: 999999}), 6);
var property = this.pad(this.natural({max: 99}), 2);
return 'UA-' + account + '-' + property;
};
Chance.prototype.hashtag = function () {
return '#' + this.word();
};
Chance.prototype.ip = function () {
// Todo: This could return some reserved IPs. See http://vq.io/137dgYy
// this should probably be updated to account for that rare as it may be
return this.natural({min: 1, max: 254}) + '.' +
this.natural({max: 255}) + '.' +
this.natural({max: 255}) + '.' +
this.natural({min: 1, max: 254});
};
Chance.prototype.ipv6 = function () {
var ip_addr = this.n(this.hash, 8, {length: 4});
return ip_addr.join(":");
};
Chance.prototype.klout = function () {
return this.natural({min: 1, max: 99});
};
Chance.prototype.semver = function (options) {
options = initOptions(options, { include_prerelease: true });
var range = this.pickone(["^", "~", "<", ">", "<=", ">=", "="]);
if (options.range) {
range = options.range;
}
var prerelease = "";
if (options.include_prerelease) {
prerelease = this.weighted(["", "-dev", "-beta", "-alpha"], [50, 10, 5, 1]);
}
return range + this.rpg('3d10').join('.') + prerelease;
};
Chance.prototype.tlds = function () {
return ['com', 'org', 'edu', 'gov', 'co.uk', 'net', 'io', 'ac', 'ad', 'ae', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao', 'aq', 'ar', 'as', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'bj', 'bm', 'bn', 'bo', 'bq', 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cc', 'cd', 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'cr', 'cu', 'cv', 'cw', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'ee', 'eg', 'eh', 'er', 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', 'gh', 'gi', 'gl', 'gm', 'gn', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il', 'im', 'in', 'io', 'iq', 'ir', 'is', 'it', 'je', 'jm', 'jo', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', 'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly', 'ma', 'mc', 'md', 'me', 'mg', 'mh', 'mk', 'ml', 'mm', 'mn', 'mo', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'nc', 'ne', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'pa', 'pe', 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'ps', 'pt', 'pw', 'py', 'qa', 're', 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr', 'ss', 'st', 'su', 'sv', 'sx', 'sy', 'sz', 'tc', 'td', 'tf', 'tg', 'th', 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'tt', 'tv', 'tw', 'tz', 'ua', 'ug', 'uk', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 'ye', 'yt', 'za', 'zm', 'zw'];
};
Chance.prototype.tld = function () {
return this.pick(this.tlds());
};
Chance.prototype.twitter = function () {
return '@' + this.word();
};
Chance.prototype.url = function (options) {
options = initOptions(options, { protocol: "http", domain: this.domain(options), domain_prefix: "", path: this.word(), extensions: []});
var extension = options.extensions.length > 0 ? "." + this.pick(options.extensions) : "";
var domain = options.domain_prefix ? options.domain_prefix + "." + options.domain : options.domain;
return options.protocol + "://" + domain + "/" + options.path + extension;
};
// -- End Web --
// -- Location --
Chance.prototype.address = function (options) {
options = initOptions(options);
return this.natural({min: 5, max: 2000}) + ' ' + this.street(options);
};
Chance.prototype.altitude = function (options) {
options = initOptions(options, {fixed: 5, min: 0, max: 8848});
return this.floating({
min: options.min,
max: options.max,
fixed: options.fixed
});
};
Chance.prototype.areacode = function (options) {
options = initOptions(options, {parens : true});
// Don't want area codes to start with 1, or have a 9 as the second digit
var areacode = this.natural({min: 2, max: 9}).toString() +
this.natural({min: 0, max: 8}).toString() +
this.natural({min: 0, max: 9}).toString();
return options.parens ? '(' + areacode + ')' : areacode;
};
Chance.prototype.city = function () {
return this.capitalize(this.word({syllables: 3}));
};
Chance.prototype.coordinates = function (options) {
return this.latitude(options) + ', ' + this.longitude(options);
};
Chance.prototype.countries = function () {
return this.get("countries");
};
Chance.prototype.country = function (options) {
options = initOptions(options);
var country = this.pick(this.countries());
return options.full ? country.name : country.abbreviation;
};
Chance.prototype.depth = function (options) {
options = initOptions(options, {fixed: 5, min: -10994, max: 0});
return this.floating({
min: options.min,
max: options.max,
fixed: options.fixed
});
};
Chance.prototype.geohash = function (options) {
options = initOptions(options, { length: 7 });
return this.string({ length: options.length, pool: '0123456789bcdefghjkmnpqrstuvwxyz' });
};
Chance.prototype.geojson = function (options) {
return this.latitude(options) + ', ' + this.longitude(options) + ', ' + this.altitude(options);
};
Chance.prototype.latitude = function (options) {
options = initOptions(options, {fixed: 5, min: -90, max: 90});
return this.floating({min: options.min, max: options.max, fixed: options.fixed});
};
Chance.prototype.longitude = function (options) {
options = initOptions(options, {fixed: 5, min: -180, max: 180});
return this.floating({min: options.min, max: options.max, fixed: options.fixed});
};
Chance.prototype.phone = function (options) {
var self = this,
numPick,
ukNum = function (parts) {
var section = [];
//fills the section part of the phone number with random numbers.
parts.sections.forEach(function(n) {
section.push(self.string({ pool: '0123456789', length: n}));
});
return parts.area + section.join(' ');
};
options = initOptions(options, {
formatted: true,
country: 'us',
mobile: false
});
if (!options.formatted) {
options.parens = false;
}
var phone;
switch (options.country) {
case 'fr':
if (!options.mobile) {
numPick = this.pick([
// Valid zone and département codes.
'01' + this.pick(['30', '34', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '53', '55', '56', '58', '60', '64', '69', '70', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83']) + self.string({ pool: '0123456789', length: 6}),
'02' + this.pick(['14', '18', '22', '23', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '40', '41', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '56', '57', '61', '62', '69', '72', '76', '77', '78', '85', '90', '96', '97', '98', '99']) + self.string({ pool: '0123456789', length: 6}),
'03' + this.pick(['10', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '39', '44', '45', '51', '52', '54', '55', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90']) + self.string({ pool: '0123456789', length: 6}),
'04' + this.pick(['11', '13', '15', '20', '22', '26', '27', '30', '32', '34', '37', '42', '43', '44', '50', '56', '57', '63', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '88', '89', '90', '91', '92', '93', '94', '95', '97', '98']) + self.string({ pool: '0123456789', length: 6}),
'05' + this.pick(['08', '16', '17', '19', '24', '31', '32', '33', '34', '35', '40', '45', '46', '47', '49', '53', '55', '56', '57', '58', '59', '61', '62', '63', '64', '65', '67', '79', '81', '82', '86', '87', '90', '94']) + self.string({ pool: '0123456789', length: 6}),
'09' + self.string({ pool: '0123456789', length: 8}),
]);
phone = options.formatted ? numPick.match(/../g).join(' ') : numPick;
} else {
numPick = this.pick(['06', '07']) + self.string({ pool: '0123456789', length: 8});
phone = options.formatted ? numPick.match(/../g).join(' ') : numPick;
}
break;
case 'uk':
if (!options.mobile) {
numPick = this.pick([
//valid area codes of major cities/counties followed by random numbers in required format.
{ area: '01' + this.character({ pool: '234569' }) + '1 ', sections: [3,4] },
{ area: '020 ' + this.character({ pool: '378' }), sections: [3,4] },
{ area: '023 ' + this.character({ pool: '89' }), sections: [3,4] },
{ area: '024 7', sections: [3,4] },
{ area: '028 ' + this.pick(['25','28','37','71','82','90','92','95']), sections: [2,4] },
{ area: '012' + this.pick(['04','08','54','76','97','98']) + ' ', sections: [5] },
{ area: '013' + this.pick(['63','64','84','86']) + ' ', sections: [5] },
{ area: '014' + this.pick(['04','20','60','61','80','88']) + ' ', sections: [5] },
{ area: '015' + this.pick(['24','27','62','66']) + ' ', sections: [5] },
{ area: '016' + this.pick(['06','29','35','47','59','95']) + ' ', sections: [5] },
{ area: '017' + this.pick(['26','44','50','68']) + ' ', sections: [5] },
{ area: '018' + this.pick(['27','37','84','97']) + ' ', sections: [5] },
{ area: '019' + this.pick(['00','05','35','46','49','63','95']) + ' ', sections: [5] }
]);
phone = options.formatted ? ukNum(numPick) : ukNum(numPick).replace(' ', '', 'g');
} else {
numPick = this.pick([
{ area: '07' + this.pick(['4','5','7','8','9']), sections: [2,6] },
{ area: '07624 ', sections: [6] }
]);
phone = options.formatted ? ukNum(numPick) : ukNum(numPick).replace(' ', '');
}
break;
case 'us':
var areacode = this.areacode(options).toString();
var exchange = this.natural({ min: 2, max: 9 }).toString() +
this.natural({ min: 0, max: 9 }).toString() +
this.natural({ min: 0, max: 9 }).toString();
var subscriber = this.natural({ min: 1000, max: 9999 }).toString(); // this could be random [0-9]{4}
phone = options.formatted ? areacode + ' ' + exchange + '-' + subscriber : areacode + exchange + subscriber;
}
return phone;
};
Chance.prototype.posta