diff --git a/js/script.js b/js/script.js index 2f2cff7..1a2a396 100644 --- a/js/script.js +++ b/js/script.js @@ -12,21 +12,196 @@ * "Inspectah J" **/ +function isNil(value) { + return value === null || value === undefined; +} + function Generator() { /* Name Arrays: Customize names to change possible output */ - this.last_names = ['the Chef', 'Digital', 'Wise', 'Knight', 'Wrecka', 'the Genius', 'the Zoo Keeper', 'the Monk', 'the Scientist', 'the Disciple', 'the Darkman', 'Pellegrino', 'the Ill Figure', 'Rocks The World', 'the Baptist',]; + this.last_names = ['the Chef', 'Digital', 'Wise', 'Knight', 'Wrecka', 'the Genius', 'the Zoo Keeper', 'the Monk', 'the Scientist', 'the Disciple', 'the Darkman', 'Pellegrino', 'the Ill Figure', 'Rocks The World', 'the Baptist']; this.first_names = ['Inspectah', 'Masta', 'Poppa', 'Five Foot', 'Ghostface', 'Old Dirty']; + this._previousName = null; + + const DEFAULT_OPTIONS = { + defaultValue: '', + chanceScale: 100, + chance: 50, + force: false, + }; + + this._pickFirstName = function(options) { + options = $.extend({}, DEFAULT_OPTIONS, options); + + if (options.force || makeDiceRoll(options.chanceScale) <= options.chance) + return pickRandomElement(this.first_names); + else + return options.defaultValue; + }; + + this._pickMiddleName = function(name, options) { + options = $.extend({}, DEFAULT_OPTIONS, options); + + if (options.force || makeDiceRoll(options.chanceScale) <= options.chance) + return asAcronym(name); + else + return capitalize(name); + }; + + this._pickLastName = function(options) { + options = $.extend({}, DEFAULT_OPTIONS, options); + + if (options.force || makeDiceRoll(options.chanceScale) <= options.chance) + return pickRandomElement(this.last_names); + else + return options.defaultValue; + } + + this.newRapName = function(weakName) { + /* + Dice Roll 1: Use First Name + Dice Roll 2: Acronymize (Only valid if Dice Roll 1 fails) + Dice Roll 3: Use Last Name + */ + + var firstName = this._pickFirstName({ + chance: 60 // First names are pretty cool, make them slightly more likely + }); + + var middleName = this._pickMiddleName(weakName); + var lastName = this._pickLastName({ + // We'll always have either a first name or a last name. + // Never will return just 'Jill' back. + force: firstName === '' + }); + + const rapName = fillTemplate('{first} {middle} {last}', { + first: firstName, + middle: middleName, + last: lastName, + }).trim(); + + if (rapName.split(' ').length === 1) + throw new Error(rapName); + + // Ensure no repeats + if (rapName === this._previousName) + return this.newRapName(weakName); + else + return (this._previousName = rapName); + } + +} + +/** + * Returns an array of dice roll values going from 0 to maxValue-1 (they're weird dice). If the first argument is an + * array, it is assumed to be an array of max values for each dice roll. + * + * For example, given [20, 40, 10] you get back [a, b, c] where a, b and c are integers in the ranges [0, 19], [0, 39], + * and [0, 9] respectively. + * + * @param {number|Array} count Either the number of die rolls or an array of max dice values + * @param {?number} maxValue Max possible value for each dice roll (only used when `count` is a number) + * @returns {Array} All generated dice roll values + */ +function makeDiceRolls(count, maxValue) { + if (typeof count === 'number') { + const rolls = []; + for (var i = 0; i < count; i++) + rolls[i] = Math.floor(Math.random() * maxValue); + return rolls; + } else + return count.map(function (max) { + return Math.round(Math.random() * max); + }); +} + +/** + * Makes a single dice roll with the given max value. Calls `makeDiceRolls`. + * + * @param {number} maxValue Maximum possible dice roll value, exclusive. + * @returns {number} Dice roll value + */ +function makeDiceRoll(maxValue) { + return makeDiceRolls(1, maxValue)[0]; +} + +/** + * Selects a random element from the given array using a dice roll. + * + * @template T + * @param {Array} arr Array to pick elements from + * @returns {T} + */ +function pickRandomElement(arr) { + return arr[makeDiceRolls(1, arr.length)[0]]; +} + +/** + * @param {string} word Word to capitalize + * @returns {string} + */ +function capitalize(word) { + return word[0].toUpperCase() + (word.length > 1 ? word.slice(1) : '') +} + +/** + * Converts a given word to an acronymized version of itself. + * + * Example: 'Jill' -> 'J.I.L.L.' + * + * @param {string} word Word to acronymize + * @returns {string} + */ +function asAcronym(word) { + return word.toUpperCase().split('').join('.'); } +// A very dumb template filler +function fillTemplate(formatString, options) { + const args = [].slice.call(arguments); + args.shift(); + args.shift(); -//Add your codez here + return formatString.replace(/{\s*(\w*)\s*}/g, function (match, name){ + if (name.length === 0) + if (args.length > 0) + return args.shift(); + else + throw new Error('Insufficient position arguments'); + + if (isNil(options[name])) { + console.error(name, options); + return match; + } + + return options[name]; + }); +} $(document).ready(function() { + const input = $('input:text.form-control'); + const messageBox = $('.messages'); + messageBox.children().hide(); + + const successMessage = messageBox.find('.response'); + const noInputError = messageBox.find('.error'); - var engine = new Generator; - //Add your codez here + var engine = new Generator(); + $('button#enter').click(function() { + const value = input.val().trim(); + input.val(value); + if (value === '') { + noInputError.show(); + successMessage.hide(); + } else { + noInputError.hide(); + var coolRapName = engine.newRapName(value); + successMessage.text(coolRapName); + successMessage.show(); + } + }); });