diff --git a/README.md b/README.md index a195b91..804f4e1 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,26 @@ $ backstabbing_roentgen5 ``` `*` This uses Math.random which means its not very random. These names should never be used as any sort of unique id. The names are mostly applicable for small lists of ephemeral objects that you want to have easy to remember identifiers for. +Seeds** can be used to generate the same name for the same seed: +```javascript +const dockerNames = require('docker-names'); +console.log(dockerNames.getRandomName(false, 'my-seed-here')); // Will always return the same name if the seed 'my-seed-here' is given +$ brave_ride +``` +`**`(Antti Sykäri's algorithm is used for seedable pseudo random number generator) + +You can pass your own custom random number generator, by supplying an object with a method `random` method (that returns values greater than or equal to 0 and less than 1): +```javascript +const dockerNames = require('docker-names'); +console.log(dockerNames.getRandomName(false, {random : () => ((Math.random() + Math.random()) / 2)})); // Example of a custom random number generator +console.log(dockerNames.getRandomName(false, {random : () => 0.213456})); // Example of a not so random number generator (that will return determined_curie) + +// Or set it globally for all names generations +dockerNames.random_number_generator = {random : () => ((Math.random() + Math.random()) / 2)}; +console.log(dockerNames.getRandomName()); +console.log(dockerNames.getRandomName()); +``` + ### Word Lists This module exports the full docker name lists as two arrays. @@ -37,4 +57,4 @@ dockerNames.adjectives = Array('admiring', 'adoring'...); // This contains all surnames to use as "right words" dockerNames.surnames = Array('albattani', 'allen' ...); -``` \ No newline at end of file +``` diff --git a/index.js b/index.js index 3abc522..3cd9919 100644 --- a/index.js +++ b/index.js @@ -8,23 +8,81 @@ * an individuals surname. This results in funny names like angry_bohr or prickly_murdock. * @param {Array} left - An array of strings to be used as the left word in docker name. * @param {Array} right - An array of strings to be used as the right word in docker name. + * @param {Object} randgen - The random number generator to be used to generate the docker name. * @returns {string} */ -function generateName(left, right) { - var first = left[Math.floor((Math.random() * left.length))]; - var second = right[Math.floor((Math.random() * right.length))]; - var result = first + "_" + second; +function generateName(left, right, randgen) { + var first = left[Math.floor((randgen.random() * left.length))]; + var second = right[Math.floor((randgen.random() * right.length))]; + var result = first + "_" + second; + + /* Steve Wozniak is not boring. This is part of the docker names spec. */ + if (result === "boring_wozniak") { + return generateName(left, right, randgen); + } + return result; +} + - /* Steve Wozniak is not boring. This is part of the docker names spec. */ - if (result === "boring_wozniak") { - return generateName(left, right); - } - return result; +/** + * @summary A random number generator initialised from a seed + * + * @param {string} [seed] - The seed to initialise the random number generator from + * @returns {RandomFromSeed} + */ +function RandomFromSeed(seed) { + this.seed = this._stringToSeed(seed.toString()); + this.randomGenerator = this._seededRandomGenerator(this.seed); } +/** + * @summary Convert a string seed input to a number seed + * + * @param {string} [str] - The string seed + * @returns {number} + */ +RandomFromSeed.prototype._stringToSeed = function(str) { + var hash = 0; + for (var i = 0; i < str.length; i++) { + hash = (hash << 5) - hash + str.charCodeAt(i); + hash |= 0; + } + return hash; +}; + +/** + * @summary Create a generator for the given seed + * + * @param {number} [seed] - The number seed + * @returns {function} + */ +RandomFromSeed.prototype._seededRandomGenerator = function(seed) { + return function() { + seed = Math.sin(seed) * 10000; + return seed - Math.floor(seed); + }; +}; + +/** + * @summary Generate a random number + * + * @param {number} [min] - (optional) From this number + * @param {number} [max] - (optional) To this number + * @returns {number} + */ +RandomFromSeed.prototype.random = function(min, max) { + if (min !== undefined && max !== undefined) { + return min + Math.floor(this.randomGenerator() * (max - min + 1)); + } else if (min !== undefined) { + return Math.floor(this.randomGenerator() * min); + } else { + return this.randomGenerator(); + } +}; + function DockerNames() { - this.left = [ - "admiring", + this.left = [ + "admiring", "adoring", "affectionate", "agitated", @@ -132,733 +190,276 @@ function DockerNames() { "youthful", "zealous", "zen", - ]; - - this.right = [ - - "agnesi", + ]; + this.right = [ + "agnesi", "albattani", - - "allen", - - "almeida", - - "antonelli", - - "archimedes", - - "ardinghelli", - - "aryabhata", - - "austin", - - "babbage", - - "banach", - - "banzai", - - "bardeen", - - "bartik", - - "bassi", - - "beaver", - - "bell", - - "benz", - - "bhabha", - - "bhaskara", - - "black", - - "blackburn", - - "blackwell", - - "bohr", - - "booth", - - "borg", - - "bose", - - "bouman", - - "boyd", - - "brahmagupta", - - "brattain", - - "brown", - - "buck", - - "burnell", - - "cannon", - - "carson", - - "cartwright", - - "carver", - - "cerf", - - "chandrasekhar", - - "chaplygin", - - "chatelet", - - "chatterjee", - - "chaum", - - "chebyshev", - - "clarke", - - "cohen", - - "colden", - - "cori", - - "cray", - - "curie", - - - - "curran", - - "darwin", - - "davinci", - - "dewdney", - - "dhawan", - - "diffie", - - "dijkstra", - - "dirac", - - "driscoll", - - "dubinsky", - - "easley", - - "edison", - - "einstein", - - "elbakyan", - - "elgamal", - - "elion", - - "ellis", - - "engelbart", - - "euclid", - - "euler", - - "faraday", - - "feistel", - - "fermat", - - "fermi", - - "feynman", - - "franklin", - - "gagarin", - - "galileo", - - "galois", - - "ganguly", - - "gates", - - "gauss", - - "germain", - - "goldberg", - - "goldstine", - - "goldwasser", - - "golick", - - "goodall", - - "gould", - - "greider", - - "grothendieck", - - "haibt", - - "hamilton", - - "haslett", - - "hawking", - - "heisenberg", - - "hellman", - - "hermann", - - "herschel", - - "hertz", - - "heyrovsky", - - "hodgkin", - - "hofstadter", - - "hoover", - - "hopper", - - "hugle", - - "hypatia", - - "ishizaka", - - "jackson", - - "jang", - - "jemison", - - "jennings", - - "jepsen", - - "johnson", - - "joliot", - - "jones", - - "kalam", - - "kapitsa", - - "kare", - - "keldysh", - - "keller", - - "kepler", - - "khayyam", - - "khorana", - - "kilby", - - "kirch", - - "knuth", - - "kowalevski", - - "lalande", - - "lamarr", - - "lamport", - - "leakey", - - "leavitt", - - "lederberg", - - "lehmann", - - "lewin", - - "lichterman", - - "liskov", - - "lovelace", - - "lumiere", - - "mahavira", - - "margulis", - - "matsumoto", - - "maxwell", - - "mayer", - - "mccarthy", - - "mcclintock", - - "mclaren", - - "mclean", - - "mcnulty", - - "meitner", - - "mendel", - - "mendeleev", - - "meninsky", - - "merkle", - - "mestorf", - - "mirzakhani", - - "montalcini", - - "moore", - - "morse", - - "moser", - - "murdock", - - "napier", - - "nash", - - "neumann", - - "newton", - - "nightingale", - - "nobel", - - "noether", - - "northcutt", - - "noyce", - - "panini", - - "pare", - - "pascal", - - "pasteur", - - "payne", - - "perlman", - - "pike", - - "poincare", - - "poitras", - - "proskuriakova", - - "ptolemy", - - "raman", - - "ramanujan", - - "rhodes", - - "ride", - - "ritchie", - - "robinson", - - "roentgen", - - "rosalind", - - "rubin", - - "saha", - - "sammet", - - "sanderson", - - "satoshi", - - "shamir", - - "shannon", - - "shaw", - - "shirley", - - "shockley", - - "shtern", - - "sinoussi", - - "snyder", - - "solomon", - - "spence", - - "stonebraker", - - "sutherland", - - "swanson", - - "swartz", - - "swirles", - - "taussig", - - "tesla", - - "tharp", - - "thompson", - - "torvalds", - - "tu", - - "turing", - - "varahamihira", - - "vaughan", - - "villani", - - "visvesvaraya", - - "volhard", - - "wescoff", - - "wilbur", - - "wiles", - - "williams", - - "williamson", - - "wilson", - - "wing", - - "wozniak", - - "wright", - - "wu", - - "yalow", - - "yonath", - - "zhukovsky", - ]; + ]; + + this.adjectives = this.left; + this.surnames = this.right; - this.adjectives = this.left; - this.surnames = this.right; + this.random_number_generator = Math; } /** * @summary Generates a random docker style name. * * @param {boolean|number} [appendNumber] - Adds a random number to the resulting docker name. + * @param {number|string|undefined|Object} generator - The seed or generator to be used to generate the docker name. * @returns {string} */ -DockerNames.prototype.getRandomName = function(appendNumber) { - var rand = (appendNumber === true || appendNumber > 0) ? String(Math.floor((Math.random() * 9) + 1)) : ""; - return generateName(this.left, this.right) + rand; +DockerNames.prototype.getRandomName = function(appendNumber, generator) { + var rand = (appendNumber === true || appendNumber > 0) ? String(Math.floor((Math.random() * 9) + 1)) : ""; + + var randgen = this.random_number_generator; + if (generator) { + // If a random number generator was given + if (typeof generator.random == 'function') { + randgen = generator; + } + // Else treat it as a seed + else { + randgen = new RandomFromSeed(generator); + } + } + return generateName(this.left, this.right, randgen) + rand; }; module.exports = new DockerNames();