commit 9032880e27ac80411421bfb8e329fcff041b78c7 Author: Berkeley Martinez Date: Tue Jun 2 20:32:10 2015 -0700 Update seed directory to use loopback diff --git a/bonfireMDNlinks.js b/bonfireMDNlinks.js new file mode 100644 index 0000000000..9a9ea86741 --- /dev/null +++ b/bonfireMDNlinks.js @@ -0,0 +1,91 @@ +// MDN Links + +/* These links are for Bonfires. Each key/value pair is used to render a Bonfire with appropriate links. + + + The text of the key is what the link text will be, e.g. Global Array Object + General convention is to use the page title of the MDN reference page. +*/ +var links = + { + // ========= NON MDN REFS + "Currying": "https://leanpub.com/javascript-allonge/read#pabc", + "Smallest Common Multiple": "https://www.mathsisfun.com/least-common-multiple.html", + "Permutations": "https://www.mathsisfun.com/combinatorics/combinations-permutations.html", + + // ========= GLOBAL OBJECTS + "Global Array Object" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array", + "Global Object" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object", + "Global String Object" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + "Boolean Objects" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean", + "RegExp" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp", + "Global Function Object": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function", + "Arguments object" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments", + "Closures": "https://developer.mozilla.org/en-US/docs/" + + "Web/JavaScript/Closures", + + // ========= GLOBAL OBJECT METHODS + "parseInt()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt", + + + // ========= PROPERTIES/MISC + "String.length" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length", + + + // ========== OBJECT METHODS + "Object.getOwnPropertyNames()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames", + "Object.keys()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys", + "Object.hasOwnProperty()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty", + + + // ======== STRING METHODS + "String.charAt()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt", + "String.charCodeAt()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt", + "String.concat()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/concat", + "String.indexOf()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf", + "String.fromCharCode()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode", + "String.lastIndexOf()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf", + "String.match()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match", + "String.replace()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace", + "String.slice()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice", + "String.split()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split", + "String.substring()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring", + "String.substr()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr", + "String.toLowerCase()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase", + "String.toString()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toString", + "String.toUpperCase()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase", + // ======== ARRAY METHODS + "Array.concat()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat", + "Array.every()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every", + "Array.filter()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter", + "Array.forEach()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach", + "Array.indexOf()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf", + "Array.isArray()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray", + "Array.join()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join", + "Array.lastIndexOf()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf", + "Array.map()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map", + "Array.pop()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop", + "Array.push()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push", + "Array.reduce()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce", + "Array.reverse()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse", + "Array.shift()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift", + "Array.slice()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice", + "Array.some()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some", + "Array.sort()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort", + "Array.splice()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice", + "Array.toString()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString", + + // ======== MATH METHODS + "Math.max()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max", + "Math.min()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min", + "Math.pow()" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/pow", + "Remainder" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Remainder_(.25)", + + // ======== GENERAL JAVASCRIPT REFERENCES + "Arithmetic Operators" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators", + "Comparison Operators" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators", + "Details of the Object Model" : "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model", + "For Loops": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for" + }; + +module.exports = links; diff --git a/challenge-migration.js b/challenge-migration.js new file mode 100644 index 0000000000..6109f7775b --- /dev/null +++ b/challenge-migration.js @@ -0,0 +1,58 @@ +require('dotenv').load(); +var bonfires = require('./bonfires.json'), + app = require('../server/server'), + mongodb = require('mongodb'), + MongoClient = mongodb.MongoClient, + User = app.models.User, + UserIdentity = app.models.userIdentity, + oldUri='mongodb://localhost:27017/app30893198', + coursewares = require('./coursewares.json'); + +var counter = 0; +var offerings = 2; + +var CompletionMonitor = function() { + counter++; + console.log('call ' + counter); + + if (counter < offerings) { + return; + } else { + process.exit(0); + } +}; + +MongoClient.connect(oldUri, function(err, database) { + + database.collection('users').find({}).batchSize(20).toArray(function(err, users) { + if (users !== null && users.length !== 0) { + var mappedUserArray = users.map(function(user) { + Object.keys(user.profile).forEach(function(prop) { + user[prop] = user.profile[prop]; + }); + Object.keys(user.portfolio).forEach(function(prop) { + user[prop] = user.portfolio[prop]; + }); + + user.completedCoursewares = Object.keys(user.challengesHash) + .filter(function(key) { + return user.challengesHash[key] !== 0; + }) + .map(function(key) { + return({ + _id: coursewares[key].id, + completedDate: user.challengesHash[key] + }); + }); + + return user; + }); + User.create(mappedUserArray, function(err) { + if (err) { + console.log(err); + } + console.log("a batch finished"); + }); + } + }); +}); diff --git a/challengeMapping.json b/challengeMapping.json new file mode 100644 index 0000000000..db6686d266 --- /dev/null +++ b/challengeMapping.json @@ -0,0 +1,226 @@ +[ + { + "oldNumber": "0", + "newId": "bd7124d8c441eddfaeb5bdef" + }, + { + "oldNumber": "1", + "newId": "bd7125d8c441eddfaeb5bd0f" + }, + { + "oldNumber": "2", + "newId": "" + }, + { + "oldNumber": "3", + "newId": "bd7127d8c441eddfaeb5bdef" + }, + { + "oldNumber": "4", + "newId": "bd7128d8c441eddfaeb5bdef" + }, + { + "oldNumber": "5", + "newId": "bd8129d8c441eddfaeb5bdef" + }, + { + "oldNumber": "6", + "newId": "" + }, + { + "oldNumber": "7", + "newId": "" + }, + { + "oldNumber": "8", + "newId": "bd7112d8c441eddfaeb5bdef" + }, + { + "oldNumber": "9", + "newId": "bd7113d8c441eddfaeb5bdef" + }, + { + "oldNumber": "10", + "newId": "bd7114d8c441eddfaeb5bdef" + }, + { + "oldNumber": "11", + "newId": "bd7115d8c441eddfaeb5bdef" + }, + { + "oldNumber": "12", + "newId": "bd7116d8c441eddfaeb5bdef" + }, + { + "oldNumber": "13", + "newId": "bd7117d8c441eddfaeb5bdef" + }, + { + "oldNumber": "14", + "newId": "bd7118d8c441eddfaeb5bdef" + }, + { + "oldNumber": "15", + "newId": "" + }, + { + "oldNumber": "16", + "newId": "" + }, + { + "oldNumber": "17", + "newId": "" + }, + { + "oldNumber": "18", + "newId": "" + }, + { + "oldNumber": "19", + "newId": "bd7123d8c441eddfaeb5bdef" + }, + { + "oldNumber": "20", + "newId": "bd8124d8c441eddfaeb5bdef" + }, + { + "oldNumber": "21", + "newId": "bd8126d8c441eddfaeb5bdef" + }, + { + "oldNumber": "22", + "newId": "bd8127d8c441eddfaeb5bdef" + }, + { + "oldNumber": "23", + "newId": "bd8128d8c441eddfaeb5bdef" + }, + { + "oldNumber": "24", + "newId": "bd7129d8c441eddfaeb5bdef" + }, + { + "oldNumber": "25", + "newId": "bd7130d8c441eddfaeb5bdef" + }, + { + "oldNumber": "26", + "newId": "bd7131d8c441eddfaeb5bdef" + }, + { + "oldNumber": "27", + "newId": "bd7132d8c441eddfaeb5bdef" + }, + { + "oldNumber": "28", + "newId": "bd7133d8c441eddfaeb5bdef" + }, + { + "oldNumber": "29", + "newId": "bd7134d8c441eddfaeb5bdef" + }, + { + "oldNumber": "30", + "newId": "bd7135d8c441eddfaeb5bdef" + }, + { + "oldNumber": "31", + "newId": "bd7136d8c441eddfaeb5bdef" + }, + { + "oldNumber": "32", + "newId": "" + }, + { + "oldNumber": "33", + "newId": "bd7138d8c441eddfaeb5bdef" + }, + { + "oldNumber": "34", + "newId": "bd7137d8c441eddfaeb5bdef" + }, + { + "oldNumber": "35", + "newId": "bd7140d8c441eddfaeb5bdef" + }, + { + "oldNumber": "36", + "newId": "" + }, + { + "oldNumber": "37", + "newId": "" + }, + { + "oldNumber": "38", + "newId": "" + }, + { + "oldNumber": "39", + "newId": "" + }, + { + "oldNumber": "40", + "newId": "" + }, + { + "oldNumber": "41", + "newId": "" + }, + { + "oldNumber": "42", + "newId": "" + }, + { + "oldNumber": "43", + "newId": "" + }, + { + "oldNumber": "44", + "newId": "" + }, + { + "oldNumber": "45", + "newId": "" + }, + { + "oldNumber": "46", + "newId": "" + }, + { + "oldNumber": "47", + "newId": "" + }, + { + "oldNumber": "48", + "newId": "bd7153d8c441eddfaeb5bd2f" + }, + { + "oldNumber": "49", + "newId": "bd7154d8c441eddfaeb5bdef" + }, + { + "oldNumber": "50", + "newId": "bd7155d8c441eddfaeb5bdef" + }, + { + "oldNumber": "51", + "newId": "bd7156d8c441eddfaeb5bdef" + }, + { + "oldNumber": "52", + "newId": "bd7157d8c441eddfaeb5bdef" + }, + { + "oldNumber": "53", + "newId": "bd7158d8c441eddfaeb5bdef" + }, + { + "oldNumber": "54", + "newId": "" + }, + { + "oldNumber": "55", + "newId": "" + } +] diff --git a/challenges/advanced-bonfires.json b/challenges/advanced-bonfires.json new file mode 100644 index 0000000000..eefd2d60ff --- /dev/null +++ b/challenges/advanced-bonfires.json @@ -0,0 +1,297 @@ +{ + "name": "Advanced Algorithm Scripting", + "order": 0.011, + "challenges": [ + { + "_id": "aff0395860f5d3034dc0bfc9", + "name": "Bonfire: Validate US Telephone Numbers", + "difficulty": "4.01", + "description": [ + "Return true if the passed string is a valid US phone number", + "The user may fill out the form field any way they choose as long as it is a valid US number. The following are all valid formats for US numbers:", + "555-555-5555, (555)555-5555, (555) 555-5555, 555 555 5555, 5555555555, 1 555 555 5555", + "For this challenge you will be presented with a string such as \"800-692-7753\" or \"8oo-six427676;laskdjf\". Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is \"1\". Return true if the string is a valid US phone number; otherwise false.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "tests": [ + "expect(telephoneCheck(\"555-555-5555\")).to.be.a(\"boolean\");", + "assert.deepEqual(telephoneCheck(\"1 555-555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1 (555) 555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"5555555555\"), true);", + "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"(555)555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1(555)555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1 555 555 5555\"), true);", + "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1 456 789 4444\"), true);", + "assert.deepEqual(telephoneCheck(\"123**&!!asdf#\"), false);", + "assert.deepEqual(telephoneCheck(\"55555555\"), false);", + "assert.deepEqual(telephoneCheck(\"(6505552368)\"), false);", + "assert.deepEqual(telephoneCheck(\"2 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"0 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"-1 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"2 757 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"10 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"27576227382\"), false);", + "assert.deepEqual(telephoneCheck(\"(275)76227382\"), false);", + "assert.deepEqual(telephoneCheck(\"2(757)6227382\"), false);", + "assert.deepEqual(telephoneCheck(\"2(757)622-7382\"), false);" + ], + "challengeSeed": [ + "function telephoneCheck(str) {", + " // Good luck!", + " return true;", + "}", + "", + "", + "", + "telephoneCheck(\"555-555-5555\");" + ], + "MDNlinks": [ + "RegExp" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a3f503de51cf954ede28891d", + "name": "Bonfire: Symmetric Difference", + "difficulty": "4.02", + "description": [ + "Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.", + "The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function sym(args) {", + " return arguments;", + "}", + "", + "sym([1, 2, 3], [5, 2, 1, 4]);" + ], + "tests": [ + "expect(sym([1, 2, 3], [5, 2, 1, 4])).to.eqls([3, 5, 4])", + "assert.deepEqual(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'should return the symmetric difference of the given arrays');", + "assert.deepEqual(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'should return an array of unique values');", + "assert.deepEqual(sym([1, 1]), [1], 'should return an array of unique values');" + ], + "MDNlinks": [ + "Array.reduce()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "aa2e6f85cab2ab736c9a9b24", + "name": "Bonfire: Exact Change", + "difficulty": "4.03", + "description": [ + "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", + "cid is a 2d array listing available currency.", + "Return the string \"Insufficient Funds\" if cash-in-drawer is less than the change due. Return the string \"Closed\" if cash-in-drawer is equal to the change due.", + "Otherwise, return change in coin and bills, sorted in highest to lowest order.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function drawer(price, cash, cid) {", + " var change;", + " // Here is your change, ma'am.", + " return change;", + "}", + "", + "// Example cash-in-drawer array:", + "// [['PENNY', 1.01],", + "// ['NICKEL', 2.05],", + "// ['DIME', 3.10],", + "// ['QUARTER', 4.25],", + "// ['ONE', 90.00],", + "// ['FIVE', 55.00],", + "// ['TEN', 20.00],", + "// ['TWENTY', 60.00],", + "// ['ONE HUNDRED', 100.00]]", + "", + "drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]);" + ], + "tests": [ + "expect(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]])).to.be.a('array');", + "expect(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", + "expect(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'return correct change');", + "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04] ], 'return correct change with multiple coins and bills');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'insufficient funds');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'cash-in-drawer equals change');" + ], + "MDNlinks": [ + "Global Object" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a56138aff60341a09ed6c480", + "name": "Bonfire: Inventory Update", + "difficulty": "4.04", + "description": [ + "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function inventory(arr1, arr2) {", + " // All inventory must be accounted for or you're fired!", + " return arr1;", + "}", + "", + "// Example inventory lists", + "var curInv = [", + " [21, 'Bowling Ball'],", + " [2, 'Dirty Sock'],", + " [1, 'Hair Pin'],", + " [5, 'Microphone']", + "];", + "", + "var newInv = [", + " [2, 'Hair Pin'],", + " [3, 'Half-Eaten Apple'],", + " [67, 'Bowling Ball'],", + " [7, 'Toothpaste']", + "];", + "", + "inventory(curInv, newInv);" + ], + "tests": [ + "expect(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']])).to.be.a('array');", + "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6);", + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']]);", + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']]);", + "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']]);", + "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']]);" + ], + "MDNlinks": [ + "Global Array Object" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a7bf700cd123b9a54eef01d5", + "name": "Bonfire: No repeats please", + "difficulty": "4.05", + "description": [ + "Return the number of total permutations of the provided string that don't have repeated consecutive letters.", + "For example, 'aab' should return 2 because it has 6 total permutations, but only 2 of them don't have the same letter (in this case 'a') repeating.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function permAlone(str) {", + " return str;", + "}", + "", + "permAlone('aab');" + ], + "tests": [ + "expect(permAlone('aab')).to.be.a.number;", + "expect(permAlone('aab')).to.equal(2);", + "expect(permAlone('aaa')).to.equal(0);", + "expect(permAlone('aabb')).to.equal(8);", + "expect(permAlone('abcdefa')).to.equal(3600);", + "expect(permAlone('abfdefa')).to.equal(2640);", + "expect(permAlone('zzzzzzzz')).to.equal(0);" + ], + "MDNlinks": [ + "Permutations", + "RegExp" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a19f0fbe1872186acd434d5a", + "name": "Bonfire: Friendly Date Ranges", + "difficulty": "4.06", + "description": [ + "Implement a way of converting two dates into a more friendly date range that could be presented to a user.", + "It must not show any redundant information in the date range.", + "For example, if the year and month are the same then only the day range should be displayed.", + "Secondly, if the starting year is the current year, and the ending year can be inferred by the reader, the year should be omitted.", + "Input date is formatted as YYYY-MM-DD", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function friendly(str) {", + " return str;", + "}", + "", + "friendly(['2015-07-01', '2015-07-04']);" + ], + "tests": [ + "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'ending month should be omitted since it is already mentioned');", + "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'one month apart can be inferred it is the next year');", + "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017']);", + "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th, 2016']);", + "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'since we do not duplicate only return once');", + "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023']);" + ], + "MDNlinks": [ + "String.split()", + "String.substr()", + "parseInt()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + } + ] +} \ No newline at end of file diff --git a/challenges/basejumps.json b/challenges/basejumps.json new file mode 100644 index 0000000000..aa8cac1acc --- /dev/null +++ b/challenges/basejumps.json @@ -0,0 +1,229 @@ +{ + "name": "Full Stack JavaScript Projects", + "order": 0.014, + "challenges": [ + { + "_id": "bd7158d8c443eddfaeb5bcef", + "name": "Waypoint: Get Set for Basejumps", + "difficulty": 2.00, + "challengeSeed": "128451852", + "description": [ + "Objective: Get the MEAN stack running on Cloud 9, push your code to GitHub, and deploy it to Heroku.", + "We'll build our Basejumps on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", + "If you don't already have Cloud 9 account, create one now at http://c9.io.", + "Now let's get your development environment ready for a new Angular-Fullstack application provided by Yeoman.", + "Open up http://c9.io and sign in to your account.", + "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", + "Give your workspace a name.", + "Choose Node.js in the selection area below the name field.", + "Click the Create button.", + "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button.", + "Click the \"Start Editing\" button.", + "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", + "Never run this command on your local machine. But in your Cloud 9 terminal window, run: rm -rf * && echo \"export NODE_PATH=$NODE_PATH:/home/ubuntu/.nvm/v0.10.35/lib/node_modules\" >> ~/.bashrc && source ~/.bashrc && npm install -g yo grunt grunt-cli generator-angular-fullstack && yo angular-fullstack", + "Yeoman will prompt you to answer some questions. Answer them like this:", + "What would you like to write scripts with? JavaScript", + "What would you like to write markup with? HTML", + "What would you like to write stylesheets with? CSS", + "What Angular router would you like to use? ngRoute", + "Would you like to include Bootstrap? Yes", + "Would you like to include UI Bootstrap? Yes", + "Would you like to use MongoDB with Mongoose for data modeling? Yes", + "Would you scaffold out an authentication boilerplate? Yes", + "Would you like to include additional oAuth strategies? Twitter", + "Would you like to use socket.io? No", + "May bower anonymously report usage statistics to improve the tool over time? (Y/n) Y", + "You may get an error similar to ERR! EEXIST, open ‘/home/ubuntu/.npm. This is caused when Cloud9 runs out of memory and kills an install. If you get this, simply re-run this process with the command yo angular-fullstack. You will then be asked a few questions regarding the re-install. Answer them as follows:", + "Existing .yo-rc configuration found, would you like to use it? (Y/n) Y", + "Overwrite client/favicon.ico? (Ynaxdh) Y", + "To finish the installation run the commands: bower install && npm install", + "To start MongoDB, run the following commands in your terminal: mkdir data && echo 'mongod --bind_ip=$IP --dbpath=data --nojournal --rest \"$@\"' > mongod && chmod a+x mongod && ./mongod", + "You will want to open up a new terminal to work from by clicking on the + icon and select New Terminal", + "Start the application by running the following command in your new terminal window: grunt serve", + "Wait for the following message to appear: xdg-open: no method available for opening 'http://localhost:8080' . Now you can open the internal Cloud9 browser. To launch the browser select Preview in the toolbar then select the dropdown option Preview Running Application.", + "Turn the folder in which your application is running into a Git repository by running the following commands: git init && git add . && git commit -am 'initial commit'.", + "Now we need to add your GitHub SSH key to c9.io. Click the \"Add-on Services\" button in the lower left of your C9 dashboard. Click \"activate\" next to the GitHub icon.", + "A pop up will appear. Allow access to your account.", + "While still on the dashboard, under “Account Settings”, click the link for \"Show your SSH key\". Copy the key to you clipboard.", + "Sign in to http://github.com and navigate to the GitHub SSH settings page. Click the \"Add SSH Key\". Give your key the title \"cloud 9\". Paste your SSH Key into the \"Key\" box, then click \"Add Key\".", + "Create a new GitHub repository by and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".", + "Enter a project name, then click the \"Create Repository\" button.", + "Find the \"...or push an existing repository from the command line\" section and click the Copy to Clipboard button beside it.", + "Paste the commands from your clipboard into the Cloud9 terminal prompt. This will push your changes to your repository on Cloud 9 up to GitHub.", + "Check back on your GitHub profile to verify the changes were successfully pushed up to GitHub.", + "Now let's push your code to Heroku. If you don't already have a Heroku account, create one at http://heroku.com. You shouldn't be charged for anything, but you will need to add your credit card information to your Heroku before you will be able to use Heroku's free MongoLab add on.", + "Before you publish to Heroku, you should free up as much memory as possible on Cloud9. In each of the Cloud9 terminal prompt tabs where MongoDB and Grunt are running, press the control + c hotkey to shut down these processes.", + "Run the following command in a Cloud9 terminal prompt tab: npm install grunt-contrib-imagemin --save-dev && npm install --save-dev && heroku login. At this point, the terminal will prompt you to log in to Heroku from the command line.", + "Now run yo angular-fullstack:heroku. You can choose a name for your Heroku project, or Heroku will create a random one for you. You can choose whether you want to deploy to servers the US or the EU.", + "Set the config flag for your Heroku environment and add MongoLab for your MongoDB instance by running the following command: cd ~/workspace/dist && heroku config:set NODE_ENV=production && heroku addons:add mongolab.", + "As you build your app, you should frequently commit changes to your codebase. Make sure you're in the ~/workspace directory by running cd ~/workspace. Then you can this code to stage the changes to your changes and commit them: git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a short summary of the changes you made to your code, such as \"added a records controller and corresponding routes\".", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Now you're ready to move on to your first Basejump. Click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bdef", + "name": "Basejump: Build a Voting App", + "difficulty": 2.01, + "challengeSeed": "128451852", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://voteplex.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As an authenticated user, I can keep my polls and come back later to access them.", + "User Story: As an authenticated user, I can share my polls with my friends.", + "User Story: As an authenticated user, I can see the aggregate results of my polls.", + "User Story: As an authenticated user, I can delete polls that I decide I don't want anymore.", + "User Story: As an authenticated user, I can create a poll with any number of possible items.", + "Bonus User Story: As an unauthenticated user, I can see everyone's polls, but I can't vote on anything.", + "Bonus User Story: As an unauthenticated or authenticated user, I can see the results of polls in chart form. (This could be implemented using Chart.js or Google Charts.)", + "Bonus User Story: As an authenticated user, if I don't like the options on a poll, I can create a new option.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bdff", + "name": "Basejump: Build a Nightlife Coordination App", + "difficulty": 2.02, + "challengeSeed": "128451852", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://sociallife.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As an unauthenticated user, I can view all bars in my area.", + "User Story: As an authenticated user, I can add myself to a bar to indicate I am going there tonight.", + "User Story: As an authenticated user, I can remove myself from a bar if I no longer want to go there.", + "Bonus User Story: As an unauthenticated user, when I login I should not have to search again.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bd0e", + "name": "Basejump: Chart the Stock Market", + "difficulty": 2.03, + "challengeSeed": "128451852", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://stockjump.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As a user, I can view a graph displaying the recent trend lines for each added stock.", + "User Story: As a user, I can add new stocks by their symbol name.", + "User Story: As a user, I can remove stocks.", + "Bonus User Story: As a user, I can see changes in real-time when any other user adds or removes a stock.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bd0f", + "name": "Basejump: Manage a Book Trading Club", + "difficulty": 2.04, + "challengeSeed": "128451852", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://bookoutpost.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As an authenticated user, I can view all books posted by every user.", + "User Story: As an authenticated user, I can add a new book.", + "User Story: As an authenticated user, I can update my settings to store my full name, city, and state.", + "Bonus User Story: As an authenticated user, I can propose a trade and wait for the other user to accept the trade.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bdee", + "name": "Basejump: Build a Pinterest Clone", + "difficulty": 2.05, + "challengeSeed": "128451852", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://linkterest.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As an unauthenticated user, I can login with Twitter.", + "User Story: As an authenticated user, I can link to images.", + "User Story: As an authenticated user, I can delete images that I've linked to.", + "User Story: As an authenticated user, I can see a Pinterest-style wall of all the images I've linked to.", + "User Story: As an unauthenticated user, I can browse other users' walls of images.", + "Bonus User Story: As an authenticated user, if I upload an image that is broken, it will be replaced by a placeholder image. (can use jQuery broken image detection)", + "Hint: Masonry.js is a library that allows for Pinterest-style image grids.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + } + ] +} diff --git a/challenges/basic-bonfires.json b/challenges/basic-bonfires.json new file mode 100644 index 0000000000..94fd787a39 --- /dev/null +++ b/challenges/basic-bonfires.json @@ -0,0 +1,1473 @@ +{ + "name": "Basic Algorithm Scripting", + "order": 0.007, + "challenges": [ + { + "_id": "bd7139d8c441eddfaeb5bdef", + "name": "Waypoint: Pair Program on Bonfires", + "difficulty": 0.44, + "challengeSeed": "119657641", + "description": [ + "OK, we're finally ready to start pair programming!", + "Pair Programming is where two people code together on the same computer. It is an efficient way to collaborate, and widely practiced at software companies. Pair Programming is one of the core concepts of \"Agile\" Software Development, which you will hear more about later.", + "Many people use Skype or Google Hangouts to pair program, but if you talk with professional software engineers, they will tell you that it's not really pair programming unless both people have the ability to use the keyboard and mouse.", + "The most popular tool for pair programming is Screen Hero. You can download Screen Hero for Mac or Windows. Create your new user account from within the app.", + "We have a special chat room for people ready to pair program. Go to our Slack chat room, navigate to the #letspair channel and type \"Hello Pair Programmers!\"", + "If someone is available, they will be your \"pair\" - the person you pair programming with.", + "If no one gets back to you in the first few minutes, don't worry. There will be lots of opportunities to pair program in the future.", + "If someone does get back to you, private message them and ask for the email address they used to register Screen Hero.", + "Add them as a new contact in Screen Hero, then click the monitor-looking button to attempt to share your screen with them.", + "Once the Screen Hero session starts, your screen's margins will glow orange. You are now sharing your screen.", + "Your pair will have their own cursor, and will be able to type text on his or her and keyboard.", + "Now it's time to tackle our Bonfires. You can begin them by advancing to the next challenge.", + "Once you you finish pair programming, end the session in Screen Hero session.", + "Congratulations! You have completed your first pair programming session.", + "Pair program as much as possible with different campers until you've completed all the Bonfire challenges. This is a big time investment, but the JavaScript practice you get will be well worth it!", + "Mark this Waypoint complete and move on." + ], + "challengeType": 2, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "ad7123c8c441eddfaeb5bdef", + "name": "Bonfire: Meet Bonfire", + "difficulty": "0", + "description": [ + "Click the button below for further instructions.", + "Your goal is to fix the failing test.", + "First, run all the tests by clicking \"Run code\" or by pressing Control + Enter", + "The failing test is in red. Fix the code so that all tests pass. Then you can move on to the next Bonfire.", + "Make this function return true no matter what." + ], + "tests": [ + "expect(meetBonfire()).to.be.a(\"boolean\");", + "expect(meetBonfire()).to.be.true;" + ], + "challengeSeed": [ + "function meetBonfire(argument) {", + " // Good luck!", + " console.log(\"you can read this function's argument in the developer tools\", argument);", + "", + " return false;", + "}", + "", + "", + "", + "meetBonfire(\"You can do this!\");" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a202eed8fc186c8434cb6d61", + "name": "Bonfire: Reverse a String", + "difficulty": "1.01", + "tests": [ + "expect(reverseString('hello')).to.be.a('String');", + "expect(reverseString('hello')).to.equal('olleh');", + "expect(reverseString('Howdy')).to.equal('ydwoH');", + "expect(reverseString('Greetings from Earth')).to.equal('htraE morf sgniteerG');" + ], + "description": [ + "Reverse the provided string.", + "You may need to turn the string into an array before you can reverse it.", + "Your result must be a string.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function reverseString(str) {", + " return str;", + "}", + "", + "reverseString('hello');" + ], + "MDNlinks": [ + "Global String Object", + "String.split()", + "Array.reverse()", + "Array.join()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a302f7aae1aa3152a5b413bc", + "name": "Bonfire: Factorialize a Number", + "tests": [ + "expect(factorialize(5)).to.be.a(\"Number\");", + "expect(factorialize(5)).to.equal(120);", + "expect(factorialize(10)).to.equal(3628800);", + "expect(factorialize(20)).to.equal(2432902008176640000);" + ], + "difficulty": "1.02", + "description": [ + "Return the factorial of the provided integer.", + "If the integer is represented with the letter n, a factorial is the product of all positive integers less than or equal to n.", + "Factorials are often represented with the shorthand notation n!", + "For example: 5! = 1 * 2 * 3 * 4 * 5 = 120f", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function factorialize(num) {", + " return num;", + "}", + "", + "factorialize(5);" + ], + "MDNlinks": [ + "Arithmetic Operators" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "aaa48de84e1ecc7c742e1124", + "name": "Bonfire: Check for Palindromes", + "difficulty": "1.03", + "description": [ + "Return true if the given string is a palindrome. Otherwise, return false.", + "A palindrome is a word or sentence that's spelled the same way both forward and backward, ignoring punctuation, case, and spacing.", + "You'll need to remove punctuation and turn everything lower case in order to check for palindromes.", + "We'll pass strings with varying formats, such as \"racecar\", \"RaceCar\", and \"race CAR\" among others.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "tests": [ + "expect(palindrome(\"eye\")).to.be.a(\"boolean\");", + "assert.deepEqual(palindrome(\"eye\"), true);", + "assert.deepEqual(palindrome(\"race car\"), true);", + "assert.deepEqual(palindrome(\"not a palindrome\"), false);", + "assert.deepEqual(palindrome(\"A man, a plan, a canal. Panama\"), true);", + "assert.deepEqual(palindrome(\"never odd or even\"), true);", + "assert.deepEqual(palindrome(\"nope\"), false);" + ], + "challengeSeed": [ + "function palindrome(str) {", + " // Good luck!", + " return true;", + "}", + "", + "", + "", + "palindrome(\"eye\");" + ], + "MDNlinks": [ + "String.replace()", + "String.toLowerCase()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a26cbbe9ad8655a977e1ceb5", + "name": "Bonfire: Find the Longest Word in a String", + "difficulty": "1.04", + "description": [ + "Return the length of the longest word in the provided sentence.", + "Your response should be a number.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function findLongestWord(str) {", + " return str.length;", + "}", + "", + "findLongestWord('The quick brown fox jumped over the lazy dog');" + ], + "tests": [ + "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.be.a('Number');", + "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.equal(6);", + "expect(findLongestWord('May the force be with you')).to.equal(5);", + "expect(findLongestWord('Google do a barrel roll')).to.equal(6);", + "expect(findLongestWord('What is the average airspeed velocity of an unladen swallow')).to.equal(8);" + ], + "MDNlinks": [ + "String.split()", + "String.length" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "ab6137d4e35944e21037b769", + "name": "Bonfire: Title Case a Sentence", + "difficulty": "1.05", + "description": [ + "Return the provided string with the first letter of each word capitalized.", + "For the purpose of this exercise, you should also capitalize connecting words like 'the' and 'of'.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function titleCase(str) {", + " return str;", + "}", + "", + "titleCase(\"I'm a little tea pot\");" + ], + "tests": [ + "expect(titleCase(\"I'm a little tea pot\")).to.be.a('String');", + "expect(titleCase(\"I'm a little tea pot\")).to.equal(\"I'm A Little Tea Pot\");", + "expect(titleCase(\"sHoRt AnD sToUt\")).to.equal(\"Short And Stout\");", + "expect(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\")).to.equal(\"Here Is My Handle Here Is My Spout\");" + ], + "MDNlinks": [ + "String.charAt()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a789b3483989747d63b0e427", + "name": "Bonfire: Return Largest Numbers in Arrays", + "difficulty": "1.06", + "description": [ + "Return an array consisting of the largest number from each provided sub-array. For simplicity, the provided array will contain exactly 4 sub-arrays.", + "Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i] .", + "If you are writing your own Chai.js tests, be sure to use a deep equal statement instead of an equal statement when comparing arrays.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function largestOfFour(arr) {", + " // You can do this!", + " return arr;", + "}", + "", + "largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);" + ], + "tests": [ + "expect(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).to.be.a('array');", + "(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).should.eql([5,27,39,1001]);", + "assert(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]).should.eql([9,35,97,1000000]));" + ], + "MDNlinks": [ + "Comparison Operators" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "acda2fb1324d9b0fa741e6b5", + "name": "Bonfire: Confirm the Ending", + "difficulty": "1.07", + "description": [ + "Check if a string (first argument) ends with the given target string (second argument).", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function end(str, target) {", + " // \"Never give up and good luck will find you.\"", + " // -- Falcor", + " return str;", + "}", + "", + "end('Bastian', 'n');" + ], + "tests": [ + "assert.strictEqual(end('Bastian', 'n'), true, 'should equal true if target equals end of string');", + "assert.strictEqual(end('He has to give me a new name', 'name'), true, 'should equal true if target equals end of string');", + "assert.strictEqual(end('If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing', 'mountain'), false, 'should equal false if target does not equal end of string');" + ], + "MDNlinks": [ + "String.substr()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "afcc8d540bea9ea2669306b6", + "name": "Bonfire: Repeat a string repeat a string", + "difficulty": "1.08", + "description": [ + "Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function repeat(str, num) {", + " // repeat after me", + " return str;", + "}", + "", + "repeat('abc', 3);" + ], + "tests": [ + "assert.strictEqual(repeat('*', 3), '***', 'should repeat a string n times');", + "assert.strictEqual(repeat('abc', 3), 'abcabcabc', 'should repeat a string n times');", + "assert.strictEqual(repeat('abc', -2), '', 'should return an empty string for negative numbers');" + ], + "MDNlinks": [ + "Global String Object" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "ac6993d51946422351508a41", + "name": "Bonfire: Truncate a string", + "difficulty": "1.09", + "description": [ + "Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a '...' ending.", + "Note that the three dots at the end add to the string length.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function truncate(str, num) {", + " // Clear out that junk in your trunk", + " return str;", + "}", + "", + "truncate('A-tisket a-tasket A green and yellow basket', 11);" + ], + "tests": [ + "expect(truncate('A-tisket a-tasket A green and yellow basket', 11)).to.eqls('A-tisket...');", + "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length) === 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is = length');", + "assert.strictEqual(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2), 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is < length');" + ], + "MDNlinks": [ + "String.slice()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a9bd25c716030ec90084d8a1", + "name": "Bonfire: Chunky Monkey", + "difficulty": "1.10", + "description": [ + "Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function chunk(arr, size) {", + " // Break it up.", + " return arr;", + "}", + "", + "chunk(['a', 'b', 'c', 'd'], 2);" + ], + "tests": [ + "assert.deepEqual(chunk(['a', 'b', 'c', 'd'], 2), [['a', 'b'], ['c', 'd']], 'should return chunked arrays');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'should return chunked arrays');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 2), [[0, 1], [2, 3], [4, 5]], 'should return chunked arrays');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'should return the last chunk as remaining elements');" + ], + "MDNlinks": [ + "Array.push()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "ab31c21b530c0dafa9e241ee", + "name": "Bonfire: Slasher Flick", + "difficulty": "1.11", + "description": [ + "Return the remaining elements of an array after chopping off n elements from the head.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function slasher(arr, howMany) {", + " // it doesn't always pay to be first", + " return arr;", + "}", + "", + "slasher([1, 2, 3], 2);" + ], + "tests": [ + "assert.deepEqual(slasher([1, 2, 3], 2), [3], 'should drop the first two elements');", + "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], 'should return all elements when n < 1');", + "assert.deepEqual(slasher([1, 2, 3], 9), [], 'should return an empty array when n >= array.length');" + ], + "MDNlinks": [ + "Array.slice()", + "Array.splice()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "af2170cad53daa0770fabdea", + "name": "Bonfire: Mutations", + "difficulty": "1.12", + "description": [ + "Return true if the string in the first element of the array contains all of the letters of the string in the second element of the array.", + "For example, ['hello', 'Hello'], should return true because all of the letters in the second string are present in the first, ignoring case.", + "The arguments ['hello', 'hey'] should return false because the string 'hello' does not contain a 'y'.", + "Another example, ['Alien', 'line'], should return true because all of the letters in 'line' are present in 'Alien'.", + "Lastly, ['Mary', 'Aarmy'] should return false because 'Mary' is only 4 letters while 'Aarmy' is 5, so 'Mary' can't possibly contain 'Aarmy'", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function mutation(arr) {", + " return arr;", + "}", + "", + "mutation(['hello', 'hey']);" + ], + "tests": [ + "expect(mutation(['hello', 'hey'])).to.be.false;", + "expect(mutation(['hello', 'Hello'])).to.be.true;", + "expect(mutation(['zyxwvutsrqponmlkjihgfedcba', 'qrstu'])).to.be.true;", + "expect(mutation(['Mary', 'Army'])).to.be.true;", + "expect(mutation(['Mary', 'Aarmy'])).to.be.false;", + "expect(mutation(['Alien', 'line'])).to.be.true;", + "expect(mutation(['floor', 'for'])).to.be.true;" + ], + "MDNlinks": [ + "Array.indexOf()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "adf08ec01beb4f99fc7a68f2", + "name": "Bonfire: Falsey Bouncer", + "difficulty": "1.50", + "description": [ + "Remove all falsey values from an array.", + "Falsey values in javascript are false, null, 0, \"\", undefined, and NaN.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function bouncer(arr) {", + " // Don't show a false ID to this bouncer.", + " return arr;", + "}", + "", + "bouncer([7, 'ate', '', false, 9]);" + ], + "tests": [ + "assert.deepEqual(bouncer([7, 'ate', '', false, 9]), [7, 'ate', 9], 'should remove falsey values');", + "assert.deepEqual(bouncer(['a', 'b', 'c']), ['a', 'b', 'c'], 'should return full array if no falsey elements');", + "assert.deepEqual(bouncer([false, null, 0]), [], 'should return empty array if all elements are falsey');" + ], + "MDNlinks": [ + "Boolean Objects", + "Array.filter()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a8e512fbe388ac2f9198f0fa", + "name": "Bonfire: Where art thou", + "difficulty": "1.55", + "description": [ + "Make a function that looks through a list (first argument) and returns an array of all objects that have equivalent property values (second argument).", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function where(collection, source) {", + " var arr = [];", + " // What's in a name?", + " return arr;", + "}", + "", + "where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });" + ], + "tests": [ + "assert.deepEqual(where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }), [{ first: 'Tybalt', last: 'Capulet' }], 'should return an array of objects');", + "assert.deepEqual(where([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'should return with multiples');" + ], + "MDNlinks": [ + "Global Object", + "Object.hasOwnProperty()", + "Object.keys()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a39963a4c10bc8b4d4f06d7e", + "name": "Bonfire: Seek and Destroy", + "difficulty": "1.60", + "description": [ + "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function destroyer(arr) {", + " // Remove all the values", + " return arr;", + "}", + "", + "destroyer([1, 2, 3, 1, 2, 3], 2, 3);" + ], + "tests": [ + "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'should remove correct values from an array');", + "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');" + ], + "MDNlinks": [ + "Arguments object", + "Array.filter()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a24c1a4622e3c05097f71d67", + "name": "Bonfire: Where do I belong", + "difficulty": "1.61", + "description": [ + "Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).", + "For example, where([1,2,3,4], 1.5) should return 1 because it is greater than 1 (0th index), but less than 2 (1st index).", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function where(arr, num) {", + " // Find my place in this sorted array.", + " return num;", + "}", + "", + "where([40, 60], 50);" + ], + "MDNlinks": [ + "Array.sort()" + ], + "tests": [ + "expect(where([10, 20, 30, 40, 50], 35)).to.equal(3);", + "expect(where([10, 20, 30, 40, 50], 30)).to.equal(2);" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a3566b1109230028080c9345", + "name": "Bonfire: Sum All Numbers in a Range", + "difficulty": "2.00", + "description": [ + "We'll pass you an array of two numbers. Return the sum of those two numbers and all numbers between them.", + "The lowest number will not always come first.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function sumAll(arr) {", + " return(1);", + "}", + "", + "sumAll([1, 4]);" + ], + "tests": [ + "expect(sumAll([1, 4])).to.be.a('Number');", + "expect(sumAll([1, 4])).to.equal(10);", + "expect(sumAll([4, 1])).to.equal(10);", + "expect(sumAll([5, 10])).to.equal(45);", + "expect(sumAll([10, 5])).to.equal(45);" + ], + "MDNlinks": [ + "Math.max()", + "Math.min()", + "Array.reduce()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a5de63ebea8dbee56860f4f2", + "name": "Bonfire: Diff Two Arrays", + "difficulty": "2.01", + "description": [ + "Compare two arrays and return a new array with any items not found in both of the original arrays.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function diff(arr1, arr2) {", + " var newArr = [];", + " // Same, same; but different.", + " return newArr;", + "}", + "", + "diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);" + ], + "tests": [ + "expect(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])).to.be.a('array');", + "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'arrays with only one difference');", + "assert.includeMembers(diff(['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['diorite', 'pink wool'], 'arrays with more than one difference');", + "assert.deepEqual(diff(['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub']), [], 'arrays with no difference');", + "assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'arrays with numbers');", + "assert.includeMembers(diff([1, 'calf', 3, 'piglet'], [1, 'calf', 3, 4]), ['piglet', 4], 'arrays with numbers and strings');", + "assert.deepEqual(diff([], ['snuffleupagus', 'cookie monster', 'elmo']), ['snuffleupagus', 'cookie monster', 'elmo'], 'empty array');" + ], + "MDNlinks": [ + "Comparison Operators", + "String.slice()", + "Array.filter()", + "Array.indexOf()", + "String.concat()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a7f4d8f2483413a6ce226cac", + "name": "Bonfire: Roman Numeral Converter", + "tests": [ + "expect(convert(12)).to.equal(\"XII\");", + "expect(convert(5)).to.equal(\"V\");", + "expect(convert(9)).to.equal(\"IX\");", + "expect(convert(29)).to.equal(\"XXIX\");", + "expect(convert(16)).to.equal(\"XVI\");" + ], + "difficulty": "2.02", + "description": [ + "Convert the given number into a roman numeral.", + "All roman numerals answers should be provided in upper-case.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function convert(num) {", + " return num;", + "}", + "", + "convert(36);" + ], + "MDNlinks": [ + "Array.splice()", + "Array.indexOf()", + "Array.join()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a0b5010f579e69b815e7c5d6", + "name": "Bonfire: Search and Replace", + "tests": [ + "expect(replace(\"Let us go to the store\", \"store\", \"mall\")).to.equal(\"Let us go to the mall\");", + "expect(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")).to.equal(\"He is Sitting on the couch\");", + "expect(replace(\"This has a spellngi error\", \"spellngi\", \"spelling\")).to.equal(\"This has a spelling error\");", + "expect(replace(\"His name is Tom\", \"Tom\", \"john\")).to.equal(\"His name is John\");", + "expect(replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")).to.equal(\"Let us get back to more Bonfires\");" + ], + "difficulty": "2.03", + "description": [ + "Perform a search and replace on the sentence using the arguments provided and return the new sentence.", + "First argument is the sentence the perform the search and replace on.", + "Second argument is the word that you will be replacing (before).", + "Third argument is what you will be replacing the second argument with (after).", + "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word 'Book' with the word 'dog', it should be replaced as 'Dog'", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function replace(str, before, after) {", + " return str;", + "}", + "", + "replace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");" + ], + "MDNlinks": [ + "Array.splice()", + "String.replace()", + "Array.join()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "aa7697ea2477d1316795783b", + "name": "Bonfire: Pig Latin", + "tests": [ + "expect(translate(\"california\")).to.equal(\"aliforniacay\");", + "expect(translate(\"paragraphs\")).to.equal(\"aragraphspay\");", + "expect(translate(\"glove\")).to.equal(\"oveglay\");", + "expect(translate(\"algorithm\")).to.equal(\"algorithmway\");", + "expect(translate(\"eight\")).to.equal(\"eightway\");" + ], + "difficulty": "2.04", + "description": [ + "Translate the provided string to pig latin.", + "Pig Latin takes the first consonant (or consonant cluster) of an English word, moves it to the end of the word and suffixes an \"ay\".", + "If a word begins with a vowel you just add \"way\" to the end.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function translate(str) {", + " return str;", + "}", + "", + "translate(\"consonant\");" + ], + "MDNlinks": [ + "Array.indexOf()", + "Array.push()", + "Array.join()", + "String.substr()", + "String.split()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "afd15382cdfb22c9efe8b7de", + "name": "Bonfire: DNA Pairing", + "tests": [ + "assert.deepEqual(pair(\"ATCGA\"),[['A','T'],['T','A'],['C','G'],['G','C'],['A','T']], 'should return the dna pair');", + "assert.deepEqual(pair(\"TTGAG\"),[['T','A'],['T','A'],['G','C'],['A','T'],['G','C']], 'should return the dna pair');", + "assert.deepEqual(pair(\"CTCTA\"),[['C','G'],['T','A'],['C','G'],['T','A'],['A','T']], 'should return the dna pair');" + ], + "difficulty": "2.05", + "description": [ + "The DNA strand is missing the pairing element. Match each character with the missing element and return the results as a 2d array.", + "Base pairs are a pair of AT and CG. Match the missing element to the provided character.", + "Return the provided character as the first element in each array.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function pair(str) {", + " return str;", + "}", + "", + "pair(\"GCG\");" + ], + "MDNlinks": [ + "Array.push()", + "String.split()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "af7588ade1100bde429baf20", + "name": "Bonfire: Missing letters", + "difficulty": "2.05", + "description": [ + "Find the missing letter in the passed letter range and return it.", + "If all letters are present in the range, return undefined.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function fearNotLetter(str) {", + " return str;", + "}", + "", + "fearNotLetter('abce');" + ], + "tests": [ + "expect(fearNotLetter('abce')).to.equal('d');", + "expect(fearNotLetter('bcd')).to.be.undefined;", + "expect(fearNotLetter('abcdefghjklmno')).to.equal('i');", + "expect(fearNotLetter('yz')).to.be.undefined;" + ], + "MDNlinks": [ + "String.charCodeAt()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a77dbc43c33f39daa4429b4f", + "name": "Bonfire: Boo who", + "difficulty": "2.06", + "description": [ + "Check if a value is classified as a boolean primitive. Return true or false.", + "Boolean primitives are true and false.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function boo(bool) {", + " // What is the new fad diet for ghost developers? The Boolean.", + " return bool;", + "}", + "", + "boo(null);" + ], + "tests": [ + "assert.strictEqual(boo(true), true);", + "assert.strictEqual(boo(false), true);", + "assert.strictEqual(boo([1, 2, 3]), false);", + "assert.strictEqual(boo([].slice), false);", + "assert.strictEqual(boo({ 'a': 1 }), false);", + "assert.strictEqual(boo(1), false);", + "assert.strictEqual(boo(NaN), false);", + "assert.strictEqual(boo('a'), false);" + ], + "MDNlinks": [ + "Boolean Objects" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a105e963526e7de52b219be9", + "name": "Bonfire: Sorted Union", + "difficulty": "2.07", + "description": [ + "Write a function that takes two or more arrays and returns a new array of unique values in the order of the original provided arrays.", + "In other words, all values present from all arrays should be included in their original order, but with no duplicates in the final array.", + "The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.", + "Check the assertion tests for examples.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function unite(arr1, arr2, arr3) {", + " return arr1;", + "}", + "", + "unite([1, 2, 3], [5, 2, 1, 4], [2, 1]);" + ], + "tests": [ + "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'should return the union of the given arrays');", + "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'should not flatten nested arrays');" + ], + "MDNlinks": [ + "Array.reduce()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a6b0bb188d873cb2c8729495", + "name": "Bonfire: Convert HTML Entities", + "difficulty": "2.07", + "description": [ + "Convert the characters \"&\", \"<\", \">\", '\"', and \"'\", in a string to their corresponding HTML entities.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function convert(str) {", + " // :)", + " return str;", + "}", + "", + "convert('Dolce & Gabbana');" + ], + "tests": [ + "assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');", + "assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');" + ], + "MDNlinks": [ + "RegExp" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a103376db3ba46b2d50db289", + "name": "Bonfire: Spinal Tap Case", + "difficulty": "2.08", + "description": [ + "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function spinalCase(str) {", + " // \"It's such a fine line between stupid, and clever.\"", + " // --David St. Hubbins", + " return str;", + "}", + "", + "spinalCase('This Is Spinal Tap');" + ], + "tests": [ + "assert.strictEqual(spinalCase('This Is Spinal Tap'), 'this-is-spinal-tap', 'should return spinal case from string with spaces');", + "assert.strictEqual(spinalCase('thisIsSpinalTap'), 'this-is-spinal-tap', 'should return spinal case from string with camel case');", + "assert.strictEqual(spinalCase('The_Andy_Griffith_Show'), 'the-andy-griffith-show', 'should return spinal case from string with snake case');", + "assert.strictEqual(spinalCase('Teletubbies say Eh-oh'), 'teletubbies-say-eh-oh', 'should return spinal case from string with spaces and hyphens');" + ], + "MDNlinks": [ + "RegExp", + "String.replace()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a5229172f011153519423690", + "name": "Bonfire: Sum All Odd Fibonacci Numbers", + "difficulty": "2.09", + "description": [ + "Return the sum of all odd Fibonacci numbers up to and including the passed number if it is a Fibonacci number.", + "The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8, and each subsequent number is the sum of the previous two numbers.", + "As an example, passing 4 to the function should return 5 because all the odd Fibonacci numbers under 4 are 1, 1, and 3.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function sumFibs(num) {", + " return num;", + "}", + "", + "sumFibs(4);" + ], + "tests": [ + "expect(sumFibs(1)).to.be.a('number');", + "expect(sumFibs(1000)).to.equal(1785);", + "expect(sumFibs(4000000)).to.equal(4613732);", + "expect(sumFibs(4)).to.equal(5);", + "expect(sumFibs(75024)).to.equal(60696);", + "expect(sumFibs(75025)).to.equal(135721);" + ], + "MDNlinks": [ + "Remainder" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a3bfc1673c0526e06d3ac698", + "name": "Bonfire: Sum All Primes", + "difficulty": "2.10", + "description": [ + "Sum all the prime numbers up to and including the provided number.", + "A prime number is defined as having only two divisors, 1 and itself. For example, 2 is a prime number because it's only divisible by 1 and 2. 1 isn't a prime number, because it's only divisible by itself.", + "The provided number may not be a prime.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function sumPrimes(num) {", + " return num;", + "}", + "", + "sumPrimes(10);" + ], + "tests": [ + "expect(sumPrimes(10)).to.be.a('number');", + "expect(sumPrimes(10)).to.equal(17);", + "expect(sumPrimes(977)).to.equal(73156);" + ], + "MDNlinks": [ + "For Loops", + "Array.push()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "ae9defd7acaf69703ab432ea", + "name": "Bonfire: Smallest Common Multiple", + "difficulty": "2.11", + "description": [ + "Find the smallest number that is evenly divisible by all numbers in the provided range.", + "The range will be an array of two numbers that will not necessarily be in numerical order.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function smallestCommons(arr) {", + " return arr;", + "}", + "", + "", + "smallestCommons([1,5]);" + ], + "tests": [ + "expect(smallestCommons([1,5])).to.be.a('number');", + "expect(smallestCommons([1,5])).to.equal(60);", + "expect(smallestCommons([5,1])).to.equal(60);", + "expect(smallestCommons([1,13])).to.equal(360360);" + ], + "MDNlinks": [ + "Smallest Common Multiple" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a6e40f1041b06c996f7b2406", + "name": "Bonfire: Finders Keepers", + "difficulty": "2.12", + "description": [ + "Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument).", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function find(arr, func) {", + " var num = 0;", + " return num;", + "}", + "", + "find([1, 2, 3, 4], function(num){ return num % 2 === 0; });" + ], + "tests": [ + "assert.strictEqual(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'should return first found value');", + "assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'should return undefined if not found');" + ], + "MDNlinks": [ + "Array.some()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a5deed1811a43193f9f1c841", + "name": "Bonfire: Drop it", + "difficulty": "2.13", + "description": [ + "Drop the elements of an array (first argument), starting from the front, until the predicate (second argument) returns true.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function drop(arr, func) {", + " // Drop them elements.", + " return arr;", + "}", + "", + "drop([1, 2, 3], function(n) {return n < 3; });" + ], + "tests": [ + "expect(drop([1, 2, 3, 4], function(n) {return n >= 3; })).to.eqls([3, 4]);", + "expect(drop([1, 2, 3], function(n) {return n > 0; })).to.eqls([1, 2, 3]);", + "expect(drop([1, 2, 3, 4], function(n) {return n > 5; })).to.eqls([]);" + ], + "MDNlinks": [ + "Arguments object", + "Array.shift()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "ab306dbdcc907c7ddfc30830", + "name": "Bonfire: Steamroller", + "difficulty": "2.14", + "description": [ + "Flatten a nested array. You must account for varying levels of nesting.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function steamroller(arr) {", + " // I'm a steamroller, baby", + " return arr;", + "}", + "", + "steamroller([1, [2], [3, [[4]]]]);" + ], + "tests": [ + "assert.deepEqual(steamroller([[['a']], [['b']]]), ['a', 'b'], 'should flatten nested arrays');", + "assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'should flatten nested arrays');", + "assert.deepEqual(steamroller([1, [], [3, [[4]]]]), [1, 3, 4], 'should work with empty arrays');" + ], + "MDNlinks": [ + "Array.isArray()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a8d97bd4c764e91f9d2bda01", + "name": "Bonfire: Binary Agents", + "difficulty": "2.15", + "description": [ + "Return an English translated sentence of the passed binary string.", + "The binary string will be space separated.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function binaryAgent(str) {", + " return str;", + "}", + "", + "binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');" + ], + "tests": [ + "expect(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111')).to.equal(\"Aren't bonfires fun!?\");", + "expect(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001')).to.equal(\"I love FreeCodeCamp!\");" + ], + "MDNlinks": [ + "String.charCodeAt()", + "String.fromCharCode()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a10d2431ad0c6a099a4b8b52", + "name": "Bonfire: Everything Be True", + "difficulty": "2.21", + "description": [ + "Check if the predicate (second argument) returns truthy (defined) for all elements of a collection (first argument).", + "For this, check to see if the property defined in the second argument is present on every element of the collection.", + "Remember, you can access object properties through either dot notation or [] notation.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function every(collection, pre) {", + " // Does everyone have one of these?", + " return pre;", + "}", + "", + "every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');" + ], + "tests": [ + "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex'), true, 'should return true if predicate returns truthy for all elements in the collection');", + "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], {'sex': 'female'}), false, 'should return false if predicate returns falsey for any element in the collection');" + ], + "MDNlinks": [ + "Object.hasOwnProperty()", + "Object.getOwnPropertyNames()" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "a97fd23d9b809dac9921074f", + "name": "Bonfire: Arguments Optional", + "difficulty": "2.22", + "description": [ + "Create a function that sums two arguments together. If only one argument is provided, return a function that expects one additional argument and will return the sum.", + "For example, add(2, 3) should return 5, and add(2) should return a function that is waiting for an argument so that var sum2And = add(2); return sum2And(3); // 5", + "If either argument isn't a valid number, return undefined.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function add() {", + " return false;", + "}", + "", + "add(2,3);" + ], + "tests": [ + "expect(add(2, 3)).to.equal(5);", + "expect(add(2)(3)).to.equal(5);", + "expect(add('http://bit.ly/IqT6zt')).to.be.undefined;", + "expect(add(2, '3')).to.be.undefined;", + "expect(add(2)([3])).to.be.undefined;" + ], + "MDNlinks": [ + "Global Function Object", + "Arguments object" + ], + "challengeType": 5, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + } + ] +} diff --git a/challenges/basic-html5-and-css.json b/challenges/basic-html5-and-css.json new file mode 100644 index 0000000000..d2a8e1f64e --- /dev/null +++ b/challenges/basic-html5-and-css.json @@ -0,0 +1,2740 @@ +{ + "name": "Basic HTML5 and CSS", + "order": 0.002, + "challenges": [ + { + "_id": "bd7123c8c441eddfaeb5bdef", + "name": "Waypoint: Say Hello to HTML Elements", + "difficulty": 0.0085, + "description": [ + "Welcome to Free Code Camp's first coding challenge! Click on the button below for further instructions.", + "Awesome. Now you can read the rest of this challenge's instructions.", + "You can edit code in your text editor, which we've embedded into this web page.", + "Do you see the code in your text editor that says <h1>Hello</h1>? That's an HTML element.", + "Most HTML elements have an opening tag and a closing tag. Opening tags look like this: <h1>. Closing tags look like this: </h1>. Note that the only difference between opening and closing tags is that closing tags have a slash after their opening angle bracket.", + "Once you've completed each challenge, and all its tests are passing, the \"Go to my next challenge\" button will become enabled. Click it - or press control and enter at the same time - to advance to the next challenge.", + "To enable the \"Go to my next challenge\" button on this exercise, change your h1 tag's text to say \"Hello World\" instead of \"Hello\"." + ], + "tests": [ + "assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1 element should have the text \"Hello World\".')" + ], + "challengeSeed": [ + "

