diff --git a/common/models/User-Identity.js b/common/models/User-Identity.js
index 87a7ffef57..779ad2f48f 100644
--- a/common/models/User-Identity.js
+++ b/common/models/User-Identity.js
@@ -79,7 +79,7 @@ export default function(UserIdent) {
}
// if user signed in with github refresh their info
- if (userIdent.provider === 'github-login') {
+ if (/github/.test(userIdent.provider)) {
debug("user isn't github cool or username from github is different");
setProfileFromGithub(user, profile, profile._json);
userChanged = true;
diff --git a/common/models/challenge.json b/common/models/challenge.json
index baa78a4e4c..08fa48779b 100644
--- a/common/models/challenge.json
+++ b/common/models/challenge.json
@@ -16,9 +16,21 @@
"title": {
"type": "string"
},
+ "type": {
+ "type": "string"
+ },
+ "order": {
+ "type": "number"
+ },
+ "suborder": {
+ "type": "number"
+ },
"dashedName": {
"type": "string"
},
+ "block": {
+ "type": "string"
+ },
"difficulty": {
"type": "string"
},
diff --git a/common/models/user.js b/common/models/user.js
index 81078d6df0..8f79fe6b75 100644
--- a/common/models/user.js
+++ b/common/models/user.js
@@ -51,6 +51,14 @@ module.exports = function(User) {
user.email = typeof user.email === 'string' ?
user.email.trim().toLowerCase() :
user.email;
+
+ if (!user.progressTimestamps) {
+ user.progressTimestamps = [];
+ }
+
+ if (user.progressTimestamps.length === 0) {
+ user.progressTimestamps.push({ timestamp: Date.now() });
+ }
}
next();
});
diff --git a/public/css/main.less b/public/css/main.less
index c828412661..f23a5b1c9d 100644
--- a/public/css/main.less
+++ b/public/css/main.less
@@ -617,6 +617,14 @@ thead {
border-radius: 5px;
}
+.gif-block {
+ margin-top: 30px;
+ margin-bottom: 10px;
+}
+
+.gif-caption {
+ font-size: 18px;
+}
.testimonial-copy {
font-size: 20px;
@@ -1026,6 +1034,10 @@ hr {
margin: 18px 0;
}
+.big-spacer {
+ padding: 30px 0 30px 0;
+}
+
#reply-to-main-post, #upvote {
cursor: pointer;
}
diff --git a/seed/challenge-migration.js b/seed/challenge-migration.js
index 5c8fd01590..7ef359781f 100644
--- a/seed/challenge-migration.js
+++ b/seed/challenge-migration.js
@@ -8,20 +8,6 @@ var bonfires = require('./bonfires.json'),
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) {
diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json
index c071bfb8b7..97482403fa 100644
--- a/seed/challenges/advanced-bonfires.json
+++ b/seed/challenges/advanced-bonfires.json
@@ -1,47 +1,56 @@
{
"name": "Advanced Algorithm Scripting",
- "order": 0.011,
+ "order": 0.013,
"challenges": [
{
- "id": "a2f1d72d9b908d0bd72bb9f6",
- "name": "Bonfire: Make a Person",
- "dashedName": "bonfire-make-a-person",
- "difficulty": "3.01",
+ "id": "aff0395860f5d3034dc0bfc9",
+ "title": "Validate US Telephone Numbers",
+ "difficulty": "4.01",
"description": [
- "Fill in the object constructor with the methods specified in the tests.",
- "Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).",
- "All functions that take an argument have an arity of 1, and the argument will be a string.",
- "These methods must be the only available means for interacting with the object.",
+ "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."
],
- "challengeSeed": [
- "var Person = function(firstAndLast) {",
- " return firstAndLast;",
- "};",
- "",
- "var bob = new Person('Bob Ross');",
- "bob.getFullName();"
- ],
"tests": [
- "expect(Object.keys(bob).length).to.eql(6);",
- "expect(bob instanceof Person).to.be.true;",
- "expect(bob.firstName).to.be.undefined();",
- "expect(bob.lastName).to.be.undefined();",
- "expect(bob.getFirstName()).to.eql('Bob');",
- "expect(bob.getLastName()).to.eql('Ross');",
- "expect(bob.getFullName()).to.eql('Bob Ross');",
- "bob.setFirstName('Happy');",
- "expect(bob.getFirstName()).to.eql('Happy');",
- "bob.setLastName('Trees');",
- "expect(bob.getLastName()).to.eql('Trees');",
- "bob.setFullName('George Carlin');",
- "expect(bob.getFullName()).to.eql('George Carlin');",
- "bob.setFullName('Bob Ross');"
+ "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": [
- "Closures",
- "Details of the Object Model"
+ "RegExp"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -55,34 +64,32 @@
"descriptionPt": []
},
{
- "id": "af4afb223120f7348cdfc9fd",
- "name": "Bonfire: Map the Debris",
- "dashedName": "bonfire-map-the-debris",
- "difficulty": "3.02",
+ "id": "a3f503de51cf954ede28891d",
+ "title": "Symmetric Difference",
+ "difficulty": "4.02",
"description": [
- "Return a new array that transforms the element's average altitude into their orbital periods.",
- "The array will contain objects in the format {name: 'name', avgAlt: avgAlt}
.",
- "You can read about orbital periods on wikipedia.",
- "The values should be rounded to the nearest whole number. The body being orbited is Earth.",
- "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418",
+ "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 orbitalPeriod(arr) {",
- " var GM = 398600.4418;",
- " var earthRadius = 6367.4447;",
- " return arr;",
+ "function sym(args) {",
+ " return arguments;",
"}",
"",
- "orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}]);"
+ "sym([1, 2, 3], [5, 2, 1, 4]);"
],
"tests": [
- "expect(orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputnik\", orbitalPeriod: 86400}]);",
- "expect(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])).to.eqls([{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]);"
+ "expect(sym([1, 2, 3], [5, 2, 1, 4])).to.equal([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": [
- "Math.pow()"
+ "Array.reduce()",
+ "Symmetric Difference"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -96,33 +103,192 @@
"descriptionPt": []
},
{
- "id": "a3f503de51cfab748ff001aa",
- "name": "Bonfire: Pairwise",
- "dashedName": "bonfire-pairwise",
- "difficulty": "3.03",
+ "id": "aa2e6f85cab2ab736c9a9b24",
+ "title": "Exact Change",
+ "difficulty": "4.03",
"description": [
- "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.",
- "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.",
- "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!",
+ "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 pairwise(arr, arg) {",
- " return arg;",
+ "function drawer(price, cash, cid) {",
+ " var change;",
+ " // Here is your change, ma'am.",
+ " return change;",
"}",
"",
- "pairwise([1,4,2,3,0,5], 7);"
+ "// 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(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);",
- "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);",
- "expect(pairwise([1,1,1], 2)).to.equal(1);",
- "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);",
- "expect(pairwise([], 100)).to.equal(0);"
+ "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": [
- "Array.reduce()"
+ "Global Object"
],
+ "type": "bonfire",
+ "challengeType": 5,
+ "nameCn": "",
+ "descriptionCn": [],
+ "nameFr": "",
+ "descriptionFr": [],
+ "nameRu": "",
+ "descriptionRu": [],
+ "nameEs": "",
+ "descriptionEs": [],
+ "namePt": "",
+ "descriptionPt": []
+ },
+ {
+ "id": "a56138aff60341a09ed6c480",
+ "title": "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"
+ ],
+ "type": "bonfire",
+ "challengeType": 5,
+ "nameCn": "",
+ "descriptionCn": [],
+ "nameFr": "",
+ "descriptionFr": [],
+ "nameRu": "",
+ "descriptionRu": [],
+ "nameEs": "",
+ "descriptionEs": [],
+ "namePt": "",
+ "descriptionPt": []
+ },
+ {
+ "id": "a7bf700cd123b9a54eef01d5",
+ "title": "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"
+ ],
+ "type": "bonfire",
+ "challengeType": 5,
+ "nameCn": "",
+ "descriptionCn": [],
+ "nameFr": "",
+ "descriptionFr": [],
+ "nameRu": "",
+ "descriptionRu": [],
+ "nameEs": "",
+ "descriptionEs": [],
+ "namePt": "",
+ "descriptionPt": []
+ },
+ {
+ "id": "a19f0fbe1872186acd434d5a",
+ "title": "Friendly Date Ranges",
+ "dashedName": "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'], 'two months apart can be inferred if 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'], 'one month apart can be inferred it is the same year');",
+ "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()"
+ ],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
diff --git a/seed/challenges/angularjs.json b/seed/challenges/angularjs.json
index 910a744bc7..ba6071a1fd 100644
--- a/seed/challenges/angularjs.json
+++ b/seed/challenges/angularjs.json
@@ -4,8 +4,7 @@
"challenges": [
{
"id": "bd7154d8c441eddfaeb5bdef",
- "name": "Waypoint: Get Started with Angular.js",
- "dashedName": "waypoint-get-started-with-angularjs",
+ "title": "Get Started with Angular.js",
"difficulty": 0.34,
"challengeSeed": ["114684726"],
"description": [
@@ -13,6 +12,7 @@
"In this course, we'll build a virtual shop entirely in Angular.js.",
"Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/1/section/1/video/1 and complete the section."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
@@ -28,8 +28,7 @@
},
{
"id": "bd7155d8c441eddfaeb5bdef",
- "name": "Waypoint: Apply Angular.js Directives",
- "dashedName": "waypoint-apply-angularjs-directives",
+ "title": "Apply Angular.js Directives",
"difficulty": 0.35,
"challengeSeed": ["114684727"],
"description": [
@@ -37,6 +36,7 @@
"Let's learn how these powerful directives work, and how to use them to make your web apps more dynamic",
"Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/2/section/1/video/1 and complete the section."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
@@ -52,8 +52,7 @@
},
{
"id": "bd7156d8c441eddfaeb5bdef",
- "name": "Waypoint: Power Forms with Angular.js",
- "dashedName": "waypoint-power-forms-with-angularjs",
+ "title": "Power Forms with Angular.js",
"difficulty": 0.36,
"challengeSeed": ["114684729"],
"description": [
@@ -61,6 +60,7 @@
"Learn how to create reactive Angular.js forms, including real-time form validation.",
"Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/3/section/1/video/1 and complete the section."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
@@ -76,14 +76,14 @@
},
{
"id": "bd7157d8c441eddfaeb5bdef",
- "name": "Waypoint: Customize Angular.js Directives",
- "dashedName": "waypoint-customize-angularjs-directives",
+ "title": "Customize Angular.js Directives",
"difficulty": 0.37,
"challengeSeed": ["114685062"],
"description": [
"Now we'll learn how to modify existing Angular.js directives, and even build directives of your own.",
"Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/4/section/1/video/1 and complete the section."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
@@ -99,8 +99,7 @@
},
{
"id": "bd7158d8c441eddfaeb5bdef",
- "name": "Waypoint: Create Angular.js Services",
- "dashedName": "waypoint-create-angularjs-services",
+ "title": "Create Angular.js Services",
"difficulty": 0.38,
"challengeSeed": ["114685060"],
"description": [
@@ -108,6 +107,7 @@
"We'll learn how to use services in this final Code School Angular.js challenge.",
"Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/5/section/1/video/1 and complete the section."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
diff --git a/seed/challenges/basejumps.json b/seed/challenges/basejumps.json
index 137e679eea..fcad55c0d9 100644
--- a/seed/challenges/basejumps.json
+++ b/seed/challenges/basejumps.json
@@ -4,8 +4,7 @@
"challenges": [
{
"id": "bd7158d8c443eddfaeb5bcef",
- "name": "Waypoint: Get Set for Basejumps",
- "dashedName": "waypoint-get-set-for-basejumps",
+ "title": "Get Set for Basejumps",
"difficulty": 2.00,
"challengeSeed": ["128451852"],
"description": [
@@ -60,13 +59,13 @@
"If you need further guidance on using Yeoman Angular-Fullstack Generator, check out: https://github.com/clnhll/guidetobasejumps.",
"Now you're ready to move on to your first Basejump. Click the \"I've completed this challenge\" and move on."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": []
},
{
"id": "bd7158d8c443eddfaeb5bdef",
- "name": "Basejump: Build a Voting App",
- "dashedName": "basejump-build-a-voting-app",
+ "title": "Build a Voting App",
"difficulty": 2.01,
"challengeSeed": ["133315786"],
"description": [
@@ -87,6 +86,7 @@
"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"
],
+ "type": "basejumps",
"challengeType": 4,
"tests": [],
"nameCn": "",
@@ -102,8 +102,7 @@
},
{
"id": "bd7158d8c443eddfaeb5bdff",
- "name": "Basejump: Build a Nightlife Coordination App",
- "dashedName": "basejump-build-a-nightlife-coordination-app",
+ "title": "Build a Nightlife Coordination App",
"difficulty": 2.02,
"challengeSeed": ["133315781"],
"description": [
@@ -121,6 +120,7 @@
"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"
],
+ "type": "basejumps",
"challengeType": 4,
"tests": [],
"nameCn": "",
@@ -136,8 +136,7 @@
},
{
"id": "bd7158d8c443eddfaeb5bd0e",
- "name": "Basejump: Chart the Stock Market",
- "dashedName": "basejump-chart-the-stock-market",
+ "title": "Chart the Stock Market",
"difficulty": 2.03,
"challengeSeed": ["133315787"],
"description": [
@@ -154,6 +153,7 @@
"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"
],
+ "type": "basejumps",
"challengeType": 4,
"tests": [],
"nameCn": "",
@@ -169,8 +169,7 @@
},
{
"id": "bd7158d8c443eddfaeb5bd0f",
- "name": "Basejump: Manage a Book Trading Club",
- "dashedName": "basejump-manage-a-book-trading-club",
+ "title": "Manage a Book Trading Club",
"difficulty": 2.04,
"challengeSeed": ["133316032"],
"description": [
@@ -187,6 +186,7 @@
"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"
],
+ "type": "basejumps",
"challengeType": 4,
"tests": [],
"nameCn": "",
@@ -202,8 +202,7 @@
},
{
"id": "bd7158d8c443eddfaeb5bdee",
- "name": "Basejump: Build a Pinterest Clone",
- "dashedName": "basejump-build-a-pinterest-clone",
+ "title": "Build a Pinterest Clone",
"difficulty": 2.05,
"challengeSeed": ["133315784"],
"description": [
@@ -223,6 +222,7 @@
"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"
],
+ "type": "basejumps",
"challengeType": 4,
"tests": [],
"nameCn": "",
diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json
index af9c9a3bd3..d75fc8ae0e 100644
--- a/seed/challenges/basic-bonfires.json
+++ b/seed/challenges/basic-bonfires.json
@@ -2,50 +2,9 @@
"name": "Basic Algorithm Scripting",
"order": 0.006,
"challenges": [
- {
- "id": "bd7139d8c441eddfaeb5bdef",
- "name": "Waypoint: Pair Program on Bonfires",
- "dashedName": "waypoint-pair-program-on-bonfires",
- "difficulty": 0.44,
- "challengeSeed": [
- "119657641"
- ],
- "description": [
- "Please note that the video for this challenge is a little outdated, and doesn't perfectly match these steps. We plan to record a new video soon.",
- "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 Screenhero. You can download Screenhero 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 LetsPair chatroom on Gitter 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 Screenhero.",
- "Add them as a new contact in Screenhero, then click the monitor-looking button to attempt to share your screen with them.",
- "Once the Screenhero 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 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 Screenhero 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",
- "dashedName": "bonfire-meet-bonfire",
+ "title": "Meet Bonfire",
"difficulty": "0",
"description": [
"Your goal is to fix the failing test.",
@@ -69,6 +28,7 @@
"",
"meetBonfire(\"You can do this!\");"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -83,8 +43,7 @@
},
{
"id": "a202eed8fc186c8434cb6d61",
- "name": "Bonfire: Reverse a String",
- "dashedName": "bonfire-reverse-a-string",
+ "title": "Reverse a String",
"difficulty": "1.01",
"tests": [
"expect(reverseString('hello')).to.be.a('String');",
@@ -96,7 +55,7 @@
"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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function reverseString(str) {",
@@ -111,6 +70,7 @@
"Array.reverse()",
"Array.join()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -125,8 +85,7 @@
},
{
"id": "a302f7aae1aa3152a5b413bc",
- "name": "Bonfire: Factorialize a Number",
- "dashedName": "bonfire-factorialize-a-number",
+ "title": "Factorialize a Number",
"tests": [
"expect(factorialize(5)).to.be.a(\"Number\");",
"expect(factorialize(5)).to.equal(120);",
@@ -139,7 +98,7 @@
"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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function factorialize(num) {",
@@ -151,6 +110,7 @@
"MDNlinks": [
"Arithmetic Operators"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -165,15 +125,14 @@
},
{
"id": "aaa48de84e1ecc7c742e1124",
- "name": "Bonfire: Check for Palindromes",
- "dashedName": "bonfire-check-for-palindromes",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"tests": [
"expect(palindrome(\"eye\")).to.be.a(\"boolean\");",
@@ -199,6 +158,7 @@
"String.replace()",
"String.toLowerCase()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -213,13 +173,12 @@
},
{
"id": "a26cbbe9ad8655a977e1ceb5",
- "name": "Bonfire: Find the Longest Word in a String",
- "dashedName": "bonfire-find-the-longest-word-in-a-string",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function findLongestWord(str) {",
@@ -233,12 +192,14 @@
"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);"
+ "expect(findLongestWord('What is the average airspeed velocity of an unladen swallow')).to.equal(8);",
+ "expect(findLongestWord('What if we try a super-long word such as otorhinolaryngology')).to.equal(19);"
],
"MDNlinks": [
"String.split()",
"String.length"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -253,13 +214,12 @@
},
{
"id": "ab6137d4e35944e21037b769",
- "name": "Bonfire: Title Case a Sentence",
- "dashedName": "bonfire-title-case-a-sentence",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function titleCase(str) {",
@@ -277,6 +237,7 @@
"MDNlinks": [
"String.charAt()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -291,14 +252,13 @@
},
{
"id": "a789b3483989747d63b0e427",
- "name": "Bonfire: Return Largest Numbers in Arrays",
- "dashedName": "bonfire-return-largest-numbers-in-arrays",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function largestOfFour(arr) {",
@@ -316,6 +276,7 @@
"MDNlinks": [
"Comparison Operators"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -330,12 +291,11 @@
},
{
"id": "acda2fb1324d9b0fa741e6b5",
- "name": "Bonfire: Confirm the Ending",
- "dashedName": "bonfire-confirm-the-ending",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function end(str, target) {",
@@ -356,6 +316,7 @@
"MDNlinks": [
"String.substr()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -370,12 +331,11 @@
},
{
"id": "afcc8d540bea9ea2669306b6",
- "name": "Bonfire: Repeat a string repeat a string",
- "dashedName": "bonfire-repeat-a-string-repeat-a-string",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function repeat(str, num) {",
@@ -393,6 +353,7 @@
"MDNlinks": [
"Global String Object"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -407,13 +368,12 @@
},
{
"id": "ac6993d51946422351508a41",
- "name": "Bonfire: Truncate a string",
- "dashedName": "bonfire-truncate-a-string",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function truncate(str, num) {",
@@ -432,6 +392,7 @@
"MDNlinks": [
"String.slice()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -446,12 +407,11 @@
},
{
"id": "a9bd25c716030ec90084d8a1",
- "name": "Bonfire: Chunky Monkey",
- "dashedName": "bonfire-chunky-monkey",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function chunk(arr, size) {",
@@ -470,6 +430,7 @@
"MDNlinks": [
"Array.push()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -484,12 +445,11 @@
},
{
"id": "ab31c21b530c0dafa9e241ee",
- "name": "Bonfire: Slasher Flick",
- "dashedName": "bonfire-slasher-flick",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function slasher(arr, howMany) {",
@@ -508,6 +468,7 @@
"Array.slice()",
"Array.splice()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -522,15 +483,14 @@
},
{
"id": "af2170cad53daa0770fabdea",
- "name": "Bonfire: Mutations",
- "dashedName": "bonfire-mutations",
+ "title": "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'.",
"Lastly, ['Alien', 'line'], should return true because all of the letters in 'line' are present in 'Alien'.",
- "Remember to use RSAP if you get stuck. Try to pair program. Write your own code."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function mutation(arr) {",
@@ -551,6 +511,7 @@
"MDNlinks": [
"Array.indexOf()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -565,13 +526,12 @@
},
{
"id": "adf08ec01beb4f99fc7a68f2",
- "name": "Bonfire: Falsey Bouncer",
- "dashedName": "bonfire-falsey-bouncer",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function bouncer(arr) {",
@@ -590,6 +550,7 @@
"Boolean Objects",
"Array.filter()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -604,12 +565,11 @@
},
{
"id": "a8e512fbe388ac2f9198f0fa",
- "name": "Bonfire: Where art thou",
- "dashedName": "bonfire-where-art-thou",
+ "title": "Where art thou",
"difficulty": "1.55",
"description": [
"Make a function that looks through an array (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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function where(collection, source) {",
@@ -629,6 +589,7 @@
"Object.hasOwnProperty()",
"Object.keys()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -643,12 +604,11 @@
},
{
"id": "a39963a4c10bc8b4d4f06d7e",
- "name": "Bonfire: Seek and Destroy",
- "dashedName": "bonfire-seek-and-destroy",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function destroyer(arr) {",
@@ -669,6 +629,7 @@
"Arguments object",
"Array.filter()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -683,13 +644,12 @@
},
{
"id": "a24c1a4622e3c05097f71d67",
- "name": "Bonfire: Where do I belong",
- "dashedName": "bonfire-where-do-i-belong",
+ "title": "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."
+ "Remember to use RSAP if you get stuck. Write your own code."
],
"challengeSeed": [
"function where(arr, num) {",
@@ -706,6 +666,7 @@
"expect(where([10, 20, 30, 40, 50], 35)).to.equal(3);",
"expect(where([10, 20, 30, 40, 50], 30)).to.equal(2);"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json
index b8e088adc0..0aa6f4f02f 100644
--- a/seed/challenges/basic-javascript.json
+++ b/seed/challenges/basic-javascript.json
@@ -4,8 +4,7 @@
"challenges": [
{
"id":"bd7123c9c441eddfaeb4bdef",
- "name": "Waypoint: Comment your JavaScript Code",
- "dashedName": "waypoint-comment-your-javascript-code",
+ "title": "Comment your JavaScript Code",
"difficulty":"9.98",
"description":[
"A comment is a very useful line of code that is not actually ran by the machine executing it. With this property comments are the perfect way of creating notes to yourself or anyone else who reads your code describing what the code does",
@@ -23,21 +22,20 @@
"assert(editor.getValue().match(/(\\/\\/)...../g), 'Make sure that there is at least one \\/\\/ style comment with at least five letters in it');"
],
"challengeSeed":[
-
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7123c9c441eddfaeb5bdef",
- "name": "Waypoint: Understand Boolean Values",
- "dashedName": "waypoint-understand-boolean-values",
+ "title": "Understand Boolean Values",
"difficulty": "9.98001",
"description": [
"Return true",
"A boolean is a type of variable that represents either true or false (Named after the British mathematician George Boole).",
"Booleans are often the result of a function or a comparative operation, for example 1==1
is true whereas 1==2
is false.",
"They are most commonly found inside if
statements which we shall cover later",
- "For now Let's modify our welcomeToBooleans
function so that it will return true
instead of false
when the run button is clicked"
+ "For now let's modify our welcomeToBooleans
function so that it will return true
instead of false
when the run button is clicked"
],
"tests": [
"assert(typeof(welcomeToBooleans())=='boolean', 'The value returned by welcomeToBooleans() should be a boolean value. (true of false)');",
@@ -51,18 +49,18 @@
"",
"welcomeToBooleans();"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7123c9c443eddfaeb5bdef",
- "name": "Waypoint: Declare JavaScript Variables",
- "dashedName": "waypoint-declare-javascript-variables",
+ "title": "Declare JavaScript Variables",
"difficulty": "9.9801",
"description": [
"Now, use the var
keyword to create a variable
called myName
. Set its value to your name.",
"Variables
are used to store values.",
- "The name variable comes from the fact that it's value, varies!",
- "Now Let's create our first variable called myName and because it's a name let's make it a string!",
+ "The name variable comes from the fact that its value varies!",
+ "Now let's create our first variable called myName and because it's a name let's make it a string!",
"Be sure to use lowercase and uppercase letters properly. JavaScript variables are written in camel case
. An example of camel case is: camelCase.",
"Look at the ourName
example if you get stuck."
],
@@ -78,12 +76,12 @@
"",
"if(typeof(myName) !== 'undefined'){(function(v){return(v);})(myName);}"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7123c9c444eddfaeb5bdef",
- "name": "Waypoint: Declare String Variables",
- "dashedName": "waypoint-declare-string-variables",
+ "title": "Declare String Variables",
"difficulty": "9.9802",
"description": [
"Programs will almost always have several different variables that are used to keep track of several different pieces of data",
@@ -105,12 +103,12 @@
"// We'll learn about functions soon.",
"if(typeof(myFirstName) !== 'undefined' && typeof(myLastName) !== 'undefined'){(function(y,z){return(y + ', ' + z);})(myFirstName, myLastName);}"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7123c9c448eddfaeb5bdef",
- "name": "Waypoint: Check the Length Property of a String Variable",
- "dashedName": "waypoint-check-the-length-property-of-a-string-variable",
+ "title": "Check the Length Property of a String Variable",
"difficulty": "9.9809",
"description": [
"Use the .length
property to count the number of characters in the lastNameLength
variable.",
@@ -138,12 +136,12 @@
"// We'll learn about functions soon.",
"if(typeof(lastNameLength) != 'undefined'){(function(v){return(v);})(lastNameLength);}"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7123c9c549eddfaeb5bdef",
- "name": "Waypoint: Use Bracket Notation to Find the First Character in a String",
- "dashedName": "waypoint-use-bracket-notation-to-find-the-first-character-in-a-string",
+ "title": "Use Bracket Notation to Find the First Character in a String",
"difficulty": "9.9810",
"description": [
"Use bracket notation
to find the first character in a the firstLetterOfLastName
variable.",
@@ -173,12 +171,12 @@
"// We'll learn about functions soon.",
"(function(v){return(v);})(firstLetterOfLastName);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7123c9c450eddfaeb5bdef",
- "name": "Waypoint: Use Bracket Notation to Find the Nth Character in a String",
- "dashedName": "waypoint-use-bracket-notation-to-find-the-nth-character-in-a-string",
+ "title": "Use Bracket Notation to Find the Nth Character in a String",
"difficulty": "9.9811",
"description": [
"Just like the last lesson where we used Bracket Notation
to access the first letter we can use the same method to get the letters ar other positions",
@@ -204,12 +202,12 @@
"// We'll learn about functions soon.",
"(function(v){return(v);})(thirdLetterOfLastName);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7123c9c451eddfaeb5bdef",
- "name": "Waypoint: Use Bracket Notation to Find the Last Character in a String",
- "dashedName": "waypoint-use-bracket-notation-to-find-the-last-character-in-a-string",
+ "title": "Use Bracket Notation to Find the Last Character in a String",
"difficulty": "9.9812",
"description": [
"Use bracket notation
to find the last character in the lastName
variable.",
@@ -234,12 +232,12 @@
"",
"(function(v){return(v);})(lastLetterOfLastName);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7123c9c452eddfaeb5bdef",
- "name": "Waypoint: Use Bracket Notation to Find the Nth-to-Last Character in a String",
- "dashedName": "waypoint-use-bracket-notation-to-find-the-nth-to-last-character-in-a-string",
+ "title": "Use Bracket Notation to Find the Nth-to-Last Character in a String",
"difficulty": "9.9813",
"description": [
"Use bracket notation
to find the second-to-last character in the lastName
variable.",
@@ -264,17 +262,17 @@
"",
"(function(v){return(v);})(secondToLastLetterOfLastName);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "cf1111c1c11feddfaeb3bdef",
- "name": "Waypoint: Add Two Numbers with JavaScript",
- "dashedName": "waypoint-add-two-numbers-with-javascript",
+ "title": "Add Two Numbers with JavaScript",
"difficulty": "9.98141",
"description": [
- "In JavaScript whole numbers (called integers) can be easily used to preform mathematical functions",
- "Let's try a few of the most commonly used ones now",
- "We use +
for addition",
+ "In JavaScript whole numbers (called integers) can be easily used to perform mathematical functions.",
+ "Let's try a few of the most commonly used ones now.",
+ "We use +
for addition.",
"Replace the 0
with correct number to achieve the result in the comment."
],
"tests": [
@@ -287,17 +285,17 @@
"",
"(function(z){return('add='+z);})(add);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "cf1111c1c11feddfaeb4bdef",
- "name": "Waypoint: Subtract One Number from Another with JavaScript",
- "dashedName": "waypoint-subtract-one-number-from-another-with-javascript",
+ "title": "Subtract One Number from Another with JavaScript",
"difficulty": "9.98142",
"description": [
- "In JavaScript whole numbers (called integers) can be easily used to preform mathematical functions",
- "Let's try a few of the most commonly used ones now",
- "We use -
for subtraction",
+ "In JavaScript whole numbers (called integers) can be easily used to perform mathematical functions.",
+ "Let's try a few of the most commonly used ones now.",
+ "We use -
for subtraction.",
"Replace the 0
with correct number to achieve the result in the comment."
],
"tests": [
@@ -310,17 +308,17 @@
"",
"(function(z){return('subtract='+z);})(subtract);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "cf1231c1c11feddfaeb5bdef",
- "name": "Waypoint: Multiply Two Numbers with JavaScript",
- "dashedName": "waypoint-multiply-two-numbers-with-javascript",
+ "title": "Multiply Two Numbers with JavaScript",
"difficulty": "9.98143",
"description": [
- "In JavaScript whole numbers (called integers) can be easily used to preform mathematical functions",
- "Let's try a few of the most commonly used ones now",
- "We use *
for multiplication",
+ "In JavaScript whole numbers (called integers) can be easily used to perform mathematical functions.",
+ "Let's try a few of the most commonly used ones now.",
+ "We use *
for multiplication.",
"Replace the 0
with correct number to achieve the result in the comment."
],
"tests": [
@@ -333,17 +331,17 @@
"",
"(function(z){return('multiply='+z);})(multiply);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "cf1111c1c11feddfaeb6bdef",
- "name": "Waypoint: Divide One Number by Another with JavaScript",
- "dashedName": "waypoint-divide-one-number-by-another-with-javascript",
+ "title": "Divide One Number by Another with JavaScript",
"difficulty": "9.9814",
"description": [
- "In JavaScript whole numbers (called integers) can be easily used to preform mathematical functions",
- "Let's try a few of the most commonly used ones now",
- "We use /
for division",
+ "In JavaScript whole numbers (called integers) can be easily used to perform mathematical functions.",
+ "Let's try a few of the most commonly used ones now.",
+ "We use /
for division.",
"Replace the 0
with correct number to achieve the result in the comment."
],
"tests": [
@@ -356,15 +354,15 @@
"",
"(function(z){return('divide='+z);})(divide);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "cf1391c1c11feddfaeb4bdef",
- "name": "Waypoint: Create Decimal Numbers with JavaScript",
- "dashedName": "waypoint-create-decimal-numbers-with-javascript",
+ "title": "Create Decimal Numbers with JavaScript",
"difficulty": "9.9815",
"description": [
- "in JavaScript we can can work with decimal numbers",
+ "In JavaScript we can work with decimal numbers.",
"Let's create a variable myDecimal
and give it a decimal value."
],
"tests": [
@@ -379,15 +377,15 @@
"",
"(function(){if(typeof(myDecimal) != 'undefined'){return(myDecimal);}})();"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7993c9c69feddfaeb7bdef",
- "name": "Waypoint: Perform Arithmetic Operations on Decimals with JavaScript",
- "dashedName": "waypoint-perform-arithmetic-operations-on-decimals-with-javascript",
+ "title": "Perform Arithmetic Operations on Decimals with JavaScript",
"difficulty": "9.98151",
"description": [
- "In JavaScript we can can work with decimal numbers."
+ "In JavaScript we can work with decimal numbers."
],
"tests": [
"assert(multiply == 15, 'The result of multiply should be 3.75');",
@@ -401,12 +399,12 @@
"",
"(function(y,z){return('multiply='+y+', divide='+z);})(multiply,divide);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bd7993c9c69feddfaeb8bdef",
- "name": "Waypoint: Store Multiple Values in one Variable using JavaScript Arrays",
- "dashedName": "waypoint-store-multiple-values-in-one-variable-using-javascript-arrays",
+ "title": "Store Multiple Values in one Variable using JavaScript Arrays",
"difficulty": "9.9816",
"description": [
"In JavaScript we can store lists or collections of data in what are called arrays",
@@ -428,12 +426,12 @@
"",
"(function(z){return(z);})(myArray);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c11feddfaeb7bdef",
- "name": "Waypoint: Nest one Array within Another Array",
- "dashedName": "waypoint-nest-one-array-within-another-array",
+ "title": "Nest one Array within Another Array",
"difficulty":"9.98161",
"description":[
"We are also able to create arrays within arrays. This technique is called nesting
.",
@@ -448,12 +446,12 @@
"",
"if(typeof(myArray) !== 'undefined'){(function(){return(myArray);})();}"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"bg9997c9c79feddfaeb9bdef",
- "name": "Waypoint: Access Array Data with Indexes",
- "dashedName": "waypoint-access-array-data-with-indexes",
+ "title": "Access Array Data with Indexes",
"difficulty":"9.9817",
"description":[
"Once an array has been created we can access the data we have stored in them using indexes",
@@ -479,12 +477,12 @@
"",
"if(typeof(myArray) != 'undefined' && typeof(data) != 'undefined'){(function(y,z){return('myArray = ' + JSON.stringify(y) + ', data = ' + JSON.stringify(z));})(myArray, data);}"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c11feddfaeb8bdef",
- "name": "Waypoint: Modify Array Data With Indexes",
- "dashedName": "waypoint-modify-array-data-with-indexes",
+ "title": "Modify Array Data With Indexes",
"difficulty":"9.98171",
"description":[
"We are able to modify the data stored in an array by using indexes",
@@ -511,12 +509,12 @@
"",
"if(typeof(myArray) != 'undefined'){(function(){return(myArray);})();}"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bg9994c9c69feddfaeb9bdef",
- "name": "Waypoint: Manipulate Arrays With pop()",
- "dashedName": "waypoint-manipulate-arrays-with-pop",
+ "title": "Manipulate Arrays With pop()",
"difficulty": "9.9818",
"description": [
"When an array has been defined we still have the ability to make changes to it afterwards",
@@ -542,12 +540,12 @@
"",
"(function(y, z){return('myArray = ' + JSON.stringify(y) + ' & removed = ' + JSON.stringify(z));})(myArray, removed);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bg9995c9c69feddfaeb9bdef",
- "name": "Waypoint: Manipulate Arrays With push()",
- "dashedName": "waypoint-manipulate-arrays-with-push",
+ "title": "Manipulate Arrays With push()",
"difficulty": "9.9818",
"description": [
"Now that we've learned how to pop
things from the end of the array, we need to learn how to push
stuff back to the end",
@@ -564,12 +562,12 @@
"",
"(function(z){return('myArray = ' + JSON.stringify(z));})(myArray);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bg9996c9c69feddfaeb9bdef",
- "name": "Waypoint: Manipulate Arrays With shift()",
- "dashedName": "waypoint-manipulate-arrays-with-shift",
+ "title": "Manipulate Arrays With shift()",
"difficulty": "9.9817",
"description": [
"Another common way in which we can manipulate the data in an array is through .shift()
",
@@ -587,12 +585,12 @@
"",
"(function(y, z){return('myArray = ' + JSON.stringify(y) + ' & removed = ' + JSON.stringify(z));})(myArray, removed);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id": "bg9997c9c69feddfaeb9bdef",
- "name": "Waypoint: Manipulate Arrays With unshift()",
- "dashedName": "waypoint-manipulate-arrays-with-unshift",
+ "title": "Manipulate Arrays With unshift()",
"difficulty": "9.9818",
"description": [
"Now that we've learned how to shift
things from the start of the array, we need to learn how to unshift
stuff back to the start",
@@ -609,12 +607,12 @@
"",
"(function(y, z){return('myArray = ' + JSON.stringify(y));})(myArray);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"bg9997c9c89feddfaeb9bdef",
- "name": "Waypoint: Write Reusable JavaScript with Functions",
- "dashedName": "waypoint-write-reusable-javascript-with-functions",
+ "title": "Write Reusable JavaScript with Functions",
"difficulty":"9.9819",
"description":[
"In JavaScript we can divide up our code into separate and reusable parts called functions",
@@ -646,12 +644,12 @@
"(function(){return(f);})();",
"}"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"bg9998c9c99feddfaeb9bdef",
- "name": "Waypoint: Build JavaScript Objects",
- "dashedName": "waypoint-build-javascript-objects",
+ "title": "Build JavaScript Objects",
"difficulty":"9.9822",
"description":[
"A very important data type in javascript is the Object
",
@@ -667,7 +665,6 @@
"",
"Objects are useful for storing data in a structured way or in a way that represents a real world object like a cat.",
"Let's try to make an Object that represents a dog called myDog!"
-
],
"tests":[
"assert((function(z){if(z.hasOwnProperty('name') && z.name != undefined && typeof(z.name) == 'string'){return(true);}else{return(false);}})(myDog), 'myDog should contain the property name and it should be a string');",
@@ -692,12 +689,12 @@
"",
"(function(z){return(z);})(myDog);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"bg9999c9c99feddfaeb9bdef",
- "name": "Waypoint: Manipulate JavaScript Objects",
- "dashedName": "waypoint-manipulate-javascript-objects",
+ "title": "Manipulate JavaScript Objects",
"difficulty":"9.9823",
"description":[
"Now that we have an objects we need to know how to add and remove properties from it",
@@ -737,12 +734,12 @@
"",
"(function(z){return(z);})(myDog);"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c11feddfaeb5bdef",
- "name": "Waypoint: Iterate with JavaScript For Loops",
- "dashedName": "waypoint-iterate-with-javascript-for-loops",
+ "title": "Iterate with JavaScript For Loops",
"difficulty":"9.9824",
"description":[
"Loops are a critical part of any program! The next few challenges",
@@ -766,12 +763,12 @@
"",
""
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c11feddfaeb1bdef",
- "name": "Waypoint: Iterate with JavaScript While Loops",
- "dashedName": "waypoint-iterate-with-javascript-while-loops",
+ "title": "Iterate with JavaScript While Loops",
"difficulty":"9.9825",
"description":[
"Loops are a critical part of any program! The next few challenges",
@@ -796,12 +793,12 @@
"",
""
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c11feddfaeb2bdef",
- "name": "Waypoint: Iterate with JavaScript Do-While Loops",
- "dashedName": "waypoint-iterate-with-javascript-do-while-loops",
+ "title": "Iterate with JavaScript Do-While Loops",
"difficulty":"9.9826",
"description":[
"Let's now take a look at the do - while loop",
@@ -826,12 +823,12 @@
"",
""
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c11feddfaeb9bdef",
- "name": "Waypoint: Generate Random Fractions with JavaScript",
- "dashedName": "waypoint-generate-random-fractions-with-javascript",
+ "title": "Generate Random Fractions with JavaScript",
"difficulty":"9.9827",
"description":[
"Random numbers are very useful for creating random behaviours and games",
@@ -852,12 +849,12 @@
"",
"(function(){return(myFunction());})();"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c12feddfaeb1bdef",
- "name": "Waypoint: Generate Random Whole Numbers with JavaScript",
- "dashedName": "waypoint-generate-random-whole-numbers-with-javascript",
+ "title": "Generate Random Whole Numbers with JavaScript",
"difficulty":"9.9828",
"description":[
"While it's great that we can create random decimal numbers it's a lot more useful to generate a random whole number",
@@ -881,12 +878,12 @@
"",
"(function(){return(myFunction());})();"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c12feddfaeb2bdef",
- "name": "Waypoint: Generate Random Whole Numbers within a Range",
- "dashedName": "waypoint-generate-random-whole-numbers-within-a-range",
+ "title": "Generate Random Whole Numbers within a Range",
"difficulty":"9.9829",
"description":[
"We can use a certain mathematical expression to get a random number between between twp numbers.",
@@ -909,12 +906,12 @@
"",
"(function(){return(myFunction());})();"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c12feddfaeb3bdef",
- "name": "Waypoint: Use Conditional Logic with If-Else Statements",
- "dashedName": "waypoint-use-conditional-logic-with-if-else-statements",
+ "title": "Use Conditional Logic with If-Else Statements",
"difficulty":"9.983",
"description":[
"We can use if statements in JavaScript to only execute code if a certain condition is met",
@@ -943,12 +940,12 @@
"",
"(function(){return(myFunction());})();"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c12feddfaeb6bdef",
- "name": "Waypoint: Sift through Text with Regular Expressions",
- "dashedName": "waypoint-sift-through-text-with-regular-expressions",
+ "title": "Sift through Text with Regular Expressions",
"difficulty":"9.984",
"description":[
"RegEx is a powerful tool we can use to find certain words or patterns in strings",
@@ -979,12 +976,12 @@
" return(testString.match(expression).length);",
"})();(function(){return(test);})();"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c12feddfaeb7bdef",
- "name": "Waypoint: Find Numbers with Regular Expressions",
- "dashedName": "waypoint-find-numbers-with-regular-expressions",
+ "title": "Find Numbers with Regular Expressions",
"difficulty":"9.985",
"description":[
"We can use special selectors in RegEx to select a particular type of value",
@@ -1009,12 +1006,12 @@
" return(testString.match(expression).length);",
"})();(function(){return(test);})();"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c12feddfaeb8bdef",
- "name": "Waypoint: Find White Space with Regular Expressions",
- "dashedName": "waypoint-find-white-space-with-regular-expressions",
+ "title": "Find White Space with Regular Expressions",
"difficulty":"9.986",
"description":[
"We can also use selectors like \\s
to find spaces in a string",
@@ -1038,12 +1035,12 @@
" return(testString.match(expression).length);",
"})();(function(){return(test);})();"
],
+ "type": "waypoint",
"challengeType": 1
},
{
"id":"cf1111c1c13feddfaeb3bdef",
- "name": "Waypoint: Invert Regular Expression Matches with JavaScript",
- "dashedName": "waypoint-invert-regular-expression-matches-with-javaScript",
+ "title": "Invert Regular Expression Matches with JavaScript",
"difficulty":"9.987",
"description":[
"Use /\\S/gi;
to match everything that isn't a space in the string",
@@ -1066,25 +1063,25 @@
" return(testString.match(expression).length);",
"})();(function(){return(test);})();"
],
+ "type": "waypoint",
"challengeType":1
},
{
"id":"cf1111c1c12feddfaeb9bdef",
- "name": "Waypoint: Create a JavaScript Slot Machine",
- "dashedName": "waypoint-create-a-javascript-slot-machine",
+ "title": "Create a JavaScript Slot Machine",
"difficulty":"9.988",
"description":[
- "We are now going to try and combine some of the stuff we've just learnt abd create the logic for a slot machine game",
+ "We are now going to try and combine some of the stuff we've just learned and create the logic for a slot machine game",
"For this we will need to generate three random numbers between 1
and 5
to represent the possible values of each individual slot",
"Store the three random numbers in slotOne
, slotTwo
and slotThree
",
"Generate the random numbers by using the system we used earlier in /challenges/random-whole-numbers-in-a-range",
"Math.floor(Math.random() * (5 - 1 + 1)) + 1;
"
],
"tests":[
- "assert(typeof(runSlots($('.slot'))[0]) == 'number', 'SlotOne should be a random number');",
- "assert(typeof(runSlots($('.slot'))[1]) == 'number', 'SlotTwo should be a random number');",
- "assert(typeof(runSlots($('.slot'))[2]) == 'number', 'SlotThree should be a random number');",
- "assert((function(){if(editor.match(/Math.floor\\(Math\\.random\\(\\)\\s\\*\\s\\(5\\s\\-\\s1\\s\\+\\s1\\)\\)\\s\\+\\s1;/gi) !== null){return(editor.match(/Math.floor\\(Math\\.random\\(\\)\\s\\*\\s\\(5\\s\\-\\s1\\s\\+\\s1\\)\\)\\s\\+\\s1;/gi).length >= 3);}else{return(false);}})(), 'You should have used Math.floor(Math.random() * (5 - 1 + 1)) + 1; three times to generate your random numbers');"
+ "assert(typeof(runSlots($('.slot'))[0]) == 'number', 'slotOne should be a random number');",
+ "assert(typeof(runSlots($('.slot'))[1]) == 'number', 'slotTwo should be a random number');",
+ "assert(typeof(runSlots($('.slot'))[2]) == 'number', 'slotThree should be a random number');",
+ "assert((function(){if(editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?5\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi) !== null){return(editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?5\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi).length >= 3);}else{return(false);}})(), 'You should have used Math.floor(Math.random() * (5 - 1 + 1)) + 1; three times to generate your random numbers');"
],
"challengeSeed":[
"fccss",
@@ -1220,12 +1217,12 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0
},
{
"id":"cf1111c1c13feddfaeb1bdef",
- "name": "Waypoint: Add your JavaScript Slot Machine Slots",
- "dashedName": "waypoint-add-your-javascript-slot-machine-slots",
+ "title": "Add your JavaScript Slot Machine Slots",
"difficulty":"9.989",
"description":[
"Now that we have our random numbers we need to go and check for when they are all the same that means we should count it as a win",
@@ -1379,12 +1376,12 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0
},
{
"id":"cf1111c1c13feddfaeb2bdef",
- "name": "Waypoint: Bring your JavaScript Slot Machine to Life",
- "dashedName": "waypoint-bring-your-javascript-slot-machine-to-life",
+ "title": "Bring your JavaScript Slot Machine to Life",
"difficulty":"9.990",
"description":[
"Now we can detect a win let's get the slot machine to look like it works",
@@ -1546,6 +1543,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0
}
]
diff --git a/seed/challenges/basic-ziplines.json b/seed/challenges/basic-ziplines.json
index e6418a32dc..b96619bb78 100644
--- a/seed/challenges/basic-ziplines.json
+++ b/seed/challenges/basic-ziplines.json
@@ -4,8 +4,7 @@
"challenges": [
{
"id": "bd7158d8c442eddfbeb5bd1f",
- "name": "Waypoint: Get Set for Ziplines",
- "dashedName": "waypoint-get-set-for-ziplines",
+ "title": "Get Set for Ziplines",
"difficulty": 1.00,
"challengeSeed": ["125658022"],
"description": [
@@ -24,6 +23,7 @@
"You can use this CodePen that you've just created as a starting point for your Ziplines. Just click the \"fork\" button at the top of your CodePen and it will create a duplicate CodePen.",
"Now you're ready for your first Zipline. Click the \"I've completed this challenge\" button."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
@@ -39,8 +39,7 @@
},
{
"id": "bd7158d8c242eddfaeb5bd13",
- "name": "Zipline: Build a Personal Portfolio Webpage",
- "dashedName": "zipline-build-a-personal-portfolio-webpage",
+ "title": "Build a Personal Portfolio Webpage",
"difficulty": 1.01,
"challengeSeed": ["133315782"],
"description": [
@@ -60,6 +59,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
@@ -75,8 +75,7 @@
},
{
"id": "bd7158d8c442eddfaeb5bd13",
- "name": "Zipline: Build a Random Quote Machine",
- "dashedName": "zipline-build-a-random-quote-machine",
+ "title": "Build a Random Quote Machine",
"difficulty": 1.02,
"challengeSeed": ["126415122"],
"description": [
@@ -92,6 +91,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
@@ -107,8 +107,7 @@
},
{
"id": "bd7158d8c442eddfaeb5bd10",
- "name": "Zipline: Show the Local Weather",
- "dashedName": "zipline-show-the-local-weather",
+ "title": "Show the Local Weather",
"difficulty": 1.03,
"challengeSeed": ["126415127"],
"description": [
@@ -125,6 +124,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
@@ -140,8 +140,7 @@
},
{
"id": "bd7158d8c442eddfaeb5bd0f",
- "name": "Zipline: Build a Pomodoro Clock",
- "dashedName": "zipline-build-a-pomodoro-clock",
+ "title": "Build a Pomodoro Clock",
"difficulty": 1.04,
"challengeSeed": ["126411567"],
"description": [
@@ -157,6 +156,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
@@ -172,8 +172,7 @@
},
{
"id": "bd7158d8c442eddfaeb5bd1f",
- "name": "Zipline: Use the Twitch.tv JSON API",
- "dashedName": "zipline-use-the-twitchtv-json-api",
+ "title": "Use the Twitch.tv JSON API",
"difficulty": 1.05,
"challengeSeed": ["126411564"],
"description": [
@@ -193,6 +192,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json
index 800f64d113..e9dad43350 100644
--- a/seed/challenges/bootstrap.json
+++ b/seed/challenges/bootstrap.json
@@ -4,8 +4,7 @@
"challenges": [
{
"id": "bad87fee1348bd9acde08712",
- "name": "Waypoint: Use Responsive Design with Bootstrap Fluid Containers",
- "dashedName": "waypoint-use-responsive-design-with-bootstrap-fluid-containers",
+ "title": "Use Responsive Design with Bootstrap Fluid Containers",
"difficulty": 2.01,
"description": [
"Now let's go back to our Cat Photo App. This time, we'll style it using the popular Bootstrap responsive CSS framework.",
@@ -15,7 +14,7 @@
"To get started, we should nest all of our HTML in a div
element with the class \"container-fluid\"."
],
"tests": [
- "assert($('div').hasClass('container-fluid'), 'Your div
element should have the class \"row\"')",
+ "assert($('div').hasClass('container-fluid'), 'Your div
element should have the class \"container-fluid\"')",
"assert(editor.match(/<\\/div>/g) && editor.match(/
src
attribute of \"http://bit.ly/fcc-kittens2\".",
@@ -159,6 +158,7 @@
" ",
"text-center
to our h1
and h2
elements.",
@@ -242,6 +241,7 @@
" ",
"button
elements, which look much better than the plain HTML ones.",
@@ -327,6 +326,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -341,8 +341,7 @@
},
{
"id": "bad87fee1348cd8acef08812",
- "name": "Waypoint: Create a Block Element Bootstrap Button",
- "dashedName": "waypoint-create-a-block-element-bootstrap-button",
+ "title": "Create a Block Element Bootstrap Button",
"difficulty": 2.05,
"description": [
"Normally, your button
elements are only as wide as the text that they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.",
@@ -416,6 +415,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -430,8 +430,7 @@
},
{
"id": "bad87fee1348cd8acef08811",
- "name": "Waypoint: Taste the Bootstrap Button Color Rainbow",
- "dashedName": "waypoint-taste-the-bootstrap-button-color-rainbow",
+ "title": "Taste the Bootstrap Button Color Rainbow",
"difficulty": 2.06,
"description": [
"The \"btn-primary\" class is the main color you'll use in your app. It is useful for highlighting actions you want your user to take.",
@@ -503,6 +502,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -517,8 +517,7 @@
},
{
"id": "bad87fee1348cd8acef08813",
- "name": "Waypoint: Call out Optional Actions with Button Info",
- "dashedName": "waypoint-call-out-optional-actions-with-button-info",
+ "title": "Call out Optional Actions with Button Info",
"difficulty": 2.07,
"description": [
"Bootstrap comes with several pre-defined colors for buttons. The \"btn-info\" class is used to call attention to optional actions that the user can take.",
@@ -591,6 +590,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -605,8 +605,7 @@
},
{
"id": "bad87fee1348ce8acef08814",
- "name": "Waypoint: Warn your Users of a Dangerous Action",
- "dashedName": "waypoint-warn-your-users-of-a-dangerous-action",
+ "title": "Warn your Users of a Dangerous Action",
"difficulty": 2.08,
"description": [
"Bootstrap comes with several pre-defined colors for buttons. The \"btn-danger\" class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.",
@@ -680,6 +679,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -694,8 +694,7 @@
},
{
"id": "bad88fee1348ce8acef08815",
- "name": "Waypoint: Use the Bootstrap Grid to Put Elements Side By Side",
- "dashedName": "waypoint-use-the-bootstrap-grid-to-put-elements-side-by-side",
+ "title": "Use the Bootstrap Grid to Put Elements Side By Side",
"difficulty": 2.09,
"description": [
"Bootstrap uses a responsive grid system, which makes it easy to put elements into rows and specify each element's relative width. Most of Bootstrap's classes can be applied to a div
element.",
@@ -774,6 +773,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -788,8 +788,7 @@
},
{
"id": "bad87fee1348bd9aedf08845",
- "name": "Waypoint: Ditch Custom CSS for Bootstrap",
- "dashedName": "waypoint-ditch-custom-css-for-bootstrap",
+ "title": "Ditch Custom CSS for Bootstrap",
"difficulty": 2.10,
"description": [
"We can clean up our code and make our Cat Photo App look more conventional by using Bootstrap's built-in styles instead of the custom styles we created earlier.",
@@ -873,6 +872,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -887,8 +887,7 @@
},
{
"id": "bad87fee1348bd9aede08845",
- "name": "Waypoint: Create a Custom Heading",
- "dashedName": "waypoint-create-a-custom-heading",
+ "title": "Create a Custom Heading",
"difficulty": 2.11,
"description": [
"We will make a simple heading for our Cat Photo App by putting them in the same row.",
@@ -962,6 +961,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -976,8 +976,7 @@
},
{
"id": "bad87fee1348bd9aedd08845",
- "name": "Waypoint: Add Font Awesome Icons to our Buttons",
- "dashedName": "waypoint-add-font-awesome-icons-to-our-buttons",
+ "title": "Add Font Awesome Icons to our Buttons",
"difficulty": 2.12,
"description": [
"Font Awesome is a convenient library of icons. These icons are vector graphics, stored in the \".svg\" file format. These icons are treated just like fonts. You can specify their size using pixels, and they will assume the font size of their parent HTML elements.",
@@ -1047,6 +1046,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1061,8 +1061,7 @@
},
{
"id": "bad87fee1348bd9aedc08845",
- "name": "Waypoint: Add Font Awesome Icons to all of our Buttons",
- "dashedName": "waypoint-add-font-awesome-icons-to-all-of-our-Buttons",
+ "title": "Add Font Awesome Icons to all of our Buttons",
"difficulty": 2.13,
"description": [
"Font Awesome is a convenient library of icons. These icons are vector graphics, stored in the \".svg\" file format. These icons are treated just like fonts. You can specify their size using pixels, and they will assume the font size of their parent HTML elements.",
@@ -1132,6 +1131,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1146,8 +1146,7 @@
},
{
"id": "bad87fee1348bd9aedb08845",
- "name": "Waypoint: Responsively Style Radio Buttons",
- "dashedName": "waypoint-responsively-style-radio-buttons",
+ "title": "Responsively Style Radio Buttons",
"difficulty": 2.14,
"description": [
"You can use Bootstrap's \"col-xs-*\" classes on form
elements, too! This way, our radio buttons will be evenly spread out across the page, regardless of how wide the screen resolution is.",
@@ -1217,6 +1216,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1231,8 +1231,7 @@
},
{
"id": "bad87fee1348bd9aeda08845",
- "name": "Waypoint: Responsively Style Checkboxes",
- "dashedName": "waypoint-responsively-style-checkboxes",
+ "title": "Responsively Style Checkboxes",
"difficulty": 2.15,
"description": [
"You can use Bootstrap's \"col-xs-*\" classes on form
elements, too! This way, our checkboxes will be evenly spread out across the page, regardless of how wide the screen resolution is.",
@@ -1309,6 +1308,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1323,8 +1323,7 @@
},
{
"id": "bad87fee1348bd9aed908845",
- "name": "Waypoint: Style Text Inputs as Form Controls",
- "dashedName": "waypoint-style-text-inputs-as-form-controls",
+ "title": "Style Text Inputs as Form Controls",
"difficulty": 2.16,
"description": [
"You can add the \"fa-paper-plane\" Font Awesome icon by adding <i class=\"fa fa-paper-plane\"></i>
within your submit button
element.",
@@ -1410,6 +1409,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1424,8 +1424,7 @@
},
{
"id": "bad87fee1348bd9aec908845",
- "name": "Waypoint: Line up Form Elements Responsively with Bootstrap",
- "dashedName": "waypoint-line-up-form-elements-responsively-with-bootstrap",
+ "title": "Line up Form Elements Responsively with Bootstrap",
"difficulty": 2.17,
"description": [
"Now let's get your form input
and your submission button
on the same line. We'll do this the same way we have previously: by using a div
element with the class \"row\", and other div
elements within it using the \"col-xs-*\" class.",
@@ -1433,9 +1432,9 @@
"This is the last challenge we'll do for our Cat Photo App for now. We hope you've enjoyed learning Font Awesome, Bootstrap, and responsive design!"
],
"tests": [
- "assert($('div.row:has(input[type=\\'text\\'])').length > 0 && $('div.row:has(button[type=\\'submit\\'])').length > 0, 'Nest your form submission button and text area in a div with class \"row\".')",
+ "assert($('div.row:has(input[type=\\'text\\'])').length > 0 && $('div.row:has(button[type=\\'submit\\'])').length > 0, 'Nest your form submission button and text input in a div with class \"row\".')",
"assert($('div.col-xs-5:has(button[type=\\'submit\\'])').length > 0, 'Nest your form submission button in a div with the class \"col-xs-5\".')",
- "assert($('div.col-xs-7:has(input[type=\\'text\\'])').length > 0, 'Nest your form text area in a div with the class \"col-xs-7\".')",
+ "assert($('div.col-xs-7:has(input[type=\\'text\\'])').length > 0, 'Nest your form text input in a div with the class \"col-xs-7\".')",
"assert(editor.match(/<\\/div>/g) && editor.match(/div
elements deep on each column of our row. This is as deep as we'll need to go. Now we can add our button
elements.",
@@ -1720,6 +1719,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1734,8 +1734,7 @@
},
{
"id": "bad87fee1348bd9aec908850",
- "name": "Waypoint: Apply the Default Bootstrap Button Style",
- "dashedName": "waypoint-apply-the-default-bootstrap-button-style",
+ "title": "Apply the Default Bootstrap Button Style",
"difficulty": 2.23,
"description": [
"Bootstrap has another button class called \"btn-default\"",
@@ -1766,6 +1765,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1780,8 +1780,7 @@
},
{
"id": "bad87fee1348bd9aec908852",
- "name": "Waypoint: Create a Class to Target with jQuery Selectors",
- "dashedName": "waypoint-create-a-class-to-target-with-jquery-selectors",
+ "title": "Create a Class to Target with jQuery Selectors",
"difficulty": 2.24,
"description": [
"Not every class needs to have corresponding CSS. Sometimes we create classes just for the purpose of selecting these elements more easily using jQuery.",
@@ -1811,6 +1810,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1825,8 +1825,7 @@
},
{
"id": "bad87fee1348bd9aec908853",
- "name": "Waypoint: Add ID Attributes to Bootstrap Elements",
- "dashedName": "waypoint-add-id-attributes-to-bootstrap-elements",
+ "title": "Add ID Attributes to Bootstrap Elements",
"difficulty": 2.25,
"description": [
"Recall that in addition to class attributes, you can give each of your elements an id attribute.",
@@ -1860,6 +1859,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1874,8 +1874,7 @@
},
{
"id": "bad87fee1348bd9aec908854",
- "name": "Waypoint: Label Bootstrap Wells",
- "dashedName": "waypoint-label-bootstrap-wells",
+ "title": "Label Bootstrap Wells",
"difficulty": 2.26,
"description": [
"For the sake of clarity, let's label both of our wells with their ids.",
@@ -1908,6 +1907,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1922,8 +1922,7 @@
},
{
"id": "bad87fee1348bd9aec908855",
- "name": "Waypoint: Give Each Element a Unique ID",
- "dashedName": "waypoint-give-each-element-a-unique-id",
+ "title": "Give Each Element a Unique ID",
"difficulty": 2.27,
"description": [
"We will also want to be able to use jQuery to target each button by its unique id.",
@@ -1960,6 +1959,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1974,8 +1974,7 @@
},
{
"id": "bad87fee1348bd9aec908856",
- "name": "Waypoint: Label Bootstrap Buttons",
- "dashedName": "waypoint-label-bootstrap-buttons",
+ "title": "Label Bootstrap Buttons",
"difficulty": 2.28,
"description": [
"Just like we labled our wells, we want to label our buttons.",
@@ -2012,6 +2011,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -2026,8 +2026,7 @@
},
{
"id": "bad87fee1348bd9aec908857",
- "name": "Waypoint: Use Comments to Clarify Code",
- "dashedName": "waypoint-use-comments-to-clarify-code",
+ "title": "Use Comments to Clarify Code",
"difficulty": 2.29,
"description": [
"When we start using jQuery, we will modify HTML elements without needing to actually change them in HTML.",
@@ -2063,6 +2062,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
diff --git a/seed/challenges/expert-bonfires.json b/seed/challenges/expert-bonfires.json
deleted file mode 100644
index 50bbe89de2..0000000000
--- a/seed/challenges/expert-bonfires.json
+++ /dev/null
@@ -1,304 +0,0 @@
-{
- "name": "Expert Algorithm Scripting",
- "order": 0.013,
- "challenges": [
- {
- "id": "aff0395860f5d3034dc0bfc9",
- "name": "Bonfire: Validate US Telephone Numbers",
- "dashedName": "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",
- "dashedName": "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.equal([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()",
- "Symmetric Difference"
- ],
- "challengeType": 5,
- "nameCn": "",
- "descriptionCn": [],
- "nameFr": "",
- "descriptionFr": [],
- "nameRu": "",
- "descriptionRu": [],
- "nameEs": "",
- "descriptionEs": [],
- "namePt": "",
- "descriptionPt": []
- },
- {
- "id": "aa2e6f85cab2ab736c9a9b24",
- "name": "Bonfire: Exact Change",
- "dashedName": "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",
- "dashedName": "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",
- "dashedName": "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",
- "dashedName": "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'], 'two months apart can be inferred if 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'], 'one month apart can be inferred it is the same year');",
- "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": []
- }
- ]
-}
diff --git a/seed/challenges/get-set-for-free-code-camp.json b/seed/challenges/get-set-for-free-code-camp.json
deleted file mode 100644
index ae22da999b..0000000000
--- a/seed/challenges/get-set-for-free-code-camp.json
+++ /dev/null
@@ -1,427 +0,0 @@
-{
- "name": "Get Set for Free Code Camp",
- "order": 0.001,
- "challenges": [
- {
- "id": "bd7124d8c441eddfaeb5bdef",
- "name": "Waypoint: Learn how Free Code Camp Works",
- "dashedName": "waypoint-learn-how-free-code-camp-works",
- "difficulty": 0.01,
- "challengeSeed": ["125407438"],
- "description": [
- "Watch this 1-minute video, or simply read this summary:",
- "Welcome to Free Code Camp. We're an open source community of busy people who learn to code, then practice by building projects for nonprofits.",
- "Learning to code is hard. It takes a lot of practice.",
- "So we've focused on making Free Code Camp as convenient and accessible as possible.",
- "Free Code Camp is self-paced, browser-based, and free.",
- "During the first 800 hours of Free Code Camp, you'll learn technologies like HTML5, Node.js and databases.",
- "During the last 800 hours, you'll build several real-life projects for nonprofits.",
- "By the time you finish, you'll be a job-ready coder who has a portfolio of apps with happy users to prove it.",
- "We'll even help you meet other coders in your city and find a coding job.",
- "We'll provide you with the most rigorous curriculum and the most supportive community on earth. All you need to do sit down, day after day, and put in the hard work.",
- "Now it's time to join our chat room. Click the \"I've completed this challenge\" button to move on to your next challenge."
- ],
- "challengeType": 2,
- "tests": [],
- "nameCn": "",
- "descriptionCn": [],
- "nameFr": "",
- "descriptionFr": [],
- "nameRu": "",
- "descriptionRu": [],
- "nameEs": "Waypoint: Aprende sobre como funciona Free Code Camp",
- "descriptionEs": [
- "Mira el video de 1 minuto o simplemente lee este resumen:",
- "Bienvenido a Free Code Camp. Somos una comunidad de personas ocupadas tratando de aprender a programar construyendo proyectos para empresas sin fines de lucro.",
- "Hemos construido esta comunidad porque aprender a programar es dificil; pero cualquiera que se pueda mantener motivado puede aprender a programar. Para mantenerte motivado, solo necesitas: h2
tag that says \"CatPhotoApp\" to create a second HTML element
below your \"Hello World\" h1
element.",
@@ -71,6 +70,7 @@
"challengeSeed": [
"p
element below your h2
element, and give it the text \"Hello Paragraph\".",
@@ -114,6 +113,7 @@
"h1
, h2
and p
elements.",
@@ -162,6 +161,7 @@
"Hello Paragraph
", "-->" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -188,8 +188,7 @@ }, { "id": "bad87fee1348bd9aedf08804", - "name": "Waypoint: Comment out HTML", - "dashedName": "waypoint-comment-out-html", + "title": "Comment out HTML", "difficulty": 1.05, "description": [ "Comment out yourh1
element and your p
element, but leave your h2
element uncommented.",
@@ -211,6 +210,7 @@
"Hello Paragraph
", "-->" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -235,8 +235,7 @@ }, { "id": "bad87fee1348bd9aedf08833", - "name": "Waypoint: Fill in the Blank with Placeholder Text", - "dashedName": "waypoint-fill-in-the-blank-with-placeholder-text", + "title": "Fill in the Blank with Placeholder Text", "difficulty": 1.06, "description": [ "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.", @@ -254,6 +253,7 @@ "", "Hello Paragraph
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -282,8 +282,7 @@ }, { "id": "bad87fed1348bd9aedf08833", - "name": "Waypoint: Delete HTML Elements", - "dashedName": "waypoint-delete-html-elements", + "title": "Delete HTML Elements", "difficulty": 1.07, "description": [ "Delete yourh1
element so we can simplify our view.",
@@ -302,6 +301,7 @@
"",
"Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -326,8 +326,7 @@ }, { "id": "bad87fee1348bd9aedf08803", - "name": "Waypoint: Change the Color of Text", - "dashedName": "waypoint-change-the-color-of-text", + "title": "Change the Color of Text", "difficulty": 1.08, "description": [ "Change yourh2
element's style so that its text color is red.",
@@ -343,6 +342,7 @@
"",
"Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -368,8 +368,7 @@ }, { "id": "bad87fee1348bd9aedf08805", - "name": "Waypoint: Use CSS Selectors to Style Elements", - "dashedName": "waypoint-use-css-selectors-to-style-elements", + "title": "Use CSS Selectors to Style Elements", "difficulty": 1.09, "description": [ "Delete yourh2
element's style attribute and instead create a CSS style
element. Add the necessary CSS to turn all h2
elements blue.",
@@ -391,6 +390,7 @@
"",
"Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -423,8 +423,7 @@ }, { "id": "bad87fee1348bd9aecf08806", - "name": "Waypoint: Use a CSS Class to Style an Element", - "dashedName": "waypoint-use-a-css-class-to-style-an-element", + "title": "Use a CSS Class to Style an Element", "difficulty": 1.11, "description": [ "Create a CSS class called \"red-text\" and apply it to yourh2
element.",
@@ -452,6 +451,7 @@
"",
"Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -477,8 +477,7 @@ }, { "id": "bad87fee1348bd9aefe08806", - "name": "Waypoint: Style Multiple Elements with a CSS Class", - "dashedName": "waypoint-style-multiple-elements-with-a-css-class", + "title": "Style Multiple Elements with a CSS Class", "difficulty": 1.12, "description": [ "Apply the \"red-text\" class to yourh2
and p
elements.",
@@ -502,6 +501,7 @@
"",
"Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -522,8 +522,7 @@ }, { "id": "bad87fee1348bd9aedf08806", - "name": "Waypoint: Change the Font Size of an Element", - "dashedName": "waypoint-change-the-font-size-of-an-element", + "title": "Change the Font Size of an Element", "difficulty": 1.13, "description": [ "Create a secondp
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.
",
@@ -548,6 +547,7 @@
"",
"Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -569,8 +569,7 @@ }, { "id": "bad87fee1348bd9aede08807", - "name": "Waypoint: Set the Font Family of an Element", - "dashedName": "waypoint-set-the-font-family-of-an-element", + "title": "Set the Font Family of an Element", "difficulty": 1.14, "description": [ "Make all of yourp
elements use the \"Monospace\" font.",
@@ -596,6 +595,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -616,8 +616,7 @@ }, { "id": "bad87fee1348bd9aedf08807", - "name": "Waypoint: Import a Google Font", - "dashedName": "waypoint-import-a-google-font", + "title": "Import a Google Font", "difficulty": 1.15, "description": [ "Apply thefont-family
of \"Lobster\" to your h2
element.",
@@ -648,6 +647,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -670,8 +670,7 @@ }, { "id": "bad87fee1348bd9aedf08808", - "name": "Waypoint: Specify How Fonts Should Degrade", - "dashedName": "waypoint-specify-how-fonts-should-degrade", + "title": "Specify How Fonts Should Degrade", "difficulty": 1.16, "description": [ "There are several default fonts that are available in all browsers. These include \"Monospace\", \"Serif\" and \"Sans-Serif\". Leave \"Lobster\" as the font-family for yourh2
elements. Make them \"degrade\" to \"Monospace\" when \"Lobster\" isn't available.",
@@ -706,6 +705,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -728,8 +728,7 @@ }, { "id": "bad87fee1348bd9aedf08812", - "name": "Waypoint: Add Images to your Website", - "dashedName": "waypoint-add-images-to-your-website", + "title": "Add Images to your Website", "difficulty": 1.17, "description": [ "You can add images to your website by using theimg
element, and point to an specific image's URL using the src
attribute.",
@@ -762,6 +761,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -783,8 +783,7 @@ }, { "id": "bad87fee1348bd9acdf08812", - "name": "Waypoint: Size your Images", - "dashedName": "waypoint-size-your-images", + "title": "Size your Images", "difficulty": 1.18, "description": [ "CSS has an attribute calledwidth
that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the image's width.",
@@ -819,6 +818,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -839,8 +839,7 @@ }, { "id": "bad87fee1348bd9bedf08813", - "name": "Waypoint: Add Borders Around your Elements", - "dashedName": "waypoint-add-borders-around-your-elements", + "title": "Add Borders Around your Elements", "difficulty": 1.19, "description": [ "CSS borders have attributes like style, color and width.", @@ -882,6 +881,7 @@ "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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -902,8 +902,7 @@ }, { "id": "bad87fee1348bd9aedf08814", - "name": "Waypoint: Add Rounded Corners with a Border Radius", - "dashedName": "waypoint-add-rounded-corners-with-a-border-radius", + "title": "Add Rounded Corners with a Border Radius", "difficulty": 1.20, "description": [ "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute calledborder-radius
.",
@@ -948,6 +947,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -968,8 +968,7 @@ }, { "id": "bad87fee1348bd9aedf08815", - "name": "Waypoint: Make Circular Images with a Border Radius", - "dashedName": "waypoint-make-circular-images-with-a-border-radius", + "title": "Make Circular Images with a Border Radius", "difficulty": 1.21, "description": [ "In addition to pixels, you can also specify aborder-radius
using a percentage.",
@@ -1014,6 +1013,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -1033,8 +1033,7 @@ }, { "id": "bad87fee1348bd9aedf08816", - "name": "Waypoint: Link to External Pages with Anchor Elements", - "dashedName": "waypoint-link-to-external-pages-with-anchor-elements", + "title": "Link to External Pages with Anchor Elements", "difficulty": 1.22, "description": [ "a
elements or \"anchor\" elements, are used to link to content outside of the current page.",
@@ -1083,6 +1082,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -1104,8 +1104,7 @@ }, { "id": "bad87fee1348bd9aede08817", - "name": "Waypoint: Nest an Anchor Element within a Paragraph", - "dashedName": "waypoint-nest-an-anchor-element-within-a-paragraph", + "title": "Nest an Anchor Element within a Paragraph", "difficulty": 1.23, "description": [ "Again, here's a diagram of ana
element for your reference:",
@@ -1160,6 +1159,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -1180,8 +1180,7 @@ }, { "id": "bad87fee1348bd9aedf08817", - "name": "Waypoint: Make Dead Links using the Hash Symbol", - "dashedName": "waypoint-make-dead-links-using-the-hash-symbol", + "title": "Make Dead Links using the Hash Symbol", "difficulty": 1.24, "description": [ "Sometimes you want to adda
elements to your website before you know where they will link.",
@@ -1228,6 +1227,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -1249,8 +1249,7 @@ }, { "id": "bad87fee1348bd9aedf08820", - "name": "Waypoint: Turn an Image into a Link", - "dashedName": "waypoint-turn-an-image-into-a-link", + "title": "Turn an Image into a Link", "difficulty": 1.25, "description": [ "You can make elements into links by nesting them within ana
element.",
@@ -1259,8 +1258,8 @@
"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($('a').children('img').length > 0, 'Nest your img
element within an a
element.')",
"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, 'Nest 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": [
@@ -1300,6 +1299,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -1322,8 +1322,7 @@ }, { "id": "bad87fee1348bd9aedf08818", - "name": "Waypoint: Add Alt Text to an Image for Accessibility", - "dashedName": "waypoint-add-alt-text-to-an-image-for-accessibility", + "title": "Add Alt Text to an Image for Accessibility", "difficulty": 1.26, "description": [ "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. And search engines also look at alt
attributes.",
@@ -1371,6 +1370,7 @@
"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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -1393,8 +1393,7 @@ }, { "id": "bad87fee1348bd9aedf08827", - "name": "Waypoint: Create a Bulleted Unordered List", - "dashedName": "waypoint-create-a-bulleted-unordered-list", + "title": "Create a Bulleted Unordered List", "difficulty": 1.27, "description": [ "HTML has a special element for creating unordered lists, or bullet point-style lists.", @@ -1450,6 +1449,7 @@ "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.
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -1471,8 +1471,7 @@ }, { "id": "bad87fee1348bd9aedf08828", - "name": "Waypoint: Create an Ordered List", - "dashedName": "waypoint-create-an-ordered-list", + "title": "Create an Ordered List", "difficulty": 1.28, "description": [ "HTML has a special element for creating ordered lists, or numbered-style lists.", @@ -1531,6 +1530,7 @@ "", "Top 3 things cats hate:
" ], + "type": "waypoint", "challengeType": 0, "nameCn": "", "descriptionCn": [], @@ -1552,8 +1552,7 @@ }, { "id": "bad87fee1348bd9aedf08829", - "name": "Waypoint: Create a Text Field", - "dashedName": "waypoint-create-a-text-field", + "title": "Create a Text Field", "difficulty": 1.29, "description": [ "Now let's create a web form.", @@ -1611,6 +1610,7 @@ "input
before your user has inputed anything.",
@@ -1691,6 +1690,7 @@
"",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1711,8 +1711,7 @@
},
{
"id": "bad87fee1348bd9aede08830",
- "name": "Waypoint: Create a Form Element",
- "dashedName": "waypoint-create-a-form-element",
+ "title": "Create a Form Element",
"difficulty": 1.31,
"description": [
"You can build web forms that actually submit data to a server using nothing more than pure HTML. You can do this by specifying an action on your form
element.",
@@ -1773,6 +1772,7 @@
"",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1793,8 +1793,7 @@
},
{
"id": "bad87fee1348bd9aedd08830",
- "name": "Waypoint: Add a Submit Button to a Form",
- "dashedName": "waypoint-add-a-submit-button-to-a-form",
+ "title": "Add a Submit Button to a Form",
"difficulty": 1.32,
"description": [
"Let's add a submit button to your form. Clicking this button will send the data from your form to the URL you specified with your form's action
attribute.",
@@ -1857,6 +1856,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1877,8 +1877,7 @@
},
{
"id": "bad87fee1348bd9aedc08830",
- "name": "Waypoint: Use HTML5 to Require a Field",
- "dashedName": "waypoint-use-html5-to-require-a-field",
+ "title": "Use HTML5 to Require a Field",
"difficulty": 1.33,
"description": [
"You can require specific form fields so that your user will not be able to submit your form until he or she has filled them out.",
@@ -1939,6 +1938,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -1959,8 +1959,7 @@
},
{
"id": "bad87fee1348bd9aedf08834",
- "name": "Waypoint: Create a Set of Radio Buttons",
- "dashedName": "waypoint-create-a-set-of-radio-buttons",
+ "title": "Create a Set of Radio Buttons",
"difficulty": 1.34,
"description": [
"You can use \"radio buttons\" for questions where you want the user to only give you one answer.",
@@ -2029,6 +2028,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -2052,8 +2052,7 @@
},
{
"id": "bad87fee1348bd9aedf08835",
- "name": "Waypoint: Create a Set of Checkboxes",
- "dashedName": "waypoint-create-a-set-of-checkboxes",
+ "title": "Create a Set of Checkboxes",
"difficulty": 1.35,
"description": [
"Forms commonly use \"checkboxes\" for questions that may have more than one answer.",
@@ -2122,6 +2121,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -2142,8 +2142,7 @@
},
{
"id": "bad87fee1348bd9aedd08835",
- "name": "Waypoint: Check Radio Buttons and Checkboxes by Default",
- "dashedName": "waypoint-check-radio-buttons-and-checkboxes-by-default",
+ "title": "Check Radio Buttons and Checkboxes by Default",
"difficulty": 1.37,
"description": [
"You can set a checkbox or radio button to be checked by default using the checked
attribute.",
@@ -2210,6 +2209,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -2230,8 +2230,7 @@
},
{
"id": "bad87fee1348bd9aede08835",
- "name": "Waypoint: Nest Many Elements within a Single Div Element",
- "dashedName": "waypoint-nest-many-elements-within-a-single-div-element",
+ "title": "Nest Many Elements within a Single Div Element",
"difficulty": 1.38,
"description": [
"The div
element, or \"Division\" element, is a general purpose container for other elements.",
@@ -2303,6 +2302,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -2325,8 +2325,7 @@
},
{
"id": "bad87fed1348bd9aede07836",
- "name": "Waypoint: Give a Background Color to a Div Element",
- "dashedName": "waypoint-give-a-background-color-to-a-div-element",
+ "title": "Give a Background Color to a Div Element",
"difficulty": 1.39,
"description": [
"You can set an element's background color with the \"background-color\" attribute.",
@@ -2396,6 +2395,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -2412,8 +2412,7 @@
},
{
"id": "bad87eee1348bd9aede07836",
- "name": "Waypoint: Set the ID of an Element",
- "dashedName": "waypoint-set-the-id-of-an-element",
+ "title": "Set the ID of an Element",
"difficulty": 1.391,
"description": [
"In addition to classes, each HTML element can also have an id
attribute.",
@@ -2484,6 +2483,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -2500,8 +2500,7 @@
},
{
"id": "bad87dee1348bd9aede07836",
- "name": "Waypoint: Use an ID Attribute to Style an Element",
- "dashedName": "waypoint-use-an-id-attribute-to-style-an-element",
+ "title": "Use an ID Attribute to Style an Element",
"difficulty": 1.392,
"description": [
"One cool thing about id
attributes is that, like classes, you can style them using CSS.",
@@ -2574,6 +2573,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -2590,8 +2590,7 @@
},
{
"id": "bad88fee1348bd9aedf08825",
- "name": "Waypoint: Adjusting the Padding of an Element",
- "dashedName": "waypoint-adjusting-the-padding-of-an-element",
+ "title": "Adjusting the Padding of an Element",
"difficulty": 1.40,
"description": [
"You may have already noticed this, but all HTML elements are essentially little rectangles.",
@@ -2640,6 +2639,7 @@
" margin
controls the amount of space between an element's border
and surrounding elements.",
@@ -2711,6 +2710,7 @@
" margin
controls the amount of space between an element's border
and surrounding elements.",
@@ -2781,6 +2780,7 @@
" padding
on each of its sides.",
@@ -2854,6 +2853,7 @@
" margin
of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.",
@@ -2926,6 +2925,7 @@
" padding-top
, padding-right
, padding-bottom
, and padding-left
attributes, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;
.",
@@ -2994,6 +2993,7 @@
" margin
this time.",
@@ -3028,7 +3027,6 @@
"assert($('.green-box').css('margin-right') === '20px', 'Your green-box
class should give the right of elements 20px of margin
.')",
"assert($('.green-box').css('margin-bottom') === '20px', 'Your green-box
class should give the bottom of elements 20px of margin
.')",
"assert($('.green-box').css('margin-left') === '40px', 'Your green-box
class should give the left of elements 40px of margin
.')"
-
],
"challengeSeed": [
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3118,8 +3117,7 @@
},
{
"id": "bad87fee1348bd9aedf08746",
- "name": "Waypoint: Inherit Styles from the Body Element",
- "dashedName": "waypoint-inherit-styles-from-the-body-element",
+ "title": "Inherit Styles from the Body Element",
"difficulty": 1.47,
"description": [
"Now we've proven that every HTML page has a body
element, and that its body
element can also be styled with CSS.",
@@ -3145,6 +3143,7 @@
"",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3161,8 +3160,7 @@
},
{
"id": "bad87fee1348bd9aedf08756",
- "name": "Waypoint: Prioritize One Style Over Another",
- "dashedName": "waypoint-prioritize-one-style-over-another",
+ "title": "Prioritize One Style Over Another",
"difficulty": 1.48,
"description": [
"Sometimes your HTML elements will receive multiple styles that conflict with one another.",
@@ -3185,6 +3183,7 @@
"",
"body
element's CSS declaration!",
@@ -3228,6 +3226,7 @@
"",
"style
element CSS.",
@@ -3328,6 +3326,7 @@
"",
"style
element.",
@@ -3382,6 +3380,7 @@
"",
"#000000
is the lowest possible value, and it represents the color black.",
"Replace the word \"black\" in our body
element's background-color with its \"hex code\" representation, #000000
. "
@@ -3418,6 +3416,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3434,8 +3433,7 @@
},
{
"id": "bad87fee1348bd9aedf08725",
- "name": "Waypoint: Use Hex Code to Color Elements White",
- "dashedName": "waypoint-use-hex-code-to-color-elements-white",
+ "title": "Use Hex Code to Color Elements White",
"difficulty": 1.55,
"description": [
"0 is the lowest number in hex code, and represents a complete absence of color.",
@@ -3453,6 +3451,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3469,8 +3468,7 @@
},
{
"id": "bad87fee1348bd9aedf08724",
- "name": "Waypoint: Use Hex Code to Color Elements Red",
- "dashedName": "waypoint-use-hex-code-to-color-elements-red",
+ "title": "Use Hex Code to Color Elements Red",
"difficulty": 1.56,
"description": [
"You may be wondering why we use 6 digits to represent a color instead of just one or two. The answer is that using 6 digits gives us a huge variety.",
@@ -3490,6 +3488,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3506,8 +3505,7 @@
},
{
"id": "bad87fee1348bd9aedf08723",
- "name": "Waypoint: Use Hex Code to Color Elements Green",
- "dashedName": "waypoint-use-hex-code-to-color-elements-green",
+ "title": "Use Hex Code to Color Elements Green",
"difficulty": 1.57,
"description": [
"Remember that hex code follows the red-green-blue, or \"RGB\" format. The first two digits of hex code represent the amount of red in the color. The third and fourth digit represent the amount of green. The fifth and sixth represent the amount of blue.",
@@ -3525,6 +3523,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3541,8 +3540,7 @@
},
{
"id": "bad87fee1348bd9aedf08722",
- "name": "Waypoint: Use Hex Code to Color Elements Blue",
- "dashedName": "waypoint-use-hex-code-to-color-elements-blue",
+ "title": "Use Hex Code to Color Elements Blue",
"difficulty": 1.58,
"description": [
"Hex code follows the red-green-blue, or \"RGB\" format. The first two digits of hex code represent the amount of red in the color. The third and fourth digit represent the amount of green. The fifth and sixth represent the amount of blue.",
@@ -3560,6 +3558,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3576,8 +3575,7 @@
},
{
"id": "bad87fee1348bd9aedf08721",
- "name": "Waypoint: Use Hex Code to Mix Colors",
- "dashedName": "waypoint-use-hex-code-to-mix-colors",
+ "title": "Use Hex Code to Mix Colors",
"difficulty": 1.59,
"description": [
"From these three pure colors (red, green and blue), we can create 16 million other colors.",
@@ -3595,6 +3593,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3611,8 +3610,7 @@
},
{
"id": "bad87fee1348bd9aede08720",
- "name": "Waypoint: Use Hex Code to Color Elements Gray",
- "dashedName": "waypoint-use-hex-code-to-color-elements-gray",
+ "title": "Use Hex Code to Color Elements Gray",
"difficulty": 1.60,
"description": [
"From these three pure colors (red, green and blue), we can create 16 million other colors.",
@@ -3630,6 +3628,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3646,8 +3645,7 @@
},
{
"id": "bad87fee1348bd9aedf08720",
- "name": "Waypoint: Use Hex Code for Specific Shades of Gray",
- "dashedName": "waypoint-use-hex-code-for-specific-shades-of-gray",
+ "title": "Use Hex Code for Specific Shades of Gray",
"difficulty": 1.61,
"description": [
"We can also create other shades of gray by evenly mixing all three colors. We can go very close to true black.",
@@ -3664,6 +3662,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3680,8 +3679,7 @@
},
{
"id": "bad87fee1348bd9aedf08719",
- "name": "Waypoint: Use Abbreviated Hex Code",
- "dashedName": "waypoint-use-abbreviated-hex-code",
+ "title": "Use Abbreviated Hex Code",
"difficulty": 1.62,
"description": [
"Many people feel overwhelmed by the possibilities of more than 16 million colors. And it's difficult to remember hex code. Fortunately, you can shorten it.",
@@ -3700,6 +3698,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3716,8 +3715,7 @@
},
{
"id": "bad87fee1348bd9aede08718",
- "name": "Waypoint: Use RGB values to Color Elements",
- "dashedName": "waypoint-use-rgb-values-to-color-elements",
+ "title": "Use RGB values to Color Elements",
"difficulty": 1.63,
"description": [
"Another way you can represent colors in CSS is by using RGB values.",
@@ -3737,6 +3735,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3753,8 +3752,7 @@
},
{
"id": "bad88fee1348bd9aedf08726",
- "name": "Waypoint: Use RGB to Color Elements White",
- "dashedName": "waypoint-use-rgb-to-color-elements-white",
+ "title": "Use RGB to Color Elements White",
"difficulty": 1.64,
"description": [
"RGB values look like this: rgb(0, 0, 0)
for black and rgb(255, 255, 255) for white.",
@@ -3772,6 +3770,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3788,8 +3787,7 @@
},
{
"id": "bad89fee1348bd9aedf08724",
- "name": "Waypoint: Use RGB to Color Elements Red",
- "dashedName": "waypoint-use-rgb-to-color-elements-red",
+ "title": "Use RGB to Color Elements Red",
"difficulty": 1.65,
"description": [
"Just like with hex code, you can represent different colors in RGB by using combinations of different values.",
@@ -3807,6 +3805,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3823,8 +3822,7 @@
},
{
"id": "bad80fee1348bd9aedf08723",
- "name": "Waypoint: Use RGB to Color Elements Green",
- "dashedName": "waypoint-use-rgb-to-color-elements-green",
+ "title": "Use RGB to Color Elements Green",
"difficulty": 1.66,
"description": [
"Now change the body
element's background color to the RGB value green: rgb(0, 255, 0)
"
@@ -3840,6 +3838,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3856,8 +3855,7 @@
},
{
"id": "bad81fee1348bd9aedf08722",
- "name": "Waypoint: Use RGB to Color Elements Blue",
- "dashedName": "waypoint-use-rgb-to-color-elements-blue",
+ "title": "Use RGB to Color Elements Blue",
"difficulty": 1.67,
"description": [
"Change the body
element's background color to the RGB value blue: rgb(0, 0, 255)
"
@@ -3873,6 +3871,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3889,8 +3888,7 @@
},
{
"id": "bad82fee1348bd9aedf08721",
- "name": "Waypoint: Use RGB to Mix Colors",
- "dashedName": "waypoint-use-rgb-to-mix-colors",
+ "title": "Use RGB to Mix Colors",
"difficulty": 1.68,
"description": [
"Just like with hex code, you can mix colors in RGB by using combinations of different values.",
@@ -3907,6 +3905,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
@@ -3923,8 +3922,7 @@
},
{
"id": "bad83fee1348bd9aede08720",
- "name": "Waypoint: Use RGB to Color Elements Gray",
- "dashedName": "waypoint-use-rgb-to-color-elements-gray",
+ "title": "Use RGB to Color Elements Gray",
"difficulty": 1.69,
"description": [
"With RGB values, we can make an element gray by using combinations of the same value for all three colors.",
@@ -3941,6 +3939,7 @@
" }",
""
],
+ "type": "waypoint",
"challengeType": 0,
"nameCn": "",
"descriptionCn": [],
diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json
index 184a648748..743f4d2e1a 100644
--- a/seed/challenges/intermediate-bonfires.json
+++ b/seed/challenges/intermediate-bonfires.json
@@ -4,8 +4,7 @@
"challenges": [
{
"id": "a3566b1109230028080c9345",
- "name": "Bonfire: Sum All Numbers in a Range",
- "dashedName": "bonfire-sum-all-numbers-in-a-range",
+ "title": "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.",
@@ -31,6 +30,7 @@
"Math.min()",
"Array.reduce()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -45,8 +45,7 @@
},
{
"id": "a5de63ebea8dbee56860f4f2",
- "name": "Bonfire: Diff Two Arrays",
- "dashedName": "bonfire-diff-two-arrays",
+ "title": "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.",
@@ -77,6 +76,7 @@
"Array.indexOf()",
"String.concat()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -91,8 +91,7 @@
},
{
"id": "a7f4d8f2483413a6ce226cac",
- "name": "Bonfire: Roman Numeral Converter",
- "dashedName": "bonfire-roman-numeral-converter",
+ "title": "Roman Numeral Converter",
"tests": [
"expect(convert(12)).to.equal(\"XII\");",
"expect(convert(5)).to.equal(\"V\");",
@@ -118,6 +117,7 @@
"Array.indexOf()",
"Array.join()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -132,8 +132,7 @@
},
{
"id": "a0b5010f579e69b815e7c5d6",
- "name": "Bonfire: Search and Replace",
- "dashedName": "bonfire-search-and-replace",
+ "title": "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\");",
@@ -162,6 +161,7 @@
"String.replace()",
"Array.join()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -176,8 +176,7 @@
},
{
"id": "aa7697ea2477d1316795783b",
- "name": "Bonfire: Pig Latin",
- "dashedName": "bonfire-pig-latin",
+ "title": "Pig Latin",
"tests": [
"expect(translate(\"california\")).to.equal(\"aliforniacay\");",
"expect(translate(\"paragraphs\")).to.equal(\"aragraphspay\");",
@@ -188,7 +187,7 @@
"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\".",
+ "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."
],
@@ -206,6 +205,7 @@
"String.substr()",
"String.split()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -220,8 +220,7 @@
},
{
"id": "afd15382cdfb22c9efe8b7de",
- "name": "Bonfire: DNA Pairing",
- "dashedName": "bonfire-dna-pairing",
+ "title": "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');",
@@ -230,7 +229,7 @@
"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.",
+ "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."
],
@@ -245,6 +244,7 @@
"Array.push()",
"String.split()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -259,8 +259,7 @@
},
{
"id": "af7588ade1100bde429baf20",
- "name": "Bonfire: Missing letters",
- "dashedName": "bonfire-missing-letters",
+ "title": "Missing letters",
"difficulty": "2.05",
"description": [
"Find the missing letter in the passed letter range and return it.",
@@ -284,6 +283,7 @@
"String.charCodeAt()",
"String.fromCharCode()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -298,8 +298,7 @@
},
{
"id": "a77dbc43c33f39daa4429b4f",
- "name": "Bonfire: Boo who",
- "dashedName": "bonfire-boo-who",
+ "title": "Boo who",
"difficulty": "2.06",
"description": [
"Check if a value is classified as a boolean primitive. Return true or false.",
@@ -327,6 +326,7 @@
"MDNlinks": [
"Boolean Objects"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -341,8 +341,7 @@
},
{
"id": "a105e963526e7de52b219be9",
- "name": "Bonfire: Sorted Union",
- "dashedName": "bonfire-sorted-union",
+ "title": "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.",
@@ -368,6 +367,7 @@
"Arguments object",
"Array.reduce()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -382,8 +382,7 @@
},
{
"id": "a6b0bb188d873cb2c8729495",
- "name": "Bonfire: Convert HTML Entities",
- "dashedName": "bonfire-convert-html-entities",
+ "title": "Convert HTML Entities",
"difficulty": "2.07",
"description": [
"Convert the characters \"&\", \"<\", \">\", '\"' (double quote), and \"'\" (apostrophe), in a string to their corresponding HTML entities.",
@@ -410,6 +409,7 @@
"RegExp",
"HTML Entities"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -424,8 +424,7 @@
},
{
"id": "a103376db3ba46b2d50db289",
- "name": "Bonfire: Spinal Tap Case",
- "dashedName": "bonfire-spinal-tap-case",
+ "title": "Spinal Tap Case",
"difficulty": "2.08",
"description": [
"Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes.",
@@ -450,6 +449,7 @@
"RegExp",
"String.replace()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -464,8 +464,7 @@
},
{
"id": "a5229172f011153519423690",
- "name": "Bonfire: Sum All Odd Fibonacci Numbers",
- "dashedName": "bonfire-sum-all-odd-fibonacci-numbers",
+ "title": "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.",
@@ -491,6 +490,7 @@
"MDNlinks": [
"Remainder"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -505,8 +505,7 @@
},
{
"id": "a3bfc1673c0526e06d3ac698",
- "name": "Bonfire: Sum All Primes",
- "dashedName": "bonfire-sum-all-primes",
+ "title": "Sum All Primes",
"difficulty": "2.10",
"description": [
"Sum all the prime numbers up to and including the provided number.",
@@ -530,6 +529,7 @@
"For Loops",
"Array.push()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -544,8 +544,7 @@
},
{
"id": "ae9defd7acaf69703ab432ea",
- "name": "Bonfire: Smallest Common Multiple",
- "dashedName": "bonfire-smallest-common-multiple",
+ "title": "Smallest Common Multiple",
"difficulty": "2.11",
"description": [
"Find the smallest number that is evenly divisible by all numbers in the provided range.",
@@ -569,6 +568,7 @@
"MDNlinks": [
"Smallest Common Multiple"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -583,8 +583,7 @@
},
{
"id": "a6e40f1041b06c996f7b2406",
- "name": "Bonfire: Finders Keepers",
- "dashedName": "bonfire-finders-keepers",
+ "title": "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).",
@@ -605,6 +604,7 @@
"MDNlinks": [
"Array.some()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -619,8 +619,7 @@
},
{
"id": "a5deed1811a43193f9f1c841",
- "name": "Bonfire: Drop it",
- "dashedName": "bonfire-drop-it",
+ "title": "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.",
@@ -643,6 +642,7 @@
"Arguments object",
"Array.shift()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -657,8 +657,7 @@
},
{
"id": "ab306dbdcc907c7ddfc30830",
- "name": "Bonfire: Steamroller",
- "dashedName": "bonfire-steamroller",
+ "title": "Steamroller",
"difficulty": "2.14",
"description": [
"Flatten a nested array. You must account for varying levels of nesting.",
@@ -681,6 +680,7 @@
"MDNlinks": [
"Array.isArray()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -695,8 +695,7 @@
},
{
"id": "a8d97bd4c764e91f9d2bda01",
- "name": "Bonfire: Binary Agents",
- "dashedName": "bonfire-binary-agents",
+ "title": "Binary Agents",
"difficulty": "2.15",
"description": [
"Return an English translated sentence of the passed binary string.",
@@ -718,6 +717,7 @@
"String.charCodeAt()",
"String.fromCharCode()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -732,8 +732,7 @@
},
{
"id": "a10d2431ad0c6a099a4b8b52",
- "name": "Bonfire: Everything Be True",
- "dashedName": "bonfire-everything-be-true",
+ "title": "Everything Be True",
"difficulty": "2.21",
"description": [
"Check if the predicate (second argument) returns truthy (defined) for all elements of a collection (first argument).",
@@ -753,12 +752,12 @@
"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');",
"assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'female'}, {'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()"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
@@ -773,8 +772,7 @@
},
{
"id": "a97fd23d9b809dac9921074f",
- "name": "Bonfire: Arguments Optional",
- "dashedName": "bonfire-arguments-optional",
+ "title": "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.",
@@ -800,6 +798,7 @@
"Global Function Object",
"Arguments object"
],
+ "type": "bonfire",
"challengeType": 5,
"nameCn": "",
"descriptionCn": [],
diff --git a/seed/challenges/intermediate-ziplines.json b/seed/challenges/intermediate-ziplines.json
index f8a267e8a9..2a2d5af952 100644
--- a/seed/challenges/intermediate-ziplines.json
+++ b/seed/challenges/intermediate-ziplines.json
@@ -4,8 +4,7 @@
"challenges": [
{
"id": "bd7158d8c442eddfaeb5bd18",
- "name": "Zipline: Stylize Stories on Camper News",
- "dashedName": "zipline-stylize-stories-on-camper-news",
+ "title": "Stylize Stories on Camper News",
"difficulty": 1.02,
"challengeSeed": ["126415129"],
"description": [
@@ -23,6 +22,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
@@ -38,8 +38,7 @@
},
{
"id": "bd7158d8c442eddfaeb5bd19",
- "name": "Zipline: Wikipedia Viewer",
- "dashedName": "zipline-wikipedia-viewer",
+ "title": "Wikipedia Viewer",
"difficulty": 1.03,
"challengeSeed": ["126415131"],
"description": [
@@ -56,6 +55,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
@@ -71,8 +71,7 @@
},
{
"id": "bd7158d8c442eddfaeb5bd17",
- "name": "Zipline: Build a JavaScript Calculator",
- "dashedName": "zipline-build-a-javascript-calculator",
+ "title": "Build a JavaScript Calculator",
"difficulty": 1.05,
"challengeSeed": ["126411565"],
"description": [
@@ -88,6 +87,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
@@ -103,8 +103,7 @@
},
{
"id": "bd7158d8c442eedfaeb5bd1c",
- "name": "Zipline: Build a Tic Tac Toe Game",
- "dashedName": "zipline-build-a-tic-tac-toe-game",
+ "title": "Build a Tic Tac Toe Game",
"difficulty": 1.06,
"challengeSeed": ["126415123"],
"description": [
@@ -121,6 +120,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
@@ -136,8 +136,7 @@
},
{
"id": "bd7158d8c442eddfaeb5bd1c",
- "name": "Zipline: Build a Simon Game",
- "dashedName": "zipline-build-a-simon-game",
+ "title": "Build a Simon Game",
"difficulty": 1.07,
"challengeSeed": ["126415123"],
"description": [
@@ -160,6 +159,7 @@
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
+ "type": "zipline",
"challengeType": 3,
"tests": [],
"nameCn": "",
diff --git a/seed/challenges/jquery-ajax-and-json.json b/seed/challenges/jquery-ajax-and-json.json
index abf05bceff..26cdb46b8a 100644
--- a/seed/challenges/jquery-ajax-and-json.json
+++ b/seed/challenges/jquery-ajax-and-json.json
@@ -1,12 +1,10 @@
{
- "name": "jQuery",
- "dashedName": "jquery",
+ "name": "jQuery",
"order": 0.004,
"challenges": [
{
"id": "bad87fee1348bd9acdd08826",
- "name": "Waypoint: Learn how Script Tags and Document Ready Work",
- "dashedName": "waypoint-learn-how-script-tags-and-document-ready-work",
+ "title": "Learn how Script Tags and Document Ready Work",
"difficulty": 3.01,
"description": [
"Now we're ready to learn jQuery, the most popular JavaScript tool of all time. Don't worry about JavaScript itself - we will cover it soon.",
@@ -44,13 +42,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9bedc08826",
- "name": "Waypoint: Target HTML Elements with Selectors Using jQuery",
- "dashedName": "waypoint-target-html-elements-with-selectors-using-jquery",
+ "title": "Target HTML Elements with Selectors Using jQuery",
"difficulty": 3.02,
"description": [
"Now we have a \"document ready function\". We'll learn more about functions later. The important thing to know is that code you put inside this function will run as soon as your browser has loaded your page.",
@@ -60,7 +57,7 @@
"For example, let's make all of your button
elements bounce. Just add this code inside your \"document ready function\": $('button').addClass('animated bounce')
."
],
"tests": [
- "assert($('button').hasClass('animated') && $('button').hasClass('bounce'), 'Use the jQuery addClass()
function to give the classes \"animated\" and \"bounce\" to your img
element.')",
+ "assert($('button').hasClass('animated') && $('button').hasClass('bounce'), 'Use the jQuery addClass()
function to give the classes \"animated\" and \"bounce\" to your button
element.')",
"assert(!editor.match(/class.*animated/g), 'Only use jQuery to add these classes to the element.')"
],
"challengeSeed": [
@@ -94,13 +91,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aedc08826",
- "name": "Waypoint: Target Elements by Class Using jQuery",
- "dashedName": "waypoint-target-elements-by-class-using-jquery",
+ "title": "Target Elements by Class Using jQuery",
"difficulty": 3.03,
"description": [
"You see how we made all of your button
elements bounce? We selected them with $('button')
, then we added some CSS classes to them with .addClass('animated bounce');
.",
@@ -145,12 +141,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
{
"id": "bad87fee1348bd9aeda08826",
- "name": "Waypoint: Target Elements by ID Using jQuery",
- "dashedName": "waypoint-target-elements-by-id-using-jquery",
+ "title": "Target Elements by ID Using jQuery",
"difficulty": 3.04,
"description": [
"You can also target elements by their id attributes.",
@@ -196,13 +192,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aeda08726",
- "name": "Waypoint: Delete your jQuery Functions",
- "dashedName": "waypoint-delete-your-jquery-functions",
+ "title": "Delete your jQuery Functions",
"difficulty": 3.05,
"description": [
"These animations were cool at first, but now they're getting kind of distracting.",
@@ -249,12 +244,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
{
"id": "bad87fee1348bd9aed908626",
- "name": "Waypoint: Target the same element with multiple jQuery Selectors",
- "dashedName": "waypoint-target-the-same-element-with-multiple-jQuery-Selectors",
+ "title": "Target the same element with multiple jQuery Selectors",
"difficulty": 3.06,
"description": [
"Now you know three ways of targeting elements: by type $('button')
, by class $('.btn')
), and by id $('#target1')
).",
@@ -300,12 +295,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
{
"id": "bad87fee1348bd9aed918626",
- "name": "Waypoint: Remove Classes from an element with jQuery",
- "dashedName": "waypoint-remove-classes-from-an-element-with-jquery",
+ "title": "Remove Classes from an element with jQuery",
"difficulty": 3.07,
"description": [
"In the same way you can add classes to an element with jQuery's addClass()
function, you can remove them with jQuery's removeClass()
function.",
@@ -350,12 +345,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
{
"id": "bad87fee1348bd9aed908826",
- "name": "Waypoint: Change the CSS of an Element Using jQuery",
- "dashedName": "waypoint-change-the-css-of-an-element-using-jquery",
+ "title": "Change the CSS of an Element Using jQuery",
"difficulty": 3.08,
"description": [
"We can also change the CSS of an HTML element directly with jQuery.",
@@ -404,13 +399,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aed808826",
- "name": "Waypoint: Disable an Element Using jQuery",
- "dashedName": "waypoint-disable-an-element-using-jquery",
+ "title": "Disable an Element Using jQuery",
"difficulty": 3.09,
"description": [
"You can also change the non-CSS properties of HTML elements with jQuery. For example, you can disable buttons.",
@@ -456,13 +450,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aed708826",
- "name": "Waypoint: Remove an Element Using jQuery",
- "dashedName": "waypoint-remove-an-element-using-jquery",
+ "title": "Remove an Element Using jQuery",
"difficulty": 3.10,
"description": [
"Now let's remove an HTML element from your page using jQuery.",
@@ -505,13 +498,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aed608826",
- "name": "Waypoint: Use appendTo to Move Elements with jQuery",
- "dashedName": "waypoint-use-appendto-to-move-elements-with-jquery",
+ "title": "Use appendTo to Move Elements with jQuery",
"difficulty": 3.11,
"description": [
"Now let's try moving elements from one div
to another.",
@@ -558,13 +550,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aed508826",
- "name": "Waypoint: Clone an Element Using jQuery",
- "dashedName": "waypoint-clone-an-element-using-jquery",
+ "title": "Clone an Element Using jQuery",
"difficulty": 3.12,
"description": [
"In addition to moving elements, you can also copy them from one place to another.",
@@ -613,13 +604,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aed308826",
- "name": "Waypoint: Target the Parent of an Element Using jQuery",
- "dashedName": "waypoint-target-the-parent-of-an-element-using-jquery",
+ "title": "Target the Parent of an Element Using jQuery",
"difficulty": 3.13,
"description": [
"Every HTML elements has a \"parent\" element from which it \"inherits\" properties.",
@@ -669,13 +659,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aed208826",
- "name": "Waypoint: Target the Children of an Element Using jQuery",
- "dashedName": "waypoint-target-the-children-of-an-element-using-jquery",
+ "title": "Target the Children of an Element Using jQuery",
"difficulty": 3.14,
"description": [
"Many HTML elements has a \"children\" element from which they \"inherits\" properties.",
@@ -685,7 +674,7 @@
"Here's an example of how you would use the children()
function: $('#left-well').children().css('color', 'blue')
"
],
"tests": [
- "assert($('#target6').css('color') === 'rgb(0, 0, 255)', 'Your \"target6\" element should have green text.')",
+ "assert($('#target6').css('color') === 'rgb(0, 255, 0), 'Your \"target6\" element should have green text.')",
"assert(!editor.match(/\\.children\\(\\)\\.css/g), 'You should use the children()
function to modify these elements.')",
"assert(!editor.match(//g), 'Only use jQuery to add these classes to the element.')"
],
@@ -726,12 +715,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
{
"id": "bad87fee1348bd9aed108826",
- "name": "Waypoint: Target a Specific Child of an Element Using jQuery",
- "dashedName": "waypoint-target-a-specific-child-of-an-element-using-jquery",
+ "title": "Target a Specific Child of an Element Using jQuery",
"difficulty": 3.15,
"description": [
"You've seen why id attributes are so convenient for targeting with jQuery selectors. But you won't always have such neat ids to work with.",
@@ -783,13 +772,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aed008826",
- "name": "Waypoint: Target Even Numbered Elements Using jQuery",
- "dashedName": "waypoint-target-even-numbered-elements-using-jquery",
+ "title": "Target Even Numbered Elements Using jQuery",
"difficulty": 3.16,
"description": [
"You can also target all the even-numbered elements.",
@@ -843,13 +831,12 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
},
-
{
"id": "bad87fee1348bd9aecb08826",
- "name": "Waypoint: Use jQuery to Modify the Entire Page",
- "dashedName": "waypoint-use-jquery-to-modify-the-entire-page",
+ "title": "Use jQuery to Modify the Entire Page",
"difficulty": 3.20,
"description": [
"We're done playing with our jQuery playground. Let's tear it down!",
@@ -901,6 +888,7 @@
" ",
""
],
+ "type": "waypoint",
"challengeType": 0
}
]
diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json
index d6b39f97c3..8745e513de 100644
--- a/seed/challenges/json-apis-and-ajax.json
+++ b/seed/challenges/json-apis-and-ajax.json
@@ -1,6 +1,5 @@
{
- "name": "JSON APIs and Ajax - Coming Soon",
- "dashedName": "json-apis-and-ajax",
+ "name": "JSON APIs and Ajax - Coming Soon",
"order": 0.007,
"challenges": [
]
diff --git a/seed/challenges/mongodb.json b/seed/challenges/mongodb.json
index a632eaf2ba..1751c617d8 100644
--- a/seed/challenges/mongodb.json
+++ b/seed/challenges/mongodb.json
@@ -4,8 +4,7 @@
"challenges": [
{
"id": "bd7243d8c341eddeaeb5bd0f",
- "name": "Waypoint: Store Data in MongoDB",
- "dashedName": "waypoint-store-data-in-mongodb",
+ "title": "Store Data in MongoDB",
"difficulty": 0.01,
"challengeSeed": ["133316035"],
"description": [
@@ -34,6 +33,7 @@
"Complete \"Aggregate\"",
"Once you've completed these steps, move on to our next challenge."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
diff --git a/seed/challenges/nodejs-and-expressjs.json b/seed/challenges/nodejs-and-expressjs.json
index ac307b57ac..ed6298910d 100644
--- a/seed/challenges/nodejs-and-expressjs.json
+++ b/seed/challenges/nodejs-and-expressjs.json
@@ -4,8 +4,7 @@
"challenges": [
{
"id": "bd7153d8c441eddfaeb5bd0f",
- "name": "Waypoint: Manage Packages with NPM",
- "dashedName": "waypoint-manage-packages-with-npm",
+ "title": "Manage Packages with NPM",
"difficulty": 0.39,
"challengeSeed": ["126433450"],
"description": [
@@ -43,6 +42,7 @@
"Complete \"Finale\"",
"Once you've completed these steps, move on to our next challenge."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
@@ -58,8 +58,7 @@
},
{
"id": "bd7153d8c441eddfaeb5bdff",
- "name": "Waypoint: Start a Node.js Server",
- "dashedName": "waypoint-start-a-nodejs-server",
+ "title": "Start a Node.js Server",
"difficulty": 0.40,
"challengeSeed": ["126411561"],
"description": [
@@ -85,6 +84,7 @@
"Complete \"HTTP Client\"",
"Once you've completed these first 7 steps, move on to our next challenge."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
@@ -100,8 +100,7 @@
},
{
"id": "bd7153d8c441eddfaeb5bdfe",
- "name": "Waypoint: Continue working with Node.js Servers",
- "dashedName": "waypoint-continue-working-with-nodejs-servers",
+ "title": "Continue working with Node.js Servers",
"difficulty": 0.41,
"challengeSeed": ["128836506"],
"description": [
@@ -114,6 +113,7 @@
"Complete \"Time Server\"",
"Once you've completed these 3 steps, move on to our next challenge."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
@@ -129,8 +129,7 @@
},
{
"id": "bd7153d8c441eddfaeb5bdfd",
- "name": "Waypoint: Finish working with Node.js Servers",
- "dashedName": "waypoint-finish-working-with-nodejs-servers",
+ "title": "Finish working with Node.js Servers",
"difficulty": 0.42,
"challengeSeed": ["128836507"],
"description": [
@@ -143,6 +142,7 @@
"Complete \"HTTP JSON API Server\"",
"Once you've completed these final 3 steps, move on to our next challenge."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
@@ -158,8 +158,7 @@
},
{
"id": "bd7153d8c441eddfaeb5bd1f",
- "name": "Waypoint: Build Web Apps with Express.js",
- "dashedName": "waypoint-build-web-apps-with-expressjs",
+ "title": "Build Web Apps with Express.js",
"difficulty": 0.43,
"challengeSeed": [
"126411559"
@@ -186,6 +185,7 @@
"Complete \"JSON Me\"",
"Once you've completed these steps, move on to our next challenge."
],
+ "type": "waypoint",
"challengeType": 2,
"tests": [],
"nameCn": "",
diff --git a/seed/challenges/object-oriented-and-functional-programming.json b/seed/challenges/object-oriented-and-functional-programming.json
index dd00934296..54b46060a3 100644
--- a/seed/challenges/object-oriented-and-functional-programming.json
+++ b/seed/challenges/object-oriented-and-functional-programming.json
@@ -1,315 +1,6 @@
{
- "name": "Object Oriented and Functional Programming - Under Construction From Challenge 4 Onwards",
- "order" : 0.009,
+ "name": "Object Oriented and Functional Programming - Coming Soon",
+ "order" : 0.010,
"challenges": [
- {
- "id": "bd7153d8c44eeddfaeb5bd0f",
- "name": "Waypoint: Learn Scope Chains and Closures",
- "dashedName": "waypoint-learn-scope-chains-and-closures",
- "difficulty": 0.01,
- "challengeSeed": ["133316031"],
- "description": [
- "We'll build this Waypoint 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.",
- "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. Then click into your new workspace.",
- "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.",
- "Install scope-chains-closures
with this command: npm install -g scope-chains-closures
",
- "Now start the tutorial by running scope-chains-closures
.",
- "Note that you can resize the c9.io's windows by dragging their borders.",
- "Make sure that you are always in your project's \"workspace\" directory. You can always navigate back to this directory by running this command: cd ~/workspace
.",
- "You can view this Node School module's source code on GitHub at https://github.com/jesstelford/scope-chains-closures.",
- "Complete \"Scopes\"",
- "Complete \"Scope Chains\"",
- "Complete \"Global Scope and Shadowing\"",
- "Complete \"Closures\"",
- "Complete \"Garbage Collection\"",
- "Once you've completed these steps, move on to our next challenge."
- ],
- "challengeType": 2,
- "tests": [],
- "nameCn": "",
- "descriptionCn": [],
- "nameFr": "",
- "descriptionFr": [],
- "nameRu": "",
- "descriptionRu": [],
- "nameEs": "",
- "descriptionEs": [],
- "namePt": "",
- "descriptionPt": []
- },
- {
- "id": "bd7153d8b44eeddfaeb5bd0f",
- "name": "Waypoint: Use Prototypes for Inheriting Properties",
- "dashedName": "waypoint-use-prototypes-for-inheriting-properties",
- "difficulty": 0.02,
- "challengeSeed": ["133316036"],
- "description": [
- "We'll build this Waypoint 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.",
- "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. Then click into your new workspace.",
- "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.",
- "Install planetproto
with this command: npm install -g planetproto
",
- "Now start the tutorial by running planetproto
.",
- "Note that you can resize the c9.io's windows by dragging their borders.",
- "Make sure that you are always in your project's \"workspace\" directory. You can always navigate back to this directory by running this command: cd ~/workspace
.",
- "You can view this Node School module's source code on GitHub at https://github.com/sporto/planetproto.",
- "Complete \"Simple Objects\"",
- "Complete \"Proto\"",
- "Complete \"Dynamic Lookups\"",
- "Complete \"Property Assignments\"",
- "Complete \"Arrays and Objects\"",
- "Complete \"Object Create\"",
- "Complete \"Dot New\"",
- "Complete \"Constructor Functions\"",
- "Complete \"Implicit This\"",
- "Note that you can skip the last challenge.",
- "Once you've completed these steps, move on to our next challenge."
- ],
- "challengeType": 2,
- "tests": [],
- "nameCn": "",
- "descriptionCn": [],
- "nameFr": "",
- "descriptionFr": [],
- "nameRu": "",
- "descriptionRu": [],
- "nameEs": "",
- "descriptionEs": [],
- "namePt": "",
- "descriptionPt": []
- },
- {
- "id": "bd7129d8c441eddfbeb5bddf",
- "name": "Waypoint: Practice Functional Programming",
- "dashedName": "waypoint-practice-functional-programming",
- "difficulty": 0.01,
- "challengeSeed": ["129169463"],
- "description": [
- "Functional programming holds the key to unlocking JavaScript's powerful asynchronous features.",
- "Jafar Husain's interactive Functional Programming course will familiarize you with the various ways you can recombine these functions.",
- "Functional programming in JavaScript involves using five key functions: \"map\", \"reduce\", \"filter\", \"concatAll\", and \"zip\".",
- "Click here to go to the challenge: http://jhusain.github.io/learnrx/.",
- "You only need to complete the first 27 steps of this tutorial.",
- "This challenge will take several hours, but don't worry. Jafar's website will save your progress (using your browser's local storage) so you don't need to finish it in one sitting.",
- "If you've spent several minutes on one of these challenges, and still can't figure out its correct answer, you can click \"show answer\", then click \"run\" to advance to the next challenge. Be sure to read the correct answer and make sure you understand it before moving on."
- ],
- "challengeType": 2,
- "tests": [],
- "nameCn": "",
- "descriptionCn": [],
- "nameFr": "",
- "descriptionFr": [],
- "nameRu": "",
- "descriptionRu": [],
- "nameEs": "",
- "descriptionEs": [],
- "namePt": "",
- "descriptionPt": []
- },
- {
- "id":"cf1111c1c14feddfaeb4bdef",
- "name":"Creating Classes",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c13feddfaeb4bdef",
- "name":"Static Properties",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c13feddfaeb5bdef",
- "name":"Dynamic Properties",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c13feddfaeb6bdef",
- "name":"Instantiation",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c13feddfaeb7bdef",
- "name":"Closures",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c13feddfaeb8bdef",
- "name":"Public Properties",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c13feddfaeb9bdef",
- "name":"Inheritance",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c14feddfaeb1bdef",
- "name":"Prototypical Inheritance",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c14feddfaeb2bdef",
- "name":"Constructors",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c14feddfaeb3bdef",
- "name":"Factories",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c14feddfaeb5bdef",
- "name":"Pure Functions",
- "Note":"May need a waypoint before each topic to announce what it is :p",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c14feddfaeb6bdef",
- "name":"Currying Functions",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c14feddfaeb7bdef",
- "name":"Composition",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c14feddfaeb8bdef",
- "name":"Functors",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- },
- {
- "id":"cf1111c1c14feddfaeb9bdef",
- "name":"Currying Functions",
- "dashedName":"#",
- "difficulty":0,
- "tests":[
- "assert(1==2, '');"
- ],
- "challengeSeed":[
- "Under Construction"
- ],
- "challengeType":0
- }
]
}
diff --git a/seed/challenges/upper-intermediate-bonfires.json b/seed/challenges/upper-intermediate-bonfires.json
new file mode 100644
index 0000000000..104b0312e2
--- /dev/null
+++ b/seed/challenges/upper-intermediate-bonfires.json
@@ -0,0 +1,140 @@
+{
+ "name": "Upper Intermediate Algorithm Scripting",
+ "order": 0.011,
+ "challenges": [
+ {
+ "id": "a2f1d72d9b908d0bd72bb9f6",
+ "title": "Make a Person",
+ "difficulty": "3.01",
+ "description": [
+ "Fill in the object constructor with the methods specified in the tests.",
+ "Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).",
+ "All functions that take an argument have an arity of 1, and the argument will be a string.",
+ "These methods must be the only available means for interacting with the object.",
+ "Remember to use RSAP if you get stuck. Try to pair program. Write your own code."
+ ],
+ "challengeSeed": [
+ "var Person = function(firstAndLast) {",
+ " return firstAndLast;",
+ "};",
+ "",
+ "var bob = new Person('Bob Ross');",
+ "bob.getFullName();"
+ ],
+ "tests": [
+ "expect(Object.keys(bob).length).to.eql(6);",
+ "expect(bob instanceof Person).to.be.true;",
+ "expect(bob.firstName).to.be.undefined();",
+ "expect(bob.lastName).to.be.undefined();",
+ "expect(bob.getFirstName()).to.eql('Bob');",
+ "expect(bob.getLastName()).to.eql('Ross');",
+ "expect(bob.getFullName()).to.eql('Bob Ross');",
+ "bob.setFirstName('Happy');",
+ "expect(bob.getFirstName()).to.eql('Happy');",
+ "bob.setLastName('Trees');",
+ "expect(bob.getLastName()).to.eql('Trees');",
+ "bob.setFullName('George Carlin');",
+ "expect(bob.getFullName()).to.eql('George Carlin');",
+ "bob.setFullName('Bob Ross');"
+ ],
+ "MDNlinks": [
+ "Closures",
+ "Details of the Object Model"
+ ],
+ "type": "bonfire",
+ "challengeType": 5,
+ "nameCn": "",
+ "descriptionCn": [],
+ "nameFr": "",
+ "descriptionFr": [],
+ "nameRu": "",
+ "descriptionRu": [],
+ "nameEs": "",
+ "descriptionEs": [],
+ "namePt": "",
+ "descriptionPt": []
+ },
+ {
+ "id": "af4afb223120f7348cdfc9fd",
+ "title": "Map the Debris",
+ "dashedName": "bonfire-map-the-debris",
+ "difficulty": "3.02",
+ "description": [
+ "Return a new array that transforms the element's average altitude into their orbital periods.",
+ "The array will contain objects in the format {name: 'name', avgAlt: avgAlt}
.",
+ "You can read about orbital periods on wikipedia.",
+ "The values should be rounded to the nearest whole number. The body being orbited is Earth.",
+ "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418",
+ "Remember to use RSAP if you get stuck. Try to pair program. Write your own code."
+ ],
+ "challengeSeed": [
+ "function orbitalPeriod(arr) {",
+ " var GM = 398600.4418;",
+ " var earthRadius = 6367.4447;",
+ " return arr;",
+ "}",
+ "",
+ "orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}]);"
+ ],
+ "tests": [
+ "expect(orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputnik\", orbitalPeriod: 86400}]);",
+ "expect(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])).to.eqls([{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]);"
+ ],
+ "MDNlinks": [
+ "Math.pow()"
+ ],
+ "type": "bonfire",
+ "challengeType": 5,
+ "nameCn": "",
+ "descriptionCn": [],
+ "nameFr": "",
+ "descriptionFr": [],
+ "nameRu": "",
+ "descriptionRu": [],
+ "nameEs": "",
+ "descriptionEs": [],
+ "namePt": "",
+ "descriptionPt": []
+ },
+ {
+ "id": "a3f503de51cfab748ff001aa",
+ "title": "Pairwise",
+ "difficulty": "3.03",
+ "description": [
+ "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.",
+ "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.",
+ "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!",
+ "Remember to use RSAP if you get stuck. Try to pair program. Write your own code."
+ ],
+ "challengeSeed": [
+ "function pairwise(arr, arg) {",
+ " return arg;",
+ "}",
+ "",
+ "pairwise([1,4,2,3,0,5], 7);"
+ ],
+ "tests": [
+ "expect(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);",
+ "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);",
+ "expect(pairwise([1,1,1], 2)).to.equal(1);",
+ "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);",
+ "expect(pairwise([], 100)).to.equal(0);"
+ ],
+ "MDNlinks": [
+ "Array.reduce()"
+ ],
+ "type": "bonfire",
+ "challengeType": 5,
+ "nameCn": "",
+ "descriptionCn": [],
+ "nameFr": "",
+ "descriptionFr": [],
+ "nameRu": "",
+ "descriptionRu": [],
+ "nameEs": "",
+ "descriptionEs": [],
+ "namePt": "",
+ "descriptionPt": []
+ }
+ ]
+}
diff --git a/seed/index.js b/seed/index.js
index 8c9b8e9361..334a11d3dc 100644
--- a/seed/index.js
+++ b/seed/index.js
@@ -2,13 +2,12 @@
require('babel/register');
require('dotenv').load();
var fs = require('fs'),
+ _ = require('lodash'),
path = require('path'),
app = require('../server/server'),
nonprofits = require('./nonprofits.json'),
jobs = require('./jobs.json');
-var challangesRegex = /^(bonfire:|waypoint:|zipline:|basejump:|hike:)/i;
-
function getFilesFor(dir) {
return fs.readdirSync(path.join(__dirname, '/' + dir));
}
@@ -18,30 +17,56 @@ var Nonprofit = app.models.Nonprofit;
var Job = app.models.Job;
var counter = 0;
var challenges = getFilesFor('challenges');
-var offerings = 2 + challenges.length;
+// plus two accounts for nonprofits and jobs seed.
+var numberToSave = challenges.length + 1;
-var CompletionMonitor = function() {
+function completionMonitor() {
+ // Increment counter
counter++;
- console.log('call ' + counter);
- if (counter < offerings) {
- return;
- } else {
+ // Exit if all challenges have been checked
+ if (counter >= numberToSave) {
process.exit(0);
}
-};
+
+ // Log where in the seed order we're currently at
+ console.log('Call: ' + counter + '/' + numberToSave);
+}
Challenge.destroyAll(function(err, info) {
if (err) {
- console.error(err);
+ throw err;
} else {
console.log('Deleted ', info);
}
challenges.forEach(function(file) {
- var challenges = require('./challenges/' + file).challenges
- .map(function(challenge) {
+ var challengeSpec = require('./challenges/' + file);
+ var order = challengeSpec.order;
+ var block = challengeSpec.name;
+
+ // challenge file has no challenges...
+ if (challengeSpec.challenges.length === 0) {
+ console.log('file %s has no challenges', file);
+ completionMonitor();
+ return;
+ }
+
+ var challenges = challengeSpec.challenges
+ .map(function(challenge, index) {
// NOTE(berks): add title for displaying in views
- challenge.title = challenge.name.replace(challangesRegex, '').trim();
+ challenge.name =
+ _.capitalize(challenge.type) +
+ ': ' +
+ challenge.title.replace(/[^a-zA-Z0-9\s]/g, '');
+
+ challenge.dashedName = challenge.name
+ .toLowerCase()
+ .replace(/\:/g, '')
+ .replace(/\s/g, '-');
+ challenge.order = order;
+ challenge.suborder = index + 1;
+ challenge.block = block;
+
return challenge;
});
@@ -49,10 +74,10 @@ Challenge.destroyAll(function(err, info) {
challenges,
function(err) {
if (err) {
- console.log(err);
+ throw err;
} else {
console.log('Successfully parsed %s', file);
- CompletionMonitor();
+ completionMonitor(err);
}
}
);
@@ -67,28 +92,28 @@ Nonprofit.destroyAll(function(err, info) {
}
Nonprofit.create(nonprofits, function(err, data) {
if (err) {
- console.log(err);
+ throw err;
} else {
console.log('Saved ', data);
}
- CompletionMonitor();
+ completionMonitor(err);
console.log('nonprofits');
});
});
Job.destroyAll(function(err, info) {
if (err) {
- console.error(err);
+ throw err;
} else {
console.log('Deleted ', info);
}
Job.create(jobs, function(err, data) {
if (err) {
- console.log(err);
+ console.log('error: ', err);
} else {
console.log('Saved ', data);
}
console.log('jobs');
- CompletionMonitor();
+ completionMonitor(err);
});
});
diff --git a/server/boot/challenge.js b/server/boot/challenge.js
index d88f2acec0..feea89818a 100644
--- a/server/boot/challenge.js
+++ b/server/boot/challenge.js
@@ -1,17 +1,24 @@
-var R = require('ramda'),
- Rx = require('rx'),
- assign = require('object.assign'),
- debug = require('debug')('freecc:challenges'),
- utils = require('../utils'),
+import _ from 'lodash';
+import moment from 'moment';
+import R from 'ramda';
+import { Observable } from 'rx';
+import assign from 'object.assign';
+import debugFactory from 'debug';
+import utils from '../utils';
- // this would be so much cleaner with destructering...
- saveUser = require('../utils/rx').saveUser,
- observableQueryFromModel = require('../utils/rx').observableQueryFromModel,
+import {
+ saveUser,
+ observeMethod,
+ observableQueryFromModel
+} from '../utils/rx';
- userMigration = require('../utils/middleware').userMigration,
- ifNoUserRedirectTo = require('../utils/middleware').ifNoUserRedirectTo,
- ifNoUserSend = require('../utils/middleware').ifNoUserSend;
+import {
+ userMigration,
+ ifNoUserRedirectTo,
+ ifNoUserSend
+} from '../utils/middleware';
+const debug = debugFactory('freecc:challenges');
var challengeMapWithNames = utils.getChallengeMapWithNames();
var challengeMapWithIds = utils.getChallengeMapWithIds();
var challengeMapWithDashedNames = utils.getChallengeMapWithDashedNames();
@@ -22,6 +29,10 @@ var unDasherize = utils.unDasherize;
var getMDNLinks = utils.getMDNLinks;
+function numberWithCommas(x) {
+ return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+}
+
function updateUserProgress(user, challengeId, completedChallenge) {
var alreadyCompleted = user.completedChallenges.some(({ id }) => {
return id === challengeId;
@@ -37,12 +48,18 @@ function updateUserProgress(user, challengeId, completedChallenge) {
}
module.exports = function(app) {
- var router = app.loopback.Router();
- var Challenge = app.models.Challenge;
- var User = app.models.User;
- var redirectNonUser =
- ifNoUserRedirectTo('/challenges/learn-how-free-code-camp-works');
- var send200toNonUser = ifNoUserSend(true);
+ const router = app.loopback.Router();
+
+ const Challenge = app.models.Challenge;
+ const findChallenge$ = observeMethod(Challenge, 'find');
+
+ const User = app.models.User;
+ const userCount$ = observeMethod(User, 'count');
+
+ const send200toNonUser = ifNoUserSend(true);
+ const redirectNonUser = ifNoUserRedirectTo(
+ '/challenges/learn-how-free-code-camp-works'
+ );
router.post(
'/completed-challenge/',
@@ -182,7 +199,7 @@ module.exports = function(app) {
.map(function(key) {
return challengeMapWithIds[key]
.filter(function(elem) {
- return elem === ('' + challenge.id);
+ return elem === '' + challenge.id;
})
.map(function() {
return key;
@@ -266,7 +283,7 @@ module.exports = function(app) {
}
})
.withLatestFrom(
- Rx.Observable.just(req.user),
+ Observable.just(req.user),
function(pairedWith, user) {
return {
user: user,
@@ -289,7 +306,7 @@ module.exports = function(app) {
// not iterate users
.flatMap(function(dats) {
debug('flatmap');
- return Rx.Observable.from([dats.user, dats.pairedWith]);
+ return Observable.from([dats.user, dats.pairedWith]);
})
// save user
.flatMap(function(user) {
@@ -392,7 +409,7 @@ module.exports = function(app) {
);
}
})
- .withLatestFrom(Rx.Observable.just(req.user), function(pairedWith, user) {
+ .withLatestFrom(Observable.just(req.user), function(pairedWith, user) {
return {
user: user,
pairedWith: pairedWith
@@ -408,7 +425,7 @@ module.exports = function(app) {
);
})
.flatMap(function({ user, pairedWith }) {
- return Rx.Observable.from([user, pairedWith]);
+ return Observable.from([user, pairedWith]);
})
// save users
.flatMap(function(user) {
@@ -428,50 +445,76 @@ module.exports = function(app) {
);
}
- function challengeMap(req, res, next) {
- var completedList = [];
+ function challengeMap({ user = {} }, res, next) {
+ const daysRunning = moment().diff(new Date('10/15/2014'), 'days');
- if (req.user) {
- completedList = req.user.completedChallenges;
- }
+ // if user
+ // get the id's of all the users completed challenges
+ const completedChallenges = !user.completedChallenges ?
+ [] :
+ _.uniq(user.completedChallenges).map(({ id }) => id);
- var noDuplicatedChallenges = R.uniq(completedList);
+ const camperCount$ = userCount$()
+ .map(camperCount => numberWithCommas(camperCount));
- var completedChallengeList = noDuplicatedChallenges
- .map(function(challenge) {
- // backwards compatibility
- return (challenge.id || challenge._id);
- });
- var challengeList = utils.
- getChallengeMapForDisplay(completedChallengeList);
+ const query = {
+ order: [
+ 'order ASC',
+ 'suborder ASC'
+ ]
+ };
- Object.keys(challengeList).forEach(function(key) {
- challengeList[key].completed = challengeList[key]
- .challenges.filter(function(elem) {
- // backwards compatibility hack
- return completedChallengeList.indexOf(elem.id || elem._id) > -1;
- });
- });
+ // create a stream of all the challenges
+ const challenge$ = findChallenge$(query)
+ .flatMap(challenges => Observable.from(challenges))
+ .shareReplay();
- function numberWithCommas(x) {
- return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
- }
+ // create a stream of an array of all the challenge blocks
+ const blocks$ = challenge$
+ // mark challenge completed
+ .map(challenge => {
+ if (completedChallenges.indexOf(challenge.id) !== -1) {
+ challenge.completed = true;
+ }
+ return challenge;
+ })
+ // group challenges by block | returns a stream of observables
+ .groupBy(challenge => challenge.block)
+ // turn block group stream into an array
+ .flatMap(block$ => block$.toArray())
+ .map(blockArray => {
+ const completedCount = blockArray.reduce((sum, { completed }) => {
+ if (completed) {
+ return sum + 1;
+ }
+ return sum;
+ });
- var date1 = new Date('10/15/2014');
- var date2 = new Date();
- var timeDiff = Math.abs(date2.getTime() - date1.getTime());
- var daysRunning = Math.ceil(timeDiff / (1000 * 3600 * 24));
+ return {
+ name: blockArray[0].block,
+ dashedName: dasherize(blockArray[0].block),
+ challenges: blockArray,
+ completed: completedCount / blockArray.length * 100
+ };
+ })
+ // turn stream of blocks into a stream of an array
+ .toArray();
- User.count(function(err, camperCount) {
- if (err) { return next(err); }
-
- res.render('challengeMap/show', {
- daysRunning: daysRunning,
- camperCount: numberWithCommas(camperCount),
- title: "A map of all Free Code Camp's Challenges",
- challengeList: challengeList,
- completedChallengeList: completedChallengeList
- });
- });
+ Observable.combineLatest(
+ camperCount$,
+ blocks$,
+ (camperCount, blocks) => ({ camperCount, blocks })
+ )
+ .subscribe(
+ ({ camperCount, blocks }) => {
+ res.render('challengeMap/show', {
+ blocks,
+ daysRunning,
+ camperCount,
+ title: "A map of all Free Code Camp's Challenges"
+ });
+ },
+ next
+ );
}
};
diff --git a/server/boot/home.js b/server/boot/home.js
index 2a75265e1a..1e40fb01a3 100644
--- a/server/boot/home.js
+++ b/server/boot/home.js
@@ -10,13 +10,18 @@ module.exports = function(app) {
app.use(router);
function index(req, res, next) {
- if (req.user && !req.user.picture) {
- req.user.picture = defaultProfileImage;
+ if (req.user)
+ if (!req.user.picture) {
+ req.user.picture = defaultProfileImage;
- req.user.save(function(err) {
- if (err) { return next(err); }
- res.render('home', { title: message });
- });
+ req.user.save(function (err) {
+ if (err) {
+ return next(err);
+ }
+ res.render('get-started', {title: message});
+ });
+ } else {
+ res.render('resources/get-started', {title: message});
} else {
res.render('home', { title: message });
}
diff --git a/server/boot/randomAPIs.js b/server/boot/randomAPIs.js
index 2b879c2341..13fd84e3c7 100644
--- a/server/boot/randomAPIs.js
+++ b/server/boot/randomAPIs.js
@@ -30,6 +30,7 @@ module.exports = function(app) {
router.get('/jobs-form', jobsForm);
router.get('/unsubscribe/:email', unsubscribe);
router.get('/unsubscribed', unsubscribed);
+ router.get('/get-started', getStarted);
app.use(router);
@@ -259,6 +260,12 @@ module.exports = function(app) {
});
}
+ function getStarted(req, res) {
+ res.render('resources/get-started', {
+ title: 'How to get started with Free Code Camp'
+ });
+ }
+
function githubCalls(req, res, next) {
var githubHeaders = {
headers: {
diff --git a/server/boot/user.js b/server/boot/user.js
index aa925e6ac9..77cd45ddfc 100644
--- a/server/boot/user.js
+++ b/server/boot/user.js
@@ -44,9 +44,7 @@ module.exports = function(app) {
router.post('/reset/:token', postReset);
router.get('/email-signup', getEmailSignup);
router.get('/email-signin', getEmailSignin);
-
router.get('/account/api', getAccountAngular);
- router.post('/account/profile', postUpdateProfile);
router.post('/account/password', postUpdatePassword);
router.post('/account/delete', postDeleteAccount);
router.get('/account/unlink/:provider', getOauthUnlink);
@@ -167,11 +165,11 @@ module.exports = function(app) {
isMigrationGrandfathered: user.isMigrationGrandfathered,
isGithubCool: user.isGithubCool,
location: user.location,
- githubProfile: user.githubProfile,
- linkedinProfile: user.linkedinProfile,
- codepenProfile: user.codepenProfile,
- facebookProfile: user.facebookProfile,
- twitterHandle: user.twitterHandle,
+ githubProfile: user.github,
+ linkedinProfile: user.linkedin,
+ googleProfile: user.google,
+ facebookProfile: user.facebook,
+ twitterHandle: user.twitter,
bio: user.bio,
picture: user.picture,
progressTimestamps: user.progressTimestamps,
@@ -185,80 +183,6 @@ module.exports = function(app) {
);
}
- /**
- * POST /account/profile
- * Update profile information.
- */
-
- function postUpdateProfile(req, res, next) {
-
- User.findById(req.user.id, function(err) {
- if (err) { return next(err); }
- var errors = req.validationErrors();
- if (errors) {
- req.flash('errors', errors);
- return res.redirect('/account');
- }
-
- User.findOne({
- where: { email: req.body.email }
- }, function(err, existingEmail) {
- if (err) {
- return next(err);
- }
- var user = req.user;
- if (existingEmail && existingEmail.email !== user.email) {
- req.flash('errors', {
- msg: 'An account with that email address already exists.'
- });
- return res.redirect('/account');
- }
- User.findOne(
- { where: { username: req.body.username } },
- function(err, existingUsername) {
- if (err) {
- return next(err);
- }
- var user = req.user;
- if (
- existingUsername &&
- existingUsername.username !== user.username
- ) {
- req.flash('errors', {
- msg: 'An account with that username already exists.'
- });
- return res.redirect('/account');
- }
- var body = req.body || {};
- user.facebookProfile = body.facebookProfile.trim() || '';
- user.linkedinProfile = body.linkedinProfile.trim() || '';
- user.codepenProfile = body.codepenProfile.trim() || '';
- user.twitterHandle = body.twitterHandle.trim() || '';
- user.bio = body.bio.trim() || '';
-
- user.save(function(err) {
- if (err) {
- return next(err);
- }
- updateUserStoryPictures(
- user.id.toString(),
- user.picture,
- user.username,
- function(err) {
- if (err) { return next(err); }
- req.flash('success', {
- msg: 'Profile information updated.'
- });
- res.redirect('/account');
- }
- );
- });
- }
- );
- });
- });
- }
-
/**
* POST /account/password
* Update current password.
diff --git a/server/passport-providers.js b/server/passport-providers.js
index ddd29f64db..5ffcbf1a09 100644
--- a/server/passport-providers.js
+++ b/server/passport-providers.js
@@ -141,5 +141,19 @@ module.exports = {
clientSecret: process.env.GITHUB_SECRET,
scope: ['email'],
failureFlash: true
+ },
+ 'github-link': {
+ provider: 'github',
+ authScheme: 'oauth2',
+ module: 'passport-github',
+ authPath: '/link/github',
+ callbackURL: '/link/github/callback',
+ callbackPath: '/link/github/callback',
+ successRedirect: successRedirect,
+ failureRedirect: failureRedirect,
+ clientID: process.env.GITHUB_ID,
+ clientSecret: process.env.GITHUB_SECRET,
+ scope: ['email'],
+ failureFlash: true
}
};
diff --git a/server/server.js b/server/server.js
index 93a0f06d8d..bf0cb8c396 100755
--- a/server/server.js
+++ b/server/server.js
@@ -102,7 +102,7 @@ var passportOptions = {
userObj.email = email;
}
- if (provider === 'github-login') {
+ if (/github/.test(provider)) {
setProfileFromGithub(userObj, profile, profile._json);
}
return userObj;
diff --git a/server/utils/index.js b/server/utils/index.js
index 784aa71366..72b37da98b 100644
--- a/server/utils/index.js
+++ b/server/utils/index.js
@@ -19,17 +19,6 @@ var allNonprofitNames,
challengeMapWithNames, allChallengeIds,
challengeMapWithDashedNames;
-Array.zip = function(left, right, combinerFunction) {
- var counter,
- results = [];
-
- for (counter = 0; counter < Math.min(left.length, right.length); counter++) {
- results.push(combinerFunction(left[counter], right[counter]));
- }
-
- return results;
-};
-
(function() {
if (!challengeMap) {
var localChallengeMap = {};
@@ -75,8 +64,8 @@ module.exports = {
challengeMapForDisplay = {};
Object.keys(challengeMap).forEach(function(key) {
challengeMapForDisplay[key] = {
- name: challengeMap[key].name,
- dashedName: challengeMap[key].name.replace(/\s/g, '-'),
+ name: challengeMap[key].title,
+ dashedName: challengeMap[key].title.replace(/\s/g, '-'),
challenges: challengeMap[key].challenges,
completedCount: challengeMap[key].challenges
};
diff --git a/server/views/account/account.jade b/server/views/account/account.jade
index 54c423dc10..22ad1b9975 100644
--- a/server/views/account/account.jade
+++ b/server/views/account/account.jade
@@ -3,113 +3,50 @@ block content
script.
var challengeName = 'Account View'
.panel.panel-info(ng-controller="profileValidationController")
- .panel-heading.text-center Update your portfolio here:
+ .panel-heading.text-center Manage your account here
.panel-body
- if (!user.isGithubCool)
- .row
- .col-xs-12
- .text-left.btn-info.btn.btn-block.btn-link-social(href='http://www.freecodecamp.com/challenges/waypoint-join-our-chat-room')
- span Link your account to GitHub to update your portfolio page. Click here if you don’t have a GitHub account yet.
- .row
- .col-xs-12
- a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/auth/github')
- i.fa.fa-github
- | Link GitHub with my account
- else
- .row
- .col-xs-12
- a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/auth/github')
- i.fa.fa-github
- | Update Github Info
-
.row
+ .col-xs-12
+ if (!user.isGithubCool)
+ a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/auth/github')
+ i.fa.fa-github
+ | Link my GitHub to unlock this profile
+ else
+ a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/link/github')
+ i.fa.fa-github
+ | Update my profile from Github
+
+ if (!user.twitter)
+ .col-xs-12
+ a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/link/twitter')
+ i.fa.fa-twitter
+ | Add my Twitter to my profile
+ if (!user.facebook)
+ .col-xs-12
+ a.btn.btn-lg.btn-block.btn-facebook.btn-link-social(href='/link/facebook')
+ i.fa.fa-facebook
+ | Add my Facebook to my profile
+ if (!user.linkedin)
+ .col-xs-12
+ a.btn.btn-lg.btn-block.btn-linkedin.btn-link-social(href='/link/linkedin')
+ i.fa.fa-linkedin
+ | Add my LinkedIn to my profile
+ if (!user.google)
+ .col-xs-12
+ a.btn.btn-lg.btn-block.btn-google-plus.btn-link-social(href='/link/google')
+ i.fa.fa-google-plus
+ | Add my Google+ to my profile
+ .big-spacer
.col-xs-12
- form.form-horizontal(action='/account/profile', method='POST', novalidate='novalidate', name='profileForm' ng-show="asyncComplete")
- input(type='hidden', name='_csrf', value=_csrf)
- .form-group
- label.col-sm-3.col-sm-offset-1.control-label(for='bio') Bio (140 characters)
- .col-sm-4
- input.form-control(type='text', name='bio', autocomplete="off", ng-model='user.bio', ng-maxlength='140', id='bio')
- .col-sm-4.col-sm-offset-5(ng-cloak, ng-show='profileForm.bio.$error.maxlength && !profileForm.bio.$pristine')
- alert(type='danger')
- span.ion-close-circled
- | Your bio must be fewer than 140 characters.
- .form-group
- label.col-sm-3.col-sm-offset-1.control-label(for='email') Twitter
- .col-sm-4
- .input-group.twitter-input
- span.input-group-addon @
- input.form-control(type='text', name='twitterHandle', autocomplete="off", id='twitterHandle', ng-model='user.twitterHandle', ng-maxlength='15', ng-pattern="/^[A-z0-9_]+$/")
- .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.twitterHandle.$error.pattern")
- alert(type='danger')
- span.ion-close-circled
- | Your Twitter handle should only contain letters, numbers and underscores (az10_).
- .col-sm-4.col-sm-offset-5(ng-cloak, ng-show='profileForm.twitterHandle.$error.maxlength && !profileForm.twitterHandle.$pristine')
- alert(type='danger')
- span.ion-close-circled
- | Your name must be fewer than 15 characters.
-
- .form-group
- label.col-sm-3.col-sm-offset-1.control-label(for='email') CodePen
- .col-sm-4
- input.form-control(type='url', name='codepenProfile', id='codepenProfile', autocomplete="off", ng-model='user.codepenProfile', placeholder='http://')
- .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.codepenProfile.$error.url && !profileForm.codepenProfile.$pristine")
- alert(type='danger')
- span.ion-close-circled
- | Please enter a valid URL format (http://www.example.com).
-
- .form-group
- label.col-sm-3.col-sm-offset-1.control-label(for='email') LinkedIn
- .col-sm-4
- input.form-control(type='url', name='linkedinProfile', id='linkedinProfile', autocomplete="off", ng-model='user.linkedinProfile', placeholder='http://')
- .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.linkedinProfile.$error.url && !profileForm.linkedinProfile.$pristine")
- alert(type='danger')
- span.ion-close-circled
- | Please enter a valid URL format (http://www.example.com).
-
- .form-group
- label.col-sm-3.col-sm-offset-1.control-label(for='email') Facebook
- .col-sm-4
- input.form-control(type='url', name='facebookProfile', id='facebookProfile', autocomplete="off", ng-model='user.facebookProfile', placeholder='http://')
- .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.facebookProfile.$error.url && !profileForm.facebookProfile.$pristine")
- alert(type='danger')
- span.ion-close-circled
- | Please enter a valid URL format (http://www.example.com).
-
- button.btn.btn-lg.btn-block.btn-primary.btn-link-social(type='submit', ng-disabled='!user.isGithubCool || profileForm.$invalid')
- span.ion-edit
- | Update my info
-
- .panel.panel-info
- .panel-heading.text-center Manage your account here:
- .panel-body
- if (!user.google || !user.facebook || !user.linkedin || !user.twitter)
- if (!user.twitter)
- .col-xs-12
- a.btn.btn-lg.btn-block.btn-twitter.btn-link-social.disabled(href='#')
- i.fa.fa-twitter
- | Link Twitter with my account
- if (!user.google)
- .col-xs-12
- a.btn.btn-lg.btn-block.btn-google-plus.btn-link-social.disabled(href='#')
- i.fa.fa-google-plus
- | Link Google with my account
- if (!user.facebook)
- .col-xs-12
- a.btn.btn-lg.btn-block.btn-facebook.btn-link-social.disabled(href='#')
- i.fa.fa-facebook
- | Link Facebook with my account
- if (!user.linkedin)
- .col-xs-12
- a.btn.btn-lg.btn-block.btn-linkedin.btn-link-social.disabled(href='#')
- i.fa.fa-linkedin
- | Link LinkedIn with my account
- .col-xs-12
a.btn.btn-lg.btn-block.btn-warning.btn-link-social(href='/logout')
span.ion-android-exit
| Sign me out of Free Code Camp
- .col-xs-12
- a.btn.btn-lg.btn-block.btn-danger.confirm-deletion.btn-link-social
+ .col-xs-12
+ a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='mailto:team@freecodecamp.com')
+ span.ion-email
+ | Email us at team@freecodecamp.com
+ .col-xs-12
+ a.btn.btn-lg.btn-block.btn-danger.btn-link-social.confirm-deletion
span.ion-trash-b
| Delete my Free Code Camp account
script.
diff --git a/server/views/account/show.jade b/server/views/account/show.jade
index bc65c80b17..ce58b8ba4a 100644
--- a/server/views/account/show.jade
+++ b/server/views/account/show.jade
@@ -10,7 +10,7 @@ block content
if (user && user.username === username)
.row.text-center
.col-xs-12.col-sm-10.col-sm-offset-1
- a.btn.btn-big.btn-primary.btn-block(href="/account") Update my portfolio page or manage my account
+ a.btn.btn-big.btn-primary.btn-block(href="/account") Manage my account
.button-spacer
.col-xs-12.col-sm-10.col-sm-offset-1
a.btn.btn-big.btn-success.btn-block(href="/signout") Sign out of Free Code Camp
@@ -23,16 +23,16 @@ block content
else
img.img-center.img-responsive.public-profile-img(src='https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png')
h1.text-center.negative-5.profile-social-icons
- if (twitterHandle)
- a.fa.fa-twitter-square.text-primary(title="@#{username}'s Twitter Profile", href="http://twitter.com/#{twitterHandle}", target='_blank')
- if (githubProfile)
- a.fa.fa-github-square.text-primary(title="@#{username}'s GitHub Profile", href=githubProfile, target='_blank')
- if (codepenProfile)
- a.ion-social-codepen.text-primary(title="@#{username}'s CodePen Profile", href=codepenProfile, target='_blank')
- if (linkedinProfile)
- a.fa.fa-linkedin-square.text-primary(title="@#{username}'s LinkedIn Profile", href=linkedinProfile, target='_blank')
- if (facebookProfile)
- a.fa.fa-facebook-square.text-primary(title="@#{username}'s Facebook Profile", href=facebookProfile, target='_blank')
+ if (twitter)
+ a.fa.fa-twitter-square.text-primary(title="@#{username}'s Twitter Profile", href=twitter, target='_blank')
+ if (github)
+ a.fa.fa-github-square.text-primary(title="@#{username}'s GitHub Profile", href=github, target='_blank')
+ if (linkedin)
+ a.fa.fa-linkedin-square.text-primary(title="@#{username}'s LinkedIn Profile", href=linkedin, target='_blank')
+ if (facebook)
+ a.fa.fa-facebook-square.text-primary(title="@#{username}'s Facebook Profile", href=facebook, target='_blank')
+ if (google)
+ a.fa.fa-google-square.text-primary(title="@#{username}'s Google Profile", href=google, target='_blank')
.visible-md.visible-lg
.col-xs-12.col-sm-12.col-md-4.text-justify
h1.flat-top.wrappable= name
@@ -77,8 +77,8 @@ block content
.row
.hidden-xs.col-sm-12.text-center
.row.text-primary
- h4.col-sm-6.text-right Longest Streak: #{longestStreak + longestStreak === 1 ? ' day' : ' days'}
- h4.col-sm-6.text-left Current Streak: #{currentStreak + currentStreak === 1 ? ' day' : ' days'}
+ h4.col-sm-6.text-right Longest Streak: #{longestStreak} #{longestStreak + longestStreak === 1 ? ' day' : ' days'}
+ h4.col-sm-6.text-left Current Streak: #{currentStreak} #{currentStreak + currentStreak === 1 ? ' day' : ' days'}
if (challenges.length > 0)
diff --git a/server/views/challengeMap/show.jade b/server/views/challengeMap/show.jade
index 77b42ca672..22927bdedb 100644
--- a/server/views/challengeMap/show.jade
+++ b/server/views/challengeMap/show.jade
@@ -1,8 +1,7 @@
extends ../layout
block content
script.
- var completedChallenges = !{JSON.stringify(completedChallengeList)};
- var challengeList = !{JSON.stringify(challengeList)};
+ var challenges = !{JSON.stringify(challenges)};
.bg-danger.default-border-radius
p
a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/beta' target='_blank') You're using our experimental beta site. None of your progress here will be saved. Please click this to learn more.
@@ -28,10 +27,10 @@ block content
.col-xs-12.col-sm-8.col-sm-offset-2
h3 800 Hours of Practice:
ol
- for challengeBlock in challengeList
+ for challengeBlock in blocks
.row
if (user)
- if (challengeBlock.completed.length === challengeBlock.challenges.length)
+ if (challengeBlock.completed === 100)
.hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center.large-p.negative-10
.col-xs-12.col-sm-9.col-md-10
li.large-p.faded.negative-10
@@ -39,7 +38,7 @@ block content
else
.hidden-xs.col-sm-3.col-md-2
.progress.progress-bar-padding.text-center.thin-progress-bar
- .progress-bar(role='progressbar', aria-valuenow=((challengeBlock.completed.length / challengeBlock.challenges.length) * 100), aria-valuemin='0', aria-valuemax='100', style='width: ' + ((challengeBlock.completed.length / challengeBlock.challenges.length) * 100) + '%;')
+ .progress-bar(role='progressbar', aria-valuenow=(challengeBlock.completed), aria-valuemin='0', aria-valuemax='100', style='width: ' + challengeBlock.completed + '%;')
.col-xs-12.col-sm-9.col-md-10
li.large-p.negative-10
a(href='#' + challengeBlock.dashedName)= challengeBlock.name
@@ -74,7 +73,7 @@ block content
li.large-p.negative-10 300-hour Nonprofit Project
hr
- for challengeBlock in challengeList
+ for challengeBlock in blocks
.row
a(href='#' name=challengeBlock.dashedName)
.spacer.negative-55
@@ -86,12 +85,12 @@ block content
.col-xs-12
ol
for challenge in challengeBlock.challenges
- if completedChallengeList.indexOf(challenge.id || challenge._id) > -1
+ if challenge.completed
.row
.hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center.large-p.negative-10
.col-xs-12.col-sm-9.col-md-10
li.faded.large-p.negative-10
- a(href="/challenges/#{challenge.dashedName}")= challenge.name
+ a(href="/challenges/#{challenge.dashedName}")= challenge.title
else
.row
@@ -99,7 +98,7 @@ block content
span.negative-10
.col-xs-12.col-sm-9.col-md-10
li.large-p.negative-10
- a(href="/challenges/#{challenge.dashedName}")= challenge.name
+ a(href="/challenges/#{challenge.dashedName}")= challenge.title
//#announcementModal.modal(tabindex='-1')
// .modal-dialog.animated.fadeInUp.fast-animation
diff --git a/server/views/home.jade b/server/views/home.jade
index e5e09f19bb..f08d7528ca 100644
--- a/server/views/home.jade
+++ b/server/views/home.jade
@@ -1,8 +1,5 @@
extends layout
block content
- .bg-danger.default-border-radius
- p
- a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/beta' target='_blank') You're using our experimental beta site. None of your progress here will be saved. Please click this to learn more.
.jumbotron
.text-center
h1.hug-top Code with Us
@@ -10,7 +7,7 @@ block content
.row
.col-xs-12.col-sm-12.col-md-3
h3.nowrap Get Connected
- img.img-responsive.landing-icon.img-center(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_connect.svg.gz', alt='Get great references and connections for your reto help you get a job')
+ img.img-responsive.landing-icon.img-center(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_connect.svg.gz', alt='Get great references and connections to start your software engineer career')
p.landing-p Join a community of busy, motivated professionals.
.col-xs-12.col-sm-12.col-md-3
h3.nowrap Learn JavaScript
@@ -27,13 +24,10 @@ block content
.big-break
.row
.col-xs-12.col-sm-8.col-sm-offset-2
- if (user)
- a.btn.btn-cta.signup-btn.btn-block(href="/challenges") Go to my next challenge
- else
- a.btn.btn-cta.signup-btn.btn-block(href="/login") Start learning to code (it's free)
+ a.btn.btn-cta.signup-btn.btn-block(href="/login") Start learning to code (it's free)
.button-spacer
a.btn.btn-cta.btn-success.btn-block(href="/nonprofits") My nonprofit needs coding help
- h2 As seen in:
+ h2 As featured in
img.img-center.img-responsive(src='https://s3.amazonaws.com/freecodecamp/as-seen-on.png')
.spacer
h2 We're a proven way to start your software engineering career:
diff --git a/server/views/partials/navbar.jade b/server/views/partials/navbar.jade
index 85996b95aa..d7861a224d 100644
--- a/server/views/partials/navbar.jade
+++ b/server/views/partials/navbar.jade
@@ -4,7 +4,7 @@ nav.navbar.navbar-default.navbar-fixed-top.nav-height
.col-xs-12
span.hamburger-text Menu
a.navbar-brand(href='/')
- img.img-responsive.nav-logo(src='https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg.gz', alt='learn to code javascript at Free Code Camp logo')
+ img.img-responsive.nav-logo(src='https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg', alt='learn to code javascript at Free Code Camp logo')
.collapse.navbar-collapse
ul.nav.navbar-nav.navbar-right.hamburger-dropdown
li
diff --git a/server/views/resources/get-started.jade b/server/views/resources/get-started.jade
new file mode 100644
index 0000000000..2b4692042f
--- /dev/null
+++ b/server/views/resources/get-started.jade
@@ -0,0 +1,167 @@
+extends ../layout
+block content
+ .jumbotron
+ h2.text-center This 10-minute guide will help you get the most out of Free Code Camp.
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/RlEk2IF.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption Welcome to Free Code Camp. We're an open source community of busy people who learn to code, then practice by building projects for nonprofits.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/pYsTbjI.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption Learning to code is hard. To succeed, you'll need lots practice and support. That's why we've created a rigorous curriculum and supportive community.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/Gtf8aIq.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption Free Code Code camp is self-paced, browser-based, and free.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/D7Y5luw.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption If you can finish Free Code Camp, you will be able to get a coding job. There are thousands of coding jobs currently going unfilled, and the demand for coders grows every year.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/dLx8nrg.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption During the first 800 hours of Free Code Camp, you'll learn technologies like HTML5, Node.js and databases.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/yXyxbDd.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption During the last 800 hours, you'll build several real-life projects for nonprofits.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/PprMPUx.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption By the time you finish, you'll have a job-winning portfolio of real apps that people use every day.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/EAR7Lvh.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption Now let's join Free Code Camp's chat rooms. You can come here any time of day to hang out, ask questions, or find another camper to pair program with.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/sign-up-for-github.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ a(href='https://github.com/join' target='_blank') Create an account with GitHub
+ | . Be sure to use your real email address - GitHub will keep this private.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/github-profile.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ | Click the pixel art in the upper right hand corner of GitHub, then choose settings. Upload a picture of yourself. A picture of your face works best. This is how people will see you in our chat rooms, so put your best foot forward. You can add your city and your name if you want.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/star-repository.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ a(href='//github.com/freecodecamp/freecodecamp' target='_blank') Go to Free Code Camp's open-source repository
+ | and "star" it. "Starring" is the GitHub equivalent of "liking" something.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/join-gitter.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ | Now that you have a GitHub account, you can
+ a(href='https://gitter.im/FreeCodeCamp/FreeCodeCamp' target='_blank') join our main chat room by logging in with GitHub
+ | . Introduce yourself by saying "Hello world!". Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/gitter-notifications.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ | Our chat rooms are extremely active. You should change your settings so you're only notified if someone mentions you.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/private-messages.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption Please note that all of our chat rooms are visible to the public. If you need to share sensitive information, such as an email address or phone number, do it in a private message.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/keep-chat-open.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption Keep our chat room open while you work through our challenges. That way, you can ask for help if you get stuck. You can also socialize with other campers when you feel like taking a break.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/download-gitter-app.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ a(href='https://gitter.im/apps' target='_blank') You can also download the chat room app to your computer or phone
+ | .
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/challenge-map.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ | Click the "Map" button in your upper right hand corner. Our map shows all our coding challenges. We recommend that you complete these from top to bottom, at a sustainable pace.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/9NJfPQv.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption After you finish all of our challenges, you'll start building projects for nonprofits.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/wiki.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ | Click the "Wiki" button in your upper right hand corner. Our community has contributed lots of useful information to this searchable wiki.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/add-github-to-profile.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ | Check out your portfolio page. Click your picture your upper right hand corner. Before you can see your portfolio page, you'll need to link your GitHub account with Free Code Camp.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/check-public-profile.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption Your portfolio page shows your progress and how many Brownie Points you have. You can get Brownie Points by completing challenges and by helping other campers in our chat rooms. If you get Brownie Points on several days in a row, you'll get a streak.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/camper-news.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ | Click the "News" button in your upper right hand corner. You can browse links on Camper News and upvote ones that you enjoy.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/Elb3dfj.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption Our Campsites help you code with campers in your city. You can coordinate study groups or attend local coding events together.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/join-facebook-group.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ span.text-info Try this:
+ a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites' target='_blank') Find your city on this list
+ | . Click the "Join group" button to join your city's Facebook group. If your city isn't on this list,
+ a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/How-to-create-a-Campsite-for-your-city' target='_blank') follow these directions to create a Facebook group for your city
+ | .
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/join-campsite-gitter-room.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption
+ a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites' target='_blank') Go back to our list of Campsites
+ | and click "Gitter" to join your city's chat room.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/add-linkedin.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption You can
+ a(href='https://www.linkedin.com/profile/edit-education?school=Free+Code+Camp' target='_blank') add Free Code Camp to your LinkedIn education background
+ | . Set your graduation date as next year. For "Degree", type "Full Stack Web Development". For "Field of study", type "Computer Software Engineering". Then click "Save Changes".
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/6VtsD1K.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption Let's cover one last thing before you start working through our challenges: how to get help. Any time you get stuck or don't know what to do next: RSAP (Read, Search, Ask, Post).
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/99BfAcK.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption First, R - Read the documentation or error message. A key skill that good coders have is the ability to interpret and then follow instructions.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/google-search.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption If that didn't help, S - Search Google. Good Google queries take a lot of practice. When you search Google, you usually want to include the language or framework you're using. You also want to limit the results to a recent period.
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='https://s3.amazonaws.com/freecodecamp/ask-for-help.gif' alt='a gif showing how to install this')
+ p.large-p.gif-caption If that didn't help, A - Ask your friends. If you have trouble, you can ask your fellow campers in our
+ a(href='https://gitter.im/FreeCodeCamp/Help' target='_blank') help chat room
+ | .
+
+ .big-spacer
+ img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/rWeBOhF.jpg' alt='a gif showing how to install this')
+ p.large-p.gif-caption Finally if you still haven't found an answer to your question, P - Post on Stack Overflow. This is a popular question and answer site where you can get help with coding questions.
+
+ .big-spacer
+ h2.text-center Nicely done. Now you have all the tools you need to succeed. Happy coding!
+ .spacer
+ a.btn.btn-cta.signup-btn.btn-block(href="/map") Take me to my Challenge Map