diff --git a/README.md b/README.md index 9b0c87d631..0611cd1816 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Our campers (students) start by working through our free, self-paced, browser-ba 80% of our campers are over 25, and nearly a fifth of our campers are women. -This code is running live at [FreeCodeCamp.com](http://www.FreeCodeCamp.com). We also have [Gitter](https://gitter.im/FreeCodeCamp/FreeCodeCamp), a [blog](http://blog.freecodecamp.com), and even a [Twitch.tv channel](http://twitch.tv/freecodecamp). +This code is running live at [FreeCodeCamp.com](http://www.FreeCodeCamp.com). We also have [Gitter](https://gitter.im/FreeCodeCamp/FreeCodeCamp), a [blog](http://medium.freecodecamp.com), and even a [Twitch.tv channel](http://twitch.tv/freecodecamp). [Join our community here](http://www.freecodecamp.com/signin). @@ -54,22 +54,26 @@ The easiest way to get started is to clone the repository: # Get the latest snapshot git clone --depth=1 https://github.com/freecodecamp/freecodecamp.git freecodecamp +# Change directory cd freecodecamp # Install NPM dependencies npm install +# Install Gulp globally +npm install -g gulp + +# Install Bower globally +npm install -g bower + # Install Bower dependencies bower install # Create a .env file and populate it with the necessary API keys and secrets: touch .env - -# Install Gulp globally -npm install -g gulp ``` -Edit your `.env` file with the following API keys accordingly (if you only use email login, only the `MONGOHQ_URL`, `SESSION_SECRET`, `MANDRILL_USER` and `MANDRILL_PASSWORD` fields are necessary. Keep in mind if you want to use more services you'll have to get your own API keys for those services. +Edit your `.env` file with the following API keys accordingly. If you only use email login, only the `MONGOHQ_URL`, `SESSION_SECRET`, `MANDRILL_USER` and `MANDRILL_PASSWORD` fields are necessary. Keep in mind if you want to use more services you'll have to get your own API keys for those services. If you only use a subset or no OAuth2 authentication methods, you may want to remove them from ```server/passport-providers.js``` - otherwise the server will complain about missing clientIDs at launch. ``` MONGOHQ_URL='mongodb://localhost:27017/freecodecamp' @@ -107,20 +111,20 @@ DEBUG=true ``` ```bash -# Start the mongo server +# Start the mongo server in a seperate terminal mongod -# Create your mongo database. -# Type "mongo" in your terminal to access the mongo shell -use freecodecamp -# Exit the mongo shell with control + d - -# Seed your database with the challenges -node seed/ +# Initialize Free Code Camp +# This will seed the database for the first time. +# This command should only be run once. +npm run first-time # start the application gulp ``` +Now navigate to your browser and open http://localhost:3001 +If the app loads, congratulations - you're all set. Otherwise, let us know by opening a GitHub issue and with your error. + License ------- diff --git a/client/commonFramework.js b/client/commonFramework.js index a28a1e743d..2505fe08f4 100644 --- a/client/commonFramework.js +++ b/client/commonFramework.js @@ -374,8 +374,9 @@ var editor = (function(CodeMirror, emmetCodeMirror, common) { } var editor = CodeMirror.fromTextArea(document.getElementById('codeEditor'), { + lint: true, lineNumbers: true, - mode: 'text', + mode: 'javascript', theme: 'monokai', runnable: true, matchBrackets: true, @@ -529,6 +530,20 @@ function safeHTMLRun(test) { // add feuxQuery s = 'var document = \"\"; var $ = function() {return(new function() {this.add=function() {return(this);};this.addBack=function() {return(this);};this.addClass=function() {return(this);};this.after=function() {return(this);};this.ajaxComplete=function() {return(this);};this.ajaxError=function() {return(this);};this.ajaxSend=function() {return(this);};this.ajaxStart=function() {return(this);};this.ajaxStop=function() {return(this);};this.ajaxSuccess=function() {return(this);};this.andSelf=function() {return(this);};this.animate=function() {return(this);};this.append=function() {return(this);};this.appendTo=function() {return(this);};this.attr=function() {return(this);};this.before=function() {return(this);};this.bind=function() {return(this);};this.blur=function() {return(this);};this.callbacksadd=function() {return(this);};this.callbacksdisable=function() {return(this);};this.callbacksdisabled=function() {return(this);};this.callbacksempty=function() {return(this);};this.callbacksfire=function() {return(this);};this.callbacksfired=function() {return(this);};this.callbacksfireWith=function() {return(this);};this.callbackshas=function() {return(this);};this.callbackslock=function() {return(this);};this.callbackslocked=function() {return(this);};this.callbacksremove=function() {return(this);};this.change=function() {return(this);};this.children=function() {return(this);};this.clearQueue=function() {return(this);};this.click=function() {return(this);};this.clone=function() {return(this);};this.closest=function() {return(this);};this.contents=function() {return(this);};this.context=function() {return(this);};this.css=function() {return(this);};this.data=function() {return(this);};this.dblclick=function() {return(this);};this.delay=function() {return(this);};this.delegate=function() {return(this);};this.dequeue=function() {return(this);};this.detach=function() {return(this);};this.die=function() {return(this);};this.each=function() {return(this);};this.empty=function() {return(this);};this.end=function() {return(this);};this.eq=function() {return(this);};this.error=function() {return(this);};this.fadeIn=function() {return(this);};this.fadeOut=function() {return(this);};this.fadeTo=function() {return(this);};this.fadeToggle=function() {return(this);};this.filter=function() {return(this);};this.find=function() {return(this);};this.finish=function() {return(this);};this.first=function() {return(this);};this.focus=function() {return(this);};this.focusin=function() {return(this);};this.focusout=function() {return(this);};this.get=function() {return(this);};this.has=function() {return(this);};this.hasClass=function() {return(this);};this.height=function() {return(this);};this.hide=function() {return(this);};this.hover=function() {return(this);};this.html=function() {return(this);};this.index=function() {return(this);};this.innerHeight=function() {return(this);};this.innerWidth=function() {return(this);};this.insertAfter=function() {return(this);};this.insertBefore=function() {return(this);};this.is=function() {return(this);};this.jQuery=function() {return(this);};this.jquery=function() {return(this);};this.keydown=function() {return(this);};this.keypress=function() {return(this);};this.keyup=function() {return(this);};this.last=function() {return(this);};this.length=function() {return(this);};this.live=function() {return(this);};this.load=function() {return(this);};this.load=function() {return(this);};this.map=function() {return(this);};this.mousedown=function() {return(this);};this.mouseenter=function() {return(this);};this.mouseleave=function() {return(this);};this.mousemove=function() {return(this);};this.mouseout=function() {return(this);};this.mouseover=function() {return(this);};this.mouseup=function() {return(this);};this.next=function() {return(this);};this.nextAll=function() {return(this);};this.nextUntil=function() {return(this);};this.not=function() {return(this);};this.off=function() {return(this);};this.offset=function() {return(this);};this.offsetParent=function() {return(this);};this.on=function() {return(this);};this.one=function() {return(this);};this.outerHeight=function() {return(this);};this.outerWidth=function() {return(this);};this.parent=function() {return(this);};this.parents=function() {return(this);};this.parentsUntil=function() {return(this);};this.position=function() {return(this);};this.prepend=function() {return(this);};this.prependTo=function() {return(this);};this.prev=function() {return(this);};this.prevAll=function() {return(this);};this.prevUntil=function() {return(this);};this.promise=function() {return(this);};this.prop=function() {return(this);};this.pushStack=function() {return(this);};this.queue=function() {return(this);};this.ready=function() {return(this);};this.remove=function() {return(this);};this.removeAttr=function() {return(this);};this.removeClass=function() {return(this);};this.removeData=function() {return(this);};this.removeProp=function() {return(this);};this.replaceAll=function() {return(this);};this.replaceWith=function() {return(this);};this.resize=function() {return(this);};this.scroll=function() {return(this);};this.scrollLeft=function() {return(this);};this.scrollTop=function() {return(this);};this.select=function() {return(this);};this.selector=function() {return(this);};this.serialize=function() {return(this);};this.serializeArray=function() {return(this);};this.show=function() {return(this);};this.siblings=function() {return(this);};this.size=function() {return(this);};this.slice=function() {return(this);};this.slideDown=function() {return(this);};this.slideToggle=function() {return(this);};this.slideUp=function() {return(this);};this.stop=function() {return(this);};this.submit=function() {return(this);};this.text=function() {return(this);};this.toArray=function() {return(this);};this.toggle=function() {return(this);};this.toggle=function() {return(this);};this.toggleClass=function() {return(this);};this.trigger=function() {return(this);};this.triggerHandler=function() {return(this);};this.unbind=function() {return(this);};this.undelegate=function() {return(this);};this.unload=function() {return(this);};this.unwrap=function() {return(this);};this.val=function() {return(this);};this.width=function() {return(this);};this.wrap=function() {return(this);};this.wrapAll=function() {return(this);};this.wrapInner=function() {return(this);}});};$.ajax=function() {return($);};$.ajaxPrefilter=function() {return($);};$.ajaxSetup=function() {return($);};$.ajaxTransport=function() {return($);};$.boxModel=function() {return($);};$.browser=function() {return($);};$.Callbacks=function() {return($);};$.contains=function() {return($);};$.cssHooks=function() {return($);};$.cssNumber=function() {return($);};$.data=function() {return($);};$.Deferred=function() {return($);};$.dequeue=function() {return($);};$.each=function() {return($);};$.error=function() {return($);};$.extend=function() {return($);};$.fnextend=function() {return($);};$.fxinterval=function() {return($);};$.fxoff=function() {return($);};$.get=function() {return($);};$.getJSON=function() {return($);};$.getScript=function() {return($);};$.globalEval=function() {return($);};$.grep=function() {return($);};$.hasData=function() {return($);};$.holdReady=function() {return($);};$.inArray=function() {return($);};$.isArray=function() {return($);};$.isEmptyObject=function() {return($);};$.isFunction=function() {return($);};$.isNumeric=function() {return($);};$.isPlainObject=function() {return($);};$.isWindow=function() {return($);};$.isXMLDoc=function() {return($);};$.makeArray=function() {return($);};$.map=function() {return($);};$.merge=function() {return($);};$.noConflict=function() {return($);};$.noop=function() {return($);};$.now=function() {return($);};$.param=function() {return($);};$.parseHTML=function() {return($);};$.parseJSON=function() {return($);};$.parseXML=function() {return($);};$.post=function() {return($);};$.proxy=function() {return($);};$.queue=function() {return($);};$.removeData=function() {return($);};$.sub=function() {return($);};$.support=function() {return($);};$.trim=function() {return($);};$.type=function() {return($);};$.unique=function() {return($);};$.when=function() {return($);};$.always=function() {return($);};$.done=function() {return($);};$.fail=function() {return($);};$.isRejected=function() {return($);};$.isResolved=function() {return($);};$.notify=function() {return($);};$.notifyWith=function() {return($);};$.pipe=function() {return($);};$.progress=function() {return($);};$.promise=function() {return($);};$.reject=function() {return($);};$.rejectWith=function() {return($);};$.resolve=function() {return($);};$.resolveWith=function() {return($);};$.state=function() {return($);};$.then=function() {return($);};$.currentTarget=function() {return($);};$.data=function() {return($);};$.delegateTarget=function() {return($);};$.isDefaultPrevented=function() {return($);};$.isImmediatePropagationStopped=function() {return($);};$.isPropagationStopped=function() {return($);};$.metaKey=function() {return($);};$.namespace=function() {return($);};$.pageX=function() {return($);};$.pageY=function() {return($);};$.preventDefault=function() {return($);};$.relatedTarget=function() {return($);};$.result=function() {return($);};$.stopImmediatePropagation=function() {return($);};$.stopPropagation=function() {return($);};$.target=function() {return($);};$.timeStamp=function() {return($);};$.type=function() {return($);};$.which=function() {return($);};' + s; + // add spoofigator + + s = " var navigator = " + + "function(){" + + " this.geolocation=function(){" + + " this.getCurrentPosition=function(){" + + " this.coords = {latitude: \"\", longitude: \"\"};" + + " return(this);" + + " };" + + " return(this);" + + " };" + + " return(this);" + + "};" + s; + sandBox.submit(scopejQuery(s), function(cls, message) { if (cls) { console.log(message.error); diff --git a/client/less/chat.less b/client/less/chat.less new file mode 100644 index 0000000000..a6f83171ca --- /dev/null +++ b/client/less/chat.less @@ -0,0 +1,24 @@ +.chat-embed-main-title { + display: flex; + flex-grow: 1; + padding-left: 31px; + padding-top: 7px; +} + +.gitter-chat-embed { + z-index: 100; + position: fixed; + + top: 0; + left: 60%; + bottom: 0; + right: 0; + + display: flex; + flex-direction: row; + transition: transform 0.3s cubic-bezier(0.16, 0.22, 0.22, 1.7); +} + +.gitter-chat-embed.is-collapsed:not(.is-loading) { + transform: translateX(110%); +} diff --git a/client/less/main.less b/client/less/main.less index 4340350da7..aa70867894 100644 --- a/client/less/main.less +++ b/client/less/main.less @@ -96,6 +96,10 @@ h1, h2, h3, h4, h5, h6, p, li { margin-right: 5px; } +.fa:hover { + text-decoration: none; +} + .img-center { margin: 0 auto; } @@ -951,6 +955,11 @@ code { margin: 0!important; } +// gitter chat +.gitter-chat-embed { + z-index: 20000 !important; +} + //uncomment this to see the dimensions of all elements outlined in red //* { // border-color: red; @@ -1058,3 +1067,5 @@ code { transform: rotate(0deg); } } + +@import "chat.less"; diff --git a/client/main.js b/client/main.js index 892610e1eb..6f147abcf7 100644 --- a/client/main.js +++ b/client/main.js @@ -4,6 +4,105 @@ main.mapShareKey = 'map-shares'; main.ga = window.ga || function() {}; +main = (function(main) { + + // should be set before gitter script loads + ((window.gitter = {}).chat = {}).options = { + disableDefaultChat: true + }; + // wait for sidecar to load + + main.chat = {}; + main.chat.isOpen = false; + main.chat.createHelpChat = function createHelpChat() { + throw new Error('Sidecar chat has not initialized'); + }; + + document.addEventListener('gitter-sidecar-ready', function(e) { + main.chat.GitterChat = e.detail.Chat; + + main.chat.createHelpChat = function(room, helpChatBtnClass, roomTitle) { + roomTitle = roomTitle || 'Waypoint Help'; + + $('body').append( + '' + ); + + main.chat.helpChat = new main.chat.GitterChat({ + room: room, + activationElement: false, + targetElement: $('#chat-embed-help') + }); + + $(helpChatBtnClass).on('click', function() { + // is button already pressed? + // no? open chat + // yes? close chat + var shouldChatBeOpen = !$(this).hasClass('active'); + main.chat.helpChat.toggleChat(shouldChatBeOpen); + if (shouldChatBeOpen) { + $(helpChatBtnClass).addClass('active'); + } + }); + + var helpTitleAdd = false; + $('#chat-embed-help').on('gitter-chat-toggle', function(e) { + var shouldButtonBePressed = !!e.originalEvent.detail.state; + + if (!helpTitleAdd) { + helpTitleAdd = true; + $('#chat-embed-help > .gitter-chat-embed-action-bar').prepend( + '
' + ); + } + + if (shouldButtonBePressed) { + return $(helpChatBtnClass).addClass('active'); + } + return $(helpChatBtnClass).removeClass('active'); + }); + }; + + $('body').append( + '' + ); + + main.chat.mainChat = new main.chat.GitterChat({ + room: 'freecodecamp/freecodecamp', + activationElement: false, + targetElement: $('#chat-embed-main') + }); + + var mainChatTitleAdded = false; + $('#chat-embed-main').on('gitter-chat-toggle', function() { + if (mainChatTitleAdded) { + return null; + } + mainChatTitleAdded = true; + + $('#chat-embed-main > .gitter-chat-embed-action-bar').prepend( + ' ' + ); + }); + + + $('#nav-chat-btn').on('click', function() { + if (!main.chat.isOpen) { + + main.chat.mainChat.toggleChat(true); + } + }); + }); + + return main; +}(main)); + var lastCompleted = typeof lastCompleted !== 'undefined' ? lastCompleted : ''; @@ -38,9 +137,10 @@ function setMapShare(id) { $(document).ready(function() { + var challengeName = typeof challengeName !== 'undefined' ? challengeName : - 'Untitled'; + ''; if (challengeName) { ga('send', 'event', 'Challenge', 'load', challengeName); @@ -135,7 +235,7 @@ $(document).ready(function() { 'links to screenshots if possible.\n\n' ].join(''); - if (editor.getValue().trim()) { + if (typeof editor !== 'undefined' && editor.getValue().trim()) { var type; switch (challengeType) { case challengeTypes.HTML_CSS_JQ: diff --git a/common/app/components/Footer/links.json b/common/app/components/Footer/links.json index 92199b127f..8089a868e4 100644 --- a/common/app/components/Footer/links.json +++ b/common/app/components/Footer/links.json @@ -2,7 +2,7 @@ { "className": "ion-speakerphone", "content": " Blog ", - "href": "http://blog.freecodecamp.com", + "href": "http://medium.freecodecamp.com", "target": "_blank" }, { diff --git a/common/models/challenge.json b/common/models/challenge.json index 84cf3a4c6b..81d6af6eef 100644 --- a/common/models/challenge.json +++ b/common/models/challenge.json @@ -82,6 +82,10 @@ }, "descriptionPt": { "type": "array" + }, + "solutions": { + "type": "array", + "default": [] } }, "validations": [], diff --git a/gulpfile.js b/gulpfile.js index fd5fdda38d..4ae0d93d23 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -79,6 +79,7 @@ var paths = { ], less: './client/less/main.less', + lessFiles: './client/less/*.less', manifest: 'server/manifests/', @@ -392,7 +393,7 @@ var watchDependents = [ ]; gulp.task('watch', watchDependents, function() { - gulp.watch(paths.less, ['less']); + gulp.watch(paths.lessFiles, ['less']); gulp.watch(paths.js, ['js']); gulp.watch(paths.challenges, ['test-challenges']); gulp.watch(paths.js, ['js', 'dependents']); diff --git a/package.json b/package.json index 06d6a933ce..1c6f77559a 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,8 @@ "url": "https://github.com/freecodecamp/freecodecamp.git" }, "scripts": { + "first-time": "npm run create-rev && echo '\n\nseeding database\n\n' && node seed && node seed/nonprofits", + "create-rev": "test ! -e server/rev-manifest.json && echo '\n\ncreating manifest\n\n' && touch server/rev-manifest.json && echo '{}' >> server/rev-manifest.json", "build": "gulp build", "start": "babel-node server/server.js", "prestart-production": "bower cache clean && bower install && gulp build", @@ -49,6 +51,13 @@ "forever": "~0.14.1", "frameguard": "^0.2.2", "github-api": "~0.7.0", + "gulp": "~3.8.8", + "gulp-eslint": "~0.9.0", + "gulp-inject": "~1.0.2", + "gulp-jsonlint": "^1.1.0", + "gulp-nodemon": "^2.0.3", + "gulp-notify": "^2.2.0", + "gulp-plumber": "^1.0.1", "gulp-less": "^3.0.3", "gulp-minify-css": "~0.5.1", "gulp-reduce-file": "0.0.1", @@ -114,13 +123,6 @@ "browserify": "^10.2.4", "chai": "~1.10.0", "envify": "^3.4.0", - "gulp": "~3.8.8", - "gulp-eslint": "~0.9.0", - "gulp-inject": "~1.0.2", - "gulp-jsonlint": "^1.1.0", - "gulp-nodemon": "^2.0.3", - "gulp-notify": "^2.2.0", - "gulp-plumber": "^1.0.1", "istanbul": "^0.3.15", "loopback-explorer": "^1.7.2", "loopback-testing": "^1.1.0", diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index 8ff025e2fe..04ab7c18b2 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -57,6 +57,9 @@ "MDNlinks": [ "RegExp" ], + "solutions": [ + "var re = /^(?:(?:\\+?1\\s*(?:[.-]\\s*)?)?(?:\\(\\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\\s*\\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\\s*(?:[.-]\\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\\s*(?:[.-]\\s*)?([0-9]{4})$/;\n\nfunction telephoneCheck(str) {\n return !!str.match(re);\n}\n\ntelephoneCheck(\"555-555-5555\");" + ], "type": "bonfire", "challengeType": 5, "nameCn": "", @@ -88,13 +91,15 @@ "tests": [ "assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 5, 4], 'message:sym([1, 2, 3], [5, 2, 1, 4])
should return [3, 5, 4]
.');",
"assert.sameMembers(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'message: sym([1, 2, 5], [2, 3, 5], [3, 4, 5])
should return [1, 4, 5]
');",
- "assert.sameMembers(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'message: sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])
should return [1, 4, 5]
.');",
- "assert.sameMembers(sym([1, 1]), [1], 'message: sym([1, 1])
should return [1]
.');"
- ],
+ "assert.sameMembers(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'message: sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])
should return [1, 4, 5]
.');"
+ ],
"MDNlinks": [
"Array.reduce()",
"Symmetric Difference"
],
+ "solutions": [
+ "function sym(args) {\n var index = -1;\n var length = arguments.length;\n var result;\n while (++index < length) {\n var array = arguments[index];\n result = result ? diff(result, array).concat(diff(array, result)) : array;\n }\n return result ? uniq(result) : [];\n}\n\nfunction uniq(arr) {\n var h = Object.create(null);\n var u = [];\n arr.forEach(function(v) {\n if (v in h) return;\n h[v] = true;\n u.push(v);\n });\n return u;\n}\n\nfunction diff(a, b) {\n var h = Object.create(null);\n b.forEach(function(v) {\n h[v] = true; \n });\n return a.filter(function(v) { return !(v in h);});\n}\nsym([1, 2, 3], [5, 2, 1, 4]);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -151,6 +156,9 @@
"MDNlinks": [
"Global Object"
],
+ "solutions": [
+ "var VALUES = [1, 5, 10, 25, 100, 500, 1000, 2000, 10000];\n\nfunction drawer(price, cash, cid) {\n cash = ~~(cash * 100);\n price = ~~(price * 100);\n var diff = cash-price;\n cid.forEach(function(c) {\n c[1] = ~~(c[1] * 100);\n });\n var totalCid = cid.reduce(function(a, c) {\n return a + c[1];\n }, 0);\n if (diff > totalCid) {\n return \"Insufficient Funds\";\n }\n if (diff === totalCid) {\n return \"Closed\";\n }\n \n var change = []; \n var index = cid.length;\n while (diff > 0 && --index > -1) {\n var t = 0;\n var value = VALUES[index];\n while (diff >= value && cid[index][1] > 0) {\n t += value;\n cid[index][1] -= value;\n diff -= value;\n }\n if (t) {\n change.push([cid[index][0], t/100]);\n }\n console.log(JSON.stringify(change));\n }\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]]);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -205,6 +213,9 @@
"MDNlinks": [
"Global Array Object"
],
+ "solutions": [
+ "function inventory(arr1, arr2) {\n arr2.forEach(function(item) {\n createOrUpdate(arr1, item);\n });\n // All inventory must be accounted for or you're fired!\n return arr1;\n}\n\nfunction createOrUpdate(arr1, item) {\n var index = -1;\n while (++index < arr1.length) {\n if (arr1[index][1] === item[1]) {\n arr1[index][0] += item[0];\n return;\n }\n if (arr1[index][1] > item[1]) {\n break;\n }\n }\n arr1.splice(index, 0, item);\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);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -246,6 +257,9 @@
"Permutations",
"RegExp"
],
+ "solutions": [
+ "function permAlone(str) {\n return permutor(str).filter(function(perm) {\n return !perm.match(/(.)\\1/g);\n }).length;\n}\n\nfunction permutor(str) {\n // http://staff.roguecc.edu/JMiller/JavaScript/permute.html\n //permArr: Global array which holds the list of permutations\n //usedChars: Global utility array which holds a list of \"currently-in-use\" characters\n var permArr = [], usedChars = [];\n function permute(input) {\n //convert input into a char array (one element for each character)\n var i, ch, chars = input.split(\"\");\n for (i = 0; i < chars.length; i++) {\n //get and remove character at index \"i\" from char array\n ch = chars.splice(i, 1);\n //add removed character to the end of used characters\n usedChars.push(ch);\n //when there are no more characters left in char array to add, add used chars to list of permutations\n if (chars.length === 0) permArr[permArr.length] = usedChars.join(\"\");\n //send characters (minus the removed one from above) from char array to be permuted\n permute(chars.join(\"\"));\n //add removed character back into char array in original position\n chars.splice(i, 0, ch);\n //remove the last character used off the end of used characters array\n usedChars.pop();\n }\n }\n permute(str);\n return permArr;\n}\n\npermAlone('aab');\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -291,6 +305,9 @@
"String.substr()",
"parseInt()"
],
+ "solutions": [
+ "function friendly(str) {\n var dates = str.map(function(s) {return s.split('-').map(Number);});\n var start = dates[0];\n var end = dates[1];\n if (str[0] === str[1]) {\n return [readable(start)];\n }\n if (start[0] !== end[0]) {\n if (start[0] + 1 === end[0] && start[1] > end[1]) {\n start[0] = undefined;\n end[0] = undefined;\n }\n return dates.map(readable);\n }\n start[0] = undefined;\n end[0] = undefined;\n if (start[1] !== end[1]) {\n return dates.map(readable);\n }\n end[1] = undefined;\n return dates.map(readable);\n}\n\nfunction readable(arr) {\n var ordD = arr[2] + nth(arr[2]);\n if (!arr[1]) {\n return ordD;\n }\n return MONTH[arr[1]] + \" \" + ordD + (!arr[0] ? \"\" : \", \" + arr[0]);\n}\n\nvar MONTH = {1: \"January\",\n 2: \"February\",\n 3: \"March\",\n 4: \"April\",\n 5: \"May\",\n 6: \"June\",\n 7: \"July\",\n 8: \"August\",\n 9: \"September\",\n 10: \"October\",\n 11: \"November\",\n 12: \"December\"};\n\nfunction nth(d) {\n if(d>3 && d<21) return 'th';\n switch (d % 10) {\n case 1: return \"st\";\n case 2: return \"nd\";\n case 3: return \"rd\";\n default: return \"th\";\n }\n} \n\nfriendly(['2015-07-01', '2015-07-04']);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
diff --git a/seed/challenges/basejumps.json b/seed/challenges/basejumps.json
index 627e95482f..850a8a2a88 100644
--- a/seed/challenges/basejumps.json
+++ b/seed/challenges/basejumps.json
@@ -6,62 +6,100 @@
{
"id": "bd7158d8c443eddfaeb5bcef",
"title": "Get Set for Basejumps",
- "challengeSeed": ["128451852"],
+ "challengeSeed": [],
"description": [
- "Objective: Get the MEAN stack running on Cloud 9, push your code to GitHub, and deploy it to Heroku.",
- "We'll build our Basejumps on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.",
- "If you don't already have Cloud 9 account, create one now at http://c9.io.",
- "Now let's get your development environment ready for a new Angular-Fullstack application provided by Yeoman.",
- "Open up http://c9.io and sign in to your account.",
- "Click on the \"+\" icon at the top right of the c9.io page to create a new workspace.",
- "Give your workspace a name and an optional description.",
- "Choose Node.js in the selection area below the name field.",
- "Click the \"Create workspace\" button.",
- "Once C9 builds and loads your workspace, you should see a terminal window in the lower right hand corner. In this window use the following commands. You don't need to know what these mean at this point.",
- "Never run this command on your local machine. But in your Cloud 9 terminal window, run: rm -rf * && echo \"export NODE_PATH=$NODE_PATH:/home/ubuntu/.nvm/v0.10.35/lib/node_modules\" >> ~/.bashrc && source ~/.bashrc && npm install -g yo grunt grunt-cli generator-angular-fullstack && yo angular-fullstack
",
- "Yeoman will prompt you to answer some questions. Answer them like this:",
- "What would you like to write scripts with? JavaScript",
- "What would you like to write markup with? HTML",
- "What would you like to write stylesheets with? CSS",
- "What Angular router would you like to use? ngRoute",
- "Would you like to include Bootstrap? Yes",
- "Would you like to include UI Bootstrap? Yes",
- "Would you like to use MongoDB with Mongoose for data modeling? Yes",
- "Would you scaffold out an authentication boilerplate? Yes",
- "Would you like to include additional oAuth strategies? Twitter",
- "Would you like to use socket.io? No",
- "May bower anonymously report usage statistics to improve the tool over time? (Y/n) Y",
- "You may get an error similar to ERR! EEXIST, open ‘/home/ubuntu/.npm
. This is caused when Cloud9 runs out of memory and kills an install. If you get this, simply re-run this process with the command yo angular-fullstack
. You will then be asked a few questions regarding the re-install. Answer them as follows:",
- "Existing .yo-rc configuration found, would you like to use it? (Y/n) Y",
- "Overwrite client/favicon.ico? (Ynaxdh) Y",
- "To finish the installation run the commands: bower install && npm install
",
- "To start MongoDB, run the following commands in your terminal: mkdir data && echo 'mongod --bind_ip=$IP --dbpath=data --nojournal --rest \"$@\"' > mongod && chmod a+x mongod && ./mongod
",
- "You will want to open up a new terminal to work from by clicking on the + icon and select New Terminal",
- "Start the application by running the following command in your new terminal window: grunt serve
",
- "Wait for the following message to appear: xdg-open: no method available for opening 'http://localhost:8080'
. Now you can open the internal Cloud9 browser. To launch the browser select Preview in the toolbar then select the dropdown option Preview Running Application.",
- "Turn the folder in which your application is running into a Git repository by running the following commands: git init && git add . && git commit -am 'initial commit'
.",
- "Now we need to add your GitHub SSH key to c9.io. Click the \"Add-on Services\" button in the lower left of your C9 dashboard. Click \"activate\" next to the GitHub icon.",
- "A pop up will appear. Allow access to your account.",
- "While still on the dashboard, under “Account Settings”, click the link for \"Show your SSH key\". Copy the key to you clipboard.",
- "Sign in to http://github.com and navigate to the GitHub SSH settings page. Click the \"Add SSH Key\". Give your key the title \"cloud 9\". Paste your SSH Key into the \"Key\" box, then click \"Add Key\".",
- "Create a new GitHub repository by and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".",
- "Enter a project name, then click the \"Create Repository\" button.",
- "Find the \"...or push an existing repository from the command line\" section and click the Copy to Clipboard button beside it.",
- "Paste the commands from your clipboard into the Cloud9 terminal prompt. This will push your changes to your repository on Cloud 9 up to GitHub.",
- "Check back on your GitHub profile to verify the changes were successfully pushed up to GitHub.",
- "Now let's push your code to Heroku. If you don't already have a Heroku account, create one at http://heroku.com. You shouldn't be charged for anything, but you will need to add your credit card information to your Heroku before you will be able to use Heroku's free MongoLab add on.",
- "Before you publish to Heroku, you should free up as much memory as possible on Cloud9. In each of the Cloud9 terminal prompt tabs where MongoDB and Grunt are running, press the control + c
hotkey to shut down these processes.",
- "Run the following command in a Cloud9 terminal prompt tab: npm install grunt-contrib-imagemin --save-dev && npm install --save-dev && heroku login
. At this point, the terminal will prompt you to log in to Heroku from the command line.",
- "Now run yo angular-fullstack:heroku
. You can choose a name for your Heroku project, or Heroku will create a random one for you. You can choose whether you want to deploy to servers the US or the EU.",
- "Set the config flag for your Heroku environment and add MongoLab for your MongoDB instance by running the following command: cd ~/workspace/dist && heroku config:set NODE_ENV=production && heroku addons:add mongolab
.",
- "As you build your app, you should frequently commit changes to your codebase. Make sure you're in the ~/workspace
directory by running cd ~/workspace
. Then you can use this code to stage the changes to your changes and commit them: git commit -am \"your commit message\"
. Note that you should replace \"your commit message\" with a short summary of the changes you made to your code, such as \"added a records controller and corresponding routes\".",
- "You can push these new commits to GitHub by running git push origin master
, and to Heroku by running grunt --force && grunt buildcontrol:heroku
.",
- "If you need further guidance on using Yeoman Angular-Fullstack Generator, check out: https://github.com/clnhll/guidetobasejumps.",
- "Now you're ready to move on to your first Basejump. Click the \"I've completed this challenge\" and move on."
+ [
+ "http://i.imgur.com/4IZjWZ3.gif",
+ "A gif showing how to create a c9.io account.",
+ "We recommend building our full stack Basejump challenges on c9.io, a powerful browser-based development environment. This save you hours of time that you would spend configuring your local computer to run Node.js and MongoDB - time you could instead spend coding. https://github.com/johnstonbl01/clementinejs-fcc.git
",
+ ""
+ ],
+ [
+ "http://i.imgur.com/42m1vyr.gif",
+ "A gif showing you how to show hidden files.",
+ "Click the gear in the upper right corner of c9.io's file structure. Select \"show hidden files\".",
+ ""
+ ],
+ [
+ "http://i.imgur.com/qrE8xaK.gif",
+ "A gif showing you how to create a new file.",
+ "Right click and create a new file called .env
.",
+ ""
+ ],
+ [
+ "http://i.imgur.com/jkQX9SQ.gif",
+ "A gif showing you how to prep your environmental variables in your .env file.",
+ "Open your .env file and paste this into it, then save it: GITHUB_KEY=
GITHUB_SECRET=
MONGO_URI=mongodb://localhost:27017/clementinejs
PORT=8080
APP_URL=http://localhost:8080/
",
+ ""
+ ],
+ [
+ "http://i.imgur.com/f3DE7zB.gif",
+ "A gif showing you how to open c9.io's preview window.",
+ "Open up your application in a preview tab by clicking window > share > application > open.",
+ ""
+ ],
+ [
+ "http://i.imgur.com/Ip0qUdQ.gif",
+ "A gif showing you how to create a GitHub app using c9.io's preview URL.",
+ "Create a GitHub app for authentication and choose an \"Application name\". For the homepage URL, paste the URL from your preview tab. You'll also paste the URL from your preview tab into \"Authorization callback URL\", then add to it: auth/github/callback
",
+ "https://github.com/settings/applications/new"
+ ],
+ [
+ "http://i.imgur.com/qCUVRFb.gif",
+ "A gif showing you how to transfer GitHub's key and secret over to your .env file, as well as your c9.io URL.",
+ "GitHub will create an app and present you with a Client ID and a Client Secret. Set your .env file's GITHUB_KEY equal to the Client ID, and set your .env file's GITHUB_SECRET equal to the Client Secret. Copy the URL from the your preview tab and paste it into your .env file as your APP_URL.",
+ ""
+ ],
+ [
+ "http://i.imgur.com/2a20Vah.gif",
+ "A gif showing you how to start mongoDB in c9.io's terminal.",
+ "In your terminal, start MongoDB by entering mongod --smallfiles
",
+ ""
+ ],
+ [
+ "http://i.imgur.com/dC55pWk.gif",
+ "A gif showing you how to open a new tab in c9.io's terminal.",
+ "Open a new terminal tab with the + button above your terminal, then run npm install
",
+ ""
+ ],
+ [
+ "http://i.imgur.com/54OC2Ro.gif",
+ "A gif showing you how to navigate to your preview tab and sign in to your new Clementine.js app.",
+ "Run node server.js
to start the server. Refresh your preview tab. You should see the Clementine.js logo. Click \"sign in\" and accept GitHub's prompt to authorize the application.",
+ ""
+ ],
+ [
+ "http://i.imgur.com/2IJfyvN.gif",
+ "A gif showing you how to click the button to trigger an AJAX action with Clementine.js and how to look at your user profile from the GitHub authentication data.",
+ "Click the \"click me\" button and you'll see that it increments the number clicks. Click the profile button and you'll see that it has your GitHub information.",
+ ""
+ ],
+ [
+ "http://i.imgur.com/bjO5pnq.gif",
+ "A gif showing you how to create a new GitHub repository and push your code up to it.",
+ "Create a new GitHub repository. Then copy its .git URL. git remote set-url origin
followed by the URL you copied from GitHub. git push origin master
. palindrome(\"almostomla\")
should return false.');",
"assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, 'message: palindrome(\"My age is 0, 0 si ega ym.\")
should return true.');",
"assert(palindrome(\"1 eye for of 1 eye.\") === false, 'message: palindrome(\"1 eye for of 1 eye.\")
should return false.');",
- "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, 'message: palindrome(\"0_0 (: /-\\\\ :) 0-0\")
should return true.');"
+ "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, 'message: palindrome(\"0_0 (: /-\\ :) 0-0\")
should return true.');"
],
"challengeSeed": [
"function palindrome(str) {",
@@ -159,6 +168,9 @@
"String.replace()",
"String.toLowerCase()"
],
+ "solutions": [
+ "function palindrome(str) {\n var a = str.toLowerCase().replace(/[^a-z]/g, '');\n console.log(a.split('').reverse().join(''));\n return a == a.split('').reverse().join('');\n}\n\n\n\npalindrome(\"eye\");\npalindrome(\"A man, a plan, a canal. Panama\");\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -199,6 +211,9 @@
"String.split()",
"String.length"
],
+ "solutions": [
+ "function findLongestWord(str) {\n return str.split(' ').sort(function(a, b) { return b.length - a.length;})[0].length;\n}\n\nfindLongestWord('The quick brown fox jumped over the lazy dog');\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -236,6 +251,9 @@
"MDNlinks": [
"String.charAt()"
],
+ "solutions": [
+ "function titleCase(str) {\n return str.split(' ').map(function(word) {\n return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase();\n }).join(' ');\n}\n\ntitleCase(\"I'm a little tea pot\");\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -274,6 +292,9 @@
"MDNlinks": [
"Comparison Operators"
],
+ "solutions": [
+ "function largestOfFour(arr) {\n return arr.map(function(subArr) {\n return Math.max.apply(null, subArr);\n });\n}\n\nlargestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -306,7 +327,7 @@
"tests": [
"assert(end(\"Bastian\", \"n\") === true, 'message: end(\"Bastian\", \"n\")
should return true.');",
"assert(end(\"Connor\", \"n\") === false, 'message: end(\"Connor\", \"n\")
should return false.');",
- "assert(end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\") === false, 'message: end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\")
should return false.');",
+ "assert(end(\"Walking on water and developing software from a specification are easy if both are frozen\", \"specification\") === false, '\"Walking on water and developing software from a specification are easy if both are frozen\", \"specification\")
should return false.');",
"assert(end(\"He has to give me a new name\", \"name\") === true, 'message: end(\"He has to give me a new name\", \"name\")
should return true.');",
"assert(end(\"He has to give me a new name\", \"me\") === true, 'message: end(\"He has to give me a new name\", \"me\")
should return true.');",
"assert(end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") === false, 'message: end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\")
should return false.');"
@@ -314,6 +335,9 @@
"MDNlinks": [
"String.substr()"
],
+ "solutions": [
+ "function end(str, target) {\n // \"Never give up and good luck will find you.\"\n // -- Falcor\n return str.substring(str.length-target.length) === target;\n}\n\nend('Bastian', 'n');\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -350,6 +374,9 @@
"MDNlinks": [
"Global String Object"
],
+ "solutions": [
+ "function repeat(str, num) {\n if (num < 0) return '';\n return num === 1 ? str : str + repeat(str, num-1);\n}\n\nrepeat('abc', 3);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -390,6 +417,9 @@
"MDNlinks": [
"String.slice()"
],
+ "solutions": [
+ "function truncate(str, num) {\n if (str.length > num) {\n return str.substring(0, num-3) + '...';\n }\n return str;\n}\n\ntruncate('A-tisket a-tasket A green and yellow basket', 11);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -427,6 +457,9 @@
"MDNlinks": [
"Array.push()"
],
+ "solutions": [
+ "function chunk(arr, size) {\n var out = [];\n for (var i = 0; i < arr.length; i+=size) {\n out.push(arr.slice(i,i+size));\n }\n return out;\n}\n\nchunk(['a', 'b', 'c', 'd'], 2);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -466,6 +499,9 @@
"Array.slice()",
"Array.splice()"
],
+ "solutions": [
+ "function slasher(arr, howMany) {\n // it doesn't always pay to be first\n return arr.slice(howMany);\n}\n\nslasher([1, 2, 3], 2);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -509,6 +545,9 @@
"MDNlinks": [
"Array.indexOf()"
],
+ "solutions": [
+ "function mutation(arr) {\n var hash = Object.create(null);\n arr[0].toLowerCase().split('').forEach(function(c) {\n hash[c] = true;\n });\n return !arr[1].toLowerCase().split('').filter(function(c) {\n return !hash[c];\n }).length;\n}\n\nmutation(['hello', 'hey']);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -547,6 +586,9 @@
"Boolean Objects",
"Array.filter()"
],
+ "solutions": [
+ "function bouncer(arr) {\n // Don't show a false ID to this bouncer.\n return arr.filter(function(e) {return e;});\n}\n\nbouncer([7, 'ate', '', false, 9]);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -586,6 +628,9 @@
"Arguments object",
"Array.filter()"
],
+ "solutions": [
+ "function destroyer(arr) {\n var hash = Object.create(null);\n [].slice.call(arguments, 1).forEach(function(e) {\n hash[e] = true;\n });\n // Remove all the values\n return arr.filter(function(e) { return !(e in hash);});\n}\n\ndestroyer([1, 2, 3, 1, 2, 3], 2, 3);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -603,8 +648,9 @@
"id": "a24c1a4622e3c05097f71d67",
"title": "Where do I belong",
"description": [
- "Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).",
- "For example, where([1,2,3,4], 1.5) should return 1 because it is greater than 1 (0th index), but less than 2 (1st index).",
+ "Return the lowest index at which a value (second argument) should be inserted into an array (first argument) once it has been sorted.",
+ "For example, where([1,2,3,4], 1.5) should return 1 because it is greater than 1 (index 0), but less than 2 (index 1).",
+ "Likewise, where([20,3,5], 19) should return 2 because it is less than 20 (index 2) and greater than 5 (index 1).",
"Remember to use Read-Search-Ask if you get stuck. Write your own code."
],
"challengeSeed": [
@@ -618,12 +664,15 @@
"MDNlinks": [
"Array.sort()"
],
+ "solutions": [
+ "function where(arr, num) {\n // Find my place in this sorted array.\n return num;\n}\n\nwhere([40, 60], 50);\n"
+ ],
"tests": [
"assert(where([10, 20, 30, 40, 50], 35) === 3, 'message: where([10, 20, 30, 40, 50], 35)
should return 3
.');",
"assert(where([10, 20, 30, 40, 50], 30) === 2, 'message: where([10, 20, 30, 40, 50], 30)
should return 2
.');",
"assert(where([40, 60], 50) === 1, 'message: where([40, 60,], 50)
should return 1
.');",
- "assert(where([5, 3, 20, 3], 3) === 0, 'message: where([5, 3, 20, 3], 3)
should return 0
.');",
- "assert(where([2, 20, 10], 1) === 0, 'message: where([2, 20, 10], 1)
should return 0
.');",
+ "assert(where([5, 3, 20, 3], 5) === 2, 'message: where([5, 3, 20, 3], 5)
should return 2
.');",
+ "assert(where([2, 20, 10], 19) === 2, 'message: where([2, 20, 10], 19)
should return 2
.');",
"assert(where([2, 5, 10], 15) === 3, 'message: where([2, 5, 10], 15)
should return 3
.');"
],
"type": "bonfire",
diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json
index e215cddda0..b22ee617c7 100644
--- a/seed/challenges/basic-javascript.json
+++ b/seed/challenges/basic-javascript.json
@@ -4,26 +4,23 @@
"time": "3h",
"challenges": [
{
- "id":"bd7123c9c441eddfaeb4bdef",
+ "id": "bd7123c9c441eddfaeb4bdef",
"title": "Comment your JavaScript Code",
- "difficulty":"9.98",
- "description":[
+ "description": [
"Comments are lines of code that your computer will intentionally ignore. Comments are a great way to leave notes to yourself and to other people who will later need to figure out what it does.",
"Let's take a look at the two ways you can write comments in JavaScript.",
"The double-slash comment will comment out the remainder of the text on the current line:",
"// This is a comment.
",
"The slash-star-star-slash comment will comment out everything between the /*
and the */
characters:",
"/* This is also a comment */
",
- "Try creating one of each.",
- "And one more thing you need to notice. Starting at this waypoint in JavaScript related challenges (except AngularJS, all Ziplines, Git, Node.js and Express.js, MongoDB and Full Stack JavaScript Projects) you can see contents of assert()
functions (in some challenges except()
, assert.equal()
and so on) which are used to test your code. It's part of these challenges that you are able to see the tests that are running against your code."
+ "Try creating one of each."
],
- "tests":[
- "assert(editor.getValue().match(/(\\/\\/)...../g), 'message: Create a //
style comment that contains at least five letters');",
+ "tests": [
+ "assert(editor.getValue().match(/(\\/\\/)...../g), 'message: Create a //
style comment that contains at least five letters.');",
"assert(editor.getValue().match(/(\\/\\*)[\\w\\W]{5,}(?=\\*\\/)/gm), 'message: Create a /* */
style comment that contains at least five letters.');",
- "assert(editor.getValue().match(/(\\*\\/)/g), 'message: Make sure that you close the comment with a */
');"
- ],
- "challengeSeed":[
+ "assert(editor.getValue().match(/(\\*\\/)/g), 'message: Make sure that you close the comment with a */
.');"
],
+ "challengeSeed": [],
"type": "waypoint",
"challengeType": 1
},
@@ -33,7 +30,7 @@
"description": [
"In computer science, data structures
are things that hold data. JavaScript has seven of these. For example, the Number
data structure holds numbers.",
"Let's learn about the most basic data structure of all: the Boolean
. Booleans can only hold the value of either true or false. They are basically little on-off switches.",
- "Let's modify our welcomeToBooleans
function so that it will return true
instead of false
when the run button is clicked."
+ "Let's modify our welcomeToBooleans
function so that it will return true
instead of false
when the run button is clicked."
],
"tests": [
"assert(typeof(welcomeToBooleans()) === 'boolean', 'message: The welcomeToBooleans()
function should return a boolean (true/false) value.');",
@@ -68,12 +65,10 @@
"assert((function(){if(typeof(myName) !== \"undefined\" && typeof(myName) === \"string\" && myName.length > 0){return true;}else{return false;}})(), 'message: myName
should be a string that contains at least one character in it.');"
],
"challengeSeed": [
- "// var ourName = \"Free Code Camp\";",
+ "var ourName = \"Free Code Camp\";",
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
"",
"if(typeof(myName) !== \"undefined\"){(function(v){return v;})(myName);}"
],
@@ -85,21 +80,20 @@
"title": "Declare String Variables",
"description": [
"In the previous challenge, we used the code var myName = \"your name\"
. This is what we call a String
variable. It is nothing more than a \"string\" of characters. JavaScript strings are always wrapped in quotes.",
- "Now let's create two new string variables: myFirstName
and myLastName
and assign them the values of your first and last name, respectively."
+ "Now let's create two new string variables: myFirstName
and myLastName
and assign them the values of your first and last name, respectively."
],
"tests": [
"assert((function(){if(typeof(myFirstName) !== \"undefined\" && typeof(myFirstName) === \"string\" && myFirstName.length > 0){return true;}else{return false;}})(), 'message: myFirstName
should be a string with at least one character in it.');",
"assert((function(){if(typeof(myLastName) !== \"undefined\" && typeof(myLastName) === \"string\" && myLastName.length > 0){return true;}else{return false;}})(), 'message: myLastName
should be a string with at least one character in it.');"
],
"challengeSeed": [
- "// var name = \"Alan Turing\";",
- "// var firstName = \"Alan\";",
- "// var lastName = \"Turing\";",
+ "var name = \"Alan Turing\";",
+ "var firstName = \"Alan\";",
+ "var lastName = \"Turing\";",
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"if(typeof(myFirstName) !== \"undefined\" && typeof(myLastName) !== \"undefined\"){(function(){return myFirstName + ', ' + myLastName;})();}"
],
"type": "waypoint",
@@ -133,8 +127,7 @@
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"if(typeof(lastNameLength) !== \"undefined\"){(function(){return lastNameLength;})();}"
],
"type": "waypoint",
@@ -167,8 +160,7 @@
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(v){return v;})(firstLetterOfLastName);"
],
"type": "waypoint",
@@ -178,9 +170,9 @@
"id": "bd7123c9c450eddfaeb5bdef",
"title": "Use Bracket Notation to Find the Nth Character in a String",
"description": [
- "You can also use bracket Notation
to get the character at other positions within a string.",
+ "You can also use bracket notation
to get the character at other positions within a string.",
"Remember that computers start counting at 0, so the first character is actually the zeroth character.",
- "Let's try to set thirdLetterOfLastName
to equal the third letter
of the lastName
variable.",
+ "Let's try to set thirdLetterOfLastName
to equal the third letter
of the lastName
variable.",
"Try looking at the secondLetterOfFirstName
variable declaration if you get stuck."
],
"tests": [
@@ -197,8 +189,7 @@
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(v){return v;})(thirdLetterOfLastName);"
],
"type": "waypoint",
@@ -228,8 +219,7 @@
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(v){return v;})(lastLetterOfLastName);"
],
"type": "waypoint",
@@ -240,7 +230,7 @@
"title": "Use Bracket Notation to Find the Nth-to-Last Character in a String",
"description": [
"In order to get the last letter of a string, you can subtract one from the string's length.",
- "For example, you can get the value of the third-to-last letter of the var firstName = \"Charles\"
string by using firstName[firstName.length - 3]
.",
+ "For example, you can get the value of the third-to-last letter of the var firstName = \"Charles\"
string by using firstName[firstName.length - 3]
",
"Use bracket notation
to find the second-to-last character in the lastName
string.",
"Try looking at the thirdToLastLetterOfFirstName
variable declaration if you get stuck."
],
@@ -259,8 +249,7 @@
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(v){return v;})(secondToLastLetterOfLastName);"
],
"type": "waypoint",
@@ -272,17 +261,16 @@
"description": [
"Let's try to add two numbers using JavaScript.",
"JavaScript uses the +
symbol for addition.",
- "Replace the 0
with the correct number so you can get the result mentioned in the comment."
+ "Change the 0
so that sum will equal 20
."
],
"tests": [
"assert((function(){if(sum === 20 && editor.getValue().match(/\\+/g).length >= 2){return true;}else{return false;}})(), 'message: Make the variable sum
equal 20.');"
],
"challengeSeed": [
- "var sum = 10 + 0; //make this equal to 20 by changing the 0 into the appropriate number.",
+ "var sum = 10 + 0;",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(z){return 'sum='+z;})(sum);"
],
"type": "waypoint",
@@ -294,17 +282,16 @@
"description": [
"We can also subtract one number from another.",
"JavaScript uses the -
symbol for subtraction.",
- "Replace the 0
with the correct number so you can get the result mentioned in the comment."
+ "Change the 0
so that difference will equal 12
."
],
"tests": [
"assert((function(){if(difference === 12 && editor.getValue().match(/\\-/g)){return true;}else{return false;}})(), 'message: Make the variable difference
equal 12.');"
],
"challengeSeed": [
- "var difference = 45 - 0; //make this equal to 12 by changing the 0 into the appropriate number.",
+ "var difference = 45 - 0;",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(z){return 'difference='+z;})(difference);"
],
"type": "waypoint",
@@ -316,17 +303,16 @@
"description": [
"We can also multiply one number by another.",
"JavaScript uses the *
symbol for multiplication.",
- "Replace the 0
with the correct number so you can get the result mentioned in the comment."
+ "Change the 0
so that product will equal 80
."
],
"tests": [
"assert((function(){if(product === 80 && editor.getValue().match(/\\*/g)){return true;}else{return false;}})(), 'message: Make the variable product
equal 80.');"
],
"challengeSeed": [
- "var product = 8 * 0; // Make this equal to 80 by changing the 0 into the appropriate number.",
+ "var product = 8 * 0;",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(z){return 'product='+z;})(product);"
],
"type": "waypoint",
@@ -338,17 +324,16 @@
"description": [
"We can also divide one number by another.",
"JavaScript uses the /
symbol for division.",
- "Replace the 0
with the correct number so you can get the result mentioned in the comment."
+ "Change the 0
so that quotient will equal 2
."
],
"tests": [
"assert((function(){if(quotient === 2 && editor.getValue().match(/var\\s*?quotient\\s*?\\=\\s*?\\d+\\s*?\\/\\s*?\\d+\\s*?;/g)){return true;}else{return false;}})(), 'message: Make the variable quotient
equal 2.');"
],
"challengeSeed": [
- "var quotient = 66 / 0; //make this equal to 2 by changing the 0 into the appropriate number.",
+ "var quotient = 66 / 0;",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(z){return 'quotient='+z;})(quotient);"
],
"type": "waypoint",
@@ -365,14 +350,11 @@
"assert((function(){if(typeof(myDecimal) !== \"undefined\" && typeof(myDecimal) === \"number\" && editor.getValue().match(/\\./g).length >=2){return true;}else{return false;}})(), 'message: myDecimal
should be a decimal point number.');"
],
"challengeSeed": [
- "// var ourDecimal = 5.7;",
- "// Create a number with a decimal point here called myDecimal",
- "",
+ "var ourDecimal = 5.7;",
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(){if(typeof(myDecimal) !== \"undefined\"){return myDecimal;}})();"
],
"type": "waypoint",
@@ -380,28 +362,47 @@
},
{
"id": "bd7993c9c69feddfaeb7bdef",
- "title": "Perform Arithmetic Operations on Decimals with JavaScript",
+ "title": "Multiply Two Decimals with JavaScript",
"description": [
"In JavaScript, you can also perform calculations with decimal numbers, just like whole numbers.",
- "Replace the 0.0
with the correct number so that you get the result mentioned in the comments."
+ "Let's multiply two decimals together to get their product.",
+ "Change the 0.0
so that product will equal 5.0
."
],
"tests": [
- "assert((function(){if(product === 5.0 && editor.getValue().match(/\\*/g)){return true;}else{return false;}})(), 'message: Make the variable product
equal 5.0.');",
- "assert((function(){if(quotient === 2.2 && editor.getValue().match(/\\//g)){return true;}else{return false;}})(), 'message: Make the variable quotient
equal 2.2.');"
+ "assert((function(){if(product === 5.0 && editor.getValue().match(/\\*/g)){return true;}else{return false;}})(), 'message: Make the variable product
equal 5.0.');"
],
"challengeSeed": [
- "var quotient = 4.4 / 2.0; // equals 2.2",
- "var product = 2.0 * 0.0; // equals 5.0",
+ "var product = 2.0 * 0.0;",
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(y){return 'product='+y;})(product);"
],
"type": "waypoint",
"challengeType": 1
},
+ {
+ "id": "bd7993c9ca9feddfaeb7bdef",
+ "title": "Divide one Decimal by Another with JavaScript",
+ "description": [
+ "Now let's divide one decimal by another.",
+ "Change the 0.0
so that your quotient will equal 2.2
."
+ ],
+ "tests": [
+ "assert((function(){if(quotient === 2.2 && editor.getValue().match(/\\//g)){return true;}else{return false;}})(), 'message: Make the variable quotient
equal 2.2
.');"
+ ],
+ "challengeSeed": [
+ "var quotient = 0.0 / 2.0;",
+ "",
+ "",
+ "// Only change code above this line.",
+ "",
+ "(function(y){return 'quotient='+y;})(quotient);"
+ ],
+ "type": "waypoint",
+ "challengeType": 1
+ },
{
"id": "bd7993c9c69feddfaeb8bdef",
"title": "Store Multiple Values in one Variable using JavaScript Arrays",
@@ -417,50 +418,47 @@
"assert(typeof(myArray[1]) !== 'undefined' && typeof(myArray[1]) == 'number', 'message: The second item in myArray
should be a number
.');"
],
"challengeSeed": [
- "// var array = [\"John\", 23];",
+ "var array = [\"John\", 23];",
"",
"// Only change code below this line.",
"",
"var myArray = [];",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(z){return z;})(myArray);"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"cf1111c1c11feddfaeb7bdef",
+ "id": "cf1111c1c11feddfaeb7bdef",
"title": "Nest one Array within Another Array",
- "difficulty":"9.98161",
- "description":[
+ "description": [
"You can also nest arrays within other arrays, like this: [[\"Bulls\", 23]]
.",
"Let's now go create a nested array called myArray
."
],
- "tests":[
+ "tests": [
"assert(Array.isArray(myArray) && myArray.some(Array.isArray), 'message: myArray
should have at least one array nested within another array.');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var ourArray = [[\"the universe\", \"everything\", 42]];",
+ "",
"// Only change code below this line.",
"",
"var myArray = [];",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"if(typeof(myArray) !== \"undefined\"){(function(){return myArray;})();}"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"bg9997c9c79feddfaeb9bdef",
+ "id": "bg9997c9c79feddfaeb9bdef",
"title": "Access Array Data with Indexes",
- "difficulty":"9.9817",
- "description":[
+ "description": [
"We can access the data inside arrays using indexes
.",
"Array indexes are written in the same bracket notation that strings use, except that instead of specifying a character, they are specifying an entry in the array.",
"For example:",
@@ -469,51 +467,53 @@
"var data = array[1];
",
"Create a variable called myData
and set it to equal the first value of myArray
."
],
- "tests":[
+ "tests": [
"assert((function(){if(typeof(myArray) != 'undefined' && typeof(myData) != 'undefined' && myArray[0] == myData){return true;}else{return false;}})(), 'message: The variable myData
should equal the first value of myArray
.');"
],
- "challengeSeed":[
- "// var ourArray = [1,2,3];",
- "// var ourData = ourArray[0]; // equals 1",
+ "challengeSeed": [
+ "var ourArray = [1,2,3];",
+ "",
+ "var ourData = ourArray[0]; // equals 1",
"",
"var myArray = [1,2,3];",
+ "",
"// Only change code below this line.",
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"if(typeof(myArray) !== \"undefined\" && typeof(myData) !== \"undefined\"){(function(y,z){return 'myArray = ' + JSON.stringify(y) + ', myData = ' + JSON.stringify(z);})(myArray, myData);}"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"cf1111c1c11feddfaeb8bdef",
+ "id": "cf1111c1c11feddfaeb8bdef",
"title": "Modify Array Data With Indexes",
- "difficulty":"9.98171",
- "description":[
+ "description": [
"We can also modify the data stored in arrays by using indexes.",
"For example:",
"var ourArray = [3,2,1];
",
"ourArray[0] = 1; // equals [1,2,1]
",
"Now modify the data stored at index 0 of myArray
to the value of 3."
],
- "tests":[
+ "tests": [
"assert((function(){if(typeof(myArray) != 'undefined' && myArray[0] == 3 && myArray[1] == 2 && myArray[2] == 3){return true;}else{return false;}})(), 'message: myArray
should now be [3,2,3].');",
"assert((function(){if(editor.getValue().match(/myArray\\[0\\]\\s?=\\s?/g)){return true;}else{return false;}})(), 'message: You should be using correct index to modify the value in myArray
.');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var ourArray = [1,2,3];",
- "ourArray[1] = 3;",
- "// ourArray now equals [1,3,3].",
+ "",
+ "ourArray[1] = 3; // ourArray now equals [1,3,3].",
+ "",
"var myArray = [1,2,3];",
+ "",
"// Only change code below this line.",
"",
"",
+ "",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"if(typeof(myArray) !== \"undefined\"){(function(){return myArray;})();}"
],
"type": "waypoint",
@@ -524,30 +524,28 @@
"title": "Manipulate Arrays With pop()",
"description": [
"Another way to change the data in an array is with the .pop()
function.",
- ".pop()
is used to \"pop\" a value off of the end of an array. We can retrieve this value by performing pop()
in a variable declaration.",
- "Any type of variable can be \"popped\" off of an array.",
- "Use the .pop()
function to remove the last item from myArray
."
+ ".pop()
is used to \"pop\" a value off of the end of an array. We can store this \"popped off\" variable by performing pop()
within a variable declaration.",
+ "Any type of data structure can be \"popped\" off of an array - numbers, strings, even nested arrays.",
+ "Use the .pop()
function to remove the last item from myArray
, assigning the \"popped off\" value to removedFromMyArray
."
],
"tests": [
"assert((function(d){if(d[0] == 'John' && d[1] == 23 && d[2] == undefined){return true;}else{return false;}})(myArray), 'message: myArray
should only contain [\"John\", 23]
.');",
- "assert((function(d){if(d[0] == 'cat' && d[1] == 2 && d[2] == undefined){return true;}else{return false;}})(removed), 'message: removed
should only contain [\"cat\", 2]
.');"
+ "assert((function(d){if(d[0] == 'cat' && d[1] == 2 && d[2] == undefined){return true;}else{return false;}})(removedFromMyArray), 'message: removedFromMyArray
should only contain [\"cat\", 2]
.');"
],
"challengeSeed": [
- "// var numbers = [1,2,3];",
- "// console.log(numbers); // logs [1,2,3]",
- "// var removed = numbers.pop();",
- "// console.log(numbers); // logs [1,2]",
- "// console.log(removed); // logs 3",
+ "var ourArray = [1,2,3];",
+ "",
+ "var removedFromOurArray = ourArray.pop(); // removedFromOurArray now equals 3, and ourArray now equals [1,2]",
"",
"var myArray = [\"John\", 23, [\"cat\", 2]];",
+ "",
"// Only change code below this line.",
"",
- "var removed = myArray; // This should be [\"cat\", 2] and myArray should now be [\"John\", 23]",
+ "var removedFromMyArray;",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
- "(function(y, z){return 'myArray = ' + JSON.stringify(y) + ' & removed = ' + JSON.stringify(z);})(myArray, removed);"
+ "",
+ "(function(y, z){return 'removedFromMyArray = ' + JSON.stringify(y) + ' & removed = ' + JSON.stringify(z);})(myArray, removedFromMyArray);"
],
"type": "waypoint",
"challengeType": 1
@@ -557,26 +555,28 @@
"title": "Manipulate Arrays With push()",
"description": [
"Not only can you pop()
data off of the end of an array, you can also push()
data onto the end of an array.",
- "Take the myArray
array and push()
this value to the end of it: [\"dog\", 3]
."
+ "Push [\"dog\", 3]
onto the end of the myArray
variable."
],
"tests": [
"assert((function(d){if(d[2] != undefined && d[0] == 'John' && d[1] == 23 && d[2][0] == 'dog' && d[2][1] == 3 && d[2].length == 2){return true;}else{return false;}})(myArray), 'message: myArray
should now equal [\"John\", 23, [\"dog\", 3]]
.');"
],
"challengeSeed": [
"var ourArray = [\"Stimpson\", \"J\", [\"cat\"]];",
- "ourArray.pop();",
- "ourArray.push([\"happy\", \"joy\"]);",
- "// ourArray now equals [\"Stimpson\", \"J\", [\"happy\", \"joy\"]].",
+ "",
+ "ourArray.pop(); // ourArray now equals [\"Stimpson\", \"J\"]",
+ "",
+ "ourArray.push([\"happy\", \"joy\"]); // ourArray now equals [\"Stimpson\", \"J\", [\"happy\", \"joy\"]]",
"",
"var myArray = [\"John\", 23, [\"cat\", 2]];",
+ "",
"myArray.pop();",
- "// Add a [\"dog\", 3] to the end of myArray using push().",
+ "",
"// Only change code below this line.",
"",
"",
+ "",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(z){return 'myArray = ' + JSON.stringify(z);})(myArray);"
],
"type": "waypoint",
@@ -586,28 +586,29 @@
"id": "bg9996c9c69feddfaeb9bdef",
"title": "Manipulate Arrays With shift()",
"description": [
- "pop()
always removes the last element of an array. What if you want to remove the first? That's where .shift()
comes in.",
- "Take the myArray
array and shift()
the first value off of it. Set myRemoved
to the first value of myArray
using shift()
."
+ "pop()
always removes the last element of an array. What if you want to remove the first?",
+ "That's where .shift()
comes in. It works just like .pop()
, except it removes the first element instead of the last.",
+ "Use the .shift()
function to remove the first item from myArray
, assigning the \"shifted off\" value to removedFromMyArray
."
],
"tests": [
"assert((function(d){if(d[0] == 23 && d[1][0] == 'dog' && d[1][1] == 3 && d[2] == undefined){return true;}else{return false;}})(myArray), 'message: myArray
should now equal [23, [\"dog\", 3]]
.');",
- "assert((function(d){if(d === 'John' && typeof(myRemoved) === 'string'){return true;}else{return false;}})(myRemoved), 'message: myRemoved
should contain \"John\"
.');"
+ "assert((function(d){if(d === 'John' && typeof(removedFromMyArray) === 'string'){return true;}else{return false;}})(removedFromMyArray), 'message: removedFromMyArray
should contain \"John\"
.');"
],
"challengeSeed": [
"var ourArray = [\"Stimpson\", \"J\", [\"cat\"]];",
- "ourRemoved = ourArray.shift();",
- "// ourArray now equals [\"J\", [\"cat\"]].",
+ "",
+ "removedFromOurArray = ourArray.shift(); // removedFromOurArray now equals \"Stimpson\" and ourArray now equals [\"J\", [\"cat\"]].",
"",
"var myArray = [\"John\", 23, [\"dog\", 3]];",
+ "",
"// Only change code below this line.",
"",
- "var myRemoved = myArray; // This should be [\"John\"] and myArray should now be [23, [\"dog\", 3]].",
+ "var removedFromMyArray;",
"",
"// Only change code above this line.",
"",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
- "(function(y, z){return 'myArray = ' + JSON.stringify(y) + ' & myRemoved = ' + JSON.stringify(z);})(myArray, myRemoved);"
+ "",
+ "(function(y, z){return 'myArray = ' + JSON.stringify(y) + ' & removedFromMyArray = ' + JSON.stringify(z);})(myArray, removedFromMyArray);"
],
"type": "waypoint",
"challengeType": 1
@@ -616,39 +617,39 @@
"id": "bg9997c9c69feddfaeb9bdef",
"title": "Manipulate Arrays With unshift()",
"description": [
- "Now that we've learned how to shift
things from the start of the array, we need to learn how to unshift
stuff back to the start.",
- "Let's take the code we had last time and unshift
this value to the start: \"Paul\"
."
+ "Not only can you shift
elements off of the beginning of an array, you can also unshift
elements onto the beginning of an array.",
+ "unshift()
works exactly like push()
, but instead of adding the element at the end of the array, unshift()
adds the element at the beginning of the array.",
+ "Add \"Paul\"
onto the beginning of the myArray
variable using unshift()
."
],
"tests": [
"assert((function(d){if(typeof(d[0]) === \"string\" && d[0].toLowerCase() == 'paul' && d[1] == 23 && d[2][0] != undefined && d[2][0] == 'dog' && d[2][1] != undefined && d[2][1] == 3){return true;}else{return false;}})(myArray), 'message: myArray
should now have [\"Paul\", 23, [\"dog\", 3]]).');"
],
"challengeSeed": [
"var ourArray = [\"Stimpson\", \"J\", [\"cat\"]];",
- "ourArray.shift();",
- "// ourArray now equals [\"J\", [\"cat\"]]",
- "ourArray.unshift(\"happy\");",
- "// ourArray now equals [\"happy\", \"J\", [\"cat\"]]",
+ "",
+ "ourArray.shift(); // ourArray now equals [\"J\", [\"cat\"]]",
+ "",
+ "ourArray.unshift(\"happy\"); // ourArray now equals [\"happy\", \"J\", [\"cat\"]]",
"",
"var myArray = [\"John\", 23, [\"dog\", 3]];",
+ "",
"myArray.shift();",
"",
- "// Add \"Paul\" to the start of myArray.",
"// Only change code below this line.",
"",
"",
+ "",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"(function(y, z){return 'myArray = ' + JSON.stringify(y);})(myArray);"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"bg9997c9c89feddfaeb9bdef",
+ "id": "bg9997c9c89feddfaeb9bdef",
"title": "Write Reusable JavaScript with Functions",
- "difficulty":"9.9819",
- "description":[
+ "description": [
"In JavaScript, we can divide up our code into reusable parts called functions.",
"Here's an example of a function:",
"function functionName(a, b) {
",
@@ -659,10 +660,10 @@
"In this example, the function will return the number 6
as this is the result of 4 + 2
.",
"Create and call a function called myFunction
that returns the sum of a
and b
."
],
- "tests":[
+ "tests": [
"assert((function(){if(typeof(f) !== \"undefined\" && f === a + b){return true;}else{return false;}})(), 'message: Your function should return the value of a + b');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var a = 4;",
"var b = 5;",
"",
@@ -670,15 +671,13 @@
" return a - b;",
"}",
"",
- "// Create a function called myFunction that returns the value of a plus b.",
"// Only change code below this line.",
"",
"",
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"if(typeof(myFunction) !== \"undefined\"){",
"var f=myFunction(a,b);",
"(function(){return f;})();",
@@ -688,109 +687,191 @@
"challengeType": 1
},
{
- "id":"bg9998c9c99feddfaeb9bdef",
+ "id": "bg9998c9c99feddfaeb9bdef",
"title": "Build JavaScript Objects",
- "difficulty":"9.9822",
- "description":[
+ "description": [
"You may have heard the term object
before.",
"Objects are similar to arrays
, except that instead of using indexes to access and modify their data, you access the data in objects through what are called properties
.",
"Here's a sample object:",
"var cat = {
",
- " \"name\": \"Whiskers\",
",
- " \"legs\": 4,
",
- " \"tails\": 1,
",
- " \"enemies\": [\"Water\", \"Dogs\"]
",
+ " \"name\": \"Whiskers\",
",
+ " \"legs\": 4,
",
+ " \"tails\": 1,
",
+ " \"enemies\": [\"Water\", \"Dogs\"]
",
"};
",
"",
"Objects are useful for storing data in a structured way, and can represent real world objects, like a cat.",
- "Let's try to make an object that represents a dog called myDog
which contains the properties 'name'
(String), 'legs'
(Number), 'tails'
(Number) and 'friends'
(Array)!"
+ "Let's try to make an object that represents a dog called myDog
which contains the properties \"name\"
(a string), \"legs\"
, \"tails\"
and \"friends\"
.",
+ "You can set these object properties to whatever values you want, as long \"name\"
is a string, \"legs\"
and \"tails\"
are numbers, and \"friends\"
is an array."
],
- "tests":[
+ "tests": [
"assert((function(z){if(z.hasOwnProperty(\"name\") && z.name !== undefined && typeof(z.name) === \"string\"){return true;}else{return false;}})(myDog), 'message: myDog
should contain the property name
and it should be a string
.');",
"assert((function(z){if(z.hasOwnProperty(\"legs\") && z.legs !== undefined && typeof(z.legs) === \"number\"){return true;}else{return false;}})(myDog), 'message: myDog
should contain the property legs
and it should be a number
.');",
"assert((function(z){if(z.hasOwnProperty(\"tails\") && z.tails !== undefined && typeof(z.tails) === \"number\"){return true;}else{return false;}})(myDog), 'message: myDog
should contain the property tails
and it should be a number
.');",
"assert((function(z){if(z.hasOwnProperty(\"friends\") && z.friends !== undefined && Array.isArray(z.friends)){return true;}else{return false;}})(myDog), 'message: myDog
should contain the property friends
and it should be an array
.');"
],
- "challengeSeed":[
- "// var ourDog = {",
- "// \"name\": \"Camper\",",
- "// \"legs\": 4,",
- "// \"tails\": 1,",
- "// \"friends\": [\"everything!\"]",
- "// };",
- "",
- "// Add the name (string), legs (number), tails (number) and friends (array) properties to myDog.",
- "// You can set them to whatever you want.",
+ "challengeSeed": [
+ "var ourDog = {",
+ " \"name\": \"Camper\",",
+ " \"legs\": 4,",
+ " \"tails\": 1,",
+ " \"friends\": [\"everything!\"]",
+ "};",
"",
"// Only change code below this line.",
"",
"var myDog = {",
- " ",
+ "",
+ "",
+ "",
+ "",
"};",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
+ "",
"(function(z){return z;})(myDog);"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"bg9999c9c99feddfaeb9bdef",
- "title": "Manipulate JavaScript Objects",
- "difficulty":"9.9823",
- "description":[
- "There are many ways to add and remove properties from objects.",
- "For example, we can add properties to objects like this:",
- "myObject.myProperty = \"myValue\";
",
- "We can also delete them like this:",
- "delete myObject.myProperty;
",
- "Let's add the property \"bark\"
, and delete the property \"tails\"
."
+ "id": "bg9999c9c99feddfaeb9bdef",
+ "title": "Update the Properties of a JavaScript Object",
+ "description": [
+ "After you've created a JavaScript object, you can update its properties at any time just like you would update any other variable.",
+ "For example, let's look at ourDog
:",
+ "var ourDog = {
",
+ " \"name\": \"Camper\",
",
+ " \"legs\": 4,
",
+ " \"tails\": 1,
,",
+ " \"friends\": [\"everything!\"]
",
+ "};
",
+ "Since he's a particularly happy dog, let's change his name to \"Happy Camper\". Here's how we update his object's name property:",
+ "myDog.name = \"Happy Camper\";
",
+ "Now when we run return myDog.name
, instead of getting \"Camper\", we'll get his new name, \"Happy Camper\".",
+ "Let's update yourDog
object's name property. Let's change her name from \"Coder\" to \"Happy Coder\"."
],
- "tests":[
- "assert(myDog.bark !== undefined, 'message: Add the property \"bark\"
to myDog
.');",
+ "tests": [
+ "assert(/happy coder/gi.test(myDog.name), 'message: Update myDog
\\'s \"name\"
property to equal \"Happy Coder\".');"
+ ],
+ "challengeSeed": [
+ "var ourDog = {",
+ " \"name\": \"Camper\",",
+ " \"legs\": 4,",
+ " \"tails\": 1,",
+ " \"friends\": [\"everything!\"]",
+ "};",
+ "",
+ "ourDog.name = \"Happy Camper\";",
+ "",
+ "var myDog = {",
+ " \"name\": \"Coder\",",
+ " \"legs\": 4,",
+ " \"tails\": 1,",
+ " \"friends\": [\"Free Code Camp Campers\"]",
+ "};",
+ "",
+ "// Only change code above this line.",
+ "",
+ "(function(z){return z;})(myDog);"
+ ],
+ "type": "waypoint",
+ "challengeType": 1
+ },
+ {
+ "id": "bg9999c9c99feedfaeb9bdef",
+ "title": "Add New Properties to a JavaScript Object",
+ "description": [
+ "You can add new properties to existing JavaScript objects the same way you would modify them.",
+ "Here's how we would add a \"bark\"
property to ourDog
:",
+ "myDog.bark = \"bow-wow\";
",
+ "Now when we run return myDog.bark
, we'll get his bark, \"bow-wow\".",
+ "Let's add a \"bark\"
property to myDog
and set it to a dog sound, such as \"woof\"."
+ ],
+ "tests": [
+ "assert(myDog.bark !== undefined, 'message: Add the property \"bark\"
to myDog
.');"
+ ],
+ "challengeSeed": [
+ "var ourDog = {",
+ " \"name\": \"Camper\",",
+ " \"legs\": 4,",
+ " \"tails\": 1,",
+ " \"friends\": [\"everything!\"]",
+ "};",
+ "",
+ "ourDog.bark = \"bow-wow\";",
+ "",
+ "var myDog = {",
+ " \"name\": \"Happy Coder\",",
+ " \"legs\": 4,",
+ " \"tails\": 1,",
+ " \"friends\": [\"Free Code Camp Campers\"]",
+ "};",
+ "",
+ "// Only change code below this line.",
+ "",
+ "",
+ "",
+ "// Only change code above this line.",
+ "",
+ "(function(z){return z;})(myDog);"
+ ],
+ "type": "waypoint",
+ "challengeType": 1
+ },
+ {
+ "id": "bg9999c9c99fdddfaeb9bdef",
+ "title": "Delete Properties from a JavaScript Object",
+ "description": [
+ "We can also delete properties from objects like this:",
+ "delete myDog.bark;
",
+ "Let's delete the \"tails\"
property from myDog
."
+ ],
+ "tests": [
"assert(myDog.tails === undefined, 'message: Delete the property \"tails\"
from myDog
.');"
],
- "challengeSeed":[
- "// var ourDog = {",
- "// \"name\": \"Camper\",",
- "// \"legs\": 4,",
- "// \"tails\": 1,",
- "// \"friends\": [\"everything!\"]",
- "// };",
+ "challengeSeed": [
+ "var ourDog = {",
+ " \"name\": \"Camper\",",
+ " \"legs\": 4,",
+ " \"tails\": 1,",
+ " \"friends\": [\"everything!\"],",
+ " \"bark\": \"bow-wow\"",
+ "};",
"",
- "// ourDog.bark = \"arf!\";",
- "// delete ourDog.tails;",
+ "delete ourDog.bark;",
"",
"var myDog = {",
- " \"name\": \"Camper\",",
- " \"legs\": 4,",
- " \"tails\": 1,",
- " \"friends\": []",
+ " \"name\": \"Happy Coder\",",
+ " \"legs\": 4,",
+ " \"tails\": 1,",
+ " \"friends\": [\"Free Code Camp Campers\"],",
+ " \"bark\": \"woof\"",
"};",
"",
"// Only change code below this line.",
"",
- "// Let's add the property bark to myDog",
- "",
- "",
- "// Now delete the property tails",
"",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
+ "",
"(function(z){return z;})(myDog);"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"cf1111c1c11feddfaeb5bdef",
+ "id": "cf1111c1c11feddfaeb5bdef",
"title": "Iterate with JavaScript For Loops",
- "difficulty":"9.9824",
- "description":[
+ "description": [
"You can run the same code multiple times by using a loop.",
"The most common type of JavaScript loop is called a \"for loop\" because it runs \"for\" a specific number of times.",
+ "For loops are declared with three optional expressions seperated by semicolons:",
+ "for([initialization]; [condition]; [final-expression])
",
+ "The initialization
statement is executed one time only before the loop starts. It is typically used to define and setup your loop varaible.",
+ "The condition
statement is evaluated at the beginning of every loop and will continue as long as it evalutes true
. When condition
is false
at the start of the loop, the loop will stop executing. This means if condition
starts as false
, your loop will never execute.",
+ "The final-expression
is executed at the end of each loop iteration, prior to the next condition
check and is usually used to increment or decrement your loop counter.",
+ "We'll initialize with i = 0
and loop while our condition i < 5
is true. We'll increment i
by 1 each loop with i++
as our final-expression
.",
"var ourArray = [];
",
"for(var i = 0; i < 5; i++) {
",
" ourArray.push(i);
",
@@ -798,24 +879,25 @@
"ourArray
will now contain [0,1,2,3,4] ",
"Let's try getting a for loop to work by pushing values to an array."
],
- "tests":[
- "assert(editor.getValue().match(/for/g), 'message: You should be using a for
loop for this.');",
- "assert.deepEqual(myArray, [0,1,2,3,4], 'message: myArray
should equal [0,1,2,3,4].');"
+ "tests": [
+ "assert(editor.getValue().match(/for\\s*\\(/g).length > 1, 'message: You should be using a for
loop for this.');",
+ "assert.deepEqual(myArray, [0,1,2,3,4], 'message: myArray
should equal [0,1,2,3,4]
');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var ourArray = [];",
+ "",
"for(var i = 0; i < 5; i++){",
" ourArray.push(i);",
"}",
+ "",
"var myArray = [];",
"",
"// Only change code below this line.",
"",
- "// Push the numbers zero through four to myArray using a \"for loop\" like above.",
+ "",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"if(typeof(myArray) !== \"undefined\"){(function(){return myArray;})();}",
""
],
@@ -823,10 +905,88 @@
"challengeType": 1
},
{
- "id":"cf1111c1c11feddfaeb1bdef",
- "title": "Iterate with JavaScript While Loops",
- "difficulty":"9.9825",
+ "id":"56104e9e514f539506016a5c",
+ "title": "Iterate Odd Numbers With a For Loop",
"description":[
+ "For loops don't have to iterate one at a time. By changing our final-expression
, we can count by even numbers.",
+ "We'll start at i = 0
and loop while i < 10
. We'll increment i
by 2 each loop with i += 2
.",
+ "var ourArray = [];
",
+ "for(var i = 0; i < 10; i += 2) {
",
+ " ourArray.push(i);
",
+ "}
",
+ "ourArray
will now contain [0,2,4,6,8] ",
+ "Let's change our initialization
and final-expression
so we can count by odd numbers.",
+ "Push the odd numbers from 1 through 9 to myArray
using a for loop
."
+ ],
+ "tests":[
+ "assert(editor.getValue().match(/for\\s*\\(/g).length > 1, 'message: You should be using a for
loop for this.');",
+ "assert.deepEqual(myArray, [1,3,5,7,9], 'message: myArray
should equal [1,3,5,7,9]
');"
+ ],
+ "challengeSeed":[
+ "var ourArray = [];",
+ "",
+ "for(var i = 1; i < 10; i += 2){",
+ " ourArray.push(i);",
+ "}",
+ "",
+ "var myArray = [];",
+ "",
+ "// Only change code below this line.",
+ "",
+ "",
+ "",
+ "// Only change code above this line.",
+ "",
+ "if(typeof(myArray) !== \"undefined\"){(function(){return myArray;})();}",
+ ""
+ ],
+ "type": "waypoint",
+ "challengeType": 1
+ },
+ {
+ "id":"56105e7b514f539506016a5e",
+ "title": "Count Backwards With a For Loop",
+ "description":[
+ "A for loop can also count backwards, so long as we can define the right conditions.",
+ "In order to count backwards by twos, we'll need to change our initialization
, condition
, and final-expression
.",
+ "We'll start at i = 10
and loop while i > 0
. We'll decrement i
by 2 each loop with i -= 2
.",
+ "var ourArray = [];
",
+ "for(var i = 10; i > 0; i -= 2) {
",
+ " ourArray.push(i);
",
+ "}
",
+ "ourArray
will now contain [10,8,6,4,2]
",
+ "Let's change our initialization
and final-expression
so we can count backward by twos for numbers.",
+ "Push the odd numbers from 9 through 1 to myArray
using a for loop
."
+ ],
+ "tests":[
+ "assert(editor.getValue().match(/for\\s*\\(/g).length > 1, 'message: You should be using a for
loop for this.');",
+ "assert.deepEqual(myArray, [9,7,5,3,1], 'message: myArray
should equal [9,7,5,3,1]
');"
+ ],
+ "challengeSeed":[
+ "var ourArray = [];",
+ "",
+ "for(var i = 10; i > 0; i -= 2){",
+ " ourArray.push(i);",
+ "}",
+ "",
+ "var myArray = [];",
+ "",
+ "// Only change code below this line.",
+ "",
+ "",
+ "",
+ "// Only change code above this line.",
+ "",
+ "if(typeof(myArray) !== \"undefined\"){(function(){return myArray;})();}",
+ ""
+ ],
+ "type": "waypoint",
+ "challengeType": 1
+ },
+ {
+ "id": "cf1111c1c11feddfaeb1bdef",
+ "title": "Iterate with JavaScript While Loops",
+ "description": [
"You can run the same code multiple times by using a loop.",
"Another type of JavaScript loop is called a \"while loop\", because it runs \"while\" something is true and stops once that something is no longer true.",
"var ourArray = [];
",
@@ -835,21 +995,22 @@
" ourArray.push(i);
",
" i++;
",
"}
",
- "Let's try getting a while loop to work by pushing values to an array."
+ "Let's try getting a while loop to work by pushing values to an array.",
+ "Push the numbers 0 through 4 to myArray
using a while loop
."
],
- "tests":[
+ "tests": [
"assert(editor.getValue().match(/while/g), 'message: You should be using a while
loop for this.');",
- "assert.deepEqual(myArray, [0,1,2,3,4], 'message: myArray
should equal [0,1,2,3,4].');"
+ "assert.deepEqual(myArray, [0,1,2,3,4], 'message: myArray
should equal [0,1,2,3,4]
');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var myArray = [];",
+ "",
"// Only change code below this line.",
"",
- "// Push the numbers zero through four to myArray using a \"while loop\".",
+ "",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
- "// You'll learn about functions soon.",
+ "",
"if(typeof(myArray) !== \"undefined\"){(function(){return myArray;})();}",
""
],
@@ -857,22 +1018,22 @@
"challengeType": 1
},
{
- "id":"cf1111c1c11feddfaeb9bdef",
+ "id": "cf1111c1c11feddfaeb9bdef",
"title": "Generate Random Fractions with JavaScript",
- "difficulty":"9.9827",
- "description":[
+ "description": [
"Random numbers are useful for creating random behavior.",
"JavaScript has a Math.random()
function that generates a random decimal number.",
- "Use Math.random()
to get myFunction
to return a random number."
+ "Change myFunction
to return a random number instead of returning 0
.",
+ "Note that you can return a function, just like you would return a variable or value."
],
- "tests":[
+ "tests": [
"assert(typeof(myFunction()) === \"number\", 'message: myFunction
should return a random number.');",
"assert((myFunction()+''). match(/\\./g), 'message: The number returned by myFunction
should be a decimal.');",
- "assert(editor.getValue().match(/Math\\.random/g).length >= 2, 'message: You should be using Math.random
to generate the random decimal number.');"
+ "assert(editor.getValue().match(/Math\\.random/g).length >= 0, 'message: You should be using Math.random
to generate the random decimal number.');"
],
- "challengeSeed":[
+ "challengeSeed": [
"function myFunction() {",
- " // Change the 0 to Math.random().",
+ "",
" // Only change code below this line.",
"",
" return 0;",
@@ -880,33 +1041,36 @@
" // Only change code above this line.",
"}",
"",
- "// We use this function to show you the value of your variable in your output box.",
"(function(){return myFunction();})();"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"cf1111c1c12feddfaeb1bdef",
+ "id": "cf1111c1c12feddfaeb1bdef",
"title": "Generate Random Whole Numbers with JavaScript",
- "difficulty":"9.9828",
- "description":[
- "It's great that we can create random decimal numbers, but it's even more useful if we use it to generate a random whole number.",
- "To achieve this we can multiply the random number by ten and use the Math.floor()
to convert the decimal number to the nearest less than or equal whole number.",
- "This technique gives us a whole number between zero and nine.",
- "Example:",
- "Math.floor(Math.random()*10);
",
- "Let's give this technique a go now."
+ "description": [
+ "It's great that we can generate random decimal numbers, but it's even more useful if we use it to generate random whole numbers.",
+ "First, let's use Math.random()
to generate a random decimal.",
+ "Then let's multiply this random decimal by 20.",
+ "Finally, let's use another function, Math.floor()
to round the number down to its nearest whole number.",
+ "This technique will gives us a whole number between 0 and 19.",
+ "Note that because we're rounding down, it's impossible to actually get 20.",
+ "Putting everything together, this is what our code looks like:",
+ "Math.floor(Math.random() * 20);
",
+ "See how Math.floor
takes (Math.random() * 20)
as its argument? That's right - you can pass a function to another function as an argument.",
+ "Let's use this technique to generate and return a random whole number between 0 and 9."
],
- "tests":[
+ "tests": [
"assert(typeof(myFunction()) === \"number\", 'message: The result of myFunction
should be a number.');",
- "assert(editor.getValue().match(/Math.random/g), 'message: You should be using Math.random to create a random number.');",
+ "assert(editor.getValue().match(/Math.random/g), 'message: You should be using Math.random to generate a random number.');",
"assert(editor.getValue().match(/\\(\\s*?Math.random\\s*?\\(\\s*?\\)\\s*?\\*\\s*?10\\s*?\\)/g) || editor.getValue().match(/\\(\\s*?10\\s*?\\*\\s*?Math.random\\s*?\\(\\s*?\\)\\s*?\\)/g), 'message: You should have multiplied the result of Math.random
by 10 to make it a number that is between zero and nine.');",
"assert(editor.getValue().match(/Math.floor/g), 'message: You should use Math.floor
to remove the decimal part of the number.');"
],
- "challengeSeed":[
+ "challengeSeed": [
+ "var randomNumberBetween0and19 = Math.floor(Math.random() * 20);",
+ "",
"function myFunction(){",
- " // Make myFunction return a random number between zero and nine instead of a decimal.",
"",
" // Only change code below this line.",
"",
@@ -915,53 +1079,67 @@
" // Only change code above this line.",
"}",
"",
- "// We use this function to show you the value of your variable in your output box.",
"(function(){return myFunction();})();"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"cf1111c1c12feddfaeb2bdef",
+ "id": "cf1111c1c12feddfaeb2bdef",
"title": "Generate Random Whole Numbers within a Range",
- "difficulty":"9.9829",
- "description":[
- "We can use a certain mathematical expression to get a random number between two numbers.",
+ "description": [
+ "Instead of generating a random number between zero and a given number like we did before, we can generate a random number that falls within a range of two specific numbers.",
+ "To do this, we'll define a minimum number min
and a maximum number max
.",
+ "Here's the formula we'll use. Take a moment to read it and try to understand what this code is doing:",
"Math.floor(Math.random() * (max - min + 1)) + min
",
- "By using this, we can control the output of a random number."
+ "Define two variables: myMin
and myMax, and set them both equal to numbers.",
+ "Then create a function called myFunction
that returns a random number that's greater than or equal to myMin
, and is less than myMax
."
],
- "tests":[
- "assert(myFunction() >= min, 'message: The random number generated by myFunction
should be greater than or equal to the minimum number.');",
- "assert(myFunction() <= max, 'message: The random number generated by myFunction
should be less than or equal to the maximum number.');",
+ "tests": [
+ "assert(myFunction() >= myMin, 'message: The random number generated by myFunction
should be greater than or equal to your minimum number, myMin
.');",
+ "assert(myFunction() <= myMax, 'message: The random number generated by myFunction
should be less than or equal to your maximum number, myMax
.');",
"assert(myFunction() % 1 === 0 , 'message: The random number generated by myFunction
should be an integer, not a decimal.');",
- "assert((function(){if(editor.getValue().match(/max/g).length >= 2 && editor.getValue().match(/min/g).length >= 2 && editor.getValue().match(/Math.floor/g) && editor.getValue().match(/Math.random/g)){return true;}else{return false;}})(), 'message: You should be using the function given in the description to calculate the random in number in a range.');"
+ "assert((function(){if(editor.getValue().match(/myMax/g).length > 1 && editor.getValue().match(/myMin/g).length > 2 && editor.getValue().match(/Math.floor/g) && editor.getValue().match(/Math.random/g)){return true;}else{return false;}})(), 'message: myFunction()
should use use both myMax
and myMin
, and return a random number in your range.');"
],
- "challengeSeed":[
- "var min = 0;",
- "var max = 9;",
- "function myFunction() {",
- " // Make myFunction return a random number between min and max values instead of a decimal",
- " // Only change code below this line.",
+ "challengeSeed": [
+ "var ourMin = 1;",
+ "",
+ "var ourMax = 9;",
+ "",
+ "function ourFunction() {",
+ "",
+ " return Math.floor(Math.random() * (ourMax - ourMin + 1)) + ourMin;",
+ "",
+ "}",
+ "",
+ "// Only change code below this line.",
+ "",
+ "var myMin;",
+ "",
+ "var myMax;",
+ "",
+ "function myFunction() {",
+ "",
+ " return;",
"",
- " return Math.random();",
"}",
"",
"// Only change code above this line.",
- "// We use this function to show you the value of your variable in your output box.",
+ "",
+ "",
"(function(){return myFunction();})();"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"cf1111c1c12feddfaeb3bdef",
+ "id": "cf1111c1c12feddfaeb3bdef",
"title": "Use Conditional Logic with If and Else Statements",
- "difficulty":"9.983",
- "description":[
+ "description": [
"We can use if
statements in JavaScript to only execute code if a certain condition is met.",
"if
statements require some sort of boolean condition to evaluate.",
"For example:",
- " if (1 === 2) {
",
+ "if (1 === 2) {
",
" return true;
",
"} else {
",
" return false;
",
@@ -969,58 +1147,59 @@
"Let's use if
and else
statements to make a coin-flip game.",
"Create if
and else
statements to return the string \"heads\"
if the flip variable is zero, or else return the string \"tails\"
if the flip variable is not zero."
],
- "tests":[
+ "tests": [
+ "assert(editor.getValue().match(/if/g).length >= 2, 'message: Create a new if statement.');",
+ "assert(editor.getValue().match(/else/g).length >= 1, 'message: Created a new else statement.');",
"assert((function(){var result = myFunction();if(result === 'heads' || result === 'tails'){return true;} else {return false;}})(), 'message: myFunction
should either return heads
or tails
.');",
- "assert((function(){var result = myFunction();if(result === 'heads' && flip === 0 || result === 'tails' && flip !== 0){return true;} else {return false;}})(), 'message: myFunction
should return heads
when flip equals 0 and tails
when flip equals 1.');",
- "assert(editor.getValue().match(/if/g).length >= 4, 'message: You should have created a new if statement.');",
- "assert(editor.getValue().match(/else/g).length >= 2, 'message: You should have created a new else statement.');"
+ "assert((function(){var result = myFunction();if(result === 'heads' && flip === 0 || result === 'tails' && flip !== 0){return true;} else {return false;}})(), 'message: myFunction
should return heads
when flip equals 0 and tails
when flip equals 1.');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var flip = Math.floor(Math.random() * (1 - 0 + 1)) + 0;",
- "function myFunction(){",
- " // Create an if-else statement here to return \"heads\" if flip is 0. Otherwise return \"tails\".",
+ "",
+ "function myFunction() {",
"",
" // Only change code below this line.",
"",
"",
"",
" // Only change code above this line.",
+ "",
"}",
"",
- "// We use this function to show you the value of your variable in your output box.",
"var result = myFunction();if(typeof(flip) !== \"undefined\" && typeof(flip) === \"number\" && typeof(result) !== \"undefined\" && typeof(result) === \"string\"){(function(y,z){return 'flip = ' + y.toString() + ', text = ' + z;})(flip, result);}"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"cf1111c1c12feddfaeb6bdef",
+ "id": "cf1111c1c12feddfaeb6bdef",
"title": "Sift through Text with Regular Expressions",
- "difficulty":"9.984",
- "description":[
+ "description": [
"Regular expressions
are used to find certain words or patterns inside of strings
.",
- "For example, if we wanted to find the word the
in the string The dog chased the cat
, we could use the following regular expression
: \/the\/gi
",
+ "For example, if we wanted to find the word the
in the string The dog chased the cat
, we could use the following regular expression
: /the/gi
",
"Let's break this down a bit:",
"the
is the pattern we want to match.",
"g
means that we want to search the entire string for this pattern instead of just the first match.",
"i
means that we want to ignore the case (uppercase or lowercase) when searching for the pattern.",
"Regular expressions
are written by surrounding the pattern with /
symbols.",
- "Let's try selecting all the occurrences of the word and
in the string Ada Lovelace and Charles Babbage designed the first computer and the software that would have run on it
. We can do this by replacing the .
part of our regular expression with the current regular expression
with the word and
."
+ "Let's try selecting all the occurrences of the word and
in the string Ada Lovelace and Charles Babbage designed the first computer and the software that would have run on it
.",
+ "We can do this by replacing the .
part of our regular expression with the current regular expression
with the word and
."
],
- "tests":[
+ "tests": [
"assert(test==2, 'message: Your regular expression
should find two occurrences of the word and
.');",
- "assert(editor.getValue().match(/\\/and\\/gi/), 'message: You should have used regular expressions
to find the word and
.');"
+ "assert(editor.getValue().match(/\\/and\\/gi/), 'message: Use regular expressions
to find the word and
in testString
.');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var test = (function() {",
" var testString = \"Ada Lovelace and Charles Babbage designed the first computer and the software that would have run on it.\";",
" var expressionToGetSoftware = /software/gi;",
+ "",
" // Only change code below this line.",
"",
" var expression = /./gi;",
"",
" // Only change code above this line.",
- " // We use this function to show you the value of your variable in your output box.",
+ "",
" return testString.match(expression).length;",
"})();(function(){return test;})();"
],
@@ -1028,22 +1207,22 @@
"challengeType": 1
},
{
- "id":"cf1111c1c12feddfaeb7bdef",
+ "id": "cf1111c1c12feddfaeb7bdef",
"title": "Find Numbers with Regular Expressions",
- "difficulty":"9.985",
- "description":[
+ "description": [
"We can use special selectors in Regular Expressions
to select a particular type of value.",
"One such selector is the digit selector \\d
which is used to grab the numbers in a string.",
"It is used like this: /\\d/g
.",
"For numbers this is often written as /\\d+/g
, where the +
following the digit selector allows this regular expression to match multi-digit numbers.",
"Use the \\d
selector to select the number of numbers in the string, allowing for the possibility of multi-digit numbers."
],
- "tests":[
- "assert(test === 2, 'message: Your RegEx should have found two numbers in the testString
.');",
- "assert(editor.getValue().match(/\\/\\\\d\\+\\//g), 'message: You should be using the following expression /\\d+/g
to find the numbers in the testString
.');"
+ "tests": [
+ "assert(editor.getValue().match(/\\/\\\\d\\+\\//g), 'message: Use the /\\d+/g
regular expression to find the numbers in testString
.');",
+ "assert(test === 2, 'message: Your regular expression should find two numbers in testString
.');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var test = (function() {",
+ "",
" var testString = \"There are 3 cats but 4 dogs.\";",
"",
" // Only change code below this line.",
@@ -1051,29 +1230,29 @@
" var expression = /.+/g;",
"",
" // Only change code above this line.",
- " // We use this function to show you the value of your variable in your output box.",
+ "",
" return testString.match(expression).length;",
+ "",
"})();(function(){return test;})();"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"cf1111c1c12feddfaeb8bdef",
+ "id": "cf1111c1c12feddfaeb8bdef",
"title": "Find Whitespace with Regular Expressions",
- "difficulty":"9.986",
- "description":[
- "We can also use selectors like \\s
to find whitespace in a string.",
- "The whitespace characters are \" \"
(space), \\r
(carriage return), \\n
(newline), \\t
(tab), and \\f
(form feed).",
- "It is used like this:",
+ "description": [
+ "We can also use regular expression selectors like \\s
to find whitespace in a string.",
+ "The whitespace characters are \" \"
(space), \\r
(the carriage return), \\n
(newline), \\t
(tab), and \\f
(the form feed).",
+ "The whitespace regular expression looks like this:",
"/\\s+/g
",
- "Select all the whitespace characters in the sentence string."
+ "Use it to select all the whitespace characters in the sentence string."
],
- "tests":[
- "assert(test === 7, 'message: Your RegEx should have found seven spaces in the testString
.');",
- "assert(editor.getValue().match(/\\/\\\\s\\+\\//g), 'message: You should be using the following expression /\\s+/g
to find the spaces in the testString
.');"
+ "tests": [
+ "assert(editor.getValue().match(/\\/\\\\s\\+\\//g), 'message: Use the /\\s+/g
regular expression to find the spaces in testString
.');",
+ "assert(test === 7, 'message: Your regular expression should find seven spaces in testString
.');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var test = (function(){",
" var testString = \"How many spaces are there in this sentence?\";",
"",
@@ -1082,26 +1261,27 @@
" var expression = /.+/g;",
"",
" // Only change code above this line.",
- " // We use this function to show you the value of your variable in your output box.",
+ "",
" return testString.match(expression).length;",
+ "",
"})();(function(){return test;})();"
],
"type": "waypoint",
"challengeType": 1
},
{
- "id":"cf1111c1c13feddfaeb3bdef",
+ "id": "cf1111c1c13feddfaeb3bdef",
"title": "Invert Regular Expression Matches with JavaScript",
- "difficulty":"9.987",
- "description":[
- "Use /\\S/g
to match everything that isn't a space in the string.",
- "You can invert any match by using the uppercase version of the selector \\s
versus \\S
for example."
+ "description": [
+ "You can invert any match by using the uppercase version of the regular expression selector.",
+ "For example, \\s
will match any whitespace, and \\S
will match anything that isn't whitespace.",
+ "Use /\\S/g
to count the number of non-whitespace characters in testString
."
],
- "tests":[
- "assert(test === 49, 'message: Your RegEx should have found forty nine non-space characters in the testString
.');",
- "assert(editor.getValue().match(/\\/\\\\S\\/g/g), 'message: You should be using the following expression /\\S/g
to find non-space characters in the testString
.');"
+ "tests": [
+ "assert(editor.getValue().match(/\\/\\\\S\\/g/g), 'message: Use the /\\S/g
regular expression to find non-space characters in testString
.');",
+ "assert(test === 49, 'message: Your regular expression should find forty nine non-space characters in the testString
.');"
],
- "challengeSeed":[
+ "challengeSeed": [
"var test = (function(){",
" var testString = \"How many non-space characters are there in this sentence?\";",
"",
@@ -1110,31 +1290,30 @@
" var expression = /./g;",
"",
" // Only change code above this line.",
- " // We use this function to show you the value of your variable in your output box.",
+ "",
" return testString.match(expression).length;",
"})();(function(){return test;})();"
],
"type": "waypoint",
- "challengeType":1
+ "challengeType": 1
},
{
- "id":"cf1111c1c12feddfaeb9bdef",
+ "id": "cf1111c1c12feddfaeb9bdef",
"title": "Create a JavaScript Slot Machine",
- "difficulty":"9.988",
- "description":[
+ "description": [
"We are now going to try and combine some of the stuff we've just learned and create the logic for a slot machine game.",
"For this we will need to generate three random numbers between 1
and 3
to represent the possible values of each individual slot.",
"Store the three random numbers in slotOne
, slotTwo
and slotThree
.",
"Generate the random numbers by using the system we used earlier (an explanation of the formula can be found here):",
"Math.floor(Math.random() * (3 - 1 + 1)) + 1;
"
],
- "tests":[
- "assert(typeof(runSlots($(\".slot\"))[0]) === \"number\", 'slotOne
should be a random number.')",
- "assert(typeof(runSlots($(\".slot\"))[1]) === \"number\", 'slotTwo
should be a random number.')",
- "assert(typeof(runSlots($(\".slot\"))[2]) === \"number\", 'slotThree
should be a random number.')",
- "assert((function(){if(editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?3\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi) !== null){return editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?3\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi).length >= 3;}else{return false;}})(), 'You should have used Math.floor(Math.random() * (3 - 1 + 1)) + 1;
three times to generate your random numbers.')"
+ "tests": [
+ "assert(typeof(runSlots($(\".slot\"))[0]) === \"number\" && runSlots($(\".slot\"))[0] > 0 && runSlots($(\".slot\"))[0] < 4, 'slotOne
should be a random number.')",
+ "assert(typeof(runSlots($(\".slot\"))[1]) === \"number\" && runSlots($(\".slot\"))[1] > 0 && runSlots($(\".slot\"))[1] < 4, 'slotTwo
should be a random number.')",
+ "assert(typeof(runSlots($(\".slot\"))[2]) === \"number\" && runSlots($(\".slot\"))[2] > 0 && runSlots($(\".slot\"))[2] < 4, 'slotThree
should be a random number.')",
+ "assert((function(){if(editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?3\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1/gi) !== null){return editor.match(/slot.*?=.*?\\(.*?\\).*?/gi).length >= 3;}else{return false;}})(), 'You should have used Math.floor(Math.random() * (3 - 1 + 1)) + 1;
three times to generate your random numbers.')"
],
- "challengeSeed":[
+ "challengeSeed": [
"fccss",
" function runSlots(){",
" var slotOne;",
@@ -1272,10 +1451,9 @@
"challengeType": 0
},
{
- "id":"cf1111c1c13feddfaeb1bdef",
+ "id": "cf1111c1c13feddfaeb1bdef",
"title": "Add your JavaScript Slot Machine Slots",
- "difficulty":"9.989",
- "description":[
+ "description": [
"Now that our slots will each generate random numbers, we need to check whether they've all returned the same number.",
"If they have, we should notify our user that they've won.",
"Otherwise, we should return null
, which is a JavaScript data structure that means nothing.",
@@ -1285,10 +1463,10 @@
" return null;
",
"}
"
],
- "tests":[
- "assert((function(){var data = runSlots();if(data === null){return true}else{if(data[0] === data[1] && data[1] === data[2]){return true;}else{return false;}}})(), 'If all three of our random numbers are the same we should return that number. Otherwise we should return null
.')"
+ "tests": [
+ "assert((function(){var data = runSlots();return data === null || data.toString().length === 1;})(), 'If all three of our random numbers are the same we should return that number. Otherwise we should return null
.')"
],
- "challengeSeed":[
+ "challengeSeed": [
"fccss",
" function runSlots(){",
" var slotOne;",
@@ -1432,10 +1610,9 @@
"challengeType": 0
},
{
- "id":"cf1111c1c13feddfaeb2bdef",
+ "id": "cf1111c1c13feddfaeb2bdef",
"title": "Bring your JavaScript Slot Machine to Life",
- "difficulty":"9.990",
- "description":[
+ "description": [
"Now we can detect a win. Let's get this slot machine working.",
"Let's use the jQuery selector
$(\".slot\")
to select all of the slots.",
"Once they are all selected, we can use bracket notation
to access each individual slot:",
@@ -1443,11 +1620,11 @@
"This jQuery will select the first and update the slot's HTML to display the correct number.",
"Use the above selector to display each number in its corresponding slot."
],
- "tests":[
+ "tests": [
"assert((function(){runSlots();if($($(\".slot\")[0]).html().replace(/\\s/gi, \"\") !== \"\" && $($(\".slot\")[1]).html().replace(/\\s/gi, \"\") !== \"\" && $($(\".slot\")[2]).html().replace(/\\s/gi, \"\") !== \"\"){return true;}else{return false;}})(), 'You should be displaying the result of the slot numbers in the corresponding slots.')",
"assert((editor.match( /\\$\\s*?\\(\\s*?\\$\\s*?\\(\\s*?(?:'|\")\\s*?\\.slot\\s*?(?:'|\")\\s*?\\)\\[\\d\\]\\s*?\\)/gi) && editor.match( /\\$\\s*?\\(\\s*?\\$\\s*?\\(\\s*?(?:'|\")\\s*?\\.slot\\s*?(?:'|\")\\s*?\\)\\[\\d\\]\\s*?\\)/gi ).length >= 3 && editor.match( /\\.html\\(slotOne\\)/gi ) && editor.match( /\\.html\\(slotTwo\\)/gi ) && editor.match( /\\.html\\(slotThree\\)/gi )), 'You should have used the the selector given in the description to select each slot and assign it the value of slotOne
, slotTwo
and slotThree
respectively.')"
],
- "challengeSeed":[
+ "challengeSeed": [
"fccss",
" function runSlots(){",
" var slotOne;",
@@ -1469,8 +1646,8 @@
" ",
" // Only change code above this line.",
" ",
- " if(slotOne !== slotTwo || slotTwo !== slotThree){",
- " return null;",
+ " if (slotOne === slotTwo && slotTwo === slotThree) {",
+ " return slotOne;",
" }",
" ",
" if(slotOne !== undefined && slotTwo !== undefined && slotThree !== undefined){",
@@ -1598,17 +1775,16 @@
"challengeType": 0
},
{
- "id":"cf1111c1c11feddfaeb1bdff",
+ "id": "cf1111c1c11feddfaeb1bdff",
"title": "Give your JavaScript Slot Machine some Stylish Images",
- "difficulty":"9.9901",
- "description":[
+ "description": [
"Now let's add some images to our slots.",
"We've already set up the images for you in an array called images
. We can use different indexes to grab each of these.",
"Here's how we would set the first slot to show a different image depending on which number its random number generates:",
"$($('.slot')[0]).html('<img src = \"' + images[slotOne-1] + '\">');
",
"Set up all three slots like this, then click the \"Go\" button to play the slot machine."
],
- "tests":[
+ "tests": [
"assert((editor.match(/\\$\\s*?\\(\\s*?\\$\\s*?\\(\\s*?(?:'|\")\\s*?\\.slot\\s*?(?:'|\")\\s*?\\)\\[\\d\\]\\s*?\\)\\.html\\(\\s*?\\'\\$('.slot')[0]
at least once.')",
"assert(editor.match(/\\$\\s*?\\(\\s*?\\$\\s*?\\(\\s*?(?:'|\")\\s*?\\.slot\\s*?(?:'|\")\\s*?\\)\\[1\\]\\s*?\\)/gi), 'You should have used $('.slot')[1]
at least once.')",
@@ -1617,7 +1793,7 @@
"assert(editor.match(/slotTwo/gi) && editor.match(/slotTwo/gi).length >= 8, 'You should have used the slotTwo
value at least once.')",
"assert(editor.match(/slotThree/gi) && editor.match(/slotThree/gi).length >= 7, 'You should have used the slotThree
value at least once.')"
],
- "challengeSeed":[
+ "challengeSeed": [
"fccss",
" function runSlots(){",
" var slotOne;",
@@ -1639,8 +1815,8 @@
" ",
" // Only change code above this line.",
" ",
- " if(slotOne !== slotTwo || slotTwo !== slotThree){",
- " return null;",
+ " if (slotOne === slotTwo && slotTwo === slotThree) {",
+ " return slotOne;",
" }",
" ",
" if(slotOne !== undefined && slotTwo !== undefined && slotThree !== undefined){",
diff --git a/seed/challenges/basic-ziplines.json b/seed/challenges/basic-ziplines.json
index 4565f364a8..0cd948d614 100644
--- a/seed/challenges/basic-ziplines.json
+++ b/seed/challenges/basic-ziplines.json
@@ -35,7 +35,7 @@
[
"http://i.imgur.com/Wzt6Y9Y.gif",
"A gif showing the process of saving and forking a pen.",
- "Save your pen with the \"Save\" button. Then click the \"Fork\" button. This will create a fork (copy) of your pen that you can experimient with.",
+ "Save your pen with the \"Save\" button. Then click the \"Fork\" button. This will create a fork (copy) of your pen that you can experiment with.",
""
]
],
@@ -68,7 +68,7 @@
"User Story: As a user, I can click different buttons that will take me to the portfolio creator's different social media pages.",
"User Story: As a user, I can see thumbnail images of different projects the portfolio creator has built (if you haven't built any websites before, use placeholders.)",
"Bonus User Story: As a user, I navigate to different sections of the webpage by clicking buttons in the navigation.",
- "Don't worry if you don't have anything to showcase on your portfolio yet - you will build several several apps on the next few CodePen challenges, and can come back and update your portfolio later.",
+ "Don't worry if you don't have anything to showcase on your portfolio yet - you will build several apps on the next few CodePen challenges, and can come back and update your portfolio later.",
"There are many great portfolio templates out there, but for this challenge, you'll need to build a portfolio page yourself. Using Bootstrap will make this much easier for you.",
"Note that CodePen.io overrides the Window.open() function, so if you want to open windows using jquery, you will need to target invisible anchor elements like this one: <a target='_blank'>
.",
"Remember to use Read-Search-Ask if you get stuck.",
diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json
index b97d45b04c..4306f0b5f7 100644
--- a/seed/challenges/bootstrap.json
+++ b/seed/challenges/bootstrap.json
@@ -10,12 +10,15 @@
"Now let's go back to our Cat Photo App. This time, we'll style it using the popular Bootstrap responsive CSS framework.",
"Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design
.",
"With responsive design, there is no need to design a mobile version of your website. It will look good on devices with screens of any width.",
- "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 added it for you to this page behind the scenes.",
+ "You can add Bootstrap to any app just by including it by adding the following code to the top of your HTML:",
+ "<link rel=\"stylesheet\" href=\"//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css\"/>
",
+ "In this case, we've already added it for you to this page behind the scenes.",
"To get started, we should nest all of our HTML in a div
element with the class container-fluid
."
],
"tests": [
- "assert($(\"div\").hasClass(\"container-fluid\"), 'Your div
element should have the class container-fluid
')",
- "assert(editor.match(/<\\/div>/g) && editor.match(/div
element should have the class container-fluid
.')",
+ "assert(editor.match(/<\\/div>/g) && editor.match(/.container-fluid
.')"
],
"challengeSeed": [
"",
@@ -90,14 +93,15 @@
"id": "bad87fee1348bd9acde08812",
"title": "Make Images Mobile Responsive",
"description": [
- "First, add a new image below the existing one. Set it's src
attribute to http://bit.ly/fcc-running-cats
.",
+ "First, add a new image below the existing one. Set its src
attribute to http://bit.ly/fcc-running-cats
.",
"It would be great if this image could be exactly the width of our phone's screen.",
"Fortunately, with Bootstrap, all we need to do is add the img-responsive
class to your image. Do this, and the image should perfectly fit the width of your page."
],
"tests": [
- "assert($(\"img\").length > 1, 'You should have a total of two images.')",
- "assert($(\"img\").hasClass(\"img-responsive\"), 'Your new image should have the class img-responsive
.')",
- "assert(new RegExp(\"http://bit.ly/fcc-running-cats\", \"gi\").test($(\"img.img-responsive\").attr(\"src\")), 'Add a second image with the src
of http://bit.ly/fcc-running-cats
.')"
+ "assert($(\"img\").length === 2, 'You should have a total of two images.')",
+ "assert($(\"img:eq(1)\").hasClass(\"img-responsive\"), 'Your new image should be below your old one and have the class img-responsive
.')",
+ "assert($(\"img:eq(1)\").attr(\"src\") === \"http://bit.ly/fcc-running-cats\", 'Your new image should have a src
of http://bit.ly/fcc-running-cats
.')",
+ "assert(editor.match(/text-center
to our h2
element.",
- "Remember that you can add several classes to the same element by separating each of them with a space, like this: <h2 class=\"red-text text-center\">your text</h2>
."
+ "Remember that you can add several classes to the same element by separating each of them with a space, like this:",
+ "<h2 class=\"red-text text-center\">your text</h2>
"
],
"tests": [
"assert($(\"h2\").hasClass(\"text-center\"), 'Your h2
element should be centered by applying the class text-center
')"
@@ -341,7 +346,7 @@
"id": "bad87fee1348cd8acef08812",
"title": "Create a Block Element Bootstrap Button",
"description": [
- "Normally, your button
elements are only as wide as the text that they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.",
+ "Normally, your button
elements are only as wide as the text that they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space and any elements following it will flow onto a \"new line\" below the block.",
"This image illustrates the difference between inline
elements and block-level
elements:",
"btn
class.",
@@ -888,7 +893,8 @@
"span
element, you can put several elements together, and even style different parts of the same element differently.",
"Nest the word \"love\" in your \"Things cats love\" element below within a span
element. Then give that span
the class text-danger
to make the text red.",
- "Here's how you would do this with the \"Top 3 things cats hate\" element: <p>Top 3 things cats <span class = \"text-danger\">hate</span></p>
"
+ "Here's how you would do this with the \"Top 3 things cats hate\" element:",
+ "<p>Top 3 things cats <span class = \"text-danger\">hate</span></p>
"
],
"tests": [
"assert($(\"p span\") && $(\"p span\").length > 0, 'Your span
element should be inside your p
element.')",
@@ -1904,9 +1910,10 @@
"title": "Add ID Attributes to Bootstrap Elements",
"description": [
"Recall that in addition to class attributes, you can give each of your elements an id
attribute.",
- "Each id should be unique to a specific element.",
+ "Each id must be unique to a specific element and used only once per page.",
"Let's give a unique id to each of our div
elements of class well
.",
- "Remember that you can give an element an id like this: <div class=\"well\" id=\"center-well\">
",
+ "Remember that you can give an element an id like this:",
+ "<div class=\"well\" id=\"center-well\">
",
"Give the well on the left the id of left-well
. Give the well on the right the id
of right-well
."
],
"tests": [
@@ -2106,11 +2113,11 @@
"When we start using jQuery, we will modify HTML elements without needing to actually change them in HTML.",
"Let's make sure that everyone knows they shouldn't actually modify any of this code directly.",
"Remember that you can start a comment with <!--
and end a comment with -->
",
- "Add a comment at the top of your HTML that says You shouldn't need to modify code below this line
."
+ "Add a comment at the top of your HTML that says Only change code above this line.
"
],
"tests": [
"assert(editor.match(/.*\\n+.+/g), 'Be sure to close your comment with -->
.')"
],
"challengeSeed": [
diff --git a/seed/challenges/gear-up-for-success.json b/seed/challenges/gear-up-for-success.json
index 7a6fd0a670..826db9bb3f 100644
--- a/seed/challenges/gear-up-for-success.json
+++ b/seed/challenges/gear-up-for-success.json
@@ -11,7 +11,7 @@
[
"http://i.imgur.com/YNwsMXM.gif",
"A gif showing how you can access our Camper News page and click the \"upvote\" button to upvote a story.",
- "Click the \"News\" button in your upper right hand corner. You can browse links on Camper News and upvote ones that you enjoy.",
+ "Click the \"News\" button in your upper right hand corner. code
in your text editor
, which we've embedded into this web page.",
"Do you see the code in your text editor that says <h1>Hello</h1>
? That's an HTML element
.",
- "Most HTML elements have an opening tag
and a closing tag
. Opening tags look like this: <h1>
. Closing tags look like this: </h1>
. Note that the only difference between opening tags and closing tags is that closing tags have a slash after their opening angle bracket.",
- "Once you've completed each challenge, and all its tests are passing, the \"Go to my next challenge\" button will become enabled. Click it - or press control and enter at the same time - to advance to the next challenge.",
- "To enable the \"Go to my next challenge\" button on this exercise, change your h1
tag's text to say \"Hello World\" instead of \"Hello\"."
+ "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 tags and closing tags is that closing tags have a slash after their opening angle bracket.",
+ "Each challenge has tests that you can run at any time by clicking the \"Run tests\" button. Once you get all tests passing, you can advance to the next challenge.",
+ "To pass the test on this challenge, change your h1
element's text to say \"Hello World\" instead of \"Hello\". Then click the \"Run tests\" button."
],
"tests": [
"assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1
element should have the text \"Hello World\".')"
@@ -45,7 +50,7 @@
"Willkommen bei der ersten Programmier-Challenge von Free Code Camp! Klicke auf den folgenden Button für weitere Instruktionen.",
"Sehr gut. Jetzt kannst du den Rest der Instruktionen für diese Challenge lesen.",
"Mithilfe des eingebauten Text Editors
kannst du den Code
bearbeiten.",
- "Siehst du den Code <h1>Hallo</h1>
im Editor? Das ist ein HTML Element
.",
+ "Siehst du den Code <h1>Hallo</h1>
im Editor? Das ist ein HTML Element
",
"Die meisten HTML Elemente haben eine öffnende Auszeichnung (Tag)
und eine sich schließende
. Öffnende Tags sehen so aus: <h1>
. Schließende Tags so: </h1>
. Beachte, dass der einzige Unterschied zwischen öffnenden und schließenden Tags in dem Slash besteht, das bei schließenden Tags auf die sich öffnende spitze Klammer folgt.",
"Sobald du eine Challenge abgeschlossen hast und alle Tests erfolgreich sind, wird der Button \"Go to my next challenge\" aktiv. Klicke auf diesen – oder drücke Steuerung (Control) und gleichzeitig Enter – um zur nächsten Challenge zu gehen.",
"Um den Button \"Go to my next challenge\" dieser Lektion zu aktivieren, ändere den Inhalt des h1
Tags von \"Hello\" zu \"Hello World\"."
@@ -57,10 +62,10 @@
"description": [
"Over the next few challenges, we'll build an HTML5 app that will look something like this:",
"h2
tag that says \"CatPhotoApp\" to create a second HTML element
below your \"Hello World\" h1
element.",
"The h2
element you enter will create an h2
element on the website.",
"This element tells the browser how to render the text that it contains.",
- "h2
elements are slightly smaller than h1
elements. There are also h3
, h4
, h5
and h6
elements."
+ "h2
elements are slightly smaller than h1
elements. There are also h3
, h4
, h5
and h6
elements.",
+ "Add an h2
tag that says \"CatPhotoApp\" to create a second HTML element
below your \"Hello World\" h1
element."
],
"tests": [
"assert(($(\"h2\").length > 0), 'Create an h2
element.')",
@@ -84,7 +89,7 @@
"Agrega una etiqueta h2
que diga \"CatPhotoApp\" para crear un segundo elemento
HTML debajo de tu elemento h1
\"Hello World\".",
"El elemento h2 que ingreses creará un elemento h2 en el sitio web.",
"Este elemento le dice al navegador cómo mostrar el texto que contiene.",
- "Los elementos h2
son ligeramente más pequeños que los elementos h1
. También hay elementos h3
, h4
, h5
y h6
."
+ "Los elementos h2
son ligeramente más pequeños que los elementos h1
. También hay elementos h3
, h4
, h5
y h6
"
],
"namePt": "",
"descriptionPt": [],
@@ -100,9 +105,10 @@
"id": "bad87fee1348bd9aedf08801",
"title": "Inform with the Paragraph Element",
"description": [
- "Create a p
element below your h2
element, and give it the text \"Hello Paragraph\".",
"p
elements are the preferred element for normal-sized paragraph text on websites. P is short for \"paragraph\".",
- "You can create a p
element like so: <p>I'm a p tag!</p>
."
+ "You can create a p
element like this:",
+ "<p>I'm a p tag!</p>
",
+ "Create a p
element below your h2
element, and give it the text \"Hello Paragraph\"."
],
"tests": [
"assert(($(\"p\").length > 0), 'Create a p
element.')",
@@ -123,9 +129,9 @@
"descriptionRu": [],
"nameEs": "Waypoint: Informa con el Elemento Párrafo",
"descriptionEs": [
- "Crea un elemento párrafo debajo de tu elemento h2, y dale el texto \"Hello Paragraph\". Apenas escribas la etiqueta de apertura <p>
, una de nuestras pruebas pasarán (ya que ésta es HTML válido). Asegúrate de cerrar el elemento agregando la etiqueta de cierre </p>
.",
+ "Crea un elemento párrafo debajo de tu elemento h2, y dale el texto \"Hello Paragraph\". Apenas escribas la etiqueta de apertura <p>
, una de nuestras pruebas pasarán (ya que ésta es HTML válido). Asegúrate de cerrar el elemento agregando la etiqueta de cierre </p>
",
"Los elementos párrafo son los principales elementos para los párrafos de texto en tamaño normal en sitios web.",
- "Tú puedes crear un elemento párrafo como éste: <p>I'm a p tag!</p>
."
+ "Tú puedes crear un elemento párrafo como éste: <p>I'm a p tag!</p>
"
],
"namePt": "",
"descriptionPt": [],
@@ -140,10 +146,10 @@
"id": "bad87fee1348bd9aedf08802",
"title": "Uncomment HTML",
"description": [
- "Uncomment your h1
, h2
and p
elements.",
"Commenting is a way that you can leave comments within your code without affecting the code itself.",
"Commenting is also a convenient way to make code inactive without having to delete it entirely.",
- "You can start a comment with <!--
and end a comment with -->
."
+ "You can start a comment with <!--
and end a comment with -->
",
+ "Uncomment your h1
, h2
and p
elements."
],
"tests": [
"assert($(\"h1\").length > 0, 'Make your h1
element visible on your page by uncommenting it.')",
@@ -170,10 +176,10 @@
"descriptionRu": [],
"nameEs": "Waypoint: Quitar comentarios HTML",
"descriptionEs": [
- "Quitar el comentario a los elementos h1
, h2
y p
.",
+ "Quitar el comentario a los elementos h1
, h2
y p
",
"Crear comentarios es una forma en la que puedes dejar mensajes dentro de tu código sin afectar el resultado.",
"Agregar comentarios es también una forma conveniente de desactivar tu código sin tener que borrarlo por completo.",
- "Puedes comenzar un comentario con <!--
y terminar de comentar con -->
."
+ "Puedes comenzar un comentario con <!--
y terminar de comentar con -->
"
],
"namePt": "",
"descriptionPt": [],
@@ -189,9 +195,9 @@
"id": "bad87fee1348bd9aedf08804",
"title": "Comment out HTML",
"description": [
- "Comment out your h1
element and your p
element, but leave your h2
element uncommented.",
- "Remember that in order to start a comment, you need to use <!--
and to end a comment, you need to use -->
.",
- "Here you'll need to end the comment before your h2
element begins."
+ "Remember that in order to start a comment, you need to use <!--
and to end a comment, you need to use -->
",
+ "Here you'll need to end the comment before your h2
element begins.",
+ "Comment out your h1
element and your p
element, but leave your h2
element uncommented."
],
"tests": [
"assert(($(\"h1\").length === 0), 'Comment out your h1
element so that it is not visible on your page.')",
@@ -218,8 +224,8 @@
"descriptionRu": [],
"nameEs": "Waypoint: Comenta en HTML",
"descriptionEs": [
- "Comenta el elemento h1
y el elemento p
, pero deja sin comentar el elemento h2
.",
- "Recuerda que para comenzar un comentario, necesitas usar <!--
y para terminar un comentario, necesitas usar -->
.",
+ "Comenta el elemento h1
y el elemento p
, pero deja sin comentar el elemento h2
",
+ "Recuerda que para comenzar un comentario, necesitas usar <!--
y para terminar un comentario, necesitas usar -->
",
"Aquí necesitarás terminar el comentario antes que comience el elemento h2."
],
"namePt": "",
@@ -235,10 +241,10 @@
"id": "bad87fee1348bd9aedf08833",
"title": "Fill in the Blank with Placeholder Text",
"description": [
- "Web developers traditionally use lorem ipsum text
as placeholder text. It's called lorem ipsum text
because those are the first two words of a famous passage by Cicero of Ancient Rome.",
- "lorem ipsum text
has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web.",
+ "Web developers traditionally use lorem ipsum text
as placeholder text. It's called lorem ipsum text because those are the first two words of a famous passage by Cicero of Ancient Rome.",
+ "Lorem ipsum text has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web.",
"Well, 5 centuries is long enough. Since we're building a CatPhotoApp, let's use something called kitty ipsum text
.",
- "Replace the text inside your p
element with the first few words of this kitty ipsum text
: Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.
"
+ "Replace the text inside your p
element with the first few words of this kitty ipsum text: Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.
"
],
"tests": [
"assert.isTrue((/Kitty(\\s)+ipsum(\\s)+dolor/gi).test($(\"p\").text()), 'Your p
element should contain the first few words of the provided kitty ipsum text
.')"
@@ -260,7 +266,7 @@
"descriptionRu": [],
"nameEs": "Waypoint: Llena espacios con texto de relleno",
"descriptionEs": [
- "Cambia el texto en el elemento p
para usar las primeras palabras del texto Kitty Ipsum
.",
+ "Cambia el texto en el elemento p
para usar las primeras palabras del texto Kitty Ipsum
",
"Los desarrolladores web tradicionalmente usan Lorem Ipsum
como texto de relleno. Se llama texto Lorem Ipsum porque esas son las primeras dos palabras de una cita famosa de Cicerón de la Roma Antigua.",
"El texto Lorem Ipsum ha sido usado como texto de relleno en las imprentas desde el siglo 16, y esta tradición continúa en la web.",
"Bueno, 5 siglos es bastante. Ya que estamos construyendo una aplicación de fotos de gatos (CatPhotoApp), ¡usemos algo llamado Kitty Ipsum!",
@@ -281,9 +287,9 @@
"id": "bad87fed1348bd9aedf08833",
"title": "Delete HTML Elements",
"description": [
- "Delete your h1
element so we can simplify our view.",
"Our phone doesn't have much vertical space.",
- "Let's remove the unnecessary elements so we can start building our CatPhotoApp."
+ "Let's remove the unnecessary elements so we can start building our CatPhotoApp.",
+ "Delete your h1
element so we can simplify our view."
],
"tests": [
"assert(($(\"h1\").length == 0), 'Delete your h1
element.')",
@@ -324,10 +330,12 @@
"id": "bad87fee1348bd9aedf08803",
"title": "Change the Color of Text",
"description": [
- "Change your h2
element's style so that its text color is red.",
- "We can do this by changing the \"style\" of your h2
element.",
+ "Now let's change the color of some of our text.",
+ "We can do this by changing the style
of your h2
element.",
"The style that is responsible for the color of an element's text is the \"color\" style.",
- "Here's how you would set your h2
element's text color to blue: <h2 style=\"color: blue\">CatPhotoApp</h2>
."
+ "Here's how you would set your h2
element's text color to blue:",
+ "<h2 style=\"color: blue\">CatPhotoApp</h2>
",
+ "Change your h2
element's style so that its text color is red."
],
"tests": [
"assert($(\"h2\").css(\"color\") === \"rgb(255, 0, 0)\", 'Your h2
element should be red.')"
@@ -348,9 +356,9 @@
"nameEs": "Waypoint: Cambia el color del texto",
"descriptionEs": [
"Cambia el estilo del elemento h2
de manera que el color de su texto sea rojo.",
- "Podemos hacer esto por medio de cambiar el estilo
del elemento h2
.",
+ "Podemos hacer esto por medio de cambiar el estilo
del elemento h2
",
"El estilo responsable del color de texto de un elemento es el estilo \"color\".",
- "Así es como podrías volver el color de texto de tu elemento h2
en azul: <h2 style=\"color: blue\">CatPhotoApp</h2>
."
+ "Así es como podrías volver el color de texto de tu elemento h2
en azul: <h2 style=\"color: blue\">CatPhotoApp</h2>
"
],
"namePt": "",
"descriptionPt": [],
@@ -358,25 +366,31 @@
"descriptionDe": [
"Ändere den Style des h2
Elements, damit die Textfarbe Rot ist.",
"Wir können das bewerkstelligen, indem wir den \"style\" des h2
Elements ändern.",
- "So könntest du die Textfarbe des h2
Elements in Blau ändern: <h2 style=\"color: blue\">CatPhotoApp</h2>
."
+ "So könntest du die Textfarbe des h2
Elements in Blau ändern: <h2 style=\"color: blue\">CatPhotoApp</h2>
"
]
},
{
"id": "bad87fee1348bd9aedf08805",
"title": "Use CSS Selectors to Style Elements",
"description": [
- "Delete your h2
element's style attribute and instead create a CSS style
element. Add the necessary CSS to turn all h2
elements blue.",
"With CSS, there are hundreds of CSS properties
that you can use to change the way an element looks on your page.",
- "When you entered <h2 style=\"color: red\">CatPhotoApp</h2>
, you were giving that individual h2
element an inline style
.",
- "That's one way to add style to an element, but a better way is by using CSS
, which stands for Cascading Style Sheets
.",
- "At the top of your code, create a style
element like this: <style></style>
.",
- "Inside that style element, you can create a CSS selector
for all h2
elements. For example, if you wanted all h2
elements to be red, your style element would look like this: <style>h2 {color: red;}</style>
.",
- "Note that it's important to have both opening and closing curly braces ({
and }
) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of your element's styles."
+ "When you entered <h2 style=\"color: red\">CatPhotoApp</h2>
, you were giving that individual h2
element an inline style
",
+ "That's one way to add style to an element, but a better way is by using CSS
, which stands for Cascading Style Sheets
",
+ "At the top of your code, create a style
element like this:",
+ "<style>
",
+ "</style>
",
+ "Inside that style element, you can create a CSS selector
for all h2
elements. For example, if you wanted all h2
elements to be red, your style element would look like this:",
+ "<style>
",
+ " h2 {color: red;}
",
+ "</style>
",
+ "Note that it's important to have both opening and closing curly braces ({
and }
) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of your element's styles.",
+ "Delete your h2
element's style attribute and instead create a CSS style
element. Add the necessary CSS to turn all h2
elements blue."
],
"tests": [
"assert(!$(\"h2\").attr(\"style\"), 'Remove the style attribute from your h2
element.')",
"assert($(\"style\") && $(\"style\").length > 1, 'Create a style
element.')",
"assert($(\"h2\").css(\"color\") === \"rgb(0, 0, 255)\", 'Your h2
element should be blue.')",
+ "assert(editor.match(/h2\\s*\\{\\s*color:\\s*blue;\\s*\\}/g), 'Ensure that your stylesheet h2
declaration is valid with a semicolon and closing brace')",
"assert(editor.match(/<\\/style>/g) && editor.match(/<\\/style>/g).length === (editor.match(/"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "nameCn": "",
- "descriptionCn": [],
- "nameFr": "",
- "descriptionFr": [],
- "nameRu": "",
- "descriptionRu": [],
- "nameEs": "",
- "descriptionEs": [],
- "namePt": "",
- "descriptionPt": [],
- "nameDe": "",
- "descriptionDe": []
}
]
}
diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json
index 248382e6f3..9ae783a1a5 100644
--- a/seed/challenges/intermediate-bonfires.json
+++ b/seed/challenges/intermediate-bonfires.json
@@ -30,6 +30,9 @@
"Math.min()",
"Array.reduce()"
],
+ "solutions": [
+ "function sumAll(arr) {\n var sum = 0;\n arr.sort(function(a,b) {return a-b;});\n for (var i = arr[0]; i <= arr[1]; i++) {\n sum += i; \n }\n return sum;\n}\n\nsumAll([1, 4]);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -67,8 +70,7 @@
"assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'message: [1, 2, 3, 5], [1, 2, 3, 4, 5]
should return [4]
.');",
"assert.includeMembers(diff([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], 'message: [1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
should return [\"piglet\", 4]
.');",
"assert.deepEqual(diff([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], 'message: [], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
should return [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
.');",
- "assert.includeMembers(diff([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]), [1, \"calf\", 3, \"piglet\", 7, \"filly\"], 'message: [1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
should return [1, \"calf\", 3, \"piglet\", 7, \"filly\"]
.');",
- "assert.deepEqual(diff([1, 2, 3, 3], [1]), [2, 3], 'message: [1, 2, 3, 3], [1]
should return [2, 3]
.');"
+ "assert.includeMembers(diff([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]), [1, \"calf\", 3, \"piglet\", 7, \"filly\"], 'message: [1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
should return [1, \"calf\", 3, \"piglet\", 7, \"filly\"]
.');"
],
"MDNlinks": [
"Comparison Operators",
@@ -77,6 +79,9 @@
"Array.indexOf()",
"Array.concat()"
],
+ "solutions": [
+ "function diff(arr1, arr2) {\n var newArr = [];\n var h1 = Object.create(null);\n arr1.forEach(function(e) {\n h1[e] = e;\n });\n \n var h2 = Object.create(null);\n arr2.forEach(function(e) {\n h2[e] = e;\n });\n \n Object.keys(h1).forEach(function(e) {\n if (!(e in h2)) newArr.push(h1[e]);\n });\n Object.keys(h2).forEach(function(e) {\n if (!(e in h1)) newArr.push(h2[e]);\n });\n // Same, same; but different.\n return newArr;\n}\n\ndiff([1, 2, 3, 5], [1, 2, 3, 4, 5]);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -94,11 +99,25 @@
"id": "a7f4d8f2483413a6ce226cac",
"title": "Roman Numeral Converter",
"tests": [
- "assert.deepEqual(convert(12), \"XII\", 'message: convert(12)
should return \"XII\".');",
"assert.deepEqual(convert(5), \"V\", 'message: convert(5)
should return \"V\".');",
"assert.deepEqual(convert(9), \"IX\", 'message: convert(9)
should return \"IX\".');",
+ "assert.deepEqual(convert(12), \"XII\", 'message: convert(12)
should return \"XII\".');",
+ "assert.deepEqual(convert(16), \"XVI\", 'message: convert(16)
should return \"XVI\".');",
"assert.deepEqual(convert(29), \"XXIX\", 'message: convert(29)
should return \"XXIX\".');",
- "assert.deepEqual(convert(16), \"XVI\", 'message: convert(16)
should return \"XVI\".');"
+ "assert.deepEqual(convert(44), \"XLIV\", 'message: convert(44)
should return \"XLIV\".');",
+ "assert.deepEqual(convert(45), \"XLV\", 'convert(45)
should return \"XLV\"');",
+ "assert.deepEqual(convert(68), \"LXVIII\", 'convert(68)
should return \"LXVIII\"');",
+ "assert.deepEqual(convert(83), \"LXXXIII\", 'convert(83)
should return \"LXXXIII\"');",
+ "assert.deepEqual(convert(97), \"XCVII\", 'convert(97)
should return \"XCVII\"');",
+ "assert.deepEqual(convert(99), \"XCIX\", 'convert(99)
should return \"XCIX\"');",
+ "assert.deepEqual(convert(500), \"D\", 'convert(500)
should return \"D\"');",
+ "assert.deepEqual(convert(501), \"DI\", 'convert(501)
should return \"DI\"');",
+ "assert.deepEqual(convert(649), \"DCXLIX\", 'convert(649)
should return \"DCXLIX\"');",
+ "assert.deepEqual(convert(798), \"DCCXCVIII\", 'convert(798)
should return \"DCCXCVIII\"');",
+ "assert.deepEqual(convert(891), \"DCCCXCI\", 'convert(891)
should return \"DCCCXCI\"');",
+ "assert.deepEqual(convert(1000), \"M\", 'convert(1000)
should return \"M\"');",
+ "assert.deepEqual(convert(1004), \"MIV\", 'convert(1004)
should return \"MIV\"');",
+ "assert.deepEqual(convert(1006), \"MVI\", 'convert(1006)
should return \"MVI\"');"
],
"description": [
"Convert the given number into a roman numeral.",
@@ -118,6 +137,9 @@
"Array.indexOf()",
"Array.join()"
],
+ "solutions": [
+ "function convert(num) {\n var ref = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]];\n var res = [];\n ref.forEach(function(p) {\n while (num >= p[1]) {\n res.push(p[0]);\n num -= p[1];\n }\n });\n return res.join('');\n}\n\nconvert(36);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -149,7 +171,7 @@
"where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" });"
],
"tests": [
- "assert.deepEqual(where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'message: where()
should return an array of objects.');",
+ "assert.deepEqual(where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'message: where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" })
should return [{ first: \"Tybalt\", last: \"Capulet\" }]
.');",
"assert.deepEqual(where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 }), [{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], 'message: where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 })
should return [{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }]
.');",
"assert.deepEqual(where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 }), [{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], 'message: where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 })
should return [{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }]
.');"
],
@@ -158,6 +180,9 @@
"Object.hasOwnProperty()",
"Object.keys()"
],
+ "solutions": [
+ "function where(collection, source) {\n var arr = [];\n var keys = Object.keys(source);\n collection.forEach(function(e) {\n if(keys.every(function(key) {return e[key] === source[key];})) {\n arr.push(e); \n }\n });\n return arr;\n}\n\nwhere([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -177,7 +202,7 @@
"tests": [
"assert.deepEqual(myReplace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'message: myReplace(\"Let us go to the store\", \"store\", \"mall\")
should return \"Let us go to the mall\".');",
"assert.deepEqual(myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'message: myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")
should return \"He is Sitting on the couch\".');",
- "assert.deepEqual(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'message: myReplace(\"This has a spellngi error\", \"spellingi\", \"spelling\")
should return \"This has a spelling error\".');",
+ "assert.deepEqual(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'message: myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\")
should return \"This has a spelling error\".');",
"assert.deepEqual(myReplace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'message: myReplace(\"His name is Tom\", \"Tom\", \"john\")
should return \"His name is John\".');",
"assert.deepEqual(myReplace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\"), \"Let us get back to more Bonfires\", 'message: myReplace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")
should return \"Let us get back to more Bonfires\".');"
],
@@ -201,6 +226,9 @@
"String.replace()",
"Array.join()"
],
+ "solutions": [
+ "function replace(str, before, after) {\n if (before.charAt(0) === before.charAt(0).toUpperCase()) {\n after = after.charAt(0).toUpperCase() + after.substring(1);\n } else {\n after = after.charAt(0).toLowerCase() + after.substring(1);\n }\n return str.replace(before, after);\n}\n\nreplace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -244,6 +272,9 @@
"String.substr()",
"String.split()"
],
+ "solutions": [
+ "function translate(str) {\n if (isVowel(str.charAt(0))) return str + \"way\";\n var front = [];\n str = str.split('');\n while (str.length && !isVowel(str[0])) {\n front.push(str.shift());\n }\n return [].concat(str, front).join('') + 'ay';\n}\n\nfunction isVowel(c) {\n return ['a', 'e', 'i', 'o', 'u'].indexOf(c.toLowerCase()) !== -1;\n}\n\ntranslate(\"consonant\");\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -284,6 +315,9 @@
"Array.push()",
"String.split()"
],
+ "solutions": [
+ "var lookup = Object.create(null);\nlookup.A = 'T';\nlookup.T = 'A';\nlookup.C = 'G';\nlookup.G = 'C';\n\nfunction pair(str) {\n return str.split('').map(function(p) {return [p, lookup[p]];});\n}\n\npair(\"GCG\");\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -322,6 +356,9 @@
"String.charCodeAt()",
"String.fromCharCode()"
],
+ "solutions": [
+ "function fearNotLetter(str) {\n var s = str.split('').map(function(c) {return c.charCodeAt(0);});\n for (var i = 1; i < s.length; i++) {\n if (s[i]-1 != s[i-1]) {\n return String.fromCharCode(s[i]-1);\n }\n }\n}\n\nfearNotLetter('abce');\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -364,6 +401,9 @@
"MDNlinks": [
"Boolean Objects"
],
+ "solutions": [
+ "function boo(bool) {\n // What is the new fad diet for ghost developers? The Boolean.\n return typeof(bool) === \"boolean\";\n}\n\nboo(null);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -404,6 +444,9 @@
"Arguments object",
"Array.reduce()"
],
+ "solutions": [
+ "function unite(arr1, arr2, arr3) {\n return [].slice.call(arguments).reduce(function(a, b) {\n return [].concat(a, b.filter(function(e) {return a.indexOf(e) === -1;}));\n }, []);\n}\n\nunite([1, 2, 3], [5, 2, 1, 4], [2, 1]);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -445,6 +488,9 @@
"RegExp",
"HTML Entities"
],
+ "solutions": [
+ "var MAP = { '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''};\n\nfunction convert(str) {\n return str.replace(/[&<>\"']/g, function(c) {\n return MAP[c];\n });\n}\n\nconvert('Dolce & Gabbana');\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -484,6 +530,9 @@
"RegExp",
"String.replace()"
],
+ "solutions": [
+ "function spinalCase(str) {\n // \"It's such a fine line between stupid, and clever.\"\n // --David St. Hubbins\n str = str.replace(/([a-z](?=[A-Z]))/g, '$1 ');\n return str.toLowerCase().replace(/\\ |\\_/g, '-');\n}\n\nspinalCase('This Is Spinal Tap');\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -524,6 +573,9 @@
"MDNlinks": [
"Remainder"
],
+ "solutions": [
+ "function sumFibs(num) {\n var a = 1; \n var b = 1;\n var s = 0;\n while (a <= num) {\n if (a % 2 !== 0) { \n s += a; \n }\n a = [b, b=b+a][0];\n }\n return s;\n}\n\nsumFibs(4);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -562,6 +614,9 @@
"For Loops",
"Array.push()"
],
+ "solutions": [
+ "function eratosthenesArray(n) {\n var primes = [];\n if (n > 2) {\n var half = n>>1;\n var sieve = Array(half);\n for (var i = 1, limit = Math.sqrt(n)>>1; i <= limit; i++) {\n if (!sieve[i]) {\n for (var step = 2*i+1, j = (step*step)>>1; j < half; j+=step) {\n sieve[j] = true;\n }\n }\n }\n primes.push(2);\n for (var p = 1; p < half; p++) {\n if (!sieve[p]) primes.push(2*p+1);\n }\n }\n return primes;\n}\n\nfunction sumPrimes(num) {\n return eratosthenesArray(num+1).reduce(function(a,b) {return a+b;}, 0);\n}\n\nsumPrimes(10);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -601,6 +656,9 @@
"MDNlinks": [
"Smallest Common Multiple"
],
+ "solutions": [
+ "function gcd(a, b) {\n while (b !== 0) {\n a = [b, b = a % b][0];\n }\n return a;\n}\n\nfunction lcm(a, b) {\n return (a * b) / gcd(a, b);\n}\n\nfunction smallestCommons(arr) {\n arr.sort(function(a,b) {return a-b;});\n var rng = [];\n for (var i = arr[0]; i <= arr[1]; i++) {\n rng.push(i);\n }\n return rng.reduce(lcm);\n}\n\n\nsmallestCommons([1,5]);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -634,7 +692,10 @@
"assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'message: find([1, 3, 5, 9], function(num) { return num % 2 === 0; })
should return undefined.');"
],
"MDNlinks": [
- "Array.some()"
+ "Array.filter()"
+ ],
+ "solutions": [
+ "function find(arr, func) {\n var num;\n arr.some(function(e) {\n if (func(e)) {\n num = e;\n return true;\n }\n });\n return num;\n}\n\nfind([1, 2, 3, 4], function(num){ return num % 2 === 0; });\n"
],
"type": "bonfire",
"challengeType": 5,
@@ -665,15 +726,18 @@
"drop([1, 2, 3], function(n) {return n < 3; });"
],
"tests": [
- "assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n>= 3;}), [3, 4], 'message: drop([1, 2, 3, 4], function(n) {return n>= 3;})
should return [3, 4]
.');",
+ "assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n>= 3;}), [3, 4], 'message: drop([1, 2, 3, 4], function(n) {return n >= 3;})
should return [3, 4]
.');",
"assert.deepEqual(drop([1, 2, 3], function(n) {return n > 0; }), [1, 2, 3], 'message: drop([1, 2, 3], function(n) {return n > 0; })
should return [1, 2, 3]
.');",
"assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n > 5;}), [], 'message: drop([1, 2, 3, 4], function(n) {return n > 5;})
should return []
.');",
- "assert.deepEqual(drop([1, 2, 3, 7, 4], function(n) {return n > 3}), [7, 4], 'message: drop([1, 2, 3, 7, 4], function(n) {return n>= 3})
should return [7, 4]
.');"
+ "assert.deepEqual(drop([1, 2, 3, 7, 4], function(n) {return n > 3}), [7, 4], 'message: drop([1, 2, 3, 7, 4], function(n) {return n > 3})
should return [7, 4]
.');"
],
"MDNlinks": [
"Arguments object",
"Array.shift()"
],
+ "solutions": [
+ "(function drop(arr, func) {\n // Drop them elements.\n while (arr.length && !func(arr[0])) {\n arr.shift();\n }\n return arr;\n}\n\ndrop([1, 2, 3], function(n) {return n < 3; });\n)"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -711,6 +775,9 @@
"MDNlinks": [
"Array.isArray()"
],
+ "solutions": [
+ "function steamroller(arr) {\n if (!Array.isArray(arr)) {\n return [arr];\n }\n var out = [];\n arr.forEach(function(e) {\n steamroller(e).forEach(function(v) {\n out.push(v);\n });\n });\n return out;\n}\n\nsteamroller([1, [2], [3, [[4]]]]);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -747,6 +814,9 @@
"String.charCodeAt()",
"String.fromCharCode()"
],
+ "solutions": [
+ "function binaryAgent(str) {\n return str.split(' ').map(function(s) { return parseInt(s, 2); }).map(function(b) { return String.fromCharCode(b);}).join('');\n}\n\nbinaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
@@ -764,14 +834,13 @@
"id": "a10d2431ad0c6a099a4b8b52",
"title": "Everything Be True",
"description": [
- "Check if the predicate (second argument) returns truthy (defined) for all elements of a collection (first argument).",
- "For this, check to see if the property defined in the second argument is present on every element of the collection.",
+ "Check if the predicate (second argument) is truthy on all elements of a collection (first argument).",
"Remember, you can access object properties through either dot notation or [] notation.",
"Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
],
"challengeSeed": [
"function every(collection, pre) {",
- " // Does everyone have one of these?",
+ " // Is everyone being true?",
" return pre;",
"}",
"",
@@ -779,12 +848,17 @@
],
"tests": [
"assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), true, 'message: every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")
should return true.');",
- "assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], {\"sex\": \"female\"}), false, 'message: every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], {\"sex\": \"female\"})
should return false.');",
- "assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"female\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], {\"sex\": \"female\"}), false, 'message: every([{\"user\": \"Tinky-Winky\", \"sex\": \"female\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], {\"sex\": \"female\"})
should return false.');"
+ "assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), false, 'message: every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")
should return false.');",
+ "assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 2}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\"), false, 'message: every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 3}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\")
should return false.');",
+ "assert.strictEqual(every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\"), false, 'message: every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\")
should return false');",
+ "assert.strictEqual(every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\"), true, 'message: every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\")
should return true');",
+ "assert.strictEqual(every([{\"single\": \"yes\"}], \"single\"), true, 'message: every([{\"single\": \"yes\"}], \"single\")
should return true');",
+ "assert.strictEqual(every([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\"), false, 'message: every([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\")
should return false');",
+ "assert.strictEqual(every([{\"single\": \"double\"}, {\"single\": undefined}], \"single\"), false, 'message: every([{\"single\": \"double\"}, {\"single\": undefined}], \"single\")
should return false');",
+ "assert.strictEqual(every([{\"single\": \"double\"}, {\"single\": NaN}], \"single\"), false, 'message: every([{\"single\": \"double\"}, {\"single\": NaN}], \"single\")
should return false');"
],
- "MDNlinks": [
- "Object.hasOwnProperty()",
- "Object.getOwnPropertyNames()"
+ "solutions": [
+ "function every(collection, pre) {\n // Does everyone have one of these?\n return collection.every(function(e) { return e[pre]; });\n}\n\nevery([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');\n"
],
"type": "bonfire",
"challengeType": 5,
@@ -829,6 +903,10 @@
"Closures",
"Arguments object"
],
+ "solutions": [
+ "function add() {\n if (arguments.length == 1) {\n var a = arguments[0];\n if (!isNumber(a)) return;\n return function(b) {\n if (!isNumber(b)) return;\n return a+b;\n };\n }\n if (![].slice.call(arguments).every(isNumber)) return;\n return arguments[0] + arguments[1];\n}\n \nfunction isNumber(obj) {\n return toString.call(obj) == '[object Number]';\n}\n\nadd(2,3);\n",
+ "function add() {\n var a = arguments[0];\n if (toString.call(a) !== '[object Number]') return; \n if (arguments.length === 1) {\n return function(b) {\n if (toString.call(b) !== '[object Number]') return;\n return a + b;\n };\n }\n var b = arguments[1];\n if (toString.call(b) !== '[object Number]') return; \n return a + arguments[1];\n}\n\nadd(2,3);\n"
+ ],
"type": "bonfire",
"challengeType": 5,
"nameCn": "",
diff --git a/seed/challenges/intermediate-ziplines.json b/seed/challenges/intermediate-ziplines.json
index fd3ea5b5e9..0d2afbcb5c 100644
--- a/seed/challenges/intermediate-ziplines.json
+++ b/seed/challenges/intermediate-ziplines.json
@@ -8,7 +8,7 @@
"title": "Show the Local Weather",
"challengeSeed": ["126415127"],
"description": [
- "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/AdventureBear/full/yNBJRj.",
+ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/FreeCodeCamp/pen/avqvgJ.",
"Rule #1: Don't look at the example project's code on CodePen. Figure it out for yourself.",
"Rule #2: You may use whichever libraries or APIs you need.",
"Rule #3: Reverse engineer the example project's functionality, and also feel free to personalize it.",
@@ -17,6 +17,7 @@
"Bonus User Story: As a user, I can see an icon depending on the weather.",
"Bonus User Story: As a user, I see a different background image (e.g. snowy mountain, hot desert) depending on the weather.",
"Bonus User Story: As a user, I can push a button to toggle between Fahrenheit and Celsius.",
+ "We recommend using the Open Weather API. This will require creating a free API key. Normally you want to avoid exposing API keys on CodePen, but we haven't been able to find a keyless API for weather.",
"Remember to use Read-Search-Ask if you get stuck.",
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project from fellow campers, click this button and paste in a link to your CodePen project. document ready function
, your code may run before your HTML is rendered, which would cause bugs."
],
"tests": [
- "assert(editor.match(/