From 94abc6cf5b914fa1080d9eda11f40f5d7bfa4082 Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Sat, 16 May 2015 00:39:43 -0400 Subject: [PATCH 1/3] Begin restructuring all Coursewares and Bonfires to one unified model and flow. --- controllers/challenge.js | 201 +++ controllers/resources.js | 34 +- models/Challenge.js | 16 +- models/User.js | 3 +- seed_data/challenges/basic_css.json | 0 seed_data/challenges/basic_html.json | 0 seed_data/challenges/basic_javascript.json | 1488 ++++++++++++++++++++ 7 files changed, 1734 insertions(+), 8 deletions(-) create mode 100644 controllers/challenge.js create mode 100644 seed_data/challenges/basic_css.json create mode 100644 seed_data/challenges/basic_html.json create mode 100644 seed_data/challenges/basic_javascript.json diff --git a/controllers/challenge.js b/controllers/challenge.js new file mode 100644 index 0000000000..398b31d535 --- /dev/null +++ b/controllers/challenge.js @@ -0,0 +1,201 @@ +/*eslint-disable no-unused-vars */ + +/** + * Created by nathanleniz on 5/15/15. + * Copyright (c) 2015, Free Code Camp + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +var debug = require('debug')('freecc:cntr:courseware'), + Challenge = require('./../models/Challenge'), + User = require('./../models/User'), + resources = require('./resources'), + R = require('ramda'), + moment = require('moment'); + +exports.showAllChallenges = function(req, res) { + var completedList = []; + if (req.user) { + completedList = req.user.completedCoursewares.map(function (elem) { + return elem._id; + }); + } + var noDuplicatedCoursewares = R.uniq(completedList); + var data = {}; + data.coursewareList = resources.allCoursewareNames(); + data.completedList = noDuplicatedCoursewares; + res.send(data); +}; + +exports.returnNextChallenge = function(req, res, next) { + if (!req.user) { + return res.redirect('../challenges/learn-how-free-code-camp-works'); + } + // find the user's current challenge and block + // look in that block and find the index of their current challenge + // if index + 1 <= block.challenges.length - 1 + // serve index + 1 challenge + // otherwise increment block key and serve the first challenge in that block + var nextChallengeName; + var challengeMapWithNames = resources.getChallengeMapWithNames(); + var challengeMapWithIds = resources.getChallengeMapWithIds(); + var challengeId = req.user.currentChallenge.challengeId; + var challengeBlock = req.user.currentChallenge.challengeBlock; + var indexOfChallenge = challengeMapWithIds[challengeBlock] + .indexOf(challengeId); + + if (indexOfChallenge + <= challengeMapWithIds[challengeBlock].length - 1) { + nextChallengeName = + challengeMapWithNames[challengeBlock][indexOfChallenge + 1]; + } else if (typeof challengeMapWithIds[challengeBlock + 1] !== 'undefined') { + nextChallengeName = R.head(challengeMapWithNames[challengeBlock + 1]); + } else { + req.flash('errors', { + msg: 'It looks like you have finished all of our challenges.' + + ' Great job! Now on to helping nonprofits!' + }); + nextChallengeName = R.head(challengeMapWithNames['0'].challenges); + } + var nameString = nextChallengeName.toLowerCase().replace(/\s/g, '-'); + return res.redirect('../challenges' + nameString); +}; + +exports.returnIndividualChallenge = function(req, res, next) { + var dashedName = req.params.challengeName; + + var challengeName = dashedName.replace(/\-/g, ' '); + + Challenge.find({'name': new RegExp(challengeName, 'i')}, + function(err, challengeFromMongo) { + if (err) { + next(err); + } + // Handle not found + if (challengeFromMongo.length < 1) { + req.flash('errors', { + msg: '404: We couldn\'t find a challenge with that name. ' + + 'Please double check the name.' + }); + return res.redirect('/challenges'); + } + var challenge = challengeFromMongo.pop(); + + // Redirect to full name if the user only entered a partial + var dashedNameFull = challenge.name.toLowerCase().replace(/\s/g, '-'); + if (dashedNameFull !== dashedName) { + return res.redirect('../challenges/' + dashedNameFull); + } + + var challengeType = { + 0: function() { + res.render('coursewares/showHTML', { + title: challenge.name, + dashedName: dashedName, + name: challenge.name, + brief: challenge.description[0], + details: challenge.description.slice(1), + tests: challenge.tests, + challengeSeed: challenge.challengeSeed, + verb: resources.randomVerb(), + phrase: resources.randomPhrase(), + compliment: resources.randomCompliment(), + coursewareHash: challenge._id, + environment: resources.whichEnvironment(), + challengeType: challenge.challengeType + }); + }, + + 1: function() { + res.render('coursewares/showJS', { + title: challenge.name, + dashedName: dashedName, + name: challenge.name, + brief: challenge.description[0], + details: challenge.description.slice(1), + tests: challenge.tests, + challengeSeed: challenge.challengeSeed, + verb: resources.randomVerb(), + phrase: resources.randomPhrase(), + compliment: resources.randomCompliment(), + coursewareHash: challenge._id, + challengeType: challenge.challengeType + }); + }, + + 2: function() { + res.render('coursewares/showVideo', { + title: challenge.name, + dashedName: dashedName, + name: challenge.name, + details: challenge.description, + tests: challenge.tests, + video: challenge.challengeSeed[0], + verb: resources.randomVerb(), + phrase: resources.randomPhrase(), + compliment: resources.randomCompliment(), + coursewareHash: challenge._id, + challengeType: challenge.challengeType + }); + }, + + 3: function() { + res.render('coursewares/showZiplineOrBasejump', { + title: challenge.name, + dashedName: dashedName, + name: challenge.name, + details: challenge.description, + video: challenge.challengeSeed[0], + verb: resources.randomVerb(), + phrase: resources.randomPhrase(), + compliment: resources.randomCompliment(), + coursewareHash: challenge._id, + challengeType: challenge.challengeType + }); + }, + + 4: function() { + res.render('coursewares/showZiplineOrBasejump', { + title: challenge.name, + dashedName: dashedName, + name: challenge.name, + details: challenge.description, + video: challenge.challengeSeed[0], + verb: resources.randomVerb(), + phrase: resources.randomPhrase(), + compliment: resources.randomCompliment(), + coursewareHash: challenge._id, + challengeType: challenge.challengeType + }); + } + }; + + return challengeType[challenge.challengeType](); + + }); +}; + +/* +challengeBlock { + 0: { + "name": "basic_html, + "challenges: [], + } +} + +userCurrentChallenge { + "challengeBlock": number, + "challengeId": _id +} + */ + diff --git a/controllers/resources.js b/controllers/resources.js index 1b9e2570e4..893e818da5 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -19,14 +19,15 @@ var async = require('async'), debug = require('debug')('freecc:cntr:resources'), cheerio = require('cheerio'), request = require('request'), - R = require('ramda'); + R = require('ramda'), + _ = require('lodash'); /** * Cached values */ var allBonfireIds, allBonfireNames, allCoursewareIds, allCoursewareNames, allFieldGuideIds, allFieldGuideNames, allNonprofitNames, - allBonfireIndexesAndNames; + allBonfireIndexesAndNames, challengeMap; /** * GET / @@ -45,6 +46,35 @@ Array.zip = function(left, right, combinerFunction) { }; module.exports = { + getChallengeMapWithIds: function() { + // TODO finish this + var challengeMapWithIds = {}; + Object.keys(challengeMap). + forEach(function(key) { + var onlyIds = challengeMap[key].challenges.map(function(elem) { + return elem.challengeId; + }); + challengeMapWithIds[key] = onlyIds; + }); + return challengeMapWithIds; + }, + + getChallengeMapWithNames: function() { + var challengeMapWithNames = {}; + Object.keys(challengeMap). + forEach(function(key) { + var onlyNames = challengeMap[key].challenges.map(function(elem) { + return elem.challengeName; + }); + challengeMapWithNames[key] = onlyNames; + }); + return challengeMapWithNames; + }, + + getChallengeName: function(challengeId) { + + }, + sitemap: function sitemap(req, res, next) { var appUrl = 'http://www.freecodecamp.com'; var now = moment(new Date()).format('YYYY-MM-DD'); diff --git a/models/Challenge.js b/models/Challenge.js index 63e2f85ef5..be82110772 100644 --- a/models/Challenge.js +++ b/models/Challenge.js @@ -1,16 +1,22 @@ var mongoose = require('mongoose'); var secrets = require('../config/secrets'); +/** + * + * @type {exports.Schema} + */ + var challengeSchema = new mongoose.Schema({ name: { type: String, unique: true }, - link: String, - time: String, - challengeNumber: Number, - video: String, - steps: Array + difficulty: String, + description: Array, + tests: Array, + challengeSeed: Array, + completionMessage: String, // Congratulations! You've finished our HTML and CSS track! + challengeType: Number // 0 = html, 1 = javascript only, 2 = video, 3 = zipline, 4 = basejump }); module.exports = mongoose.model('Challenge', challengeSchema); diff --git a/models/User.js b/models/User.js index 38c073a2ba..686468c8d7 100644 --- a/models/User.js +++ b/models/User.js @@ -149,7 +149,8 @@ var userSchema = new mongoose.Schema({ needsMigration: { type: Boolean, default: true }, finishedWaypoints: { type: Boolean, default: false }, sendMonthlyEmail: { type: Boolean, default: true }, - challengesHash: {} + challengesHash: {}, + currentChallenge: {} }); /** diff --git a/seed_data/challenges/basic_css.json b/seed_data/challenges/basic_css.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/seed_data/challenges/basic_html.json b/seed_data/challenges/basic_html.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/seed_data/challenges/basic_javascript.json b/seed_data/challenges/basic_javascript.json new file mode 100644 index 0000000000..578dd17771 --- /dev/null +++ b/seed_data/challenges/basic_javascript.json @@ -0,0 +1,1488 @@ +[ + { + "_id" : "bd7123d8c441eddfaeb5bdef", + "name": "Learn how Free Code Camp Works", + "difficulty": 0.00, + "description": [ + "Watch this 90 second video, or simply read this summary:", + "Welcome to Free Code Camp. We're a community of busy people learning to code.", + "We built this community because learning to code is hard. But anyone who can stay motivated can learn to code. And the best way to stay motivated is to code with friends.", + "To maximize accessibility, all our challenges are self-paced, browser-based, and free.", + "All of us start with the same 100 hours of interactive coding challenges. These cover Computer Science and databases. They also cover in-demand JavaScript tools like jQuery, Node.js and MongoDB.", + "Once we have a basic understanding of web development, we'll spend another 900 hours putting that theory into practice. We'll build full stack solutions for nonprofits.", + "By the end of this process, we'll be good at coding. We'll have a portfolio of apps with happy users to prove it. We'll also have an alumni network of fellow coders and nonprofits ready to serve as references.", + "If you make it through Free Code Camp, you will be able to get a coding job. There are far more job openings out there than there are qualified coders to fill them.", + "Also, for every pure coding job, there are at least 5 additional jobs that require some coding skills. So even if you decide not to pursue coding as a career, you'll still walk away with a valuable job skill.", + "There are 3 keys to succeeding in our community: do the challenges, make friends, and find a routine.", + "Now it's time to join our chatroom. Click the \"Go to my next challenge\" button to move on to your next challenge." + ], + "tests": [ + "" + ], + "challengeSeed": [ + "114486344" + ], + "challengeType" : 2 + }, + { + "_id": "bd7123c8c441eddfaeb5bdef", + "name": "Meet Booleans", + "difficulty": "0.001", + "description": [ + "Return true" + ], + "tests": [ + "expect(welcomeToBooleans()).to.be.a(\"boolean\");", + "expect(welcomeToBooleans()).to.be.true;" + ], + "challengeSeed": [ + "function welcomeToBooleans() {\n // Good luck!\n return false;\n}\n\nwelcomeToBooleans();" + ], + "challengeType": 1 + }, + { + "_id" : "bd7123c8c441eddfaeb5bdef", + "name": "Start our Challenges", + "difficulty": "0.002", + "description": [ + "Welcome to Free Code Camp's first challenge! Click on the button below for further instructions.", + "Awesome. Now you can read the rest of this challenge's instructions.", + "You can edit code in the text editor we've embedded into this web page.", + "Do you see the code in the text editor that says <h1>hello</h1>? That's an HTML element.", + "Most HTML elements have an opening tag and a closing tag. Opening tags look like this: <h1>. Closing tags look like this: </h1>. Note that the only difference between opening and closing tags is that closing tags have a slash after their opening angle bracket.", + "Once you've completed the challenge, the \"Go to my next challenge\" button will become enabled. Click it - or press control and enter at the same time - to advance to the next challenge.", + "To enable the \"Go to my next challenge\" button on this exercise, change the h1 tag's text to say \"Hello World\" instead of \"Hello\"." + ], + "tests": [ + "expect((/hello(\\s)+world/gi).test($('h1').text())).to.be.true;" + ], + "challengeSeed": [ + "

Hello

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf0887a", + "name": "Use the h2 Element", + "difficulty" : "0.01", + "description": [ + "Add an h2 tag that says \"cat photo app\" to make a second HTML element below the \"hello world\" h1 element.", + "The h2 element you enter will create an h2 element on the website.", + "This element tells the browser how to render the text that it contains.", + "h2 elements are slightly smaller than h1 elements. There are also h3, h4, h5 and h6 elements." + ], + "tests": [ + "expect((/hello(\\s)+world/gi).test($('h1').text())).to.be.true;", + "expect((/cat(\\s)+photo(\\s)+app/gi).test($('h2').text())).to.be.true;" + ], + "challengeSeed": [ + "

hello world

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08801", + "name": "Use the P Element", + "difficulty" : "0.02", + "description": [ + "Create a p element below the h2 element, and give it the text \"hello paragraph\".", + "p elements are the preferred element for normal-sized paragraph text on websites.", + "You can create a p element like so: <p>I'm a p tag!</p>" + ], + "tests": [ + "expect((/hello(\\s)+paragraph/gi).test($('p').text())).to.be.true;" + ], + "challengeSeed": [ + "

hello world

", + "

hello html

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aeaf08801", + "name": "Add a Line Break to Visually Separate Elements", + "difficulty" : "0.03", + "description": [ + "Add a line break between the <h2> and <p> elements.", + "You can create an line break element with <br/>.", + "Note that <br/> has no closing tag. It is a self-closing element. See how a forward-slash precedes the closing bracket?" + ], + "tests": [ + "expect($('br')).to.exist;" + ], + "challengeSeed": [ + "

hello world

", + "

hello html

", + "

hello paragraph

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08802", + "name": "Uncomment HTML", + "difficulty" : "0.04", + "description": [ + "Uncomment the h1, h2 and p elements.", + "Commenting is a way that you can leave comments within your code without affecting the code itself.", + "Commenting is also a convenient way to make code inactive without having to delete it entirely.", + "You can start a comment with <!-- and end a comment with -->." + ], + "tests": [ + "expect((/hello(\\s)+world/gi).test($('h1').text())).to.be.true;" + ], + "challengeSeed": [ + "", + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08809", + "name": "Using Important to Override Styles", + "difficulty" : "0.14", + "description": [ + "Apply both the \"blue-text\" and \"urgently-red\" classes to all h2 elements, but use !important to ensure the element is rendered as being red.", + "Sometimes HTML elements will receive conflicting information from CSS classes as to how they should be styled.", + "If there's a conflict in the CSS, the browser will use whichever style declaration is closest to the bottom of the CSS document (whichever declaration comes last). Note that in-line style declarations are the final authority in how an HTML element will be rendered.", + "There's one way to ensure that an element is rendered with a certain style, regardless of where that declaration is located. That one way is to use !important.", + "Look at the example in the editor's style tag to see how you can use !important.", + "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, or changing the sequence of CSS class declarations." + ], + "tests": [ + "expect($('h2')).to.have.class('urgently-red');", + "expect($('h2')).to.have.class('blue-text');", + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08810", + "name": "Use Hex Codes for Precise Colors", + "difficulty" : "0.15", + "description": [ + "Change the hex code in the \"red-text\" class to hex code for the color red.", + "Hexadecimal (hex) code is a popular way of specifying color in CSS.", + "Hex code is called \"hex\" because each digit has 16 possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f", + "The six hex code correspond to red-red-green-green-blue-blue.", + "You can change these six values to make more than 16 million colors!", + "The higher the value in a field, the more intense its color. For example, #000000 is black, #ffffff is white, and #00ff00 is bright green. You can also get less intense colors by using values lower than f. For example, #00f000 with the second green digit set to 0 is a light green, and #00f900 is a slightly brighter green", + "Now figure out how to make the bright green in the \"red-text\" class into a bright red." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9bedf08810", + "name": "Use Shortened 3 Digit Hex Codes", + "difficulty" : "0.16", + "description": [ + "Change the hex code in the \"red-text\" class to the shortened 3-digit hex code for the color red.", + "You can also shorten the 6-digit color hex code to a 3-digit code. For example, #00ff00 becomes #0f0. This is less precise, but equally effective." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08811", + "name": "Use RGB Codes for Precise Colors", + "difficulty" : "0.17", + "description": [ + "Change the RGB code to be red.", + "Another way to represent color in CSS is with RGB, or red-green-blue notation.", + "For each of the three colors, you specify a value between 0 and 256.", + "For example, black is rgb(0, 0, 0), white is rgb(255, 255, 255), bright green is rgb(0, 255, 0). You can also get less intense colors by using values lower than 255. For example, light green is rgb(0, 123, 0).", + "If you think about it, this is just as precise as using hex code, because 16 times 16 is 256. In practice, most developers use hex code since it's faster to say out loud and to type." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08812", + "name": "Add an Image to your Website", + "difficulty" : "0.18", + "description": [ + "Use an img element to add the image http://bit.ly/cutegraycat to your website.", + "You can add images to your website by using the img element.", + "An example of this would be <img src=\"www.your-image-source.com/your-image.jpg\"/>. Note that in most cases, img elements are self-closing.", + "Try it with this image: http://bit.ly/cutegraycat." + ], + "tests": [ + "expect($('img').attr('src')).to.equal('http://bit.ly/cutegraycat');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9acdf08812", + "name": "Specify an Image Size TEST", + "difficulty" : "0.19", + "description": [ + "Create a class called narrow-image and use it to resize the image so that it's only 200 pixels wide", + "Uh-oh, our image is too big to fit on a mobile phone. As a result, our user will need to scroll horizontally to view the image. But we can fix this by specifying an image size.", + "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the images width.", + "Create a class called narrow-image and added it to the image element. Change the width to 200 pixels." + ], + "tests": [ + "expect($('img')).to.have.class('narrow-image');", + "expect($('img')).to.have.css('width', 200px)" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9bedf08813", + "name": "Add a Border Around an Element", + "difficulty" : "0.20", + "description": [ + "Create a class called \"thick-green-border\" that puts a 5-pixel-wide black border around your cat photo.", + "CSS Borders have attributes like style, color and width.", + "We've created an example border around your h1 element. See if you can add a 10-pixel-wide green border around your cat photo." + ], + "tests": [ + "expect($('img')).to.have.class('thick-green-border');", + "expect($('img')).to.have.css('border-color', 'rgb(0,255,0)'));", + "expect($('img')).to.have.css('border-width', '10px');" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08814", + "name": "Add Rounded Corners with a Border Radius", + "difficulty" : "0.21", + "description": [ + "Give your cat photo a border radius of 10 pixels.", + "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute called border-radius.", + "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." + ], + "tests": [ + "expect($('img')).to.have.class('thick-green-border');", + "expect($('img')).to.have.css('border-radius', '10px');" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08815", + "name": "Make an Image Circular with a Border Radius", + "difficulty" : "0.22", + "description": [ + "Give your cat photo a border-radius of 50%.", + "In addition to pixels, you can also specify a border-radius of a percentage." + ], + "tests": [ + "expect($('img')).to.have.css('border-radius', '50%');" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08816", + "name": "Use an Anchor Tag to Link to an External Page", + "difficulty" : "0.23", + "description": [ + "Create an anchor tag hyperlink that links to freecodecamp.com", + "" + ], + "tests": [ + "expect((/free(\\s+)?code(\\s+)?camp(\\s+)?/gi).test($('a').text())).to.be.true;", + "expect($('a').filter(function(index) { return /freecodecamp\\.com/gi.test($('a')[index]); }).length).to.eql(1);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "", + "
", + "This is a link to Google", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08817", + "name": "Make Named Anchors using the Hash Symbol", + "difficulty" : "0.24", + "description": [ + "Use the hash symbol(#) to turn the link to the bottom of the page into a named anchor.", + "Sometimes you want to add anchor elements to your website before you know where they will link.", + "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", + "Replace the href in the link to freecodecamp.com with a hash symbol to turn it into a named anchor." + ], + "tests": [ + "expect((/this link leads nowhere/gi).test($('a').text())).to.be.true;", + "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(1);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "", + "
", + "This named anchor leads nowhere", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08820", + "name": "Turn an Image into a Link", + "difficulty" : "0.25", + "description": [ + "Wrap the gray cat's image with an anchor tag that leads nowhere.", + "You can make elements into links by wrapping them in an anchor tag.", + "Check out the example snow-colored cat's photo. When you hover over it with your cursor, you'll see the finger pointer you usually see when you hover over a link. The photo is now a link.", + "Wrap your gray cat's photo in an anchor tag", + "Use the hash symbol as the anchor tag's href." + ], + "tests": [ + "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08818", + "name": "Add Alt Text to an image", + "difficulty" : "0.26", + "description": [ + "Add the alt text \"a photo of a cute gray cat\" to our cat photo", + "alt text is what browsers will display if they fail to load the image. alt text is also important for blind or visually impaired users to understand what an image portrays. Search engines also look at alt text.", + "In short, every image should have alt text!", + "You can add alt text right in the image tag, like we've done here with the \"cute white cat\" image." + ], + "tests": [ + "expect($('img').filter(function(){ return /cat/gi.test(this.alt) }).length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "\"a", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad88fee1348bd9aedf08825", + "name": "Adjusting the Padding of an Element", + "difficulty" : "0.27", + "description": [ + "Change the padding of the green box to match that of the red box.", + "An element's padding controls the amount of space between an element and its border.", + "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more padding than the green box.", + "When you increase the green box's padding, it will increase the distance between the word \"padding\" and the border around the text." + ], + "tests": [ + "expect($('.green-box')).to.have.css('padding', '20px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08822", + "name": "Adjust the Margin of an Element", + "difficulty" : "0.28", + "description": [ + "Change the margin of the green box to match that of the red box.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", + "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin', '20px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08823", + "name": "Add a Negative Margin to an Element", + "difficulty" : "0.29", + "description": [ + "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "If you set an element's margin to a negative value, the element will grow larger.", + "Try to set the margin to a negative value like the one for the red box." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin', '-15px')" + ], + "challengeSeed": [ + "", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08824", + "name": "Add Different Padding to Each Side of an Element TEST", + "difficulty" : "0.30", + "description": [ + "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has different padding on each of its sides.", + "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." + ], + "tests": [ + "expect($('.green-box')).to.have.css('padding-bottom', '20px')", + "expect($('.green-box')).to.have.css('padding-left', '40px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1248bd9aedf08824", + "name": "Add Different a Margin to Each Side of an Element TEST", + "difficulty" : "0.31", + "description": [ + "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", + "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin-bottom', '20px')", + "expect($('.green-box')).to.have.css('margin-left', '40px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08826", + "name": "Use Clockwise Notation to Specify an Element's Padding", + "difficulty" : "0.32", + "description": [ + "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Instead of specifying an element's 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;.", + "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", + "You can also use this notation for margins!" + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin-bottom', '20px')", + "expect($('.green-box')).to.have.css('margin-left', '40px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9acde08812", + "name": "Use Bootstrap for Responsive Images", + "difficulty" : "0.33", + "description": [ + "Add the img-responsive Bootstrap class to the image.", + "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", + "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", + "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", + "Now all you need to do is add the img-responsive class to your image." + ], + "tests": [ + "expect($('img')).to.have.class('img-responsive');" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "This is a link to Google", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd8acde08812", + "name": "Center Text with Bootstrap", + "difficulty" : "0.34", + "description": [ + "Add Bootstrap's text-center class to your h2 element.", + "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", + "Note that you can add several classes to the same element by seperating each of them with a space, like this: <h2 class=\"text-red text-center\">your text</h2>." + ], + "tests": [ + "expect($('h2')).to.have.class('text-center');" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acde08812", + "name": "Create a Button", + "difficulty" : "0.35", + "description": [ + "Create a button with the text \"Delete\" using the HTML button element.", + "HTML has special elements that function like links, but look like buttons. Let's creating a default HTML button." + ], + "tests": [ + "expect((/delete/gi).test($('button').text())).to.be.true;" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acdf08812", + "name": "Create a Bootstrap Button", + "difficulty" : "0.36", + "description": [ + "Apply the Bootstrap's btn class to both of your buttons.", + "Bootstrap has its own button styles, which look much better than the plain HTML ones." + ], + "tests": [ + "expect($('.btn').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acef08812", + "name": "Create a Block Element Bootstrap Button", + "difficulty" : "0.37", + "description": [ + "Add Bootstrap's btn-block class to both of your buttons.", + "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", + "Note that these buttons still need the btn class." + ], + "tests": [ + "expect($('.btn-block').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acef08812", + "name": "Color a Bootstrap Button with Button Primary", + "difficulty" : "0.38", + "description": [ + "Add Bootstrap's btn-block class to both of your buttons.", + "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", + "Note that these buttons still need the btn class." + ], + "tests": [ + "expect($('.btn-block').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acef08812", + "name": "Color a Bootstrap Button with Button Primary", + "difficulty" : "0.39", + "description": [ + "Add Bootstrap's btn-primary class to both of your buttons.", + "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", + "Note that these buttons still need the btn and btn-block classes." + ], + "tests": [ + "expect($('.btn-primary').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348ce8acef08812", + "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", + "difficulty" : "0.40", + "description": [ + "Change the \"Delete\" button from btn-primary to btn-danger.", + "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.", + "Note that this button still needs the btn and btn-block classes." + ], + "tests": [ + "expect($('.btn-danger').length).to.eql(1);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad88fee1348ce8acef08812", + "name": "Use the Bootstrap Grid to Put Two Elements Side By Side", + "difficulty" : "0.41", + "description": [ + "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", + "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.", + "The row class is applied to a div, and the buttons themselves can be nested within it." + ], + "tests": [ + "expect($('.row').length).to.eql(2);", + "expect($('.col-xs-12').length).to.eql(4);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "
", + "
", + " ", + "
", + "
", + " ", + "
", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad89fee1348ce8acef08812", + "name": "Wrap Side By Side Elements in a Bootstrap Row", + "difficulty" : "0.42", + "description": [ + "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", + "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.", + "The row class is applied to a div, and the buttons themselves can be nested within it." + ], + "tests": [ + "expect($('.row').length).to.eql(2);", + "expect($('.col-xs-12').length).to.eql(4);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "
", + "
", + " ", + "
", + "
", + " ", + "
", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + { + "_id" : "bad87fee1348bd9aedf08813", + "name": "Add Alt Text to an Image TEST", + "difficulty" : "0.43", + "description": [ + "Add the alt text \"A picture of a gray cat\" to the image.", + "Alt text is a useful way to tell people (and web crawlers like Google) what is pictured in a photo. It's extremely important for helping blind or visually impaired people understand the content of your website.", + "You can add alt text right in the img element like this: <img src=\"www.your-image-source.com/your-image.jpg\" alt=\"your alt text\"/>." + ], + "tests": [ + "expect((/cat/gi).test($('img').attr('alt')).to.be.true;" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + } +] From e6851b22d877fc2b08aa50e9b26cddd8dbd2963b Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Mon, 18 May 2015 21:20:32 -0400 Subject: [PATCH 2/3] Minor updates --- controllers/challenge.js | 18 +++-- controllers/resources.js | 10 ++- .../js/lib/bonfire/bonfireFramework_v0.1.3.js | 19 ----- seed_data/bonfires.json | 74 +++++++++---------- 4 files changed, 57 insertions(+), 64 deletions(-) diff --git a/controllers/challenge.js b/controllers/challenge.js index 398b31d535..9062945916 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -23,6 +23,9 @@ var debug = require('debug')('freecc:cntr:courseware'), R = require('ramda'), moment = require('moment'); +var challengeMapWithNames = resources.getChallengeMapWithNames(); +var challengeMapWithIds = resources.getChallengeMapWithIds(); + exports.showAllChallenges = function(req, res) { var completedList = []; if (req.user) { @@ -47,8 +50,6 @@ exports.returnNextChallenge = function(req, res, next) { // serve index + 1 challenge // otherwise increment block key and serve the first challenge in that block var nextChallengeName; - var challengeMapWithNames = resources.getChallengeMapWithNames(); - var challengeMapWithIds = resources.getChallengeMapWithIds(); var challengeId = req.user.currentChallenge.challengeId; var challengeBlock = req.user.currentChallenge.challengeBlock; var indexOfChallenge = challengeMapWithIds[challengeBlock] @@ -188,14 +189,19 @@ exports.returnIndividualChallenge = function(req, res, next) { /* challengeBlock { 0: { - "name": "basic_html, - "challenges: [], + "name": "basic_html", + "challenges: [] + }, + 1: { + "name": "basic_css", + "challenges": [], } } -userCurrentChallenge { +currentChallenge{ "challengeBlock": number, - "challengeId": _id + "challengeId": _id, + "challengeName": string } */ diff --git a/controllers/resources.js b/controllers/resources.js index 893e818da5..ac7f838695 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -45,9 +45,17 @@ Array.zip = function(left, right, combinerFunction) { return results; }; +buildChallengeMap = function() { + +}; + module.exports = { + getChallengeMapWithIds: function() { // TODO finish this + if (challengeMap === null) { + buildChallengeMap(); + } var challengeMapWithIds = {}; Object.keys(challengeMap). forEach(function(key) { @@ -71,9 +79,7 @@ module.exports = { return challengeMapWithNames; }, - getChallengeName: function(challengeId) { - }, sitemap: function sitemap(req, res, next) { var appUrl = 'http://www.freecodecamp.com'; diff --git a/public/js/lib/bonfire/bonfireFramework_v0.1.3.js b/public/js/lib/bonfire/bonfireFramework_v0.1.3.js index fb56ced9d0..31fb730808 100644 --- a/public/js/lib/bonfire/bonfireFramework_v0.1.3.js +++ b/public/js/lib/bonfire/bonfireFramework_v0.1.3.js @@ -33,9 +33,6 @@ editor.setOption("extraKeys", { cm.replaceSelection(spaces); } }, - - - "Ctrl-Enter": function() { bonfireExecute(); return false; @@ -49,22 +46,6 @@ if (attempts) { attempts = 0; } -// Default value for editor if one isn't provided in (i.e. a challenge) -var nonChallengeValue = '/*Welcome to Bonfire, Free Code Camp\'s future CoderByte replacement.\n' + - 'Please feel free to use Bonfire as an in-browser playground and linting tool.\n' + - 'Note that you can also write tests using Chai.js by using the keywords assert and expect */\n\n' + - 'function test() {\n' + - ' assert(2 !== 3, "2 is not equal to 3");\n' + - ' return [1,2,3].map(function(elem) {\n' + - ' return elem * elem;\n' + - ' });\n' + - '}\n' + - 'expect(test()).to.be.a("array");\n\n' + - 'assert.deepEqual(test(), [1,4,9]);\n\n' + - 'var foo = test();\n' + - 'foo.should.be.a("array");\n\n' + - 'test();\n'; - var codeOutput = CodeMirror.fromTextArea(document.getElementById("codeOutput"), { lineNumbers: false, mode: "text", diff --git a/seed_data/bonfires.json b/seed_data/bonfires.json index 04116d840b..5ac7923de5 100644 --- a/seed_data/bonfires.json +++ b/seed_data/bonfires.json @@ -31,7 +31,7 @@ "You may need to turn the string into an array before you can reverse it.", "Your result must be a string." ], - "challengeSeed": "function reverseString(str) {\n return str;\r\n}\n\nreverseString('hello');", + "challengeSeed": "function reverseString(str) {\n return str;\n}\n\nreverseString('hello');", "MDNlinks" : ["Global String Object", "String.split()", "Array.reverse()", "Array.join()"] }, { @@ -50,7 +50,7 @@ "Factorials are often represented with the shorthand notation n!", "For example: 5! = 1 * 2 * 3 * 4 * 5 = 120f" ], - "challengeSeed": "function factorialize(num) {\n return num;\r\n}\n\nfactorialize(5);", + "challengeSeed": "function factorialize(num) {\n return num;\n}\n\nfactorialize(5);", "MDNlinks" : ["Arithmetic Operators"] }, { @@ -83,7 +83,7 @@ "Return the length of the longest word in the provided sentence.", "Your response should be a number." ], - "challengeSeed": "function findLongestWord(str) {\n return str.length;\r\n}\n\nfindLongestWord('The quick brown fox jumped over the lazy dog');", + "challengeSeed": "function findLongestWord(str) {\n return str.length;\n}\n\nfindLongestWord('The quick brown fox jumped over the lazy dog');", "tests": [ "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.be.a('Number');", "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.equal(6);", @@ -101,7 +101,7 @@ "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'." ], - "challengeSeed": "function titleCase(str) {\n return str;\r\n}\n\ntitleCase(\"I'm a little tea pot\");", + "challengeSeed": "function titleCase(str) {\n return str;\n}\n\ntitleCase(\"I'm a little tea pot\");", "tests": [ "expect(titleCase(\"I'm a little tea pot\")).to.be.a('String');", "expect(titleCase(\"I'm a little tea pot\")).to.equal(\"I'm A Little Tea Pot\");", @@ -119,7 +119,7 @@ "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." ], - "challengeSeed": "function largestOfFour(arr) {\n // You can do this!\r\n return arr;\r\n}\n\nlargestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);", + "challengeSeed": "function largestOfFour(arr) {\n // You can do this!\n return arr;\n}\n\nlargestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);", "tests": [ "expect(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).to.be.a('array');", "(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).should.eql([5,27,39,1001]);", @@ -135,7 +135,7 @@ "Check if a string (first argument) ends with the given target string (second argument)." ], - "challengeSeed": "function end(str, target) {\n // \"Never give up and good luck will find you.\"\r\n // -- Falcor\r\n return str;\r\n}\n\nend('Bastian', 'n');", + "challengeSeed": "function end(str, target) {\n // \"Never give up and good luck will find you.\"\n // -- Falcor\n return str;\n}\n\nend('Bastian', 'n');", "tests": [ "assert.strictEqual(end('Bastian', 'n'), true, 'should equal true if target equals end of string');", "assert.strictEqual(end('He has to give me a new name', 'name'), true, 'should equal true if target equals end of string');", @@ -150,7 +150,7 @@ "description": [ "Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number." ], - "challengeSeed": "function repeat(str, num) {\n // repeat after me\r\n return str;\r\n}\n\nrepeat('abc', 3);", + "challengeSeed": "function repeat(str, num) {\n // repeat after me\n return str;\n}\n\nrepeat('abc', 3);", "tests": [ "assert.strictEqual(repeat('*', 3), '***', 'should repeat a string n times');", "assert.strictEqual(repeat('abc', 3), 'abcabcabc', 'should repeat a string n times');", @@ -166,7 +166,7 @@ "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." ], - "challengeSeed":"function truncate(str, num) {\n // Clear out that junk in your trunk\r\n return str;\r\n}\n\ntruncate('A-tisket a-tasket A green and yellow basket', 11);", + "challengeSeed":"function truncate(str, num) {\n // Clear out that junk in your trunk\n return str;\n}\n\ntruncate('A-tisket a-tasket A green and yellow basket', 11);", "tests": [ "expect(truncate('A-tisket a-tasket A green and yellow basket', 11)).to.eqls('A-tisket...');", "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length) === 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is = length');", @@ -181,7 +181,7 @@ "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." ], - "challengeSeed": "function chunk(arr, size) {\n // Break it up.\r\n return arr;\r\n}\n\nchunk(['a', 'b', 'c', 'd'], 2);", + "challengeSeed": "function chunk(arr, size) {\n // Break it up.\n return arr;\n}\n\nchunk(['a', 'b', 'c', 'd'], 2);", "tests": [ "assert.deepEqual(chunk(['a', 'b', 'c', 'd'], 2), [['a', 'b'], ['c', 'd']], 'should return chunked arrays');", "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'should return chunked arrays');", @@ -196,7 +196,7 @@ "description": [ "Return the remaining elements of an array after chopping off n elements from the head." ], - "challengeSeed": "function slasher(arr, howMany) {\n // it doesn't always pay to be first\r\n return arr;\r\n}\n\nslasher([1, 2, 3], 2);", + "challengeSeed": "function slasher(arr, howMany) {\n // it doesn't always pay to be first\n return arr;\n}\n\nslasher([1, 2, 3], 2);", "tests": [ "assert.deepEqual(slasher([1, 2, 3], 2), [3], 'should drop the first two elements');", "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], 'should return all elements when n < 1');", @@ -232,7 +232,7 @@ "Remove all falsey values from an array.", "Falsey values in javascript are false, null, 0, \"\", undefined, and NaN." ], - "challengeSeed": "function bouncer(arr) {\n // Don't show a false ID to this bouncer.\r\n return arr;\r\n}\n\nbouncer([7, 'ate', '', false, 9]);", + "challengeSeed": "function bouncer(arr) {\n // Don't show a false ID to this bouncer.\n return arr;\n}\n\nbouncer([7, 'ate', '', false, 9]);", "tests": [ "assert.deepEqual(bouncer([7, 'ate', '', false, 9]), [7, 'ate', 9], 'should remove falsey values');", "assert.deepEqual(bouncer(['a', 'b', 'c']), ['a', 'b', 'c'], 'should return full array if no falsey elements');", @@ -247,7 +247,7 @@ "description":[ "Make a function that looks through a list (first argument) and returns an array of all objects that have equivalent property values (second argument)." ], - "challengeSeed":"function where(collection, source) {\n var arr = [];\r\n // What's in a name?\r\n return arr;\r\n}\n\nwhere([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });", + "challengeSeed":"function where(collection, source) {\n var arr = [];\n // What's in a name?\n return arr;\n}\n\nwhere([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });", "tests":[ "assert.deepEqual(where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }), [{ first: 'Tybalt', last: 'Capulet' }], 'should return an array of objects');", "assert.deepEqual(where([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'should return with multiples');" @@ -261,7 +261,7 @@ "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." ], - "challengeSeed": "function destroyer(arr) {\n // Remove all the values\r\n return arr;\r\n}\n\ndestroyer([1, 2, 3, 1, 2, 3], 2, 3);", + "challengeSeed": "function destroyer(arr) {\n // Remove all the values\n return arr;\n}\n\ndestroyer([1, 2, 3, 1, 2, 3], 2, 3);", "tests": [ "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'should remove correct values from an array');", "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');" @@ -276,7 +276,7 @@ "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)." ], - "challengeSeed": "function where(arr, num) {\n // Find my place in this sorted array.\r\n return num;\r\n}\n\nwhere([40, 60], 50);", + "challengeSeed": "function where(arr, num) {\n // Find my place in this sorted array.\n return num;\n}\n\nwhere([40, 60], 50);", "tests": [ "expect(where([10, 20, 30, 40, 50], 35)).to.equal(3);", "expect(where([10, 20, 30, 40, 50], 30)).to.equal(2);" @@ -290,7 +290,7 @@ "We'll pass you an array of two numbers. Return the sum of those two numbers and all numbers between them.", "The lowest number will not always come first." ], - "challengeSeed": "function sumAll(arr) {\n return(1);\r\n}\n\nsumAll([1, 4]);", + "challengeSeed": "function sumAll(arr) {\n return(1);\n}\n\nsumAll([1, 4]);", "tests": [ "expect(sumAll([1, 4])).to.be.a('Number');", "expect(sumAll([1, 4])).to.equal(10);", @@ -307,7 +307,7 @@ "description": [ "Compare two arrays and return a new array with any items not found in both of the original arrays." ], - "challengeSeed": "function diff(arr1, arr2) {\n var newArr = [];\r\n // Same, same; but different.\r\n return newArr;\r\n}\n\ndiff([1, 2, 3, 5], [1, 2, 3, 4, 5]);", + "challengeSeed": "function diff(arr1, arr2) {\n var newArr = [];\n // Same, same; but different.\n return newArr;\n}\n\ndiff([1, 2, 3, 5], [1, 2, 3, 4, 5]);", "tests": [ "expect(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])).to.be.a('array');", "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'arrays with only one difference');", @@ -333,7 +333,7 @@ "Convert the number be a roman numeral.", "All roman numerals answers should be provided in upper-case." ], - "challengeSeed": "function convert(num) {\n return num;\r\n}\n\nconvert(36);", + "challengeSeed": "function convert(num) {\n return num;\n}\n\nconvert(36);", "MDNlinks" : ["Array.splice()", "Array.indexOf()", "Array.join()"] }, { @@ -354,7 +354,7 @@ "Third argument is what you will be replacing the second argument with (after).", "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word 'Book' with the word 'dog', it should be replaced as 'Dog'" ], - "challengeSeed": "function replace(str, before, after) {\n return str;\r\n}\n\nreplace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");", + "challengeSeed": "function replace(str, before, after) {\n return str;\n}\n\nreplace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");", "MDNlinks" : ["Array.splice()", "String.replace()", "Array.join()"] }, { @@ -373,7 +373,7 @@ "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." ], - "challengeSeed": "function translate(str) {\n return str;\r\n}\n\ntranslate(\"consonant\");", + "challengeSeed": "function translate(str) {\n return str;\n}\n\ntranslate(\"consonant\");", "MDNlinks" : ["Array.indexOf()", "Array.push()", "Array.join()", "String.substr()", "String.split()"] }, { @@ -390,7 +390,7 @@ "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." ], - "challengeSeed": "function pair(str) {\n return str;\r\n}\n\npair(\"GCG\");", + "challengeSeed": "function pair(str) {\n return str;\n}\n\npair(\"GCG\");", "MDNlinks" : ["Array.push()", "String.split()"] }, { @@ -418,7 +418,7 @@ "Check if a value is classified as a boolean primitive. Return true or false.", "Boolean primitives are true and false." ], - "challengeSeed": "function boo(bool) {\n // What is the new fad diet for ghost developers? The Boolean.\r\n return bool;\r\n}\n\nboo(null);", + "challengeSeed": "function boo(bool) {\n // What is the new fad diet for ghost developers? The Boolean.\n return bool;\n}\n\nboo(null);", "tests": [ "assert.strictEqual(boo(true), true);", "assert.strictEqual(boo(false), true);", @@ -441,7 +441,7 @@ "The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.", "Check the assertion tests for examples." ], - "challengeSeed": "function unite(arr1, arr2, arr3) {\n return arr1;\r\n}\n\nunite([1, 2, 3], [5, 2, 1, 4], [2, 1]);", + "challengeSeed": "function unite(arr1, arr2, arr3) {\n return arr1;\n}\n\nunite([1, 2, 3], [5, 2, 1, 4], [2, 1]);", "tests": [ "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'should return the union of the given arrays');", "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'should not flatten nested arrays');" @@ -454,7 +454,7 @@ "description": [ "Convert the characters \"&\", \"<\", \">\", '\"', and \"'\", in a string to their corresponding HTML entities." ], - "challengeSeed": "function convert(str) {\n // :)\r\n return str;\r\n}\n\nconvert('Dolce & Gabbana');", + "challengeSeed": "function convert(str) {\n // :)\n return str;\n}\n\nconvert('Dolce & Gabbana');", "tests": [ "assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');", "assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');" @@ -468,7 +468,7 @@ "description": [ "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes." ], - "challengeSeed": "function spinalCase(str) {\n // \"It's such a fine line between stupid, and clever.\"\r\n // --David St. Hubbins\r\n return str;\r\n}\n\nspinalCase('This Is Spinal Tap');", + "challengeSeed": "function spinalCase(str) {\n // \"It's such a fine line between stupid, and clever.\"\n // --David St. Hubbins\n return str;\n}\n\nspinalCase('This Is Spinal Tap');", "tests": [ "assert.strictEqual(spinalCase('This Is Spinal Tap'), 'this-is-spinal-tap', 'should return spinal case from string with spaces');", "assert.strictEqual(spinalCase('thisIsSpinalTap'), 'this-is-spinal-tap', 'should return spinal case from string with camel case');", @@ -486,7 +486,7 @@ "The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8, and each subsequent number is the sum of the previous two numbers.", "As an example, passing 4 to the function should return 5 because all the odd Fibonacci numbers under 4 are 1, 1, and 3." ], - "challengeSeed": "function sumFibs(num) {\n return num;\r\n}\n\nsumFibs(4);", + "challengeSeed": "function sumFibs(num) {\n return num;\n}\n\nsumFibs(4);", "tests": [ "expect(sumFibs(1)).to.be.a('number');", "expect(sumFibs(1000)).to.equal(1785);", @@ -506,7 +506,7 @@ "A prime number is defined as having only two divisors, 1 and itself. For example, 2 is a prime number because it's only divisible by 1 and 2. 1 isn't a prime number, because it's only divisible by itself.", "The provided number may not be a prime." ], - "challengeSeed": "function sumPrimes(num) {\n return num;\r\n}\n\nsumPrimes(10);", + "challengeSeed": "function sumPrimes(num) {\n return num;\n}\n\nsumPrimes(10);", "tests": [ "expect(sumPrimes(10)).to.be.a('number');", "expect(sumPrimes(10)).to.equal(17);", @@ -521,7 +521,7 @@ "Find the smallest number that is evenly divisible by all numbers in the provided range.", "The range will be an array of two numbers that will not necessarily be in numerical order." ], - "challengeSeed": "function smallestCommons(arr) {\n return arr;\r\n}\r\n\n\nsmallestCommons([1,5]);", + "challengeSeed": "function smallestCommons(arr) {\n return arr;\n}\n\n\nsmallestCommons([1,5]);", "tests": [ "expect(smallestCommons([1,5])).to.be.a('number');", "expect(smallestCommons([1,5])).to.equal(60);", @@ -536,7 +536,7 @@ "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)." ], - "challengeSeed": "function find(arr, func) {\n var num = 0;\r\n return num;\r\n}\n\nfind([1, 2, 3, 4], function(num){ return num % 2 === 0; });", + "challengeSeed": "function find(arr, func) {\n var num = 0;\n return num;\n}\n\nfind([1, 2, 3, 4], function(num){ return num % 2 === 0; });", "tests": [ "assert.strictEqual(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'should return first found value');", "assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'should return undefined if not found');" @@ -550,7 +550,7 @@ "description": [ "Drop the elements of an array (first argument), starting from the front, until the predicate (second argument) returns true." ], - "challengeSeed": "function drop(arr, func) {\n // Drop them elements.\r\n return arr;\r\n}\n\ndrop([1, 2, 3], function(n) {return n < 3; });", + "challengeSeed": "function drop(arr, func) {\n // Drop them elements.\n return arr;\n}\n\ndrop([1, 2, 3], function(n) {return n < 3; });", "tests": [ "expect(drop([1, 2, 3, 4], function(n) {return n >= 3; })).to.eqls([3, 4]);", "expect(drop([1, 2, 3], function(n) {return n > 0; })).to.eqls([1, 2, 3]);", @@ -565,7 +565,7 @@ "description": [ "Flatten a nested array. You must account for varying levels of nesting." ], - "challengeSeed": "function steamroller(arr) {\n // I'm a steamroller, baby\r\n return arr;\r\n}\n\nsteamroller([1, [2], [3, [[4]]]]);", + "challengeSeed": "function steamroller(arr) {\n // I'm a steamroller, baby\n return arr;\n}\n\nsteamroller([1, [2], [3, [[4]]]]);", "tests": [ "assert.deepEqual(steamroller([[['a']], [['b']]]), ['a', 'b'], 'should flatten nested arrays');", "assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'should flatten nested arrays');", @@ -581,7 +581,7 @@ "Return an English translated sentence of the passed binary string.", "The binary string will be space separated." ], - "challengeSeed": "function binaryAgent(str) {\n return str;\r\n}\n\nbinaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');", + "challengeSeed": "function binaryAgent(str) {\n return str;\n}\n\nbinaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');", "tests": [ "expect(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111')).to.equal(\"Aren't bonfires fun!?\");", "expect(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001')).to.equal(\"I love FreeCodeCamp!\");" @@ -615,7 +615,7 @@ "For this, check to see if the property defined in the second argument is present on every element of the collection.", "Remember, you can access object properties through either dot notation or [] notation." ], - "challengeSeed": "function every(collection, pre) {\n // Does everyone have one of these?\r\n return pre;\r\n}\n\nevery([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');", + "challengeSeed": "function every(collection, pre) {\n // Does everyone have one of these?\n return pre;\n}\n\nevery([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');", "tests": [ "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex'), true, 'should return true if predicate returns truthy for all elements in the collection');", "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], {'sex': 'female'}), false, 'should return false if predicate returns falsey for any element in the collection');" @@ -651,7 +651,7 @@ "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." ], - "challengeSeed": "var Person = function(firstAndLast) {\n return firstAndLast;\r\n};\n\nvar bob = new Person('Bob Ross');\nbob.getFullName();", + "challengeSeed": "var Person = function(firstAndLast) {\n return firstAndLast;\n};\n\nvar bob = new Person('Bob Ross');\nbob.getFullName();", "tests": [ "expect(Object.keys(bob).length).to.eql(6);", "expect(bob instanceof Person).to.be.true;", @@ -681,7 +681,7 @@ "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" ], - "challengeSeed": "function orbitalPeriod(arr) {\n var GM = 398600.4418;\n var earthRadius = 6367.4447;\n return arr;\r\n}\r\n\r\norbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);", + "challengeSeed": "function orbitalPeriod(arr) {\n var GM = 398600.4418;\n var earthRadius = 6367.4447;\n return arr;\n}\n\norbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);", "tests": [ "expect(orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputkin\", 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}]);" @@ -732,7 +732,7 @@ "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." ], - "challengeSeed": "function sym(args) {\n return arguments;\r\n}\n\nsym([1, 2, 3], [5, 2, 1, 4]);", + "challengeSeed": "function sym(args) {\n return arguments;\n}\n\nsym([1, 2, 3], [5, 2, 1, 4]);", "tests": [ "expect(sym([1, 2, 3], [5, 2, 1, 4])).to.eqls([3, 5, 4])", "assert.deepEqual(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'should return the symmetric difference of the given arrays');", @@ -747,7 +747,7 @@ "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." ], - "challengeSeed": "function drawer(price, cash, cid) {\n var change;\r\n // Here is your change, ma'am.\r\n return change;\r\n}\r\n\r\n// Example cash-in-drawer array:\r\n// [['PENNY', 1.01],\r\n// ['NICKEL', 2.05],\r\n// ['DIME', 3.10],\r\n// ['QUARTER', 4.25],\r\n// ['ONE', 90.00],\r\n// ['FIVE', 55.00],\r\n// ['TEN', 20.00],\r\n// ['TWENTY', 60.00],\r\n// ['ONE HUNDRED', 100.00]]\n\ndrawer(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]]);", + "challengeSeed": "function drawer(price, cash, cid) {\n var change;\n // Here is your change, ma'am.\n return change;\n}\n\n// Example cash-in-drawer array:\n// [['PENNY', 1.01],\n// ['NICKEL', 2.05],\n// ['DIME', 3.10],\n// ['QUARTER', 4.25],\n// ['ONE', 90.00],\n// ['FIVE', 55.00],\n// ['TEN', 20.00],\n// ['TWENTY', 60.00],\n// ['ONE HUNDRED', 100.00]]\n\ndrawer(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');", @@ -765,7 +765,7 @@ "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." ], - "challengeSeed": "function inventory(arr1, arr2) {\n // All inventory must be accounted for or you're fired!\r\n return arr1;\r\n}\n\n// Example inventory lists\r\nvar curInv = [\r\n [21, 'Bowling Ball'],\r\n [2, 'Dirty Sock'],\r\n [1, 'Hair Pin'],\r\n [5, 'Microphone']\r\n];\r\n\r\nvar newInv = [\r\n [2, 'Hair Pin'],\r\n [3, 'Half-Eaten Apple'],\r\n [67, 'Bowling Ball'],\r\n [7, 'Toothpaste']\r\n];\r\n\r\ninventory(curInv, newInv);", + "challengeSeed": "function inventory(arr1, arr2) {\n // All inventory must be accounted for or you're fired!\n return arr1;\n}\n\n// Example inventory lists\nvar curInv = [\n [21, 'Bowling Ball'],\n [2, 'Dirty Sock'],\n [1, 'Hair Pin'],\n [5, 'Microphone']\n];\n\nvar newInv = [\n [2, 'Hair Pin'],\n [3, 'Half-Eaten Apple'],\n [67, 'Bowling Ball'],\n [7, 'Toothpaste']\n];\n\ninventory(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);", From ba29f0533aa295298503b8b70317daa30f355753 Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Mon, 18 May 2015 22:03:27 -0400 Subject: [PATCH 3/3] Updated to show how json should be modeled, fleshed out resources to load new challengeMap stub --- config/bootstrap.js | 29 - controllers/resources.js | 18 +- seed_data/challenges.json | 1 + seed_data/challenges/basic_css.json | 0 seed_data/challenges/basic_html.json | 0 seed_data/challenges/basic_javascript.json | 1488 -------------------- seed_data/challenges/basics.json | 59 + seed_data/challenges/prepwork.json | 55 + seed_data/seed.js | 128 +- 9 files changed, 186 insertions(+), 1592 deletions(-) delete mode 100644 config/bootstrap.js create mode 100644 seed_data/challenges.json delete mode 100644 seed_data/challenges/basic_css.json delete mode 100644 seed_data/challenges/basic_html.json delete mode 100644 seed_data/challenges/basic_javascript.json create mode 100644 seed_data/challenges/basics.json create mode 100644 seed_data/challenges/prepwork.json diff --git a/config/bootstrap.js b/config/bootstrap.js deleted file mode 100644 index c38ffac08e..0000000000 --- a/config/bootstrap.js +++ /dev/null @@ -1,29 +0,0 @@ -var mongoose = require('mongoose'), - debug = require('debug')('freecc:config:boot'), - secrets = require('./secrets'), - courses = require('../seed_data/courses.json'), - Course = require('./../models/Course'), - challenges = require('../seed_data/challenges.json'), - Challenge = require('./../models/Challenge'); - -mongoose.connect(secrets.db); -mongoose.connection.on('error', function() { - console.error('MongoDB Connection Error. Make sure MongoDB is running.'); -}); - - -Course.create(courses, function(err, data) { - if (err) { - debug(err); - } else { - debug('Saved ', data); - } -}); - -Challenge.create(challenges, function(err, data) { - if (err) { - console.log(err); - } else { - console.log('Saved ', data); - } -}); diff --git a/controllers/resources.js b/controllers/resources.js index ac7f838695..aa87e04d49 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -20,7 +20,8 @@ var async = require('async'), cheerio = require('cheerio'), request = require('request'), R = require('ramda'), - _ = require('lodash'); + _ = require('lodash'), + fs = require('fs'); /** * Cached values @@ -46,7 +47,20 @@ Array.zip = function(left, right, combinerFunction) { }; buildChallengeMap = function() { - + challengeMap = {}; + fs.readdir(__dirname + '../seed_data/challenges', function(err, files) { + if (err) { + debug(err); + } else { + var keyCounter = 0; + files = files.sort(function(a, b) { + return a.order < b.order ? a : b; + }); + files.forEach(function(file) { + challengeMap[keyCounter++] = file; + }); + } + }); }; module.exports = { diff --git a/seed_data/challenges.json b/seed_data/challenges.json new file mode 100644 index 0000000000..c1212e28a1 --- /dev/null +++ b/seed_data/challenges.json @@ -0,0 +1 @@ +["./challenges/prepwork.json", "./challenges/basics.json"] \ No newline at end of file diff --git a/seed_data/challenges/basic_css.json b/seed_data/challenges/basic_css.json deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/seed_data/challenges/basic_html.json b/seed_data/challenges/basic_html.json deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/seed_data/challenges/basic_javascript.json b/seed_data/challenges/basic_javascript.json deleted file mode 100644 index 578dd17771..0000000000 --- a/seed_data/challenges/basic_javascript.json +++ /dev/null @@ -1,1488 +0,0 @@ -[ - { - "_id" : "bd7123d8c441eddfaeb5bdef", - "name": "Learn how Free Code Camp Works", - "difficulty": 0.00, - "description": [ - "Watch this 90 second video, or simply read this summary:", - "Welcome to Free Code Camp. We're a community of busy people learning to code.", - "We built this community because learning to code is hard. But anyone who can stay motivated can learn to code. And the best way to stay motivated is to code with friends.", - "To maximize accessibility, all our challenges are self-paced, browser-based, and free.", - "All of us start with the same 100 hours of interactive coding challenges. These cover Computer Science and databases. They also cover in-demand JavaScript tools like jQuery, Node.js and MongoDB.", - "Once we have a basic understanding of web development, we'll spend another 900 hours putting that theory into practice. We'll build full stack solutions for nonprofits.", - "By the end of this process, we'll be good at coding. We'll have a portfolio of apps with happy users to prove it. We'll also have an alumni network of fellow coders and nonprofits ready to serve as references.", - "If you make it through Free Code Camp, you will be able to get a coding job. There are far more job openings out there than there are qualified coders to fill them.", - "Also, for every pure coding job, there are at least 5 additional jobs that require some coding skills. So even if you decide not to pursue coding as a career, you'll still walk away with a valuable job skill.", - "There are 3 keys to succeeding in our community: do the challenges, make friends, and find a routine.", - "Now it's time to join our chatroom. Click the \"Go to my next challenge\" button to move on to your next challenge." - ], - "tests": [ - "" - ], - "challengeSeed": [ - "114486344" - ], - "challengeType" : 2 - }, - { - "_id": "bd7123c8c441eddfaeb5bdef", - "name": "Meet Booleans", - "difficulty": "0.001", - "description": [ - "Return true" - ], - "tests": [ - "expect(welcomeToBooleans()).to.be.a(\"boolean\");", - "expect(welcomeToBooleans()).to.be.true;" - ], - "challengeSeed": [ - "function welcomeToBooleans() {\n // Good luck!\n return false;\n}\n\nwelcomeToBooleans();" - ], - "challengeType": 1 - }, - { - "_id" : "bd7123c8c441eddfaeb5bdef", - "name": "Start our Challenges", - "difficulty": "0.002", - "description": [ - "Welcome to Free Code Camp's first challenge! Click on the button below for further instructions.", - "Awesome. Now you can read the rest of this challenge's instructions.", - "You can edit code in the text editor we've embedded into this web page.", - "Do you see the code in the text editor that says <h1>hello</h1>? That's an HTML element.", - "Most HTML elements have an opening tag and a closing tag. Opening tags look like this: <h1>. Closing tags look like this: </h1>. Note that the only difference between opening and closing tags is that closing tags have a slash after their opening angle bracket.", - "Once you've completed the challenge, the \"Go to my next challenge\" button will become enabled. Click it - or press control and enter at the same time - to advance to the next challenge.", - "To enable the \"Go to my next challenge\" button on this exercise, change the h1 tag's text to say \"Hello World\" instead of \"Hello\"." - ], - "tests": [ - "expect((/hello(\\s)+world/gi).test($('h1').text())).to.be.true;" - ], - "challengeSeed": [ - "

Hello

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf0887a", - "name": "Use the h2 Element", - "difficulty" : "0.01", - "description": [ - "Add an h2 tag that says \"cat photo app\" to make a second HTML element below the \"hello world\" h1 element.", - "The h2 element you enter will create an h2 element on the website.", - "This element tells the browser how to render the text that it contains.", - "h2 elements are slightly smaller than h1 elements. There are also h3, h4, h5 and h6 elements." - ], - "tests": [ - "expect((/hello(\\s)+world/gi).test($('h1').text())).to.be.true;", - "expect((/cat(\\s)+photo(\\s)+app/gi).test($('h2').text())).to.be.true;" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08801", - "name": "Use the P Element", - "difficulty" : "0.02", - "description": [ - "Create a p element below the h2 element, and give it the text \"hello paragraph\".", - "p elements are the preferred element for normal-sized paragraph text on websites.", - "You can create a p element like so: <p>I'm a p tag!</p>" - ], - "tests": [ - "expect((/hello(\\s)+paragraph/gi).test($('p').text())).to.be.true;" - ], - "challengeSeed": [ - "

hello world

", - "

hello html

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aeaf08801", - "name": "Add a Line Break to Visually Separate Elements", - "difficulty" : "0.03", - "description": [ - "Add a line break between the <h2> and <p> elements.", - "You can create an line break element with <br/>.", - "Note that <br/> has no closing tag. It is a self-closing element. See how a forward-slash precedes the closing bracket?" - ], - "tests": [ - "expect($('br')).to.exist;" - ], - "challengeSeed": [ - "

hello world

", - "

hello html

", - "

hello paragraph

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08802", - "name": "Uncomment HTML", - "difficulty" : "0.04", - "description": [ - "Uncomment the h1, h2 and p elements.", - "Commenting is a way that you can leave comments within your code without affecting the code itself.", - "Commenting is also a convenient way to make code inactive without having to delete it entirely.", - "You can start a comment with <!-- and end a comment with -->." - ], - "tests": [ - "expect((/hello(\\s)+world/gi).test($('h1').text())).to.be.true;" - ], - "challengeSeed": [ - "", - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08809", - "name": "Using Important to Override Styles", - "difficulty" : "0.14", - "description": [ - "Apply both the \"blue-text\" and \"urgently-red\" classes to all h2 elements, but use !important to ensure the element is rendered as being red.", - "Sometimes HTML elements will receive conflicting information from CSS classes as to how they should be styled.", - "If there's a conflict in the CSS, the browser will use whichever style declaration is closest to the bottom of the CSS document (whichever declaration comes last). Note that in-line style declarations are the final authority in how an HTML element will be rendered.", - "There's one way to ensure that an element is rendered with a certain style, regardless of where that declaration is located. That one way is to use !important.", - "Look at the example in the editor's style tag to see how you can use !important.", - "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, or changing the sequence of CSS class declarations." - ], - "tests": [ - "expect($('h2')).to.have.class('urgently-red');", - "expect($('h2')).to.have.class('blue-text');", - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08810", - "name": "Use Hex Codes for Precise Colors", - "difficulty" : "0.15", - "description": [ - "Change the hex code in the \"red-text\" class to hex code for the color red.", - "Hexadecimal (hex) code is a popular way of specifying color in CSS.", - "Hex code is called \"hex\" because each digit has 16 possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f", - "The six hex code correspond to red-red-green-green-blue-blue.", - "You can change these six values to make more than 16 million colors!", - "The higher the value in a field, the more intense its color. For example, #000000 is black, #ffffff is white, and #00ff00 is bright green. You can also get less intense colors by using values lower than f. For example, #00f000 with the second green digit set to 0 is a light green, and #00f900 is a slightly brighter green", - "Now figure out how to make the bright green in the \"red-text\" class into a bright red." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9bedf08810", - "name": "Use Shortened 3 Digit Hex Codes", - "difficulty" : "0.16", - "description": [ - "Change the hex code in the \"red-text\" class to the shortened 3-digit hex code for the color red.", - "You can also shorten the 6-digit color hex code to a 3-digit code. For example, #00ff00 becomes #0f0. This is less precise, but equally effective." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08811", - "name": "Use RGB Codes for Precise Colors", - "difficulty" : "0.17", - "description": [ - "Change the RGB code to be red.", - "Another way to represent color in CSS is with RGB, or red-green-blue notation.", - "For each of the three colors, you specify a value between 0 and 256.", - "For example, black is rgb(0, 0, 0), white is rgb(255, 255, 255), bright green is rgb(0, 255, 0). You can also get less intense colors by using values lower than 255. For example, light green is rgb(0, 123, 0).", - "If you think about it, this is just as precise as using hex code, because 16 times 16 is 256. In practice, most developers use hex code since it's faster to say out loud and to type." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08812", - "name": "Add an Image to your Website", - "difficulty" : "0.18", - "description": [ - "Use an img element to add the image http://bit.ly/cutegraycat to your website.", - "You can add images to your website by using the img element.", - "An example of this would be <img src=\"www.your-image-source.com/your-image.jpg\"/>. Note that in most cases, img elements are self-closing.", - "Try it with this image: http://bit.ly/cutegraycat." - ], - "tests": [ - "expect($('img').attr('src')).to.equal('http://bit.ly/cutegraycat');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9acdf08812", - "name": "Specify an Image Size TEST", - "difficulty" : "0.19", - "description": [ - "Create a class called narrow-image and use it to resize the image so that it's only 200 pixels wide", - "Uh-oh, our image is too big to fit on a mobile phone. As a result, our user will need to scroll horizontally to view the image. But we can fix this by specifying an image size.", - "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the images width.", - "Create a class called narrow-image and added it to the image element. Change the width to 200 pixels." - ], - "tests": [ - "expect($('img')).to.have.class('narrow-image');", - "expect($('img')).to.have.css('width', 200px)" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9bedf08813", - "name": "Add a Border Around an Element", - "difficulty" : "0.20", - "description": [ - "Create a class called \"thick-green-border\" that puts a 5-pixel-wide black border around your cat photo.", - "CSS Borders have attributes like style, color and width.", - "We've created an example border around your h1 element. See if you can add a 10-pixel-wide green border around your cat photo." - ], - "tests": [ - "expect($('img')).to.have.class('thick-green-border');", - "expect($('img')).to.have.css('border-color', 'rgb(0,255,0)'));", - "expect($('img')).to.have.css('border-width', '10px');" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08814", - "name": "Add Rounded Corners with a Border Radius", - "difficulty" : "0.21", - "description": [ - "Give your cat photo a border radius of 10 pixels.", - "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute called border-radius.", - "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." - ], - "tests": [ - "expect($('img')).to.have.class('thick-green-border');", - "expect($('img')).to.have.css('border-radius', '10px');" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08815", - "name": "Make an Image Circular with a Border Radius", - "difficulty" : "0.22", - "description": [ - "Give your cat photo a border-radius of 50%.", - "In addition to pixels, you can also specify a border-radius of a percentage." - ], - "tests": [ - "expect($('img')).to.have.css('border-radius', '50%');" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08816", - "name": "Use an Anchor Tag to Link to an External Page", - "difficulty" : "0.23", - "description": [ - "Create an anchor tag hyperlink that links to freecodecamp.com", - "" - ], - "tests": [ - "expect((/free(\\s+)?code(\\s+)?camp(\\s+)?/gi).test($('a').text())).to.be.true;", - "expect($('a').filter(function(index) { return /freecodecamp\\.com/gi.test($('a')[index]); }).length).to.eql(1);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "", - "
", - "This is a link to Google", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08817", - "name": "Make Named Anchors using the Hash Symbol", - "difficulty" : "0.24", - "description": [ - "Use the hash symbol(#) to turn the link to the bottom of the page into a named anchor.", - "Sometimes you want to add anchor elements to your website before you know where they will link.", - "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", - "Replace the href in the link to freecodecamp.com with a hash symbol to turn it into a named anchor." - ], - "tests": [ - "expect((/this link leads nowhere/gi).test($('a').text())).to.be.true;", - "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(1);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "", - "
", - "This named anchor leads nowhere", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08820", - "name": "Turn an Image into a Link", - "difficulty" : "0.25", - "description": [ - "Wrap the gray cat's image with an anchor tag that leads nowhere.", - "You can make elements into links by wrapping them in an anchor tag.", - "Check out the example snow-colored cat's photo. When you hover over it with your cursor, you'll see the finger pointer you usually see when you hover over a link. The photo is now a link.", - "Wrap your gray cat's photo in an anchor tag", - "Use the hash symbol as the anchor tag's href." - ], - "tests": [ - "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08818", - "name": "Add Alt Text to an image", - "difficulty" : "0.26", - "description": [ - "Add the alt text \"a photo of a cute gray cat\" to our cat photo", - "alt text is what browsers will display if they fail to load the image. alt text is also important for blind or visually impaired users to understand what an image portrays. Search engines also look at alt text.", - "In short, every image should have alt text!", - "You can add alt text right in the image tag, like we've done here with the \"cute white cat\" image." - ], - "tests": [ - "expect($('img').filter(function(){ return /cat/gi.test(this.alt) }).length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "\"a", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad88fee1348bd9aedf08825", - "name": "Adjusting the Padding of an Element", - "difficulty" : "0.27", - "description": [ - "Change the padding of the green box to match that of the red box.", - "An element's padding controls the amount of space between an element and its border.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more padding than the green box.", - "When you increase the green box's padding, it will increase the distance between the word \"padding\" and the border around the text." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding', '20px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08822", - "name": "Adjust the Margin of an Element", - "difficulty" : "0.28", - "description": [ - "Change the margin of the green box to match that of the red box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", - "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '20px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08823", - "name": "Add a Negative Margin to an Element", - "difficulty" : "0.29", - "description": [ - "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "If you set an element's margin to a negative value, the element will grow larger.", - "Try to set the margin to a negative value like the one for the red box." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '-15px')" - ], - "challengeSeed": [ - "", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08824", - "name": "Add Different Padding to Each Side of an Element TEST", - "difficulty" : "0.30", - "description": [ - "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has different padding on each of its sides.", - "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding-bottom', '20px')", - "expect($('.green-box')).to.have.css('padding-left', '40px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1248bd9aedf08824", - "name": "Add Different a Margin to Each Side of an Element TEST", - "difficulty" : "0.31", - "description": [ - "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", - "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08826", - "name": "Use Clockwise Notation to Specify an Element's Padding", - "difficulty" : "0.32", - "description": [ - "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Instead of specifying an element's 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;.", - "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", - "You can also use this notation for margins!" - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9acde08812", - "name": "Use Bootstrap for Responsive Images", - "difficulty" : "0.33", - "description": [ - "Add the img-responsive Bootstrap class to the image.", - "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", - "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", - "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", - "Now all you need to do is add the img-responsive class to your image." - ], - "tests": [ - "expect($('img')).to.have.class('img-responsive');" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "This is a link to Google", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd8acde08812", - "name": "Center Text with Bootstrap", - "difficulty" : "0.34", - "description": [ - "Add Bootstrap's text-center class to your h2 element.", - "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", - "Note that you can add several classes to the same element by seperating each of them with a space, like this: <h2 class=\"text-red text-center\">your text</h2>." - ], - "tests": [ - "expect($('h2')).to.have.class('text-center');" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acde08812", - "name": "Create a Button", - "difficulty" : "0.35", - "description": [ - "Create a button with the text \"Delete\" using the HTML button element.", - "HTML has special elements that function like links, but look like buttons. Let's creating a default HTML button." - ], - "tests": [ - "expect((/delete/gi).test($('button').text())).to.be.true;" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acdf08812", - "name": "Create a Bootstrap Button", - "difficulty" : "0.36", - "description": [ - "Apply the Bootstrap's btn class to both of your buttons.", - "Bootstrap has its own button styles, which look much better than the plain HTML ones." - ], - "tests": [ - "expect($('.btn').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acef08812", - "name": "Create a Block Element Bootstrap Button", - "difficulty" : "0.37", - "description": [ - "Add Bootstrap's btn-block class to both of your buttons.", - "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", - "Note that these buttons still need the btn class." - ], - "tests": [ - "expect($('.btn-block').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acef08812", - "name": "Color a Bootstrap Button with Button Primary", - "difficulty" : "0.38", - "description": [ - "Add Bootstrap's btn-block class to both of your buttons.", - "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", - "Note that these buttons still need the btn class." - ], - "tests": [ - "expect($('.btn-block').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acef08812", - "name": "Color a Bootstrap Button with Button Primary", - "difficulty" : "0.39", - "description": [ - "Add Bootstrap's btn-primary class to both of your buttons.", - "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", - "Note that these buttons still need the btn and btn-block classes." - ], - "tests": [ - "expect($('.btn-primary').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348ce8acef08812", - "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", - "difficulty" : "0.40", - "description": [ - "Change the \"Delete\" button from btn-primary to btn-danger.", - "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.", - "Note that this button still needs the btn and btn-block classes." - ], - "tests": [ - "expect($('.btn-danger').length).to.eql(1);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad88fee1348ce8acef08812", - "name": "Use the Bootstrap Grid to Put Two Elements Side By Side", - "difficulty" : "0.41", - "description": [ - "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", - "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.", - "The row class is applied to a div, and the buttons themselves can be nested within it." - ], - "tests": [ - "expect($('.row').length).to.eql(2);", - "expect($('.col-xs-12').length).to.eql(4);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "
", - "
", - " ", - "
", - "
", - " ", - "
", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad89fee1348ce8acef08812", - "name": "Wrap Side By Side Elements in a Bootstrap Row", - "difficulty" : "0.42", - "description": [ - "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", - "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.", - "The row class is applied to a div, and the buttons themselves can be nested within it." - ], - "tests": [ - "expect($('.row').length).to.eql(2);", - "expect($('.col-xs-12').length).to.eql(4);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "
", - "
", - " ", - "
", - "
", - " ", - "
", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - { - "_id" : "bad87fee1348bd9aedf08813", - "name": "Add Alt Text to an Image TEST", - "difficulty" : "0.43", - "description": [ - "Add the alt text \"A picture of a gray cat\" to the image.", - "Alt text is a useful way to tell people (and web crawlers like Google) what is pictured in a photo. It's extremely important for helping blind or visually impaired people understand the content of your website.", - "You can add alt text right in the img element like this: <img src=\"www.your-image-source.com/your-image.jpg\" alt=\"your alt text\"/>." - ], - "tests": [ - "expect((/cat/gi).test($('img').attr('alt')).to.be.true;" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - } -] diff --git a/seed_data/challenges/basics.json b/seed_data/challenges/basics.json new file mode 100644 index 0000000000..16134aa92f --- /dev/null +++ b/seed_data/challenges/basics.json @@ -0,0 +1,59 @@ +{ + "name": "basics", + "order" : 0.001, + "challenges": [ + { + "_id": "bd7126d8c441eddfaeb5bd3e", + "name": "Meet Other Campers in your City", + "difficulty": 0.065, + "challengeSeed": "127358841", + "description": [ + "One of the best ways to stay motivated when learning to code is to hang out with other campers.", + "Slack and Camper News are great ways to communicate with other campers, but there's no substitute for meeting people in-person.", + "The easiest way to meet other campers in your city is to join your city's Facebook Group. Click here to view our growing list of local groups.", + "Click the link to your city, then, once Facebook loads, click \"Join group\".", + "Our local groups are new, so if you don't see your city on this list, you should follow the directions to create a Facebook group for your city.", + "If you don't have a Facebook account, we strongly recommend you create one, even if it's just for the purpose of coordinating with campers in your city through this group.", + "Our groups allow you to create events, coordinate those events, and share photos from the events afterward.", + "Whether you're hosting a study group, pair programming at your local library, or going to a weekend hackathon, your city's group will help you make it happen." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7137d8c441eddfaeb5bdef", + "name": "Get Help the Hacker Way with RSAP", + "difficulty": 0.07, + "challengeSeed": "125407432", + "description": [ + "Let's cover one last thing before you start working through our lessons: how to get help.", + "Any time you get stuck or don't know what to do next, follow this simple algorithm (procedure): RSAP (Read, Search, Ask, Post).", + "First, R - Read the documentation or error message. A key skill that good coders have is the ability to interpret and then follow instructions.", + "Next, 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.", + "Then, if you still haven't found an answer to your question, A - Ask your friends. If you have trouble, you can ask your fellow campers. We have a special chat room specifically for getting help with tools you learn through these Free Code Camp Challenges. Go to https://freecode.slack.com/messages/help/. Keep this chat open while you work on the remaining challenges.", + "Finally, P - Post on Stack Overflow. Before you attempt to do this, read Stack Overflow's guide to asking good questions: http://stackoverflow.com/help/how-to-ask.", + "Here's our detailed field guide on getting help: http://freecodecamp.com/field-guide/how-do-i-get-help-when-i-get-stuck.", + "Now you have a clear algorithm to follow when you need help! Let's start coding! Move on to your next challenge." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7127d8c441eddfaeb5bdef", + "name": "Build a Landing Page with HTML", + "difficulty": 0.08, + "challengeSeed": "125671867", + "description": [ + "Now it's time for us to start our actual coding lessons. We've curated a series of free, self-paced, browser-based lessons from providers like Codecademy and Stanford University.", + "These lessons will cover a lot of ground quickly, and will hold your hand throughout the process. Don't try to memorize everything - you'll spend more than a thousand hours practicing these later, and you can always look things up. Just keep moving.", + "If you've learned HTML and CSS before, these next few Waypoints will be a valuable review. If you haven't learned HTML or CSS before, you're in for a treat!", + "This Codecademy will quickly cover HTML, CSS and even Responsive Design with Bootstrap.", + "If you don't already have a Codecademy account, create one here: http://www.codecademy.com.", + "Go to http://www.codecademy.com/en/skills/make-a-website/topics/html-elements and complete the section.", + "Once you're done, mark this Waypoint complete and move on the next Waypoint." + ], + "challengeType": 2, + "tests": [] + } + ] +} \ No newline at end of file diff --git a/seed_data/challenges/prepwork.json b/seed_data/challenges/prepwork.json new file mode 100644 index 0000000000..3049d6c31a --- /dev/null +++ b/seed_data/challenges/prepwork.json @@ -0,0 +1,55 @@ +[ + { + "_id": "bd7124d8c441eddfaeb5bdef", + "name": "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 a community of busy people learning to code by building projects for nonprofits.", + "We built this community because learning to code is hard. But anyone who can stay motivated can learn to code. And to stay motivated, you just need to:
  1. make friends with people who code
  2. code a little every day
    1. ", + "All our challenges are
      1. free
      2. self-paced
      3. browser-based
      ", + "We'll spend
      1. 200 hours learning tools like HTML, CSS, JavaScript, Node.js and databases
      2. 600 hours building practice projects
      3. 800 hours building full stack solutions for nonprofits
      ", + "By the end, we'll
      1. be good at coding
      2. have the portfolio of apps with happy users to prove it
      ", + "Once you make it through Free Code Camp, you will be able to get a coding job. There are far more job openings out there than there are qualified coders to fill them.", + "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": [] + }, + { + "_id": "bd7125d8c441eddfaeb5bd0f", + "name": "Join Our Chat Room", + "difficulty": 0.02, + "challengeSeed": "124555254", + "description": [ + "Now we're going to join the Free Code Camp chat room. You can come here any time of day to hang out, ask questions, or find another camper to pair program with.", + "Make sure your Free Code Camp account includes your email address. You can do this here: http://freecodecamp.com/account.", + "Click this link, which will email you an invite to Free Code Camp's Slack chat room: http://freecodecamp.com/api/slack.", + "Now check your email and click the link in the email from Slack", + "Complete the sign up process, then update your biographical information and upload an image. A picture of your face works best. This is how people will see you in the chat room, so put your best foot forward.", + "Now enter the general chat room and introduce yourself to our chat room by typing: \"hello world!\".", + "Note that you're expected to follow our Code of Conduct: http://freecodecamp.com/field-guide/what-is-the-free-code-camp-code-of-conduct?", + "Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code.", + "Keep the chat room open while you work through the other challenges. That way you ask for help if you get stuck on a challenge. You can also socialize when you feel like taking a break.", + "You can also access this chat room by clicking the \"Chat\" button in the upper right hand corner." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7125d8c441eddfaeb5bdff", + "name": "Preview our Challenge Map", + "difficulty": 0.03, + "challengeSeed": "125407437", + "description": [ + "Before you start learning how to code, we'd like to introduce you to a few things.", + "Let's look at our Challenge Map. Click on the \"Map\" button in the upper right hand corner. This map shows all the challenges that will teach you how to code.", + "You should complete all these challenges in order.", + "Once you finish these Waypoint challenges, you'll move on to Bonfires (algorithm practice), then Ziplines (front end development practice) and finally Basejumps (full stack development practice). After that, you'll start building projects for nonprofits.", + "This challenge map is just for your reference. When you return to FreeCodeCamp.com, we'll automatically redirect you to the next challenge that you should be doing." + ], + "challengeType": 2, + "tests": [] + } +] \ No newline at end of file diff --git a/seed_data/seed.js b/seed_data/seed.js index 95c35b328f..fc87f56d02 100644 --- a/seed_data/seed.js +++ b/seed_data/seed.js @@ -1,96 +1,78 @@ require('dotenv').load(); -var Bonfire = require('../models/Bonfire.js'), - Courseware = require('../models/Courseware.js'), - FieldGuide = require('../models/FieldGuide.js'), - Nonprofit = require('../models/Nonprofit.js'), - mongoose = require('mongoose'), - secrets = require('../config/secrets'), - coursewares = require('./coursewares.json'), - fieldGuides = require('./field-guides.json'), - nonprofits = require('./nonprofits.json'), - bonfires = require('./bonfires.json'); +var Challenge = require('../models/Challenge.js'), + FieldGuide = require('../models/FieldGuide.js'), + Nonprofit = require('../models/Nonprofit.js'), + mongoose = require('mongoose'), + secrets = require('../config/secrets'), + fieldGuides = require('./field-guides.json'), + nonprofits = require('./nonprofits.json'), + fs = require('fs'); mongoose.connect(secrets.db); +var challenges = fs.readdirSync(__dirname + '/challenges'); var counter = 0; -var offerings = 4; +var offerings = 3; var CompletionMonitor = function() { - counter++; - console.log('call ' + counter); + counter++; + console.log('call ' + counter); - if (counter < offerings) { - return; - } else { - process.exit(0); - } + if (counter < offerings) { + return; + } else { + process.exit(0); + } }; - -Bonfire.remove({}, function(err, data) { - if (err) { - console.error(err); - } else { - console.log('Deleted ', data); - } - Bonfire.create(bonfires, function(err, data) { - if (err) { - console.log(err); - } else { - console.log('Saved ', data); - } - CompletionMonitor(); +Challenge.remove({}, function(err, data) { + if (err) { + console.err(err); + } else { + console.log('Deleted ', data); + } + challenges.forEach(function (file) { + Challenge.create(require('./challenges/' + file), function (err, data) { + if (err) { + console.log(err); + } else { + console.log('Successfully parsed %s', file); + } }); - console.log('bonfires'); + }); }); - -Courseware.remove({}, function(err, data) { - if (err) { - console.error(err); - } else { - console.log('Deleted ', data); - } - Courseware.create(coursewares, function(err, data) { - if (err) { - console.log(err); - } else { - console.log('Saved ', data); - } - CompletionMonitor(); - }); - console.log('coursewares'); -}); - +/* FieldGuide.remove({}, function(err, data) { + if (err) { + console.error(err); + } else { + console.log('Deleted ', data); + } + FieldGuide.create(fieldGuides, function(err, data) { if (err) { - console.error(err); + console.log(err); } else { - console.log('Deleted ', data); + console.log('Saved ', data); } - FieldGuide.create(fieldGuides, function(err, data) { - if (err) { - console.log(err); - } else { - console.log('Saved ', data); - } - CompletionMonitor(); - }); - console.log('field guides'); + CompletionMonitor(); + }); + console.log('field guides'); }); Nonprofit.remove({}, function(err, data) { + if (err) { + console.error(err); + } else { + console.log('Deleted ', data); + } + Nonprofit.create(nonprofits, function(err, data) { if (err) { - console.error(err); + console.log(err); } else { - console.log('Deleted ', data); + console.log('Saved ', data); } - Nonprofit.create(nonprofits, function(err, data) { - if (err) { - console.log(err); - } else { - console.log('Saved ', data); - } - CompletionMonitor(); - }); - console.log('nonprofits'); + CompletionMonitor(); + }); + console.log('nonprofits'); }); +*/