Hello

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "Waypoint: Saluda a los Elementos HTML", + "descriptionEs": [ + "¡Bienvenido/a al primer desafío de programación de Free Code Camp! Haz click en el botón de abajo para tener más instrucciones.", + "Genial. Ahora puedes leer el resto de las instrucciones de este desafío.", + "Puedes editar tu código en tu editor de texto, que hemos incrustado en esta página web.", + "¿Ves el código en tu editor de texto que dice <h1>Hello</h1>? Ese es un elemento HTML.", + "La mayoría de los elementos HTML tienen una etiqueta de apertura y una etiqueta de cierre. Las etiquetas de apertura se ven como: <h1>. Las etiquetas de cierre se ven como: </h1>. Fíjate que la única diferencia entre las etiquetas de apertura y de cierre es que estas últimas tienen un / después de su signo de apertura (<).", + "Una vez que hayas completado cada desafío, y que hayas pasado todas sus pruebas, el botón \"Ir a mi siguiente desafío\" se activará. Haz click en él - o presiona control y enter al mismo tiempo - para avanzar al siguiente desafío.", + "Para activar el botón \"Ir a mi siguiente desafío\" de este ejercicio, cambia tu texto de la etiqueta h1 para que diga \"Hello World\" en lugar de \"Hello\"." + ], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf0887a", + "name": "Waypoint: Headline with the h2 Element", + "difficulty": 0.010, + "description": [ + "Add an h2 tag that says \"CatPhotoApp\" to create a second HTML element below your \"Hello World\" h1 element.", + "The h2 element you enter will create an h2 element on the website.", + "This element tells the browser how to render the text that it contains.", + "h2 elements are slightly smaller than h1 elements. There are also h3, h4, h5 and h6 elements." + ], + "tests": [ + "assert(($('h2').length > 0), 'Create an h2 element.')", + "assert(editor.match(/<\\/h2>/g) && editor.match(/<\\/h2>/g).length === editor.match(/

/g).length, 'Make sure your h2 element has a closing tag.')", + "assert.isTrue((/cat(\\s)?photo(\\s)?app/gi).test($('h2').text()), 'Your h2 element should have the text \"CatPhotoApp\".')", + "assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1 element should have the text \"Hello World\".')" + ], + "challengeSeed": [ + "

Hello World

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "Waypoint: Encabezado con el elemento h2", + "descriptionEs": [ + "Agrega una etiqueta h2 que diga \"CatPhotoApp\" para crear un segundo elemento HTML debajo de tu elemento h1 \"Hello World\".", + "El elemento h2 que ingreses creará un elemento h2 en el sitio web.", + "Este elemento le dice al navegador cómo mostrar el texto que contiene.", + "Los elementos h2 son ligeramente más pequeños que los elementos h1. También hay elementos h3, h4, h5 y h6." + ], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08801", + "name": "Waypoint: Inform with the Paragraph Element", + "difficulty": 0.011, + "description": [ + "Create a p element below your h2 element, and give it the text \"Hello Paragraph\".", + "p elements are the preferred element for normal-sized paragraph text on websites. P is short for \"paragraph\".", + "You can create a p element like so: <p>I'm a p tag!</p>." + ], + "tests": [ + "assert(($('p').length > 0), 'Create a p element.')", + "assert.isTrue((/hello(\\s)+paragraph/gi).test($('p').text()), 'Your p element should have the text \"Hello Paragraph\".')", + "assert(editor.match(/<\\/p>/g) && editor.match(/<\\/p>/g).length === editor.match(/

p element has a closing tag.')" + ], + "challengeSeed": [ + "

Hello World

", + "

CatPhotoApp

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "Waypoint: Informa con el Elemento Párrafo", + "descriptionEs": [ + "Crea un elemento párrafo debajo de tu elemento h2, y dale el texto \"Hello Paragraph\". Apenas escribas la etiqueta de apertura <p>, una de nuestras pruebas pasarán (ya que ésta es HTML válido). Asegúrate de cerrar el elemento agregando la etiqueta de cierre </p>.", + "Los elementos párrafo son los principales elementos para los párrafos de texto en tamaño normal en sitios web.", + "Tú puedes crear un elemento párrafo como éste: <p>I'm a p tag!</p>." + ], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aeaf08801", + "name": "Waypoint: Visually Separate Elements with Line Breaks", + "difficulty": 0.012, + "description": [ + "Add a br element to your page, preferably between two of your elements.", + "br elements, also known as \"line break\" elements, can be created with <br>.", + "Note that <br> has no closing tag. It is a \"self-closing\" element.", + "You'll encounter other self-closing element tags soon." + ], + "tests": [ + "assert(($('br').length > 0), 'Add a br element to your page preferably between two of your elements.')" + ], + "challengeSeed": [ + "

Hello World

", + "

CatPhotoApp

", + "

Hello Paragraph

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "Waypoint: Separa Elementos Visualmente con Saltos de Línea", + "descriptionEs": [ + "Agrega un salto de línea entre los elementos <h2> y <p>.", + "Puedes crear un elemento de salto de línea con <br/>.", + "Fíjate que <br/> no tiene etiqueta de cierre. Es un elemento auto-cerrado. ¿Ves cómo un / precede el signo de cierre (>)?", + "Luego te encontrarás con otras etiquetas de elementos auto-cerrados." + ], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08802", + "name": "Waypoint: Uncomment HTML", + "difficulty": 0.013, + "description": [ + "Uncomment your h1, h2 and p elements.", + "Commenting is a way that you can leave comments within your code without affecting the code itself.", + "Commenting is also a convenient way to make code inactive without having to delete it entirely.", + "You can start a comment with <!-- and end a comment with -->." + ], + "tests": [ + "assert($('h1').length > 0, 'Make your h1 element visible on your page by uncommenting it.')", + "assert($('h2').length > 0, 'Make your h2 element visible on your page by uncommenting it.')", + "assert($('p').length > 0, 'Make your p element visible on your page by uncommenting it.')", + "assert(!new RegExp('-->', 'gi').test(editor), 'Be sure to delete the --> that ends the comment.')" + ], + "challengeSeed": [ + "" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "Waypoint: Quitar comentarios HTML", + "descriptionEs": [ + "Quitar el comentario a los elementos h1, h2 y p.", + "Crear comentarios es una forma en la que puedes dejar mensajes dentro de tu código sin afectar el resultado.", + "Agregar comentarios es también una forma conveniente de desactivar tu código sin tener que borrarlo por completo.", + "Puedes comenzar un comentario con <!-- y terminar de comentar con -->." + ], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08804", + "name": "Waypoint: Comment out HTML", + "difficulty": 0.014, + "description": [ + "Comment out your h1 element and your p element, but leave your h2 element uncommented.", + "Remember that in order to start a comment, you need to use <!-- and to end a comment, you need to use -->.", + "Here you'll need to end the comment before your h2 element begins." + ], + "tests": [ + "assert(($('h1').length === 0), 'Comment out your h1 element so that it is not visible on your page.')", + "assert(($('h2').length > 0), 'Leave your h2 element uncommented so that is not visible on your page.')", + "assert(($('p').length === 0), 'Comment out your p element so that it is not visible on your page.')", + "assert(editor.match(/-->/g).length > 0, 'Be sure to close each of your comments with -->.')" + ], + "challengeSeed": [ + "" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "Waypoint: Comenta en HTML", + "descriptionEs": [ + "Comenta el elemento h1 y el elemento p, pero deja sin comentar el elemento h2.", + "Recuerda que para comenzar un comentario, necesitas usar <!-- y para terminar un comentario, necesitas usar -->.", + "Aquí necesitarás terminar el comentario antes que comience el elemento h2." + ], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08833", + "name": "Waypoint: Fill in the Blank with Placeholder Text", + "difficulty": 0.015, + "description": [ + "Replace the text inside your p element with the first few words of the provided \"Kitty Ipsum\" text.", + "Web developers traditionally use \"Lorem Ipsum\" text as placeholder text. It's called \"Lorem Ipsum\" text because those are the first two words of a famous passage by Cicero of Ancient Rome.", + "\"Lorem Ipsum\" text has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web.", + "Well, 5 centuries is long enough. Since we're building a CatPhotoApp, let's use something called \"Kitty Ipsum\"!", + "Here are the first few words of \"Kitty Ipsum\" text, which you can copy and paste into the right position: Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff." + ], + "tests": [ + "assert.isTrue((/Kitty(\\s)+ipsum(\\s)+dolor/gi).test($('p').text()), 'Your p element should contain the first few words of the provided \"Kitty Ipsum\" text.')" + ], + "challengeSeed": [ + "

Hello World

", + "", + "

CatPhotoApp

", + "", + "
", + "", + "

Hello Paragraph

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "Waypoint: Llena espacios con texto de relleno", + "descriptionEs": [ + "Cambia el texto en el elemento p para usar las primeras palabras del texto Kitty Ipsum.", + "Los desarrolladores web tradicionalmente usan Lorem Ipsum como texto de relleno. Se llama texto Lorem Ipsum porque esas son las primeras dos palabras de una cita famosa de Cicerón de la Roma Antigua.", + "El texto Lorem Ipsum ha sido usado como texto de relleno en las imprentas desde el siglo 16, y esta tradición continúa en la web.", + "Bueno, 5 siglos es bastante. Ya que estamos construyendo una aplicación de fotos de gatos (CatPhotoApp), ¡usemos algo llamado Kitty Ipsum!", + "Aquí están las primeras palabras del texto Kitty Ipsum, que puedes copiar y pegar en la posición correcta: Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff." + ], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fed1348bd9aedf08833", + "name": "Waypoint: Delete HTML Elements", + "difficulty": 0.016, + "description": [ + "Delete your h1 and br elements so we can simplify our view.", + "Our phone doesn't have much vertical space.", + "Let's remove the unnecessary elements so we can start building our CatPhotoApp." + ], + "tests": [ + "assert(($('h1').length == 0), 'Delete your h1 element.')", + "assert(($('h2').length > 0), 'Leave your h2 element on the page.')", + "assert(($('br').length == 0), 'Delete your br element.')", + "assert(($('p').length > 0), 'Leave your p element on the page.')" + ], + "challengeSeed": [ + "

Hello World

", + "", + "

CatPhotoApp

", + "", + "
", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "Waypoint: Borra elementos HTML", + "descriptionEs": [ + "Borra los elementos h1 y br para simplificar nuestra vista.", + "Nuestro teléfono no tiene mucho espacio para elementos HTML.", + "Removamos los elementos innecesarios para que empecemos a construir nuestra CatPhotoApp." + ], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08803", + "name": "Waypoint: Change the Color of Text", + "difficulty": 0.017, + "description": [ + "Change your h2 element's style so that its text color is red.", + "We can do this by changing the \"style\" of your h2 element.", + "The style that is responsible for the color of an element's text is the \"color\" style.", + "Here's how you would set your h2 element's text color to blue: <h2 style=\"color: blue\">CatPhotoApp</h2>." + ], + "tests": [ + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')" + ], + "challengeSeed": [ + "

CatPhotoApp

", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "Waypoint: Cambia el color del texto", + "descriptionEs": [ + "Cambia el estilo del elemento h2 de manera que el color de su texto sea rojo.", + "Podemos hacer esto por medio de cambiar el estilo del elemento h2.", + "El estilo responsable del color de texto de un elemento es el estilo \"color\".", + "Así es como podrías volver el color de texto de tu elemento h2 en azul: <h2 style=\"color: blue\">CatPhotoApp</h2>." + ], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08805", + "name": "Waypoint: Use CSS Selectors to Style Elements", + "difficulty": 0.018, + "description": [ + "Delete your h2 element's style attribute and instead create a CSS style element. Add the necessary CSS to turn all h2 elements blue.", + "With CSS, there are hundreds of CSS \"attributes\" that you can use to change the way an element looks on your page.", + "When you entered <h2 style=\"color: red\">CatPhotoApp</h2>, you were giving that individual h2 element an \"inline style\".", + "That's one way to add style to an element, but a better way is by using Cascading Style Sheets (CSS).", + "At the top of your code, create a style element like this: <style></style>.", + "Inside that style element, you can create a \"CSS selector\" for all h2 elements. For example, if you wanted all h2 elements to be red, your style element would look like this: <style>h2 {color: red;}</style>.", + "Note that it's important to have both opening and closing curly braces ({ and }) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of your element's styles." + ], + "tests": [ + "assert($('h2').css('color') === 'rgb(0, 0, 255)', 'Your h2 element should be blue.')", + "assert(!$('h2').attr('style'), 'Remove the style attribute from your h2 element.')", + "assert(($('style').length > 1), 'Create a style element.')", + "assert(editor.match(/<\\/style>/g) && editor.match(/<\\/style>/g).length === editor.match(/", + "", + "

CatPhotoApp

", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aefe08806", + "name": "Waypoint: Style Multiple Elements with a CSS Class", + "difficulty": 0.020, + "description": [ + "Apply the \"red-text\" class to your h2 and p elements.", + "Remember that you can attach classes to HTML elements by using class=\"your-class-here\" within the relevant element's opening tag.", + "Remember that CSS selectors require a period at the beginning like this: .red-text { color: blue; }, but that class declarations don't use a period, like this: <h2 class=\"blue-text\">CatPhotoApp<h2>." + ], + "tests": [ + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", + "assert($('h2').hasClass('red-text'), 'Your h2 element should have the class \"red-text\".')", + "assert($('p').css('color') === 'rgb(255, 0, 0)', 'Your p element should be red.')", + "assert($('p').hasClass('red-text'), 'Your p element should have the class \"red-text\".')" + ], + "challengeSeed": [ + "", + "", + "

CatPhotoApp

", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08806", + "name": "Waypoint: Change the Font Size of an Element", + "difficulty": 0.021, + "description": [ + "Create a second p element. Then, inside your <style> element, set the \"font-size\" of all p elements to 16 pixels.", + "Font size is controlled by the \"font-size\" CSS attribute, like this: h1 { font-size: 30px; }.", + "First, create a second p element with the following Kitty Ipsum text: Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.", + "See if you can figure out how to give both of your p elements the font-size of 16 pixels (16px). You can do this inside the same <style> tag that we created for your \"red-text\" class." + ], + "tests": [ + "assert($('p').length > 1, 'You need 2 p elements with Kitty Ipsum text.')", + "assert(editor.match(/<\\/p>/g) && editor.match(/<\\/p>/g).length === editor.match(/

p elements has a closing tag.')", + "assert.isTrue((/Purr\\s+jump\\s+eat/gi).test($('p').text()), 'Your p element should contain the first few words of the provided additional \"Kitty Ipsum\" text.')", + "assert($('p').css('font-size') === '16px', 'Give your p elements the font-size of 16px.')" + ], + "challengeSeed": [ + "", + "", + "

CatPhotoApp

", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aede08807", + "name": "Waypoint: Set the Font Family of an Element", + "difficulty": 0.022, + "description": [ + "Make all of your p elements use the \"Monospace\" font.", + "You can set an element's font by using the \"font-family\" attribute.", + "For example, if you wanted to set your h2 element's font to \"Sans-serif\", you would use the following CSS: h2 { font-family: Sans-serif; }." + ], + "tests": [ + "assert($('p').css('font-family').match(/monospace/i), 'Your p elements should use the font \"Monospace\".')" + ], + "challengeSeed": [ + "", + "", + "

CatPhotoApp

", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08807", + "name": "Waypoint: Import a Google Font", + "difficulty": 0.023, + "description": [ + "Apply the font-family of \"Lobster\" to your h2 element.", + "First, you'll need to make a \"call\" to Google to grab the \"Lobster\" font and load it into your HTML.", + "Copy the following code snippet and paste it into your code editor above your style element:", + "<link href='http://fonts.googleapis.com/css?family=Lobster' rel='stylesheet' type='text/css'>.", + "Now you can set \"Lobster\" as a font-family attribute on your h2 element." + ], + "tests": [ + "assert(new RegExp('googleapis', 'gi').test(editor), 'Import the \"Lobster\" font.')", + "assert($('h2').css('font-family').match(/lobster/i), 'Your h2 element should use the font \"Lobster\".')", + "assert($('p').css('font-family').match(/monospace/i), 'Your p element should still use the font \"Monospace\".')" + ], + "challengeSeed": [ + "", + "", + "

CatPhotoApp

", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08808", + "name": "Waypoint: Specify How Fonts Should Degrade", + "difficulty": 0.024, + "description": [ + "Make all your h2 elements use \"Lobster\" as their font family, but degrade to the \"Monospace\" font when the \"Lobster\" font isn't available.", + "You can leave \"Lobster\" your h2 element's font-family, and have it \"degrade\" to a different font when \"Lobster\" isn't available.", + "For example, if you wanted an element to use the \"Helvetica\" font, but also degrade to the \"Sans-Serif\" font when \"Helvetica\" wasn't available, you could do use this CSS style: p { font-family: Helvetica, Sans-Serif; }.", + "There are several default fonts that are available in all browsers. These include \"Monospace\", \"Serif\" and \"Sans-Serif\". See if you can set your h2 elements to use \"Lobster\" and degrade to \"Monospace\".", + "Now try commenting out your call to Google Fonts, so that the \"Lobster\" font isn't available. Notice how it degrades to the \"Monospace\" font." + ], + "tests": [ + "assert($('h2').css('font-family').match(/lobster/i), 'Your h2 element should use the font \"Lobster\".')", + "assert($('h2').css('font-family').match(/monospace/i), 'Your h2 element should degrade to the font \"Monospace\" when \"Lobster\" is not available.')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08809", + "name": "Waypoint: Override Styles with Important", + "difficulty": 0.025, + "description": [ + "Create an \"urgently-red\" class that gives an element the font-color of red, but add !important to the class to ensure the element is rendered as being red. Immediately below your \"urgently-red\" class declaration, create a \"blue-text\" class that gives an element the font-color of blue. Apply both classes to your h2 element.", + "You can add more than one class to an element by separating the class declarations with a space, like this: <h2 class='green-text giant-text'>This will be giant green text</h2>.", + "Sometimes HTML elements will receive conflicting information from CSS classes as to how they should be styled.", + "If there's a conflict in the CSS, the browser will use whichever style declaration is closest to the bottom of the CSS document (whichever declaration comes last). Note that in-line style declarations are the final authority in how an HTML element will be rendered.", + "There's one way to ensure that an element is rendered with a certain style, regardless of where that declaration is located. That one way is to use !important.", + "In case you're curious, this is the priority hierarchy for element styles: !important beats inline styles, which beats CSS class selectors, which beats CSS selector. That is, !important trumps all other styles, and inline styles trump style tag declarations.", + "Here's an example of a CSS style that uses !important: <style> .urgently-blue { color: blue !important; } </style>.", + "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, and without changing the sequence of CSS class declarations." + ], + "tests": [ + "assert(new RegExp('.blue-text', 'gi').test(editor), 'Create the CSS class \"blue-text\"')", + "assert(new RegExp('.urgently-red', 'gi').test(editor), 'Create the CSS class \"urgently-red\"')", + "assert(new RegExp('red.?!important', 'gi').test(editor), 'Add the \"!important\" declaration!')", + "assert($('h2').hasClass('blue-text'), 'Your h2 element should have the class \"blue-text\".')", + "assert($('h2').hasClass('urgently-red'), 'Your h2 element should have the class \"urgently-red\".')", + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08812", + "name": "Waypoint: Add Images to your Website", + "difficulty": 0.026, + "description": [ + "Use an img element to add the image http://bit.ly/fcc-kittens to your website.", + "You can add images to your website by using the img element, and point to an specific image's URL using the src attribute.", + "An example of this would be <img src=\"www.your-image-source.com/your-image.jpg\"/>. Note that in most cases, img elements are self-closing.", + "Try it with this image: http://bit.ly/fcc-kittens." + ], + "tests": [ + "assert($('img').length > 0, 'Your page should have an image element.')", + "assert($('img').filter(function(index) { return /http:\\/\\/bit\\.ly\\/fcc-kittens/gi.test($('img').attr('src')); }).length > 0, 'Your image should have have a src attribute that points to the kitten image.')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9acdf08812", + "name": "Waypoint: Size your Images", + "difficulty": 0.027, + "description": [ + "Create a class called smaller-image and use it to resize the image so that it's only 100 pixels wide.", + "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the image's width.", + "For example, if we wanted to create a CSS class called \"larger-image\" that gave HTML elements a width of 500 pixels, we'd use: <style> .larger-image { width: 500px; } </style>." + ], + "tests": [ + "assert($('img').hasClass('smaller-image'), 'Your img element should have the class \"smaller-image\".')", + "assert($('img').width() === 100, 'Your image should be 100 pixels wide.')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9bedf08813", + "name": "Waypoint: Add Borders Around your Elements", + "difficulty": 0.028, + "description": [ + "Create a class called \"thick-green-border\" that puts a 10-pixel-wide green border with a style of \"solid\" around an HTML element, and apply that class to your cat photo.", + "CSS borders have attributes like style, color and width.", + "For example, if we wanted to create a red, 5 pixel border around an HTML element, we could use this class: <style> .thin-red-border { border-color: red; border-width: 5px; border-style: solid; } </style>." + ], + "tests": [ + "assert($('img').hasClass('smaller-image'), 'Your img element should have the class \"smaller-image\".')", + "assert($('img').hasClass('thick-green-border'), 'Your img element should have the class \"thick-green-border\".')", + "assert($('img').hasClass('thick-green-border') && parseInt($('img').css('border-top-width')), 'Give your image a border width of 10px.')", + "assert(new RegExp('solid', 'gi').test(editor), 'Give your image a border style of \"solid\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08814", + "name": "Waypoint: Add Rounded Corners with a Border Radius", + "difficulty": 0.029, + "description": [ + "Give your cat photo a border-radius of 10 pixels.", + "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute called border-radius.", + "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." + ], + "tests": [ + "assert($('img').hasClass('thick-green-border'), 'Your image element should have the class \"thick-green-border\".')", + "assert(parseInt($('img').css('border-top-left-radius')) > 8, 'Your image should have a border radius of 10 pixels')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08815", + "name": "Waypoint: Make Circular Images with a Border Radius", + "difficulty": 0.030, + "description": [ + "Give your cat photo a border-radius of 50%.", + "In addition to pixels, you can also specify a border-radius using a percentage." + ], + "tests": [ + "assert(parseInt($('img').css('border-top-left-radius')) > 48, 'Your image should have a border radius of 50 percent, making it perfectly circular.')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08816", + "name": "Waypoint: Link to External Pages with Anchor Elements", + "difficulty": 0.031, + "description": [ + "Create an a element, or \"anchor element\", that links to http://catphotoapp.com and has \"cat photos\" as its link text, or \"anchor text\".", + "Here's a diagram of an a element. In this case, it's used in the middle of a paragraph element, which means your link will appear in the middle of your sentence.", + "a diagram of how anchor tags are composed with the same text as on the following line", + "Here's an example: <p>Here's a <a href='http://freecodecamp.com'> link to Free Code Camp</a> for you to follow.</p>." + ], + "tests": [ + "assert((/cat photos/gi).test($('a').text()), 'Your a element should have the anchor text of \"cat photos\"')", + "assert($('a').filter(function(index) { return /com/gi.test($('a').attr('href')); }).length > 0, 'You need an a element that links to http://catphotoapp.com.')", + "assert(editor.match(/<\\/a>/g) && editor.match(/<\\/a>/g).length === editor.match(/a element has a closing tag.')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aede08817", + "name": "Waypoint: Wrap an Anchor Element within a Paragraph", + "difficulty": 0.032, + "description": [ + "Now wrap your a element within a p element so that the surrounding paragraph says \"click here for cat photos\", but where only \"cat photos\" is a link - the rest is plain text.", + "Again, here's a diagram of an a element for your reference:", + "a diagram of how anchor tags are composed with the same text as on the following line", + "Here's an example: <p>Here's a <a href='http://freecodecamp.com'> link to Free Code Camp</a> for you to follow.</p>." + ], + "tests": [ + "assert($('a').attr('href').match(/catphotoapp.com/gi).length > 0, 'You need an a element that links to \"catphotoapp.com\".')", + "assert($('a').text().match(/cat\\sphotos/gi).length > 0, 'Your a element should have the anchor text of \"cat photos\"')", + "assert($('a[href=\\'http://www.catphotoapp.com\\']').parent().is('p'), 'Your a element should be wrapped within a paragraph element.')", + "assert($('p').text().match(/click\\shere\\sfor/gi), 'Your p element should have the text \"click here for\".')", + "assert(editor.match(/<\\/p>/g) && editor.match(/

/g).length === editor.match(/

p elements has a closing tag.')", + "assert(editor.match(/<\\/a>/g) && editor.match(//g).length === editor.match(/a elements has a closing tag.')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "cat photos", + "", + "", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08817", + "name": "Waypoint: Make Dead Links using the Hash Symbol", + "difficulty": 0.033, + "description": [ + "Use the hash symbol (#) to turn your a element's link into a dead link.", + "Sometimes you want to add a elements to your website before you know where they will link.", + "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", + "Replace your a element's href attribute with a hash symbol to turn it into a dead link." + ], + "tests": [ + "assert($('a').attr('href') === '#', 'Your anchor element should be a dead link with a href attribute set to \"#\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08820", + "name": "Waypoint: Turn an Image into a Link", + "difficulty": 0.034, + "description": [ + "Wrap your img element inside an a element with a dead link.", + "You can make elements into links by wrapping them within an a element.", + "Wrap your image within an a element. Here's an example: <a href='#'><img src='http://bit.ly/fcc-kittens2'/></a>.", + "Remember to use the hash symbol (#) as your a element's href property in order to turn it into a dead link.", + "Once you've done this, hover over your image with your cursor. Your cursor's normal pointer should become the link clicking pointer. The photo is now a link." + ], + "tests": [ + "assert(new RegExp('#').test($('a').children('img').parent().attr('href')), 'Your a element should be a dead link with a href attribute set to \"#\".')", + "assert($('a').children('img').length > 0, 'Wrap your image element within an a element.')", + "assert(editor.match(/<\\/a>/g) && editor.match(//g).length === editor.match(/a elements has a closing tag.')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08818", + "name": "Waypoint: Add Alt Text to an Image for Accessibility", + "difficulty": 0.035, + "description": [ + "Add an alt attribute with the text \"A cute orange cat lying on its back\" to our cat photo.", + "alt attributes, also known as \"alt text\", are what browsers will display if they fail to load the image. alt attributes are also important for blind or visually impaired users to understand what an image portrays. Search engines also look at alt attributes.", + "In short, every image should have an alt attribute!", + "alt attributes are a useful way to tell people (and web crawlers like Google) what is pictured in a photo. It's extremely important for helping blind or visually impaired people understand the content of your website.", + "You can add an alt attribute right in the img element like this: <img src=\"www.your-image-source.com/your-image.jpg\" alt=\"your alt text\"/>." + ], + "tests": [ + "assert($('img').filter(function(){ return /cat/gi.test(this.alt) }).length > 0, 'Your image element should have an alt attribute set to \"A cute orange cat lying on its back\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

CatPhotoApp

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "

Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" + ], + "challengeType": 0, + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "_id": "bad87fee1348bd9aedf08827", + "name": "Waypoint: Create a Bulleted Unordered List", + "difficulty": 0.036, + "description": [ + "Replace your p elements with an unordered list of three things that cats love.", + "HTML has a special element for creating unordered lists, or bullet point-style lists.", + "Unordered lists start with a <ul> element. Then they contain some number of <li> elements.", + "For example: <ul><li>milk</li><li>cheese</li></ul> would create a bulleted list of \"milk\" and \"cheese\"." + ], + "tests": [ + "assert($('ul').length > 0, 'Create a ul element.')", + "assert($('li').length > 2, 'Add three li elements to your ul element.')", + "assert(editor.match(/<\\/ul>/g) && editor.match(/<\\/ul>/g).length === editor.match(/