From c4c90689505de61cdd0f7d971f177f9c968e295b Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 8 Sep 2015 22:52:32 -0700 Subject: [PATCH 01/63] start refactoring account view into show view --- server/boot/user.js | 22 +-------- server/views/account/account.jade | 70 ----------------------------- server/views/account/show.jade | 74 ++++++++++++++++++++++++++++++- server/views/partials/navbar.jade | 7 --- 4 files changed, 74 insertions(+), 99 deletions(-) diff --git a/server/boot/user.js b/server/boot/user.js index 33a80c5c62..f521404ced 100644 --- a/server/boot/user.js +++ b/server/boot/user.js @@ -68,7 +68,6 @@ module.exports = function(app) { router.post('/reset-password', postReset); router.get('/email-signup', getEmailSignup); router.get('/email-signin', getEmailSignin); - router.get('/account/api', getAccountAngular); router.post( '/account/delete', ifNoUser401, @@ -114,18 +113,7 @@ module.exports = function(app) { } function getAccount(req, res) { - if (!req.user) { - return res.redirect('/'); - } - res.render('account/account', { - title: 'Manage your Free Code Camp Account' - }); - } - - function getAccountAngular(req, res) { - res.json({ - user: req.user || {} - }); + return res.redirect('/' + user.username); } function returnUser(req, res, next) { @@ -143,14 +131,6 @@ module.exports = function(app) { }); return res.redirect('/'); } - if (!user.isGithubCool && !user.isMigrationGrandfathered) { - req.flash('errors', { - msg: ` - user ${ username } has not completed account signup - ` - }); - return res.redirect('/'); - } var cals = user .progressTimestamps diff --git a/server/views/account/account.jade b/server/views/account/account.jade index d4d00c46ce..0259b504f7 100644 --- a/server/views/account/account.jade +++ b/server/views/account/account.jade @@ -2,74 +2,4 @@ extends ../layout block content script. var challengeName = 'Account View' - .panel.panel-info - .panel-heading.text-center Manage your account here - .panel-body - .row - .col-xs-12 - if (!user.isGithubCool) - a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/link/github') - i.fa.fa-github - | Link my GitHub to unlock this profile - else - a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/link/github') - i.fa.fa-github - | Update my profile from GitHub - if (!user.twitter) - .col-xs-12 - a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/link/twitter') - i.fa.fa-twitter - | Add my Twitter to my profile - if (!user.facebook) - .col-xs-12 - a.btn.btn-lg.btn-block.btn-facebook.btn-link-social(href='/link/facebook') - i.fa.fa-facebook - | Add my Facebook to my profile - if (!user.linkedin) - .col-xs-12 - a.btn.btn-lg.btn-block.btn-linkedin.btn-link-social(href='/link/linkedin') - i.fa.fa-linkedin - | Add my LinkedIn to my profile - if (!user.google) - .col-xs-12 - a.btn.btn-lg.btn-block.btn-google-plus.btn-link-social(href='/link/google') - i.fa.fa-google-plus - | Add my Google+ to my profile - .big-spacer - .col-xs-12 - a.btn.btn-lg.btn-block.btn-warning.btn-link-social(href='/logout') - span.ion-android-exit - | Sign me out of Free Code Camp - .col-xs-12 - a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='mailto:team@freecodecamp.com') - span.ion-email - | Email us at team@freecodecamp.com - .col-xs-12 - a.btn.btn-lg.btn-block.btn-danger.btn-link-social.confirm-deletion - span.ion-trash-b - | Delete my Free Code Camp account - script. - $('.confirm-deletion').on("click", function() { - $('#modal-dialog').modal('show'); - }); - #modal-dialog.modal.animated.wobble - .modal-dialog - .modal-content - .modal-header - a.close(href='#', data-dismiss='modal', aria-hidden='true') × - h3 Are you really leaving us? - .modal-body - p Pro Tip: If you tweet feedback to  - a(href="https://twitter.com/intent/tweet?text=Hey%20@freecodecamp") @FreeCodeCamp - | , we'll act quickly on it! - .modal-footer - a.btn.btn-success.btn-block(href='#', data-dismiss='modal', aria-hidden='true') - span.ion-happy - | Nevermind, I'll stick around - br - form(action='/account/delete', method='POST') - input(type='hidden', name='_csrf', value=_csrf) - button.btn.btn-danger.btn-block(type='submit') - span.ion-trash-b - | Yes, delete my account diff --git a/server/views/account/show.jade b/server/views/account/show.jade index c559f84aa3..2b80bba9f2 100644 --- a/server/views/account/show.jade +++ b/server/views/account/show.jade @@ -3,11 +3,83 @@ block content script(src="/bower_components/cal-heatmap/cal-heatmap.min.js") script. var challengeName = 'Profile View'; + if (user && user.username === username) + .panel.panel-info + .panel-heading.text-center Manage your account + .panel-body + .row + .col-xs-12 + if (!user.isGithubCool) + a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/link/github') + i.fa.fa-github + | Link my GitHub to unlock this profile + else + a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/link/github') + i.fa.fa-github + | Update my profile from GitHub + if (!user.twitter) + .col-xs-12 + a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/link/twitter') + i.fa.fa-twitter + | Add my Twitter to my profile + if (!user.facebook) + .col-xs-12 + a.btn.btn-lg.btn-block.btn-facebook.btn-link-social(href='/link/facebook') + i.fa.fa-facebook + | Add my Facebook to my profile + if (!user.linkedin) + .col-xs-12 + a.btn.btn-lg.btn-block.btn-linkedin.btn-link-social(href='/link/linkedin') + i.fa.fa-linkedin + | Add my LinkedIn to my profile + if (!user.google) + .col-xs-12 + a.btn.btn-lg.btn-block.btn-google-plus.btn-link-social(href='/link/google') + i.fa.fa-google-plus + | Add my Google+ to my profile + .big-spacer + .col-xs-12 + a.btn.btn-lg.btn-block.btn-warning.btn-link-social(href='/logout') + span.ion-android-exit + | Sign me out of Free Code Camp + .col-xs-12 + a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='mailto:team@freecodecamp.com') + span.ion-email + | Email us at team@freecodecamp.com + .col-xs-12 + a.btn.btn-lg.btn-block.btn-danger.btn-link-social.confirm-deletion + span.ion-trash-b + | Delete my Free Code Camp account + script. + $('.confirm-deletion').on("click", function () { + $('#modal-dialog').modal('show'); + }); + #modal-dialog.modal.animated.wobble + .modal-dialog + .modal-content + .modal-header + a.close(href='#', data-dismiss='modal', aria-hidden='true') × + h3 You don't really want to delete your account, do you? + .modal-body + p This will really delete all your data, including all your progress, news stories and brownie points. + p We won't be able to recover any of it for you later, even if you change your mind. + p If there's something we could do better, send us an email instead and we'll do our best:   + a(href="mailto:team@freecodecamp.com") team@freecodecamp.com + | . + .modal-footer + a.btn.btn-success.btn-block(href='#', data-dismiss='modal', aria-hidden='true') + span.ion-happy + | Nevermind, I don't want to delete all my progress + .btn-spacer + form(action='/account/delete', method='POST') + input(type='hidden', name='_csrf', value=_csrf) + button.btn.btn-danger.btn-block(type='submit') + span.ion-trash-b + | I am 100% sure I want to delete all my progress .panel.panel-info .panel-heading.text-center h1 #{username}'s portfolio .panel-body - if (user && user.username === username) .row.text-center .col-xs-12.col-sm-10.col-sm-offset-1 a.btn.btn-big.btn-primary.btn-block(href="/account") Manage my account diff --git a/server/views/partials/navbar.jade b/server/views/partials/navbar.jade index d7861a224d..123f96391f 100644 --- a/server/views/partials/navbar.jade +++ b/server/views/partials/navbar.jade @@ -20,15 +20,8 @@ nav.navbar.navbar-default.navbar-fixed-top.nav-height li a.btn.signup-btn.signup-btn-nav(href='/login') Sign in else - if user.isGithubCool li a(href='/' + user.username) [ #{user.progressTimestamps.length} ] .hidden-xs.hidden-sm a(href='/' + user.username) img.profile-picture.float-right(src='#{user.picture}') - else - li - a(href='/account') [ #{user.progressTimestamps.length} ] - .hidden-xs.hidden-sm - a(href='/account') - img.profile-picture.float-right(src='#{user.picture}') From 93029f4e35fb53c749c67633ec7f45d88766a794 Mon Sep 17 00:00:00 2001 From: Aniruddh Agarwal Date: Fri, 18 Sep 2015 10:37:32 +0800 Subject: [PATCH 02/63] Refactored intermediate bonfires expect to assert --- seed/challenges/intermediate-bonfires.json | 98 +++++++++++----------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json index 88c331fd7c..fb1173440e 100644 --- a/seed/challenges/intermediate-bonfires.json +++ b/seed/challenges/intermediate-bonfires.json @@ -19,11 +19,11 @@ "sumAll([1, 4]);" ], "tests": [ - "expect(sumAll([1, 4])).to.be.a('Number');", - "expect(sumAll([1, 4])).to.equal(10);", - "expect(sumAll([4, 1])).to.equal(10);", - "expect(sumAll([5, 10])).to.equal(45);", - "expect(sumAll([10, 5])).to.equal(45);" + "assert(typeof(sumAll([1, 4])) === \"number\", 'The result should be a number');", + "assert.deepEqual(sumAll([1, 4]), 10, 'sumAll([1, 4]) should return 10');", + "assert.deepEqual(sumAll([4, 1]), 10, 'sumAll([4, 1]) should return 10');", + "assert.deepEqual(sumAll([5, 10]), 45, 'sumAll([5, 10]) should return 45');", + "assert.deepEqual(sumAll([10, 5]), 45, 'sumAll([10, 5]) should return 45');" ], "MDNlinks": [ "Math.max()", @@ -61,7 +61,7 @@ "diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);" ], "tests": [ - "expect(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])).to.be.a('array');", + "assert(typeof(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])) === \"object\", 'The result should be an array.');", "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'arrays with only one difference');", "assert.includeMembers(diff(['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['diorite', 'pink wool'], 'arrays with more than one difference');", "assert.deepEqual(diff(['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub']), [], 'arrays with no difference');", @@ -93,11 +93,11 @@ "id": "a7f4d8f2483413a6ce226cac", "title": "Roman Numeral Converter", "tests": [ - "expect(convert(12)).to.equal(\"XII\");", - "expect(convert(5)).to.equal(\"V\");", - "expect(convert(9)).to.equal(\"IX\");", - "expect(convert(29)).to.equal(\"XXIX\");", - "expect(convert(16)).to.equal(\"XVI\");" + "assert.deepEqual(convert(12), \"XII\", 'convert(12) should return \"XII\"');", + "assert.deepEqual(convert(5), \"V\", 'convert(5) should return \"V\"');", + "assert.deepEqual(convert(9), \"IX\", 'convert(9) should return \"IX\"');", + "assert.deepEqual(convert(29), \"XXIX\", 'convert(29) should return \"XXIX\"');", + "assert.deepEqual(convert(16), \"XVI\", 'convert(16) should return \"XVI\"');" ], "difficulty": "2.02", "description": [ @@ -177,11 +177,11 @@ "id": "a0b5010f579e69b815e7c5d6", "title": "Search and Replace", "tests": [ - "expect(replace(\"Let us go to the store\", \"store\", \"mall\")).to.equal(\"Let us go to the mall\");", - "expect(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")).to.equal(\"He is Sitting on the couch\");", - "expect(replace(\"This has a spellngi error\", \"spellngi\", \"spelling\")).to.equal(\"This has a spelling error\");", - "expect(replace(\"His name is Tom\", \"Tom\", \"john\")).to.equal(\"His name is John\");", - "expect(replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")).to.equal(\"Let us get back to more Bonfires\");" + "assert.deepEqual(replace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'replace(\"Let us go to the store\", \"store\", \"mall\") should return \"Let us go to the mall\"');", + "assert.deepEqual(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\") should return \"He is Sitting on the couch\"');", + "assert.deepEqual(replace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'replace(\"This has a spellngi error\", \"spellingi\", \"spelling\") should return \"This has a spelling error\"');", + "assert.deepEqual(replace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'replace(\"His name is Tom\", \"Tom\", \"john\") should return \"His name is John\"');", + "assert.deepEqual(replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\"), \"Let us get back to more Bonfires\", 'replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\") should return \"Let us get back to more Bonfires\"');" ], "difficulty": "2.035", "description": [ @@ -221,11 +221,11 @@ "id": "aa7697ea2477d1316795783b", "title": "Pig Latin", "tests": [ - "expect(translate(\"california\")).to.equal(\"aliforniacay\");", - "expect(translate(\"paragraphs\")).to.equal(\"aragraphspay\");", - "expect(translate(\"glove\")).to.equal(\"oveglay\");", - "expect(translate(\"algorithm\")).to.equal(\"algorithmway\");", - "expect(translate(\"eight\")).to.equal(\"eightway\");" + "assert.deepEqual(translate(\"california\"), \"aliforniacay\", 'translate(\"california\") should return \"aliforniacay\"');", + "assert.deepEqual(translate(\"paragraphs\"), \"aragraphspay\", 'translate(\"paragraphs\") should return \"aragraphspay\"');", + "assert.deepEqual(translate(\"glove\"), \"oveglay\", 'translate(\"glove\") should return \"oveglay\"');", + "assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'translate(\"algorithm\") should return \"algorithmway\"');", + "assert.deepEqual(translate(\"eight\"), \"eightway\", 'translate(\"eight\") should return \"eightway\"');" ], "difficulty": "2.04", "description": [ @@ -319,10 +319,10 @@ "fearNotLetter('abce');" ], "tests": [ - "expect(fearNotLetter('abce')).to.equal('d');", - "expect(fearNotLetter('bcd')).to.be.undefined;", - "expect(fearNotLetter('abcdefghjklmno')).to.equal('i');", - "expect(fearNotLetter('yz')).to.be.undefined;" + "assert.deepEqual(fearNotLetter(\"abce\"), \"d\", 'fearNotLetter(\"abce\") should return d');", + "assert.deepEqual(fearNotLetter(\"abcdefghjklmno\"), \"i\", 'fearNotLetter(\"abcdefghjklmno\") should return i');", + "assert.isUndefined(fearNotLetter(\"bcd\"), 'fearNotLetter(\"bcd\") should return undefined');", + "assert.isUndefined(fearNotLetter(\"yz\"), 'fearNotLetter(\"yz\") should return undefined');" ], "MDNlinks": [ "String.charCodeAt()", @@ -525,12 +525,12 @@ "sumFibs(4);" ], "tests": [ - "expect(sumFibs(1)).to.be.a('number');", - "expect(sumFibs(1000)).to.equal(1785);", - "expect(sumFibs(4000000)).to.equal(4613732);", - "expect(sumFibs(4)).to.equal(5);", - "expect(sumFibs(75024)).to.equal(60696);", - "expect(sumFibs(75025)).to.equal(135721);" + "assert.deepEqual(typeof(sumFibs(1)), \"number\", \"The result should be a number\");", + "assert.deepEqual(sumFibs(1000), 1785, 'sumFibs(1000) should return 1785');", + "assert.deepEqual(sumFibs(4000000), 4613732, 'sumFibs(4000000) should return 4613732');", + "assert.deepEqual(sumFibs(4), 5, 'sumFibs(4) should return 5');", + "assert.deepEqual(sumFibs(75024), 60696, 'sumFibs(75024) should return 60696');", + "assert.deepEqual(sumFibs(75025), 135721, 'sumFibs(75025) should return 135721');" ], "MDNlinks": [ "Remainder" @@ -566,9 +566,9 @@ "sumPrimes(10);" ], "tests": [ - "expect(sumPrimes(10)).to.be.a('number');", - "expect(sumPrimes(10)).to.equal(17);", - "expect(sumPrimes(977)).to.equal(73156);" + "assert.deepEqual(typeof(sumPrimes(10)), \"number\", \"The result should be a number\");", + "assert.deepEqual(sumPrimes(10), 17, 'sumPrimes(10) should return 17');", + "assert.deepEqual(sumPrimes(977), 73156, 'sumPrimes(977) should return 73156');" ], "MDNlinks": [ "For Loops", @@ -606,10 +606,10 @@ "smallestCommons([1,5]);" ], "tests": [ - "expect(smallestCommons([1,5])).to.be.a('number');", - "expect(smallestCommons([1,5])).to.equal(60);", - "expect(smallestCommons([5,1])).to.equal(60);", - "expect(smallestCommons([1,13])).to.equal(360360);" + "assert.deepEqual(typeof(smallestCommons([1, 5])), \"number\", \"The result should be a number\");", + "assert.deepEqual(smallestCommons([1, 5]), 60, 'smallestCommons([1, 5]) should return 60');", + "assert.deepEqual(smallestCommons([5, 1]), 60, 'smallestCommons([5, 1]) should return 60');", + "assert.deepEqual(smallestCommons([1, 13]), 360360, 'smallestCommons([1, 13]) should return 360360');" ], "MDNlinks": [ "Smallest Common Multiple" @@ -680,10 +680,10 @@ "drop([1, 2, 3], function(n) {return n < 3; });" ], "tests": [ - "expect(drop([1, 2, 3, 4], function(n) {return n >= 3; })).to.eqls([3, 4]);", - "expect(drop([1, 2, 3], function(n) {return n > 0; })).to.eqls([1, 2, 3]);", - "expect(drop([1, 2, 3, 4], function(n) {return n > 5; })).to.eqls([]);", - "expect(drop([1, 2, 3, 7, 4], function(n) { return n > 5; })).to.eqls([7, 4]);" + "assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n>= 3;}), [3, 4], '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], '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;}), [], '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], 'drop([1, 2, 3, 7, 4], function(n) {return n>= 3}) should return [7, 4]');" ], "MDNlinks": [ "Arguments object", @@ -757,8 +757,8 @@ "binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');" ], "tests": [ - "expect(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111')).to.equal(\"Aren't bonfires fun!?\");", - "expect(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001')).to.equal(\"I love FreeCodeCamp!\");" + "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", \"binaryAgent() should return Aren't bonfires fun!?\");", + "assert.deepEqual(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001'), \"I love FreeCodeCamp!\", 'binaryAgent() should return \"I love FreeCodeCamp!\"');" ], "MDNlinks": [ "String.charCodeAt()", @@ -838,11 +838,11 @@ "add(2,3);" ], "tests": [ - "expect(add(2, 3)).to.equal(5);", - "expect(add(2)(3)).to.equal(5);", - "expect(add('http://bit.ly/IqT6zt')).to.be.undefined;", - "expect(add(2, '3')).to.be.undefined;", - "expect(add(2)([3])).to.be.undefined;" + "assert.deepEqual(add(2, 3), 5, 'add(2, 3) should return 5');", + "assert.deepEqual(add(2)(3), 5, 'add(2)(3) should return 5');", + "assert.isUndefined(add(\"http://bit.ly/IqT6zt\"), 'add(\"http://bit.ly/IqT6zt\") should return undefined');", + "assert.isUndefined(add(2, \"3\"), 'add(2, \"3\") should return undefined');", + "assert.isUndefined(add(2)([3]), 'add(2)([3]) should return undefined');" ], "MDNlinks": [ "Global Function Object", From c62503bec4709fca1264cccad98873180eabb726 Mon Sep 17 00:00:00 2001 From: natac13 Date: Sun, 20 Sep 2015 11:21:57 -0400 Subject: [PATCH 03/63] fix unclear description slasher flick closes #3373 --- seed/challenges/basic-bonfires.json | 1 + 1 file changed, 1 insertion(+) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index cbcdbd1b83..b252db2dcd 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -453,6 +453,7 @@ "difficulty": "1.11", "description": [ "Return the remaining elements of an array after chopping off n elements from the head.", + "The head meaning the beginning of the array, or the zeroth index", "Remember to use Read-Search-Ask if you get stuck. Write your own code." ], "challengeSeed": [ From 6d8835ba5605fc476ddc8c920b9e9a8ed062b785 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Fri, 11 Sep 2015 10:58:24 -0700 Subject: [PATCH 04/63] return undefined if job is not found null values count as values when using default values so properties must be undefined when expecting default value to work --- common/app/routes/Jobs/flux/Actions.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/app/routes/Jobs/flux/Actions.js b/common/app/routes/Jobs/flux/Actions.js index 4df2ae42c6..ce31070736 100644 --- a/common/app/routes/Jobs/flux/Actions.js +++ b/common/app/routes/Jobs/flux/Actions.js @@ -56,7 +56,10 @@ export default Actions({ debug('job services experienced an issue', err); return jobActions.setError({ err }); } - jobActions.setJobs({ currentJob: job }); + if (job) { + jobActions.setJobs({ currentJob: job }); + } + jobActions.setJobs({}); }); }); return jobActions; From e579cbd778433421b6eee03fb2c12c5aab1785c8 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Sun, 13 Sep 2015 18:12:22 -0700 Subject: [PATCH 05/63] update to react-router 1.0.0-rc1 --- client/index.js | 19 +++++++++++++------ common/app/app-stream.jsx | 12 ++++++------ common/app/routes/Jobs/components/Jobs.jsx | 6 +++--- package.json | 3 ++- server/boot/a-react.js | 18 +++++++++--------- 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/client/index.js b/client/index.js index 79c5c541c1..a7818eece5 100644 --- a/client/index.js +++ b/client/index.js @@ -4,7 +4,7 @@ import React from 'react'; import Fetchr from 'fetchr'; import debugFactory from 'debug'; import { Router } from 'react-router'; -import { history } from 'react-router/lib/BrowserHistory'; +import { createLocation, createHistory } from 'history'; import { hydrate } from 'thundercats'; import { Render } from 'thundercats-react'; @@ -18,21 +18,28 @@ const services = new Fetchr({ }); Rx.config.longStackSupport = !!debug.enabled; - +const history = createHistory(); +const appLocation = createLocation( + location.pathname + location.search +); // returns an observable -app$(history) +app$({ history, location: appLocation }) .flatMap( ({ AppCat }) => { + // instantiate the cat with service const appCat = AppCat(null, services); + // hydrate the stores return hydrate(appCat, catState) .map(() => appCat); }, - ({ initialState }, appCat) => ({ initialState, appCat }) + // not using nextLocation at the moment but will be used for + // redirects in the future + ({ nextLocation, props }, appCat) => ({ nextLocation, props, appCat }) ) - .flatMap(({ initialState, appCat }) => { + .flatMap(({ props, appCat }) => { return Render( appCat, - React.createElement(Router, initialState), + React.createElement(Router, props), DOMContianer ); }) diff --git a/common/app/app-stream.jsx b/common/app/app-stream.jsx index 25ae2a6300..82d5568c09 100644 --- a/common/app/app-stream.jsx +++ b/common/app/app-stream.jsx @@ -1,17 +1,17 @@ import Rx from 'rx'; -import { Router } from 'react-router'; +import { match } from 'react-router'; import App from './App.jsx'; import AppCat from './Cat'; import childRoutes from './routes'; -const router$ = Rx.Observable.fromNodeCallback(Router.run, Router); +const route$ = Rx.Observable.fromNodeCallback(match); const routes = Object.assign({ components: App }, childRoutes); -export default function app$(location) { - return router$(routes, location) - .map(([initialState, transistion]) => { - return { initialState, transistion, AppCat }; +export default function app$({ location, history }) { + return route$({ routes, location, history }) + .map(([nextLocation, props]) => { + return { nextLocation, props, AppCat }; }); } diff --git a/common/app/routes/Jobs/components/Jobs.jsx b/common/app/routes/Jobs/components/Jobs.jsx index a6bc6a9a9f..6c40cf6b0c 100644 --- a/common/app/routes/Jobs/components/Jobs.jsx +++ b/common/app/routes/Jobs/components/Jobs.jsx @@ -1,6 +1,6 @@ import React, { cloneElement, PropTypes } from 'react'; import { contain } from 'thundercats-react'; -import { Navigation } from 'react-router'; +import { History } from 'react-router'; import { Button, Jumbotron, Row } from 'react-bootstrap'; import ListJobs from './List.jsx'; @@ -18,7 +18,7 @@ export default contain( jobActions: PropTypes.object, jobs: PropTypes.array }, - mixins: [Navigation], + mixins: [History], handleJobClick(id) { const { jobActions } = this.props; @@ -26,7 +26,7 @@ export default contain( return null; } jobActions.findJob(id); - this.transitionTo(`/jobs/${id}`); + this.history.pushState(null, `/jobs/${id}`); }, renderList(handleJobClick, jobs) { diff --git a/package.json b/package.json index 901b54ea3a..4b25530278 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "gulp-webpack": "^1.5.0", "helmet": "~0.9.0", "helmet-csp": "^0.2.3", + "history": "^1.9.0", "jade": "~1.8.0", "json-loader": "^0.5.2", "less": "~1.7.5", @@ -89,7 +90,7 @@ "react": "^0.13.3", "react-bootstrap": "~0.23.7", "react-motion": "~0.1.0", - "react-router": "https://github.com/BerkeleyTrue/react-router#freecodecamp", + "react-router": "^1.0.0-rc1", "react-vimeo": "^0.0.3", "request": "~2.53.0", "rev-del": "^1.0.5", diff --git a/server/boot/a-react.js b/server/boot/a-react.js index 6c0cd04819..9b1f4926c9 100644 --- a/server/boot/a-react.js +++ b/server/boot/a-react.js @@ -1,7 +1,7 @@ import React from 'react'; -import Router from 'react-router'; +import { RoutingContext } from 'react-router'; import Fetchr from 'fetchr'; -import Location from 'react-router/lib/Location'; +import { createLocation } from 'history'; import debugFactory from 'debug'; import { app$ } from '../../common/app'; import { RenderToString } from 'thundercats-react'; @@ -30,25 +30,25 @@ export default function reactSubRouter(app) { function serveReactApp(req, res, next) { const services = new Fetchr({ req }); - const location = new Location(req.path, req.query); + const location = createLocation(req.path); // returns a router wrapped app - app$(location) + app$({ location }) // if react-router does not find a route send down the chain - .filter(function({ initialState }) { - if (!initialState) { + .filter(function({ props}) { + if (!props) { debug('react tried to find %s but got 404', location.pathname); return next(); } - return !!initialState; + return !!props; }) - .flatMap(function({ initialState, AppCat }) { + .flatMap(function({ props, AppCat }) { // call thundercats renderToString // prefetches data and sets up it up for current state debug('rendering to string'); return RenderToString( AppCat(null, services), - React.createElement(Router, initialState) + React.createElement(RoutingContext, props) ); }) // makes sure we only get one onNext and closes subscription From a34bcc2266cd33c6afbea1a224c1d6f999cba6a0 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Sun, 13 Sep 2015 22:14:49 -0700 Subject: [PATCH 06/63] fix (hack) override history object with original --- client/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/index.js b/client/index.js index a7818eece5..44bdb0a82c 100644 --- a/client/index.js +++ b/client/index.js @@ -37,6 +37,7 @@ app$({ history, location: appLocation }) ({ nextLocation, props }, appCat) => ({ nextLocation, props, appCat }) ) .flatMap(({ props, appCat }) => { + props.history = history; return Render( appCat, React.createElement(Router, props), From fe144f7297deafbb88ea181a1db7590457d2f559 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 14 Sep 2015 12:12:31 -0700 Subject: [PATCH 07/63] add highlighting to jobs --- common/app/routes/Jobs/components/List.jsx | 2 ++ common/app/routes/index.js | 12 ++++-------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/common/app/routes/Jobs/components/List.jsx b/common/app/routes/Jobs/components/List.jsx index ec8325a98b..2457bcb7f0 100644 --- a/common/app/routes/Jobs/components/List.jsx +++ b/common/app/routes/Jobs/components/List.jsx @@ -22,6 +22,7 @@ export default React.createClass({ id, company, position, + isHighlighted, description, logo, city, @@ -44,6 +45,7 @@ export default React.createClass({ ); return ( { - cb(null, [ - Jobs, - Hikes - ]); - }, 0); - } + childRoutes: [ + Jobs, + Hikes + ] }; From 523af406417025dbbb42d0346bb728a1d7fdd3fc Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 14 Sep 2015 12:17:23 -0700 Subject: [PATCH 08/63] bump less remove old less middleware --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 4b25530278..16c58aae82 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,7 @@ "history": "^1.9.0", "jade": "~1.8.0", "json-loader": "^0.5.2", - "less": "~1.7.5", - "less-middleware": "~2.0.1", + "less": "~2.5.1", "lodash": "^3.9.3", "loopback": "https://github.com/FreeCodeCamp/loopback.git#fix/no-password", "loopback-boot": "2.8.2", From d8e8f3bb67982ffab614de6236695a6470b0eb3b Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 14 Sep 2015 13:06:27 -0700 Subject: [PATCH 09/63] add `create job` modal --- .../routes/Jobs/components/CreateJobModal.jsx | 33 +++++++++++++++++++ common/app/routes/Jobs/components/Jobs.jsx | 23 ++++++++++--- common/app/routes/Jobs/flux/Actions.js | 6 ++++ common/app/routes/Jobs/flux/Store.js | 12 +++++-- 4 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 common/app/routes/Jobs/components/CreateJobModal.jsx diff --git a/common/app/routes/Jobs/components/CreateJobModal.jsx b/common/app/routes/Jobs/components/CreateJobModal.jsx new file mode 100644 index 0000000000..d3e6d34581 --- /dev/null +++ b/common/app/routes/Jobs/components/CreateJobModal.jsx @@ -0,0 +1,33 @@ +import React, { PropTypes } from 'react'; +import { Button, Modal } from 'react-bootstrap'; + +export default React.createClass({ + displayName: 'CreateJobsModal', + propTypes: { + onHide: PropTypes.func, + showModal: PropTypes.bool + }, + + render() { + const { + showModal, + onHide + } = this.props; + + return ( + + +

Welcome to Free Code Camp's board

+

We post jobs specifically target to our junior developers.

+ +
+
+ ); + } +}); diff --git a/common/app/routes/Jobs/components/Jobs.jsx b/common/app/routes/Jobs/components/Jobs.jsx index 6c40cf6b0c..a4d8354b3f 100644 --- a/common/app/routes/Jobs/components/Jobs.jsx +++ b/common/app/routes/Jobs/components/Jobs.jsx @@ -2,6 +2,8 @@ import React, { cloneElement, PropTypes } from 'react'; import { contain } from 'thundercats-react'; import { History } from 'react-router'; import { Button, Jumbotron, Row } from 'react-bootstrap'; + +import CreateJobModal from './CreateJobModal.jsx'; import ListJobs from './List.jsx'; export default contain( @@ -13,12 +15,14 @@ export default contain( React.createClass({ displayName: 'Jobs', + mixins: [History], + propTypes: { children: PropTypes.element, jobActions: PropTypes.object, - jobs: PropTypes.array + jobs: PropTypes.array, + showModal: PropTypes.bool }, - mixins: [History], handleJobClick(id) { const { jobActions } = this.props; @@ -48,7 +52,12 @@ export default contain( }, render() { - const { children, jobs } = this.props; + const { + children, + jobs, + showModal, + jobActions + } = this.props; return (
@@ -62,7 +71,8 @@ export default contain(

@@ -70,7 +80,10 @@ export default contain( { this.renderChild(children, jobs) || this.renderList(this.handleJobClick, jobs) } - + +
); } diff --git a/common/app/routes/Jobs/flux/Actions.js b/common/app/routes/Jobs/flux/Actions.js index ce31070736..40c78025d0 100644 --- a/common/app/routes/Jobs/flux/Actions.js +++ b/common/app/routes/Jobs/flux/Actions.js @@ -31,6 +31,12 @@ export default Actions({ getJob: null, getJobs(params) { return { params }; + }, + openModal() { + return { showModal: true }; + }, + closeModal() { + return { showModal: false }; } }) .refs({ displayName: 'JobActions' }) diff --git a/common/app/routes/Jobs/flux/Store.js b/common/app/routes/Jobs/flux/Store.js index 2fdfa50207..abe3eb61cc 100644 --- a/common/app/routes/Jobs/flux/Store.js +++ b/common/app/routes/Jobs/flux/Store.js @@ -6,12 +6,20 @@ const { transformer } = Store; -export default Store() +export default Store({ showModal: false }) .refs({ displayName: 'JobsStore' }) .init(({ instance: jobsStore, args: [cat] }) => { - const { setJobs, findJob, setError } = cat.getActions('JobActions'); + const { + setJobs, + findJob, + setError, + openModal, + closeModal + } = cat.getActions('JobActions'); const register = createRegistrar(jobsStore); register(setter(setJobs)); register(transformer(findJob)); register(setter(setError)); + register(setter(openModal)); + register(setter(closeModal)); }); From d3f2d603df7d2f36780624da2eb4f3e70e2730ca Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 14 Sep 2015 17:31:24 -0700 Subject: [PATCH 10/63] fix nodemon should ignore seed files --- gulpfile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/gulpfile.js b/gulpfile.js index afe9b421f5..fd5fdda38d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -49,6 +49,7 @@ var paths = { '!public/js/bundle*', 'node_modules/', 'client/', + 'seed', 'server/manifests/*.json', 'server/rev-manifest.json' ], From 41933a83604a4ebb0bcbca577b68e4cc378fe227 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 14 Sep 2015 17:31:48 -0700 Subject: [PATCH 11/63] initial job form and job form nav --- .../routes/Jobs/components/CreateJobModal.jsx | 11 +++- common/app/routes/Jobs/components/NewJob.jsx | 56 +++++++++++++++++++ common/app/routes/Jobs/index.js | 4 ++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 common/app/routes/Jobs/components/NewJob.jsx diff --git a/common/app/routes/Jobs/components/CreateJobModal.jsx b/common/app/routes/Jobs/components/CreateJobModal.jsx index d3e6d34581..8a02400293 100644 --- a/common/app/routes/Jobs/components/CreateJobModal.jsx +++ b/common/app/routes/Jobs/components/CreateJobModal.jsx @@ -1,13 +1,21 @@ import React, { PropTypes } from 'react'; +import { History } from 'react-router'; import { Button, Modal } from 'react-bootstrap'; export default React.createClass({ displayName: 'CreateJobsModal', + propTypes: { onHide: PropTypes.func, showModal: PropTypes.bool }, + mixins: [History], + + goToNewJob() { + this.history.pushState(null, '/jobs/new'); + }, + render() { const { showModal, @@ -23,7 +31,8 @@ export default React.createClass({

We post jobs specifically target to our junior developers.

diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx new file mode 100644 index 0000000000..a412ff6d7d --- /dev/null +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -0,0 +1,56 @@ +import React, { PropTypes } from 'react'; +import { contain } from 'thundercats-react'; +import { + Col, + Input, + Row, + Well +} from 'react-bootstrap'; + +export default contain({ + actions: 'jobActions', + store: 'jobsStore', + map({ form = {} }) { + return form; + } + }, + React.createClass({ + displayName: 'NewJob', + propTypes: { + jobActions: PropTypes.object + }, + render() { + return ( +
+ + + +

Create You Job Post

+
+ + + +
+
+ +
+
+ ); + } + }) +); diff --git a/common/app/routes/Jobs/index.js b/common/app/routes/Jobs/index.js index ac6b07f866..3564332d32 100644 --- a/common/app/routes/Jobs/index.js +++ b/common/app/routes/Jobs/index.js @@ -1,4 +1,5 @@ import Jobs from './components/Jobs.jsx'; +import NewJob from './components/NewJob.jsx'; import Show from './components/Show.jsx'; /* @@ -11,6 +12,9 @@ export default { childRoutes: [{ path: '/jobs', component: Jobs + }, { + path: 'jobs/new', + component: NewJob }, { path: 'jobs/:id', component: Show From 65572d65c8a234d388b059811dda32ca94a003db Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 21 Sep 2015 20:38:09 -0700 Subject: [PATCH 12/63] close modal before transition to job form --- common/app/routes/Jobs/components/CreateJobModal.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/app/routes/Jobs/components/CreateJobModal.jsx b/common/app/routes/Jobs/components/CreateJobModal.jsx index 8a02400293..446ed957d6 100644 --- a/common/app/routes/Jobs/components/CreateJobModal.jsx +++ b/common/app/routes/Jobs/components/CreateJobModal.jsx @@ -12,7 +12,8 @@ export default React.createClass({ mixins: [History], - goToNewJob() { + goToNewJob(onHide) { + onHide(); this.history.pushState(null, '/jobs/new'); }, @@ -32,7 +33,7 @@ export default React.createClass({ From 10b3b8d75854187741fa008e1b5830377bd35bcf Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 21 Sep 2015 22:41:12 -0700 Subject: [PATCH 13/63] add validation to one input not sure this is the best approach --- common/app/routes/Jobs/components/NewJob.jsx | 55 +++++++++++++++++++- common/app/routes/Jobs/flux/Actions.js | 35 ++++++++++++- common/app/routes/Jobs/flux/Store.js | 7 ++- 3 files changed, 92 insertions(+), 5 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index a412ff6d7d..61bf46530a 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -7,19 +7,57 @@ import { Well } from 'react-bootstrap'; +const defaults = { + 'string': { + value: '', + valid: false, + pristine: true + } +}; + +function defaultValue(type) { + return defaults[type]; +} + +function validatePosition(value) { + if (!value && typeof value !== 'string') { + return false; + } + return true; +} + export default contain({ actions: 'jobActions', store: 'jobsStore', map({ form = {} }) { - return form; + const { + position = defaultValue('string'), + location = defaultValue('string'), + description = defaultValue('string') + } = form; + return { + position, + location, + description + }; } }, React.createClass({ displayName: 'NewJob', + propTypes: { - jobActions: PropTypes.object + jobActions: PropTypes.object, + position: PropTypes.object, + location: PropTypes.object, + description: PropTypes.object }, + render() { + const { + jobActions, + position + } = this.props; + return (
@@ -28,10 +66,23 @@ export default contain({

Create You Job Post

{ + jobActions.handleForm({ + name: 'position', + value, + validator: validatePosition + }); + }} placeholder='Position' type='text' + value={ position.value } wrapperClassName='col-xs-10' /> {} }) { + if (!name) { + // operation noop + return { replace: null }; + } + if (!validator(value)) { + return { + transform(oldState) { + const { oldForm } = oldState; + const newState = assign({}, oldState); + newState.form = assign( + {}, + oldForm, + { [name]: { value, valid: false, pristine: false }} + ); + return newState; + } + }; + } + return { + transform(oldState) { + const { oldForm } = oldState; + const newState = assign({}, oldState); + newState.form = assign( + {}, + oldForm, + { [name]: { value, valid: true, pristine: false }} + ); + return newState; + } + }; } }) .refs({ displayName: 'JobActions' }) diff --git a/common/app/routes/Jobs/flux/Store.js b/common/app/routes/Jobs/flux/Store.js index abe3eb61cc..a73235f1aa 100644 --- a/common/app/routes/Jobs/flux/Store.js +++ b/common/app/routes/Jobs/flux/Store.js @@ -14,12 +14,15 @@ export default Store({ showModal: false }) findJob, setError, openModal, - closeModal + closeModal, + handleForm } = cat.getActions('JobActions'); const register = createRegistrar(jobsStore); register(setter(setJobs)); - register(transformer(findJob)); register(setter(setError)); register(setter(openModal)); register(setter(closeModal)); + + register(transformer(findJob)); + register(handleForm); }); From 4d4aae6cf4e4d19630ccae9f9e2be4043377eaf7 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 22 Sep 2015 12:23:45 -0700 Subject: [PATCH 14/63] start refactoring advanced bonfires --- seed/challenges/advanced-bonfires.json | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index e7cd4030d4..2917dc893c 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -14,28 +14,28 @@ "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." ], "tests": [ - "assert.isBoolean(telephoneCheck(\"555-555-5555\"), 'should return a boolean.');", - "assert.deepEqual(telephoneCheck(\"1 555-555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1 (555) 555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"5555555555\"), true);", - "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"(555)555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1(555)555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1 555 555 5555\"), true);", - "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1 456 789 4444\"), true);", - "assert.deepEqual(telephoneCheck(\"123**&!!asdf#\"), false);", - "assert.deepEqual(telephoneCheck(\"55555555\"), false);", - "assert.deepEqual(telephoneCheck(\"(6505552368)\"), false);", - "assert.deepEqual(telephoneCheck(\"2 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"0 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"-1 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"2 757 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"10 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"27576227382\"), false);", - "assert.deepEqual(telephoneCheck(\"(275)76227382\"), false);", - "assert.deepEqual(telephoneCheck(\"2(757)6227382\"), false);", - "assert.deepEqual(telephoneCheck(\"2(757)622-7382\"), false);" + "assert.isBoolean(telephoneCheck(\"555-555-5555\") === 'should return a boolean.');", + "assert(telephoneCheck(\"1 555-555-5555\") === true, '1 555-555-5555 should return true.');", + "assert(telephoneCheck(\"1 (555) 555-5555\") === true), '1 (555) 555-5555 should return true.';", + "assert(telephoneCheck(\"5555555555\") === true, '5555555555 should return true.');", + "assert(telephoneCheck(\"555-555-5555\") === true, '555-555-5555 should return true.');", + "assert(telephoneCheck(\"(555)555-5555\") === true, '(555)555-5555 should return true.');", + "assert(telephoneCheck(\"1(555)555-5555\") === true, '1(555)555-5555 should return true.');", + "assert(telephoneCheck(\"1 555 555 5555\") === true, '1 555 555 5555 should return true.');", + "assert(telephoneCheck(\"555-555-5555\") === true), '555-555-5555 should return true.';", + "assert(telephoneCheck(\"1 456 789 4444\") === true, '1 456 789 4444 should return true.');", + "assert(telephoneCheck(\"123**&!!asdf#\") === false, '123**&!!asdf# should return false.');", + "assert(telephoneCheck(\"55555555\") === false, '55555555 should return false.');", + "assert(telephoneCheck(\"(6505552368)\") === false, '(6505552368) should return false');", + "assert(telephoneCheck(\"2 (757) 622-7382\") === false, '2 (757) 622-7382 should return false.');", + "assert(telephoneCheck(\"0 (757) 622-7382\") === false, '0 (757) 622-7382 should return false.');", + "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, '-1 (757) 622-7382 should return false');", + "assert(telephoneCheck(\"2 757 622-7382\") === false, '2 757 622-7382 should return false.');", + "assert(telephoneCheck(\"10 (757) 622-7382\") === false, '10 (757) 622-7382 should return false.');", + "assert(telephoneCheck(\"27576227382\") === false, '27576227382 should return false.');", + "assert(telephoneCheck(\"(275)76227382\") === false, '(275)76227382 should return false.');", + "assert(telephoneCheck(\"2(757)6227382\") === false, '2(757)6227382 should return false.');", + "assert(telephoneCheck(\"2(757)622-7382\") === false, '2(757)622-7382 should return false.');" ], "challengeSeed": [ "function telephoneCheck(str) {", From 5258145ef601d607ef2f2a90e9f04b20a7b2bc8d Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Tue, 22 Sep 2015 13:56:55 -0700 Subject: [PATCH 15/63] add validation to all current inputs validation right now is simply validating that the value is indeed a string --- common/app/routes/Jobs/components/NewJob.jsx | 41 +++++++++++++++++--- common/app/routes/Jobs/flux/Actions.js | 8 ++-- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index 61bf46530a..b1b1ff30c3 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -19,7 +19,7 @@ function defaultValue(type) { return defaults[type]; } -function validatePosition(value) { +function validateString(value) { if (!value && typeof value !== 'string') { return false; } @@ -32,12 +32,12 @@ export default contain({ map({ form = {} }) { const { position = defaultValue('string'), - location = defaultValue('string'), + locale = defaultValue('string'), description = defaultValue('string') } = form; return { position, - location, + locale, description }; } @@ -48,14 +48,16 @@ export default contain({ propTypes: { jobActions: PropTypes.object, position: PropTypes.object, - location: PropTypes.object, + locale: PropTypes.object, description: PropTypes.object }, render() { const { jobActions, - position + position, + locale, + description } = this.props; return ( @@ -77,7 +79,7 @@ export default contain({ jobActions.handleForm({ name: 'position', value, - validator: validatePosition + validator: validateString }); }} placeholder='Position' @@ -85,16 +87,43 @@ export default contain({ value={ position.value } wrapperClassName='col-xs-10' /> { + jobActions.handleForm({ + name: 'locale', + value, + validator: validateString + }); + }} placeholder='Location' type='text' + value={ locale.value } wrapperClassName='col-xs-10' /> { + jobActions.handleForm({ + name: 'description', + value, + validator: validateString + }); + }} placeholder='Description' + rows='10' type='textarea' + value={ description.value } wrapperClassName='col-xs-10' /> diff --git a/common/app/routes/Jobs/flux/Actions.js b/common/app/routes/Jobs/flux/Actions.js index 664d04caf3..ccaab9c755 100644 --- a/common/app/routes/Jobs/flux/Actions.js +++ b/common/app/routes/Jobs/flux/Actions.js @@ -47,11 +47,11 @@ export default Actions({ if (!validator(value)) { return { transform(oldState) { - const { oldForm } = oldState; + const { form } = oldState; const newState = assign({}, oldState); newState.form = assign( {}, - oldForm, + form, { [name]: { value, valid: false, pristine: false }} ); return newState; @@ -60,11 +60,11 @@ export default Actions({ } return { transform(oldState) { - const { oldForm } = oldState; + const { form } = oldState; const newState = assign({}, oldState); newState.form = assign( {}, - oldForm, + form, { [name]: { value, valid: true, pristine: false }} ); return newState; From 98af05256a7c838461394cbd65c410a0b3cc176e Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Tue, 22 Sep 2015 16:10:12 -0700 Subject: [PATCH 16/63] switch to validator add email field --- common/app/routes/Jobs/components/NewJob.jsx | 64 +++++++++++--------- common/app/routes/Jobs/flux/Actions.js | 14 ++++- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index b1b1ff30c3..83f773e05d 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -6,6 +6,10 @@ import { Row, Well } from 'react-bootstrap'; +import { + isAscii, + isEmail +} from 'validator'; const defaults = { 'string': { @@ -19,13 +23,6 @@ function defaultValue(type) { return defaults[type]; } -function validateString(value) { - if (!value && typeof value !== 'string') { - return false; - } - return true; -} - export default contain({ actions: 'jobActions', store: 'jobsStore', @@ -33,12 +30,14 @@ export default contain({ const { position = defaultValue('string'), locale = defaultValue('string'), - description = defaultValue('string') + description = defaultValue('string'), + email = defaultValue('string') } = form; return { position, locale, - description + description, + email }; } }, @@ -49,7 +48,8 @@ export default contain({ jobActions: PropTypes.object, position: PropTypes.object, locale: PropTypes.object, - description: PropTypes.object + description: PropTypes.object, + email: PropTypes.object }, render() { @@ -57,7 +57,8 @@ export default contain({ jobActions, position, locale, - description + description, + email } = this.props; return ( @@ -65,21 +66,17 @@ export default contain({ -

Create You Job Post

+

Create Your Job Post

{ jobActions.handleForm({ name: 'position', value, - validator: validateString + validator: isAscii }); }} placeholder='Position' @@ -87,18 +84,14 @@ export default contain({ value={ position.value } wrapperClassName='col-xs-10' /> { jobActions.handleForm({ name: 'locale', value, - validator: validateString + validator: isAscii }); }} placeholder='Location' @@ -106,18 +99,14 @@ export default contain({ value={ locale.value } wrapperClassName='col-xs-10' /> { jobActions.handleForm({ name: 'description', value, - validator: validateString + validator: isAscii }); }} placeholder='Description' @@ -125,6 +114,21 @@ export default contain({ type='textarea' value={ description.value } wrapperClassName='col-xs-10' /> + { + jobActions.handleForm({ + name: 'email', + value, + validator: isEmail + }); + }} + placeholder='Email' + type='email' + value={ email.value } + wrapperClassName='col-xs-10' />
diff --git a/common/app/routes/Jobs/flux/Actions.js b/common/app/routes/Jobs/flux/Actions.js index ccaab9c755..5b284e4b8c 100644 --- a/common/app/routes/Jobs/flux/Actions.js +++ b/common/app/routes/Jobs/flux/Actions.js @@ -52,7 +52,12 @@ export default Actions({ newState.form = assign( {}, form, - { [name]: { value, valid: false, pristine: false }} + { [name]: { + value, + valid: false, + pristine: false, + bsStyle: value ? 'error' : null + }} ); return newState; } @@ -65,7 +70,12 @@ export default Actions({ newState.form = assign( {}, form, - { [name]: { value, valid: true, pristine: false }} + { [name]: { + value, + valid: true, + pristine: false, + bsStyle: value ? 'success' : null + }} ); return newState; } From 70b823ca63b7a3d377af7c0dca9800177020b5c4 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Tue, 22 Sep 2015 17:19:14 -0700 Subject: [PATCH 17/63] add phone number input change validation function scheme update validator --- common/app/routes/Jobs/components/NewJob.jsx | 168 +++++++++++-------- common/models/job.json | 1 + package.json | 2 +- 3 files changed, 103 insertions(+), 68 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index 83f773e05d..ae1e5eab51 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -8,7 +8,8 @@ import { } from 'react-bootstrap'; import { isAscii, - isEmail + isEmail, + isMobilePhone } from 'validator'; const defaults = { @@ -31,13 +32,15 @@ export default contain({ position = defaultValue('string'), locale = defaultValue('string'), description = defaultValue('string'), - email = defaultValue('string') + email = defaultValue('string'), + phone = defaultValue('string') } = form; return { position, locale, description, - email + email, + phone }; } }, @@ -49,17 +52,25 @@ export default contain({ position: PropTypes.object, locale: PropTypes.object, description: PropTypes.object, - email: PropTypes.object + email: PropTypes.object, + phone: PropTypes.object + }, + + handleChange(name, validator, { target: { value } }) { + const { jobActions: { handleForm } } = this.props; + handleForm({ name, value, validator }); }, render() { const { - jobActions, position, locale, description, - email + email, + phone } = this.props; + const labelClass = 'col-sm-offset-1 col-sm-2'; + const inputClass = 'col-sm-6'; return (
@@ -68,67 +79,90 @@ export default contain({

Create Your Job Post

- { - jobActions.handleForm({ - name: 'position', - value, - validator: isAscii - }); - }} - placeholder='Position' - type='text' - value={ position.value } - wrapperClassName='col-xs-10' /> - { - jobActions.handleForm({ - name: 'locale', - value, - validator: isAscii - }); - }} - placeholder='Location' - type='text' - value={ locale.value } - wrapperClassName='col-xs-10' /> - { - jobActions.handleForm({ - name: 'description', - value, - validator: isAscii - }); - }} - placeholder='Description' - rows='10' - type='textarea' - value={ description.value } - wrapperClassName='col-xs-10' /> - { - jobActions.handleForm({ - name: 'email', - value, - validator: isEmail - }); - }} - placeholder='Email' - type='email' - value={ email.value } - wrapperClassName='col-xs-10' /> + +
+

Job Information

+
+ { + this.handleChange( + 'position', + isAscii, + e + ); + }} + placeholder='Position' + type='text' + value={ position.value } + wrapperClassName={ inputClass } /> + { + this.handleChange( + 'locale', + isAscii, + e, + ); + }} + placeholder='Location' + type='text' + value={ locale.value } + wrapperClassName={ inputClass } /> + { + this.handleChange( + 'description', + isAscii, + e + ); + }} + placeholder='Description' + rows='10' + type='textarea' + value={ description.value } + wrapperClassName={ inputClass } /> +
+

Company Information

+
+ { + this.handleChange( + 'email', + isEmail, + e + ); + }} + placeholder='Email' + type='email' + value={ email.value } + wrapperClassName={ inputClass } /> + { + this.handleChange( + 'phone', + (data) => isMobilePhone(data, 'en-US'), + e + ); + }} + placeholder='555-123-1234' + type='tel' + value={ phone.value } + wrapperClassName={ inputClass } /> +
diff --git a/common/models/job.json b/common/models/job.json index a3392fee82..197f0619bf 100644 --- a/common/models/job.json +++ b/common/models/job.json @@ -1,6 +1,7 @@ { "name": "job", "base": "PersistedModel", + "strict": true, "idInjection": true, "trackChanges": false, "properties": { diff --git a/package.json b/package.json index 16c58aae82..df579eb2bc 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "thundercats-react": "^0.1.0", "twit": "~1.1.20", "uglify-js": "~2.4.15", - "validator": "~3.22.1", + "validator": "^3.22.1", "webpack": "^1.9.12", "yui": "~3.18.1" }, From 2ee22340503511d6671ac5c5c837f13f768a1e1f Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Tue, 22 Sep 2015 17:26:53 -0700 Subject: [PATCH 18/63] add company URL --- common/app/routes/Jobs/components/NewJob.jsx | 30 ++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index ae1e5eab51..fd5e2aafa9 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -9,7 +9,8 @@ import { import { isAscii, isEmail, - isMobilePhone + isMobilePhone, + isURL } from 'validator'; const defaults = { @@ -33,14 +34,16 @@ export default contain({ locale = defaultValue('string'), description = defaultValue('string'), email = defaultValue('string'), - phone = defaultValue('string') + phone = defaultValue('string'), + url = defaultValue('string') } = form; return { position, locale, description, email, - phone + phone, + url }; } }, @@ -53,7 +56,8 @@ export default contain({ locale: PropTypes.object, description: PropTypes.object, email: PropTypes.object, - phone: PropTypes.object + phone: PropTypes.object, + url: PropTypes.object }, handleChange(name, validator, { target: { value } }) { @@ -67,7 +71,8 @@ export default contain({ locale, description, email, - phone + phone, + url } = this.props; const labelClass = 'col-sm-offset-1 col-sm-2'; const inputClass = 'col-sm-6'; @@ -162,6 +167,21 @@ export default contain({ type='tel' value={ phone.value } wrapperClassName={ inputClass } /> + { + this.handleChange( + 'url', + (data) => isURL(data, { 'require_protocol': true }), + e + ); + }} + placeholder='http://freecatphotoapp.com' + type='url' + value={ url.value } + wrapperClassName={ inputClass } /> From 01a40500591539c75aaa5070354725efee5e0809 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Tue, 22 Sep 2015 18:25:09 -0700 Subject: [PATCH 19/63] Add higlight, company name --- common/app/routes/Jobs/components/NewJob.jsx | 86 ++++++++++++++++---- 1 file changed, 72 insertions(+), 14 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index fd5e2aafa9..f76113959c 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -18,24 +18,26 @@ const defaults = { value: '', valid: false, pristine: true + }, + bool: { + value: false } }; -function defaultValue(type) { - return defaults[type]; -} - export default contain({ actions: 'jobActions', store: 'jobsStore', map({ form = {} }) { const { - position = defaultValue('string'), - locale = defaultValue('string'), - description = defaultValue('string'), - email = defaultValue('string'), - phone = defaultValue('string'), - url = defaultValue('string') + position = defaults['string'], + locale = defaults['string'], + description = defaults['string'], + email = defaults['string'], + phone = defaults['string'], + url = defaults['string'], + logo = defaults['string'], + name = defaults['string'], + highlight = defaults['bool'] } = form; return { position, @@ -43,7 +45,10 @@ export default contain({ description, email, phone, - url + url, + logo, + name, + highlight }; } }, @@ -57,7 +62,10 @@ export default contain({ description: PropTypes.object, email: PropTypes.object, phone: PropTypes.object, - url: PropTypes.object + url: PropTypes.object, + logo: PropTypes.object, + name: PropTypes.object, + highlight: PropTypes.object }, handleChange(name, validator, { target: { value } }) { @@ -72,7 +80,10 @@ export default contain({ description, email, phone, - url + url, + logo, + name, + highlight } = this.props; const labelClass = 'col-sm-offset-1 col-sm-2'; const inputClass = 'col-sm-6'; @@ -134,9 +145,25 @@ export default contain({ type='textarea' value={ description.value } wrapperClassName={ inputClass } /> +

Company Information

+ { + this.handleChange( + 'name', + isAscii, + e, + ); + }} + placeholder='Foo, INC' + type='text' + value={ name.value } + wrapperClassName={ inputClass } /> { this.handleChange( @@ -182,6 +209,37 @@ export default contain({ type='url' value={ url.value } wrapperClassName={ inputClass } /> + { + this.handleChange( + 'logo', + (data) => isURL(data, { 'require_protocol': true }), + e + ); + }} + placeholder='http://freecatphotoapp.com/logo.png' + type='url' + value={ logo.value } + wrapperClassName={ inputClass } /> + +
+

Make it stand out

+
+ { + this.handleChange( + 'highlight', + () => { return true; }, + e + ); + }} + type='checkbox' + value={ highlight.value } /> From d8a6373b1ec46545d7f2435be64ecb4aeddf525a Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 23 Sep 2015 13:31:27 -0700 Subject: [PATCH 20/63] add submit button --- common/app/routes/Jobs/components/NewJob.jsx | 301 ++++++++++--------- 1 file changed, 157 insertions(+), 144 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index f76113959c..41d20db840 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -1,6 +1,7 @@ import React, { PropTypes } from 'react'; import { contain } from 'thundercats-react'; import { + Button, Col, Input, Row, @@ -95,151 +96,163 @@ export default contain({

Create Your Job Post

+ +
+

Job Information

+
+ { + this.handleChange( + 'position', + isAscii, + e + ); + }} + placeholder='Position' + type='text' + value={ position.value } + wrapperClassName={ inputClass } /> + { + this.handleChange( + 'locale', + isAscii, + e, + ); + }} + placeholder='Location' + type='text' + value={ locale.value } + wrapperClassName={ inputClass } /> + { + this.handleChange( + 'description', + isAscii, + e + ); + }} + placeholder='Description' + rows='10' + type='textarea' + value={ description.value } + wrapperClassName={ inputClass } /> + +
+

Company Information

+
+ { + this.handleChange( + 'name', + isAscii, + e, + ); + }} + placeholder='Foo, INC' + type='text' + value={ name.value } + wrapperClassName={ inputClass } /> + { + this.handleChange( + 'email', + isEmail, + e + ); + }} + placeholder='Email' + type='email' + value={ email.value } + wrapperClassName={ inputClass } /> + { + this.handleChange( + 'phone', + (data) => isMobilePhone(data, 'en-US'), + e + ); + }} + placeholder='555-123-1234' + type='tel' + value={ phone.value } + wrapperClassName={ inputClass } /> + { + this.handleChange( + 'url', + (data) => isURL(data, { 'require_protocol': true }), + e + ); + }} + placeholder='http://freecatphotoapp.com' + type='url' + value={ url.value } + wrapperClassName={ inputClass } /> + { + this.handleChange( + 'logo', + (data) => isURL(data, { 'require_protocol': true }), + e + ); + }} + placeholder='http://freecatphotoapp.com/logo.png' + type='url' + value={ logo.value } + wrapperClassName={ inputClass } /> + +
+

Make it stand out

+
+ { + this.handleChange( + 'highlight', + () => { return true; }, + e + ); + }} + type='checkbox' + value={ highlight.value } /> +
-
-

Job Information

-
- { - this.handleChange( - 'position', - isAscii, - e - ); - }} - placeholder='Position' - type='text' - value={ position.value } - wrapperClassName={ inputClass } /> - { - this.handleChange( - 'locale', - isAscii, - e, - ); - }} - placeholder='Location' - type='text' - value={ locale.value } - wrapperClassName={ inputClass } /> - { - this.handleChange( - 'description', - isAscii, - e - ); - }} - placeholder='Description' - rows='10' - type='textarea' - value={ description.value } - wrapperClassName={ inputClass } /> - -
-

Company Information

-
- { - this.handleChange( - 'name', - isAscii, - e, - ); - }} - placeholder='Foo, INC' - type='text' - value={ name.value } - wrapperClassName={ inputClass } /> - { - this.handleChange( - 'email', - isEmail, - e - ); - }} - placeholder='Email' - type='email' - value={ email.value } - wrapperClassName={ inputClass } /> - { - this.handleChange( - 'phone', - (data) => isMobilePhone(data, 'en-US'), - e - ); - }} - placeholder='555-123-1234' - type='tel' - value={ phone.value } - wrapperClassName={ inputClass } /> - { - this.handleChange( - 'url', - (data) => isURL(data, { 'require_protocol': true }), - e - ); - }} - placeholder='http://freecatphotoapp.com' - type='url' - value={ url.value } - wrapperClassName={ inputClass } /> - { - this.handleChange( - 'logo', - (data) => isURL(data, { 'require_protocol': true }), - e - ); - }} - placeholder='http://freecatphotoapp.com/logo.png' - type='url' - value={ logo.value } - wrapperClassName={ inputClass } /> - -
-

Make it stand out

-
- { - this.handleChange( - 'highlight', - () => { return true; }, - e - ); - }} - type='checkbox' - value={ highlight.value } /> + + +
From 8148c1a19cedbd1cae09f11d799576f1e099be6f Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Thu, 24 Sep 2015 20:28:04 -0700 Subject: [PATCH 21/63] save form to localStorage --- common/app/routes/Jobs/components/NewJob.jsx | 121 +++++++++++++++---- common/app/routes/Jobs/flux/Actions.js | 52 ++++++-- common/app/routes/Jobs/flux/Store.js | 4 +- common/app/routes/Jobs/utils.js | 22 ++++ common/models/job.json | 5 +- package.json | 2 + 6 files changed, 169 insertions(+), 37 deletions(-) create mode 100644 common/app/routes/Jobs/utils.js diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index 41d20db840..b160671c4b 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -1,5 +1,13 @@ import React, { PropTypes } from 'react'; import { contain } from 'thundercats-react'; +import debugFactory from 'debug'; +import { getDefaults } from '../utils'; + +import { + inHTMLData, + uriInSingleQuotedAttr +} from 'xss-filters'; + import { Button, Col, @@ -7,6 +15,7 @@ import { Row, Well } from 'react-bootstrap'; + import { isAscii, isEmail, @@ -14,31 +23,34 @@ import { isURL } from 'validator'; -const defaults = { - 'string': { - value: '', - valid: false, - pristine: true - }, - bool: { - value: false - } -}; +const debug = debugFactory('freecc:jobs:newForm'); + +const checkValidity = [ + 'position', + 'locale', + 'description', + 'email', + 'phone', + 'url', + 'logo', + 'name', + 'highlight' +]; export default contain({ actions: 'jobActions', store: 'jobsStore', map({ form = {} }) { const { - position = defaults['string'], - locale = defaults['string'], - description = defaults['string'], - email = defaults['string'], - phone = defaults['string'], - url = defaults['string'], - logo = defaults['string'], - name = defaults['string'], - highlight = defaults['bool'] + position = getDefaults('string'), + locale = getDefaults('string'), + description = getDefaults('string'), + email = getDefaults('string'), + phone = getDefaults('string'), + url = getDefaults('string'), + logo = getDefaults('string'), + name = getDefaults('string'), + highlight = getDefaults('bool') } = form; return { position, @@ -51,6 +63,9 @@ export default contain({ name, highlight }; + }, + subscribeOnWillMount() { + return typeof window !== 'undefined'; } }, React.createClass({ @@ -69,6 +84,63 @@ export default contain({ highlight: PropTypes.object }, + handleSubmit(e) { + e.preventDefault(); + let valid = true; + checkValidity.forEach((prop) => { + // if value exist, check if it is valid + if (this.props[prop].value) { + valid = valid && !!this.props[prop].valid; + } + }); + + if (!valid) { + debug('form not valid'); + return; + } + + const { + position, + locale, + description, + email, + phone, + url, + logo, + name, + highlight, + jobActions + } = this.props; + + // sanitize user output + const jobValues = { + position: inHTMLData(position.value), + location: inHTMLData(locale.value), + description: inHTMLData(description.value), + email: inHTMLData(email.value), + phone: inHTMLData(phone.value), + url: uriInSingleQuotedAttr(url.value), + logo: uriInSingleQuotedAttr(logo.value), + name: inHTMLData(name.value), + highlight: !!highlight.value + }; + + const job = Object.keys(jobValues).reduce((accu, prop) => { + if (jobValues[prop]) { + accu[prop] = jobValues[prop]; + } + return accu; + }, {}); + + debug('job sanitized', job); + jobActions.saveForm(job); + }, + + componentDidMount() { + const { jobActions } = this.props; + jobActions.getSavedForm(); + }, + handleChange(name, validator, { target: { value } }) { const { jobActions: { handleForm } } = this.props; handleForm({ name, value, validator }); @@ -95,7 +167,9 @@ export default contain({

Create Your Job Post

-
+

Job Information

@@ -151,7 +225,7 @@ export default contain({

Company Information

{ @@ -248,8 +322,9 @@ export default contain({ lgOffset={ 3 }> diff --git a/common/app/routes/Jobs/flux/Actions.js b/common/app/routes/Jobs/flux/Actions.js index 5b284e4b8c..771c520013 100644 --- a/common/app/routes/Jobs/flux/Actions.js +++ b/common/app/routes/Jobs/flux/Actions.js @@ -1,4 +1,6 @@ import { Actions } from 'thundercats'; +import store from 'store'; +import { getDefaults } from '../utils'; import debugFactory from 'debug'; const debug = debugFactory('freecc:jobs:actions'); @@ -52,12 +54,14 @@ export default Actions({ newState.form = assign( {}, form, - { [name]: { - value, - valid: false, - pristine: false, - bsStyle: value ? 'error' : null - }} + { + [name]: { + value, + valid: false, + pristine: false, + bsStyle: value ? 'error' : null + } + } ); return newState; } @@ -70,16 +74,31 @@ export default Actions({ newState.form = assign( {}, form, - { [name]: { - value, - valid: true, - pristine: false, - bsStyle: value ? 'success' : null - }} + { + [name]: { + value, + valid: true, + pristine: false, + bsStyle: value ? 'success' : null + } + } ); return newState; } }; + }, + saveForm: null, + getSavedForm: null, + setForm(job) { + const form = Object.keys(job).reduce((accu, prop) => { + console.log('form', accu); + return Object.assign( + accu, + { [prop]: getDefaults(typeof prop, job[prop]) } + ); + }, {}); + + return { form }; } }) .refs({ displayName: 'JobActions' }) @@ -111,5 +130,14 @@ export default Actions({ jobActions.setJobs({}); }); }); + + jobActions.saveForm.subscribe((form) => { + store.set('newJob', form); + }); + + jobActions.getSavedForm.subscribe(() => { + const job = store.get('newJob'); + jobActions.setForm(job); + }); return jobActions; }); diff --git a/common/app/routes/Jobs/flux/Store.js b/common/app/routes/Jobs/flux/Store.js index a73235f1aa..b2f5132013 100644 --- a/common/app/routes/Jobs/flux/Store.js +++ b/common/app/routes/Jobs/flux/Store.js @@ -15,13 +15,15 @@ export default Store({ showModal: false }) setError, openModal, closeModal, - handleForm + handleForm, + setForm } = cat.getActions('JobActions'); const register = createRegistrar(jobsStore); register(setter(setJobs)); register(setter(setError)); register(setter(openModal)); register(setter(closeModal)); + register(setter(setForm)); register(transformer(findJob)); register(handleForm); diff --git a/common/app/routes/Jobs/utils.js b/common/app/routes/Jobs/utils.js new file mode 100644 index 0000000000..3a60c373a8 --- /dev/null +++ b/common/app/routes/Jobs/utils.js @@ -0,0 +1,22 @@ +const defaults = { + 'string': { + value: '', + valid: false, + pristine: true, + type: 'string' + }, + bool: { + value: false, + type: 'boolean' + } +}; + +export function getDefaults(type, value) { + if (!type) { + return defaults['string']; + } + if (value) { + return Object.assign({}, defaults[type], { value }); + } + return defaults[type]; +} diff --git a/common/models/job.json b/common/models/job.json index 197f0619bf..f77fc6defa 100644 --- a/common/models/job.json +++ b/common/models/job.json @@ -30,6 +30,9 @@ "state": { "type": "string" }, + "url": { + "type": "string" + }, "country": { "type": "string" }, @@ -39,7 +42,7 @@ "description": { "type": "string" }, - "isApproverd": { + "isApproved": { "type": "boolean" }, "isHighlighted": { diff --git a/package.json b/package.json index df579eb2bc..f16e4bb9db 100644 --- a/package.json +++ b/package.json @@ -97,12 +97,14 @@ "sanitize-html": "~1.6.1", "sort-keys": "^1.1.1", "source-map-support": "^0.3.2", + "store": "https://github.com/berkeleytrue/store.js.git#feature/noop-server", "thundercats": "^2.1.0", "thundercats-react": "^0.1.0", "twit": "~1.1.20", "uglify-js": "~2.4.15", "validator": "^3.22.1", "webpack": "^1.9.12", + "xss-filters": "^1.2.6", "yui": "~3.18.1" }, "devDependencies": { From c63a983fb93a5352b82eedeaf5e9c4e51379d064 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Fri, 25 Sep 2015 00:04:38 -0700 Subject: [PATCH 22/63] filter output from localStorage --- common/app/routes/Jobs/flux/Actions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/app/routes/Jobs/flux/Actions.js b/common/app/routes/Jobs/flux/Actions.js index 771c520013..15229e039d 100644 --- a/common/app/routes/Jobs/flux/Actions.js +++ b/common/app/routes/Jobs/flux/Actions.js @@ -137,7 +137,9 @@ export default Actions({ jobActions.getSavedForm.subscribe(() => { const job = store.get('newJob'); - jobActions.setForm(job); + if (job && !Array.isArray(job) && typeof job === 'object') { + jobActions.setForm(job); + } }); return jobActions; }); From 891341532b95953d028edf7250c1798c973903da Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Fri, 25 Sep 2015 12:53:29 -0700 Subject: [PATCH 23/63] refactor form to do validation right in component --- common/app/routes/Jobs/components/NewJob.jsx | 135 ++++++++----------- common/app/routes/Jobs/flux/Actions.js | 47 +------ common/app/routes/Jobs/utils.js | 2 +- 3 files changed, 58 insertions(+), 126 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index b160671c4b..12f9b425a0 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -37,22 +37,31 @@ const checkValidity = [ 'highlight' ]; +function formatValue(value, validator, type = 'string') { + const formated = getDefaults(type); + if (validator && type === 'string') { + formated.valid = validator(value); + } + if (value) { + formated.value = value; + formated.bsStyle = formated.valid ? 'success' : 'error'; + } + return formated; +} + +function isValidURL(data) { + return isURL(data, { 'require_protocol': true }); +} + +function isValidPhone(data) { + return isMobilePhone(data, 'en-US'); +} + export default contain({ actions: 'jobActions', store: 'jobsStore', map({ form = {} }) { const { - position = getDefaults('string'), - locale = getDefaults('string'), - description = getDefaults('string'), - email = getDefaults('string'), - phone = getDefaults('string'), - url = getDefaults('string'), - logo = getDefaults('string'), - name = getDefaults('string'), - highlight = getDefaults('bool') - } = form; - return { position, locale, description, @@ -62,6 +71,17 @@ export default contain({ logo, name, highlight + } = form; + return { + position: formatValue(position, isAscii), + locale: formatValue(locale, isAscii), + description: formatValue(description, isAscii), + email: formatValue(email, isEmail), + phone: formatValue(phone, isValidPhone), + url: formatValue(url, isValidURL), + logo: formatValue(logo, isValidURL), + name: formatValue(name, isAscii), + highlight: formatValue(highlight, null, 'bool') }; }, subscribeOnWillMount() { @@ -86,11 +106,12 @@ export default contain({ handleSubmit(e) { e.preventDefault(); + const props = this.props; let valid = true; checkValidity.forEach((prop) => { // if value exist, check if it is valid - if (this.props[prop].value) { - valid = valid && !!this.props[prop].valid; + if (props[prop].value && props[prop].type !== 'boolean') { + valid = valid && !!props[prop].valid; } }); @@ -141,9 +162,9 @@ export default contain({ jobActions.getSavedForm(); }, - handleChange(name, validator, { target: { value } }) { + handleChange(name, { target: { value } }) { const { jobActions: { handleForm } } = this.props; - handleForm({ name, value, validator }); + handleForm({ [name]: value }); }, render() { @@ -156,8 +177,10 @@ export default contain({ url, logo, name, - highlight + highlight, + jobActions: { handleForm } } = this.props; + const { handleChange } = this; const labelClass = 'col-sm-offset-1 col-sm-2'; const inputClass = 'col-sm-6'; @@ -178,13 +201,7 @@ export default contain({ bsStyle={ position.bsStyle } label='Position' labelClassName={ labelClass } - onChange={ (e) => { - this.handleChange( - 'position', - isAscii, - e - ); - }} + onChange={ (e) => handleChange('position', e) } placeholder='Position' type='text' value={ position.value } @@ -193,13 +210,7 @@ export default contain({ bsStyle={ locale.bsStyle } label='Location' labelClassName={ labelClass } - onChange={ (e) => { - this.handleChange( - 'locale', - isAscii, - e, - ); - }} + onChange={ (e) => handleChange('locale', e) } placeholder='Location' type='text' value={ locale.value } @@ -208,13 +219,7 @@ export default contain({ bsStyle={ description.bsStyle } label='Description' labelClassName={ labelClass } - onChange={ (e) => { - this.handleChange( - 'description', - isAscii, - e - ); - }} + onChange={ (e) => handleChange('description', e) } placeholder='Description' rows='10' type='textarea' @@ -228,13 +233,7 @@ export default contain({ bsStyle={ name.bsStyle } label='Company Name' labelClassName={ labelClass } - onChange={ (e) => { - this.handleChange( - 'name', - isAscii, - e, - ); - }} + onChange={ (e) => handleChange('name', e) } placeholder='Foo, INC' type='text' value={ name.value } @@ -243,13 +242,7 @@ export default contain({ bsStyle={ email.bsStyle } label='Email' labelClassName={ labelClass } - onChange={ (e) => { - this.handleChange( - 'email', - isEmail, - e - ); - }} + onChange={ (e) => handleChange('email', e) } placeholder='Email' type='email' value={ email.value } @@ -258,13 +251,7 @@ export default contain({ bsStyle={ phone.bsStyle } label='Phone' labelClassName={ labelClass } - onChange={ (e) => { - this.handleChange( - 'phone', - (data) => isMobilePhone(data, 'en-US'), - e - ); - }} + onChange={ (e) => handleChange('phone', e) } placeholder='555-123-1234' type='tel' value={ phone.value } @@ -273,13 +260,7 @@ export default contain({ bsStyle={ url.bsStyle } label='URL' labelClassName={ labelClass } - onChange={ (e) => { - this.handleChange( - 'url', - (data) => isURL(data, { 'require_protocol': true }), - e - ); - }} + onChange={ (e) => handleChange('url', e) } placeholder='http://freecatphotoapp.com' type='url' value={ url.value } @@ -288,13 +269,7 @@ export default contain({ bsStyle={ logo.bsStyle } label='Logo' labelClassName={ labelClass } - onChange={ (e) => { - this.handleChange( - 'logo', - (data) => isURL(data, { 'require_protocol': true }), - e - ); - }} + onChange={ (e) => handleChange('logo', e) } placeholder='http://freecatphotoapp.com/logo.png' type='url' value={ logo.value } @@ -304,17 +279,15 @@ export default contain({

Make it stand out

{ - this.handleChange( - 'highlight', - () => { return true; }, - e - ); - }} - type='checkbox' - value={ highlight.value } /> + onChange={ + ({ target: { checked } }) => handleForm({ + highlight: !!checked + }) + } + type='checkbox' />
{} }) { - if (!name) { - // operation noop - return { replace: null }; - } - if (!validator(value)) { - return { - transform(oldState) { - const { form } = oldState; - const newState = assign({}, oldState); - newState.form = assign( - {}, - form, - { - [name]: { - value, - valid: false, - pristine: false, - bsStyle: value ? 'error' : null - } - } - ); - return newState; - } - }; - } + handleForm(value) { return { transform(oldState) { const { form } = oldState; @@ -74,14 +48,7 @@ export default Actions({ newState.form = assign( {}, form, - { - [name]: { - value, - valid: true, - pristine: false, - bsStyle: value ? 'success' : null - } - } + value ); return newState; } @@ -89,15 +56,7 @@ export default Actions({ }, saveForm: null, getSavedForm: null, - setForm(job) { - const form = Object.keys(job).reduce((accu, prop) => { - console.log('form', accu); - return Object.assign( - accu, - { [prop]: getDefaults(typeof prop, job[prop]) } - ); - }, {}); - + setForm(form) { return { form }; } }) diff --git a/common/app/routes/Jobs/utils.js b/common/app/routes/Jobs/utils.js index 3a60c373a8..aeb0396c12 100644 --- a/common/app/routes/Jobs/utils.js +++ b/common/app/routes/Jobs/utils.js @@ -18,5 +18,5 @@ export function getDefaults(type, value) { if (value) { return Object.assign({}, defaults[type], { value }); } - return defaults[type]; + return Object.assign({}, defaults[type]); } From 90f6d986d783a9d5b6931dff89d1ef846b1766b4 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Sat, 26 Sep 2015 22:23:56 -0700 Subject: [PATCH 24/63] show preview from new job --- common/app/routes/Jobs/components/NewJob.jsx | 6 ++ common/app/routes/Jobs/components/Preview.jsx | 14 ++++ common/app/routes/Jobs/components/Show.jsx | 68 +------------------ common/app/routes/Jobs/components/ShowJob.jsx | 67 ++++++++++++++++++ common/app/routes/Jobs/index.js | 4 ++ 5 files changed, 93 insertions(+), 66 deletions(-) create mode 100644 common/app/routes/Jobs/components/Preview.jsx create mode 100644 common/app/routes/Jobs/components/ShowJob.jsx diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index 12f9b425a0..4c369411f0 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -1,4 +1,5 @@ import React, { PropTypes } from 'react'; +import { History } from 'react-router'; import { contain } from 'thundercats-react'; import debugFactory from 'debug'; import { getDefaults } from '../utils'; @@ -104,6 +105,8 @@ export default contain({ highlight: PropTypes.object }, + mixins: [History], + handleSubmit(e) { e.preventDefault(); const props = this.props; @@ -153,8 +156,11 @@ export default contain({ return accu; }, {}); + job.postedOn = new Date(); debug('job sanitized', job); jobActions.saveForm(job); + + this.history.pushState(null, '/jobs/new/preview'); }, componentDidMount() { diff --git a/common/app/routes/Jobs/components/Preview.jsx b/common/app/routes/Jobs/components/Preview.jsx new file mode 100644 index 0000000000..5b6081be5c --- /dev/null +++ b/common/app/routes/Jobs/components/Preview.jsx @@ -0,0 +1,14 @@ +// import React, { PropTypes } from 'react'; +import { contain } from 'thundercats-react'; +import ShowJob from './ShowJob.jsx'; + +export default contain( + { + store: 'JobsStore', + actions: 'JobActions', + map({ form: job = {} }) { + return { job }; + } + }, + ShowJob +); diff --git a/common/app/routes/Jobs/components/Show.jsx b/common/app/routes/Jobs/components/Show.jsx index 0baedb82b3..ce2512c27d 100644 --- a/common/app/routes/Jobs/components/Show.jsx +++ b/common/app/routes/Jobs/components/Show.jsx @@ -1,13 +1,5 @@ -import React, { PropTypes } from 'react'; import { contain } from 'thundercats-react'; -import { Row, Thumbnail, Panel, Well } from 'react-bootstrap'; -import moment from 'moment'; - -const thumbnailStyle = { - backgroundColor: 'white', - maxHeight: '100px', - maxWidth: '100px' -}; +import ShowJob from './ShowJob.jsx'; export default contain( { @@ -28,61 +20,5 @@ export default contain( return job.id !== id; } }, - React.createClass({ - displayName: 'ShowJob', - propTypes: { - job: PropTypes.object, - params: PropTypes.object - }, - - renderHeader({ company, position }) { - return ( -
-

{ company }

-
- { position } -
-
- ); - }, - - render() { - const { job = {} } = this.props; - const { - logo, - position, - city, - company, - state, - email, - phone, - postedOn, - description - } = job; - - return ( -
- - - - - Position: { position } - Location: { city }, { state } -
- Contact: { email || phone || 'N/A' } -
- Posted On: { moment(postedOn).format('MMMM Do, YYYY') } -
-

{ description }

-
-
-
- ); - } - }) + ShowJob ); diff --git a/common/app/routes/Jobs/components/ShowJob.jsx b/common/app/routes/Jobs/components/ShowJob.jsx new file mode 100644 index 0000000000..1a048a3fff --- /dev/null +++ b/common/app/routes/Jobs/components/ShowJob.jsx @@ -0,0 +1,67 @@ +import React, { PropTypes } from 'react'; +import { Row, Thumbnail, Panel, Well } from 'react-bootstrap'; +import moment from 'moment'; + +const thumbnailStyle = { + backgroundColor: 'white', + maxHeight: '100px', + maxWidth: '100px' +}; + +export default React.createClass({ + displayName: 'ShowJob', + propTypes: { + job: PropTypes.object, + params: PropTypes.object + }, + + renderHeader({ company, position }) { + return ( +
+

{ company }

+
+ { position } +
+
+ ); + }, + + render() { + const { job = {} } = this.props; + const { + logo, + position, + city, + company, + state, + email, + phone, + postedOn, + description + } = job; + + return ( +
+ + + + + Position: { position } + Location: { city }, { state } +
+ Contact: { email || phone || 'N/A' } +
+ Posted On: { moment(postedOn).format('MMMM Do, YYYY') } +
+

{ description }

+
+
+
+ ); + } +}); diff --git a/common/app/routes/Jobs/index.js b/common/app/routes/Jobs/index.js index 3564332d32..6c556c994e 100644 --- a/common/app/routes/Jobs/index.js +++ b/common/app/routes/Jobs/index.js @@ -1,6 +1,7 @@ import Jobs from './components/Jobs.jsx'; import NewJob from './components/NewJob.jsx'; import Show from './components/Show.jsx'; +import Preview from './components/Preview.jsx'; /* * index: /jobs list jobs @@ -15,6 +16,9 @@ export default { }, { path: 'jobs/new', component: NewJob + }, { + path: 'jobs/new/preview', + component: Preview }, { path: 'jobs/:id', component: Show From d25330278b1db1c39fbf1fc8032bb362110605d0 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 27 Sep 2015 00:21:15 -0700 Subject: [PATCH 25/63] remove unneccessary additional bonfire argument I added a month ago --- seed/challenges/basic-bonfires.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index cbcdbd1b83..e08a8b2a9d 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -270,7 +270,7 @@ " return arr;", "}", "", - "largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]], \"\");" + "largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);" ], "tests": [ "assert(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]).constructor === Array, 'largestOfFour() should return an array.');", From dc48635f5de9c24cd02a01a15d955d3e2de1373f Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 27 Sep 2015 00:52:27 -0700 Subject: [PATCH 26/63] make more improvements to advanced bonfire tests --- seed/challenges/advanced-bonfires.json | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index 2917dc893c..f824a479fc 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -9,20 +9,25 @@ "description": [ "Return true if the passed string is a valid US phone number", "The user may fill out the form field any way they choose as long as it is a valid US number. The following are all valid formats for US numbers:", - "555-555-5555, (555)555-5555, (555) 555-5555, 555 555 5555, 5555555555, 1 555 555 5555", - "For this challenge you will be presented with a string such as \"800-692-7753\" or \"8oo-six427676;laskdjf\". Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is \"1\". Return true if the string is a valid US phone number; otherwise false.", + "555-555-5555", + "(555)555-5555", + "(555) 555-5555", + "555 555 5555", + "5555555555", + "1 555 555 5555", + "For this challenge you will be presented with a string such as 800-692-7753 or 8oo-six427676;laskdjf. Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is 1. Return true if the string is a valid US phone number; otherwise false.", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." ], "tests": [ "assert.isBoolean(telephoneCheck(\"555-555-5555\") === 'should return a boolean.');", "assert(telephoneCheck(\"1 555-555-5555\") === true, '1 555-555-5555 should return true.');", - "assert(telephoneCheck(\"1 (555) 555-5555\") === true), '1 (555) 555-5555 should return true.';", + "assert(telephoneCheck(\"1 (555) 555-5555\") === true, '1 (555) 555-5555 should return true.');", "assert(telephoneCheck(\"5555555555\") === true, '5555555555 should return true.');", "assert(telephoneCheck(\"555-555-5555\") === true, '555-555-5555 should return true.');", "assert(telephoneCheck(\"(555)555-5555\") === true, '(555)555-5555 should return true.');", "assert(telephoneCheck(\"1(555)555-5555\") === true, '1(555)555-5555 should return true.');", "assert(telephoneCheck(\"1 555 555 5555\") === true, '1 555 555 5555 should return true.');", - "assert(telephoneCheck(\"555-555-5555\") === true), '555-555-5555 should return true.';", + "assert(telephoneCheck(\"555-555-5555\") === true, '555-555-5555 should return true.');", "assert(telephoneCheck(\"1 456 789 4444\") === true, '1 456 789 4444 should return true.');", "assert(telephoneCheck(\"123**&!!asdf#\") === false, '123**&!!asdf# should return false.');", "assert(telephoneCheck(\"55555555\") === false, '55555555 should return false.');", @@ -74,16 +79,16 @@ ], "challengeSeed": [ "function sym(args) {", - " return arguments;", + " return args;", "}", "", "sym([1, 2, 3], [5, 2, 1, 4]);" ], "tests": [ - "assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 5, 4], 'should return an array of unique values');", - "assert.sameMembers(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'should return the symmetric difference of the given arrays');", - "assert.sameMembers(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'should return an array of unique values');", - "assert.sameMembers(sym([1, 1]), [1], 'should return an array of unique values');" + "assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 5, 4], '[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], '[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], '[1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5] should return [1, 4, 5].');", + "assert.sameMembers(sym([1, 1]), [1], '[1, 1] should return [1].');" ], "MDNlinks": [ "Array.reduce()", From 96804d37cf2deecf68aa597ba6c4ba4756ca3ece Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 27 Sep 2015 01:04:21 -0700 Subject: [PATCH 27/63] confirm all advanced bonfires work though test output is not ideal yet --- seed/challenges/advanced-bonfires.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index f824a479fc..04ff5d7f5e 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -235,13 +235,13 @@ "permAlone('aab');" ], "tests": [ - "assert.isNumber(permAlone('aab'), 'should return a \"number\".');", - "assert.strictEqual(permAlone('aab'), 2, 'should return 2.');", - "assert.strictEqual(permAlone('aaa'), 0, 'should return 0.');", - "assert.strictEqual(permAlone('aabb'), 8, 'should return 8.');", - "assert.strictEqual(permAlone('abcdefa'), 3600, 'should return 3600.');", - "assert.strictEqual(permAlone('abfdefa'), 2640, 'should return 2640.');", - "assert.strictEqual(permAlone('zzzzzzzz'), 0, 'should return 0.');" + "assert.isNumber(permAlone('aab'), 'aab should return a number.');", + "assert.strictEqual(permAlone('aab'), 2, 'aab should return 2.');", + "assert.strictEqual(permAlone('aaa'), 0, 'aaa should return 0.');", + "assert.strictEqual(permAlone('aabb'), 8, 'aabb should return 8.');", + "assert.strictEqual(permAlone('abcdefa'), 3600, 'abcdefa should return 3600.');", + "assert.strictEqual(permAlone('abfdefa'), 2640, 'abfdefa should return 2640.');", + "assert.strictEqual(permAlone('zzzzzzzz'), 0, 'zzzzzzzz should return 0.');" ], "MDNlinks": [ "Permutations", @@ -281,12 +281,12 @@ "friendly(['2015-07-01', '2015-07-04']);" ], "tests": [ - "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'ending month should be omitted since it is already mentioned');", - "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'two months apart can be inferred if it is the next year');", - "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017']);", - "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th'], 'one month apart can be inferred it is the same year');", - "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'since we do not duplicate only return once');", - "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023']);" + "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], '[\"2015-07-01\", \"2015-07-04\"] should return [\"July 1st\",\"4th\"].');", + "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], '[\"2015-12-01\", \"2016-02-03\"] should return [\"December 1st\",\"February 3rd\"].');", + "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017'], '[\"2015-12-01\", \"2017-02-03\"] should return [\"December 1st, 2015\",\"February 3rd, 2017\"].');", + "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th'], '[\"2016-03-01\", \"2016-05-05\"] should return [\"March 1st\",\"May 5th\"]');", + "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], '[\"2017-01-01\", \"2017-01-01\"] should return [\"January 1st, 2017\"].');", + "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023'], '[\"2022-09-05\", \"2023-09-04\"] should return [\"September 5th, 2022\",\"September 4th, 2023\"].');" ], "MDNlinks": [ "String.split()", From e74533a727383363148506689e675ad4a22a4a04 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 27 Sep 2015 17:08:56 -0700 Subject: [PATCH 28/63] add lockdown mode toggling --- common/models/user.json | 4 + server/boot/user.js | 30 +++++++ server/views/account/account.jade | 5 -- server/views/account/show.jade | 142 ++++++++++++++++-------------- 4 files changed, 111 insertions(+), 70 deletions(-) delete mode 100644 server/views/account/account.jade diff --git a/common/models/user.json b/common/models/user.json index d0d8bed6e8..e1547203b1 100644 --- a/common/models/user.json +++ b/common/models/user.json @@ -133,6 +133,10 @@ "type": "boolean", "default": true }, + "lockdownMode": { + "type": "boolean", + "default": false + }, "currentChallenge": { "type": {} }, diff --git a/server/boot/user.js b/server/boot/user.js index f521404ced..2b08e4db62 100644 --- a/server/boot/user.js +++ b/server/boot/user.js @@ -68,6 +68,7 @@ module.exports = function(app) { router.post('/reset-password', postReset); router.get('/email-signup', getEmailSignup); router.get('/email-signin', getEmailSignin); + router.get('/toggle-lockdown-mode', toggleLockdownMode); router.post( '/account/delete', ifNoUser401, @@ -192,6 +193,35 @@ module.exports = function(app) { ); } + + + function toggleLockdownMode(req, res) { + if (req.user) { + if (req.user.lockdownMode === true) { + req.user.lockdownMode = false; + req.user.save(function (err) { + if (err) { + return next(err); + } + req.flash('success', {msg: 'Other people can now view all your challenge solutions. You can change this back at any time in the "Manage My Account" section at the bottom of this page.'}); + res.redirect(req.user.username); + }); + } else { + req.user.lockdownMode = true; + req.user.save(function (err) { + if (err) { + return next(err); + } + req.flash('success', {msg: 'All your challenge solutions are now hidden from other people. You can change this back at any time in the "Manage My Account" section at the bottom of this page.'}); + res.redirect(req.user.username); + }); + } + } else { + req.flash('error', {msg: 'You must be signed in to change your account settings.'}); + res.redirect('/'); + } + } + function postDeleteAccount(req, res, next) { User.destroyById(req.user.id, function(err) { if (err) { return next(err); } diff --git a/server/views/account/account.jade b/server/views/account/account.jade deleted file mode 100644 index 0259b504f7..0000000000 --- a/server/views/account/account.jade +++ /dev/null @@ -1,5 +0,0 @@ -extends ../layout -block content - script. - var challengeName = 'Account View' - diff --git a/server/views/account/show.jade b/server/views/account/show.jade index 2b80bba9f2..bee515fcff 100644 --- a/server/views/account/show.jade +++ b/server/views/account/show.jade @@ -5,7 +5,7 @@ block content var challengeName = 'Profile View'; if (user && user.username === username) .panel.panel-info - .panel-heading.text-center Manage your account + .panel-heading.text-center Update Your Portfolio .panel-body .row .col-xs-12 @@ -37,56 +37,18 @@ block content a.btn.btn-lg.btn-block.btn-google-plus.btn-link-social(href='/link/google') i.fa.fa-google-plus | Add my Google+ to my profile - .big-spacer - .col-xs-12 - a.btn.btn-lg.btn-block.btn-warning.btn-link-social(href='/logout') - span.ion-android-exit - | Sign me out of Free Code Camp - .col-xs-12 - a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='mailto:team@freecodecamp.com') - span.ion-email - | Email us at team@freecodecamp.com - .col-xs-12 - a.btn.btn-lg.btn-block.btn-danger.btn-link-social.confirm-deletion - span.ion-trash-b - | Delete my Free Code Camp account - script. - $('.confirm-deletion').on("click", function () { - $('#modal-dialog').modal('show'); - }); - #modal-dialog.modal.animated.wobble - .modal-dialog - .modal-content - .modal-header - a.close(href='#', data-dismiss='modal', aria-hidden='true') × - h3 You don't really want to delete your account, do you? - .modal-body - p This will really delete all your data, including all your progress, news stories and brownie points. - p We won't be able to recover any of it for you later, even if you change your mind. - p If there's something we could do better, send us an email instead and we'll do our best:   - a(href="mailto:team@freecodecamp.com") team@freecodecamp.com - | . - .modal-footer - a.btn.btn-success.btn-block(href='#', data-dismiss='modal', aria-hidden='true') - span.ion-happy - | Nevermind, I don't want to delete all my progress - .btn-spacer - form(action='/account/delete', method='POST') - input(type='hidden', name='_csrf', value=_csrf) - button.btn.btn-danger.btn-block(type='submit') - span.ion-trash-b - | I am 100% sure I want to delete all my progress + .panel.panel-info .panel-heading.text-center h1 #{username}'s portfolio .panel-body - .row.text-center - .col-xs-12.col-sm-10.col-sm-offset-1 - a.btn.btn-big.btn-primary.btn-block(href="/account") Manage my account - .button-spacer - .col-xs-12.col-sm-10.col-sm-offset-1 - a.btn.btn-big.btn-success.btn-block(href="/signout") Sign out of Free Code Camp - .spacer + .row.text-center + .col-xs-12.col-sm-10.col-sm-offset-1 + a.btn.btn-big.btn-primary.btn-block(href="/account") Manage my account + .button-spacer + .col-xs-12.col-sm-10.col-sm-offset-1 + a.btn.btn-big.btn-success.btn-block(href="/signout") Sign out of Free Code Camp + .spacer .row .col-xs-12 .col-xs-12.col-sm-12.col-md-5 @@ -166,21 +128,71 @@ block content td.col-xs-2= moment(challenge.completedDate, 'x').format("MMM DD, YYYY") td.col-xs-6 a(href=challenge.solution, target='_blank') View my solution - if (user && user.username === username) - br - if (bonfires.length > 0) - .col-sm-12 - table.table.table-striped - thead - tr - th.col-xs-4 Bonfire - th.col-xs-2 Completed - th.col-xs-6 Solution - for bonfire in bonfires - tr - td.col-xs-4 - a(href='/challenges/' + bonfire.name, target='_blank')= bonfire.name - td.col-xs-2= moment(bonfire.completedDate, 'x').format("MMM DD, YYYY") - td.col-xs-6 - pre.wrappable= bonfire.solution - br + if (bonfires.length > 0) + .col-sm-12 + table.table.table-striped + thead + tr + th.col-xs-4 Bonfire + th.col-xs-2 Completed + th.col-xs-6 Solution + for bonfire in bonfires + tr + td.col-xs-4 + a(href='/challenges/' + bonfire.name, target='_blank')= bonfire.name + td.col-xs-2= moment(bonfire.completedDate, 'x').format("MMM DD, YYYY") + td.col-xs-6 + pre.wrappable= bonfire.solution + + if (user && user.username === username) + .panel.panel-info + .panel-heading.text-center Manage Your Account + .panel-body + .col-xs-12 + a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='mailto:team@freecodecamp.com') + span.ion-email + | Email us at team@freecodecamp.com + if (!user.lockdownMode) + .col-xs-12 + a.btn.btn-lg.btn-block.btn-info.btn-link-social(href='/toggle-lockdown-mode') + span.ion-locked + | Hide all my solutions from other people + else + .col-xs-12 + a.btn.btn-lg.btn-block.btn-info.btn-link-social(href='/toggle-lockdown-mode') + span.ion-unlocked + | Let other people see all my solutions + .col-xs-12 + a.btn.btn-lg.btn-block.btn-warning.btn-link-social(href='/logout') + span.ion-android-exit + | Sign me out of Free Code Camp + .col-xs-12 + a.btn.btn-lg.btn-block.btn-danger.btn-link-social.confirm-deletion + span.ion-trash-b + | Delete my Free Code Camp account + script. + $('.confirm-deletion').on("click", function () { + $('#modal-dialog').modal('show'); + }); + #modal-dialog.modal.animated.wobble + .modal-dialog + .modal-content + .modal-header + a.close(href='#', data-dismiss='modal', aria-hidden='true') × + h3 You don't really want to delete your account, do you? + .modal-body + p This will really delete all your data, including all your progress, news stories and brownie points. + p We won't be able to recover any of it for you later, even if you change your mind. + p If there's something we could do better, send us an email instead and we'll do our best:   + a(href="mailto:team@freecodecamp.com") team@freecodecamp.com + | . + .modal-footer + a.btn.btn-success.btn-block(href='#', data-dismiss='modal', aria-hidden='true') + span.ion-happy + | Nevermind, I don't want to delete all my progress + .btn-spacer + form(action='/account/delete', method='POST') + input(type='hidden', name='_csrf', value=_csrf) + button.btn.btn-danger.btn-block(type='submit') + span.ion-trash-b + | I am 100% sure I want to delete all my progress From 3e25b3a6bce0816aae8ffa7dcbf91bb2385bc3ea Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 27 Sep 2015 21:52:13 -0700 Subject: [PATCH 29/63] improve button html --- server/views/account/show.jade | 149 +++++++++++++++------------------ 1 file changed, 67 insertions(+), 82 deletions(-) diff --git a/server/views/account/show.jade b/server/views/account/show.jade index bee515fcff..184ffbe0e8 100644 --- a/server/views/account/show.jade +++ b/server/views/account/show.jade @@ -18,67 +18,51 @@ block content i.fa.fa-github | Update my profile from GitHub if (!user.twitter) - .col-xs-12 - a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/link/twitter') - i.fa.fa-twitter - | Add my Twitter to my profile + a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/link/twitter') + i.fa.fa-twitter + | Add my Twitter to my profile if (!user.facebook) - .col-xs-12 - a.btn.btn-lg.btn-block.btn-facebook.btn-link-social(href='/link/facebook') - i.fa.fa-facebook - | Add my Facebook to my profile + a.btn.btn-lg.btn-block.btn-facebook.btn-link-social(href='/link/facebook') + i.fa.fa-facebook + | Add my Facebook to my profile if (!user.linkedin) - .col-xs-12 - a.btn.btn-lg.btn-block.btn-linkedin.btn-link-social(href='/link/linkedin') - i.fa.fa-linkedin - | Add my LinkedIn to my profile + a.btn.btn-lg.btn-block.btn-linkedin.btn-link-social(href='/link/linkedin') + i.fa.fa-linkedin + | Add my LinkedIn to my profile if (!user.google) - .col-xs-12 - a.btn.btn-lg.btn-block.btn-google-plus.btn-link-social(href='/link/google') - i.fa.fa-google-plus - | Add my Google+ to my profile + a.btn.btn-lg.btn-block.btn-google-plus.btn-link-social(href='/link/google') + i.fa.fa-google-plus + | Add my Google+ to my profile .panel.panel-info .panel-heading.text-center h1 #{username}'s portfolio .panel-body - .row.text-center - .col-xs-12.col-sm-10.col-sm-offset-1 - a.btn.btn-big.btn-primary.btn-block(href="/account") Manage my account - .button-spacer - .col-xs-12.col-sm-10.col-sm-offset-1 - a.btn.btn-big.btn-success.btn-block(href="/signout") Sign out of Free Code Camp - .spacer .row - .col-xs-12 - .col-xs-12.col-sm-12.col-md-5 - if picture - img.img-center.img-responsive.public-profile-img(src=picture) - else - img.img-center.img-responsive.public-profile-img(src='https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png') - h1.text-center.negative-5.profile-social-icons - if (twitter) - a.fa.fa-twitter-square.text-primary(title="@#{username}'s Twitter Profile", href='https://twitter.com/' + twitter, target='_blank') - if (github) - a.fa.fa-github-square.text-primary(title="@#{username}'s GitHub Profile", href=github, target='_blank') - if (linkedin) - a.fa.fa-linkedin-square.text-primary(title="@#{username}'s LinkedIn Profile", href=linkedin, target='_blank') - if (facebook) - a.fa.fa-facebook-square.text-primary(title="@#{username}'s Facebook Profile", href='https://facebook.com/' + facebook, target='_blank') - if (google) - a.fa.fa-google-plus-square.text-primary(title="@#{username}'s Google Profile", href='https://plus.google.com/' + google, target='_blank') - .visible-md.visible-lg - .col-xs-12.col-sm-12.col-md-4.text-justify - h1.flat-top.wrappable= name - h3.flat-top.bolded.wrappable= location - .visible-xs.visible-sm - .col-xs-12.col-sm-12.col-md-4.text-center - h1.flat-top.wrappable= name - h3.flat-top.bolded.wrappable= location - .col-xs-12.col-sm-12.col-md-3.text-center - .background-svg.img-center - .points-on-top - = "[ " + (progressTimestamps.length) + " ]" + .col-xs-12.col-sm-10.col-sm-offset-1.col-md-8.col-md-offset-2.text-center + if picture + img.img-center.img-responsive.public-profile-img(src=picture) + else + img.img-center.img-responsive.public-profile-img(src='https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png') + h1.text-center.negative-5.profile-social-icons + if (twitter) + a.fa.fa-twitter-square.text-primary(title="@#{username}'s Twitter Profile", href='https://twitter.com/' + twitter, target='_blank') + if (github) + a.fa.fa-github-square.text-primary(title="@#{username}'s GitHub Profile", href=github, target='_blank') + if (linkedin) + a.fa.fa-linkedin-square.text-primary(title="@#{username}'s LinkedIn Profile", href=linkedin, target='_blank') + if (facebook) + a.fa.fa-facebook-square.text-primary(title="@#{username}'s Facebook Profile", href='https://facebook.com/' + facebook, target='_blank') + if (google) + a.fa.fa-google-plus-square.text-primary(title="@#{username}'s Google Profile", href='https://plus.google.com/' + google, target='_blank') + h1.flat-top.wrappable= name + h1.flat-top.wrappable= location + h1.flat-top.text-primary= "[ " + (progressTimestamps.length) + " ]" + if (user && user.username !== username) + a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/link/twitter') + i.fa.fa-plus-square + | Add them to my personal leaderboard + .spacer .hidden-xs.hidden-sm.col-md-12 #cal-heatmap.d3-centered @@ -113,36 +97,37 @@ block content h4.col-sm-6.text-left Current Streak: #{currentStreak} #{currentStreak + currentStreak === 1 ? ' day' : ' days'} - if (challenges.length > 0) - .col-sm-12 - table.table.table-striped - thead - tr - th.col-xs-4 Challenge - th.col-xs-2 Completed - th.col-xs-6 Link - for challenge in challenges - tr - td.col-xs-4 - a(href='/challenges/' + challenge.name, target='_blank')= challenge.name - td.col-xs-2= moment(challenge.completedDate, 'x').format("MMM DD, YYYY") - td.col-xs-6 - a(href=challenge.solution, target='_blank') View my solution - if (bonfires.length > 0) - .col-sm-12 - table.table.table-striped - thead - tr - th.col-xs-4 Bonfire - th.col-xs-2 Completed - th.col-xs-6 Solution - for bonfire in bonfires - tr - td.col-xs-4 - a(href='/challenges/' + bonfire.name, target='_blank')= bonfire.name - td.col-xs-2= moment(bonfire.completedDate, 'x').format("MMM DD, YYYY") - td.col-xs-6 - pre.wrappable= bonfire.solution + if (!user.lockdownMode) + if (challenges.length > 0) + .col-sm-12 + table.table.table-striped + thead + tr + th.col-xs-4 Project + th.col-xs-2 Completed + th.col-xs-6 Link + for challenge in challenges + tr + td.col-xs-4 + a(href='/challenges/' + challenge.name, target='_blank')= challenge.name + td.col-xs-2= moment(challenge.completedDate, 'x').format("MMM DD, YYYY") + td.col-xs-6 + a(href=challenge.solution, target='_blank') View my project + if (bonfires.length > 0) + .col-sm-12 + table.table.table-striped + thead + tr + th.col-xs-4 Bonfire + th.col-xs-2 Completed + th.col-xs-6 Solution + for bonfire in bonfires + tr + td.col-xs-4 + a(href='/challenges/' + bonfire.name, target='_blank')= bonfire.name + td.col-xs-2= moment(bonfire.completedDate, 'x').format("MMM DD, YYYY") + td.col-xs-6 + pre.wrappable= bonfire.solution if (user && user.username === username) .panel.panel-info From 27f231e72f7b69e1b4ba723724b0e2e5f3b8b9e9 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 27 Sep 2015 23:22:06 -0700 Subject: [PATCH 30/63] refactor tests to show same message when passing and failing --- client/commonFramework.js | 32 ++++----- client/less/main.less | 4 ++ seed/challenges/basic-bonfires.json | 92 +++++++++++++------------- server/views/coursewares/showHTML.jade | 2 +- 4 files changed, 64 insertions(+), 66 deletions(-) diff --git a/client/commonFramework.js b/client/commonFramework.js index 6e5bb4f2cf..f43ddc65fb 100644 --- a/client/commonFramework.js +++ b/client/commonFramework.js @@ -580,28 +580,22 @@ var createTestDisplay = function() { userTests.pop(); } for (var i = 0; i < userTests.length; i++) { - var test = userTests[i]; + var didTestPass = !userTests[i].err; + var testText = userTests[i].text.split('message: ').pop().replace(/\)|;|'/g, ''); var testDoc = document.createElement('div'); - if (test.err) { - console.log('Should be displaying bad tests'); + var iconClass = didTestPass ? + '"ion-checkmark-circled big-success-icon"' : + '"ion-close-circled big-error-icon"'; - $(testDoc).html( - "
" + - test.text + "
" + - test.err + "
" - ) - .appendTo($('#testSuite')); - - } else { - - $(testDoc).html( - "
" + - test.text + - "
" - ) - .appendTo($('#testSuite')); - } + $(testDoc).html( + "
" + + testText + + "
" + ) + .appendTo($('#testSuite')); } }; diff --git a/client/less/main.less b/client/less/main.less index e21023754e..7a7cbe8433 100644 --- a/client/less/main.less +++ b/client/less/main.less @@ -899,6 +899,10 @@ hr { color: @gray-light; } +code { + padding: 0; +} + @media only screen and (min-width: 993px) { .iframe-scroll { position: fixed !important; diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index e08a8b2a9d..e05978194a 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -89,8 +89,8 @@ "tests": [ "assert(typeof(factorialize(5)) === \"number\", 'factorialize() should return a number.');", "assert(factorialize(5) === 120, '5 should return 120.');", - "assert(factorialize(10) === 3628800, '10 should return 3,628,800.');", - "assert(factorialize(20) === 2432902008176640000, '20 should return 2,432,902,008,176,640,000.');", + "assert(factorialize(10) === 3628800, '10 should return 3,628,800.');", + "assert(factorialize(20) === 2432902008176640000, '20 should return 2,432,902,008,176,640,000.');", "assert(factorialize(0) === 1, '0 should return 1.');" ], "difficulty": "1.02", @@ -273,9 +273,9 @@ "largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);" ], "tests": [ - "assert(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]).constructor === Array, 'largestOfFour() should return an array.');", - "assert.deepEqual(largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]), [27,5,39,1001], '[[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]] should return [27,5,39,1001].');", - "assert.deepEqual(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]), [9,35,97,1000000], '[[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]] should return [9, 35, 97, 1000000].');" + "assert(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]).constructor === Array, 'message: largestOfFour() should return an array.');", + "assert.deepEqual(largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]), [27,5,39,1001], 'message: [[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]] should return [27,5,39,1001].');", + "assert.deepEqual(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]), [9,35,97,1000000], 'message: [[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]] should return [9, 35, 97, 1000000].');" ], "MDNlinks": [ "Comparison Operators" @@ -311,11 +311,11 @@ "end(\"Bastian\", \"n\", \"\");" ], "tests": [ - "assert(end(\"Bastian\", \"n\") === true, '\"Bastian\", \"n\" should return true.');", - "assert(end(\"Connor\", \"n\") === false, '\"Connor\", \"n\" 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, '\"He has to give me a new name\", \"name\" 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, '\"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.');" + "assert(end(\"Bastian\", \"n\") === true, '\"Bastian\", \"n\" should return true.');", + "assert(end(\"Connor\", \"n\") === false, '\"Connor\", \"n\" 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, '\"He has to give me a new name\", \"name\" 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, '\"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.');" ], "MDNlinks": [ "String.substr()" @@ -350,9 +350,9 @@ "repeat(\"abc\", 3, \"\");" ], "tests": [ - "assert(repeat(\"*\", 3) === \"***\", '\"*\", 3 should return \"***\".');", - "assert(repeat(\"abc\", 3) === \"abcabcabc\", '\"abc\", 3 should return \"abcabcabc\".');", - "assert(repeat(\"abc\", -2) === \"\", '\"abc\", -2 should return \"\".');" + "assert(repeat(\"*\", 3) === \"***\", '\"*\", 3 should return \"***\".');", + "assert(repeat(\"abc\", 3) === \"abcabcabc\", '\"abc\", 3 should return \"abcabcabc\".');", + "assert(repeat(\"abc\", -2) === \"\", '\"abc\", -2 should return \"\".');" ], "MDNlinks": [ "Global String Object" @@ -388,10 +388,10 @@ "truncate(\"A-tisket a-tasket A green and yellow basket\", 11, \"\");" ], "tests": [ - "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", '\"A-tisket a-tasket A green and yellow basket\", 1 should return \"A-tisket...\".');", - "assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", '\"Peter Piper picked a peck of pickled peppers\", 14 should return \"Peter Piper...\".');", - "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", '\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) should return \"A-tisket a-tasket A green and yellow basket\".');", - "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', '\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2 should return \"A-tisket a-tasket A green and yellow basket\".');" + "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", '\"A-tisket a-tasket A green and yellow basket\", 1 should return \"A-tisket...\".');", + "assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", '\"Peter Piper picked a peck of pickled peppers\", 14 should return \"Peter Piper...\".');", + "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", '\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) should return \"A-tisket a-tasket A green and yellow basket\".');", + "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', '\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2 should return \"A-tisket a-tasket A green and yellow basket\".');" ], "MDNlinks": [ "String.slice()" @@ -426,10 +426,10 @@ "chunk([\"a\", \"b\", \"c\", \"d\"], 2, \"\");" ], "tests": [ - "assert.deepEqual(chunk([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], '[\"a\", \"b\", \"c\", \"d\"], 2 should return [[\"a\", \"b\"], [\"c\", \"d\"]].');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], '[0, 1, 2, 3, 4, 5] should return [[0, 1, 2], [3, 4, 5]].');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 2), [[0, 1], [2, 3], [4, 5]], '[0, 1, 2, 3, 4, 5], 2 should return [[0, 1], [2, 3], [4, 5]].');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], '[0, 1, 2, 3, 4, 5], 4 should return [[0, 1, 2, 3], [4, 5]].');" + "assert.deepEqual(chunk([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], '[\"a\", \"b\", \"c\", \"d\"], 2 should return [[\"a\", \"b\"], [\"c\", \"d\"]].');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], '[0, 1, 2, 3, 4, 5] should return [[0, 1, 2], [3, 4, 5]].');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 2), [[0, 1], [2, 3], [4, 5]], '[0, 1, 2, 3, 4, 5], 2 should return [[0, 1], [2, 3], [4, 5]].');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], '[0, 1, 2, 3, 4, 5], 4 should return [[0, 1, 2, 3], [4, 5]].');" ], "MDNlinks": [ "Array.push()" @@ -464,9 +464,9 @@ "slasher([1, 2, 3], 2, \"\");" ], "tests": [ - "assert.deepEqual(slasher([1, 2, 3], 2), [3], '[1, 2, 3], 2, [3] should return [3].');", - "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], '[1, 2, 3], 0 should return [1, 2, 3].');", - "assert.deepEqual(slasher([1, 2, 3], 9), [], '[1, 2, 3], 9 should return [].');" + "assert.deepEqual(slasher([1, 2, 3], 2), [3], '[1, 2, 3], 2, [3] should return [3].');", + "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], '[1, 2, 3], 0 should return [1, 2, 3].');", + "assert.deepEqual(slasher([1, 2, 3], 9), [], '[1, 2, 3], 9 should return [].');" ], "MDNlinks": [ "Array.slice()", @@ -504,14 +504,14 @@ "mutation([\"hello\", \"hey\"], \"\");" ], "tests": [ - "assert(mutation([\"hello\", \"hey\"]) === false, '[\"hello\", \"hey\"] should return false.');", - "assert(mutation([\"hello\", \"Hello\"]) === true, '[\"hello\", \"Hello\"] should return true.');", - "assert(mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) === true, '[\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"] should return true.');", - "assert(mutation([\"Mary\", \"Army\"]) === true, '[\"Mary\", \"Army\"] should return true.');", - "assert(mutation([\"Mary\", \"Aarmy\"]) === true, '[\"Mary\", \"Aarmy\"] should return true.');", - "assert(mutation([\"Alien\", \"line\"]) === true, '[\"Alien\", \"line\"] should return true.');", - "assert(mutation([\"floor\", \"for\"]) === true, '[\"floor\", \"for\"] should return true.');", - "assert(mutation([\"hello\", \"neo\"]) === false, '[\"hello\", \"neo\"] should return false.');" + "assert(mutation([\"hello\", \"hey\"]) === false, '[\"hello\", \"hey\"] should return false.');", + "assert(mutation([\"hello\", \"Hello\"]) === true, '[\"hello\", \"Hello\"] should return true.');", + "assert(mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) === true, '[\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"] should return true.');", + "assert(mutation([\"Mary\", \"Army\"]) === true, '[\"Mary\", \"Army\"] should return true.');", + "assert(mutation([\"Mary\", \"Aarmy\"]) === true, '[\"Mary\", \"Aarmy\"] should return true.');", + "assert(mutation([\"Alien\", \"line\"]) === true, '[\"Alien\", \"line\"] should return true.');", + "assert(mutation([\"floor\", \"for\"]) === true, '[\"floor\", \"for\"] should return true.');", + "assert(mutation([\"hello\", \"neo\"]) === false, '[\"hello\", \"neo\"] should return false.');" ], "MDNlinks": [ "Array.indexOf()" @@ -547,9 +547,9 @@ "bouncer([7, \"ate\", \"\", false, 9], \"\");" ], "tests": [ - "assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], '[7, \"ate\", \"\", false, 9] should return [7, \"ate\", 9].');", - "assert.deepEqual(bouncer([\"a\", \"b\", \"c\"]), [\"a\", \"b\", \"c\"], '[\"a\", \"b\", \"c\"] should return [\"a\", \"b\", \"c\"].');", - "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, '']), [], '[false, null, 0] should return [].');" + "assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], '[7, \"ate\", \"\", false, 9] should return [7, \"ate\", 9].');", + "assert.deepEqual(bouncer([\"a\", \"b\", \"c\"]), [\"a\", \"b\", \"c\"], '[\"a\", \"b\", \"c\"] should return [\"a\", \"b\", \"c\"].');", + "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, '']), [], '[false, null, 0] should return [].');" ], "MDNlinks": [ "Boolean Objects", @@ -585,11 +585,11 @@ "destroyer([1, 2, 3, 1, 2, 3], 2, 3, \"\");" ], "tests": [ - "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], '[1, 2, 3, 1, 2, 3], 2, 3 should return [1, 1].');", - "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], '[1, 2, 3, 5, 1, 2, 3], 2, 3 should return [1, 5, 1].');", - "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], '[3, 5, 1, 2, 2], 2, 3, 5 should return [1].');", - "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], '[2, 3, 2, 3], 2, 3 should return [].');", - "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], '[\"tree\", \"hamburger\", 53], \"tree\", 53) should return [\"hamburger\"].');" + "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], '[1, 2, 3, 1, 2, 3], 2, 3 should return [1, 1].');", + "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], '[1, 2, 3, 5, 1, 2, 3], 2, 3 should return [1, 5, 1].');", + "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], '[3, 5, 1, 2, 2], 2, 3, 5 should return [1].');", + "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], '[2, 3, 2, 3], 2, 3 should return [].');", + "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], '[\"tree\", \"hamburger\", 53], \"tree\", 53) should return [\"hamburger\"].');" ], "MDNlinks": [ "Arguments object", @@ -629,12 +629,12 @@ "Array.sort()" ], "tests": [ - "assert(where([10, 20, 30, 40, 50], 35) === 3, '[10, 20, 30, 40, 50], 35 should return 3.');", - "assert(where([10, 20, 30, 40, 50], 30) === 2, '[10, 20, 30, 40, 50], 30) should return 2.');", - "assert(where([40, 60], 50) === 1, '[40, 60,], 50 should return 1.');", - "assert(where([5, 3, 20, 3], 3) === 0, '[5, 3, 20, 3], 3 should return 0.');", - "assert(where([2, 20, 10], 1) === 0, '[2, 20, 10], 1 should return 0.');", - "assert(where([2, 5, 10], 15) === 3, '[2, 5, 10], 15 should return 3.');" + "assert(where([10, 20, 30, 40, 50], 35) === 3, '[10, 20, 30, 40, 50], 35 should return 3.');", + "assert(where([10, 20, 30, 40, 50], 30) === 2, '[10, 20, 30, 40, 50], 30) should return 2.');", + "assert(where([40, 60], 50) === 1, '[40, 60,], 50 should return 1.');", + "assert(where([5, 3, 20, 3], 3) === 0, '[5, 3, 20, 3], 3 should return 0.');", + "assert(where([2, 20, 10], 1) === 0, '[2, 20, 10], 1 should return 0.');", + "assert(where([2, 5, 10], 15) === 3, '[2, 5, 10], 15 should return 3.');" ], "type": "bonfire", "challengeType": 5, diff --git a/server/views/coursewares/showHTML.jade b/server/views/coursewares/showHTML.jade index 3ebe1a19ff..f08d6997dc 100644 --- a/server/views/coursewares/showHTML.jade +++ b/server/views/coursewares/showHTML.jade @@ -52,7 +52,7 @@ block content script. var userLoggedIn = false; .button-spacer - ul#testSuite.list-group + #testSuite br script(type="text/javascript"). $('#next-courseware-button').attr('disabled', 'disabled'); From 5fc97da3c3e186754e2d2ee5b299c1a21df48fcf Mon Sep 17 00:00:00 2001 From: Aniruddh Agarwal Date: Mon, 21 Sep 2015 22:01:10 +0800 Subject: [PATCH 31/63] Add test HTML5 waypoint to make it stricter - Added a test to the "Nest an Anchor Element within a Paragraph" waypoint. The text 'View more' must now be outside the tags. --- seed/challenges/html5-and-css.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seed/challenges/html5-and-css.json b/seed/challenges/html5-and-css.json index 051b6764c7..d865ce2d56 100644 --- a/seed/challenges/html5-and-css.json +++ b/seed/challenges/html5-and-css.json @@ -1142,7 +1142,8 @@ "assert($(\"a\").text().match(/cat\\sphotos/gi), 'Your a element should have the anchor text of \"cat photos\"')", "assert($(\"p\") && $(\"p\").length > 2, 'Create a new p element around your a element.')", "assert($(\"a[href=\\\"http://www.freecatphotoapp.com\\\"]\").parent().is(\"p\"), 'Your a element should be nested within your new p element.')", - "assert($(\"p\").text().match(/View\\smore/gi), 'Your p element should have the text \"View more\".')", + "assert($(\"p\").text().match(/^View\\smore\\s/gi), 'Your p element should have the text \"View more \" (with a space after it).')", + "assert(!$(\"a\").text().match(/View\\smore/gi), 'Your a element should not have the text \"View more\".')", "assert(editor.match(/<\\/p>/g) && editor.match(/

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

p elements has a closing tag.')", "assert(editor.match(/<\\/a>/g) && editor.match(//g).length === editor.match(/a elements has a closing tag.')" ], From 91efd5940d733b377f49b3cf7c0afcd37f651463 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 22 Sep 2015 13:17:48 -0700 Subject: [PATCH 32/63] add facebook sharing to map on completed challenges remove twitter share from non-bonfire challenges --- client/main.js | 53 +++++++++++++++++++++++++ server/views/challengeMap/show.jade | 9 ++++- server/views/coursewares/showJS.jade | 4 -- server/views/coursewares/showVideo.jade | 6 --- 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/client/main.js b/client/main.js index 6e6ce8c696..5128ddb5e4 100644 --- a/client/main.js +++ b/client/main.js @@ -1,3 +1,29 @@ +var mapShareKey = 'map-shares'; + +function getMapShares() { + var alreadyShared = JSON.parse(localStorage.getItem(mapShareKey) || '[]'); + if (!alreadyShared || !Array.isArray(alreadyShared)) { + localStorage.setItem(mapShareKey, JSON.stringify([])); + alreadyShared = []; + } + return alreadyShared; +} + +function setMapShare(id) { + var alreadyShared = getMapShares(); + var found = false; + alreadyShared.forEach(function(_id) { + if (_id === id) { + found = true; + } + }); + if (!found) { + alreadyShared.push(id); + } + localStorage.setItem(mapShareKey, JSON.stringify(alreadyShared)); + return alreadyShared; +} + $(document).ready(function() { var challengeName = typeof challengeName !== 'undefined' ? @@ -383,6 +409,33 @@ $(document).ready(function() { } }, false); } + + + // map sharing + var alreadyShared = getMapShares(); + alreadyShared.map(function(id) { + // find share button div and hide as camper has already shared + $('div[id="' + id + '"]').parent().parent().hide(); + }); + + // on map view + $('.map-challenge-block-share').on('click', function(e) { + e.preventDefault(); + var challengeBlockName = $(this).children().attr('id'); + var challengeBlockEscapedName = challengeBlockName.replace(/\s/, '%20'); + + var link = 'https://www.facebook.com/dialog/feed?' + + 'app_id=1644598365767721' + + '&display=page&' + + 'caption=I%20just%20completed%20' + + challengeBlockEscapedName + + '%20on%20Free%20Code%20Camp' + + '&link=http%3A%2F%2Ffreecodecamp.com' + + '&redirect_uri=http://freecodecamp.com/map'; + + setMapShare(challengeBlockName); + window.location.href = link; + }); }); function defCheck(a){ diff --git a/server/views/challengeMap/show.jade b/server/views/challengeMap/show.jade index 11d14bceee..a7408ada09 100644 --- a/server/views/challengeMap/show.jade +++ b/server/views/challengeMap/show.jade @@ -131,7 +131,14 @@ block content span= challenge.title span.sr-only= " Incomplete" - //#announcementModal.modal(tabindex='-1') + if (challengeBlock.completed === 100) + .button-spacer + .row + .col-xs-12.col-sm-8.col-md-6.col-sm-offset-3.col-md-offset-2 + a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete! Tell your friends. + .hidden(id="#{challengeBlock.name}") + + // #announcementModal.modal(tabindex='-1') // .modal-dialog.animated.fadeInUp.fast-animation // .modal-content // .modal-header.challenge-list-header Add us to your LinkedIn profile diff --git a/server/views/coursewares/showJS.jade b/server/views/coursewares/showJS.jade index 03d6b823e1..f4621b5b28 100644 --- a/server/views/coursewares/showJS.jade +++ b/server/views/coursewares/showJS.jade @@ -94,10 +94,6 @@ block content .row if (user) #submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter) - if (user.progressTimestamps.length > 2) - a.btn.btn-lg.btn-block.btn-twitter(target="_blank", href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{dashedName}&hashtags=LearnToCode, JavaScript") - i.fa.fa-twitter   - = phrase else a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge include ../partials/challenge-modals diff --git a/server/views/coursewares/showVideo.jade b/server/views/coursewares/showVideo.jade index 30ad2d5f1a..bd7f42e5ed 100644 --- a/server/views/coursewares/showVideo.jade +++ b/server/views/coursewares/showVideo.jade @@ -69,12 +69,6 @@ block content a.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf) I've completed this challenge (ctrl + enter) script. $('#complete-courseware-editorless-dialog').bind('keypress', modalControlEnterHandler); - - if (user.progressTimestamps.length > 2) - .button-spacer - a.btn.btn-lg.btn-block.btn-twitter(href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{dashedName}&hashtags=LearnToCode, JavaScript" target="_blank") - i.fa.fa-twitter   - = phrase else a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) I've completed this challenge (ctrl + enter) script. From 1ff55374dbd2b56bc9b4cfceb3a0afb86b676865 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 28 Sep 2015 19:04:44 -0700 Subject: [PATCH 33/63] improve facebook sharing copy --- client/main.js | 11 ++++++----- server/views/challengeMap/show.jade | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/client/main.js b/client/main.js index 5128ddb5e4..47a9905394 100644 --- a/client/main.js +++ b/client/main.js @@ -423,16 +423,17 @@ $(document).ready(function() { e.preventDefault(); var challengeBlockName = $(this).children().attr('id'); var challengeBlockEscapedName = challengeBlockName.replace(/\s/, '%20'); + var username = typeof window.username !== "undefined" ? window.username : ""; var link = 'https://www.facebook.com/dialog/feed?' + 'app_id=1644598365767721' + '&display=page&' + - 'caption=I%20just%20completed%20' + + 'caption=I%20just%20completed%20the%20' + challengeBlockEscapedName + - '%20on%20Free%20Code%20Camp' + - '&link=http%3A%2F%2Ffreecodecamp.com' + - '&redirect_uri=http://freecodecamp.com/map'; - + '%20section%20on%20Free%20Code%20Camp%2E%20Check%20out%20my%20portfolio%20so%20far%2E' + + '&link=http%3A%2F%2Ffreecodecamp%2Ecom%2F' + + username + + '&redirect_uri=http%3A%2F%2Ffreecodecamp%2Ecom%2Fmap'; setMapShare(challengeBlockName); window.location.href = link; }); diff --git a/server/views/challengeMap/show.jade b/server/views/challengeMap/show.jade index a7408ada09..4ac3064426 100644 --- a/server/views/challengeMap/show.jade +++ b/server/views/challengeMap/show.jade @@ -135,9 +135,10 @@ block content .button-spacer .row .col-xs-12.col-sm-8.col-md-6.col-sm-offset-3.col-md-offset-2 - a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete! Tell your friends. + a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete. Share your Portfolio with your friends. .hidden(id="#{challengeBlock.name}") - + script. + var username = !{JSON.stringify(user && user.username || "")}; // #announcementModal.modal(tabindex='-1') // .modal-dialog.animated.fadeInUp.fast-animation // .modal-content From 6a5bea67f7cb1d47050669a7a412d35f0a3341dc Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 28 Sep 2015 19:20:29 -0700 Subject: [PATCH 34/63] set last completed block in map view --- server/boot/challenge.js | 10 +++++++++- server/views/challengeMap/show.jade | 3 ++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/server/boot/challenge.js b/server/boot/challenge.js index 15736e3a51..239d21d4d0 100644 --- a/server/boot/challenge.js +++ b/server/boot/challenge.js @@ -471,6 +471,7 @@ module.exports = function(app) { } function challengeMap({ user = {} }, res, next) { + let lastCompleted; const daysRunning = moment().diff(new Date('10/15/2014'), 'days'); // if user @@ -513,7 +514,13 @@ module.exports = function(app) { }) .filter(({ name }) => name !== 'Hikes') // turn stream of blocks into a stream of an array - .toArray(); + .toArray() + .doOnNext((blocks) => { + const lastCompletedBlock = _.findLast(blocks, (block) => { + return block.completed === 100; + }); + lastCompleted = lastCompletedBlock.name; + }); Observable.combineLatest( camperCount$, @@ -526,6 +533,7 @@ module.exports = function(app) { blocks, daysRunning, camperCount, + lastCompleted, title: "A map of all Free Code Camp's Challenges" }); }, diff --git a/server/views/challengeMap/show.jade b/server/views/challengeMap/show.jade index 4ac3064426..21515a3613 100644 --- a/server/views/challengeMap/show.jade +++ b/server/views/challengeMap/show.jade @@ -138,7 +138,8 @@ block content a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete. Share your Portfolio with your friends. .hidden(id="#{challengeBlock.name}") script. - var username = !{JSON.stringify(user && user.username || "")}; + var username = !{JSON.stringify(user && user.username || '')}; + var lastCompleted = !{JSON.stringify(lastCompleted || false)} // #announcementModal.modal(tabindex='-1') // .modal-dialog.animated.fadeInUp.fast-animation // .modal-content From c7d68932ce8f1763e89b5e375333703bd1c729ce Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 28 Sep 2015 19:47:45 -0700 Subject: [PATCH 35/63] Show share button from last completed --- client/main.js | 22 ++++++++++++++++------ server/views/challengeMap/show.jade | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/client/main.js b/client/main.js index 47a9905394..bdde23f436 100644 --- a/client/main.js +++ b/client/main.js @@ -1,4 +1,7 @@ var mapShareKey = 'map-shares'; +var lastCompleted = typeof lastCompleted !== 'undefined' ? + lastCompleted : + ''; function getMapShares() { var alreadyShared = JSON.parse(localStorage.getItem(mapShareKey) || '[]'); @@ -413,27 +416,34 @@ $(document).ready(function() { // map sharing var alreadyShared = getMapShares(); - alreadyShared.map(function(id) { - // find share button div and hide as camper has already shared - $('div[id="' + id + '"]').parent().parent().hide(); - }); + + if (lastCompleted && alreadyShared.indexOf(lastCompleted) === -1) { + $('div[id="' + lastCompleted + '"]') + .parent() + .parent() + .removeClass('hidden'); + } // on map view $('.map-challenge-block-share').on('click', function(e) { e.preventDefault(); var challengeBlockName = $(this).children().attr('id'); var challengeBlockEscapedName = challengeBlockName.replace(/\s/, '%20'); - var username = typeof window.username !== "undefined" ? window.username : ""; + var username = typeof window.username !== 'undefined' ? + window.username : + ''; var link = 'https://www.facebook.com/dialog/feed?' + 'app_id=1644598365767721' + '&display=page&' + 'caption=I%20just%20completed%20the%20' + challengeBlockEscapedName + - '%20section%20on%20Free%20Code%20Camp%2E%20Check%20out%20my%20portfolio%20so%20far%2E' + + '%20section%20on%20Free%20Code%20Camp%2E%20Check%20out' + + '%20my%20portfolio%20so%20far%2E' + '&link=http%3A%2F%2Ffreecodecamp%2Ecom%2F' + username + '&redirect_uri=http%3A%2F%2Ffreecodecamp%2Ecom%2Fmap'; + setMapShare(challengeBlockName); window.location.href = link; }); diff --git a/server/views/challengeMap/show.jade b/server/views/challengeMap/show.jade index 21515a3613..42fa90422b 100644 --- a/server/views/challengeMap/show.jade +++ b/server/views/challengeMap/show.jade @@ -134,7 +134,7 @@ block content if (challengeBlock.completed === 100) .button-spacer .row - .col-xs-12.col-sm-8.col-md-6.col-sm-offset-3.col-md-offset-2 + .col-xs-12.col-sm-8.col-md-6.col-sm-offset-3.col-md-offset-2.hidden a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete. Share your Portfolio with your friends. .hidden(id="#{challengeBlock.name}") script. From 1a653182e7dafd08183189f7ef8b316f104e1f10 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 28 Sep 2015 19:55:58 -0700 Subject: [PATCH 36/63] add messages to basic and advanced bonfires --- seed/challenges/advanced-bonfires.json | 104 +++++++++--------- seed/challenges/basic-bonfires.json | 146 ++++++++++++------------- 2 files changed, 125 insertions(+), 125 deletions(-) diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index 04ff5d7f5e..b186b9290d 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -19,28 +19,28 @@ "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." ], "tests": [ - "assert.isBoolean(telephoneCheck(\"555-555-5555\") === 'should return a boolean.');", - "assert(telephoneCheck(\"1 555-555-5555\") === true, '1 555-555-5555 should return true.');", - "assert(telephoneCheck(\"1 (555) 555-5555\") === true, '1 (555) 555-5555 should return true.');", - "assert(telephoneCheck(\"5555555555\") === true, '5555555555 should return true.');", - "assert(telephoneCheck(\"555-555-5555\") === true, '555-555-5555 should return true.');", - "assert(telephoneCheck(\"(555)555-5555\") === true, '(555)555-5555 should return true.');", - "assert(telephoneCheck(\"1(555)555-5555\") === true, '1(555)555-5555 should return true.');", - "assert(telephoneCheck(\"1 555 555 5555\") === true, '1 555 555 5555 should return true.');", - "assert(telephoneCheck(\"555-555-5555\") === true, '555-555-5555 should return true.');", - "assert(telephoneCheck(\"1 456 789 4444\") === true, '1 456 789 4444 should return true.');", - "assert(telephoneCheck(\"123**&!!asdf#\") === false, '123**&!!asdf# should return false.');", - "assert(telephoneCheck(\"55555555\") === false, '55555555 should return false.');", - "assert(telephoneCheck(\"(6505552368)\") === false, '(6505552368) should return false');", - "assert(telephoneCheck(\"2 (757) 622-7382\") === false, '2 (757) 622-7382 should return false.');", - "assert(telephoneCheck(\"0 (757) 622-7382\") === false, '0 (757) 622-7382 should return false.');", - "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, '-1 (757) 622-7382 should return false');", - "assert(telephoneCheck(\"2 757 622-7382\") === false, '2 757 622-7382 should return false.');", - "assert(telephoneCheck(\"10 (757) 622-7382\") === false, '10 (757) 622-7382 should return false.');", - "assert(telephoneCheck(\"27576227382\") === false, '27576227382 should return false.');", - "assert(telephoneCheck(\"(275)76227382\") === false, '(275)76227382 should return false.');", - "assert(telephoneCheck(\"2(757)6227382\") === false, '2(757)6227382 should return false.');", - "assert(telephoneCheck(\"2(757)622-7382\") === false, '2(757)622-7382 should return false.');" + "assert.isBoolean(telephoneCheck(\"555-555-5555\"), 'message: should return a boolean.');", + "assert(telephoneCheck(\"1 555-555-5555\") === true, 'message: 1 555-555-5555 should return true.');", + "assert(telephoneCheck(\"1 (555) 555-5555\") === true, 'message: 1 (555) 555-5555 should return true.');", + "assert(telephoneCheck(\"5555555555\") === true, 'message: 5555555555 should return true.');", + "assert(telephoneCheck(\"555-555-5555\") === true, 'message: 555-555-5555 should return true.');", + "assert(telephoneCheck(\"(555)555-5555\") === true, 'message: (555)555-5555 should return true.');", + "assert(telephoneCheck(\"1(555)555-5555\") === true, 'message: 1(555)555-5555 should return true.');", + "assert(telephoneCheck(\"1 555 555 5555\") === true, 'message: 1 555 555 5555 should return true.');", + "assert(telephoneCheck(\"555-555-5555\") === true, 'message: 555-555-5555 should return true.');", + "assert(telephoneCheck(\"1 456 789 4444\") === true, 'message: 1 456 789 4444 should return true.');", + "assert(telephoneCheck(\"123**&!!asdf#\") === false, 'message: 123**&!!asdf# should return false.');", + "assert(telephoneCheck(\"55555555\") === false, 'message: 55555555 should return false.');", + "assert(telephoneCheck(\"(6505552368)\") === false, 'message: (6505552368) should return false');", + "assert(telephoneCheck(\"2 (757) 622-7382\") === false, 'message: 2 (757) 622-7382 should return false.');", + "assert(telephoneCheck(\"0 (757) 622-7382\") === false, 'message: 0 (757) 622-7382 should return false.');", + "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, 'message: -1 (757) 622-7382 should return false');", + "assert(telephoneCheck(\"2 757 622-7382\") === false, 'message: 2 757 622-7382 should return false.');", + "assert(telephoneCheck(\"10 (757) 622-7382\") === false, 'message: 10 (757) 622-7382 should return false.');", + "assert(telephoneCheck(\"27576227382\") === false, 'message: 27576227382 should return false.');", + "assert(telephoneCheck(\"(275)76227382\") === false, 'message: (275)76227382 should return false.');", + "assert(telephoneCheck(\"2(757)6227382\") === false, 'message: 2(757)6227382 should return false.');", + "assert(telephoneCheck(\"2(757)622-7382\") === false, 'message: 2(757)622-7382 should return false.');" ], "challengeSeed": [ "function telephoneCheck(str) {", @@ -85,10 +85,10 @@ "sym([1, 2, 3], [5, 2, 1, 4]);" ], "tests": [ - "assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 5, 4], '[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], '[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], '[1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5] should return [1, 4, 5].');", - "assert.sameMembers(sym([1, 1]), [1], '[1, 1] should return [1].');" + "assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 5, 4], 'message: [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: [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: [1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5] should return [1, 4, 5].');", + "assert.sameMembers(sym([1, 1]), [1], 'message: [1, 1] should return [1].');" ], "MDNlinks": [ "Array.reduce()", @@ -139,13 +139,13 @@ "drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]);" ], "tests": [ - "assert.isArray(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), 'should return an array.');", - "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'should return a string.');", - "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'should return a string.');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'return correct change');", - "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04] ], 'return correct change with multiple coins and bills');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'insufficient funds');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'cash-in-drawer equals change');" + "assert.isArray(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), 'message: 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]] should return an array.');", + "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'message: 19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]] should return a string.');", + "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'message: 19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]] should return a string.');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'message: 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]]) should return [['QUARTER', 0.50]].');", + "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04]], 'message: 3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]] should return [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04]].');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'message: 19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]] should return \"Insufficient Funds\".');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'message: 19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]] should return \"Closed\".');" ], "MDNlinks": [ "Global Object" @@ -195,12 +195,12 @@ "inventory(curInv, newInv);" ], "tests": [ - "assert.isArray(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), 'should return an array.');", - "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6, 'should return an array with a length of 6.');", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']]);", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']]);", - "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']]);", - "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']]);" + "assert.isArray(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), 'message: inventory() should return an array.');", + "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6, 'message: inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length should return an array with a length of 6.');", + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']], 'message: [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']] should return [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']].');", + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], 'message: [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [] should return [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']].);", + "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']], 'message: [], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']] should return [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']].');", + "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']], 'message: [[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']] should return [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']].');" ], "MDNlinks": [ "Global Array Object" @@ -235,13 +235,13 @@ "permAlone('aab');" ], "tests": [ - "assert.isNumber(permAlone('aab'), 'aab should return a number.');", - "assert.strictEqual(permAlone('aab'), 2, 'aab should return 2.');", - "assert.strictEqual(permAlone('aaa'), 0, 'aaa should return 0.');", - "assert.strictEqual(permAlone('aabb'), 8, 'aabb should return 8.');", - "assert.strictEqual(permAlone('abcdefa'), 3600, 'abcdefa should return 3600.');", - "assert.strictEqual(permAlone('abfdefa'), 2640, 'abfdefa should return 2640.');", - "assert.strictEqual(permAlone('zzzzzzzz'), 0, 'zzzzzzzz should return 0.');" + "assert.isNumber(permAlone('aab'), 'message: aab should return a number.');", + "assert.strictEqual(permAlone('aab'), 2, 'message: aab should return 2.');", + "assert.strictEqual(permAlone('aaa'), 0, 'message: aaa should return 0.');", + "assert.strictEqual(permAlone('aabb'), 8, 'message: aabb should return 8.');", + "assert.strictEqual(permAlone('abcdefa'), 3600, 'message: abcdefa should return 3600.');", + "assert.strictEqual(permAlone('abfdefa'), 2640, 'message: abfdefa should return 2640.');", + "assert.strictEqual(permAlone('zzzzzzzz'), 0, 'message: zzzzzzzz should return 0.');" ], "MDNlinks": [ "Permutations", @@ -281,12 +281,12 @@ "friendly(['2015-07-01', '2015-07-04']);" ], "tests": [ - "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], '[\"2015-07-01\", \"2015-07-04\"] should return [\"July 1st\",\"4th\"].');", - "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], '[\"2015-12-01\", \"2016-02-03\"] should return [\"December 1st\",\"February 3rd\"].');", - "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017'], '[\"2015-12-01\", \"2017-02-03\"] should return [\"December 1st, 2015\",\"February 3rd, 2017\"].');", - "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th'], '[\"2016-03-01\", \"2016-05-05\"] should return [\"March 1st\",\"May 5th\"]');", - "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], '[\"2017-01-01\", \"2017-01-01\"] should return [\"January 1st, 2017\"].');", - "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023'], '[\"2022-09-05\", \"2023-09-04\"] should return [\"September 5th, 2022\",\"September 4th, 2023\"].');" + "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'message: [\"2015-07-01\", \"2015-07-04\"] should return [\"July 1st\",\"4th\"].');", + "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'message: [\"2015-12-01\", \"2016-02-03\"] should return [\"December 1st\",\"February 3rd\"].');", + "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017'], 'message: [\"2015-12-01\", \"2017-02-03\"] should return [\"December 1st, 2015\",\"February 3rd, 2017\"].');", + "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th'], 'message: [\"2016-03-01\", \"2016-05-05\"] should return [\"March 1st\",\"May 5th\"]');", + "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'message: [\"2017-01-01\", \"2017-01-01\"] should return [\"January 1st, 2017\"].');", + "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023'], 'message: [\"2022-09-05\", \"2023-09-04\"] should return [\"September 5th, 2022\",\"September 4th, 2023\"].');" ], "MDNlinks": [ "String.split()", diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index e05978194a..f94842ebaa 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -13,8 +13,8 @@ "Make this function return true no matter what." ], "tests": [ - "assert(typeof(meetBonfire()) === \"boolean\", 'The result should be a Boolean value of true or false.');", - "assert(meetBonfire() === true, 'Your meetBonfire() function should return true.');" + "assert(typeof(meetBonfire()) === \"boolean\", 'message: The result should be a Boolean value of true or false.');", + "assert(meetBonfire() === true, 'message: Your meetBonfire() function should return true.');" ], "challengeSeed": [ "function meetBonfire(argument) {", @@ -46,10 +46,10 @@ "title": "Reverse a String", "difficulty": "1.01", "tests": [ - "assert(typeof(reverseString(\"hello\")) === \"string\", 'reverseString() should return a string.');", - "assert(reverseString(\"hello\") === \"olleh\", '\"hello\" should become \"olleh\".');", - "assert(reverseString(\"Howdy\") === \"ydwoH\", '\"Howdy\" should become \"ydwoH\".');", - "assert(reverseString(\"Greetings from Earth\") === \"htraE morf sgniteerG\", '\"Greetings from Earth\" should return \"htraE morf sgniteerG\".');" + "assert(typeof(reverseString(\"hello\")) === \"string\", 'message: reverseString() should return a string.');", + "assert(reverseString(\"hello\") === \"olleh\", 'message: \"hello\" should become \"olleh\".');", + "assert(reverseString(\"Howdy\") === \"ydwoH\", 'message: \"Howdy\" should become \"ydwoH\".');", + "assert(reverseString(\"Greetings from Earth\") === \"htraE morf sgniteerG\", 'message: \"Greetings from Earth\" should return \"htraE morf sgniteerG\".');" ], "description": [ "Reverse the provided string.", @@ -87,11 +87,11 @@ "id": "a302f7aae1aa3152a5b413bc", "title": "Factorialize a Number", "tests": [ - "assert(typeof(factorialize(5)) === \"number\", 'factorialize() should return a number.');", - "assert(factorialize(5) === 120, '5 should return 120.');", - "assert(factorialize(10) === 3628800, '10 should return 3,628,800.');", - "assert(factorialize(20) === 2432902008176640000, '20 should return 2,432,902,008,176,640,000.');", - "assert(factorialize(0) === 1, '0 should return 1.');" + "assert(typeof(factorialize(5)) === \"number\", 'message: factorialize() should return a number.');", + "assert(factorialize(5) === 120, 'message: 5 should return 120.');", + "assert(factorialize(10) === 3628800, 'message: 10 should return 3,628,800.');", + "assert(factorialize(20) === 2432902008176640000, 'message: 20 should return 2,432,902,008,176,640,000.');", + "assert(factorialize(0) === 1, 'message: 0 should return 1.');" ], "difficulty": "1.02", "description": [ @@ -136,17 +136,17 @@ "Remember to use Read-Search-Ask if you get stuck. Write your own code." ], "tests": [ - "assert(typeof(palindrome(\"eye\")) === \"boolean\", 'palindrome() should return a boolean.');", - "assert(palindrome(\"eye\") === true, '\"eye\" should return true.');", - "assert(palindrome(\"race car\") === true, '\"race car\" should return true.');", - "assert(palindrome(\"not a palindrome\") === false, '\"not a palindrome\" should return false.');", - "assert(palindrome(\"A man, a plan, a canal. Panama\") === true, '\"A man, a plan, a canal. Panama\" should return true.');", - "assert(palindrome(\"never odd or even\") === true, '\"never odd or even\" should return true.');", - "assert(palindrome(\"nope\") === false, '\"nope\" should return false.');", - "assert(palindrome(\"almostomla\") === false, '\"almostomla\" should return false.');", - "assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, '\"My age is 0, 0 si ega ym.\" should return true.');", - "assert(palindrome(\"1 eye for of 1 eye.\") === false, '\"1 eye for of 1 eye.\" should return false.');", - "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, '\"0_0 (: /-\\\\ :) 0-0\" should return true.');" + "assert(typeof(palindrome(\"eye\")) === \"boolean\", 'message: palindrome() should return a boolean.');", + "assert(palindrome(\"eye\") === true, 'message: \"eye\" should return true.');", + "assert(palindrome(\"race car\") === true, 'message: \"race car\" should return true.');", + "assert(palindrome(\"not a palindrome\") === false, 'message: \"not a palindrome\" should return false.');", + "assert(palindrome(\"A man, a plan, a canal. Panama\") === true, 'message: \"A man, a plan, a canal. Panama\" should return true.');", + "assert(palindrome(\"never odd or even\") === true, 'message: \"never odd or even\" should return true.');", + "assert(palindrome(\"nope\") === false, 'message: \"nope\" should return false.');", + "assert(palindrome(\"almostomla\") === false, 'message: \"almostomla\" should return false.');", + "assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, 'message: \"My age is 0, 0 si ega ym.\" should return true.');", + "assert(palindrome(\"1 eye for of 1 eye.\") === false, 'message: \"1 eye for of 1 eye.\" should return false.');", + "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, 'message: \"0_0 (: /-\\\\ :) 0-0\" should return true.');" ], "challengeSeed": [ "function palindrome(str) {", @@ -192,12 +192,12 @@ "findLongestWord(\"The quick brown fox jumped over the lazy dog\");" ], "tests": [ - "assert(typeof(findLongestWord(\"The quick brown fox jumped over the lazy dog\")) === \"number\", 'findLongestWord() should return a number.');", - "assert(findLongestWord(\"The quick brown fox jumped over the lazy dog\") === 6, '\"The quick brown fox jumped over the lazy dog\" should return 6.');", - "assert(findLongestWord(\"May the force be with you\") === 5, '\"May the force be with you\" should return 5.');", - "assert(findLongestWord(\"Google do a barrel roll\") === 6, '\"Google do a barrel roll\" should return 6.');", - "assert(findLongestWord(\"What is the average airspeed velocity of an unladen swallow\") === 8, '\"What is the average airspeed velocity of an unladen swallow\" should return 8.');", - "assert(findLongestWord(\"What if we try a super-long word such as otorhinolaryngology\") === 19, '\"What if we try a super-long word such as otorhinolaryngology\" should return 19.');" + "assert(typeof(findLongestWord(\"The quick brown fox jumped over the lazy dog\")) === \"number\", 'message: findLongestWord() should return a number.');", + "assert(findLongestWord(\"The quick brown fox jumped over the lazy dog\") === 6, 'message: \"The quick brown fox jumped over the lazy dog\" should return 6.');", + "assert(findLongestWord(\"May the force be with you\") === 5, 'message: \"May the force be with you\" should return 5.');", + "assert(findLongestWord(\"Google do a barrel roll\") === 6, 'message: \"Google do a barrel roll\" should return 6.');", + "assert(findLongestWord(\"What is the average airspeed velocity of an unladen swallow\") === 8, 'message: \"What is the average airspeed velocity of an unladen swallow\" should return 8.');", + "assert(findLongestWord(\"What if we try a super-long word such as otorhinolaryngology\") === 19, 'message: \"What if we try a super-long word such as otorhinolaryngology\" should return 19.');" ], "MDNlinks": [ "String.split()", @@ -233,10 +233,10 @@ "titleCase(\"I'm a little tea pot\", \"\");" ], "tests": [ - "assert(typeof(titleCase(\"I'm a little tea pot\")) === \"string\", 'titleCase() should return a string.');", - "assert(titleCase(\"I'm a little tea pot\") === \"I'm A Little Tea Pot\", '\"I'm a little tea pot\" should return \"I'm A Little Tea Pot\".');", - "assert(titleCase(\"sHoRt AnD sToUt\") === \"Short And Stout\", '\"sHoRt AnD sToUt\" should return \"Short And Stout\".');", - "assert(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\") === \"Here Is My Handle Here Is My Spout\", '\"HERE IS MY HANDLE HERE IS MY SPOUT\" should return \"Here Is My Handle Here Is My Spout\"');" + "assert(typeof(titleCase(\"I'm a little tea pot\")) === \"string\", 'message: titleCase() should return a string.');", + "assert(titleCase(\"I'm a little tea pot\") === \"I'm A Little Tea Pot\", 'message: \"I'm a little tea pot\" should return \"I'm A Little Tea Pot\".');", + "assert(titleCase(\"sHoRt AnD sToUt\") === \"Short And Stout\", 'message: \"sHoRt AnD sToUt\" should return \"Short And Stout\".');", + "assert(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\") === \"Here Is My Handle Here Is My Spout\", 'message: \"HERE IS MY HANDLE HERE IS MY SPOUT\" should return \"Here Is My Handle Here Is My Spout\"');" ], "MDNlinks": [ "String.charAt()" @@ -311,11 +311,11 @@ "end(\"Bastian\", \"n\", \"\");" ], "tests": [ - "assert(end(\"Bastian\", \"n\") === true, '\"Bastian\", \"n\" should return true.');", - "assert(end(\"Connor\", \"n\") === false, '\"Connor\", \"n\" 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, '\"He has to give me a new name\", \"name\" 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, '\"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.');" + "assert(end(\"Bastian\", \"n\") === true, 'message: \"Bastian\", \"n\" should return true.');", + "assert(end(\"Connor\", \"n\") === false, 'message: \"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: \"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: \"He has to give me a new name\", \"name\" 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: \"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.');" ], "MDNlinks": [ "String.substr()" @@ -350,9 +350,9 @@ "repeat(\"abc\", 3, \"\");" ], "tests": [ - "assert(repeat(\"*\", 3) === \"***\", '\"*\", 3 should return \"***\".');", - "assert(repeat(\"abc\", 3) === \"abcabcabc\", '\"abc\", 3 should return \"abcabcabc\".');", - "assert(repeat(\"abc\", -2) === \"\", '\"abc\", -2 should return \"\".');" + "assert(repeat(\"*\", 3) === \"***\", 'message: \"*\", 3 should return \"***\".');", + "assert(repeat(\"abc\", 3) === \"abcabcabc\", 'message: \"abc\", 3 should return \"abcabcabc\".');", + "assert(repeat(\"abc\", -2) === \"\", 'message: \"abc\", -2 should return \"\".');" ], "MDNlinks": [ "Global String Object" @@ -388,10 +388,10 @@ "truncate(\"A-tisket a-tasket A green and yellow basket\", 11, \"\");" ], "tests": [ - "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", '\"A-tisket a-tasket A green and yellow basket\", 1 should return \"A-tisket...\".');", - "assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", '\"Peter Piper picked a peck of pickled peppers\", 14 should return \"Peter Piper...\".');", - "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", '\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) should return \"A-tisket a-tasket A green and yellow basket\".');", - "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', '\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2 should return \"A-tisket a-tasket A green and yellow basket\".');" + "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", 'message: \"A-tisket a-tasket A green and yellow basket\", 1 should return \"A-tisket...\".');", + "assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", 'message: \"Peter Piper picked a peck of pickled peppers\", 14 should return \"Peter Piper...\".');", + "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", 'message: \"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) should return \"A-tisket a-tasket A green and yellow basket\".');", + "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', 'message: \"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2 should return \"A-tisket a-tasket A green and yellow basket\".');" ], "MDNlinks": [ "String.slice()" @@ -426,10 +426,10 @@ "chunk([\"a\", \"b\", \"c\", \"d\"], 2, \"\");" ], "tests": [ - "assert.deepEqual(chunk([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], '[\"a\", \"b\", \"c\", \"d\"], 2 should return [[\"a\", \"b\"], [\"c\", \"d\"]].');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], '[0, 1, 2, 3, 4, 5] should return [[0, 1, 2], [3, 4, 5]].');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 2), [[0, 1], [2, 3], [4, 5]], '[0, 1, 2, 3, 4, 5], 2 should return [[0, 1], [2, 3], [4, 5]].');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], '[0, 1, 2, 3, 4, 5], 4 should return [[0, 1, 2, 3], [4, 5]].');" + "assert.deepEqual(chunk([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], 'message: [\"a\", \"b\", \"c\", \"d\"], 2 should return [[\"a\", \"b\"], [\"c\", \"d\"]].');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'message: [0, 1, 2, 3, 4, 5] should return [[0, 1, 2], [3, 4, 5]].');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 2), [[0, 1], [2, 3], [4, 5]], 'message: [0, 1, 2, 3, 4, 5], 2 should return [[0, 1], [2, 3], [4, 5]].');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'message: [0, 1, 2, 3, 4, 5], 4 should return [[0, 1, 2, 3], [4, 5]].');" ], "MDNlinks": [ "Array.push()" @@ -464,9 +464,9 @@ "slasher([1, 2, 3], 2, \"\");" ], "tests": [ - "assert.deepEqual(slasher([1, 2, 3], 2), [3], '[1, 2, 3], 2, [3] should return [3].');", - "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], '[1, 2, 3], 0 should return [1, 2, 3].');", - "assert.deepEqual(slasher([1, 2, 3], 9), [], '[1, 2, 3], 9 should return [].');" + "assert.deepEqual(slasher([1, 2, 3], 2), [3], 'message: [1, 2, 3], 2, [3] should return [3].');", + "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], 'message: [1, 2, 3], 0 should return [1, 2, 3].');", + "assert.deepEqual(slasher([1, 2, 3], 9), [], 'message: [1, 2, 3], 9 should return [].');" ], "MDNlinks": [ "Array.slice()", @@ -504,14 +504,14 @@ "mutation([\"hello\", \"hey\"], \"\");" ], "tests": [ - "assert(mutation([\"hello\", \"hey\"]) === false, '[\"hello\", \"hey\"] should return false.');", - "assert(mutation([\"hello\", \"Hello\"]) === true, '[\"hello\", \"Hello\"] should return true.');", - "assert(mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) === true, '[\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"] should return true.');", - "assert(mutation([\"Mary\", \"Army\"]) === true, '[\"Mary\", \"Army\"] should return true.');", - "assert(mutation([\"Mary\", \"Aarmy\"]) === true, '[\"Mary\", \"Aarmy\"] should return true.');", - "assert(mutation([\"Alien\", \"line\"]) === true, '[\"Alien\", \"line\"] should return true.');", - "assert(mutation([\"floor\", \"for\"]) === true, '[\"floor\", \"for\"] should return true.');", - "assert(mutation([\"hello\", \"neo\"]) === false, '[\"hello\", \"neo\"] should return false.');" + "assert(mutation([\"hello\", \"hey\"]) === false, 'message: [\"hello\", \"hey\"] should return false.');", + "assert(mutation([\"hello\", \"Hello\"]) === true, 'message: [\"hello\", \"Hello\"] should return true.');", + "assert(mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) === true, 'message: [\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"] should return true.');", + "assert(mutation([\"Mary\", \"Army\"]) === true, 'message: [\"Mary\", \"Army\"] should return true.');", + "assert(mutation([\"Mary\", \"Aarmy\"]) === true, 'message: [\"Mary\", \"Aarmy\"] should return true.');", + "assert(mutation([\"Alien\", \"line\"]) === true, 'message: [\"Alien\", \"line\"] should return true.');", + "assert(mutation([\"floor\", \"for\"]) === true, 'message: [\"floor\", \"for\"] should return true.');", + "assert(mutation([\"hello\", \"neo\"]) === false, 'message: [\"hello\", \"neo\"] should return false.');" ], "MDNlinks": [ "Array.indexOf()" @@ -547,9 +547,9 @@ "bouncer([7, \"ate\", \"\", false, 9], \"\");" ], "tests": [ - "assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], '[7, \"ate\", \"\", false, 9] should return [7, \"ate\", 9].');", - "assert.deepEqual(bouncer([\"a\", \"b\", \"c\"]), [\"a\", \"b\", \"c\"], '[\"a\", \"b\", \"c\"] should return [\"a\", \"b\", \"c\"].');", - "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, '']), [], '[false, null, 0] should return [].');" + "assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], 'message: [7, \"ate\", \"\", false, 9] should return [7, \"ate\", 9].');", + "assert.deepEqual(bouncer([\"a\", \"b\", \"c\"]), [\"a\", \"b\", \"c\"], 'message: [\"a\", \"b\", \"c\"] should return [\"a\", \"b\", \"c\"].');", + "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, '']), [], 'message: [false, null, 0] should return [].');" ], "MDNlinks": [ "Boolean Objects", @@ -585,11 +585,11 @@ "destroyer([1, 2, 3, 1, 2, 3], 2, 3, \"\");" ], "tests": [ - "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], '[1, 2, 3, 1, 2, 3], 2, 3 should return [1, 1].');", - "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], '[1, 2, 3, 5, 1, 2, 3], 2, 3 should return [1, 5, 1].');", - "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], '[3, 5, 1, 2, 2], 2, 3, 5 should return [1].');", - "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], '[2, 3, 2, 3], 2, 3 should return [].');", - "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], '[\"tree\", \"hamburger\", 53], \"tree\", 53) should return [\"hamburger\"].');" + "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'message: [1, 2, 3, 1, 2, 3], 2, 3 should return [1, 1].');", + "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'message: [1, 2, 3, 5, 1, 2, 3], 2, 3 should return [1, 5, 1].');", + "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], 'message: [3, 5, 1, 2, 2], 2, 3, 5 should return [1].');", + "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], 'message: [2, 3, 2, 3], 2, 3 should return [].');", + "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], 'message: [\"tree\", \"hamburger\", 53], \"tree\", 53) should return [\"hamburger\"].');" ], "MDNlinks": [ "Arguments object", @@ -629,12 +629,12 @@ "Array.sort()" ], "tests": [ - "assert(where([10, 20, 30, 40, 50], 35) === 3, '[10, 20, 30, 40, 50], 35 should return 3.');", - "assert(where([10, 20, 30, 40, 50], 30) === 2, '[10, 20, 30, 40, 50], 30) should return 2.');", - "assert(where([40, 60], 50) === 1, '[40, 60,], 50 should return 1.');", - "assert(where([5, 3, 20, 3], 3) === 0, '[5, 3, 20, 3], 3 should return 0.');", - "assert(where([2, 20, 10], 1) === 0, '[2, 20, 10], 1 should return 0.');", - "assert(where([2, 5, 10], 15) === 3, '[2, 5, 10], 15 should return 3.');" + "assert(where([10, 20, 30, 40, 50], 35) === 3, 'message: [10, 20, 30, 40, 50], 35 should return 3.');", + "assert(where([10, 20, 30, 40, 50], 30) === 2, 'message: [10, 20, 30, 40, 50], 30) should return 2.');", + "assert(where([40, 60], 50) === 1, 'message: [40, 60,], 50 should return 1.');", + "assert(where([5, 3, 20, 3], 3) === 0, 'message: [5, 3, 20, 3], 3 should return 0.');", + "assert(where([2, 20, 10], 1) === 0, 'message: [2, 20, 10], 1 should return 0.');", + "assert(where([2, 5, 10], 15) === 3, 'message: [2, 5, 10], 15 should return 3.');" ], "type": "bonfire", "challengeType": 5, From 55de772aded1047091d9e5e64fe874edb55fb78f Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 28 Sep 2015 20:05:22 -0700 Subject: [PATCH 37/63] Remove portfolio comment from share --- client/main.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/main.js b/client/main.js index bdde23f436..c1578c1d6f 100644 --- a/client/main.js +++ b/client/main.js @@ -438,8 +438,7 @@ $(document).ready(function() { '&display=page&' + 'caption=I%20just%20completed%20the%20' + challengeBlockEscapedName + - '%20section%20on%20Free%20Code%20Camp%2E%20Check%20out' + - '%20my%20portfolio%20so%20far%2E' + + '%20section%20on%20Free%20Code%20Camp%2E' + '&link=http%3A%2F%2Ffreecodecamp%2Ecom%2F' + username + '&redirect_uri=http%3A%2F%2Ffreecodecamp%2Ecom%2Fmap'; From 52c74f5a3d0ce8064f2631f526927627952e03ce Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 29 Sep 2015 13:44:58 -0700 Subject: [PATCH 38/63] merge staging --- seed/challenges/intermediate-bonfires.json | 140 ++++++++++----------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json index d804919dfd..ef3e7be3f0 100644 --- a/seed/challenges/intermediate-bonfires.json +++ b/seed/challenges/intermediate-bonfires.json @@ -19,11 +19,11 @@ "sumAll([1, 4]);" ], "tests": [ - "expect(sumAll([1, 4])).to.be.a('Number');", - "expect(sumAll([1, 4])).to.equal(10);", - "expect(sumAll([4, 1])).to.equal(10);", - "expect(sumAll([5, 10])).to.equal(45);", - "expect(sumAll([10, 5])).to.equal(45);" + "assert(typeof(sumAll([1, 4])) === \"number\", 'message: sumAll() should return a number');", + "assert.deepEqual(sumAll([1, 4]), 10, 'message: sumAll([1, 4]) should return 10');", + "assert.deepEqual(sumAll([4, 1]), 10, 'message: sumAll([4, 1]) should return 10');", + "assert.deepEqual(sumAll([5, 10]), 45, 'message: sumAll([5, 10]) should return 45');", + "assert.deepEqual(sumAll([10, 5]), 45, 'message: sumAll([10, 5]) should return 45');" ], "MDNlinks": [ "Math.max()", @@ -61,13 +61,13 @@ "diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);" ], "tests": [ - "expect(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])).to.be.a('array');", - "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'arrays with only one difference');", - "assert.includeMembers(diff(['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['diorite', 'pink wool'], 'arrays with more than one difference');", - "assert.deepEqual(diff(['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub']), [], 'arrays with no difference');", - "assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'arrays with numbers');", - "assert.includeMembers(diff([1, 'calf', 3, 'piglet'], [1, 'calf', 3, 4]), ['piglet', 4], 'arrays with numbers and strings');", - "assert.deepEqual(diff([], ['snuffleupagus', 'cookie monster', 'elmo']), ['snuffleupagus', 'cookie monster', 'elmo'], 'empty array');" + "assert(typeof(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])) === \"object\", 'message: diff() should return an array.');", + "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'message: ['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub'] should return ['pink wool'].');", + "assert.includeMembers(diff(['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['diorite', 'pink wool'], 'message: ['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub'] should return ['diorite', 'pink wool'].');", + "assert.deepEqual(diff(['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub']), [], 'message: ['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub'] should return [].');", + "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'].');" ], "MDNlinks": [ "Comparison Operators", @@ -93,11 +93,11 @@ "id": "a7f4d8f2483413a6ce226cac", "title": "Roman Numeral Converter", "tests": [ - "expect(convert(12)).to.equal(\"XII\");", - "expect(convert(5)).to.equal(\"V\");", - "expect(convert(9)).to.equal(\"IX\");", - "expect(convert(29)).to.equal(\"XXIX\");", - "expect(convert(16)).to.equal(\"XVI\");" + "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(29), \"XXIX\", 'message: convert(29) should return \"XXIX\"');", + "assert.deepEqual(convert(16), \"XVI\", 'message: convert(16) should return \"XVI\"');" ], "difficulty": "2.02", "description": [ @@ -150,10 +150,10 @@ "where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });" ], "tests": [ - "assert.deepEqual(where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }), [{ first: 'Tybalt', last: 'Capulet' }], 'should return an array of objects');", - "assert.deepEqual(where([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'should return with multiples');", - "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 }], 'should return two objects in array');", - "assert.deepEqual(where([{ 'a': 5 }, { 'a': 5 }, { 'a': 5, 'b': 10 }], { 'a': 5, 'b': 10 }), [{ 'a': 5, 'b': 10 }], 'should return a single object in array');" + "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([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'message: should return .');", + "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: should return .');", + "assert.deepEqual(where([{ 'a': 5 }, { 'b': 10 }, { 'a': 5, 'b': 10 }], { 'a': 5, 'b': 10 }), [{ 'a': 5, 'b': 10 }], 'message: should return .');" ], "MDNlinks": [ "Global Object", @@ -177,11 +177,11 @@ "id": "a0b5010f579e69b815e7c5d6", "title": "Search and Replace", "tests": [ - "expect(myReplace(\"Let us go to the store\", \"store\", \"mall\")).to.equal(\"Let us go to the mall\");", - "expect(myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")).to.equal(\"He is Sitting on the couch\");", - "expect(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\")).to.equal(\"This has a spelling error\");", - "expect(myReplace(\"His name is Tom\", \"Tom\", \"john\")).to.equal(\"His name is John\");", - "expect(myReplace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")).to.equal(\"Let us get back to more Bonfires\");" + "assert.deepEqual(replace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'message: replace(\"Let us go to the store\", \"store\", \"mall\") should return \"Let us go to the mall\"');", + "assert.deepEqual(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'message: replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\") should return \"He is Sitting on the couch\"');", + "assert.deepEqual(replace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'message: replace(\"This has a spellngi error\", \"spellingi\", \"spelling\") should return \"This has a spelling error\"');", + "assert.deepEqual(replace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'message: replace(\"His name is Tom\", \"Tom\", \"john\") should return \"His name is John\"');", + "assert.deepEqual(replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\"), \"Let us get back to more Bonfires\", 'message: replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\") should return \"Let us get back to more Bonfires\"');" ], "difficulty": "2.035", "description": [ @@ -221,11 +221,11 @@ "id": "aa7697ea2477d1316795783b", "title": "Pig Latin", "tests": [ - "expect(translate(\"california\")).to.equal(\"aliforniacay\");", - "expect(translate(\"paragraphs\")).to.equal(\"aragraphspay\");", - "expect(translate(\"glove\")).to.equal(\"oveglay\");", - "expect(translate(\"algorithm\")).to.equal(\"algorithmway\");", - "expect(translate(\"eight\")).to.equal(\"eightway\");" + "assert.deepEqual(translate(\"california\"), \"aliforniacay\", 'message: translate(\"california\") should return \"aliforniacay\"');", + "assert.deepEqual(translate(\"paragraphs\"), \"aragraphspay\", 'message: translate(\"paragraphs\") should return \"aragraphspay\"');", + "assert.deepEqual(translate(\"glove\"), \"oveglay\", 'message: translate(\"glove\") should return \"oveglay\"');", + "assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'message: translate(\"algorithm\") should return \"algorithmway\"');", + "assert.deepEqual(translate(\"eight\"), \"eightway\", 'message: translate(\"eight\") should return \"eightway\"');" ], "difficulty": "2.04", "description": [ @@ -265,9 +265,9 @@ "id": "afd15382cdfb22c9efe8b7de", "title": "DNA Pairing", "tests": [ - "assert.deepEqual(pair(\"ATCGA\"),[['A','T'],['T','A'],['C','G'],['G','C'],['A','T']], 'should return the dna pair');", - "assert.deepEqual(pair(\"TTGAG\"),[['T','A'],['T','A'],['G','C'],['A','T'],['G','C']], 'should return the dna pair');", - "assert.deepEqual(pair(\"CTCTA\"),[['C','G'],['T','A'],['C','G'],['T','A'],['A','T']], 'should return the dna pair');" + "assert.deepEqual(pair(\"ATCGA\"),[['A','T'],['T','A'],['C','G'],['G','C'],['A','T']], 'message: should return .');", + "assert.deepEqual(pair(\"TTGAG\"),[['T','A'],['T','A'],['G','C'],['A','T'],['G','C']], 'message: should return .');", + "assert.deepEqual(pair(\"CTCTA\"),[['C','G'],['T','A'],['C','G'],['T','A'],['A','T']], 'message: should return .');" ], "difficulty": "2.05", "description": [ @@ -319,10 +319,10 @@ "fearNotLetter('abce');" ], "tests": [ - "expect(fearNotLetter('abce')).to.equal('d');", - "expect(fearNotLetter('bcd')).to.be.undefined;", - "expect(fearNotLetter('abcdefghjklmno')).to.equal('i');", - "expect(fearNotLetter('yz')).to.be.undefined;" + "assert.deepEqual(fearNotLetter(\"abce\"), \"d\", 'message: fearNotLetter(\"abce\") should return d');", + "assert.deepEqual(fearNotLetter(\"abcdefghjklmno\"), \"i\", 'message: fearNotLetter(\"abcdefghjklmno\") should return i');", + "assert.isUndefined(fearNotLetter(\"bcd\"), 'message: fearNotLetter(\"bcd\") should return undefined');", + "assert.isUndefined(fearNotLetter(\"yz\"), 'message: fearNotLetter(\"yz\") should return undefined');" ], "MDNlinks": [ "String.charCodeAt()", @@ -359,14 +359,14 @@ "boo(null);" ], "tests": [ - "assert.strictEqual(boo(true), true);", - "assert.strictEqual(boo(false), true);", - "assert.strictEqual(boo([1, 2, 3]), false);", - "assert.strictEqual(boo([].slice), false);", - "assert.strictEqual(boo({ 'a': 1 }), false);", - "assert.strictEqual(boo(1), false);", - "assert.strictEqual(boo(NaN), false);", - "assert.strictEqual(boo('a'), false);" + "assert.strictEqual(boo(true), true, 'message: should return true.');", + "assert.strictEqual(boo(false), true, 'message: should return true.');", + "assert.strictEqual(boo([1, 2, 3]), false, 'message: should return false.');", + "assert.strictEqual(boo([].slice), false, 'message: should return false.');", + "assert.strictEqual(boo({ 'a': 1 }), false, 'message: should return false.');", + "assert.strictEqual(boo(1), false, 'message: should return false.');", + "assert.strictEqual(boo(NaN), false, 'message: should return true.');", + "assert.strictEqual(boo('a'), false, 'message: should return false.');" ], "MDNlinks": [ "Boolean Objects" @@ -525,12 +525,12 @@ "sumFibs(4);" ], "tests": [ - "expect(sumFibs(1)).to.be.a('number');", - "expect(sumFibs(1000)).to.equal(1785);", - "expect(sumFibs(4000000)).to.equal(4613732);", - "expect(sumFibs(4)).to.equal(5);", - "expect(sumFibs(75024)).to.equal(60696);", - "expect(sumFibs(75025)).to.equal(135721);" + "assert.deepEqual(typeof(sumFibs(1)), \"number\", \"The result should be a number\");", + "assert.deepEqual(sumFibs(1000), 1785, 'message: sumFibs(1000) should return 1785');", + "assert.deepEqual(sumFibs(4000000), 4613732, 'message: sumFibs(4000000) should return 4613732');", + "assert.deepEqual(sumFibs(4), 5, 'message: sumFibs(4) should return 5');", + "assert.deepEqual(sumFibs(75024), 60696, 'message: sumFibs(75024) should return 60696');", + "assert.deepEqual(sumFibs(75025), 135721, 'message: sumFibs(75025) should return 135721');" ], "MDNlinks": [ "Remainder" @@ -566,9 +566,9 @@ "sumPrimes(10);" ], "tests": [ - "expect(sumPrimes(10)).to.be.a('number');", - "expect(sumPrimes(10)).to.equal(17);", - "expect(sumPrimes(977)).to.equal(73156);" + "assert.deepEqual(typeof(sumPrimes(10)), \"number\", \"The result should be a number\");", + "assert.deepEqual(sumPrimes(10), 17, 'message: sumPrimes(10) should return 17');", + "assert.deepEqual(sumPrimes(977), 73156, 'message: sumPrimes(977) should return 73156');" ], "MDNlinks": [ "For Loops", @@ -606,10 +606,10 @@ "smallestCommons([1,5]);" ], "tests": [ - "expect(smallestCommons([1,5])).to.be.a('number');", - "expect(smallestCommons([1,5])).to.equal(60);", - "expect(smallestCommons([5,1])).to.equal(60);", - "expect(smallestCommons([1,13])).to.equal(360360);" + "assert.deepEqual(typeof(smallestCommons([1, 5])), \"number\", \"The result should be a number\");", + "assert.deepEqual(smallestCommons([1, 5]), 60, 'message: smallestCommons([1, 5]) should return 60');", + "assert.deepEqual(smallestCommons([5, 1]), 60, 'message: smallestCommons([5, 1]) should return 60');", + "assert.deepEqual(smallestCommons([1, 13]), 360360, 'message: smallestCommons([1, 13]) should return 360360');" ], "MDNlinks": [ "Smallest Common Multiple" @@ -680,10 +680,10 @@ "drop([1, 2, 3], function(n) {return n < 3; });" ], "tests": [ - "expect(drop([1, 2, 3, 4], function(n) {return n >= 3; })).to.eqls([3, 4]);", - "expect(drop([1, 2, 3], function(n) {return n > 0; })).to.eqls([1, 2, 3]);", - "expect(drop([1, 2, 3, 4], function(n) {return n > 5; })).to.eqls([]);", - "expect(drop([1, 2, 3, 7, 4], function(n) { return n > 5; })).to.eqls([7, 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]');" ], "MDNlinks": [ "Arguments object", @@ -757,8 +757,8 @@ "binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');" ], "tests": [ - "expect(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111')).to.equal(\"Aren't bonfires fun!?\");", - "expect(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001')).to.equal(\"I love FreeCodeCamp!\");" + "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", \"binaryAgent() should return Aren't bonfires fun!?\");", + "assert.deepEqual(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001'), \"I love FreeCodeCamp!\", 'message: binaryAgent() should return \"I love FreeCodeCamp!\"');" ], "MDNlinks": [ "String.charCodeAt()", @@ -838,11 +838,11 @@ "add(2,3);" ], "tests": [ - "expect(add(2, 3)).to.equal(5);", - "expect(add(2)(3)).to.equal(5);", - "expect(add('http://bit.ly/IqT6zt')).to.be.undefined;", - "expect(add(2, '3')).to.be.undefined;", - "expect(add(2)([3])).to.be.undefined;" + "assert.deepEqual(add(2, 3), 5, 'message: add(2, 3) should return 5');", + "assert.deepEqual(add(2)(3), 5, 'message: add(2)(3) should return 5');", + "assert.isUndefined(add(\"http://bit.ly/IqT6zt\"), 'message: add(\"http://bit.ly/IqT6zt\") should return undefined');", + "assert.isUndefined(add(2, \"3\"), 'message: add(2, \"3\") should return undefined');", + "assert.isUndefined(add(2)([3]), 'message: add(2)([3]) should return undefined');" ], "MDNlinks": [ "Global Function Object", From 665734872287eeea1892d62688753f0e17988f6f Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 29 Sep 2015 14:18:43 -0700 Subject: [PATCH 39/63] finish first pass at intermediate bonfires --- seed/challenges/intermediate-bonfires.json | 116 ++++++++++----------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json index ef3e7be3f0..85fdf9cb61 100644 --- a/seed/challenges/intermediate-bonfires.json +++ b/seed/challenges/intermediate-bonfires.json @@ -151,9 +151,9 @@ ], "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([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'message: should return .');", - "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: should return .');", - "assert.deepEqual(where([{ 'a': 5 }, { 'b': 10 }, { 'a': 5, 'b': 10 }], { 'a': 5, 'b': 10 }), [{ 'a': 5, 'b': 10 }], 'message: should return .');" + "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 }].');", + "assert.deepEqual(where([{ 'a': 5 }, { 'b': 10 }, { 'a': 5, 'b': 10 }], { 'a': 5, 'b': 10 }), [{ 'a': 5, 'b': 10 }], 'message: where([{ 'a': 5 }, { 'b': 10 }, { 'a': 5, 'b': 10 }], { 'a': 5, 'b': 10 }) should return [{ 'a': 5, 'b': 10 }].');" ], "MDNlinks": [ "Global Object", @@ -265,9 +265,9 @@ "id": "afd15382cdfb22c9efe8b7de", "title": "DNA Pairing", "tests": [ - "assert.deepEqual(pair(\"ATCGA\"),[['A','T'],['T','A'],['C','G'],['G','C'],['A','T']], 'message: should return .');", - "assert.deepEqual(pair(\"TTGAG\"),[['T','A'],['T','A'],['G','C'],['A','T'],['G','C']], 'message: should return .');", - "assert.deepEqual(pair(\"CTCTA\"),[['C','G'],['T','A'],['C','G'],['T','A'],['A','T']], 'message: should return .');" + "assert.deepEqual(pair(\"ATCGA\"),[['A','T'],['T','A'],['C','G'],['G','C'],['A','T']], 'message: pair(\"ATCGA\") should return [['A','T'],['T','A'],['C','G'],['G','C'],['A','T']].');", + "assert.deepEqual(pair(\"TTGAG\"),[['T','A'],['T','A'],['G','C'],['A','T'],['G','C']], 'message: pair(\"TTGAG\") should return [['T','A'],['T','A'],['G','C'],['A','T'],['G','C']].');", + "assert.deepEqual(pair(\"CTCTA\"),[['C','G'],['T','A'],['C','G'],['T','A'],['A','T']], 'message: pair(\"CTCTA\") should return [['C','G'],['T','A'],['C','G'],['T','A'],['A','T']].');" ], "difficulty": "2.05", "description": [ @@ -319,10 +319,10 @@ "fearNotLetter('abce');" ], "tests": [ - "assert.deepEqual(fearNotLetter(\"abce\"), \"d\", 'message: fearNotLetter(\"abce\") should return d');", - "assert.deepEqual(fearNotLetter(\"abcdefghjklmno\"), \"i\", 'message: fearNotLetter(\"abcdefghjklmno\") should return i');", - "assert.isUndefined(fearNotLetter(\"bcd\"), 'message: fearNotLetter(\"bcd\") should return undefined');", - "assert.isUndefined(fearNotLetter(\"yz\"), 'message: fearNotLetter(\"yz\") should return undefined');" + "assert.deepEqual(fearNotLetter(\"abce\"), \"d\", 'message: fearNotLetter(\"abce\") should return \"d\".');", + "assert.deepEqual(fearNotLetter(\"abcdefghjklmno\"), \"i\", 'message: fearNotLetter(\"abcdefghjklmno\") should return \"i\".');", + "assert.isUndefined(fearNotLetter(\"bcd\"), 'message: fearNotLetter(\"bcd\") should return undefined.');", + "assert.isUndefined(fearNotLetter(\"yz\"), 'message: fearNotLetter(\"yz\") should return undefined.');" ], "MDNlinks": [ "String.charCodeAt()", @@ -359,14 +359,14 @@ "boo(null);" ], "tests": [ - "assert.strictEqual(boo(true), true, 'message: should return true.');", - "assert.strictEqual(boo(false), true, 'message: should return true.');", - "assert.strictEqual(boo([1, 2, 3]), false, 'message: should return false.');", - "assert.strictEqual(boo([].slice), false, 'message: should return false.');", - "assert.strictEqual(boo({ 'a': 1 }), false, 'message: should return false.');", - "assert.strictEqual(boo(1), false, 'message: should return false.');", - "assert.strictEqual(boo(NaN), false, 'message: should return true.');", - "assert.strictEqual(boo('a'), false, 'message: should return false.');" + "assert.strictEqual(boo(true), true, 'message: boo(true) should return true.');", + "assert.strictEqual(boo(false), true, 'message: boo(false) should return true.');", + "assert.strictEqual(boo([1, 2, 3]), false, 'message: boo([1, 2, 3]) should return false.');", + "assert.strictEqual(boo([].slice), false, 'message: boo([].slice) should return false.');", + "assert.strictEqual(boo({ 'a': 1 }), false, 'message: boo({ 'a': 1 }) should return false.');", + "assert.strictEqual(boo(1), false, 'message: boo(1) should return false.');", + "assert.strictEqual(boo(NaN), false, 'message: boo(NaN) should return true.');", + "assert.strictEqual(boo('a'), false, 'message: boo('a') should return false.');" ], "MDNlinks": [ "Boolean Objects" @@ -403,10 +403,10 @@ "unite([1, 3, 2], [5, 2, 1, 4], [2, 1]);" ], "tests": [ - "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'should return the union of the given arrays');", - "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'should not flatten nested arrays');", - "assert.deepEqual(unite([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'should correctly handle exactly two arguments');", - "assert.deepEqual(unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [ 1, 2, 3, 5, 4, 6, 7, 8 ], 'should correctly handle higher numbers of arguments');" + "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'message: should return .');", + "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'message: should return .');", + "assert.deepEqual(unite([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'message: should return .');", + "assert.deepEqual(unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [ 1, 2, 3, 5, 4, 6, 7, 8 ], 'message: should return .');" ], "MDNlinks": [ "Arguments object", @@ -442,13 +442,13 @@ "convert('Dolce & Gabbana');" ], "tests": [ - "assert.match(convert('Dolce & Gabbana'), /Dolce &(amp|AMP|#x00026|#38); Gabbana/, 'should escape characters');", - "assert.match(convert('Hamburgers < Pizza < Tacos'), /Hamburgers &(lt|LT|#x0003C|#60); Pizza &(lt|LT|#x0003C|#60); Tacos/, 'should escape characters');", - "assert.match(convert('Sixty > twelve'), /Sixty &(gt|GT|#x0003E|#62); twelve/, 'should escape characters');", - "assert.match(convert('Stuff in \"quotation marks\"'), /Stuff in &(quot|QUOT|#x00022|#34);quotation marks&(quot|QUOT|#x00022|#34);/, 'should escape characters');", - "assert.match(convert(\"Shindler's List\"), /Shindler&(apos|#x00027|#39);s List/, 'should escape characters');", - "assert.match(convert('<>'), /&(lt|LT|#x0003C|#60);&(gt|GT|#x0003E|#62);/, 'should escape characters');", - "assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');" + "assert.match(convert('Dolce & Gabbana'), /Dolce &(amp|AMP|#x00026|#38); Gabbana/, 'message: convert('Dolce & Gabbana') should return /Dolce &(amp|AMP|#x00026|#38); Gabbana/.');", + "assert.match(convert('Hamburgers < Pizza < Tacos'), /Hamburgers &(lt|LT|#x0003C|#60); Pizza &(lt|LT|#x0003C|#60); Tacos/, 'message: convert('Hamburgers < Pizza < Tacos') should return /Hamburgers &(lt|LT|#x0003C|#60); Pizza &(lt|LT|#x0003C|#60); Tacos/.');", + "assert.match(convert('Sixty > twelve'), /Sixty &(gt|GT|#x0003E|#62); twelve/, 'message: convert('Sixty > twelve') should return /Sixty &(gt|GT|#x0003E|#62); twelve/.');", + "assert.match(convert('Stuff in \"quotation marks\"'), /Stuff in &(quot|QUOT|#x00022|#34);quotation marks&(quot|QUOT|#x00022|#34);/, 'message: convert('Stuff in \"quotation marks\"') should return /Stuff in &(quot|QUOT|#x00022|#34);quotation marks&(quot|QUOT|#x00022|#34);/.');", + "assert.match(convert(\"Shindler's List\"), /Shindler&(apos|#x00027|#39);s List/, 'message: convert(\"Shindler's List\") should return /Shindler&(apos|#x00027|#39);s List/.');", + "assert.match(convert('<>'), /&(lt|LT|#x0003C|#60);&(gt|GT|#x0003E|#62);/, 'message: convert('<>') should return /&(lt|LT|#x0003C|#60);&(gt|GT|#x0003E|#62);/.');", + "assert.strictEqual(convert('abc'), 'abc', 'message: convert(\"abc\") should return \"abc\".');" ], "MDNlinks": [ "RegExp", @@ -485,10 +485,10 @@ "spinalCase('This Is Spinal Tap');" ], "tests": [ - "assert.strictEqual(spinalCase('This Is Spinal Tap'), 'this-is-spinal-tap', 'should return spinal case from string with spaces');", - "assert.strictEqual(spinalCase('thisIsSpinalTap'), 'this-is-spinal-tap', 'should return spinal case from string with camel case');", - "assert.strictEqual(spinalCase('The_Andy_Griffith_Show'), 'the-andy-griffith-show', 'should return spinal case from string with snake case');", - "assert.strictEqual(spinalCase('Teletubbies say Eh-oh'), 'teletubbies-say-eh-oh', 'should return spinal case from string with spaces and hyphens');" + "assert.strictEqual(spinalCase('This Is Spinal Tap'), 'this-is-spinal-tap', 'message: spinalCase('This Is Spinal Tap') should return 'this-is-spinal-tap'.');", + "assert.strictEqual(spinalCase('thisIsSpinalTap'), 'this-is-spinal-tap', 'message: spinalCase('thisIsSpinalTap') should return 'this-is-spinal-tap'.');", + "assert.strictEqual(spinalCase('The_Andy_Griffith_Show'), 'the-andy-griffith-show', 'message: spinalCase('The_Andy_Griffith_Show') should return 'the-andy-griffith-show'.');", + "assert.strictEqual(spinalCase('Teletubbies say Eh-oh'), 'teletubbies-say-eh-oh', 'message: spinalCase('Teletubbies say Eh-oh') should return 'teletubbies-say-eh-oh'.');" ], "MDNlinks": [ "RegExp", @@ -525,7 +525,7 @@ "sumFibs(4);" ], "tests": [ - "assert.deepEqual(typeof(sumFibs(1)), \"number\", \"The result should be a number\");", + "assert.deepEqual(typeof(sumFibs(1)), \"number\", message: sumFibs() should return a number.);", "assert.deepEqual(sumFibs(1000), 1785, 'message: sumFibs(1000) should return 1785');", "assert.deepEqual(sumFibs(4000000), 4613732, 'message: sumFibs(4000000) should return 4613732');", "assert.deepEqual(sumFibs(4), 5, 'message: sumFibs(4) should return 5');", @@ -566,9 +566,9 @@ "sumPrimes(10);" ], "tests": [ - "assert.deepEqual(typeof(sumPrimes(10)), \"number\", \"The result should be a number\");", - "assert.deepEqual(sumPrimes(10), 17, 'message: sumPrimes(10) should return 17');", - "assert.deepEqual(sumPrimes(977), 73156, 'message: sumPrimes(977) should return 73156');" + "assert.deepEqual(typeof(sumPrimes(10)), \"number\", 'message: sumPrimes() should return a number.');", + "assert.deepEqual(sumPrimes(10), 17, 'message: sumPrimes(10) should return 17.');", + "assert.deepEqual(sumPrimes(977), 73156, 'message: sumPrimes(977) should return 73156.');" ], "MDNlinks": [ "For Loops", @@ -606,7 +606,7 @@ "smallestCommons([1,5]);" ], "tests": [ - "assert.deepEqual(typeof(smallestCommons([1, 5])), \"number\", \"The result should be a number\");", + "assert.deepEqual(typeof(smallestCommons([1, 5])), \"number\", 'message: smallestCommons() should return a number.');", "assert.deepEqual(smallestCommons([1, 5]), 60, 'message: smallestCommons([1, 5]) should return 60');", "assert.deepEqual(smallestCommons([5, 1]), 60, 'message: smallestCommons([5, 1]) should return 60');", "assert.deepEqual(smallestCommons([1, 13]), 360360, 'message: smallestCommons([1, 13]) should return 360360');" @@ -644,8 +644,8 @@ "find([1, 2, 3, 4], function(num){ return num % 2 === 0; });" ], "tests": [ - "assert.strictEqual(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'should return first found value');", - "assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'should return undefined if not found');" + "assert.strictEqual(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'message: find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }) should return 8.');", + "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()" @@ -680,10 +680,10 @@ "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], 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, 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].');" ], "MDNlinks": [ "Arguments object", @@ -719,10 +719,10 @@ "steamroller([1, [2], [3, [[4]]]]);" ], "tests": [ - "assert.deepEqual(steamroller([[['a']], [['b']]]), ['a', 'b'], 'should flatten nested arrays');", - "assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'should flatten nested arrays');", - "assert.deepEqual(steamroller([1, [], [3, [[4]]]]), [1, 3, 4], 'should work with empty arrays');", - "assert.deepEqual(steamroller([1, {}, [3, [[4]]]]), [1, {}, 3, 4], 'should work with actual objects');" + "assert.deepEqual(steamroller([[['a']], [['b']]]), ['a', 'b'], 'message: steamroller([[['a']], [['b']]]) should return ['a', 'b'].');", + "assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'message: steamroller([1, [2], [3, [[4]]]]) should return [1, 2, 3, 4].');", + "assert.deepEqual(steamroller([1, [], [3, [[4]]]]), [1, 3, 4], 'message: steamroller([1, [], [3, [[4]]]]) should return [1, 3, 4].');", + "assert.deepEqual(steamroller([1, {}, [3, [[4]]]]), [1, {}, 3, 4], 'message: steamroller([1, {}, [3, [[4]]]]) should return [1, {}, 3, 4].');" ], "MDNlinks": [ "Array.isArray()" @@ -757,8 +757,8 @@ "binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');" ], "tests": [ - "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", \"binaryAgent() should return Aren't bonfires fun!?\");", - "assert.deepEqual(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001'), \"I love FreeCodeCamp!\", 'message: binaryAgent() should return \"I love FreeCodeCamp!\"');" + "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", 'binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\") should return \"Aren't bonfires fun!?\"');", + "assert.deepEqual(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001'), \"I love FreeCodeCamp!\", 'message: binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\" should return \"I love FreeCodeCamp!\"');" ], "MDNlinks": [ "String.charCodeAt()", @@ -796,9 +796,9 @@ "every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');" ], "tests": [ - "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex'), true, 'should return true if predicate returns truthy for all elements in the collection');", - "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], {'sex': 'female'}), false, 'should return false if predicate returns falsey for any element in the collection');", - "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'female'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], {'sex': 'female'}), false, 'should return false if predicate returns falsey for any element in the collection');" + "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.');" ], "MDNlinks": [ "Object.hasOwnProperty()", @@ -838,11 +838,11 @@ "add(2,3);" ], "tests": [ - "assert.deepEqual(add(2, 3), 5, 'message: add(2, 3) should return 5');", - "assert.deepEqual(add(2)(3), 5, 'message: add(2)(3) should return 5');", - "assert.isUndefined(add(\"http://bit.ly/IqT6zt\"), 'message: add(\"http://bit.ly/IqT6zt\") should return undefined');", - "assert.isUndefined(add(2, \"3\"), 'message: add(2, \"3\") should return undefined');", - "assert.isUndefined(add(2)([3]), 'message: add(2)([3]) should return undefined');" + "assert.deepEqual(add(2, 3), 5, 'message: add(2, 3) should return 5.');", + "assert.deepEqual(add(2)(3), 5, 'message: add(2)(3) should return 5.');", + "assert.isUndefined(add(\"http://bit.ly/IqT6zt\"), 'message: add(\"http://bit.ly/IqT6zt\") should return undefined.');", + "assert.isUndefined(add(2, \"3\"), 'message: add(2, \"3\") should return undefined.');", + "assert.isUndefined(add(2)([3]), 'message: add(2)([3]) should return undefined.');" ], "MDNlinks": [ "Global Function Object", From 838a80167e6c7a4ac258f34864f83d8ad399d7f8 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 29 Sep 2015 14:34:51 -0700 Subject: [PATCH 40/63] finish first take at upper-intermediate bonfires --- .../upper-intermediate-bonfires.json | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/seed/challenges/upper-intermediate-bonfires.json b/seed/challenges/upper-intermediate-bonfires.json index 04d9cc63bb..bdaeefc084 100644 --- a/seed/challenges/upper-intermediate-bonfires.json +++ b/seed/challenges/upper-intermediate-bonfires.json @@ -22,20 +22,13 @@ "bob.getFullName();" ], "tests": [ - "expect(Object.keys(bob).length).to.eql(6);", - "expect(bob instanceof Person).to.be.true;", - "expect(bob.firstName).to.be.undefined();", - "expect(bob.lastName).to.be.undefined();", - "expect(bob.getFirstName()).to.eql('Bob');", - "expect(bob.getLastName()).to.eql('Ross');", - "expect(bob.getFullName()).to.eql('Bob Ross');", - "bob.setFirstName('Happy');", - "expect(bob.getFirstName()).to.eql('Happy');", - "bob.setLastName('Trees');", - "expect(bob.getLastName()).to.eql('Trees');", - "bob.setFullName('George Carlin');", - "expect(bob.getFullName()).to.eql('George Carlin');", - "bob.setFullName('Bob Ross');" + "assert.deepEqual(Object.keys(bob).length, 6, 'message: Object.keys(bob).length should return 6.');", + "assert.deepEqual(bob instanceof Person, true, 'message: bob instanceof Person should return true.');", + "assert.deepEqual(bob.firstName, undefined, 'message: bob.firstName should return undefined.');", + "assert.deepEqual(bob.lastName, undefined, 'message: bob.lastName should return undefined.';", + "assert.deepEqual(bob.getFirstName(), 'Bob', 'message: bob.getFirstName() should return \"Bob\".');", + "assert.deepEqual(bob.getLastName(), 'Ross', 'message: bob.getLastName() should return \"Ross\".';", + "assert.deepEqual(bob.getFullName(), 'Bob Ross', 'message: bob.getFullName() should return \"Bob Ross\".');" ], "MDNlinks": [ "Closures", @@ -77,8 +70,8 @@ "orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}]);" ], "tests": [ - "expect(orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputnik\", orbitalPeriod: 86400}]);", - "expect(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])).to.eqls([{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]);" + "assert.deepEqual(orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}]), [{name: \"sputnik\", orbitalPeriod: 86400}], 'message: orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}]) should return [{name: \"sputnik\", orbitalPeriod: 86400}].');", + "assert.deepEqual(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}]), [{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}], 'message: orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}]) should return [{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}].');" ], "MDNlinks": [ "Math.pow()" @@ -114,11 +107,11 @@ "pairwise([1,4,2,3,0,5], 7);" ], "tests": [ - "expect(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);", - "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);", - "expect(pairwise([1,1,1], 2)).to.equal(1);", - "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);", - "expect(pairwise([], 100)).to.equal(0);" + "assert.deepEqual(pairwise([1, 4, 2, 3, 0, 5], 7), 11, 'message: pairwise([1, 4, 2, 3, 0, 5], 7) should return 11.');", + "expect(pairwise([1, 3, 2, 4], 4), 1, 'message: pairwise([1, 3, 2, 4], 4), 1 should return 1.');", + "expect(pairwise([1,1,1], 2), 1, 'message: pairwise([1,1,1], 2) should return 1.');", + "expect(pairwise([0, 0, 0, 0, 1, 1], 1), 10, 'message: pairwise([0, 0, 0, 0, 1, 1], 1) should return 10.');", + "expect(pairwise([], 100), 0, 'message: pairwise([], 100) should return 0.');" ], "MDNlinks": [ "Array.reduce()" From cbc21ee03f308d534616465c7d5c8c85dde767fc Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 29 Sep 2015 15:00:27 -0700 Subject: [PATCH 41/63] refactor messages on basic and advanced bonfires --- seed/challenges/advanced-bonfires.json | 98 ++++++++-------- seed/challenges/basic-bonfires.json | 152 ++++++++++++------------- 2 files changed, 125 insertions(+), 125 deletions(-) diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index b186b9290d..dd4b9d3778 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -20,27 +20,27 @@ ], "tests": [ "assert.isBoolean(telephoneCheck(\"555-555-5555\"), 'message: should return a boolean.');", - "assert(telephoneCheck(\"1 555-555-5555\") === true, 'message: 1 555-555-5555 should return true.');", - "assert(telephoneCheck(\"1 (555) 555-5555\") === true, 'message: 1 (555) 555-5555 should return true.');", - "assert(telephoneCheck(\"5555555555\") === true, 'message: 5555555555 should return true.');", - "assert(telephoneCheck(\"555-555-5555\") === true, 'message: 555-555-5555 should return true.');", - "assert(telephoneCheck(\"(555)555-5555\") === true, 'message: (555)555-5555 should return true.');", - "assert(telephoneCheck(\"1(555)555-5555\") === true, 'message: 1(555)555-5555 should return true.');", - "assert(telephoneCheck(\"1 555 555 5555\") === true, 'message: 1 555 555 5555 should return true.');", - "assert(telephoneCheck(\"555-555-5555\") === true, 'message: 555-555-5555 should return true.');", - "assert(telephoneCheck(\"1 456 789 4444\") === true, 'message: 1 456 789 4444 should return true.');", - "assert(telephoneCheck(\"123**&!!asdf#\") === false, 'message: 123**&!!asdf# should return false.');", - "assert(telephoneCheck(\"55555555\") === false, 'message: 55555555 should return false.');", - "assert(telephoneCheck(\"(6505552368)\") === false, 'message: (6505552368) should return false');", - "assert(telephoneCheck(\"2 (757) 622-7382\") === false, 'message: 2 (757) 622-7382 should return false.');", - "assert(telephoneCheck(\"0 (757) 622-7382\") === false, 'message: 0 (757) 622-7382 should return false.');", - "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, 'message: -1 (757) 622-7382 should return false');", - "assert(telephoneCheck(\"2 757 622-7382\") === false, 'message: 2 757 622-7382 should return false.');", - "assert(telephoneCheck(\"10 (757) 622-7382\") === false, 'message: 10 (757) 622-7382 should return false.');", - "assert(telephoneCheck(\"27576227382\") === false, 'message: 27576227382 should return false.');", - "assert(telephoneCheck(\"(275)76227382\") === false, 'message: (275)76227382 should return false.');", - "assert(telephoneCheck(\"2(757)6227382\") === false, 'message: 2(757)6227382 should return false.');", - "assert(telephoneCheck(\"2(757)622-7382\") === false, 'message: 2(757)622-7382 should return false.');" + "assert(telephoneCheck(\"1 555-555-5555\") === true, 'message: telephoneCheck(\"1 555-555-5555\") should return true.');", + "assert(telephoneCheck(\"1 (555) 555-5555\") === true, 'message: telephoneCheck(\"1 (555) 555-5555\") should return true.');", + "assert(telephoneCheck(\"5555555555\") === true, 'message: telephoneCheck(\"5555555555\") should return true.');", + "assert(telephoneCheck(\"555-555-5555\") === true, 'message: telephoneCheck(\"555-555-5555\") should return true.');", + "assert(telephoneCheck(\"(555)555-5555\") === true, 'message: telephoneCheck(\"(555)555-5555\") should return true.');", + "assert(telephoneCheck(\"1(555)555-5555\") === true, 'message: telephoneCheck(\"1(555)555-5555\") should return true.');", + "assert(telephoneCheck(\"1 555 555 5555\") === true, 'message: telephoneCheck(\"1 555 555 5555\") should return true.');", + "assert(telephoneCheck(\"555-555-5555\") === true, 'message: telephoneCheck(\"555-555-5555\") should return true.');", + "assert(telephoneCheck(\"1 456 789 4444\") === true, 'message: telephoneCheck(\"1 456 789 4444\") should return true.');", + "assert(telephoneCheck(\"123**&!!asdf#\") === false, 'message: telephoneCheck(\"123**&!!asdf#\") should return false.');", + "assert(telephoneCheck(\"55555555\") === false, 'message: telephoneCheck(\"55555555\") should return false.');", + "assert(telephoneCheck(\"(6505552368)\") === false, 'message: telephoneCheck(\"(6505552368)\") should return false');", + "assert(telephoneCheck(\"2 (757) 622-7382\") === false, 'message: telephoneCheck(\"2 (757) 622-7382\") should return false.');", + "assert(telephoneCheck(\"0 (757) 622-7382\") === false, 'message: telephoneCheck(\"0 (757) 622-7382\") should return false.');", + "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, 'message: telephoneCheck(\"-1 (757) 622-7382\") should return false');", + "assert(telephoneCheck(\"2 757 622-7382\") === false, 'message: telephoneCheck(\"2 757 622-7382\") should return false.');", + "assert(telephoneCheck(\"10 (757) 622-7382\") === false, 'message: telephoneCheck(\"10 (757) 622-7382\") should return false.');", + "assert(telephoneCheck(\"27576227382\") === false, 'message: telephoneCheck(\"27576227382\") should return false.');", + "assert(telephoneCheck(\"(275)76227382\") === false, 'message: telephoneCheck(\"(275)76227382\") should return false.');", + "assert(telephoneCheck(\"2(757)6227382\") === false, 'message: telephoneCheck(\"2(757)6227382\") should return false.');", + "assert(telephoneCheck(\"2(757)622-7382\") === false, 'message: telephoneCheck(\"2(757)622-7382\") should return false.');" ], "challengeSeed": [ "function telephoneCheck(str) {", @@ -85,10 +85,10 @@ "sym([1, 2, 3], [5, 2, 1, 4]);" ], "tests": [ - "assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 5, 4], 'message: [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: [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: [1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5] should return [1, 4, 5].');", - "assert.sameMembers(sym([1, 1]), [1], 'message: [1, 1] should return [1].');" + "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].');" ], "MDNlinks": [ "Array.reduce()", @@ -139,13 +139,13 @@ "drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]);" ], "tests": [ - "assert.isArray(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), 'message: 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]] should return an array.');", - "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'message: 19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]] should return a string.');", - "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'message: 19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]] should return a string.');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'message: 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]]) should return [['QUARTER', 0.50]].');", - "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04]], 'message: 3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]] should return [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04]].');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'message: 19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]] should return \"Insufficient Funds\".');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'message: 19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]] should return \"Closed\".');" + "assert.isArray(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), 'message: drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]) should return an array.');", + "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'message: drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]) should return a string.');", + "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'message: drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]) should return a string.');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'message: drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]) should return [['QUARTER', 0.50]].');", + "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04]], 'message: drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]) should return [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04]].');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'message: drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]) should return \"Insufficient Funds\".');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'message: drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]) should return \"Closed\".');" ], "MDNlinks": [ "Global Object" @@ -197,10 +197,10 @@ "tests": [ "assert.isArray(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), 'message: inventory() should return an array.');", "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6, 'message: inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length should return an array with a length of 6.');", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']], 'message: [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']] should return [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']].');", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], 'message: [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [] should return [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']].);", - "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']], 'message: [], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']] should return [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']].');", - "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']], 'message: [[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']] should return [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']].');" + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']], 'message: inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]) should return [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']].');", + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], 'message: inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []) should return [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']].);", + "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']], 'message: inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]) should return [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']].');", + "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']], 'message: inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]) should return [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']].');" ], "MDNlinks": [ "Global Array Object" @@ -235,13 +235,13 @@ "permAlone('aab');" ], "tests": [ - "assert.isNumber(permAlone('aab'), 'message: aab should return a number.');", - "assert.strictEqual(permAlone('aab'), 2, 'message: aab should return 2.');", - "assert.strictEqual(permAlone('aaa'), 0, 'message: aaa should return 0.');", - "assert.strictEqual(permAlone('aabb'), 8, 'message: aabb should return 8.');", - "assert.strictEqual(permAlone('abcdefa'), 3600, 'message: abcdefa should return 3600.');", - "assert.strictEqual(permAlone('abfdefa'), 2640, 'message: abfdefa should return 2640.');", - "assert.strictEqual(permAlone('zzzzzzzz'), 0, 'message: zzzzzzzz should return 0.');" + "assert.isNumber(permAlone('aab'), 'message: permAlone() should return a number.');", + "assert.strictEqual(permAlone('aab'), 2, 'message: permAlone(aab) should return 2.');", + "assert.strictEqual(permAlone('aaa'), 0, 'message: permAlone(aaa) should return 0.');", + "assert.strictEqual(permAlone('aabb'), 8, 'message: permAlone(aabb) should return 8.');", + "assert.strictEqual(permAlone('abcdefa'), 3600, 'message: permAlone(abcdefa) should return 3600.');", + "assert.strictEqual(permAlone('abfdefa'), 2640, 'message: permAlone(abfdefa) should return 2640.');", + "assert.strictEqual(permAlone('zzzzzzzz'), 0, 'message: permAlone(zzzzzzzz) should return 0.');" ], "MDNlinks": [ "Permutations", @@ -281,12 +281,12 @@ "friendly(['2015-07-01', '2015-07-04']);" ], "tests": [ - "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'message: [\"2015-07-01\", \"2015-07-04\"] should return [\"July 1st\",\"4th\"].');", - "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'message: [\"2015-12-01\", \"2016-02-03\"] should return [\"December 1st\",\"February 3rd\"].');", - "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017'], 'message: [\"2015-12-01\", \"2017-02-03\"] should return [\"December 1st, 2015\",\"February 3rd, 2017\"].');", - "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th'], 'message: [\"2016-03-01\", \"2016-05-05\"] should return [\"March 1st\",\"May 5th\"]');", - "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'message: [\"2017-01-01\", \"2017-01-01\"] should return [\"January 1st, 2017\"].');", - "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023'], 'message: [\"2022-09-05\", \"2023-09-04\"] should return [\"September 5th, 2022\",\"September 4th, 2023\"].');" + "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'message: friendly([\"2015-07-01\", \"2015-07-04\"]) should return [\"July 1st\",\"4th\"].');", + "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'message: friendly([\"2015-12-01\", \"2016-02-03\"]) should return [\"December 1st\",\"February 3rd\"].');", + "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017'], 'message: friendly([\"2015-12-01\", \"2017-02-03\"]) should return [\"December 1st, 2015\",\"February 3rd, 2017\"].');", + "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th'], 'message: friendly([\"2016-03-01\", \"2016-05-05\"]) should return [\"March 1st\",\"May 5th\"]');", + "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'message: friendly([\"2017-01-01\", \"2017-01-01\"]) should return [\"January 1st, 2017\"].');", + "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023'], 'message: friendly([\"2022-09-05\", \"2023-09-04\"]) should return [\"September 5th, 2022\",\"September 4th, 2023\"].');" ], "MDNlinks": [ "String.split()", diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index f94842ebaa..c903c225d5 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -13,8 +13,8 @@ "Make this function return true no matter what." ], "tests": [ - "assert(typeof(meetBonfire()) === \"boolean\", 'message: The result should be a Boolean value of true or false.');", - "assert(meetBonfire() === true, 'message: Your meetBonfire() function should return true.');" + "assert(typeof(meetBonfire()) === \"boolean\", 'message: meetBonfire() should return a boolean value.');", + "assert(meetBonfire() === true, 'message: meetBonfire() should return true.');" ], "challengeSeed": [ "function meetBonfire(argument) {", @@ -46,10 +46,10 @@ "title": "Reverse a String", "difficulty": "1.01", "tests": [ - "assert(typeof(reverseString(\"hello\")) === \"string\", 'message: reverseString() should return a string.');", - "assert(reverseString(\"hello\") === \"olleh\", 'message: \"hello\" should become \"olleh\".');", - "assert(reverseString(\"Howdy\") === \"ydwoH\", 'message: \"Howdy\" should become \"ydwoH\".');", - "assert(reverseString(\"Greetings from Earth\") === \"htraE morf sgniteerG\", 'message: \"Greetings from Earth\" should return \"htraE morf sgniteerG\".');" + "assert(typeof(reverseString(\"hello\")) === \"string\", 'message: reverseString() should return a string.');", + "assert(reverseString(\"hello\") === \"olleh\", 'message: reverseString(\"hello\") should become \"olleh\".');", + "assert(reverseString(\"Howdy\") === \"ydwoH\", 'message: reverseString(\"Howdy\") should become \"ydwoH\".');", + "assert(reverseString(\"Greetings from Earth\") === \"htraE morf sgniteerG\", 'message: reverseString(\"Greetings from Earth\") should return \"htraE morf sgniteerG\".');" ], "description": [ "Reverse the provided string.", @@ -87,11 +87,11 @@ "id": "a302f7aae1aa3152a5b413bc", "title": "Factorialize a Number", "tests": [ - "assert(typeof(factorialize(5)) === \"number\", 'message: factorialize() should return a number.');", - "assert(factorialize(5) === 120, 'message: 5 should return 120.');", - "assert(factorialize(10) === 3628800, 'message: 10 should return 3,628,800.');", - "assert(factorialize(20) === 2432902008176640000, 'message: 20 should return 2,432,902,008,176,640,000.');", - "assert(factorialize(0) === 1, 'message: 0 should return 1.');" + "assert(typeof(factorialize(5)) === \"number\", 'message: factorialize() should return a number.');", + "assert(factorialize(5) === 120, 'message: factorialize(5) should return 120.');", + "assert(factorialize(10) === 3628800, 'message: factorialize(10) should return 3,628,800.');", + "assert(factorialize(20) === 2432902008176640000, 'message: factorialize(20) should return 2,432,902,008,176,640,000.');", + "assert(factorialize(0) === 1, 'message: factorialize(0) should return 1.');" ], "difficulty": "1.02", "description": [ @@ -136,17 +136,17 @@ "Remember to use Read-Search-Ask if you get stuck. Write your own code." ], "tests": [ - "assert(typeof(palindrome(\"eye\")) === \"boolean\", 'message: palindrome() should return a boolean.');", - "assert(palindrome(\"eye\") === true, 'message: \"eye\" should return true.');", - "assert(palindrome(\"race car\") === true, 'message: \"race car\" should return true.');", - "assert(palindrome(\"not a palindrome\") === false, 'message: \"not a palindrome\" should return false.');", - "assert(palindrome(\"A man, a plan, a canal. Panama\") === true, 'message: \"A man, a plan, a canal. Panama\" should return true.');", - "assert(palindrome(\"never odd or even\") === true, 'message: \"never odd or even\" should return true.');", - "assert(palindrome(\"nope\") === false, 'message: \"nope\" should return false.');", - "assert(palindrome(\"almostomla\") === false, 'message: \"almostomla\" should return false.');", - "assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, 'message: \"My age is 0, 0 si ega ym.\" should return true.');", - "assert(palindrome(\"1 eye for of 1 eye.\") === false, 'message: \"1 eye for of 1 eye.\" should return false.');", - "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, 'message: \"0_0 (: /-\\\\ :) 0-0\" should return true.');" + "assert(typeof(palindrome(\"eye\")) === \"boolean\", 'message: palindrome() should return a boolean.');", + "assert(palindrome(\"eye\") === true, 'message: palindrome(\"eye\") should return true.');", + "assert(palindrome(\"race car\") === true, 'message: palindrome(\"race car\") should return true.');", + "assert(palindrome(\"not a palindrome\") === false, 'message: palindrome(\"not a palindrome\") should return false.');", + "assert(palindrome(\"A man, a plan, a canal. Panama\") === true, 'message: palindrome(\"A man, a plan, a canal. Panama\") should return true.');", + "assert(palindrome(\"never odd or even\") === true, 'message: palindrome(\"never odd or even\") should return true.');", + "assert(palindrome(\"nope\") === false, 'message: palindrome(\"nope\") should return false.');", + "assert(palindrome(\"almostomla\") === false, 'message: 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.');" ], "challengeSeed": [ "function palindrome(str) {", @@ -192,12 +192,12 @@ "findLongestWord(\"The quick brown fox jumped over the lazy dog\");" ], "tests": [ - "assert(typeof(findLongestWord(\"The quick brown fox jumped over the lazy dog\")) === \"number\", 'message: findLongestWord() should return a number.');", - "assert(findLongestWord(\"The quick brown fox jumped over the lazy dog\") === 6, 'message: \"The quick brown fox jumped over the lazy dog\" should return 6.');", - "assert(findLongestWord(\"May the force be with you\") === 5, 'message: \"May the force be with you\" should return 5.');", - "assert(findLongestWord(\"Google do a barrel roll\") === 6, 'message: \"Google do a barrel roll\" should return 6.');", - "assert(findLongestWord(\"What is the average airspeed velocity of an unladen swallow\") === 8, 'message: \"What is the average airspeed velocity of an unladen swallow\" should return 8.');", - "assert(findLongestWord(\"What if we try a super-long word such as otorhinolaryngology\") === 19, 'message: \"What if we try a super-long word such as otorhinolaryngology\" should return 19.');" + "assert(typeof(findLongestWord(\"The quick brown fox jumped over the lazy dog\")) === \"number\", 'message: findLongestWord() should return a number.');", + "assert(findLongestWord(\"The quick brown fox jumped over the lazy dog\") === 6, 'message: findLongestWord(\"The quick brown fox jumped over the lazy dog\") should return 6.');", + "assert(findLongestWord(\"May the force be with you\") === 5, 'message: findLongestWord(\"May the force be with you\") should return 5.');", + "assert(findLongestWord(\"Google do a barrel roll\") === 6, 'message: findLongestWord(\"Google do a barrel roll\") should return 6.');", + "assert(findLongestWord(\"What is the average airspeed velocity of an unladen swallow\") === 8, 'message: findLongestWord(\"What is the average airspeed velocity of an unladen swallow\") should return 8.');", + "assert(findLongestWord(\"What if we try a super-long word such as otorhinolaryngology\") === 19, 'message: findLongestWord(\"What if we try a super-long word such as otorhinolaryngology\") should return 19.');" ], "MDNlinks": [ "String.split()", @@ -233,10 +233,10 @@ "titleCase(\"I'm a little tea pot\", \"\");" ], "tests": [ - "assert(typeof(titleCase(\"I'm a little tea pot\")) === \"string\", 'message: titleCase() should return a string.');", - "assert(titleCase(\"I'm a little tea pot\") === \"I'm A Little Tea Pot\", 'message: \"I'm a little tea pot\" should return \"I'm A Little Tea Pot\".');", - "assert(titleCase(\"sHoRt AnD sToUt\") === \"Short And Stout\", 'message: \"sHoRt AnD sToUt\" should return \"Short And Stout\".');", - "assert(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\") === \"Here Is My Handle Here Is My Spout\", 'message: \"HERE IS MY HANDLE HERE IS MY SPOUT\" should return \"Here Is My Handle Here Is My Spout\"');" + "assert(typeof(titleCase(\"I'm a little tea pot\")) === \"string\", 'message: titleCase() should return a string.');", + "assert(titleCase(\"I'm a little tea pot\") === \"I'm A Little Tea Pot\", 'message: titleCase(\"I'm a little tea pot\") should return \"I'm A Little Tea Pot\".');", + "assert(titleCase(\"sHoRt AnD sToUt\") === \"Short And Stout\", 'message: titleCase(\"sHoRt AnD sToUt\") should return \"Short And Stout\".');", + "assert(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\") === \"Here Is My Handle Here Is My Spout\", 'message: titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\") should return \"Here Is My Handle Here Is My Spout\".');" ], "MDNlinks": [ "String.charAt()" @@ -273,9 +273,9 @@ "largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);" ], "tests": [ - "assert(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]).constructor === Array, 'message: largestOfFour() should return an array.');", - "assert.deepEqual(largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]), [27,5,39,1001], 'message: [[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]] should return [27,5,39,1001].');", - "assert.deepEqual(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]), [9,35,97,1000000], 'message: [[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]] should return [9, 35, 97, 1000000].');" + "assert(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]).constructor === Array, 'message: largestOfFour() should return an array.');", + "assert.deepEqual(largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]), [27,5,39,1001], 'message: largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]) should return [27,5,39,1001].');", + "assert.deepEqual(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]), [9,35,97,1000000], 'message: largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]) should return [9, 35, 97, 1000000].');" ], "MDNlinks": [ "Comparison Operators" @@ -311,11 +311,11 @@ "end(\"Bastian\", \"n\", \"\");" ], "tests": [ - "assert(end(\"Bastian\", \"n\") === true, 'message: \"Bastian\", \"n\" should return true.');", - "assert(end(\"Connor\", \"n\") === false, 'message: \"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: \"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: \"He has to give me a new name\", \"name\" 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: \"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.');" + "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(\"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(\"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.');" ], "MDNlinks": [ "String.substr()" @@ -350,9 +350,9 @@ "repeat(\"abc\", 3, \"\");" ], "tests": [ - "assert(repeat(\"*\", 3) === \"***\", 'message: \"*\", 3 should return \"***\".');", - "assert(repeat(\"abc\", 3) === \"abcabcabc\", 'message: \"abc\", 3 should return \"abcabcabc\".');", - "assert(repeat(\"abc\", -2) === \"\", 'message: \"abc\", -2 should return \"\".');" + "assert(repeat(\"*\", 3) === \"***\", 'message: repeat(\"*\", 3) should return \"***\".');", + "assert(repeat(\"abc\", 3) === \"abcabcabc\", 'message: repeat(\"abc\", 3) should return \"abcabcabc\".');", + "assert(repeat(\"abc\", -2) === \"\", 'message: repeat(\"abc\", -2) should return \"\".');" ], "MDNlinks": [ "Global String Object" @@ -388,10 +388,10 @@ "truncate(\"A-tisket a-tasket A green and yellow basket\", 11, \"\");" ], "tests": [ - "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", 'message: \"A-tisket a-tasket A green and yellow basket\", 1 should return \"A-tisket...\".');", - "assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", 'message: \"Peter Piper picked a peck of pickled peppers\", 14 should return \"Peter Piper...\".');", - "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", 'message: \"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) should return \"A-tisket a-tasket A green and yellow basket\".');", - "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', 'message: \"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2 should return \"A-tisket a-tasket A green and yellow basket\".');" + "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", 'message: truncate(\"A-tisket a-tasket A green and yellow basket\", 1) should return \"A-tisket...\".');", + "assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", 'message: truncate(\"Peter Piper picked a peck of pickled peppers\", 14) should return \"Peter Piper...\".');", + "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", 'message: truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) should return \"A-tisket a-tasket A green and yellow basket\".');", + "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', 'message: truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2) should return \"A-tisket a-tasket A green and yellow basket\".');" ], "MDNlinks": [ "String.slice()" @@ -426,10 +426,10 @@ "chunk([\"a\", \"b\", \"c\", \"d\"], 2, \"\");" ], "tests": [ - "assert.deepEqual(chunk([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], 'message: [\"a\", \"b\", \"c\", \"d\"], 2 should return [[\"a\", \"b\"], [\"c\", \"d\"]].');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'message: [0, 1, 2, 3, 4, 5] should return [[0, 1, 2], [3, 4, 5]].');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 2), [[0, 1], [2, 3], [4, 5]], 'message: [0, 1, 2, 3, 4, 5], 2 should return [[0, 1], [2, 3], [4, 5]].');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'message: [0, 1, 2, 3, 4, 5], 4 should return [[0, 1, 2, 3], [4, 5]].');" + "assert.deepEqual(chunk([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], 'message: chunk([\"a\", \"b\", \"c\", \"d\"], 2) should return [[\"a\", \"b\"], [\"c\", \"d\"]].');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'message: chunk([0, 1, 2, 3, 4, 5], 3) should return [[0, 1, 2], [3, 4, 5]].');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 2), [[0, 1], [2, 3], [4, 5]], 'message: chunk([0, 1, 2, 3, 4, 5], 2) should return [[0, 1], [2, 3], [4, 5]].');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'message: chunk([0, 1, 2, 3, 4, 5], 4) should return [[0, 1, 2, 3], [4, 5]].');" ], "MDNlinks": [ "Array.push()" @@ -464,9 +464,9 @@ "slasher([1, 2, 3], 2, \"\");" ], "tests": [ - "assert.deepEqual(slasher([1, 2, 3], 2), [3], 'message: [1, 2, 3], 2, [3] should return [3].');", - "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], 'message: [1, 2, 3], 0 should return [1, 2, 3].');", - "assert.deepEqual(slasher([1, 2, 3], 9), [], 'message: [1, 2, 3], 9 should return [].');" + "assert.deepEqual(slasher([1, 2, 3], 2), [3], 'message: slasher([1, 2, 3], 2, [3]) should return [3].');", + "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], 'message: slasher([1, 2, 3], 0) should return [1, 2, 3].');", + "assert.deepEqual(slasher([1, 2, 3], 9), [], 'message: slasher([1, 2, 3], 9) should return [].');" ], "MDNlinks": [ "Array.slice()", @@ -504,14 +504,14 @@ "mutation([\"hello\", \"hey\"], \"\");" ], "tests": [ - "assert(mutation([\"hello\", \"hey\"]) === false, 'message: [\"hello\", \"hey\"] should return false.');", - "assert(mutation([\"hello\", \"Hello\"]) === true, 'message: [\"hello\", \"Hello\"] should return true.');", - "assert(mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) === true, 'message: [\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"] should return true.');", - "assert(mutation([\"Mary\", \"Army\"]) === true, 'message: [\"Mary\", \"Army\"] should return true.');", - "assert(mutation([\"Mary\", \"Aarmy\"]) === true, 'message: [\"Mary\", \"Aarmy\"] should return true.');", - "assert(mutation([\"Alien\", \"line\"]) === true, 'message: [\"Alien\", \"line\"] should return true.');", - "assert(mutation([\"floor\", \"for\"]) === true, 'message: [\"floor\", \"for\"] should return true.');", - "assert(mutation([\"hello\", \"neo\"]) === false, 'message: [\"hello\", \"neo\"] should return false.');" + "assert(mutation([\"hello\", \"hey\"]) === false, 'message: mutation([\"hello\", \"hey\"]) should return false.');", + "assert(mutation([\"hello\", \"Hello\"]) === true, 'message: mutation([\"hello\", \"Hello\"]) should return true.');", + "assert(mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) === true, 'message: mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) should return true.');", + "assert(mutation([\"Mary\", \"Army\"]) === true, 'message: mutation([\"Mary\", \"Army\"]) should return true.');", + "assert(mutation([\"Mary\", \"Aarmy\"]) === true, 'message: mutation([\"Mary\", \"Aarmy\"]) should return true.');", + "assert(mutation([\"Alien\", \"line\"]) === true, 'message: mutation([\"Alien\", \"line\"]) should return true.');", + "assert(mutation([\"floor\", \"for\"]) === true, 'message: mutation([\"floor\", \"for\"]) should return true.');", + "assert(mutation([\"hello\", \"neo\"]) === false, 'message: mutation([\"hello\", \"neo\"]) should return false.');" ], "MDNlinks": [ "Array.indexOf()" @@ -547,9 +547,9 @@ "bouncer([7, \"ate\", \"\", false, 9], \"\");" ], "tests": [ - "assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], 'message: [7, \"ate\", \"\", false, 9] should return [7, \"ate\", 9].');", - "assert.deepEqual(bouncer([\"a\", \"b\", \"c\"]), [\"a\", \"b\", \"c\"], 'message: [\"a\", \"b\", \"c\"] should return [\"a\", \"b\", \"c\"].');", - "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, '']), [], 'message: [false, null, 0] should return [].');" + "assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], 'message: bouncer([7, \"ate\", \"\", false, 9]) should return [7, \"ate\", 9].');", + "assert.deepEqual(bouncer([\"a\", \"b\", \"c\"]), [\"a\", \"b\", \"c\"], 'message: bouncer([\"a\", \"b\", \"c\"]) should return [\"a\", \"b\", \"c\"].');", + "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, '']), [], 'message: bouncer([false, null, 0]) should return [].');" ], "MDNlinks": [ "Boolean Objects", @@ -585,11 +585,11 @@ "destroyer([1, 2, 3, 1, 2, 3], 2, 3, \"\");" ], "tests": [ - "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'message: [1, 2, 3, 1, 2, 3], 2, 3 should return [1, 1].');", - "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'message: [1, 2, 3, 5, 1, 2, 3], 2, 3 should return [1, 5, 1].');", - "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], 'message: [3, 5, 1, 2, 2], 2, 3, 5 should return [1].');", - "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], 'message: [2, 3, 2, 3], 2, 3 should return [].');", - "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], 'message: [\"tree\", \"hamburger\", 53], \"tree\", 53) should return [\"hamburger\"].');" + "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'message: destroyer([1, 2, 3, 1, 2, 3], 2, 3) should return [1, 1].');", + "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'message: destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3) should return [1, 5, 1].');", + "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], 'message: destroyer([3, 5, 1, 2, 2], 2, 3, 5) should return [1].');", + "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], 'message: destroyer([2, 3, 2, 3], 2, 3) should return [].');", + "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], 'message: destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53) should return [\"hamburger\"].');" ], "MDNlinks": [ "Arguments object", @@ -629,12 +629,12 @@ "Array.sort()" ], "tests": [ - "assert(where([10, 20, 30, 40, 50], 35) === 3, 'message: [10, 20, 30, 40, 50], 35 should return 3.');", - "assert(where([10, 20, 30, 40, 50], 30) === 2, 'message: [10, 20, 30, 40, 50], 30) should return 2.');", - "assert(where([40, 60], 50) === 1, 'message: [40, 60,], 50 should return 1.');", - "assert(where([5, 3, 20, 3], 3) === 0, 'message: [5, 3, 20, 3], 3 should return 0.');", - "assert(where([2, 20, 10], 1) === 0, 'message: [2, 20, 10], 1 should return 0.');", - "assert(where([2, 5, 10], 15) === 3, 'message: [2, 5, 10], 15 should return 3.');" + "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([2, 5, 10], 15) === 3, 'message: where([2, 5, 10], 15) should return 3.');" ], "type": "bonfire", "challengeType": 5, From ee9827ea587e38c3cd3e6ae5978766832b71d336 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 29 Sep 2015 17:59:16 -0700 Subject: [PATCH 42/63] fix issues with get-started and remove pair button --- server/views/coursewares/showBonfire.jade | 41 ------------------- .../coursewares/showZiplineOrBasejump.jade | 3 -- server/views/partials/challenge-modals.jade | 14 ------- server/views/resources/get-started.jade | 24 ++--------- 4 files changed, 4 insertions(+), 78 deletions(-) diff --git a/server/views/coursewares/showBonfire.jade b/server/views/coursewares/showBonfire.jade index 52ec4a097b..e64424e1ac 100644 --- a/server/views/coursewares/showBonfire.jade +++ b/server/views/coursewares/showBonfire.jade @@ -21,44 +21,6 @@ block content .innerMarginFix(style=' width: 99%') #testCreatePanel.well h3.text-center.negative-10= name - .positive-15.positive-15-bottom - h4.text-center.bonfire-flames Difficulty:  - if (difficulty == "0") - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - if (difficulty == "1") - i.ion-ios-flame - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - if (difficulty == "2") - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - if (difficulty == "3") - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame-outline - i.ion-ios-flame-outline - if (difficulty == "4") - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame-outline - if (difficulty == "5") - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame .row .col-xs-12 .bonfire-instructions @@ -93,9 +55,6 @@ block content label.btn.btn-success#trigger-help-modal i.fa.fa-medkit |   Help - label.btn.btn-success#trigger-pair-modal - i.fa.fa-user-plus - |   Pair label.btn.btn-success#trigger-issue-modal i.fa.fa-bug |   Bug diff --git a/server/views/coursewares/showZiplineOrBasejump.jade b/server/views/coursewares/showZiplineOrBasejump.jade index 58f84f1c77..174be42e3e 100644 --- a/server/views/coursewares/showZiplineOrBasejump.jade +++ b/server/views/coursewares/showZiplineOrBasejump.jade @@ -27,9 +27,6 @@ block content .btn.btn-success.btn-big#trigger-help-modal i.fa.fa-medkit |   Help - .btn.btn-success.btn-big#trigger-pair-modal - i.fa.fa-user-plus - |   Pair .btn.btn-success.btn-big#trigger-issue-modal i.fa.fa-bug |   Bug diff --git a/server/views/partials/challenge-modals.jade b/server/views/partials/challenge-modals.jade index 4503e2ac17..746c1a6929 100644 --- a/server/views/partials/challenge-modals.jade +++ b/server/views/partials/challenge-modals.jade @@ -1,17 +1,3 @@ -#pair-modal.modal(tabindex='-1') - .modal-dialog.animated.fadeIn.fast-animation - .modal-content - .modal-header.challenge-list-header Ready to pair program? - a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × - .modal-body.text-center - h3 This will take you to our pair programming room where you can request a pair. - h3 You'll need   - a(href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-install-Screenhero' target='_blank') Screenhero - | . - h3 Other campers may then message you about pair programming. - a.btn.btn-lg.btn-primary.btn-block.close-modal(href='https://gitter.im/FreeCodeCamp/LetsPair', target='_blank') Take me to the pair programming room - a.btn.btn-lg.btn-info.btn-block(href='#', data-dismiss='modal', aria-hidden='true') Cancel - #issue-modal.modal(tabindex='-1') .modal-dialog.animated.fadeIn.fast-animation .modal-content diff --git a/server/views/resources/get-started.jade b/server/views/resources/get-started.jade index a3d19984f8..8767841a66 100644 --- a/server/views/resources/get-started.jade +++ b/server/views/resources/get-started.jade @@ -65,7 +65,7 @@ block content .big-spacer .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/EZHzKCV.gif' alt='A gif showing you how to click the link below to go to our chat room and click the \"sign in with GitHub\" button. Then you can click into the text input field and type a message to your fellow campers.') + img.gif-block.img-center.img-responsive(src='http://i.imgur.com/Uuc2Ked.gif' alt='A gif showing you how to click the link below to go to our chat room and click the \"sign in with GitHub\" button. Then you can click into the text input field and type a message to your fellow campers.') .caption p.large-p Try this:  | Now that you have a GitHub account, you can  @@ -99,12 +99,6 @@ block content a(href='https://gitter.im/apps' target='_blank') download the chat room app |  to your computer or phone. - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/DoOqkNW.gif' alt='A gif showing how you can click the "Wiki" button in your upper-right corner to access the wiki.') - .caption - p.large-p Try this: Click the "Wiki" button in your upper right hand corner. Our community has contributed lots of useful information to this searchable wiki. - .big-spacer .thumbnail img.gif-block.img-center.img-responsive(src='http://i.imgur.com/FkEzbto.gif' alt='A gif showing how you can click your profile image in your upper right hand corner to access the account page and connect GitHub.') @@ -128,25 +122,15 @@ block content .thumbnail img.gif-block.img-center.img-responsive(src='http://i.imgur.com/Elb3dfj.jpg' alt='A picture of some of our campers meeting in a local cafe. 3 men and 3 women are sitting around a table with laptops out, and are smiling and coding.') .caption - p.large-p Our Campsites help you code with campers in your city. You can coordinate study groups or attend local coding events together. + p.large-p Our Campsites help you code with campers in your city. You can discuss coding and attend local Coffee-n-Code events. .big-spacer .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/EZHzKCV.gif' alt="A gif showing how you can click the link below, find your city on the list of Campsites, then click on the Facebook link for your city and join your city's Facebook group.") + img.gif-block.img-center.img-responsive(src='http://i.imgur.com/tYf8jrI.gif' alt="A gif showing how you can click the link below, find your city on the list of Campsites, then click on the Facebook link for your city and join your city's Facebook group.") .caption p.large-p Try this:  a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites' target='_blank') Find your city on this list - | . Click the "Join group" button to join your city's Facebook group. If your city isn't on this list,  - a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/How-to-create-a-Campsite-for-your-city' target='_blank') follow these directions to create a Facebook group for your city - | . - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/3AgvJQg.gif' alt="A gif showing how click the link below, find your city, and click the \"Gitter\" button to join your city's Gitter chat room") - .caption - p.large-p Try this:  - a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites' target='_blank') Go back to our list of Campsites  - | and click "Gitter" to join your city's chat room. + | , then click it. Click the "Join group" button to join your city's Campsite. .big-spacer .thumbnail From cdf8c6a54c8c02beb7cd6c5c6e7bb7f0414c922f Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Tue, 29 Sep 2015 22:12:02 -0700 Subject: [PATCH 43/63] fix check for existance when getting last challenge --- server/boot/challenge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/boot/challenge.js b/server/boot/challenge.js index 239d21d4d0..4ce4937e67 100644 --- a/server/boot/challenge.js +++ b/server/boot/challenge.js @@ -519,7 +519,7 @@ module.exports = function(app) { const lastCompletedBlock = _.findLast(blocks, (block) => { return block.completed === 100; }); - lastCompleted = lastCompletedBlock.name; + lastCompleted = lastCompleted && lastCompletedBlock.name || null; }); Observable.combineLatest( From ab204c654ea8fd84278100a2450d38a381a2ea06 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 28 Sep 2015 20:48:56 -0700 Subject: [PATCH 44/63] fix search results formatting for mobile and desktop camper news --- server/views/stories/news-nav.jade | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/server/views/stories/news-nav.jade b/server/views/stories/news-nav.jade index fcf7018933..16631279c1 100644 --- a/server/views/stories/news-nav.jade +++ b/server/views/stories/news-nav.jade @@ -13,15 +13,6 @@ .visible-xs .button-spacer -//.spacer -//.row -// .col-xs-12.col-sm-8.col-sm-offset-2.well -// h4.text-center Which other free resources do you use? -// img.img-responsive(src='https://www.evernote.com/l/AHRNhlwViM1Kh5qCm6iy7MSWrbdyxYbRkWkB/image.png') -// p Link us to your favorite free coding resources. -// p Use the headline: "Awesome Free Resource: (the name of the book, podcast, or video series)". We'll publish a list of the 25 most-upvoted resources (and the campers who submitted them) in Wednesday's blog post, and in an upcoming Field Guide article. Also - as always - you'll get 1 point every time someone upvotes your post. -//.spacer - #search-results .spacer @@ -58,6 +49,9 @@ script. }) .done(function (data, textStatus, xhr) { $('#search-results').empty(); + var spacer = document.createElement('div'); + $(spacer).html("

"); + $(spacer).appendTo($('#search-results')); for (var i = 0; i < data.length; i++) { var div = document.createElement('div'); var linkedName = getLinkedName(data[i].storyLink); @@ -117,7 +111,7 @@ script. $(div).appendTo($('#search-results')); } var hr = document.createElement("div"); - $(hr).html("

End search results

") + $(hr).html("

End search results

") $(hr).appendTo($('#search-results')); }); } From ab72094333652a867a8b55c6cd42b08fbb23c1d8 Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 30 Sep 2015 02:40:21 -0400 Subject: [PATCH 45/63] Remove Unnecessary Left Over Semicolon Remove left over semicolon from function that was converted from an anonymous function at https://github.com/FreeCodeCamp/FreeCodeCamp/issues/3287 --- seed/challenges/basic-javascript.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index 13c28c2021..80ff4839bf 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -686,7 +686,7 @@ "", "function ourFunction(a, b) {", " return a - b;", - "};", + "}", "", "// Create a function called myFunction that returns the value of a plus b.", "// Only change code below this line.", From 03675ef0a6ee4453186e87b4574634db794cfe48 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Wed, 30 Sep 2015 01:33:07 -0700 Subject: [PATCH 46/63] finish QAing basic and intermediate bonfires --- client/commonFramework.js | 2 +- client/less/main.less | 1 + seed/challenges/basic-bonfires.json | 10 +- seed/challenges/intermediate-bonfires.json | 142 ++++++++++----------- server/views/coursewares/showBonfire.jade | 38 ------ 5 files changed, 78 insertions(+), 115 deletions(-) diff --git a/client/commonFramework.js b/client/commonFramework.js index f43ddc65fb..e7fe48d574 100644 --- a/client/commonFramework.js +++ b/client/commonFramework.js @@ -581,7 +581,7 @@ var createTestDisplay = function() { } for (var i = 0; i < userTests.length; i++) { var didTestPass = !userTests[i].err; - var testText = userTests[i].text.split('message: ').pop().replace(/\)|;|'/g, ''); + var testText = userTests[i].text.split('message: ').pop().replace(/\'\);/g, ''); var testDoc = document.createElement('div'); var iconClass = didTestPass ? diff --git a/client/less/main.less b/client/less/main.less index 7a7cbe8433..067290e9be 100644 --- a/client/less/main.less +++ b/client/less/main.less @@ -610,6 +610,7 @@ form.code span { .test-output { font-size: 15px; font-family: "Ubuntu Mono"; + margin-top: 8px; } #mainEditorPanel .panel-body { diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index c903c225d5..88a8dbb87a 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -89,8 +89,8 @@ "tests": [ "assert(typeof(factorialize(5)) === \"number\", 'message: factorialize() should return a number.');", "assert(factorialize(5) === 120, 'message: factorialize(5) should return 120.');", - "assert(factorialize(10) === 3628800, 'message: factorialize(10) should return 3,628,800.');", - "assert(factorialize(20) === 2432902008176640000, 'message: factorialize(20) should return 2,432,902,008,176,640,000.');", + "assert(factorialize(10) === 3628800, 'message: factorialize(10) should return 3628800.');", + "assert(factorialize(20) === 2432902008176640000, 'message: factorialize(20) should return 2432902008176640000.');", "assert(factorialize(0) === 1, 'message: factorialize(0) should return 1.');" ], "difficulty": "1.02", @@ -136,7 +136,7 @@ "Remember to use Read-Search-Ask if you get stuck. Write your own code." ], "tests": [ - "assert(typeof(palindrome(\"eye\")) === \"boolean\", 'message: palindrome() should return a boolean.');", + "assert(typeof(palindrome(\"eye\")) === \"boolean\", 'message: palindrome() should return a boolean.');", "assert(palindrome(\"eye\") === true, 'message: palindrome(\"eye\") should return true.');", "assert(palindrome(\"race car\") === true, 'message: palindrome(\"race car\") should return true.');", "assert(palindrome(\"not a palindrome\") === false, 'message: palindrome(\"not a palindrome\") should return false.');", @@ -535,7 +535,7 @@ "difficulty": "1.50", "description": [ "Remove all falsy values from an array.", - "Falsy values in javascript are false, null, 0, \"\", undefined, and NaN.", + "Falsy values in javascript are false, null, 0, \"\", undefined, and NaN.", "Remember to use Read-Search-Ask if you get stuck. Write your own code." ], "challengeSeed": [ @@ -549,7 +549,7 @@ "tests": [ "assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], 'message: bouncer([7, \"ate\", \"\", false, 9]) should return [7, \"ate\", 9].');", "assert.deepEqual(bouncer([\"a\", \"b\", \"c\"]), [\"a\", \"b\", \"c\"], 'message: bouncer([\"a\", \"b\", \"c\"]) should return [\"a\", \"b\", \"c\"].');", - "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, '']), [], 'message: bouncer([false, null, 0]) should return [].');" + "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, \"\"]), [], 'message: bouncer([false, null, 0, NaN, undefined, \"\"]) should return [].');" ], "MDNlinks": [ "Boolean Objects", diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json index 85fdf9cb61..35ccf0c7f9 100644 --- a/seed/challenges/intermediate-bonfires.json +++ b/seed/challenges/intermediate-bonfires.json @@ -19,11 +19,11 @@ "sumAll([1, 4]);" ], "tests": [ - "assert(typeof(sumAll([1, 4])) === \"number\", 'message: sumAll() should return a number');", - "assert.deepEqual(sumAll([1, 4]), 10, 'message: sumAll([1, 4]) should return 10');", - "assert.deepEqual(sumAll([4, 1]), 10, 'message: sumAll([4, 1]) should return 10');", - "assert.deepEqual(sumAll([5, 10]), 45, 'message: sumAll([5, 10]) should return 45');", - "assert.deepEqual(sumAll([10, 5]), 45, 'message: sumAll([10, 5]) should return 45');" + "assert(typeof(sumAll([1, 4])) === \"number\", 'message: sumAll() should return a number.');", + "assert.deepEqual(sumAll([1, 4]), 10, 'message: sumAll([1, 4]) should return 10.');", + "assert.deepEqual(sumAll([4, 1]), 10, 'message: sumAll([4, 1]) should return 10.');", + "assert.deepEqual(sumAll([5, 10]), 45, 'message: sumAll([5, 10]) should return 45.');", + "assert.deepEqual(sumAll([10, 5]), 45, 'message: sumAll([10, 5]) should return 45.');" ], "MDNlinks": [ "Math.max()", @@ -62,12 +62,12 @@ ], "tests": [ "assert(typeof(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])) === \"object\", 'message: diff() should return an array.');", - "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'message: ['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub'] should return ['pink wool'].');", - "assert.includeMembers(diff(['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['diorite', 'pink wool'], 'message: ['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub'] should return ['diorite', 'pink wool'].');", - "assert.deepEqual(diff(['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub']), [], 'message: ['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub'] should return [].');", + "assert.deepEqual(diff([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"pink wool\"], 'message: [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return [\"pink wool\"].');", + "assert.includeMembers(diff([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"diorite\", \"pink wool\"], 'message: [\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return [\"diorite\", \"pink wool\"].');", + "assert.deepEqual(diff([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [], 'message: [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return [].');", "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\"], [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\"].');" ], "MDNlinks": [ "Comparison Operators", @@ -93,11 +93,11 @@ "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(29), \"XXIX\", 'message: convert(29) should return \"XXIX\"');", - "assert.deepEqual(convert(16), \"XVI\", 'message: convert(16) should return \"XVI\"');" + "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(29), \"XXIX\", 'message: convert(29) should return \"XXIX\".');", + "assert.deepEqual(convert(16), \"XVI\", 'message: convert(16) should return \"XVI\".');" ], "difficulty": "2.02", "description": [ @@ -137,7 +137,7 @@ "difficulty": "2.03", "description": [ "Make a function that looks through an array of objects (first argument) and returns an array of all objects that have matching property and value pairs (second argument). Each property and value pair of the source object has to be present in the object from the collection if it is to be included in the returned array.", - "For example, if the first argument is [{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], and the second argument is { last: 'Capulet' }, then you must return the third object from the array (the first argument), because it contains the property and it's value, that was passed on as the second argument.", + "For example, if the first argument is [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], and the second argument is { last: \"Capulet\" }, then you must return the third object from the array (the first argument), because it contains the property and it's value, that was passed on as the second argument.", "Remember to use Read-Search-Ask if you get stuck. Write your own code." ], "challengeSeed": [ @@ -147,13 +147,13 @@ " return arr;", "}", "", - "where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });" + "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([{ '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 }].');", - "assert.deepEqual(where([{ 'a': 5 }, { 'b': 10 }, { 'a': 5, 'b': 10 }], { 'a': 5, 'b': 10 }), [{ 'a': 5, 'b': 10 }], 'message: where([{ 'a': 5 }, { 'b': 10 }, { 'a': 5, 'b': 10 }], { 'a': 5, 'b': 10 }) should return [{ 'a': 5, 'b': 10 }].');" + "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([{ '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 }].');", + "assert.deepEqual(where([{ \"a\": 5 }, { \"b\": 10 }, { \"a\": 5, \"b\": 10 }], { \"a\": 5, \"b\": 10 }), [{ \"a\": 5, \"b\": 10 }], 'message: where([{ \"a\": 5 }, { \"b\": 10 }, { \"a\": 5, \"b\": 10 }], { \"a\": 5, \"b\": 10 }) should return [{ \"a\": 5, \"b\": 10 }].');" ], "MDNlinks": [ "Global Object", @@ -177,11 +177,11 @@ "id": "a0b5010f579e69b815e7c5d6", "title": "Search and Replace", "tests": [ - "assert.deepEqual(replace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'message: replace(\"Let us go to the store\", \"store\", \"mall\") should return \"Let us go to the mall\"');", - "assert.deepEqual(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'message: replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\") should return \"He is Sitting on the couch\"');", - "assert.deepEqual(replace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'message: replace(\"This has a spellngi error\", \"spellingi\", \"spelling\") should return \"This has a spelling error\"');", - "assert.deepEqual(replace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'message: replace(\"His name is Tom\", \"Tom\", \"john\") should return \"His name is John\"');", - "assert.deepEqual(replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\"), \"Let us get back to more Bonfires\", 'message: replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\") should return \"Let us get back to more Bonfires\"');" + "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(\"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\".');" ], "difficulty": "2.035", "description": [ @@ -189,7 +189,7 @@ "First argument is the sentence to perform the search and replace on.", "Second argument is the word that you will be replacing (before).", "Third argument is what you will be replacing the second argument with (after).", - "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word 'Book' with the word 'dog', it should be replaced as 'Dog'", + "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word \"Book\" with the word \"dog\", it should be replaced as \"Dog\"", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ @@ -221,11 +221,11 @@ "id": "aa7697ea2477d1316795783b", "title": "Pig Latin", "tests": [ - "assert.deepEqual(translate(\"california\"), \"aliforniacay\", 'message: translate(\"california\") should return \"aliforniacay\"');", - "assert.deepEqual(translate(\"paragraphs\"), \"aragraphspay\", 'message: translate(\"paragraphs\") should return \"aragraphspay\"');", - "assert.deepEqual(translate(\"glove\"), \"oveglay\", 'message: translate(\"glove\") should return \"oveglay\"');", - "assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'message: translate(\"algorithm\") should return \"algorithmway\"');", - "assert.deepEqual(translate(\"eight\"), \"eightway\", 'message: translate(\"eight\") should return \"eightway\"');" + "assert.deepEqual(translate(\"california\"), \"aliforniacay\", 'message: translate(\"california\") should return \"aliforniacay\".');", + "assert.deepEqual(translate(\"paragraphs\"), \"aragraphspay\", 'message: translate(\"paragraphs\") should return \"aragraphspay\".');", + "assert.deepEqual(translate(\"glove\"), \"oveglay\", 'message: translate(\"glove\") should return \"oveglay\".');", + "assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'message: translate(\"algorithm\") should return \"algorithmway\".');", + "assert.deepEqual(translate(\"eight\"), \"eightway\", 'message: translate(\"eight\") should return \"eightway\".');" ], "difficulty": "2.04", "description": [ @@ -265,16 +265,16 @@ "id": "afd15382cdfb22c9efe8b7de", "title": "DNA Pairing", "tests": [ - "assert.deepEqual(pair(\"ATCGA\"),[['A','T'],['T','A'],['C','G'],['G','C'],['A','T']], 'message: pair(\"ATCGA\") should return [['A','T'],['T','A'],['C','G'],['G','C'],['A','T']].');", - "assert.deepEqual(pair(\"TTGAG\"),[['T','A'],['T','A'],['G','C'],['A','T'],['G','C']], 'message: pair(\"TTGAG\") should return [['T','A'],['T','A'],['G','C'],['A','T'],['G','C']].');", - "assert.deepEqual(pair(\"CTCTA\"),[['C','G'],['T','A'],['C','G'],['T','A'],['A','T']], 'message: pair(\"CTCTA\") should return [['C','G'],['T','A'],['C','G'],['T','A'],['A','T']].');" + "assert.deepEqual(pair(\"ATCGA\"),[[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]], 'message: pair(\"ATCGA\") should return [[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]].');", + "assert.deepEqual(pair(\"TTGAG\"),[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]], 'message: pair(\"TTGAG\") should return [[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]].');", + "assert.deepEqual(pair(\"CTCTA\"),[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]], 'message: pair(\"CTCTA\") should return [[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]].');" ], "difficulty": "2.05", "description": [ "The DNA strand is missing the pairing element. Take each character, get its pair, and return the results as a 2d array.", "Base pairs are a pair of AT and CG. Match the missing element to the provided character.", "Return the provided character as the first element in each array.", - "For example, for the input GCG, return [['G', 'C'], ['C','G'],['G', 'C']]", + "For example, for the input GCG, return [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]", "The character and its pair are paired up in an array, and all the arrays are grouped into one encapsulating array.", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." ], @@ -316,7 +316,7 @@ " return str;", "}", "", - "fearNotLetter('abce');" + "fearNotLetter(\"abce\");" ], "tests": [ "assert.deepEqual(fearNotLetter(\"abce\"), \"d\", 'message: fearNotLetter(\"abce\") should return \"d\".');", @@ -363,10 +363,10 @@ "assert.strictEqual(boo(false), true, 'message: boo(false) should return true.');", "assert.strictEqual(boo([1, 2, 3]), false, 'message: boo([1, 2, 3]) should return false.');", "assert.strictEqual(boo([].slice), false, 'message: boo([].slice) should return false.');", - "assert.strictEqual(boo({ 'a': 1 }), false, 'message: boo({ 'a': 1 }) should return false.');", + "assert.strictEqual(boo({ \"a\": 1 }), false, 'message: boo({ \"a\": 1 }) should return false.');", "assert.strictEqual(boo(1), false, 'message: boo(1) should return false.');", "assert.strictEqual(boo(NaN), false, 'message: boo(NaN) should return true.');", - "assert.strictEqual(boo('a'), false, 'message: boo('a') should return false.');" + "assert.strictEqual(boo(\"a\"), false, 'message: boo(\"a\") should return false.');" ], "MDNlinks": [ "Boolean Objects" @@ -403,10 +403,10 @@ "unite([1, 3, 2], [5, 2, 1, 4], [2, 1]);" ], "tests": [ - "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'message: should return .');", - "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'message: should return .');", - "assert.deepEqual(unite([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'message: should return .');", - "assert.deepEqual(unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [ 1, 2, 3, 5, 4, 6, 7, 8 ], 'message: should return .');" + "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'message: unite([1, 3, 2], [5, 2, 1, 4], [2, 1]) should return [1, 3, 2, 5, 4].');", + "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'message: unite([1, 3, 2], [1, [5]], [2, [4]]) should return [1, 3, 2, [5], [4]].');", + "assert.deepEqual(unite([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'message: unite([1, 2, 3], [5, 2, 1]) should return [1, 2, 3, 5].');", + "assert.deepEqual(unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [1, 2, 3, 5, 4, 6, 7, 8], 'message: unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]) should return [1, 2, 3, 5, 4, 6, 7, 8].');" ], "MDNlinks": [ "Arguments object", @@ -439,15 +439,15 @@ " return str;", "}", "", - "convert('Dolce & Gabbana');" + "convert(\"Dolce & Gabbana\");" ], "tests": [ - "assert.match(convert('Dolce & Gabbana'), /Dolce &(amp|AMP|#x00026|#38); Gabbana/, 'message: convert('Dolce & Gabbana') should return /Dolce &(amp|AMP|#x00026|#38); Gabbana/.');", - "assert.match(convert('Hamburgers < Pizza < Tacos'), /Hamburgers &(lt|LT|#x0003C|#60); Pizza &(lt|LT|#x0003C|#60); Tacos/, 'message: convert('Hamburgers < Pizza < Tacos') should return /Hamburgers &(lt|LT|#x0003C|#60); Pizza &(lt|LT|#x0003C|#60); Tacos/.');", - "assert.match(convert('Sixty > twelve'), /Sixty &(gt|GT|#x0003E|#62); twelve/, 'message: convert('Sixty > twelve') should return /Sixty &(gt|GT|#x0003E|#62); twelve/.');", - "assert.match(convert('Stuff in \"quotation marks\"'), /Stuff in &(quot|QUOT|#x00022|#34);quotation marks&(quot|QUOT|#x00022|#34);/, 'message: convert('Stuff in \"quotation marks\"') should return /Stuff in &(quot|QUOT|#x00022|#34);quotation marks&(quot|QUOT|#x00022|#34);/.');", - "assert.match(convert(\"Shindler's List\"), /Shindler&(apos|#x00027|#39);s List/, 'message: convert(\"Shindler's List\") should return /Shindler&(apos|#x00027|#39);s List/.');", - "assert.match(convert('<>'), /&(lt|LT|#x0003C|#60);&(gt|GT|#x0003E|#62);/, 'message: convert('<>') should return /&(lt|LT|#x0003C|#60);&(gt|GT|#x0003E|#62);/.');", + "assert.match(convert(\"Dolce & Gabbana\"), /Dolce & Gabbana/, 'message: convert(\"Dolce & Gabbana\") should return Dolce & Gabbana.');", + "assert.match(convert(\"Hamburgers < Pizza < Tacos\"), /Hamburgers < Pizza < Tacos/, 'message: convert(\"Hamburgers < Pizza < Tacos\") should return Hamburgers < Pizza < Tacos.');", + "assert.match(convert(\"Sixty > twelve\"), /Sixty > twelve/, 'message: convert(\"Sixty > twelve\") should return Sixty > twelve.');", + "assert.match(convert('Stuff in \"quotation marks\"'), /Stuff in "quotation marks"/, 'message: convert('Stuff in \"quotation marks\"') should return Stuff in "quotation marks".');", + "assert.match(convert(\"Shindler's List\"), /Shindler's List/, 'message: convert(\"Shindler's List\") should return Shindler's List.');", + "assert.match(convert('<>'), /<>/, 'message: convert('<>') should return <>.');", "assert.strictEqual(convert('abc'), 'abc', 'message: convert(\"abc\") should return \"abc\".');" ], "MDNlinks": [ @@ -485,10 +485,10 @@ "spinalCase('This Is Spinal Tap');" ], "tests": [ - "assert.strictEqual(spinalCase('This Is Spinal Tap'), 'this-is-spinal-tap', 'message: spinalCase('This Is Spinal Tap') should return 'this-is-spinal-tap'.');", - "assert.strictEqual(spinalCase('thisIsSpinalTap'), 'this-is-spinal-tap', 'message: spinalCase('thisIsSpinalTap') should return 'this-is-spinal-tap'.');", - "assert.strictEqual(spinalCase('The_Andy_Griffith_Show'), 'the-andy-griffith-show', 'message: spinalCase('The_Andy_Griffith_Show') should return 'the-andy-griffith-show'.');", - "assert.strictEqual(spinalCase('Teletubbies say Eh-oh'), 'teletubbies-say-eh-oh', 'message: spinalCase('Teletubbies say Eh-oh') should return 'teletubbies-say-eh-oh'.');" + "assert.deepEqual(spinalCase(\"This Is Spinal Tap\"), \"this-is-spinal-tap\", 'message: spinalCase(\"This Is Spinal Tap\") should return \"this-is-spinal-tap\".');", + "assert.strictEqual(spinalCase('thisIsSpinalTap'), \"this-is-spinal-tap\", 'message: spinalCase(\"thisIsSpinalTap\") should return \"this-is-spinal-tap\".');", + "assert.strictEqual(spinalCase(\"The_Andy_Griffith_Show\"), \"the-andy-griffith-show\", 'message: spinalCase(\"The_Andy_Griffith_Show\") should return \"the-andy-griffith-show\".');", + "assert.strictEqual(spinalCase(\"Teletubbies say Eh-oh\"), \"teletubbies-say-eh-oh\", 'message: spinalCase(\"Teletubbies say Eh-oh\") should return \"teletubbies-say-eh-oh\".');" ], "MDNlinks": [ "RegExp", @@ -525,12 +525,12 @@ "sumFibs(4);" ], "tests": [ - "assert.deepEqual(typeof(sumFibs(1)), \"number\", message: sumFibs() should return a number.);", - "assert.deepEqual(sumFibs(1000), 1785, 'message: sumFibs(1000) should return 1785');", - "assert.deepEqual(sumFibs(4000000), 4613732, 'message: sumFibs(4000000) should return 4613732');", - "assert.deepEqual(sumFibs(4), 5, 'message: sumFibs(4) should return 5');", - "assert.deepEqual(sumFibs(75024), 60696, 'message: sumFibs(75024) should return 60696');", - "assert.deepEqual(sumFibs(75025), 135721, 'message: sumFibs(75025) should return 135721');" + "assert(typeof(sumFibs(1)) === \"number\", 'message: sumFibs() should return a number.');", + "assert.deepEqual(sumFibs(1000), 1785, 'message: sumFibs(1000) should return 1785.');", + "assert.deepEqual(sumFibs(4000000), 4613732, 'message: sumFibs(4000000) should return 4613732.');", + "assert.deepEqual(sumFibs(4), 5, 'message: sumFibs(4) should return 5.');", + "assert.deepEqual(sumFibs(75024), 60696, 'message: sumFibs(75024) should return 60696.');", + "assert.deepEqual(sumFibs(75025), 135721, 'message: sumFibs(75025) should return 135721.');" ], "MDNlinks": [ "Remainder" @@ -607,9 +607,9 @@ ], "tests": [ "assert.deepEqual(typeof(smallestCommons([1, 5])), \"number\", 'message: smallestCommons() should return a number.');", - "assert.deepEqual(smallestCommons([1, 5]), 60, 'message: smallestCommons([1, 5]) should return 60');", - "assert.deepEqual(smallestCommons([5, 1]), 60, 'message: smallestCommons([5, 1]) should return 60');", - "assert.deepEqual(smallestCommons([1, 13]), 360360, 'message: smallestCommons([1, 13]) should return 360360');" + "assert.deepEqual(smallestCommons([1, 5]), 60, 'message: smallestCommons([1, 5]) should return 60.');", + "assert.deepEqual(smallestCommons([5, 1]), 60, 'message: smallestCommons([5, 1]) should return 60.');", + "assert.deepEqual(smallestCommons([1, 13]), 360360, 'message: smallestCommons([1, 13]) should return 360360.');" ], "MDNlinks": [ "Smallest Common Multiple" @@ -719,7 +719,7 @@ "steamroller([1, [2], [3, [[4]]]]);" ], "tests": [ - "assert.deepEqual(steamroller([[['a']], [['b']]]), ['a', 'b'], 'message: steamroller([[['a']], [['b']]]) should return ['a', 'b'].');", + "assert.deepEqual(steamroller([[[\"a\"]], [[\"b\"]]]), [\"a\", \"b\"], 'message: steamroller([[[\"a\"]], [[\"b\"]]]) should return [\"a\", \"b\"].');", "assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'message: steamroller([1, [2], [3, [[4]]]]) should return [1, 2, 3, 4].');", "assert.deepEqual(steamroller([1, [], [3, [[4]]]]), [1, 3, 4], 'message: steamroller([1, [], [3, [[4]]]]) should return [1, 3, 4].');", "assert.deepEqual(steamroller([1, {}, [3, [[4]]]]), [1, {}, 3, 4], 'message: steamroller([1, {}, [3, [[4]]]]) should return [1, {}, 3, 4].');" @@ -754,11 +754,11 @@ " return str;", "}", "", - "binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');" + "binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\");" ], "tests": [ - "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", 'binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\") should return \"Aren't bonfires fun!?\"');", - "assert.deepEqual(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001'), \"I love FreeCodeCamp!\", 'message: binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\" should return \"I love FreeCodeCamp!\"');" + "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", 'message: binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\") should return \"Aren't bonfires fun!?\"');", + "assert.deepEqual(binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\"), \"I love FreeCodeCamp!\", 'message: binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\" should return \"I love FreeCodeCamp!\"');" ], "MDNlinks": [ "String.charCodeAt()", @@ -793,12 +793,12 @@ " return pre;", "}", "", - "every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');" + "every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\");" ], "tests": [ - "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex'), true, '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\", \"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.');" ], "MDNlinks": [ "Object.hasOwnProperty()", diff --git a/server/views/coursewares/showBonfire.jade b/server/views/coursewares/showBonfire.jade index 52ec4a097b..084fd03d4b 100644 --- a/server/views/coursewares/showBonfire.jade +++ b/server/views/coursewares/showBonfire.jade @@ -21,44 +21,6 @@ block content .innerMarginFix(style=' width: 99%') #testCreatePanel.well h3.text-center.negative-10= name - .positive-15.positive-15-bottom - h4.text-center.bonfire-flames Difficulty:  - if (difficulty == "0") - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - if (difficulty == "1") - i.ion-ios-flame - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - if (difficulty == "2") - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame-outline - i.ion-ios-flame-outline - i.ion-ios-flame-outline - if (difficulty == "3") - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame-outline - i.ion-ios-flame-outline - if (difficulty == "4") - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame-outline - if (difficulty == "5") - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame - i.ion-ios-flame .row .col-xs-12 .bonfire-instructions From 416a866ec005ebf20cc03abb008b1b92e4702265 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 27 Sep 2015 15:58:59 -0700 Subject: [PATCH 47/63] add step based challenge to framework --- client/commonFramework.js | 429 ++++++++++++++------ seed/challenges/basejumps.json | 2 +- seed/challenges/getting-started.json | 321 +++++++++++++++ server/boot/challenge.js | 4 +- server/boot/home.js | 2 +- server/views/coursewares/getstuff.jade | 9 - server/views/coursewares/showStep.jade | 39 ++ server/views/partials/challenge-modals.jade | 2 +- server/views/resources/get-started.jade | 173 -------- server/views/resources/jobs-form.jade | 3 - 10 files changed, 668 insertions(+), 316 deletions(-) create mode 100644 seed/challenges/getting-started.json delete mode 100644 server/views/coursewares/getstuff.jade create mode 100644 server/views/coursewares/showStep.jade delete mode 100644 server/views/resources/get-started.jade delete mode 100644 server/views/resources/jobs-form.jade diff --git a/client/commonFramework.js b/client/commonFramework.js index 6e5bb4f2cf..3a8a0c808a 100644 --- a/client/commonFramework.js +++ b/client/commonFramework.js @@ -1,6 +1,23 @@ -/* globals jailed, CodeMirror, challenge_Id, challenge_Name, challengeType */ +// common namespace +// all classes should be stored here +var common = common || { + // init is an array of functions that are + // called at the beginning of dom ready + init: [] +}; + +common.challengeName = common.challengeName || window.challenge_Name ? + window.challenge_Name : + ''; + +common.challengeType = common.challengeType || window.challengeType ? + window.challengeType : + 0; + +common.challengeId = common.challengeId || window.challenge_Id; + // codeStorage -var codeStorageFactory = (function($, localStorage) { +common.codeStorageFactory = (function($, localStorage) { var CodeStorageProps = { version: 0.01, @@ -68,8 +85,45 @@ var codeStorageFactory = (function($, localStorage) { return codeStorageFactory; }($, localStorage)); -var sandBox = (function() { +common.codeOutput = (function(CodeMirror, document, challengeType) { + if (!CodeMirror) { + return {}; + } + if ( + challengeType === '0' || + challengeType === '7' + ) { + return {}; + } + var codeOutput = CodeMirror.fromTextArea( + document.getElementById('codeOutput'), + { + lineNumbers: false, + mode: 'text', + theme: 'monokai', + readOnly: 'nocursor', + lineWrapping: true + } + ); + codeOutput.setValue( + '/**\n' + + ' * Your output will go here.\n' + + ' * Console.log() -type statements\n' + + ' * will appear in your browser\'s\n' + + ' * DevTools JavaScript console.\n' + + ' */' + ); + + codeOutput.setSize('100%', '100%'); + + return codeOutput; +}(window.CodeMirror, window.document, common.challengeType || 0)); + +var sandBox = (function(jailed, codeOutput) { + if (!jailed) { + return {}; + } var plugin = null; var sandBox = { @@ -150,7 +204,7 @@ var sandBox = (function() { endLoading(); console.log('resetting on fatal plugin error'); - if (challengeType === 0) { + if (common.challengeType === 0) { codeOutput.setValue( 'Sorry, your code is either too slow, has a fatal error, ' + 'or contains an infinite loop.' @@ -163,7 +217,7 @@ var sandBox = (function() { reset(); sandBox.submit = submit; return sandBox; -}()); +}(window.jailed, common.codeOutput)); function replaceSafeTags(value) { return value @@ -180,33 +234,105 @@ var BDDregex = new RegExp( var isInitRun = false; var initPreview = true; -var editor; -editor = CodeMirror.fromTextArea(document.getElementById('codeEditor'), { - lineNumbers: true, - mode: 'text', - theme: 'monokai', - runnable: true, - matchBrackets: true, - autoCloseBrackets: true, - scrollbarStyle: 'null', - lineWrapping: true, - gutters: ['CodeMirror-lint-markers'] -}); +var editor = (function(CodeMirror, emmetCodeMirror, common) { + var codeStorageFactory = common.codeStorageFactory; + if (!CodeMirror) { + return {}; + } -var codeStorage = codeStorageFactory(editor, challenge_Name); -var myCodeMirror = editor; + var editor = CodeMirror.fromTextArea(document.getElementById('codeEditor'), { + lineNumbers: true, + mode: 'text', + theme: 'monokai', + runnable: true, + matchBrackets: true, + autoCloseBrackets: true, + scrollbarStyle: 'null', + lineWrapping: true, + gutters: ['CodeMirror-lint-markers'] + }); + + editor.setSize('100%', 'auto'); + + var codeStorage = common.codeStorage = + codeStorageFactory(editor, common.challengeName); + + editor.on('keyup', function() { + clearTimeout(codeStorage.updateTimeoutId); + codeStorage.updateTimeoutId = setTimeout( + codeStorage.updateStorage.bind(codeStorage), + codeStorage.updateWait + ); + }); + + // Initialize CodeMirror editor with a nice html5 canvas demo. + editor.on('keyup', function() { + clearTimeout(delay); + delay = setTimeout(updatePreview, 300); + }); + + editor.setOption('extraKeys', { + Tab: function(cm) { + if (cm.somethingSelected()) { + cm.indentSelection('add'); + } else { + var spaces = Array(cm.getOption('indentUnit') + 1).join(' '); + cm.replaceSelection(spaces); + } + }, + 'Shift-Tab': function(cm) { + if (cm.somethingSelected()) { + cm.indentSelection('subtract'); + } else { + var spaces = Array(cm.getOption('indentUnit') + 1).join(' '); + cm.replaceSelection(spaces); + } + }, + 'Ctrl-Enter': function() { + isInitRun = false; + bonfireExecute(true); + return false; + } + }); + + + var info = editor.getScrollInfo(); + + var after = editor.charCoords({ + line: editor.getCursor().line + 1, + ch: 0 + }, 'local').top; + + if (info.top + info.clientHeight < after) { + editor.scrollTo(null, after - info.clientHeight + 3); + } + + if (emmetCodeMirror) { + emmetCodeMirror( + editor, + { + 'Cmd-E': 'emmet.expand_abbreviation', + Tab: 'emmet.expand_abbreviation_with_tab', + Enter: 'emmet.insert_formatted_line_break_only' + } + ); + } + common.init.push(function() { + editorValue = codeStorage.isAlive() ? + codeStorage.getStoredValue() : + allSeeds; + + editor.setValue(replaceSafeTags(editorValue)); + editor.refresh(); + }); + + return editor; +}(window.CodeMirror, window.emmetCodeMirror, common)); -editor.on('keyup', function() { - clearTimeout(codeStorage.updateTimeoutId); - codeStorage.updateTimeoutId = setTimeout( - codeStorage.updateStorage.bind(codeStorage), - codeStorage.updateWait - ); -}); var editorValue; -var challengeSeed = challengeSeed || null; +var challengeSeed = challengeSeed || []; var tests = tests || []; var allSeeds = ''; @@ -216,42 +342,6 @@ var allSeeds = ''; }); })(); -if (typeof emmetCodeMirror !== 'undefined') { - var defaultKeymap = { - 'Cmd-E': 'emmet.expand_abbreviation', - 'Tab': 'emmet.expand_abbreviation_with_tab', - 'Enter': 'emmet.insert_formatted_line_break_only' - }; - - emmetCodeMirror(editor, defaultKeymap); -} - -editor.setOption('extraKeys', { - Tab: function(cm) { - if (cm.somethingSelected()) { - cm.indentSelection('add'); - } else { - var spaces = Array(cm.getOption('indentUnit') + 1).join(' '); - cm.replaceSelection(spaces); - } - }, - 'Shift-Tab': function(cm) { - if (cm.somethingSelected()) { - cm.indentSelection('subtract'); - } else { - var spaces = Array(cm.getOption('indentUnit') + 1).join(' '); - cm.replaceSelection(spaces); - } - }, - 'Ctrl-Enter': function() { - isInitRun = false; - bonfireExecute(true); - return false; - } -}); - -editor.setSize('100%', 'auto'); - var libraryIncludes = "" + "" + "" + @@ -294,7 +384,8 @@ function scopejQuery(str) { } function safeHTMLRun(test) { - if (challengeType === '0') { + var codeStorage = common.codeStorage; + if (common.challengeType === '0') { var previewFrame = document.getElementById('preview'); var preview = previewFrame.contentDocument || previewFrame.contentWindow.document; if (editor.getValue().match(/\/gi) !== null) { @@ -304,7 +395,7 @@ function safeHTMLRun(test) { .split(/\<\s?\/\s?script\s?\>/gi)[0]; // 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; + 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; sandBox.submit(scopejQuery(s), function(cls, message) { if (cls) { @@ -369,17 +460,11 @@ if (typeof prodOrDev !== 'undefined') { 'http://www.freecodecamp.com' : 'http://localhost:3001'; - if (challengeType === '0') { + if (common.challengeType === '0') { setTimeout(updatePreview, 300); } } -// Initialize CodeMirror editor with a nice html5 canvas demo. -editor.on('keyup', function() { - clearTimeout(delay); - delay = setTimeout(updatePreview, 300); -}); - /** * "post" methods */ @@ -437,9 +522,9 @@ function showCompletion() { 'event', 'Challenge', 'solved', - challenge_Name + ', Time: ' + time + ', Attempts: ' + attempts + common.challengeName + ', Time: ' + time + ', Attempts: ' + attempts ); - var bonfireSolution = myCodeMirror.getValue(); + var bonfireSolution = editor.getValue(); var didCompleteWith = $('#completed-with').val() || null; $('#complete-courseware-dialog').modal('show'); @@ -470,16 +555,17 @@ function showCompletion() { $.post( '/completed-bonfire/', { challengeInfo: { - challengeId: challenge_Id, - challengeName: challenge_Name, + challengeId: common.challengeId, + challengeName: common.challengeName, completedWith: didCompleteWith, - challengeType: challengeType, + challengeType: common.challengeType, solution: bonfireSolution } }, function(res) { if (res) { - window.location = '/challenges/next-challenge?id=' + challenge_Id; + window.location = + '/challenges/next-challenge?id=' + common.challengeId; } } ); @@ -490,7 +576,7 @@ var resetEditor = function resetEditor() { editor.setValue(replaceSafeTags(allSeeds)); $('#testSuite').empty(); bonfireExecute(true); - codeStorage.updateStorage(); + common.codeStorage.updateStorage(); }; var attempts = 0; @@ -498,35 +584,6 @@ if (attempts) { attempts = 0; } -if (challengeType !== '0') { - var codeOutput = CodeMirror.fromTextArea( - document.getElementById('codeOutput'), - { - lineNumbers: false, - mode: 'text', - theme: 'monokai', - readOnly: 'nocursor', - lineWrapping: true - } - ); - - codeOutput.setValue('/**\n' + - ' * Your output will go here.\n' + ' * Console.log() -type statements\n' + - ' * will appear in your browser\'s\n' + ' * DevTools JavaScript console.\n' + - ' */'); - codeOutput.setSize('100%', '100%'); -} - -var info = editor.getScrollInfo(); - -var after = editor.charCoords({ - line: editor.getCursor().line + 1, - ch: 0 -}, 'local').top; - -if (info.top + info.clientHeight < after) { - editor.scrollTo(null, after - info.clientHeight + 3); -} var userTests; var testSalt = Math.random(); @@ -605,9 +662,15 @@ var createTestDisplay = function() { } }; -var expect = chai.expect; -var assert = chai.assert; -var should = chai.should(); +(function(win, chai) { + if (!chai) { + return; + } + win.expect = chai.expect; + win.assert = chai.assert; + win.should = chai.should(); + +}(window, window.chai)); var reassembleTest = function(test, data) { @@ -646,9 +709,9 @@ var runTests = function(err, data) { ) { try { if (chaiTestFromJSON) { - /* eslint-disable no-eval */ + /* eslint-disable no-eval, no-unused-vars */ var output = eval(reassembleTest(chaiTestFromJSON, data)); - /* eslint-enable no-eval */ + /* eslint-enable no-eval, no-unused-vars */ } } catch (error) { allTestsPassed = false; @@ -669,19 +732,133 @@ var runTests = function(err, data) { } }; +// step challenge +common.init.push((function() { + var stepClass = '.challenge-step'; + var nextBtnClass = '.challenge-step-btn-next'; + var actionBtnClass = '.challenge-step-btn-action'; + var finishBtnClass = '.challenge-step-btn-finish'; + var submitBtnId = '#challenge-step-btn-submit'; + var submitModalId = '#challenge-step-modal'; + + function getNextStep($challengeSteps) { + var length = $challengeSteps.length; + var $nextStep = false; + var nextStepIndex = 0; + $challengeSteps.each(function(index) { + var $step = $(this); + if ( + !$step.hasClass('hidden') && + index + 1 !== length + ) { + nextStepIndex = index + 1; + } + }); + + $nextStep = $challengeSteps[nextStepIndex]; + + return $nextStep; + } + + function handleNextStepClick(e) { + e.preventDefault(); + var nextStep = getNextStep($(stepClass)); + $(this) + .parent() + .addClass('animated fadeOutLeft') + .delay(700) + .queue(function(next) { + $(this).addClass('hidden'); + if (nextStep) { + $(nextStep) + .removeClass('hidden') + .addClass('animated slideInRight') + .delay(1000) + .queue(function(next) { + $(this).removeClass('slideInRight'); + next(); + }); + } + next(); + }); + + } + + function handleActionClick() { + $(this) + .parent() + .find('.disabled') + .removeClass('disabled'); + } + + function handleFinishClick(e) { + e.preventDefault(); + $(submitModalId).modal('show'); + $(submitModalId + '.modal-header').click(); + $(submitBtnId).click(handleSubmitClick); + } + + function handleSubmitClick(e) { + e.preventDefault(); + + $('#submit-challenge') + .attr('disabled', 'true') + .removeClass('btn-primary') + .addClass('btn-warning disabled'); + + var $checkmarkContainer = $('#checkmark-container'); + $checkmarkContainer.css({ height: $checkmarkContainer.innerHeight() }); + + $('#challenge-checkmark') + .addClass('zoomOutUp') + .delay(1000) + .queue(function(next) { + $(this).replaceWith( + '
' + + 'submitting...
' + ); + next(); + }); + + $.post( + '/completed-bonfire/', { + challengeInfo: { + challengeId: common.challengeId, + challengeName: common.challengeName, + challengeType: common.challengeType + } + }, + function(res) { + if (res) { + window.location = + '/challenges/next-challenge?id=' + common.challengeId; + } + } + ); + } + + return function($) { + $(nextBtnClass).click(handleNextStepClick); + $(actionBtnClass).click(handleActionClick); + $(finishBtnClass).click(handleFinishClick); + }; +}(window.$))); + function bonfireExecute(shouldTest) { + var codeOutput = common.codeOutput; initPreview = false; goodTests = 0; attempts++; - ga('send', 'event', 'Challenge', 'ran-code', challenge_Name); + ga('send', 'event', 'Challenge', 'ran-code', common.challengeName); userTests = null; $('#testSuite').empty(); if ( - challengeType !== '0' && + common.challengeType !== '0' && !editor.getValue().match(/\$\s*?\(\s*?\$\s*?\)/gi) ) { - var userJavaScript = myCodeMirror.getValue(); + var userJavaScript = editor.getValue(); var failedCommentTest = false; // checks if the number of opening comments(/*) matches the number of @@ -701,7 +878,7 @@ function bonfireExecute(shouldTest) { if (userJavaScript.match(/function\s*?\(|function\s+\w+\s*?\(/gi)) { sandBox.submit(userJavaScript, function(cls, message) { if (failedCommentTest) { - myCodeMirror.setValue(myCodeMirror.getValue() + '*/'); + editor.setValue(editor.getValue() + '*/'); console.log('Caught Unfinished Comment'); codeOutput.setValue('Unfinished multi-line comment'); failedCommentTest = false; @@ -726,7 +903,7 @@ function bonfireExecute(shouldTest) { sandBox.submit(userJavaScript, function(cls, message) { if (failedCommentTest) { - myCodeMirror.setValue(myCodeMirror.getValue() + '*/'); + editor.setValue(editor.getValue() + '*/'); console.log('Caught Unfinished Comment'); codeOutput.setValue('Unfinished mulit-line comment'); failedCommentTest = false; @@ -756,7 +933,7 @@ function bonfireExecute(shouldTest) { } if ( !editor.getValue().match(/\$\s*?\(\s*?\$\s*?\)/gi) && - challengeType === '0' + common.challengeType === '0' ) { safeHTMLRun(shouldTest); } else { @@ -776,6 +953,10 @@ $('#submitButton').on('click', function() { $(document).ready(function() { + common.init.forEach(function(init) { + init($); + }); + // init modal keybindings on open $('#complete-courseware-dialog').on('shown.bs.modal', function() { $('#complete-courseware-dialog').keydown(ctrlEnterClickHandler); @@ -789,20 +970,14 @@ $(document).ready(function() { var $preview = $('#preview'); isInitRun = true; - editorValue = codeStorage.isAlive() ? - codeStorage.getStoredValue() : - allSeeds; - - myCodeMirror.setValue(replaceSafeTags(editorValue)); - myCodeMirror.refresh(); - if (typeof $preview.html() !== 'undefined') { $preview.load(function() { if (initPreview) { bonfireExecute(true); } }); - } else { + } else if (common.challengeType !== 7) { bonfireExecute(true); } + }); diff --git a/seed/challenges/basejumps.json b/seed/challenges/basejumps.json index 26f091cbcb..2235eefc58 100644 --- a/seed/challenges/basejumps.json +++ b/seed/challenges/basejumps.json @@ -86,7 +86,7 @@ "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project from fellow campers, click this button and paste in a link to your CodePen project.

Click here then add your link to your tweet's text" ], - "type": "basejumps", + "type": "basejump", "challengeType": 4, "tests": [], "nameCn": "", diff --git a/seed/challenges/getting-started.json b/seed/challenges/getting-started.json new file mode 100644 index 0000000000..5ac330c4e3 --- /dev/null +++ b/seed/challenges/getting-started.json @@ -0,0 +1,321 @@ +{ + "name": "Get Started with Free Code Camp", + "order": 0.000, + "challenges": [ + { + "id": "560add10cb82ac38a17513be", + "title": "Learn how Free Code Camp Works", + "difficulty": 0.00, + "challengeSeed": [], + "description": [ + [ + "http://i.imgur.com/RlEk2IF.jpg", + "a picture of Free Code Camp's 4 benefits: Get connected, Learn JavaScript, Build your Portfolio, Help nonprofits", + "Welcome to Free Code Camp. We're an open source community of busy people who learn to code and help nonprofits.", + "" + ], + [ + "http://i.imgur.com/pYsTbjI.jpg", + "a screenshot of our curriculum alongside a screenshot of our chat room.", + "Learning to code is hard. To succeed, you'll need lots of practice and support. That's why we've created a rigorous curriculum and supportive community.", + "" + ], + [ + "http://i.imgur.com/D7Y5luw.jpg", + "A graph of the rate of job growth against growth in computer science degree graduates. There are 1.4 million jobs and only 400 million people to fill them.", + "There are thousands of coding jobs currently going unfilled, and the demand for coders grows every year. If you want a coding job, we can help prepare you to get one.", + "" + ], + [ + "http://i.imgur.com/dLx8nrg.jpg", + "An illustration showing that you will learn HTML5, CSS3, JavaScript, Databases, Git, Node.js, Angular.js and Agile.", + "First you'll work through our rigorous 800-hour curriculum learn technologies like HTML5, Node.js and databases. It's self-paced and 100% free.", + "" + ], + [ + "http://i.imgur.com/q4IjuCL.jpg", + "a screenshot of our Front End Development Certificate", + "About half way through our curriculum, you'll earn a verified Front End Development Certificate. If you can finish our entire curriculum, you'll earn a verified Full Stack Development Certificate.", + "" + ], + [ + "http://i.imgur.com/yXyxbDd.jpg", + "a screen shot of our nonprofit project directory.", + "Then you'll build several real-life projects for nonprofits. By the time you finish, you'll have a portfolio of real apps that people use every day.", + "" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "id": "560add37cb82ac38a17513bf", + "title": "Create a GitHub Account and Join our Chat Rooms", + "difficulty": 0.01, + "challengeSeed": [], + "description": [ + [ + "http://i.imgur.com/EAR7Lvh.jpg", + "a screenshot of our one of our Gitter chat rooms.", + "Now let's join Free Code Camp's chat rooms. You can come here any time of day to hang out, ask questions, or find another camper to pair program with. First you'll need a GitHub account.", + "" + ], + [ + "http://i.imgur.com/FEImaEN.gif", + "A gif showing you to click the link below to go to GitHub. Fill in the necessary fields and click submit.", + "Create an account with GitHub. Be sure to use your real email address - GitHub will keep this private.", + "https://github.com/join" + ], + [ + "http://i.imgur.com/ALN6zPK.gif", + "A gif showing you how to click the profile image in the upper right hand corner of GitHub. Upload a photo of yourself or you will continue to use the automatically generated pixel art. Then fill in the remaining form fields and click submit.", + "Click the pixel art in the upper right hand corner of GitHub, then choose settings. Upload a picture of yourself. A picture of your face works best. This is how your fellow campers will see you in our chat rooms, so put your best foot forward. You can add your city and your name if you want.", + "https://github.com/settings/profile" + ], + [ + "http://i.imgur.com/OXL3G3n.gif", + "Click the link below to navigate to Free Code Camp's open-source repository. In the upper right hand corner, you can click the \"star\" button to star this repository.", + "Go to Free Code Camp's open-source repository and \"star\" it. \"Starring\" is the GitHub equivalent of \"liking\" something.", + "https://github.com/freecodecamp/freecodecamp" + ], + [ + "http://i.imgur.com/EZHzKCV.gif", + "A gif showing you how to click the link below to go to our chat room and click the \"sign in with GitHub\" button. Then you can click into the text input field and type a message to your fellow campers.", + " Now that you have a GitHub account, you can join our main chat room by logging in with GitHub. Introduce yourself by saying \"Hello world!\". Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code.", + "https://gitter.im/FreeCodeCamp/FreeCodeCamp" + ], + [ + "http://i.imgur.com/Ecs5XAd.gif", + "A gif showing you how you can click the settings button in the upper right hand corner and modify your notification settings.", + "Our chat rooms are extremely active. You should change your settings so you're only notified if someone mentions you.", + "" + ], + [ + "http://i.imgur.com/T0bGJPe.gif", + "A gif showing how you can click on a user profile image to initiate a private message with that user.", + "Please note that all of our chat rooms are visible to the public. If you need to share sensitive information, such as an email address or phone number, do it in a private message.", + "" + ], + [ + "http://i.imgur.com/vDTMJSh.gif", + "A gif showing that you can tab back and forth between challenges and our chat rooms.", + "Keep our chat room open while you work through our challenges. That way, you can ask for help if you get stuck. You can also socialize with other campers when you feel like taking a break.", + "" + ], + [ + "http://i.imgur.com/SLQ27Gr.gif", + "A gif showing how you can click the link below to download a native chat room app for your computer.", + "You can also download the chat room app to your computer or phone.", + "https://gitter.im/apps" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "id": "560add56cb82ac38a17513c0", + "title": "Configure your Public Profile", + "difficulty": 0.02, + "challengeSeed": [], + "description": [ + [ + "http://i.imgur.com/FkEzbto.gif", + "A gif showing how you can click your profile image in your upper right hand corner to access the account page and connect GitHub.", + "Check out your portfolio page. Click your picture your upper right hand corner. To activate your portfolio page, you'll need to link your GitHub account with Free Code Camp.", + "" + ], + [ + "http://i.imgur.com/WKzEr1q.gif", + "A gif showing how you can access your profile page and hover over different days to see how many brownie points you got on those days.", + "Your portfolio page shows your progress and how many Brownie Points you have. You can get Brownie Points by completing challenges and by helping other campers in our chat rooms. If you get Brownie Points on several days in a row, you'll get a streak.", + "" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "id": "560add65cb82ac38a17513c1", + "title": "Try our Wiki and Camper News", + "difficulty": 0.03, + "challengeSeed": [], + "description": [ + [ + "http://i.imgur.com/DoOqkNW.gif", + "A gif showing how you can click the \"Wiki\" button in your upper-right corner to access the wiki.", + "Try this: Click the \"Wiki\" button in your upper right hand corner. Our community has contributed lots of useful information to this searchable wiki.", + "" + ], + [ + "http://i.imgur.com/nmSiMy1.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.", + "" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "id": "560add71cb82ac38a17513c2", + "title": "Join a Campsite in Your City", + "difficulty": 0.04, + "challengeSeed": [], + "description": [ + [ + "http://i.imgur.com/Elb3dfj.jpg", + "A picture of some of our campers meeting in a local cafe. 3 men and 3 women are sitting around a table with laptops out, and are smiling and coding.", + "Our Campsites help you code with campers in your city. You can coordinate study groups or attend local coding events together.", + "" + ], + [ + "http://i.imgur.com/EZHzKCV.gif", + "A gif showing how you can click the link below, find your city on the list of Campsites, then click on the Facebook link for your city and join your city's Facebook group.", + "Find your city on this list, click the \"Facebook\" link, then click the \"Join group\" button to apply to join your city's Facebook group (someone from the campsite should approve you shortly). If your city isn't on this list, scroll to the bottom of the wiki article for instructions for how you can create your city's Campsite.", + "https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "id": "560add8ccb82ac38a17513c3", + "title": "Join our Alumni Network and Commit to Your Goal", + "difficulty": 0.05, + "challengeSeed": [], + "description": [ + [ + "http://i.imgur.com/P7qfJXt.gif", + "A gif showing how you can click the link below and fill in the necessary fields to add your Free Code Camp studies to your LinkedIn profile.", + "You can add Free Code Camp to your LinkedIn education background. Set your graduation date as next year. For \"Degree\", type \"Full Stack Web Development\". For \"Field of study\", type \"Computer Software Engineering\". Then click \"Save Changes\".", + "https://www.linkedin.com/profile/edit-education?school=Free+Code+Camp" + ], + [ + "", + "", + "Free Code Camp will always be free. If you want to feel more motivated to earn our certificates faster, we encourage you to instead donate each month to a nonprofit.", + "" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "id": "560add8ccb82ac38a17513c4", + "title": "Learn What to Do If You Get Stuck", + "difficulty": 0.06, + "challengeSeed": [], + "description": [ + [ + "http://i.imgur.com/EWWZBag.jpg", + "An image with the text \"1. Read the error 2. Search Google 3. Ask for help.", + "Let's cover one last thing before you start working through our challenges: how to get help. Any time you get stuck or don't know what to do next: Read-Search-Ask.", + "" + ], + [ + "http://i.imgur.com/99BfAcK.jpg", + "An image showing jQuery documentation", + "First, read the documentation or error message. A key skill that good coders have is the ability to interpret and then follow instructions.", + "" + ], + [ + "http://i.imgur.com/GxvrsFb.gif", + "A gif showing you how to do an advanced Google search. First, we enter the query \"jquery doesn't run when my page loads\". Then we click search tools button and change the \"Any time\" select box to \"within the last year\". Then we click on a result and read through the article and find our answer.", + "If that didn't help, search Google. Good Google queries take a lot of practice. When you search Google, you usually want to include the language or framework you're using. You also want to limit the results to a recent period.", + "" + ], + [ + "http://i.imgur.com/LZYU7p2.gif", + "A gif showing us following the link below to go to the help chat room and ask \"jquery doesn't run when my page loads\".", + "If that didn't help, ask your friends. If you have trouble, you can ask your fellow campers in our help chat room.", + "https://gitter.im/FreeCodeCamp/Help" + ], + [ + "http://i.imgur.com/WsfzvVo.gif", + "A gif showing us clicking the \"map\" button in our upper right hand corner and browsing our challenge map.", + "Now you're ready to start coding! The \"Map\" button in your upper right hand corner will show you our challenge map. This map shows all our coding challenges. We recommend that you complete these from top to bottom, at a sustainable pace. You can also return to your next challenge by clicking the \"Learn\" button.", + "" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + } + ] +} diff --git a/server/boot/challenge.js b/server/boot/challenge.js index 4ce4937e67..3846498915 100644 --- a/server/boot/challenge.js +++ b/server/boot/challenge.js @@ -26,7 +26,8 @@ const challengeView = { 2: 'coursewares/showVideo', 3: 'coursewares/showZiplineOrBasejump', 4: 'coursewares/showZiplineOrBasejump', - 5: 'coursewares/showBonfire' + 5: 'coursewares/showBonfire', + 7: 'coursewares/showStep' }; const dasherize = utils.dasherize; @@ -247,6 +248,7 @@ module.exports = function(app) { dashedName: origChallengeName, name: challenge.name, details: challenge.description, + description: challenge.description, tests: challenge.tests, challengeSeed: challenge.challengeSeed, verb: utils.randomVerb(), diff --git a/server/boot/home.js b/server/boot/home.js index d6855a9914..511c9aedf4 100644 --- a/server/boot/home.js +++ b/server/boot/home.js @@ -22,7 +22,7 @@ module.exports = function(app) { function index(req, res) { if (req.user) { - return res.render('resources/get-started', { title: message }); + return res.redirect('/map'); } res.render('home', { title: message }); } diff --git a/server/views/coursewares/getstuff.jade b/server/views/coursewares/getstuff.jade deleted file mode 100644 index 6645059ee2..0000000000 --- a/server/views/coursewares/getstuff.jade +++ /dev/null @@ -1,9 +0,0 @@ -// - Created by nathanleniz on 5/19/15. - -extends ../layout-wide -block content - script. - var stuff = !{JSON.stringify(stuff)}; - var challengeMapWithIds = !{JSON.stringify(stuffWithIds)}; - diff --git a/server/views/coursewares/showStep.jade b/server/views/coursewares/showStep.jade new file mode 100644 index 0000000000..f89d65eda2 --- /dev/null +++ b/server/views/coursewares/showStep.jade @@ -0,0 +1,39 @@ +extends ../layout-wide +block content + .row + .col-md-8.col-md-offset-2 + .jumbotron + for step, index in description + .thumbnail.challenge-step(class=index !== 0 ? 'hidden': '') + img.gif-block.img-center.img-responsive.thumbnail(src='#{step[0]}' alt='#{step[1]}') + .caption + p.large-p= step[2] + if step[3] + a.btn.btn-block.btn-primary.challenge-step-btn-action(href='#{step[3]}' target='_blank') Go To Link + if index + 1 === description.length + .btn.btn-block.btn-primary.challenge-step-btn-finish(id='last' class=step[3] ? 'disabled' : '') Finish challenge + else + .btn.btn-block.btn-primary.challenge-step-btn-next(id='#{index}' class=step[3] ? 'disabled' : '') Go to my next step + #challenge-step-modal.modal(tabindex='-1') + .modal-dialog.animated.fadeIn.fast-animation + .modal-content + .modal-header.challenge-list-header= compliment + a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × + .modal-body + .text-center + #checkmark-container.row + #challenge-checkmark.animated.zoomInDown.delay-half + span.completion-icon.ion-checkmark-circled.text-primary + .spacer + .row + if (user) + #challenge-step-btn-submit.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter) + else + a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge + script(src=rev('/js', 'commonFramework.js')) + script. + var common = common || { init: [] }; + common.challengeId = !{JSON.stringify(challengeId)}; + common.challengeName = !{JSON.stringify(name)}; + common.challengeType = 7; + common.dashedName = !{JSON.stringify(dashedName || '')}; diff --git a/server/views/partials/challenge-modals.jade b/server/views/partials/challenge-modals.jade index 746c1a6929..85165c357b 100644 --- a/server/views/partials/challenge-modals.jade +++ b/server/views/partials/challenge-modals.jade @@ -35,5 +35,5 @@ a.btn.btn-lg.btn-primary.btn-block(href='#', data-dismiss='modal', aria-hidden='true') Cancel script. if (typeof localStorage !== 'undefined') { - localStorage.setItem('currentDashedName', dashedName); + localStorage.setItem('currentDashedName', common.dashedName || dashedName || ''); } diff --git a/server/views/resources/get-started.jade b/server/views/resources/get-started.jade deleted file mode 100644 index 8767841a66..0000000000 --- a/server/views/resources/get-started.jade +++ /dev/null @@ -1,173 +0,0 @@ -extends ../layout -block content - .jumbotron - h2.text-center Scroll down and follow along with this 8-minute guide. - br - | It will help you get the most out of Free Code Camp. - - .thumbnail - img.gif-block.img-center.img-responsive.thumbnail(src='http://i.imgur.com/RlEk2IF.jpg' alt="a picture of Free Code Camp's 4 benefits: Get connected, Learn JavaScript, Build your Portfolio, Help nonprofits") - .caption - p.large-p Welcome to Free Code Camp. We're an open source community of busy people who learn to code and build projects for nonprofits. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/pYsTbjI.jpg' alt='a screenshot of our curriculum alongside a screenshot of our chat room.') - .caption - p.large-p Learning to code is hard. To succeed, you'll need lots of practice and support. That's why we've created a rigorous curriculum and supportive community. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/D7Y5luw.jpg' alt='A graph of the rate of job growth against growth in computer science degree graduates. There are 1.4 million jobs and only 400 million people to fill them.') - .caption - p.large-p There are thousands of coding jobs currently going unfilled, and the demand for coders grows every year. If you want a coding job, we can help prepare you to get one. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/dLx8nrg.jpg' alt='An illustration showing that you will learn HTML5, CSS3, JavaScript, Databases, Git, Node.js, Angular.js and Agile.') - .caption - p.large-p During the first 800 hours of Free Code Camp, you'll learn technologies like HTML5, Node.js and databases. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/yXyxbDd.jpg' alt='a screen shot of our nonprofit project directory.') - .caption - p.large-p During the last 800 hours, you'll build several real-life projects for nonprofits. By the time you finish, you'll have a portfolio of real apps that people use every day. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/EAR7Lvh.jpg' alt='a screenshot of our one of our Gitter chat rooms.') - .caption - p.large-p Now let's join Free Code Camp's chat rooms. You can come here any time of day to hang out, ask questions, or find another camper to pair program with. First you'll need a GitHub account. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/FEImaEN.gif' alt='A gif showing you to click the link below to go to GitHub. Fill in the necessary fields and click submit.') - .caption - p.large-p Try this:  - a(href='https://github.com/join' target='_blank') Create an account with GitHub - | . Be sure to use your real email address - GitHub will keep this private. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/ALN6zPK.gif' alt='A gif showing you how to click the profile image in the upper right hand corner of GitHub. Upload a photo of yourself or you will continue to use the automatically generated pixel art. Then fill in the remaining form fields and click submit.') - .caption - p.large-p Try this:  - | Click the pixel art in the upper right hand corner of GitHub, then choose settings. Upload a picture of yourself. A picture of your face works best. This is how your fellow campers will see you in our chat rooms, so put your best foot forward. You can add your city and your name if you want. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/OXL3G3n.gif' alt="Click the link below to navigate to Free Code Camp's open-source repository. In the upper right hand corner, you can click the \"star\" button to star this repository.") - .caption - p.large-p Try this:  - a(href='//github.com/freecodecamp/freecodecamp' target='_blank') Go to Free Code Camp's open-source repository - |  and "star" it. "Starring" is the GitHub equivalent of "liking" something. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/Uuc2Ked.gif' alt='A gif showing you how to click the link below to go to our chat room and click the \"sign in with GitHub\" button. Then you can click into the text input field and type a message to your fellow campers.') - .caption - p.large-p Try this:  - | Now that you have a GitHub account, you can  - a(href='https://gitter.im/FreeCodeCamp/FreeCodeCamp' target='_blank') join our main chat room by logging in with GitHub - | . Introduce yourself by saying "Hello world!". Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/Ecs5XAd.gif' alt='A gif showing you how you can click the settings button in the upper right hand corner and modify your notification settings.') - .caption - p.large-p Try this:  - | Our chat rooms are extremely active. You should change your settings so you're only notified if someone mentions you. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/T0bGJPe.gif' alt='A gif showing how you can click on a user profile image to initiate a private message with that user.') - .caption - p.large-p Please note that all of our chat rooms are visible to the public. If you need to share sensitive information, such as an email address or phone number, do it in a private message. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/vDTMJSh.gif' alt='A gif showing that you can tab back and forth between challenges and our chat rooms.') - .caption - p.large-p Keep our chat room open while you work through our challenges. That way, you can ask for help if you get stuck. You can also socialize with other campers when you feel like taking a break. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/SLQ27Gr.gif' alt='A gif showing how you can click the link below to download a native chat room app for your computer.') - .caption - p.large-p You can also  - a(href='https://gitter.im/apps' target='_blank') download the chat room app - |  to your computer or phone. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/FkEzbto.gif' alt='A gif showing how you can click your profile image in your upper right hand corner to access the account page and connect GitHub.') - .caption - p.large-p Try this: Check out your portfolio page. Click your picture your upper right hand corner. To activate your portfolio page, you'll need to link your GitHub account with Free Code Camp. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/WKzEr1q.gif' alt='A gif showing how you can access your profile page and hover over different days to see how many brownie points you got on those days.') - .caption - p.large-p Your portfolio page shows your progress and how many Brownie Points you have. You can get Brownie Points by completing challenges and by helping other campers in our chat rooms. If you get Brownie Points on several days in a row, you'll get a streak. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/nmSiMy1.gif' alt='A gif showing how you can access our Camper News page and click the "upvote" button to upvote a story.') - .caption - p.large-p Try this:  - | Click the "News" button in your upper right hand corner. You can browse links on Camper News and upvote ones that you enjoy. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/Elb3dfj.jpg' alt='A picture of some of our campers meeting in a local cafe. 3 men and 3 women are sitting around a table with laptops out, and are smiling and coding.') - .caption - p.large-p Our Campsites help you code with campers in your city. You can discuss coding and attend local Coffee-n-Code events. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/tYf8jrI.gif' alt="A gif showing how you can click the link below, find your city on the list of Campsites, then click on the Facebook link for your city and join your city's Facebook group.") - .caption - p.large-p Try this:  - a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites' target='_blank') Find your city on this list - | , then click it. Click the "Join group" button to join your city's Campsite. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/P7qfJXt.gif' alt='A gif showing how you can click the link below and fill in the necessary fields to add your Free Code Camp studies to your LinkedIn profile.') - .caption - p.large-p You can  - a(href='https://www.linkedin.com/profile/edit-education?school=Free+Code+Camp' target='_blank') add Free Code Camp to your LinkedIn education background - | . Set your graduation date as next year. For "Degree", type "Full Stack Web Development". For "Field of study", type "Computer Software Engineering". Then click "Save Changes". - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/EWWZBag.jpg' alt='An image with the text \"1. Read the error 2. Search Google 3. Ask for help.') - .caption - p.large-p Let's cover one last thing before you start working through our challenges: how to get help. Any time you get stuck or don't know what to do next: Read-Search-Ask. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/99BfAcK.jpg' alt='An image showing jQuery documentation') - .caption - p.large-p First, read the documentation or error message. A key skill that good coders have is the ability to interpret and then follow instructions. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/GxvrsFb.gif' alt="A gif showing you how to do an advanced Google search. First, we enter the query \"jquery doesn't run when my page loads\". Then we click search tools button and change the \"Any time\" select box to \"within the last year\". Then we click on a result and read through the article and find our answer.") - .caption - p.large-p If that didn't help, search Google. Good Google queries take a lot of practice. When you search Google, you usually want to include the language or framework you're using. You also want to limit the results to a recent period. - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/LZYU7p2.gif' alt="A gif showing us following the link below to go to the help chat room and ask \"jquery doesn't run when my page loads\".") - .caption - p.large-p If that didn't help, ask your friends. If you have trouble, you can ask your fellow campers in our  - a(href='https://gitter.im/FreeCodeCamp/Help' target='_blank') help chat room - | . - - .big-spacer - .thumbnail - img.gif-block.img-center.img-responsive(src='http://i.imgur.com/WsfzvVo.gif' alt='A gif showing us clicking the \"map\" button in our upper right hand corner and browsing our challenge map.') - .caption - p.large-p Now you're ready to start coding! Click the "Map" button in your upper right hand corner. Our map shows all our coding challenges. We recommend that you complete these from top to bottom, at a sustainable pace. diff --git a/server/views/resources/jobs-form.jade b/server/views/resources/jobs-form.jade deleted file mode 100644 index f7a693ca17..0000000000 --- a/server/views/resources/jobs-form.jade +++ /dev/null @@ -1,3 +0,0 @@ -extends ../layout -block content - iframe(src="https://docs.google.com/forms/d/1b8JYvQ5ibdwwC0owQ9e9EMRlg22O2wbJgqMvPjiILqs/viewform?embedded=true", frameborder="0", marginheight="0", marginwidth="0", width='102%', height=2100, scrolling="no") Loading... From 1994e340d33c840e1d23f880165a73d7382cab70 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Wed, 30 Sep 2015 14:57:58 -0700 Subject: [PATCH 48/63] all but 4 bonfires work --- seed/challenges/upper-intermediate-bonfires.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seed/challenges/upper-intermediate-bonfires.json b/seed/challenges/upper-intermediate-bonfires.json index bdaeefc084..83e3584e5b 100644 --- a/seed/challenges/upper-intermediate-bonfires.json +++ b/seed/challenges/upper-intermediate-bonfires.json @@ -25,9 +25,9 @@ "assert.deepEqual(Object.keys(bob).length, 6, 'message: Object.keys(bob).length should return 6.');", "assert.deepEqual(bob instanceof Person, true, 'message: bob instanceof Person should return true.');", "assert.deepEqual(bob.firstName, undefined, 'message: bob.firstName should return undefined.');", - "assert.deepEqual(bob.lastName, undefined, 'message: bob.lastName should return undefined.';", + "assert.deepEqual(bob.lastName, undefined, 'message: bob.lastName should return undefined.');", "assert.deepEqual(bob.getFirstName(), 'Bob', 'message: bob.getFirstName() should return \"Bob\".');", - "assert.deepEqual(bob.getLastName(), 'Ross', 'message: bob.getLastName() should return \"Ross\".';", + "assert.deepEqual(bob.getLastName(), 'Ross', 'message: bob.getLastName() should return \"Ross\".');", "assert.deepEqual(bob.getFullName(), 'Bob Ross', 'message: bob.getFullName() should return \"Bob Ross\".');" ], "MDNlinks": [ From 4fffabfe8f8544fe1b1b806832d18f6a49cde964 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Wed, 30 Sep 2015 18:33:32 -0700 Subject: [PATCH 49/63] fix exact change and QA all JS challenges --- seed/challenges/advanced-bonfires.json | 34 ++-- .../automated-testing-and-debugging.json | 10 +- seed/challenges/basic-javascript.json | 150 +++++++++--------- ...t-oriented-and-functional-programming.json | 68 ++++---- 4 files changed, 131 insertions(+), 131 deletions(-) diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index dd4b9d3778..48bc294b7b 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -126,26 +126,26 @@ "}", "", "// Example cash-in-drawer array:", - "// [['PENNY', 1.01],", - "// ['NICKEL', 2.05],", - "// ['DIME', 3.10],", - "// ['QUARTER', 4.25],", - "// ['ONE', 90.00],", - "// ['FIVE', 55.00],", - "// ['TEN', 20.00],", - "// ['TWENTY', 60.00],", - "// ['ONE HUNDRED', 100.00]]", + "// [[\"PENNY\", 1.01],", + "// [\"NICKEL\", 2.05],", + "// [\"DIME\", 3.10],", + "// [\"QUARTER\", 4.25],", + "// [\"ONE\", 90.00],", + "// [\"FIVE\", 55.00],", + "// [\"TEN\", 20.00],", + "// [\"TWENTY\", 60.00],", + "// [\"ONE HUNDRED\", 100.00]]", "", - "drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]);" + "drawer(19.50, 20.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]);" ], "tests": [ - "assert.isArray(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), 'message: drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]) should return an array.');", - "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'message: drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]) should return a string.');", - "assert.isString(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'message: drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]) should return a string.');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'message: drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]) should return [['QUARTER', 0.50]].');", - "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04]], 'message: drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]) should return [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04]].');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'message: drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]) should return \"Insufficient Funds\".');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'message: drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]) should return \"Closed\".');" + "assert.isArray(drawer(19.50, 20.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]), 'message: drawer(19.50, 20.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]) should return an array.');", + "assert.isString(drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), 'message: drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]) should return a string.');", + "assert.isString(drawer(19.50, 20.00, [[\"PENNY\", 0.50], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), 'message: drawer(19.50, 20.00, [[\"PENNY\", 0.50], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]) should return a string.');", + "assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]), [[\"QUARTER\", 0.50]], 'message: drawer(19.50, 20.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]) should return [[\"QUARTER\", 0.50]].');", + "assert.deepEqual(drawer(3.26, 100.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]), [[\"TWENTY\", 60.00], [\"TEN\", 20.00], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.50], [\"DIME\", 0.20], [\"PENNY\", 0.04]], 'message: drawer(3.26, 100.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]) should return [[\"TWENTY\", 60.00], [\"TEN\", 20.00], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.50], [\"DIME\", 0.20], [\"PENNY\", 0.04]].');", + "assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), \"Insufficient Funds\", 'message: drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]) should return \"Insufficient Funds\".');", + "assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 0.50], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), \"Closed\", 'message: drawer(19.50, 20.00, [[\"PENNY\", 0.50], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]) should return \"Closed\".');" ], "MDNlinks": [ "Global Object" diff --git a/seed/challenges/automated-testing-and-debugging.json b/seed/challenges/automated-testing-and-debugging.json index 2fbb5352d7..294739a6ca 100644 --- a/seed/challenges/automated-testing-and-debugging.json +++ b/seed/challenges/automated-testing-and-debugging.json @@ -13,7 +13,7 @@ "console.log('Hello world!')" ], "tests":[ - "assert(editor.getValue().match(/console\\.log\\(/gi), 'You should use the console.log method to log \"Hello world!\" to your JavaScript console.');" + "assert(editor.getValue().match(/console\\.log\\(/gi), 'message: You should use the console.log method to log \"Hello world!\" to your JavaScript console.');" ], "challengeSeed":[ "", @@ -37,10 +37,10 @@ "console.log(typeof({}));" ], "tests":[ - "assert(editor.getValue().match(/console\\.log\\(typeof\\(\"\"\\)\\);/gi), 'You should console.log the typeof a string.');", - "assert(editor.getValue().match(/console\\.log\\(typeof\\(0\\)\\);/gi), 'You should console.log the typeof a number.');", - "assert(editor.getValue().match(/console\\.log\\(typeof\\(\\[\\]\\)\\);/gi), 'You should console.log the typeof an array.');", - "assert(editor.getValue().match(/console\\.log\\(typeof\\(\\{\\}\\)\\);/gi), 'You should console.log the typeof a object.');" + "assert(editor.getValue().match(/console\\.log\\(typeof\\(\"\"\\)\\);/gi), 'message: You should console.log the typeof a string.');", + "assert(editor.getValue().match(/console\\.log\\(typeof\\(0\\)\\);/gi), 'message: You should console.log the typeof a number.');", + "assert(editor.getValue().match(/console\\.log\\(typeof\\(\\[\\]\\)\\);/gi), 'message: You should console.log the typeof an array.');", + "assert(editor.getValue().match(/console\\.log\\(typeof\\(\\{\\}\\)\\);/gi), 'message: You should console.log the typeof a object.');" ], "challengeSeed":[ "", diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index e3542ee41d..95d0884101 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -17,9 +17,9 @@ "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." ], "tests":[ - "assert(editor.getValue().match(/(\\/\\/)...../g), 'Create a // style comment that contains at least five letters');", - "assert(editor.getValue().match(/(\\/\\*)[\\w\\W]{5,}(?=\\*\\/)/gm), 'Create a /* */ style comment that contains at least five letters.');", - "assert(editor.getValue().match(/(\\*\\/)/g), 'Make sure that you close the comment with a */');" + "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":[ ], @@ -36,8 +36,8 @@ "Let's modify our welcomeToBooleansfunction so that it will return trueinstead of falsewhen the run button is clicked." ], "tests": [ - "assert(typeof(welcomeToBooleans()) === 'boolean', 'The welcomeToBooleans() function should return a boolean (true/false) value.');", - "assert(welcomeToBooleans() === true, 'welcomeToBooleans() should return true.');" + "assert(typeof(welcomeToBooleans()) === 'boolean', 'message: The welcomeToBooleans() function should return a boolean (true/false) value.');", + "assert(welcomeToBooleans() === true, 'message: welcomeToBooleans() should return true.');" ], "challengeSeed": [ "function welcomeToBooleans() {", @@ -66,7 +66,7 @@ "Look at the ourName example if you get stuck." ], "tests": [ - "assert((function(){if(typeof(myName) !== \"undefined\" && typeof(myName) === \"string\" && myName.length > 0){return true;}else{return false;}})(), 'myName should be a string that contains at least one character in it.');" + "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\";", @@ -90,8 +90,8 @@ "Now let's create two new string variables: myFirstNameand 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;}})(), '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;}})(), 'myLastName should be a string with at least one character in it.');" + "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\";", @@ -117,8 +117,8 @@ "Use the .length property to count the number of characters in the lastName variable." ], "tests": [ - "assert((function(){if(typeof(lastNameLength) !== \"undefined\" && typeof(lastNameLength) === \"number\" && lastNameLength === 8){return true;}else{return false;}})(), 'lastNameLength should be equal to eight.');", - "assert((function(){if(editor.getValue().match(/\\.length/gi) && editor.getValue().match(/\\.length/gi).length >= 2 && editor.getValue().match(/var lastNameLength \\= 0;/gi) && editor.getValue().match(/var lastNameLength \\= 0;/gi).length >= 1){return true;}else{return false;}})(), 'You should be getting the length of lastName by using .length like this: lastName.length.');" + "assert((function(){if(typeof(lastNameLength) !== \"undefined\" && typeof(lastNameLength) === \"number\" && lastNameLength === 8){return true;}else{return false;}})(), 'message: lastNameLength should be equal to eight.');", + "assert((function(){if(editor.getValue().match(/\\.length/gi) && editor.getValue().match(/\\.length/gi).length >= 2 && editor.getValue().match(/var lastNameLength \\= 0;/gi) && editor.getValue().match(/var lastNameLength \\= 0;/gi).length >= 1){return true;}else{return false;}})(), 'message: You should be getting the length of lastName by using .length like this: lastName.length.');" ], "challengeSeed": [ "var firstNameLength = 0;", @@ -155,7 +155,7 @@ "Try looking at the firstLetterOfFirstName variable declaration if you get stuck." ], "tests": [ - "assert((function(){if(typeof(firstLetterOfLastName) !== \"undefined\" && editor.getValue().match(/\\[0\\]/gi) && typeof(firstLetterOfLastName) === \"string\" && firstLetterOfLastName === \"L\"){return true;}else{return false;}})(), 'The first letter of firstLetterOfLastName should be a \"L\".');" + "assert((function(){if(typeof(firstLetterOfLastName) !== \"undefined\" && editor.getValue().match(/\\[0\\]/gi) && typeof(firstLetterOfLastName) === \"string\" && firstLetterOfLastName === \"L\"){return true;}else{return false;}})(), 'message: The first letter of firstLetterOfLastName should be a \"L\".');" ], "challengeSeed": [ "var firstLetterOfFirstName = \"\";", @@ -189,7 +189,7 @@ "Try looking at the secondLetterOfFirstName variable declaration if you get stuck." ], "tests": [ - "assert(thirdLetterOfLastName === 'v', 'The third letter of lastName should be a \"v\".');" + "assert(thirdLetterOfLastName === 'v', 'message: The third letter of lastName should be a \"v\".');" ], "challengeSeed": [ "var firstName = \"Ada\";", @@ -220,8 +220,8 @@ "Try looking at the lastLetterOfFirstName variable declaration if you get stuck." ], "tests": [ - "assert(lastLetterOfLastName === \"e\", 'lastLetterOfLastName should be \"e\".');", - "assert(editor.getValue().match(/\\.length/g).length === 2, 'You have to use .length to get the last letter.');" + "assert(lastLetterOfLastName === \"e\", 'message: lastLetterOfLastName should be \"e\".');", + "assert(editor.getValue().match(/\\.length/g).length === 2, 'message: You have to use .length to get the last letter.');" ], "challengeSeed": [ "var firstName = \"Ada\";", @@ -252,8 +252,8 @@ "Try looking at the thirdToLastLetterOfFirstName variable declaration if you get stuck." ], "tests": [ - "assert(secondToLastLetterOfLastName === 'c', 'secondToLastLetterOfLastName should be \"c\".');", - "assert(editor.getValue().match(/\\.length/g).length === 2, 'You have to use .length to get the second last letter.');" + "assert(secondToLastLetterOfLastName === 'c', 'message: secondToLastLetterOfLastName should be \"c\".');", + "assert(editor.getValue().match(/\\.length/g).length === 2, 'message: You have to use .length to get the second last letter.');" ], "challengeSeed": [ "var firstName = \"Ada\";", @@ -283,7 +283,7 @@ "Replace the 0 with the correct number so you can get the result mentioned in the comment." ], "tests": [ - "assert((function(){if(sum === 20 && editor.getValue().match(/\\+/g).length >= 2){return true;}else{return false;}})(), 'Make the variable sum equal 20.');" + "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.", @@ -306,7 +306,7 @@ "Replace the 0 with the correct number so you can get the result mentioned in the comment." ], "tests": [ - "assert((function(){if(difference === 12 && editor.getValue().match(/\\-/g)){return true;}else{return false;}})(), 'Make the variable difference equal 12.');" + "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.", @@ -329,7 +329,7 @@ "Replace the 0 with the correct number so you can get the result mentioned in the comment." ], "tests": [ - "assert((function(){if(product === 80 && editor.getValue().match(/\\*/g)){return true;}else{return false;}})(), 'Make the variable product equal 80.');" + "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.", @@ -352,7 +352,7 @@ "Replace the 0 with the correct number so you can get the result mentioned in the comment." ], "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;}})(), 'Make the variable quotient equal 2.');" + "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.", @@ -374,7 +374,7 @@ "Let's create a variable myDecimal and give it a decimal value." ], "tests": [ - "assert((function(){if(typeof(myDecimal) !== \"undefined\" && typeof(myDecimal) === \"number\" && editor.getValue().match(/\\./g).length >=2){return true;}else{return false;}})(), 'myDecimal should be a decimal point number.');" + "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;", @@ -399,8 +399,8 @@ "Replace the 0.0 with the correct number so that you get the result mentioned in the comments." ], "tests": [ - "assert((function(){if(product === 5.0 && editor.getValue().match(/\\*/g)){return true;}else{return false;}})(), 'Make the variable product equal 5.0.');", - "assert((function(){if(quotient === 2.2 && editor.getValue().match(/\\//g)){return true;}else{return false;}})(), '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.');", + "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 = 4.4 / 2.0; // equals 2.2", @@ -426,9 +426,9 @@ "Refer to the commented code in the text editor if you get stuck." ], "tests": [ - "assert(typeof(myArray) == 'object', 'myArray should be an array.');", - "assert(typeof(myArray[0]) !== 'undefined' && typeof(myArray[0]) == 'string', 'The first item in myArray should be a string.');", - "assert(typeof(myArray[1]) !== 'undefined' && typeof(myArray[1]) == 'number', 'The second item in myArray should be a number.');" + "assert(typeof(myArray) == 'object', 'message: myArray should be an array.');", + "assert(typeof(myArray[0]) !== 'undefined' && typeof(myArray[0]) == 'string', 'message: The first item in myArray should be a string.');", + "assert(typeof(myArray[1]) !== 'undefined' && typeof(myArray[1]) == 'number', 'message: The second item in myArray should be a number.');" ], "challengeSeed": [ "// var array = [\"John\", 23];", @@ -454,7 +454,7 @@ "Let's now go create a nested array called myArray." ], "tests":[ - "assert(Array.isArray(myArray) && myArray.some(Array.isArray), 'myArray should have at least one array nested within another array.');" + "assert(Array.isArray(myArray) && myArray.some(Array.isArray), 'message: myArray should have at least one array nested within another array.');" ], "challengeSeed":[ "var ourArray = [[\"the universe\", \"everything\", 42]];", @@ -484,7 +484,7 @@ "Create a variable called myData and set it to equal the first value of myArray." ], "tests":[ - "assert((function(){if(typeof(myArray) != 'undefined' && typeof(myData) != 'undefined' && myArray[0] == myData){return true;}else{return false;}})(), 'The variable myData should equal the first value of myArray.');" + "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];", @@ -514,8 +514,8 @@ "Now modify the data stored at index 0 of myArray to the value of 3." ], "tests":[ - "assert((function(){if(typeof(myArray) != 'undefined' && myArray[0] == 3 && myArray[1] == 2 && myArray[2] == 3){return true;}else{return false;}})(), 'myArray should now be [3,2,3].');", - "assert((function(){if(editor.getValue().match(/myArray\\[0\\]\\s?=\\s?/g)){return true;}else{return false;}})(), 'You should be using correct index to modify the value in myArray.');" + "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":[ "var ourArray = [1,2,3];", @@ -544,8 +544,8 @@ "Use the .pop() function to remove the last item from myArray." ], "tests": [ - "assert((function(d){if(d[0] == 'John' && d[1] == 23 && d[2] == undefined){return true;}else{return false;}})(myArray), 'myArray should only have the first two values left([\"John\", 23]).');", - "assert((function(d){if(d[0] == 'cat' && d[1] == 2 && d[2] == undefined){return true;}else{return false;}})(removed), 'removed should only have the first two values left([\"cat\"], 2).');" + "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.');" ], "challengeSeed": [ "// var numbers = [1,2,3];", @@ -576,7 +576,7 @@ "Take the myArray array and push() this value to the end of it: [\"dog\", 3]." ], "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), 'myArray should only have the first two values left([\"John\", 23, [\"dog\", 3]]).');" + "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\"]];", @@ -607,8 +607,8 @@ "Take the myArray array and shift() the first value off of it. Set myRemoved to the first value of myArray using shift()." ], "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), 'myArray should only have the last two values left([23, [\"dog\", 3]]).');", - "assert((function(d){if(d === 'John' && typeof(myRemoved) === 'string'){return true;}else{return false;}})(myRemoved), 'myRemoved should contain \"John\".');" + "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\".');" ], "challengeSeed": [ "var ourArray = [\"Stimpson\", \"J\", [\"cat\"]];", @@ -638,7 +638,7 @@ "Let's take the code we had last time and unshiftthis value to the start: \"Paul\"." ], "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), 'myArray should now have [\"Paul\", 23, [\"dog\", 3]]).');" + "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\"]];", @@ -677,7 +677,7 @@ "Create and call a function called myFunction that returns the sum of a and b." ], "tests":[ - "assert((function(){if(typeof(f) !== \"undefined\" && f === a + b){return true;}else{return false;}})(), 'Your function should return the value of a + b');" + "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":[ "var a = 4;", @@ -723,10 +723,10 @@ "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)!" ], "tests":[ - "assert((function(z){if(z.hasOwnProperty(\"name\") && z.name !== undefined && typeof(z.name) === \"string\"){return true;}else{return false;}})(myDog), 'myDog should contain the property name and it should be a string.');", - "assert((function(z){if(z.hasOwnProperty(\"legs\") && z.legs !== undefined && typeof(z.legs) === \"number\"){return true;}else{return false;}})(myDog), '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), '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), 'myDog should contain the property friends and it should be an array.');" + "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 = {", @@ -765,8 +765,8 @@ "Let's add the property \"bark\", and delete the property \"tails\"." ], "tests":[ - "assert(myDog.bark !== undefined, 'Add the property \"bark\" to myDog.');", - "assert(myDog.tails === undefined, 'Delete the property \"tails\" from myDog.');" + "assert(myDog.bark !== undefined, 'message: Add the property \"bark\" to myDog.');", + "assert(myDog.tails === undefined, 'message: Delete the property \"tails\" from myDog.');" ], "challengeSeed":[ "// var ourDog = {", @@ -816,8 +816,8 @@ "Let's try getting a for loop to work by pushing values to an array." ], "tests":[ - "assert(editor.getValue().match(/for/g), 'You should be using a for loop for this.');", - "assert.deepEqual(myArray, [0,1,2,3,4], 'myArray should equal [0,1,2,3,4].');" + "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].');" ], "challengeSeed":[ "ourArray = [];", @@ -855,8 +855,8 @@ "Let's try getting a while loop to work by pushing values to an array." ], "tests":[ - "assert(editor.getValue().match(/while/g), 'You should be using a while loop for this.');", - "assert.deepEqual(myArray, [0,1,2,3,4], 'myArray should equal [0,1,2,3,4].');" + "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].');" ], "challengeSeed":[ "var myArray = [];", @@ -883,9 +883,9 @@ "Use Math.random() to get myFunction to return a random number." ], "tests":[ - "assert(typeof(myFunction()) === \"number\", 'myFunction should return a random number.');", - "assert((myFunction()+''). match(/\\./g), 'The number returned by myFunction should be a decimal.');", - "assert(editor.getValue().match(/Math\\.random/g).length >= 2, 'You should be using Math.random to generate the random decimal number.');" + "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.');" ], "challengeSeed":[ "function myFunction() {", @@ -916,10 +916,10 @@ "Let's give this technique a go now." ], "tests":[ - "assert(typeof(myFunction()) === \"number\", 'The result of myFunction should be a number.');", - "assert(editor.getValue().match(/Math.random/g), 'You should be using Math.random to create 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), 'You should have multiplied the result of Math.random by 10 to make it a number that\\'s between zero and nine.');", - "assert(editor.getValue().match(/Math.floor/g), 'You should use Math.floor to remove the decimal part of the number.');" + "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(/\\(\\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":[ "function myFunction(){", @@ -948,10 +948,10 @@ "By using this, we can control the output of a random number." ], "tests":[ - "assert(myFunction() >= min, 'The random number that\\'s generated by myFunction should be greater than or equal to the minimum number');", - "assert(myFunction() <= max, 'The random number that\\'s generated by myFunction should be less than or equal to the maximum number');", - "assert(myFunction() % 1 === 0 , 'The random number that\\'s generated by myFunction should be an integer');", - "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;}})(), 'You should be using the function given in the description to calculate the random in number in a range');" + "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.');", + "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.');" ], "challengeSeed":[ "var min = 0;", @@ -987,10 +987,10 @@ "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":[ - "assert((function(){var result = myFunction();if(result === 'heads' || result === 'tails'){return true;} else {return false;}})(), '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;}})(), 'myFunction should return heads when flip equals 0 and tails when flip equals 1.');", - "assert(editor.getValue().match(/if/g).length >= 4, 'You should have created a new if statement.');", - "assert(editor.getValue().match(/else/g).length >= 2, 'You should have 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.');" ], "challengeSeed":[ "var flip = Math.floor(Math.random() * (1 - 0 + 1)) + 0;", @@ -1025,8 +1025,8 @@ "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":[ - "assert(test==2, 'Your regular expression should find two occurrences of the word and.');", - "assert(editor.getValue().match(/\\/and\\/gi/), 'You should have used regular expressions to find the word and.');" + "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.');" ], "challengeSeed":[ "var test = (function() {", @@ -1056,8 +1056,8 @@ "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, 'Your RegEx should have found two numbers in the testString.');", - "assert(editor.getValue().match(/\\/\\\\d\\+\\//gi), 'You should be using the following expression /\\\\d+/gi to find the numbers in the testString.');" + "assert(test === 2, 'message: Your RegEx should have found two numbers in the testString.');", + "assert(editor.getValue().match(/\\/\\\\d\\+\\//gi), 'message: You should be using the following expression /\\\\d+/gi to find the numbers in the testString.');" ], "challengeSeed":[ "var test = (function() {", @@ -1086,8 +1086,8 @@ "Select all the spaces in the sentence string." ], "tests":[ - "assert(test === 7, 'Your RegEx should have found seven spaces in the testString.');", - "assert(editor.getValue().match(/\\/\\\\s\\+\\//gi), 'You should be using the following expression /\\\\s+/gi to find the spaces in the testString.');" + "assert(test === 7, 'message: Your RegEx should have found seven spaces in the testString.');", + "assert(editor.getValue().match(/\\/\\\\s\\+\\//gi), 'message: You should be using the following expression /\\\\s+/gi to find the spaces in the testString.');" ], "challengeSeed":[ "var test = (function(){", @@ -1114,8 +1114,8 @@ "You can invert any match by using the uppercase version of the selector \\s versus \\S for example." ], "tests":[ - "assert(test === 49, 'Your RegEx should have found forty nine non-space characters in the testString.');", - "assert(editor.getValue().match(/\\/\\\\S\\/gi/gi), 'You should be using the following expression /\\\\S/gi to find non-space characters in the testString.');" + "assert(test === 49, 'message: Your RegEx should have found forty nine non-space characters in the testString.');", + "assert(editor.getValue().match(/\\/\\\\S\\/gi/gi), 'message: You should be using the following expression /\\\\S/gi to find non-space characters in the testString.');" ], "challengeSeed":[ "var test = (function(){", @@ -1145,10 +1145,10 @@ "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.')" + "assert(typeof(runSlots($(\".slot\"))[0]) === \"number\", 'message: slotOne should be a random number.')", + "assert(typeof(runSlots($(\".slot\"))[1]) === \"number\", 'message: slotTwo should be a random number.')", + "assert(typeof(runSlots($(\".slot\"))[2]) === \"number\", 'message: 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;}})(), 'message: You should have used Math.floor(Math.random() * (3 - 1 + 1)) + 1; three times to generate your random numbers.')" ], "challengeSeed":[ "fccss", @@ -1615,7 +1615,7 @@ }, { "id":"cf1111c1c11feddfaeb1bdff", - "title": "Give your JavaScript Slot Machine some stylish images", + "title": "Give your JavaScript Slot Machine some Stylish Images", "difficulty":"9.9901", "description":[ "Now let's add some images to our slots.", diff --git a/seed/challenges/object-oriented-and-functional-programming.json b/seed/challenges/object-oriented-and-functional-programming.json index 2b89e9f6c0..ea84d904db 100644 --- a/seed/challenges/object-oriented-and-functional-programming.json +++ b/seed/challenges/object-oriented-and-functional-programming.json @@ -20,9 +20,9 @@ "Give your motorBike object a wheels, engines and seats attribute and set them to numbers." ], "tests":[ - "assert(typeof(motorBike.engines) === 'number', 'motorBike should have a engines attribute set to a number.');", - "assert(typeof(motorBike.wheels) === 'number', 'motorBike should have a wheels attribute set to a number.');", - "assert(typeof(motorBike.seats) === 'number', 'motorBike should have a seats attribute set to a number.');" + "assert(typeof(motorBike.engines) === 'number', 'message: motorBike should have a engines attribute set to a number.');", + "assert(typeof(motorBike.wheels) === 'number', 'message: motorBike should have a wheels attribute set to a number.');", + "assert(typeof(motorBike.seats) === 'number', 'message: motorBike should have a seats attribute set to a number.');" ], "challengeSeed":[ "//Here is a sample Object", @@ -57,9 +57,9 @@ "Give your myMotorBike object a wheels, engines and seats attribute and set them to numbers." ], "tests":[ - "assert(typeof((new MotorBike()).engines) === 'number', 'myMotorBike should have a engines attribute set to a number.');", - "assert(typeof((new MotorBike()).wheels) === 'number', 'myMotorBike should have a wheels attribute set to a number.');", - "assert(typeof((new MotorBike()).seats) === 'number', 'myMotorBike should have a seats attribute set to a number.');" + "assert(typeof((new MotorBike()).engines) === 'number', 'message: myMotorBike should have a engines attribute set to a number.');", + "assert(typeof((new MotorBike()).wheels) === 'number', 'message: myMotorBike should have a wheels attribute set to a number.');", + "assert(typeof((new MotorBike()).seats) === 'number', 'message: myMotorBike should have a seats attribute set to a number.');" ], "challengeSeed":[ "// Let's add the properties engines and seats to the car in the same way that the property wheels has been added below. They should both be numbers.", @@ -98,9 +98,9 @@ "See if you can keep myBike.speed and myBike.addUnit private, while making myBike.getSpeed publicly accessible." ], "tests":[ - "assert(typeof(myBike.getSpeed)!=='undefined' && typeof(myBike.getSpeed) === 'function', 'The method getSpeed of myBike should be accessible outside the object');", - "assert(typeof(myBike.speed) === 'undefined', 'myBike.speed should remain undefined.');", - "assert(typeof(myBike.addUnit) === 'undefined', 'myBike.addUnit should remain undefined.');" + "assert(typeof(myBike.getSpeed)!=='undefined' && typeof(myBike.getSpeed) === 'function', 'message: The method getSpeed of myBike should be accessible outside the object.');", + "assert(typeof(myBike.speed) === 'undefined', 'message: myBike.speed should remain undefined.');", + "assert(typeof(myBike.addUnit) === 'undefined', 'message: myBike.addUnit should remain undefined.');" ], "challengeSeed":[ "//Let's create an object with a two functions. One attached as a property and one not.", @@ -149,10 +149,10 @@ "Then you can give the instance new properties." ], "tests":[ - "assert((new Car()).wheels === 4, 'The property wheels should still be 4 like in the object constructor');", - "assert(typeof((new Car()).engines) === 'undefined', 'There should not be a property engine in the object constructor');", - "assert(myCar.wheels === 4, 'The property wheels of myCar should be four');", - "assert(typeof(myCar.engines) === 'number', 'The property engine of myCar should be a number');" + "assert((new Car()).wheels === 4, 'message: The property wheels should still be 4 like in the object constructor.');", + "assert(typeof((new Car()).engines) === 'undefined', 'message: There should not be a property engines in the object constructor.');", + "assert(myCar.wheels === 4, 'message: The property wheels of myCar should equal 4.');", + "assert(typeof(myCar.engines) === 'number', 'message: The property engines of myCar should be a number.');" ], "challengeSeed":[ "var Car = function() {", @@ -184,9 +184,9 @@ "Use the map function to add 3 to every value in the variable array" ], "tests":[ - "assert.deepEqual(array, [4,5,6,7,8], 'You should have added three to each value in the array');", - "assert(editor.getValue().match(/\\.map\\(/gi), 'You should be making use of the map method');", - "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\]/gi), 'You should only modify the array with .map');" + "assert.deepEqual(array, [4,5,6,7,8], 'message: You should add three to each value in the array.');", + "assert(editor.getValue().match(/\\.map\\(/gi), 'message: You should be making use of the map method.');", + "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\]/gi), 'message: You should only modify the array with .map.');" ], "challengeSeed":[ "//Use map to add three to each value in the array", @@ -212,8 +212,8 @@ "});" ], "tests":[ - "assert(singleVal == 30, 'singleVal should have been set to the result of you reduce operation');", - "assert(editor.getValue().match(/\\.reduce\\(/gi), 'You should have made use of the reduce method');" + "assert(singleVal == 30, 'message: singleVal should have been set to the result of you reduce operation.');", + "assert(editor.getValue().match(/\\.reduce\\(/gi), 'message: You should have made use of the reduce method.');" ], "challengeSeed":[ "var array = [4,5,6,7,8];", @@ -240,9 +240,9 @@ "});" ], "tests":[ - "assert.deepEqual(array, [1,2,3,4,5], 'You should have removed all the values from the array that are greater than five');", - "assert(editor.getValue().match(/array\\.filter\\(/gi), 'You should be using the filter method to remove the values from the array');", - "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7\\,8\\,9\\,10\\]/gi), 'You should only be using .filter to modify the contents of the array');" + "assert.deepEqual(array, [1,2,3,4], 'message: You should have removed all the values from the array that are greater than 4.');", + "assert(editor.getValue().match(/array\\.filter\\(/gi), 'message: You should be using the filter method to remove the values from the array.');", + "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7\\,8\\,9\\,10\\]/gi), 'message: You should only be using .filter to modify the contents of the array.');" ], "challengeSeed":[ "var array = [1,2,3,4,5,6,7,8,9,10];", @@ -267,9 +267,9 @@ "This will return [1, 2, 3]" ], "tests":[ - "assert.deepEqual(array, ['alpha', 'beta', 'charlie'], 'You should have sorted the array alphabetically');", - "assert(editor.getValue().match(/\\[\\'beta\\'\\,\\s\\'alpha\\'\\,\\s'charlie\\'\\];/gi), 'You should be sorting the array using sort');", - "assert(editor.getValue().match(/\\.sort\\(\\)/gi), 'You should have made use of the sort method');" + "assert.deepEqual(array, ['alpha', 'beta', 'charlie'], 'message: You should have sorted the array alphabetically.');", + "assert(editor.getValue().match(/\\[\\'beta\\'\\,\\s\\'alpha\\'\\,\\s'charlie\\'\\];/gi), 'message: You should be sorting the array using sort.');", + "assert(editor.getValue().match(/\\.sort\\(\\)/gi), 'message: You should have made use of the sort method.');" ], "challengeSeed":[ "var array = ['beta', 'alpha', 'charlie'];", @@ -291,9 +291,9 @@ "You can use the .reverse() function to reverse the contents of an array." ], "tests": [ - "assert.deepEqual(array, [7,6,5,4,3,2,1], 'You should reverse the array');", - "assert(editor.getValue().match(/\\.reverse\\(\\)/gi), '');", - "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7/gi), '');" + "assert.deepEqual(array, [7,6,5,4,3,2,1], 'message: You should reverse the array.');", + "assert(editor.getValue().match(/\\.reverse\\(\\)/gi), 'message: You should use the reverse method.');", + "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7/gi), 'message: You should return [7,6,5,4,3,2,1].');" ], "challengeSeed": [ "var array = [1,2,3,4,5,6,7];", @@ -316,9 +316,9 @@ "array = array.concat(otherArray);" ], "tests": [ - "assert.deepEqual(array, [1,2,3,4,5,6], 'You should concat the two arrays together');", - "assert(editor.getValue().match(/\\.concat\\(/gi), 'You should be using the concat method to merge the two arrays');", - "assert(editor.getValue().match(/\\[1\\,2\\,3\\]/gi) && editor.getValue().match(/\\[4\\,5\\,6\\]/gi), 'You should only modify the two arrays without changing the origional ones');" + "assert.deepEqual(array, [1,2,3,4,5,6], 'You should concat the two arrays together.');", + "assert(editor.getValue().match(/\\.concat\\(/gi), 'message: You should be use the concat method to merge the two arrays.');", + "assert(editor.getValue().match(/\\[1\\,2\\,3\\]/gi) && editor.getValue().match(/\\[4\\,5\\,6\\]/gi), 'message: You should only modify the two arrays without changing the origional ones.');" ], "challengeSeed": [ "var array = [1,2,3];", @@ -344,8 +344,8 @@ "array = string.split(' ');" ], "tests":[ - "assert(typeof(array) === 'object' && array.length === 5, 'You should have split the string by it\\'s spaces');", - "assert(/\\.split\\(/gi, 'You should have made use of the split method on the string');" + "assert(typeof(array) === 'object' && array.length === 5, 'message: You should split the string by its spaces.');", + "assert(/\\.split\\(/gi, 'message: You should use the split method on the string.');" ], "challengeSeed":[ "var string = \"Split me into an array\";", @@ -368,8 +368,8 @@ "var joinMe = joinMe.join(\" \");" ], "tests":[ - "assert(typeof(joinMe) === 'string' && joinMe === \"Split me into an array\", 'You should have joined the arrays by it\\'s spaces');", - "assert(/\\.join\\(/gi, 'You should have made use of the join method on the array');" + "assert(typeof(joinMe) === 'string' && joinMe === \"Split me into an array\", 'message: You should join the arrays by their spaces.');", + "assert(/\\.join\\(/gi, 'message: You should use of the join method on the array.');" ], "challengeSeed":[ "var joinMe = [\"Split\",\"me\",\"into\",\"an\",\"array\"];", From 16c0c23b2c2efb782d7e11427e5d7f293dddbb28 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Wed, 30 Sep 2015 19:04:26 -0700 Subject: [PATCH 50/63] finish QAing all bonfires --- seed/challenges/advanced-bonfires.json | 28 +++++++++++----------- seed/challenges/intermediate-bonfires.json | 19 +++++++-------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index 48bc294b7b..3ee8a9f041 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -179,28 +179,28 @@ "", "// Example inventory lists", "var curInv = [", - " [21, 'Bowling Ball'],", - " [2, 'Dirty Sock'],", - " [1, 'Hair Pin'],", - " [5, 'Microphone']", + " [21, \"Bowling Ball\"],", + " [2, \"Dirty Sock\"],", + " [1, \"Hair Pin\"],", + " [5, \"Microphone\"]", "];", "", "var newInv = [", - " [2, 'Hair Pin'],", - " [3, 'Half-Eaten Apple'],", - " [67, 'Bowling Ball'],", - " [7, 'Toothpaste']", + " [2, \"Hair Pin\"],", + " [3, \"Half-Eaten Apple\"],", + " [67, \"Bowling Ball\"],", + " [7, \"Toothpaste\"]", "];", "", "inventory(curInv, newInv);" ], "tests": [ - "assert.isArray(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), 'message: inventory() should return an array.');", - "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6, 'message: inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length should return an array with a length of 6.');", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']], 'message: inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]) should return [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']].');", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], 'message: inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []) should return [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']].);", - "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']], 'message: inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]) should return [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']].');", - "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']], 'message: inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]) should return [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']].');" + "assert.isArray(inventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]), 'message: inventory() should return an array.');", + "assert.equal(inventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]).length, 6, 'message: inventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]).length should return an array with a length of 6.');", + "assert.deepEqual(inventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]), [[88, \"Bowling Ball\"], [2, \"Dirty Sock\"], [3, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [5, \"Microphone\"], [7, \"Toothpaste\"]], 'message: inventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]) should return [[88, \"Bowling Ball\"], [2, \"Dirty Sock\"], [3, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [5, \"Microphone\"], [7, \"Toothpaste\"]].');", + "assert.deepEqual(inventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], []), [[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], 'message: inventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], []) should return [[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]].');", + "assert.deepEqual(inventory([], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]), [[67, \"Bowling Ball\"], [2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [7, \"Toothpaste\"]], 'message: inventory([], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]) should return [[67, \"Bowling Ball\"], [2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [7, \"Toothpaste\"]].');", + "assert.deepEqual(inventory([[0, \"Bowling Ball\"], [0, \"Dirty Sock\"], [0, \"Hair Pin\"], [0, \"Microphone\"]], [[1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [1, \"Bowling Ball\"], [1, \"Toothpaste\"]]), [[1, \"Bowling Ball\"], [0, \"Dirty Sock\"], [1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [0, \"Microphone\"], [1, \"Toothpaste\"]], 'message: inventory([[0, \"Bowling Ball\"], [0, \"Dirty Sock\"], [0, \"Hair Pin\"], [0, \"Microphone\"]], [[1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [1, \"Bowling Ball\"], [1, \"Toothpaste\"]]) should return [[1, \"Bowling Ball\"], [0, \"Dirty Sock\"], [1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [0, \"Microphone\"], [1, \"Toothpaste\"]].');" ], "MDNlinks": [ "Global Array Object" diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json index 35ccf0c7f9..684afd44e8 100644 --- a/seed/challenges/intermediate-bonfires.json +++ b/seed/challenges/intermediate-bonfires.json @@ -151,9 +151,8 @@ ], "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([{ '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 }].');", - "assert.deepEqual(where([{ \"a\": 5 }, { \"b\": 10 }, { \"a\": 5, \"b\": 10 }], { \"a\": 5, \"b\": 10 }), [{ \"a\": 5, \"b\": 10 }], 'message: where([{ \"a\": 5 }, { \"b\": 10 }, { \"a\": 5, \"b\": 10 }], { \"a\": 5, \"b\": 10 }) should return [{ \"a\": 5, \"b\": 10 }].');" + "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 }].');" ], "MDNlinks": [ "Global Object", @@ -442,13 +441,13 @@ "convert(\"Dolce & Gabbana\");" ], "tests": [ - "assert.match(convert(\"Dolce & Gabbana\"), /Dolce & Gabbana/, 'message: convert(\"Dolce & Gabbana\") should return Dolce & Gabbana.');", - "assert.match(convert(\"Hamburgers < Pizza < Tacos\"), /Hamburgers < Pizza < Tacos/, 'message: convert(\"Hamburgers < Pizza < Tacos\") should return Hamburgers < Pizza < Tacos.');", - "assert.match(convert(\"Sixty > twelve\"), /Sixty > twelve/, 'message: convert(\"Sixty > twelve\") should return Sixty > twelve.');", - "assert.match(convert('Stuff in \"quotation marks\"'), /Stuff in "quotation marks"/, 'message: convert('Stuff in \"quotation marks\"') should return Stuff in "quotation marks".');", - "assert.match(convert(\"Shindler's List\"), /Shindler's List/, 'message: convert(\"Shindler's List\") should return Shindler's List.');", - "assert.match(convert('<>'), /<>/, 'message: convert('<>') should return <>.');", - "assert.strictEqual(convert('abc'), 'abc', 'message: convert(\"abc\") should return \"abc\".');" + "assert.match(convert(\"Dolce & Gabbana\"), /Dolce & Gabbana/, 'message: convert(\"Dolce & Gabbana\") should return Dolce &​amp; Gabbana.');", + "assert.match(convert(\"Hamburgers < Pizza < Tacos\"), /Hamburgers < Pizza < Tacos/, 'message: convert(\"Hamburgers < Pizza < Tacos\") should return Hamburgers &​lt; Pizza &​lt; Tacos.');", + "assert.match(convert(\"Sixty > twelve\"), /Sixty > twelve/, 'message: convert(\"Sixty > twelve\") should return Sixty &​gt; twelve.');", + "assert.match(convert('Stuff in \"quotation marks\"'), /Stuff in "quotation marks"/, 'message: convert('Stuff in \"quotation marks\"') should return Stuff in &​quot;quotation marks&​quot;.');", + "assert.match(convert(\"Shindler's List\"), /Shindler's List/, 'message: convert(\"Shindler's List\") should return Shindler&​apos;s List.');", + "assert.match(convert('<>'), /<>/, 'message: convert(\"<>\") should return &​lt;&​gt;.');", + "assert.strictEqual(convert('abc'), 'abc', 'message: convert(\"abc\") should return abc.');" ], "MDNlinks": [ "RegExp", From c2af4f9b4c85767014a7907959e1128240952b7f Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Wed, 30 Sep 2015 19:26:05 -0700 Subject: [PATCH 51/63] fix bad merge --- seed/challenges/intermediate-bonfires.json | 90 ---------------------- 1 file changed, 90 deletions(-) diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json index 62aef4687d..684afd44e8 100644 --- a/seed/challenges/intermediate-bonfires.json +++ b/seed/challenges/intermediate-bonfires.json @@ -61,7 +61,6 @@ "diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);" ], "tests": [ -<<<<<<< HEAD "assert(typeof(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])) === \"object\", 'message: diff() should return an array.');", "assert.deepEqual(diff([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"pink wool\"], 'message: [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return [\"pink wool\"].');", "assert.includeMembers(diff([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"diorite\", \"pink wool\"], 'message: [\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return [\"diorite\", \"pink wool\"].');", @@ -69,15 +68,6 @@ "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(typeof(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])) === \"object\", 'The result should be an array.');", - "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'arrays with only one difference');", - "assert.includeMembers(diff(['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['diorite', 'pink wool'], 'arrays with more than one difference');", - "assert.deepEqual(diff(['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub']), [], 'arrays with no difference');", - "assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'arrays with numbers');", - "assert.includeMembers(diff([1, 'calf', 3, 'piglet'], [1, 'calf', 3, 4]), ['piglet', 4], 'arrays with numbers and strings');", - "assert.deepEqual(diff([], ['snuffleupagus', 'cookie monster', 'elmo']), ['snuffleupagus', 'cookie monster', 'elmo'], 'empty array');" ->>>>>>> staging ], "MDNlinks": [ "Comparison Operators", @@ -103,19 +93,11 @@ "id": "a7f4d8f2483413a6ce226cac", "title": "Roman Numeral Converter", "tests": [ -<<<<<<< HEAD "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(29), \"XXIX\", 'message: convert(29) should return \"XXIX\".');", "assert.deepEqual(convert(16), \"XVI\", 'message: convert(16) should return \"XVI\".');" -======= - "assert.deepEqual(convert(12), \"XII\", 'convert(12) should return \"XII\"');", - "assert.deepEqual(convert(5), \"V\", 'convert(5) should return \"V\"');", - "assert.deepEqual(convert(9), \"IX\", 'convert(9) should return \"IX\"');", - "assert.deepEqual(convert(29), \"XXIX\", 'convert(29) should return \"XXIX\"');", - "assert.deepEqual(convert(16), \"XVI\", 'convert(16) should return \"XVI\"');" ->>>>>>> staging ], "difficulty": "2.02", "description": [ @@ -168,16 +150,9 @@ "where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" });" ], "tests": [ -<<<<<<< HEAD "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([{ \"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 }].');" -======= - "assert.deepEqual(where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }), [{ first: 'Tybalt', last: 'Capulet' }], 'should return an array of objects');", - "assert.deepEqual(where([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'should return with multiples');", - "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 }], 'should return two objects in array');", - "assert.deepEqual(where([{ 'a': 5 }, { 'b': 10 }, { 'a': 5, 'b': 10 }], { 'a': 5, 'b': 10 }), [{ 'a': 5, 'b': 10 }], 'should return a single object in array');" ->>>>>>> staging ], "MDNlinks": [ "Global Object", @@ -201,19 +176,11 @@ "id": "a0b5010f579e69b815e7c5d6", "title": "Search and Replace", "tests": [ -<<<<<<< HEAD "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(\"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\".');" -======= - "assert.deepEqual(replace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'replace(\"Let us go to the store\", \"store\", \"mall\") should return \"Let us go to the mall\"');", - "assert.deepEqual(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\") should return \"He is Sitting on the couch\"');", - "assert.deepEqual(replace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'replace(\"This has a spellngi error\", \"spellingi\", \"spelling\") should return \"This has a spelling error\"');", - "assert.deepEqual(replace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'replace(\"His name is Tom\", \"Tom\", \"john\") should return \"His name is John\"');", - "assert.deepEqual(replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\"), \"Let us get back to more Bonfires\", 'replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\") should return \"Let us get back to more Bonfires\"');" ->>>>>>> staging ], "difficulty": "2.035", "description": [ @@ -253,19 +220,11 @@ "id": "aa7697ea2477d1316795783b", "title": "Pig Latin", "tests": [ -<<<<<<< HEAD "assert.deepEqual(translate(\"california\"), \"aliforniacay\", 'message: translate(\"california\") should return \"aliforniacay\".');", "assert.deepEqual(translate(\"paragraphs\"), \"aragraphspay\", 'message: translate(\"paragraphs\") should return \"aragraphspay\".');", "assert.deepEqual(translate(\"glove\"), \"oveglay\", 'message: translate(\"glove\") should return \"oveglay\".');", "assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'message: translate(\"algorithm\") should return \"algorithmway\".');", "assert.deepEqual(translate(\"eight\"), \"eightway\", 'message: translate(\"eight\") should return \"eightway\".');" -======= - "assert.deepEqual(translate(\"california\"), \"aliforniacay\", 'translate(\"california\") should return \"aliforniacay\"');", - "assert.deepEqual(translate(\"paragraphs\"), \"aragraphspay\", 'translate(\"paragraphs\") should return \"aragraphspay\"');", - "assert.deepEqual(translate(\"glove\"), \"oveglay\", 'translate(\"glove\") should return \"oveglay\"');", - "assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'translate(\"algorithm\") should return \"algorithmway\"');", - "assert.deepEqual(translate(\"eight\"), \"eightway\", 'translate(\"eight\") should return \"eightway\"');" ->>>>>>> staging ], "difficulty": "2.04", "description": [ @@ -359,17 +318,10 @@ "fearNotLetter(\"abce\");" ], "tests": [ -<<<<<<< HEAD "assert.deepEqual(fearNotLetter(\"abce\"), \"d\", 'message: fearNotLetter(\"abce\") should return \"d\".');", "assert.deepEqual(fearNotLetter(\"abcdefghjklmno\"), \"i\", 'message: fearNotLetter(\"abcdefghjklmno\") should return \"i\".');", "assert.isUndefined(fearNotLetter(\"bcd\"), 'message: fearNotLetter(\"bcd\") should return undefined.');", "assert.isUndefined(fearNotLetter(\"yz\"), 'message: fearNotLetter(\"yz\") should return undefined.');" -======= - "assert.deepEqual(fearNotLetter(\"abce\"), \"d\", 'fearNotLetter(\"abce\") should return d');", - "assert.deepEqual(fearNotLetter(\"abcdefghjklmno\"), \"i\", 'fearNotLetter(\"abcdefghjklmno\") should return i');", - "assert.isUndefined(fearNotLetter(\"bcd\"), 'fearNotLetter(\"bcd\") should return undefined');", - "assert.isUndefined(fearNotLetter(\"yz\"), 'fearNotLetter(\"yz\") should return undefined');" ->>>>>>> staging ], "MDNlinks": [ "String.charCodeAt()", @@ -572,21 +524,12 @@ "sumFibs(4);" ], "tests": [ -<<<<<<< HEAD "assert(typeof(sumFibs(1)) === \"number\", 'message: sumFibs() should return a number.');", "assert.deepEqual(sumFibs(1000), 1785, 'message: sumFibs(1000) should return 1785.');", "assert.deepEqual(sumFibs(4000000), 4613732, 'message: sumFibs(4000000) should return 4613732.');", "assert.deepEqual(sumFibs(4), 5, 'message: sumFibs(4) should return 5.');", "assert.deepEqual(sumFibs(75024), 60696, 'message: sumFibs(75024) should return 60696.');", "assert.deepEqual(sumFibs(75025), 135721, 'message: sumFibs(75025) should return 135721.');" -======= - "assert.deepEqual(typeof(sumFibs(1)), \"number\", \"The result should be a number\");", - "assert.deepEqual(sumFibs(1000), 1785, 'sumFibs(1000) should return 1785');", - "assert.deepEqual(sumFibs(4000000), 4613732, 'sumFibs(4000000) should return 4613732');", - "assert.deepEqual(sumFibs(4), 5, 'sumFibs(4) should return 5');", - "assert.deepEqual(sumFibs(75024), 60696, 'sumFibs(75024) should return 60696');", - "assert.deepEqual(sumFibs(75025), 135721, 'sumFibs(75025) should return 135721');" ->>>>>>> staging ], "MDNlinks": [ "Remainder" @@ -622,15 +565,9 @@ "sumPrimes(10);" ], "tests": [ -<<<<<<< HEAD "assert.deepEqual(typeof(sumPrimes(10)), \"number\", 'message: sumPrimes() should return a number.');", "assert.deepEqual(sumPrimes(10), 17, 'message: sumPrimes(10) should return 17.');", "assert.deepEqual(sumPrimes(977), 73156, 'message: sumPrimes(977) should return 73156.');" -======= - "assert.deepEqual(typeof(sumPrimes(10)), \"number\", \"The result should be a number\");", - "assert.deepEqual(sumPrimes(10), 17, 'sumPrimes(10) should return 17');", - "assert.deepEqual(sumPrimes(977), 73156, 'sumPrimes(977) should return 73156');" ->>>>>>> staging ], "MDNlinks": [ "For Loops", @@ -668,17 +605,10 @@ "smallestCommons([1,5]);" ], "tests": [ -<<<<<<< HEAD "assert.deepEqual(typeof(smallestCommons([1, 5])), \"number\", 'message: smallestCommons() should return a number.');", "assert.deepEqual(smallestCommons([1, 5]), 60, 'message: smallestCommons([1, 5]) should return 60.');", "assert.deepEqual(smallestCommons([5, 1]), 60, 'message: smallestCommons([5, 1]) should return 60.');", "assert.deepEqual(smallestCommons([1, 13]), 360360, 'message: smallestCommons([1, 13]) should return 360360.');" -======= - "assert.deepEqual(typeof(smallestCommons([1, 5])), \"number\", \"The result should be a number\");", - "assert.deepEqual(smallestCommons([1, 5]), 60, 'smallestCommons([1, 5]) should return 60');", - "assert.deepEqual(smallestCommons([5, 1]), 60, 'smallestCommons([5, 1]) should return 60');", - "assert.deepEqual(smallestCommons([1, 13]), 360360, 'smallestCommons([1, 13]) should return 360360');" ->>>>>>> staging ], "MDNlinks": [ "Smallest Common Multiple" @@ -749,17 +679,10 @@ "drop([1, 2, 3], function(n) {return n < 3; });" ], "tests": [ -<<<<<<< HEAD "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, 4], function(n) {return n>= 3;}), [3, 4], '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], '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;}), [], '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], 'drop([1, 2, 3, 7, 4], function(n) {return n>= 3}) should return [7, 4]');" ->>>>>>> staging ], "MDNlinks": [ "Arguments object", @@ -833,13 +756,8 @@ "binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\");" ], "tests": [ -<<<<<<< HEAD "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", 'message: binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\") should return \"Aren't bonfires fun!?\"');", "assert.deepEqual(binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\"), \"I love FreeCodeCamp!\", 'message: binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\" should return \"I love FreeCodeCamp!\"');" -======= - "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", \"binaryAgent() should return Aren't bonfires fun!?\");", - "assert.deepEqual(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001'), \"I love FreeCodeCamp!\", 'binaryAgent() should return \"I love FreeCodeCamp!\"');" ->>>>>>> staging ], "MDNlinks": [ "String.charCodeAt()", @@ -919,19 +837,11 @@ "add(2,3);" ], "tests": [ -<<<<<<< HEAD "assert.deepEqual(add(2, 3), 5, 'message: add(2, 3) should return 5.');", "assert.deepEqual(add(2)(3), 5, 'message: add(2)(3) should return 5.');", "assert.isUndefined(add(\"http://bit.ly/IqT6zt\"), 'message: add(\"http://bit.ly/IqT6zt\") should return undefined.');", "assert.isUndefined(add(2, \"3\"), 'message: add(2, \"3\") should return undefined.');", "assert.isUndefined(add(2)([3]), 'message: add(2)([3]) should return undefined.');" -======= - "assert.deepEqual(add(2, 3), 5, 'add(2, 3) should return 5');", - "assert.deepEqual(add(2)(3), 5, 'add(2)(3) should return 5');", - "assert.isUndefined(add(\"http://bit.ly/IqT6zt\"), 'add(\"http://bit.ly/IqT6zt\") should return undefined');", - "assert.isUndefined(add(2, \"3\"), 'add(2, \"3\") should return undefined');", - "assert.isUndefined(add(2)([3]), 'add(2)([3]) should return undefined');" ->>>>>>> staging ], "MDNlinks": [ "Global Function Object", From 72e0595ca69612f94b9ad999ab5e00d9b7b4eb73 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 30 Sep 2015 22:32:31 -0700 Subject: [PATCH 52/63] add uri code storage --- client/commonFramework.js | 126 ++++++++++++++++++++++++++++++++------ 1 file changed, 108 insertions(+), 18 deletions(-) diff --git a/client/commonFramework.js b/client/commonFramework.js index 2d07b27cfc..8abcb6a9dc 100644 --- a/client/commonFramework.js +++ b/client/commonFramework.js @@ -16,8 +16,92 @@ common.challengeType = common.challengeType || window.challengeType ? common.challengeId = common.challengeId || window.challenge_Id; +common.challengeSeed = common.challengeSeed || window.challengeSeed ? + window.challengeSeed : + []; + +common.seed = common.challengeSeed.reduce(function(seed, line) { + return seed + line + '\n'; +}, ''); + +// store code in the URL +common.codeUri = (function(common, encode, decode, location, history) { + var codeUri = { + encode: function(code) { + return encode(code); + }, + decode: function(code) { + try { + return decode(code); + } catch (ignore) { + return null; + } + }, + isInQuery: function(query) { + var decoded = codeUri.decode(query); + if (!decoded || typeof decoded.split !== 'function') { + return false; + } + return decoded + .split('?') + .splice(1) + .reduce(function(found, param) { + var key = param.split('=')[0]; + if (key === 'solution') { + return true; + } + return found; + }, false); + }, + isAlive: function() { + return codeUri.isInQuery(location.search) || + codeUri.isInQuery(location.hash); + }, + parse: function() { + var query; + if (location.search && codeUri.isInQuery(location.search)) { + query = location.search.replace(/^\?/, ''); + if (history && typeof history.replaceState === 'function') { + history.replaceState( + history.state, + null, + location.href.split('?')[0] + ); + location.hash = '#?' + query; + } + } else { + query = location.hash.replace(/^\#\?/, ''); + } + if (!query) { + return null; + } + + return query + .split('&') + .reduce(function(solution, param) { + var key = param.split('=')[0]; + var value = param.split('=')[1]; + if (key === 'solution') { + return codeUri.decode(value); + } + return solution; + }, null); + }, + querify: function(solution) { + location.hash = '?solution=' + codeUri.encode(solution); + return solution; + } + }; + + common.init.push(function() { + codeUri.parse(); + }); + + return codeUri; +}(common, encodeURIComponent, decodeURIComponent, location, history)); + // codeStorage -common.codeStorageFactory = (function($, localStorage) { +common.codeStorageFactory = (function($, localStorage, codeUri) { var CodeStorageProps = { version: 0.01, @@ -58,7 +142,10 @@ common.codeStorageFactory = (function($, localStorage) { updateStorage: function() { if (typeof localStorage !== 'undefined') { var value = this.editor.getValue(); + // store in localStorage localStorage.setItem(this.keyValue, value); + // also store code in URL + codeUri.querify(value); } else { console.log('no web storage'); } @@ -83,7 +170,7 @@ common.codeStorageFactory = (function($, localStorage) { } return codeStorageFactory; -}($, localStorage)); +}($, localStorage, common.codeUri)); common.codeOutput = (function(CodeMirror, document, challengeType) { if (!CodeMirror) { @@ -319,9 +406,15 @@ var editor = (function(CodeMirror, emmetCodeMirror, common) { ); } common.init.push(function() { - editorValue = codeStorage.isAlive() ? - codeStorage.getStoredValue() : - allSeeds; + var editorValue; + if (common.codeUri.isAlive()) { + console.log('in query'); + editorValue = common.codeUri.parse(); + } else { + editorValue = codeStorage.isAlive() ? + codeStorage.getStoredValue() : + common.seed; + } editor.setValue(replaceSafeTags(editorValue)); editor.refresh(); @@ -331,16 +424,7 @@ var editor = (function(CodeMirror, emmetCodeMirror, common) { }(window.CodeMirror, window.emmetCodeMirror, common)); -var editorValue; -var challengeSeed = challengeSeed || []; var tests = tests || []; -var allSeeds = ''; - -(function() { - challengeSeed.forEach(function(elem) { - allSeeds += elem + '\n'; - }); -})(); var libraryIncludes = "" + "" + @@ -547,7 +631,9 @@ function showCompletion() { .delay(1000) .queue(function(next) { $(this).replaceWith( - '
submitting...
' + '
' + + 'submitting...
' ); next(); }); @@ -573,7 +659,7 @@ function showCompletion() { } var resetEditor = function resetEditor() { - editor.setValue(replaceSafeTags(allSeeds)); + editor.setValue(replaceSafeTags(common.seed)); $('#testSuite').empty(); bonfireExecute(true); common.codeStorage.updateStorage(); @@ -588,7 +674,6 @@ if (attempts) { var userTests; var testSalt = Math.random(); - var scrapeTests = function(userJavaScript) { // insert tests from mongo @@ -638,7 +723,11 @@ var createTestDisplay = function() { } for (var i = 0; i < userTests.length; i++) { var didTestPass = !userTests[i].err; - var testText = userTests[i].text.split('message: ').pop().replace(/\'\);/g, ''); + var testText = userTests[i].text + .split('message: ') + .pop() + .replace(/\'\);/g, ''); + var testDoc = document.createElement('div'); var iconClass = didTestPass ? @@ -674,6 +763,7 @@ var reassembleTest = function(test, data) { }; var runTests = function(err, data) { + var editorValue = editor.getValue(); // userTests = userTests ? null : []; var allTestsPassed = true; pushed = false; From 8a1a7f238d892e9cdcfba0b17662360af6892fa1 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Thu, 1 Oct 2015 20:55:55 -0700 Subject: [PATCH 53/63] fix undefined username and remove old function fix many bugs and undefined fix linting errors --- server/boot/user.js | 119 ++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 64 deletions(-) diff --git a/server/boot/user.js b/server/boot/user.js index fe678924cf..69e1d61e81 100644 --- a/server/boot/user.js +++ b/server/boot/user.js @@ -1,12 +1,12 @@ -import _ from 'lodash'; -import async from 'async'; +import dedent from 'dedent'; import moment from 'moment'; import debugFactory from 'debug'; -import { ifNoUser401 } from '../utils/middleware'; +import { ifNoUser401, ifNoUserRedirectTo } from '../utils/middleware'; const debug = debugFactory('freecc:boot:user'); const daysBetween = 1.5; +const sendNonUserToMap = ifNoUserRedirectTo('/map'); function calcCurrentStreak(cals) { const revCals = cals.concat([Date.now()]).slice().reverse(); @@ -52,7 +52,7 @@ function dayDiff([head, tail]) { module.exports = function(app) { var router = app.loopback.Router(); var User = app.models.User; - var Story = app.models.Story; + // var Story = app.models.Story; router.get('/login', function(req, res) { res.redirect(301, '/signin'); @@ -68,14 +68,21 @@ module.exports = function(app) { router.post('/reset-password', postReset); router.get('/email-signup', getEmailSignup); router.get('/email-signin', getEmailSignin); - router.get('/toggle-lockdown-mode', toggleLockdownMode); + router.get( + '/toggle-lockdown-mode', + sendNonUserToMap, + toggleLockdownMode + ); router.post( '/account/delete', ifNoUser401, postDeleteAccount ); - router.get('/account/unlink/:provider', getOauthUnlink); - router.get('/account', getAccount); + router.get( + '/account', + sendNonUserToMap, + getAccount + ); router.get('/vote1', vote1); router.get('/vote2', vote2); // Ensure this is the last route! @@ -116,7 +123,8 @@ module.exports = function(app) { } function getAccount(req, res) { - return res.redirect('/' + user.username); + const { username } = req.user; + return res.redirect('/' + username); } function returnUser(req, res, next) { @@ -196,33 +204,35 @@ module.exports = function(app) { ); } + function toggleLockdownMode(req, res, next) { + if (req.user.lockdownMode === true) { + req.user.lockdownMode = false; + return req.user.save(function(err) { + if (err) { return next(err); } - - function toggleLockdownMode(req, res) { - if (req.user) { - if (req.user.lockdownMode === true) { - req.user.lockdownMode = false; - req.user.save(function (err) { - if (err) { - return next(err); - } - req.flash('success', {msg: 'Other people can now view all your challenge solutions. You can change this back at any time in the "Manage My Account" section at the bottom of this page.'}); - res.redirect(req.user.username); + req.flash('success', { + msg: dedent` + Other people can now view all your challenge solutions. + You can change this back at any time in the "Manage My Account" + section at the bottom of this page. + ` }); - } else { - req.user.lockdownMode = true; - req.user.save(function (err) { - if (err) { - return next(err); - } - req.flash('success', {msg: 'All your challenge solutions are now hidden from other people. You can change this back at any time in the "Manage My Account" section at the bottom of this page.'}); - res.redirect(req.user.username); - }); - } - } else { - req.flash('error', {msg: 'You must be signed in to change your account settings.'}); - res.redirect('/'); + res.redirect('/' + req.user.username); + }); } + req.user.lockdownMode = true; + return req.user.save(function(err) { + if (err) { return next(err); } + + req.flash('success', { + msg: dedent` + All your challenge solutions are now hidden from other people. + You can change this back at any time in the "Manage My Account" + section at the bottom of this page. + ` + }); + res.redirect('/' + req.user.username); + }); } function postDeleteAccount(req, res, next) { @@ -234,25 +244,6 @@ module.exports = function(app) { }); } - function getOauthUnlink(req, res, next) { - var provider = req.params.provider; - User.findById(req.user.id, function(err, user) { - if (err) { return next(err); } - - user[provider] = null; - user.tokens = - _.reject(user.tokens, function(token) { - return token.kind === provider; - }); - - user.save(function(err) { - if (err) { return next(err); } - req.flash('info', { msg: provider + ' account has been unlinked.' }); - res.redirect('/account'); - }); - }); - } - function getReset(req, res) { if (!req.accessToken) { req.flash('errors', { msg: 'access token invalid' }); @@ -325,6 +316,7 @@ module.exports = function(app) { }); } + /* function updateUserStoryPictures(userId, picture, username, cb) { Story.find({ 'author.userId': userId }, function(err, stories) { if (err) { return cb(err); } @@ -345,31 +337,30 @@ module.exports = function(app) { }); }); } + */ - function vote1(req, res) { + function vote1(req, res, next) { if (req.user) { req.user.tshirtVote = 1; - req.user.save(function (err) { - if (err) { - return next(err); - } - req.flash('success', {msg: 'Thanks for voting!'}); + req.user.save(function(err) { + if (err) { return next(err); } + + req.flash('success', { msg: 'Thanks for voting!' }); res.redirect('/map'); }); } else { - req.flash('error', {msg: 'You must be signed in to vote.'}); + req.flash('error', { msg: 'You must be signed in to vote.' }); res.redirect('/map'); } } - function vote2(req, res) { + function vote2(req, res, next) { if (req.user) { req.user.tshirtVote = 2; - req.user.save(function (err) { - if (err) { - return next(err); - } - req.flash('success', {msg: 'Thanks for voting!'}); + req.user.save(function(err) { + if (err) { return next(err); } + + req.flash('success', { msg: 'Thanks for voting!' }); res.redirect('/map'); }); } else { From d0528ec7686188c27f690982969723d4774bd77b Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Thu, 1 Oct 2015 21:11:15 -0700 Subject: [PATCH 54/63] fix re-encode uri during redirect --- server/boot/challenge.js | 7 ++++++- server/boot/user.js | 3 +-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/server/boot/challenge.js b/server/boot/challenge.js index 39cb57a33c..1102da7f62 100644 --- a/server/boot/challenge.js +++ b/server/boot/challenge.js @@ -240,7 +240,12 @@ module.exports = function(app) { } if (dasherize(challenge.name) !== origChallengeName) { - return Observable.just('/challenges/' + dasherize(challenge.name) + '?solution=' + solutionCode); + return Observable.just( + '/challenges/' + + dasherize(challenge.name) + + '?solution=' + + encodeURIComponent(solutionCode) + ); } // save user does nothing if user does not exist diff --git a/server/boot/user.js b/server/boot/user.js index 69e1d61e81..09e1034bcc 100644 --- a/server/boot/user.js +++ b/server/boot/user.js @@ -197,8 +197,7 @@ module.exports = function(app) { bonfires: bonfires, moment: moment, longestStreak: user.longestStreak, - currentStreak: user.currentStreak, - encodeURI: encodeURI + currentStreak: user.currentStreak }); } ); From 6c305dbc6763b4bda0c164e6fd2a5516ce08c366 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Thu, 1 Oct 2015 21:44:24 -0700 Subject: [PATCH 55/63] feature make completedChallenges uniq now when users complete a challenge, it will instead update the last save if it exists. --- common/models/user.json | 38 +++++--------------------------------- server/boot/challenge.js | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/common/models/user.json b/common/models/user.json index 01a3b3a6bc..bc5e579604 100644 --- a/common/models/user.json +++ b/common/models/user.json @@ -88,39 +88,6 @@ "google": { "type": "string" }, - "completedBonfires": { - "type": [ - { - "id": "string", - "name": "string", - "completedWith": "string", - "completedDate": "string", - "solution": "string" - } - ], - "default": [] - }, - "uncompletedCoursewares": { - "type": "array", - "default": [] - }, - "completedCoursewares": { - "type": [ - { - "completedDate": { - "type": "string", - "defaultFn": "now" - }, - "id": "string", - "name": "string", - "completedWith": "string", - "solution": "string", - "githubLink": "string", - "verified": "boolean" - } - ], - "default": [] - }, "currentStreak": { "type": "number", "default": 0 @@ -140,10 +107,15 @@ "currentChallenge": { "type": {} }, + "isUniqMigrated": { + "type": "boolean", + "default": false + }, "completedChallenges": { "type": [ { "completedDate": "number", + "lastUpdated": "number", "id": "string", "name": "string", "completedWith": "string", diff --git a/server/boot/challenge.js b/server/boot/challenge.js index 1102da7f62..b8b5ed60f4 100644 --- a/server/boot/challenge.js +++ b/server/boot/challenge.js @@ -34,22 +34,52 @@ const dasherize = utils.dasherize; const unDasherize = utils.unDasherize; const getMDNLinks = utils.getMDNLinks; +function makeChallengesUnique(challengeArr) { + // clone and reverse challenges + // then filter by unique id's + // then reverse again + return _.uniq(challengeArr.slice().reverse(), 'id').reverse(); +} function numberWithCommas(x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); } function updateUserProgress(user, challengeId, completedChallenge) { - const alreadyCompleted = user.completedChallenges.some(({ id }) => { - return id === challengeId; + let { completedChallenges } = user; + + // migrate user challenges object to remove + if (!user.isUniqMigrated) { + user.isUniqMigrated = true; + + completedChallenges = user.completedChallenges = + makeChallengesUnique(completedChallenges); + } + + const indexOfChallenge = _.findIndex(completedChallenges, { + id: challengeId }); + const alreadyCompleted = indexOfChallenge !== -1; + if (!alreadyCompleted) { user.progressTimestamps.push({ timestamp: Date.now(), - completedChallenge + completedChallenge: challengeId }); + user.completedChallenges.push(completedChallenge); + return user; } - user.completedChallenges.push(completedChallenge); + + const oldCompletedChallenge = completedChallenges[indexOfChallenge]; + user.completedChallenges[indexOfChallenge] = + Object.assign( + {}, + completedChallenge, + { + completedDate: oldCompletedChallenge.completedDate, + lastUpdated: completedChallenge.completedDate + } + ); return user; } From ee35fe075cb5d52dd38dc4d198b898c71e152481 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Thu, 1 Oct 2015 23:03:52 -0700 Subject: [PATCH 56/63] Feature show Waypoints on user profile page This PR also fixes some bugs in lockedDown mode --- common/models/user.json | 2 +- server/boot/user.js | 73 ++++++++++++++++++++-------------- server/views/account/show.jade | 25 ++++++++++-- 3 files changed, 65 insertions(+), 35 deletions(-) diff --git a/common/models/user.json b/common/models/user.json index bc5e579604..c46d1c2f13 100644 --- a/common/models/user.json +++ b/common/models/user.json @@ -100,7 +100,7 @@ "type": "boolean", "default": true }, - "lockdownMode": { + "isLocked": { "type": "boolean", "default": false }, diff --git a/server/boot/user.js b/server/boot/user.js index 09e1034bcc..214c0b9264 100644 --- a/server/boot/user.js +++ b/server/boot/user.js @@ -132,18 +132,18 @@ module.exports = function(app) { const { path } = req; User.findOne( { where: { username } }, - function(err, user) { + function(err, profileUser) { if (err) { return next(err); } - if (!user) { + if (!profileUser) { req.flash('errors', { msg: `404: We couldn't find path ${ path }` }); return res.redirect('/'); } - var cals = user + var cals = profileUser .progressTimestamps .map(objOrNum => { return typeof objOrNum === 'number' ? @@ -152,10 +152,10 @@ module.exports = function(app) { }) .sort(); - user.currentStreak = calcCurrentStreak(cals); - user.longestStreak = calcLongestStreak(cals); + profileUser.currentStreak = calcCurrentStreak(cals); + profileUser.longestStreak = calcLongestStreak(cals); - const data = user + const data = profileUser .progressTimestamps .map((objOrNum) => { return typeof objOrNum === 'number' ? @@ -170,42 +170,55 @@ module.exports = function(app) { return data; }, {}); - const challenges = user.completedChallenges.filter(function(obj) { + const baseAndZip = profileUser.completedChallenges.filter( + function(obj) { return obj.challengeType === 3 || obj.challengeType === 4; - }); + } + ); - const bonfires = user.completedChallenges.filter(function(obj) { + const bonfires = profileUser.completedChallenges.filter(function(obj) { return obj.challengeType === 5 && (obj.name || '').match(/Bonfire/g); }); + const waypoints = profileUser.completedChallenges.filter(function(obj) { + return (obj.name || '').match(/^Waypoint/i); + }); + res.render('account/show', { - title: 'Camper ' + user.username + '\'s portfolio', - username: user.username, - name: user.name, - isMigrationGrandfathered: user.isMigrationGrandfathered, - isGithubCool: user.isGithubCool, - location: user.location, - github: user.githubURL, - linkedin: user.linkedin, - google: user.google, - facebook: user.facebook, - twitter: user.twitter, - picture: user.picture, - progressTimestamps: user.progressTimestamps, + title: 'Camper ' + profileUser.username + '\'s portfolio', + username: profileUser.username, + name: profileUser.name, + isMigrationGrandfathered: profileUser.isMigrationGrandfathered, + isGithubCool: profileUser.isGithubCool, + isLocked: !!profileUser.isLocked, + + location: profileUser.location, calender: data, - challenges: challenges, - bonfires: bonfires, - moment: moment, - longestStreak: user.longestStreak, - currentStreak: user.currentStreak + + github: profileUser.githubURL, + linkedin: profileUser.linkedin, + google: profileUser.google, + facebook: profileUser.facebook, + twitter: profileUser.twitter, + picture: profileUser.picture, + + progressTimestamps: profileUser.progressTimestamps, + + baseAndZip, + bonfires, + waypoints, + moment, + + longestStreak: profileUser.longestStreak, + currentStreak: profileUser.currentStreak }); } ); } function toggleLockdownMode(req, res, next) { - if (req.user.lockdownMode === true) { - req.user.lockdownMode = false; + if (req.user.isLocked === true) { + req.user.isLocked = false; return req.user.save(function(err) { if (err) { return next(err); } @@ -219,7 +232,7 @@ module.exports = function(app) { res.redirect('/' + req.user.username); }); } - req.user.lockdownMode = true; + req.user.isLocked = true; return req.user.save(function(err) { if (err) { return next(err); } diff --git a/server/views/account/show.jade b/server/views/account/show.jade index d633f7f7b7..5f07918815 100644 --- a/server/views/account/show.jade +++ b/server/views/account/show.jade @@ -97,8 +97,8 @@ block content h4.col-sm-6.text-left Current Streak: #{currentStreak} #{currentStreak + currentStreak === 1 ? ' day' : ' days'} - if (user.username == username || !user.lockdownMode) - if (challenges.length > 0) + if (user && user.username == username || !isLocked) + if (baseAndZip.length > 0) .col-sm-12 table.table.table-striped thead @@ -106,7 +106,7 @@ block content th.col-xs-4 Project th.col-xs-2 Completed th.col-xs-6 Link - for challenge in challenges + for challenge in baseAndZip tr td.col-xs-4 a(href='/challenges/' + challenge.name, target='_blank')= challenge.name @@ -127,6 +127,23 @@ block content td.col-xs-2= moment(bonfire.completedDate, 'x').format("MMM DD, YYYY") td.col-xs-6 a(href='/challenges/' + bonfire.name + '?solution=' + encodeURIComponent(bonfire.solution), target='_blank') View my solution + if (waypoints.length > 0) + .col-sm-12 + table.table.table-striped + thead + tr + th.col-xs-4 Waypoints + th.col-xs-2 Completed + th.col-xs-6 Solution + for challenge in waypoints + tr + td.col-xs-4= challenge.name + td.col-xs-2= moment(challenge.completedDate, 'x').format("MMM DD, YYYY") + td.col-xs-6 + if (challenge.solution) + a(href='/challenges/' + challenge.name + '?solution=' + encodeURIComponent(challenge.solution), target='_blank') View my solution + else + a(href='/challenges/' + challenge.name) View this challenge if (user && user.username === username) .panel.panel-info @@ -136,7 +153,7 @@ block content a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='mailto:team@freecodecamp.com') span.ion-email | Email us at team@freecodecamp.com - if (!user.lockdownMode) + if (!user.isLocked) .col-xs-12 a.btn.btn-lg.btn-block.btn-info.btn-link-social(href='/toggle-lockdown-mode') span.ion-locked From 69a372902582745ba30b1e93d171c35564163c5f Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Thu, 1 Oct 2015 23:54:20 -0700 Subject: [PATCH 57/63] restructure challenges and add certificate challenge skeletons --- seed/challenges/advanced-bonfires.json | 2 +- seed/challenges/angularjs.json | 2 +- .../automated-testing-and-debugging.json | 2 +- seed/challenges/basejumps.json | 2 +- seed/challenges/basic-bonfires.json | 2 +- seed/challenges/basic-javascript.json | 2 +- seed/challenges/basic-ziplines.json | 92 ++--------- seed/challenges/bootstrap.json | 2 +- .../front-end-development-certificate.json | 33 ++++ .../full-stack-development-certificate.json | 33 ++++ seed/challenges/getting-started.json | 2 +- seed/challenges/git.json | 2 +- seed/challenges/html5-and-css.json | 2 +- seed/challenges/intermediate-bonfires.json | 2 +- seed/challenges/intermediate-ziplines.json | 143 +++++++++++++----- seed/challenges/jquery.json | 2 +- seed/challenges/json-apis-and-ajax.json | 23 +++ seed/challenges/mongodb.json | 2 +- seed/challenges/nodejs-and-expressjs.json | 2 +- ...t-oriented-and-functional-programming.json | 2 +- .../upper-intermediate-bonfires.json | 2 +- 21 files changed, 223 insertions(+), 133 deletions(-) create mode 100644 seed/challenges/front-end-development-certificate.json create mode 100644 seed/challenges/full-stack-development-certificate.json create mode 100644 seed/challenges/json-apis-and-ajax.json diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index 3ee8a9f041..beb458c837 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -1,6 +1,6 @@ { "name": "Advanced Algorithm Scripting", - "order": 0.013, + "order": 15, "challenges": [ { "id": "aff0395860f5d3034dc0bfc9", diff --git a/seed/challenges/angularjs.json b/seed/challenges/angularjs.json index 7a3155ed4f..72235565bf 100644 --- a/seed/challenges/angularjs.json +++ b/seed/challenges/angularjs.json @@ -1,6 +1,6 @@ { "name": "AngularJS", - "order": 0.014, + "order": 16, "challenges": [ { "id": "bd7154d8c441eddfaeb5bdef", diff --git a/seed/challenges/automated-testing-and-debugging.json b/seed/challenges/automated-testing-and-debugging.json index 294739a6ca..b5ab25c2f9 100644 --- a/seed/challenges/automated-testing-and-debugging.json +++ b/seed/challenges/automated-testing-and-debugging.json @@ -1,6 +1,6 @@ { "name": "Automated Testing and Debugging", - "order": 0.012, + "order": 14, "challenges": [ { "id":"cf1111c1c16feddfaeb6bdef", diff --git a/seed/challenges/basejumps.json b/seed/challenges/basejumps.json index 2235eefc58..7fe92f14bc 100644 --- a/seed/challenges/basejumps.json +++ b/seed/challenges/basejumps.json @@ -1,6 +1,6 @@ { "name": "Full Stack JavaScript Projects", - "order": 0.019, + "order": 20, "challenges": [ { "id": "bd7158d8c443eddfaeb5bcef", diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 54d3879aff..55b0284595 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -1,6 +1,6 @@ { "name": "Basic Algorithm Scripting", - "order": 0.007, + "order": 7, "challenges": [ { "id": "ad7123c8c441eddfaeb5bdef", diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index 1c7ecb2b7e..1047c6845d 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -1,6 +1,6 @@ { "name": "Basic JavaScript", - "order": 0.005, + "order": 5, "challenges": [ { "id":"bd7123c9c441eddfaeb4bdef", diff --git a/seed/challenges/basic-ziplines.json b/seed/challenges/basic-ziplines.json index 113d9e7de5..e26eb9faca 100644 --- a/seed/challenges/basic-ziplines.json +++ b/seed/challenges/basic-ziplines.json @@ -1,6 +1,6 @@ { "name": "Basic Front End Development Projects", - "order": 0.008, + "order": 8, "challenges": [ { "id": "bd7158d8c442eddfbeb5bd1f", @@ -148,56 +148,10 @@ "namePt": "", "descriptionPt": [] }, - { - "id": "bd7158d8c442eddfaeb5bd10", - "title": "Show the Local Weather", - "difficulty": 1.03, - "challengeSeed": ["126415127"], - "description": [ - "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/AdventureBear/full/yNBJRj.", - "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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can see the weather in my current location.", - "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.", - "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.

Click here then add your link to your tweet's text" - ], - "type": "zipline", - "challengeType": 3, - "tests": [], - "nameCn": "", - "descriptionCn": [], - "nameFr": "", - "descriptionFr": [], - "nameRu": "Покажите местную погоду", - "descriptionRu": [ - "Задание: Создайте CodePen.io который успешно копирует вот этот: http://codepen.io/AdventureBear/full/yNBJRj.", - "Правило #1: Не подсматривайте код приведенного на CodePen примера. Напишите его самостоятельно.", - "Правило #2: Можете использовать любые библиотеки или API, которые потребуются.", - "Правило #3: Воссоздайте функционал приведенного примера и не стесняйтесь добавить что-нибудь от себя.", - "Реализуйте следующие пользовательские истории, сделайте также бонусные по желанию:", - "Пользовательская история: В качестве пользователя, я могу узнать погоду с учетом моего текущего местоположения.", - "Бонусная пользовательская история: В качестве пользователя, я могу в зависимости от погоды видеть различные температурные значки.", - "Бонусная пользовательская история: В качестве пользователя, я могу в зависимости от погоды видеть различные фоновые изображения (снежные горы, знойная пустыня).", - "Бонусная пользовательская история: В качестве пользователя, я могу нажать на кнопку чтобы переключится между градусами по Цельсию или по Фаренгейту.", - "Если что-то не получается, воспользуйтесь Read-Search-Ask.", - "Когда выполните задание кликните кнопку \"I've completed this challenge\" и добавьте ссылку на ваш CodePen. Если вы программировали с кем-то в паре, также добавьте имя вашего напарника.", - "Если вы хотите получить немедленную оценку вашего проекта, нажмите эту кнопку и добавьте ссылку на ваш CodePen. В противном случае мы проверим его перед тем как вы приступите к проектам для некоммерческих организаций.

Click here then add your link to your tweet's text" - ], - "nameEs": "", - "descriptionEs": [], - "namePt": "", - "descriptionPt": [] - }, { "id": "bd7158d8c442eddfaeb5bd0f", "title": "Build a Pomodoro Clock", - "difficulty": 1.04, + "difficulty": 1.03, "challengeSeed": ["126411567"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/RPbGxZ/.", @@ -239,24 +193,19 @@ "descriptionPt": [] }, { - "id": "bd7158d8c442eddfaeb5bd1f", - "title": "Use the Twitch.tv JSON API", - "difficulty": 1.05, - "challengeSeed": ["126411564"], + "id": "bd7158d8c442eddfaeb5bd17", + "title": "Build a JavaScript Calculator", + "difficulty": 1.04, + "challengeSeed": ["126411565"], "description": [ - "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/GJKRxZ.", + "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/zxgaqw.", "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.", "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can see whether Free Code Camp is currently streaming on Twitch.tv.", - "User Story: As a user, I can click the status output and be sent directly to the Free Code Camp's Twitch.tv channel.", - "User Story: As a user, if Free Code Camp is streaming, I can see additional details about what they are streaming.", - "Bonus User Story: As a user, I can search through the streams listed.", - "Bonus User Story: As a user, I will see a placeholder notification if a streamer has closed their Twitch account. You can verify this works by adding brunofin and comster404 to your array of Twitch streamers.", - "Hint: Here's an example call to Twitch.tv's JSON API: https://api.twitch.tv/kraken/streams/freecodecamp.", - "Hint: The relevant documentation about this API call is here: https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel.", - "Hint: Here's an array of the Twitch.tv usernames of people who regularly stream coding: [\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]", + "User Story: As a user, I can add, subtract, multiply and divide two numbers.", + "Bonus User Story: I can clear the input field with a clear button.", + "Bonus User Story: I can keep chaining mathematical operations together until I hit the clear button, and the calculator will tell me the correct output.", "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.

Click here then add your link to your tweet's text" @@ -268,25 +217,8 @@ "descriptionCn": [], "nameFr": "", "descriptionFr": [], - "nameRu": "Используйте Twitch.tv JSON API", - "descriptionRu": [ - "Задание: Создайте CodePen.io который успешно копирует вот этот: http://codepen.io/GeoffStorbeck/full/GJKRxZ.", - "Правило #1: Не подсматривайте код приведенного на CodePen примера. Напишите его самостоятельно.", - "Правило #2: Можете использовать любые библиотеки или API, которые потребуются.", - "Правило #3: Воссоздайте функционал приведенного примера и не стесняйтесь добавить что-нибудь от себя.", - "Реализуйте следующие пользовательские истории, сделайте также бонусные по желанию:", - "Пользовательская история: В качестве пользователя, я могу увидеть идет ли в данный момент на Twitch.tv трансляция Free Code Camp.", - "Пользовательская история: В качестве пользователя, я могу, кликнув на описание трансляции, перейти на канал Free Code Camp.", - "Пользовательская история: В качестве пользователя, я могу видеть дополнительную информацию о текущей трансляции Free Code Camp.", - "Бонусная пользовательская история: В качестве пользователя, я могу произвести поиск среди перечисленных каналов.", - "Бонусная пользовательская история: В качестве пользователя, я могу видеть уведомление, если создатель канала закрыл свой аккаунт на Twitch.tv. Добавьте в массив имена пользователей brunofin и comster404, чтобы убедиться, что эта функция реализована правильно.", - "Подсказка: Пример запроса к Twitch.tv JSON API: https://api.twitch.tv/kraken/streams/freecodecamp.", - "Подсказка: Документацию об этом запросе можно найти по ссылке: https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel.", - "Подсказка: В этом массиве приведены имена пользователей, которые регулярно пишут код онлайн: [\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"comster404\",\"brunofin\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]", - "Если что-то не получается, воспользуйтесь Read-Search-Ask.", - "Когда выполните задание кликните кнопку \"I've completed this challenge\" и добавьте ссылку на ваш CodePen. Если вы программировали с кем-то в паре, также добавьте имя вашего напарника.", - "Если вы хотите получить немедленную оценку вашего проекта, нажмите эту кнопку и добавьте ссылку на ваш CodePen. В противном случае мы проверим его перед тем как вы приступите к проектам для некоммерческих организаций.

Click here then add your link to your tweet's text" - ], + "nameRu": "", + "descriptionRu": [], "nameEs": "", "descriptionEs": [], "namePt": "", diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index fb4f864474..ad61359b30 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -1,6 +1,6 @@ { "name": "Responsive Design with Bootstrap", - "order": 0.003, + "order": 3, "challenges": [ { "id": "bad87fee1348bd9acde08712", diff --git a/seed/challenges/front-end-development-certificate.json b/seed/challenges/front-end-development-certificate.json new file mode 100644 index 0000000000..fc34cac488 --- /dev/null +++ b/seed/challenges/front-end-development-certificate.json @@ -0,0 +1,33 @@ +{ + "name": "Claim Your Front End Development Certificate", + "order": 12, + "challenges": [ + { + "id": "561add10cb82ac38a17513be", + "title": "Claim Your Front End Development Certificate", + "difficulty": 0.00, + "challengeSeed": [], + "description": [ + [ + "http://i.imgur.com/RlEk2IF.jpg", + "a picture of Free Code Camp's 4 benefits: Get connected, Learn JavaScript, Build your Portfolio, Help nonprofits", + "Welcome to Free Code Camp. We're an open source community of busy people who learn to code and help nonprofits.", + "" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + } + ] +} diff --git a/seed/challenges/full-stack-development-certificate.json b/seed/challenges/full-stack-development-certificate.json new file mode 100644 index 0000000000..edd2c5e932 --- /dev/null +++ b/seed/challenges/full-stack-development-certificate.json @@ -0,0 +1,33 @@ +{ + "name": "Claim Your Full Stack Development Certificate", + "order": 21, + "challenges": [ + { + "id": "660add10cb82ac38a17513be", + "title": "Claim Your Full Stack Development Certificate", + "difficulty": 0.00, + "challengeSeed": [], + "description": [ + [ + "http://i.imgur.com/RlEk2IF.jpg", + "a picture of Free Code Camp's 4 benefits: Get connected, Learn JavaScript, Build your Portfolio, Help nonprofits", + "Welcome to Free Code Camp. We're an open source community of busy people who learn to code and help nonprofits.", + "" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + } + ] +} diff --git a/seed/challenges/getting-started.json b/seed/challenges/getting-started.json index 5ac330c4e3..71a6ee995a 100644 --- a/seed/challenges/getting-started.json +++ b/seed/challenges/getting-started.json @@ -1,6 +1,6 @@ { "name": "Get Started with Free Code Camp", - "order": 0.000, + "order": 1, "challenges": [ { "id": "560add10cb82ac38a17513be", diff --git a/seed/challenges/git.json b/seed/challenges/git.json index 4cb9c7c930..40bc382434 100644 --- a/seed/challenges/git.json +++ b/seed/challenges/git.json @@ -1,6 +1,6 @@ { "name": "Git", - "order" : 0.016, + "order" : 17, "challenges": [ { "id": "bd7353d8c341eddeaeb5bd0f", diff --git a/seed/challenges/html5-and-css.json b/seed/challenges/html5-and-css.json index d865ce2d56..105b877909 100644 --- a/seed/challenges/html5-and-css.json +++ b/seed/challenges/html5-and-css.json @@ -1,6 +1,6 @@ { "name": "HTML5 and CSS", - "order": 0.002, + "order": 2, "challenges": [ { "id": "bd7123c8c441eddfaeb5bdef", diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json index 684afd44e8..c1299dfce2 100644 --- a/seed/challenges/intermediate-bonfires.json +++ b/seed/challenges/intermediate-bonfires.json @@ -1,6 +1,6 @@ { "name": "Intermediate Algorithm Scripting", - "order": 0.009, + "order": 9, "challenges": [ { "id": "a3566b1109230028080c9345", diff --git a/seed/challenges/intermediate-ziplines.json b/seed/challenges/intermediate-ziplines.json index c119db33af..409b225be6 100644 --- a/seed/challenges/intermediate-ziplines.json +++ b/seed/challenges/intermediate-ziplines.json @@ -1,11 +1,112 @@ { "name": "Intermediate Front End Development Projects", - "order": 0.015, + "order": 11, "challenges": [ { + "id": "bd7158d8c442eddfaeb5bd10", + "title": "Show the Local Weather", + "difficulty": 1.01, + "challengeSeed": ["126415127"], + "description": [ + "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/AdventureBear/full/yNBJRj.", + "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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can see the weather in my current location.", + "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.", + "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.

Click here then add your link to your tweet's text" + ], + "type": "zipline", + "challengeType": 3, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "Покажите местную погоду", + "descriptionRu": [ + "Задание: Создайте CodePen.io который успешно копирует вот этот: http://codepen.io/AdventureBear/full/yNBJRj.", + "Правило #1: Не подсматривайте код приведенного на CodePen примера. Напишите его самостоятельно.", + "Правило #2: Можете использовать любые библиотеки или API, которые потребуются.", + "Правило #3: Воссоздайте функционал приведенного примера и не стесняйтесь добавить что-нибудь от себя.", + "Реализуйте следующие пользовательские истории, сделайте также бонусные по желанию:", + "Пользовательская история: В качестве пользователя, я могу узнать погоду с учетом моего текущего местоположения.", + "Бонусная пользовательская история: В качестве пользователя, я могу в зависимости от погоды видеть различные температурные значки.", + "Бонусная пользовательская история: В качестве пользователя, я могу в зависимости от погоды видеть различные фоновые изображения (снежные горы, знойная пустыня).", + "Бонусная пользовательская история: В качестве пользователя, я могу нажать на кнопку чтобы переключится между градусами по Цельсию или по Фаренгейту.", + "Если что-то не получается, воспользуйтесь Read-Search-Ask.", + "Когда выполните задание кликните кнопку \"I've completed this challenge\" и добавьте ссылку на ваш CodePen. Если вы программировали с кем-то в паре, также добавьте имя вашего напарника.", + "Если вы хотите получить немедленную оценку вашего проекта, нажмите эту кнопку и добавьте ссылку на ваш CodePen. В противном случае мы проверим его перед тем как вы приступите к проектам для некоммерческих организаций.

Click here then add your link to your tweet's text" + ], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "id": "bd7158d8c442eddfaeb5bd1f", + "title": "Use the Twitch.tv JSON API", + "difficulty": 1.02, + "challengeSeed": ["126411564"], + "description": [ + "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/GJKRxZ.", + "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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can see whether Free Code Camp is currently streaming on Twitch.tv.", + "User Story: As a user, I can click the status output and be sent directly to the Free Code Camp's Twitch.tv channel.", + "User Story: As a user, if Free Code Camp is streaming, I can see additional details about what they are streaming.", + "Bonus User Story: As a user, I can search through the streams listed.", + "Bonus User Story: As a user, I will see a placeholder notification if a streamer has closed their Twitch account. You can verify this works by adding brunofin and comster404 to your array of Twitch streamers.", + "Hint: Here's an example call to Twitch.tv's JSON API: https://api.twitch.tv/kraken/streams/freecodecamp.", + "Hint: The relevant documentation about this API call is here: https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel.", + "Hint: Here's an array of the Twitch.tv usernames of people who regularly stream coding: [\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]", + "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.

Click here then add your link to your tweet's text" + ], + "type": "zipline", + "challengeType": 3, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "Используйте Twitch.tv JSON API", + "descriptionRu": [ + "Задание: Создайте CodePen.io который успешно копирует вот этот: http://codepen.io/GeoffStorbeck/full/GJKRxZ.", + "Правило #1: Не подсматривайте код приведенного на CodePen примера. Напишите его самостоятельно.", + "Правило #2: Можете использовать любые библиотеки или API, которые потребуются.", + "Правило #3: Воссоздайте функционал приведенного примера и не стесняйтесь добавить что-нибудь от себя.", + "Реализуйте следующие пользовательские истории, сделайте также бонусные по желанию:", + "Пользовательская история: В качестве пользователя, я могу увидеть идет ли в данный момент на Twitch.tv трансляция Free Code Camp.", + "Пользовательская история: В качестве пользователя, я могу, кликнув на описание трансляции, перейти на канал Free Code Camp.", + "Пользовательская история: В качестве пользователя, я могу видеть дополнительную информацию о текущей трансляции Free Code Camp.", + "Бонусная пользовательская история: В качестве пользователя, я могу произвести поиск среди перечисленных каналов.", + "Бонусная пользовательская история: В качестве пользователя, я могу видеть уведомление, если создатель канала закрыл свой аккаунт на Twitch.tv. Добавьте в массив имена пользователей brunofin и comster404, чтобы убедиться, что эта функция реализована правильно.", + "Подсказка: Пример запроса к Twitch.tv JSON API: https://api.twitch.tv/kraken/streams/freecodecamp.", + "Подсказка: Документацию об этом запросе можно найти по ссылке: https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel.", + "Подсказка: В этом массиве приведены имена пользователей, которые регулярно пишут код онлайн: [\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"comster404\",\"brunofin\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]", + "Если что-то не получается, воспользуйтесь Read-Search-Ask.", + "Когда выполните задание кликните кнопку \"I've completed this challenge\" и добавьте ссылку на ваш CodePen. Если вы программировали с кем-то в паре, также добавьте имя вашего напарника.", + "Если вы хотите получить немедленную оценку вашего проекта, нажмите эту кнопку и добавьте ссылку на ваш CodePen. В противном случае мы проверим его перед тем как вы приступите к проектам для некоммерческих организаций.

Click here then add your link to your tweet's text" + ], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + { + "id": "bd7158d8c442eddfaeb5bd18", "title": "Stylize Stories on Camper News", - "difficulty": 1.02, + "difficulty": 1.03, "challengeSeed": ["126415129"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/MarufSarker/full/ZGPZLq/.", @@ -38,7 +139,7 @@ { "id": "bd7158d8c442eddfaeb5bd19", "title": "Build a Wikipedia Viewer", - "difficulty": 1.03, + "difficulty": 1.04, "challengeSeed": ["126415131"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/MwgQea.", @@ -68,42 +169,10 @@ "namePt": "", "descriptionPt": [] }, - { - "id": "bd7158d8c442eddfaeb5bd17", - "title": "Build a JavaScript Calculator", - "difficulty": 1.05, - "challengeSeed": ["126411565"], - "description": [ - "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/zxgaqw.", - "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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can add, subtract, multiply and divide two numbers.", - "Bonus User Story: I can clear the input field with a clear button.", - "Bonus User Story: I can keep chaining mathematical operations together until I hit the clear button, and the calculator will tell me the correct output.", - "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.

Click here then add your link to your tweet's text" - ], - "type": "zipline", - "challengeType": 3, - "tests": [], - "nameCn": "", - "descriptionCn": [], - "nameFr": "", - "descriptionFr": [], - "nameRu": "", - "descriptionRu": [], - "nameEs": "", - "descriptionEs": [], - "namePt": "", - "descriptionPt": [] - }, { "id": "bd7158d8c442eedfaeb5bd1c", "title": "Build a Tic Tac Toe Game", - "difficulty": 1.06, + "difficulty": 1.05, "challengeSeed": ["126415123"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/alex-dixon/full/JogOpQ/.", @@ -136,7 +205,7 @@ { "id": "bd7158d8c442eddfaeb5bd1c", "title": "Build a Simon Game", - "difficulty": 1.07, + "difficulty": 1.06, "challengeSeed": ["137213633"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/dting/full/QbRyqq/.", diff --git a/seed/challenges/jquery.json b/seed/challenges/jquery.json index 95214991e4..32a312788b 100644 --- a/seed/challenges/jquery.json +++ b/seed/challenges/jquery.json @@ -1,6 +1,6 @@ { "name": "jQuery", - "order": 0.004, + "order": 4, "challenges": [ { "id": "bad87fee1348bd9acdd08826", diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json new file mode 100644 index 0000000000..f8e11696b7 --- /dev/null +++ b/seed/challenges/json-apis-and-ajax.json @@ -0,0 +1,23 @@ +{ + "name": "JSON APIs and Ajax", + "order": 10, + "challenges": [ + { + "id": "bad88fee1348bd9ae8c08416", + "title": "Stand in challenge", + "dashedName": "waypoint-stand-in-challenge", + "difficulty": 3.24, + "description": [ + "" + ], + "tests": [ + + ], + "challengeSeed": [ + "" + ], + "challengeType": 0, + "type": "waypoint" + } + ] +} diff --git a/seed/challenges/mongodb.json b/seed/challenges/mongodb.json index ad7961c8a8..7e87d0c5fe 100644 --- a/seed/challenges/mongodb.json +++ b/seed/challenges/mongodb.json @@ -1,6 +1,6 @@ { "name": "MongoDB", - "order" : 0.018, + "order" : 19, "challenges": [ { "id": "bd7243d8c341eddeaeb5bd0f", diff --git a/seed/challenges/nodejs-and-expressjs.json b/seed/challenges/nodejs-and-expressjs.json index b2fe33e477..c38c67becc 100644 --- a/seed/challenges/nodejs-and-expressjs.json +++ b/seed/challenges/nodejs-and-expressjs.json @@ -1,6 +1,6 @@ { "name": "Node.js and Express.js", - "order" : 0.017, + "order" : 18, "challenges": [ { "id": "bd7153d8c441eddfaeb5bd0f", diff --git a/seed/challenges/object-oriented-and-functional-programming.json b/seed/challenges/object-oriented-and-functional-programming.json index ea84d904db..256a7e0c8c 100644 --- a/seed/challenges/object-oriented-and-functional-programming.json +++ b/seed/challenges/object-oriented-and-functional-programming.json @@ -1,6 +1,6 @@ { "name": "Object Oriented and Functional Programming", - "order": 0.006, + "order": 6, "note": [ "Methods", "Closures", diff --git a/seed/challenges/upper-intermediate-bonfires.json b/seed/challenges/upper-intermediate-bonfires.json index 83e3584e5b..beb0019040 100644 --- a/seed/challenges/upper-intermediate-bonfires.json +++ b/seed/challenges/upper-intermediate-bonfires.json @@ -1,6 +1,6 @@ { "name": "Upper Intermediate Algorithm Scripting", - "order": 0.011, + "order": 13, "challenges": [ { "id": "a2f1d72d9b908d0bd72bb9f6", From a90fdf1e0cf7802687487ea41c312aca0cf71f92 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Thu, 1 Oct 2015 23:58:56 -0700 Subject: [PATCH 58/63] Fix check for existence --- server/views/partials/challenge-modals.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/views/partials/challenge-modals.jade b/server/views/partials/challenge-modals.jade index 85165c357b..46f6eae7ee 100644 --- a/server/views/partials/challenge-modals.jade +++ b/server/views/partials/challenge-modals.jade @@ -35,5 +35,5 @@ a.btn.btn-lg.btn-primary.btn-block(href='#', data-dismiss='modal', aria-hidden='true') Cancel script. if (typeof localStorage !== 'undefined') { - localStorage.setItem('currentDashedName', common.dashedName || dashedName || ''); + localStorage.setItem('currentDashedName', typeof common !== 'undefined' && common.dashedName || dashedName || ''); } From ea33385fea80630878d0b51b1fe5ce1eb2b17e3a Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Fri, 2 Oct 2015 01:06:27 -0700 Subject: [PATCH 59/63] remove vestigial difficulty attribute from challenges --- seed/challenges/advanced-bonfires.json | 6 -- seed/challenges/angularjs.json | 5 -- seed/challenges/basejumps.json | 6 -- seed/challenges/basic-bonfires.json | 16 ----- seed/challenges/basic-javascript.json | 19 ----- seed/challenges/basic-ziplines.json | 6 -- seed/challenges/bootstrap.json | 31 -------- seed/challenges/getting-started.json | 7 -- seed/challenges/git.json | 1 - seed/challenges/hikes.json | 21 ------ seed/challenges/html5-and-css.json | 71 +------------------ seed/challenges/intermediate-bonfires.json | 21 ------ seed/challenges/intermediate-ziplines.json | 5 -- seed/challenges/jquery.json | 17 ----- seed/challenges/mongodb.json | 1 - seed/challenges/nodejs-and-expressjs.json | 5 -- ...t-oriented-and-functional-programming.json | 2 - .../upper-intermediate-bonfires.json | 3 - .../json-apis-and-ajax.json | 13 ---- 19 files changed, 2 insertions(+), 254 deletions(-) diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index 3ee8a9f041..fff06546dd 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -5,7 +5,6 @@ { "id": "aff0395860f5d3034dc0bfc9", "title": "Validate US Telephone Numbers", - "difficulty": "4.01", "description": [ "Return true if the passed string is a valid US phone number", "The user may fill out the form field any way they choose as long as it is a valid US number. The following are all valid formats for US numbers:", @@ -71,7 +70,6 @@ { "id": "a3f503de51cf954ede28891d", "title": "Symmetric Difference", - "difficulty": "4.02", "description": [ "Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.", "The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both.", @@ -110,7 +108,6 @@ { "id": "aa2e6f85cab2ab736c9a9b24", "title": "Exact Change", - "difficulty": "4.03", "description": [ "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", "cid is a 2d array listing available currency.", @@ -166,7 +163,6 @@ { "id": "a56138aff60341a09ed6c480", "title": "Inventory Update", - "difficulty": "4.04", "description": [ "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order.", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." @@ -221,7 +217,6 @@ { "id": "a7bf700cd123b9a54eef01d5", "title": "No repeats please", - "difficulty": "4.05", "description": [ "Return the number of total permutations of the provided string that don't have repeated consecutive letters.", "For example, 'aab' should return 2 because it has 6 total permutations, but only 2 of them don't have the same letter (in this case 'a') repeating.", @@ -264,7 +259,6 @@ "id": "a19f0fbe1872186acd434d5a", "title": "Friendly Date Ranges", "dashedName": "bonfire-friendly-date-ranges", - "difficulty": "4.06", "description": [ "Implement a way of converting two dates into a more friendly date range that could be presented to a user.", "It must not show any redundant information in the date range.", diff --git a/seed/challenges/angularjs.json b/seed/challenges/angularjs.json index 7a3155ed4f..fcdc14cf3a 100644 --- a/seed/challenges/angularjs.json +++ b/seed/challenges/angularjs.json @@ -5,7 +5,6 @@ { "id": "bd7154d8c441eddfaeb5bdef", "title": "Get Started with Angular.js", - "difficulty": 0.34, "challengeSeed": ["114684726"], "description": [ "Code School has a short, free Angular.js course. This will give us a quick tour of Angular.js's mechanics and features.", @@ -29,7 +28,6 @@ { "id": "bd7155d8c441eddfaeb5bdef", "title": "Apply Angular.js Directives", - "difficulty": 0.35, "challengeSeed": ["114684727"], "description": [ "Directives serve as markers in your HTML. When Angular.js compiles your HTML, it will alter the behavior of DOM elements based on the directives you've used.", @@ -53,7 +51,6 @@ { "id": "bd7156d8c441eddfaeb5bdef", "title": "Power Forms with Angular.js", - "difficulty": 0.36, "challengeSeed": ["114684729"], "description": [ "One area where Angular.js really shines is its powerful web forms.", @@ -77,7 +74,6 @@ { "id": "bd7157d8c441eddfaeb5bdef", "title": "Customize Angular.js Directives", - "difficulty": 0.37, "challengeSeed": ["114685062"], "description": [ "Now we'll learn how to modify existing Angular.js directives, and even build directives of your own.", @@ -100,7 +96,6 @@ { "id": "bd7158d8c441eddfaeb5bdef", "title": "Create Angular.js Services", - "difficulty": 0.38, "challengeSeed": ["114685060"], "description": [ "Services are functions that you can use and reuse throughout your Angular.js app to get things done.", diff --git a/seed/challenges/basejumps.json b/seed/challenges/basejumps.json index 2235eefc58..bfa6d56d1c 100644 --- a/seed/challenges/basejumps.json +++ b/seed/challenges/basejumps.json @@ -5,7 +5,6 @@ { "id": "bd7158d8c443eddfaeb5bcef", "title": "Get Set for Basejumps", - "difficulty": 2.00, "challengeSeed": ["128451852"], "description": [ "Objective: Get the MEAN stack running on Cloud 9, push your code to GitHub, and deploy it to Heroku.", @@ -66,7 +65,6 @@ { "id": "bd7158d8c443eddfaeb5bdef", "title": "Build a Voting App", - "difficulty": 2.01, "challengeSeed": ["133315786"], "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://votingapp.herokuapp.com/ and deploy it to Heroku.", @@ -103,7 +101,6 @@ { "id": "bd7158d8c443eddfaeb5bdff", "title": "Build a Nightlife Coordination App", - "difficulty": 2.02, "challengeSeed": ["133315781"], "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://whatsgoinontonight.herokuapp.com/ and deploy it to Heroku.", @@ -137,7 +134,6 @@ { "id": "bd7158d8c443eddfaeb5bd0e", "title": "Chart the Stock Market", - "difficulty": 2.03, "challengeSeed": ["133315787"], "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://stockstream.herokuapp.com/ and deploy it to Heroku.", @@ -170,7 +166,6 @@ { "id": "bd7158d8c443eddfaeb5bd0f", "title": "Manage a Book Trading Club", - "difficulty": 2.04, "challengeSeed": ["133316032"], "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://bookjump.herokuapp.com/ and deploy it to Heroku.", @@ -203,7 +198,6 @@ { "id": "bd7158d8c443eddfaeb5bdee", "title": "Build a Pinterest Clone", - "difficulty": 2.05, "challengeSeed": ["133315784"], "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://stark-lowlands-3680.herokuapp.com/ and deploy it to Heroku.", diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 54d3879aff..c8fbdd1920 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -5,7 +5,6 @@ { "id": "ad7123c8c441eddfaeb5bdef", "title": "Meet Bonfire", - "difficulty": "0", "description": [ "Your goal is to fix the failing test.", "First, run all the tests by clicking \"Run tests\" or by pressing Control + Enter.", @@ -44,7 +43,6 @@ { "id": "a202eed8fc186c8434cb6d61", "title": "Reverse a String", - "difficulty": "1.01", "tests": [ "assert(typeof(reverseString(\"hello\")) === \"string\", 'message: reverseString() should return a string.');", "assert(reverseString(\"hello\") === \"olleh\", 'message: reverseString(\"hello\") should become \"olleh\".');", @@ -93,7 +91,6 @@ "assert(factorialize(20) === 2432902008176640000, 'message: factorialize(20) should return 2432902008176640000.');", "assert(factorialize(0) === 1, 'message: factorialize(0) should return 1.');" ], - "difficulty": "1.02", "description": [ "Return the factorial of the provided integer.", "If the integer is represented with the letter n, a factorial is the product of all positive integers less than or equal to n.", @@ -127,7 +124,6 @@ { "id": "aaa48de84e1ecc7c742e1124", "title": "Check for Palindromes", - "difficulty": "1.03", "description": [ "Return true if the given string is a palindrome. Otherwise, return false.", "A palindrome is a word or sentence that's spelled the same way both forward and backward, ignoring punctuation, case, and spacing.", @@ -178,7 +174,6 @@ { "id": "a26cbbe9ad8655a977e1ceb5", "title": "Find the Longest Word in a String", - "difficulty": "1.04", "description": [ "Return the length of the longest word in the provided sentence.", "Your response should be a number.", @@ -219,7 +214,6 @@ { "id": "ab6137d4e35944e21037b769", "title": "Title Case a Sentence", - "difficulty": "1.05", "description": [ "Return the provided string with the first letter of each word capitalized. Make sure the rest of the word is in lower case.", "For the purpose of this exercise, you should also capitalize connecting words like \"the\" and \"of\".", @@ -257,7 +251,6 @@ { "id": "a789b3483989747d63b0e427", "title": "Return Largest Numbers in Arrays", - "difficulty": "1.06", "description": [ "Return an array consisting of the largest number from each provided sub-array. For simplicity, the provided array will contain exactly 4 sub-arrays.", "Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i] .", @@ -296,7 +289,6 @@ { "id": "acda2fb1324d9b0fa741e6b5", "title": "Confirm the Ending", - "difficulty": "1.07", "description": [ "Check if a string (first argument) ends with the given target string (second argument).", "Remember to use Read-Search-Ask if you get stuck. Write your own code." @@ -336,7 +328,6 @@ { "id": "afcc8d540bea9ea2669306b6", "title": "Repeat a string repeat a string", - "difficulty": "1.08", "description": [ "Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number.", "Remember to use Read-Search-Ask if you get stuck. Write your own code." @@ -373,7 +364,6 @@ { "id": "ac6993d51946422351508a41", "title": "Truncate a string", - "difficulty": "1.09", "description": [ "Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a \"...\" ending.", "Note that the three dots at the end add to the string length.", @@ -412,7 +402,6 @@ { "id": "a9bd25c716030ec90084d8a1", "title": "Chunky Monkey", - "difficulty": "1.10", "description": [ "Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array.", "Remember to use Read-Search-Ask if you get stuck. Write your own code." @@ -450,7 +439,6 @@ { "id": "ab31c21b530c0dafa9e241ee", "title": "Slasher Flick", - "difficulty": "1.11", "description": [ "Return the remaining elements of an array after chopping off n elements from the head.", "The head meaning the beginning of the array, or the zeroth index", @@ -489,7 +477,6 @@ { "id": "af2170cad53daa0770fabdea", "title": "Mutations", - "difficulty": "1.12", "description": [ "Return true if the string in the first element of the array contains all of the letters of the string in the second element of the array.", "For example, [\"hello\", \"Hello\"], should return true because all of the letters in the second string are present in the first, ignoring case.", @@ -533,7 +520,6 @@ { "id": "adf08ec01beb4f99fc7a68f2", "title": "Falsy Bouncer", - "difficulty": "1.50", "description": [ "Remove all falsy values from an array.", "Falsy values in javascript are false, null, 0, \"\", undefined, and NaN.", @@ -572,7 +558,6 @@ { "id": "a39963a4c10bc8b4d4f06d7e", "title": "Seek and Destroy", - "difficulty": "1.60", "description": [ "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.", "Remember to use Read-Search-Ask if you get stuck. Write your own code." @@ -612,7 +597,6 @@ { "id": "a24c1a4622e3c05097f71d67", "title": "Where do I belong", - "difficulty": "1.61", "description": [ "Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).", "For example, where([1,2,3,4], 1.5) should return 1 because it is greater than 1 (0th index), but less than 2 (1st index).", diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index 1c7ecb2b7e..424df615db 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -29,7 +29,6 @@ { "id": "bd7123c9c441eddfaeb5bdef", "title": "Understand Boolean Values", - "difficulty": "9.98001", "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.", @@ -57,7 +56,6 @@ { "id": "bd7123c9c443eddfaeb5bdef", "title": "Declare JavaScript Variables", - "difficulty": "9.9801", "description": [ "When we store data in a data structure, we call it a variable. These variables are no different from the x and y variables you use in math.", "Let's create our first variable and call it \"myName\".", @@ -84,7 +82,6 @@ { "id": "bd7123c9c444eddfaeb5bdef", "title": "Declare String Variables", - "difficulty": "9.9802", "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: myFirstNameand myLastName and assign them the values of your first and last name, respectively." @@ -110,7 +107,6 @@ { "id": "bd7123c9c448eddfaeb5bdef", "title": "Check the Length Property of a String Variable", - "difficulty": "9.9809", "description": [ "Data structures have properties. For example, strings have a property called .length that will tell you how many characters are in the string.", "For example, if we created a variable var firstName = \"Charles\", we could find out how long the string \"Charles\" is by using the firstName.length property.", @@ -146,7 +142,6 @@ { "id": "bd7123c9c549eddfaeb5bdef", "title": "Use Bracket Notation to Find the First Character in a String", - "difficulty": "9.9810", "description": [ "Bracket notation is a way to get a character at a specific index within a string.", "Computers don't start counting at 1 like humans do. They start at 0.", @@ -181,7 +176,6 @@ { "id": "bd7123c9c450eddfaeb5bdef", "title": "Use Bracket Notation to Find the Nth Character in a String", - "difficulty": "9.9811", "description": [ "You can also use bracket Notationto 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.", @@ -212,7 +206,6 @@ { "id": "bd7123c9c451eddfaeb5bdef", "title": "Use Bracket Notation to Find the Last Character in a String", - "difficulty": "9.9812", "description": [ "In order to get the last letter of a string, you can subtract one from the string's length.", "For example, if var firstName = \"Charles\", you can get the value of the last letter of the string by using firstName[firstName.length - 1].", @@ -244,7 +237,6 @@ { "id": "bd7123c9c452eddfaeb5bdef", "title": "Use Bracket Notation to Find the Nth-to-Last Character in a String", - "difficulty": "9.9813", "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].", @@ -276,7 +268,6 @@ { "id": "cf1111c1c11feddfaeb3bdef", "title": "Add Two Numbers with JavaScript", - "difficulty": "9.98141", "description": [ "Let's try to add two numbers using JavaScript.", "JavaScript uses the + symbol for addition.", @@ -299,7 +290,6 @@ { "id": "cf1111c1c11feddfaeb4bdef", "title": "Subtract One Number from Another with JavaScript", - "difficulty": "9.98142", "description": [ "We can also subtract one number from another.", "JavaScript uses the - symbol for subtraction.", @@ -322,7 +312,6 @@ { "id": "cf1231c1c11feddfaeb5bdef", "title": "Multiply Two Numbers with JavaScript", - "difficulty": "9.98143", "description": [ "We can also multiply one number by another.", "JavaScript uses the * symbol for multiplication.", @@ -345,7 +334,6 @@ { "id": "cf1111c1c11feddfaeb6bdef", "title": "Divide One Number by Another with JavaScript", - "difficulty": "9.9814", "description": [ "We can also divide one number by another.", "JavaScript uses the / symbol for division.", @@ -368,7 +356,6 @@ { "id": "cf1391c1c11feddfaeb4bdef", "title": "Create Decimal Numbers with JavaScript", - "difficulty": "9.9815", "description": [ "JavaScript number variables can also have decimals.", "Let's create a variable myDecimal and give it a decimal value." @@ -393,7 +380,6 @@ { "id": "bd7993c9c69feddfaeb7bdef", "title": "Perform Arithmetic Operations on Decimals with JavaScript", - "difficulty": "9.98151", "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." @@ -418,7 +404,6 @@ { "id": "bd7993c9c69feddfaeb8bdef", "title": "Store Multiple Values in one Variable using JavaScript Arrays", - "difficulty": "9.9816", "description": [ "With JavaScript array variables, we can store several pieces of data in one place.", "You start an array declaration with an opening square bracket, end it with a closing square bracket, and put a comma between each entry, like this: var sandwich = [\"peanut butter\", \"jelly\", \"bread\"].", @@ -536,7 +521,6 @@ { "id": "bg9994c9c69feddfaeb9bdef", "title": "Manipulate Arrays With pop()", - "difficulty": "9.9818", "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.", @@ -570,7 +554,6 @@ { "id": "bg9995c9c69feddfaeb9bdef", "title": "Manipulate Arrays With push()", - "difficulty": "9.9818", "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]." @@ -601,7 +584,6 @@ { "id": "bg9996c9c69feddfaeb9bdef", "title": "Manipulate Arrays With shift()", - "difficulty": "9.9817", "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()." @@ -632,7 +614,6 @@ { "id": "bg9997c9c69feddfaeb9bdef", "title": "Manipulate Arrays With unshift()", - "difficulty": "9.9818", "description": [ "Now that we've learned how to shiftthings from the start of the array, we need to learn how to unshiftstuff back to the start.", "Let's take the code we had last time and unshiftthis value to the start: \"Paul\"." diff --git a/seed/challenges/basic-ziplines.json b/seed/challenges/basic-ziplines.json index 113d9e7de5..0e51533b87 100644 --- a/seed/challenges/basic-ziplines.json +++ b/seed/challenges/basic-ziplines.json @@ -5,7 +5,6 @@ { "id": "bd7158d8c442eddfbeb5bd1f", "title": "Get Set for Ziplines", - "difficulty": 1.00, "challengeSeed": ["125658022"], "description": [ "Now you're ready to start our Zipline challenges. These front-end development challenges will give you many opportunities to apply the HTML, CSS, jQuery and JavaScript you've learned to build static (database-less) applications.", @@ -53,7 +52,6 @@ { "id": "bd7158d8c242eddfaeb5bd13", "title": "Build a Personal Portfolio Webpage", - "difficulty": 1.01, "challengeSeed": ["133315782"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/ThiagoFerreir4/full/eNMxEp.", @@ -107,7 +105,6 @@ { "id": "bd7158d8c442eddfaeb5bd13", "title": "Build a Random Quote Machine", - "difficulty": 1.02, "challengeSeed": ["126415122"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/AdventureBear/full/vEoVMw.", @@ -151,7 +148,6 @@ { "id": "bd7158d8c442eddfaeb5bd10", "title": "Show the Local Weather", - "difficulty": 1.03, "challengeSeed": ["126415127"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/AdventureBear/full/yNBJRj.", @@ -197,7 +193,6 @@ { "id": "bd7158d8c442eddfaeb5bd0f", "title": "Build a Pomodoro Clock", - "difficulty": 1.04, "challengeSeed": ["126411567"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/RPbGxZ/.", @@ -241,7 +236,6 @@ { "id": "bd7158d8c442eddfaeb5bd1f", "title": "Use the Twitch.tv JSON API", - "difficulty": 1.05, "challengeSeed": ["126411564"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/GJKRxZ.", diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index fb4f864474..091c94446e 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -5,7 +5,6 @@ { "id": "bad87fee1348bd9acde08712", "title": "Use Responsive Design with Bootstrap Fluid Containers", - "difficulty": 2.01, "description": [ "Now let's go back to our Cat Photo App. This time, we'll style it using the popular Bootstrap responsive CSS framework.", "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", @@ -89,7 +88,6 @@ { "id": "bad87fee1348bd9acde08812", "title": "Make Images Mobile Responsive", - "difficulty": 2.02, "description": [ "First, add a new image below the existing one. Set it's 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.", @@ -174,7 +172,6 @@ { "id": "bad87fee1348bd8acde08812", "title": "Center Text with Bootstrap", - "difficulty": 2.03, "description": [ "Now that we're using Bootstrap, we can center our heading element to make it look better. All we need to do is add the class 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>." @@ -257,7 +254,6 @@ { "id": "bad87fee1348cd8acdf08812", "title": "Create a Bootstrap Button", - "difficulty": 2.04, "description": [ "Bootstrap has its own styles for button elements, which look much better than the plain HTML ones.", "Create a new button element below your large kitten photo. Give it the class btn and the text of \"Like\"." @@ -343,7 +339,6 @@ { "id": "bad87fee1348cd8acef08812", "title": "Create a Block Element Bootstrap Button", - "difficulty": 2.05, "description": [ "Normally, your button elements are only as wide as the text that they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", "This image illustrates the difference between inline elements and block-level elements:", @@ -432,7 +427,6 @@ { "id": "bad87fee1348cd8acef08811", "title": "Taste the Bootstrap Button Color Rainbow", - "difficulty": 2.06, "description": [ "The btn-primary class is the main color you'll use in your app. It is useful for highlighting actions you want your user to take.", "Add Bootstrap's btn-primary class to your button.", @@ -519,7 +513,6 @@ { "id": "bad87fee1348cd8acef08813", "title": "Call out Optional Actions with Button Info", - "difficulty": 2.07, "description": [ "Bootstrap comes with several pre-defined colors for buttons. The btn-info class is used to call attention to optional actions that the user can take.", "Create a new block-level Bootstrap button below your \"Like\" button with the text \"Info\", and add Bootstrap's btn-info and btn-block classes to it.", @@ -607,7 +600,6 @@ { "id": "bad87fee1348ce8acef08814", "title": "Warn your Users of a Dangerous Action", - "difficulty": 2.08, "description": [ "Bootstrap comes with several pre-defined colors for buttons. The btn-danger class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.", "Create a button with the text \"Delete\" and give it the class btn-danger.", @@ -696,7 +688,6 @@ { "id": "bad88fee1348ce8acef08815", "title": "Use the Bootstrap Grid to Put Elements Side By Side", - "difficulty": 2.09, "description": [ "Bootstrap uses a responsive grid system, which makes it easy to put elements into rows and specify each element's relative width. Most of Bootstrap's classes can be applied to a div element.", "Here's a diagram of how Bootstrap's 12-column grid layout works:", @@ -790,7 +781,6 @@ { "id": "bad87fee1347bd9aedf08845", "title": "Ditch Custom CSS for Bootstrap", - "difficulty": 2.10, "description": [ "We can clean up our code and make our Cat Photo App look more conventional by using Bootstrap's built-in styles instead of the custom styles we created earlier.", "Don't worry - there will be plenty of time to customize our CSS later.", @@ -891,7 +881,6 @@ { "id": "bad87fee1348bd9aedf08845", "title": "Use Spans for Inline Elements", - "difficulty": 2.105, "description": [ "You can use spans to create inline elements. Remember when we used the btn-block class to make the button fill the entire row?", "This image illustrates the difference between inline elements and block-level elements:", @@ -979,7 +968,6 @@ { "id": "bad87fee1348bd9aede08845", "title": "Create a Custom Heading", - "difficulty": 2.11, "description": [ "We will make a simple heading for our Cat Photo App by putting them in the same row.", "Remember, Bootstrap uses a responsive grid system, which makes it easy to put elements into rows and specify each element's relative width. Most of Bootstrap's classes can be applied to a div element.", @@ -1068,7 +1056,6 @@ { "id": "bad87fee1348bd9aedd08845", "title": "Add Font Awesome Icons to our Buttons", - "difficulty": 2.12, "description": [ "Font Awesome is a convenient library of icons. These icons are vector graphics, stored in the .svg file format. These icons are treated just like fonts. You can specify their size using pixels, and they will assume the font size of their parent HTML elements.", "Use Font Awesome to add a thumbs-up icon to your like button by giving it a i element with the classes fa and fa-thumbs-up." @@ -1153,7 +1140,6 @@ { "id": "bad87fee1348bd9aedc08845", "title": "Add Font Awesome Icons to all of our Buttons", - "difficulty": 2.13, "description": [ "Font Awesome is a convenient library of icons. These icons are vector graphics, stored in the .svg file format. These icons are treated just like fonts. You can specify their size using pixels, and they will assume the font size of their parent HTML elements.", "Use Font Awesome to add a info-circle icon to your info button and a trash icon to your delete button." @@ -1238,7 +1224,6 @@ { "id": "bad87fee1348bd9aedb08845", "title": "Responsively Style Radio Buttons", - "difficulty": 2.14, "description": [ "You can use Bootstrap's col-xs-* classes on form elements, too! This way, our radio buttons will be evenly spread out across the page, regardless of how wide the screen resolution is.", "Nest all of your radio buttons within a <div class=\"row\"> element. Then nest each of them within a <div class=\"col-xs-6\"> element." @@ -1323,7 +1308,6 @@ { "id": "bad87fee1348bd9aeda08845", "title": "Responsively Style Checkboxes", - "difficulty": 2.15, "description": [ "You can use Bootstrap's col-xs-* classes on form elements, too! This way, our checkboxes will be evenly spread out across the page, regardless of how wide the screen resolution is.", "Nest all your checkboxes in a <div class=\"row\"> element. Then nest each of them in a <div class=\"col-xs-4\"> element." @@ -1415,7 +1399,6 @@ { "id": "bad87fee1348bd9aed908845", "title": "Style Text Inputs as Form Controls", - "difficulty": 2.16, "description": [ "You can add the fa-paper-plane Font Awesome icon by adding <i class=\"fa fa-paper-plane\"></i> within your submit button element.", "Give your form's text input field a class of form-control. Give your form's submit button the classes btn btn-primary. Also give this button the Font Awesome icon of fa-paper-plane." @@ -1516,7 +1499,6 @@ { "id": "bad87fee1348bd9aec908845", "title": "Line up Form Elements Responsively with Bootstrap", - "difficulty": 2.17, "description": [ "Now let's get your form input and your submission button on the same line. We'll do this the same way we have previously: by using a div element with the class row, and other div elements within it using the col-xs-* class.", "Nest both your form's text input and submit button within a div with the class row. Nest your form's text input within a div with the class of col-xs-7. Nest your form's submit button in a div with the class col-xs-5.", @@ -1618,7 +1600,6 @@ { "id": "bad87fee1348bd9aec908846", "title": "Create a Bootstrap Headline", - "difficulty": 2.18, "description": [ "Now let's build something from scratch to practice our HTML, CSS and Bootstrap skills.", "We'll build a jQuery playground, which we'll soon put to use in our jQuery challenges.", @@ -1653,7 +1634,6 @@ { "id": "bad87fee1348bd9aec908746", "title": "House our page within a Bootstrap Container Fluid Div", - "difficulty": 2.18, "description": [ "Now let's make sure all the content on your page is mobile-responsive.", "Let's nest your h3 element within a div element with the class container-fluid." @@ -1683,7 +1663,6 @@ { "id": "bad87fee1348bd9bec908846", "title": "Create a Bootstrap Row", - "difficulty": 2.19, "description": [ "Now we'll create a Bootstrap row for our inline elements.", "Create a div element with the class row." @@ -1716,7 +1695,6 @@ { "id": "bad87fee1348bd9aec908847", "title": "Split your Bootstrap Row", - "difficulty": 2.20, "description": [ "Now that we have a Bootstrap Row, let's split it into two columns to house our elements.", "Create two div elements within your row, both with the class col-xs-6." @@ -1750,7 +1728,6 @@ { "id": "bad87fee1348bd9aec908848", "title": "Create Bootstrap Wells", - "difficulty": 2.21, "description": [ "Bootstrap has a class called well that can create a visual sense of depth for your columns.", "Nest one div element with the class well within each of your col-xs-6 div elements." @@ -1789,7 +1766,6 @@ { "id": "bad87fee1348bd9aec908849", "title": "Add Elements within your Bootstrap Wells", - "difficulty": 2.22, "description": [ "Now we're several div elements deep on each column of our row. This is as deep as we'll need to go. Now we can add our button elements.", "Nest three button elements within each of your well div elements." @@ -1836,7 +1812,6 @@ { "id": "bad87fee1348bd9aec908850", "title": "Apply the Default Bootstrap Button Style", - "difficulty": 2.23, "description": [ "Bootstrap has another button class called btn-default.", "Apply both the btn and btn-default classes to each of your button elements." @@ -1882,7 +1857,6 @@ { "id": "bad87fee1348bd9aec908852", "title": "Create a Class to Target with jQuery Selectors", - "difficulty": 2.24, "description": [ "Not every class needs to have corresponding CSS. Sometimes we create classes just for the purpose of selecting these elements more easily using jQuery.", "Give each of your button elements the class target." @@ -1927,7 +1901,6 @@ { "id": "bad87fee1348bd9aec908853", "title": "Add ID Attributes to Bootstrap Elements", - "difficulty": 2.25, "description": [ "Recall that in addition to class attributes, you can give each of your elements an id attribute.", "Each id should be unique to a specific element.", @@ -1976,7 +1949,6 @@ { "id": "bad87fee1348bd9aec908854", "title": "Label Bootstrap Wells", - "difficulty": 2.26, "description": [ "For the sake of clarity, let's label both of our wells with their ids.", "Above your left-well, inside its col-xs-6 div element, add a h4 element with the text #left-well.", @@ -2027,7 +1999,6 @@ { "id": "bad87fee1348bd9aec908855", "title": "Give Each Element a Unique ID", - "difficulty": 2.27, "description": [ "We will also want to be able to use jQuery to target each button by its unique id.", "Give each of your buttons a unique id like, starting with target1 and ending with target6." @@ -2079,7 +2050,6 @@ { "id": "bad87fee1348bd9aec908856", "title": "Label Bootstrap Buttons", - "difficulty": 2.28, "description": [ "Just like we labeled our wells, we want to label our buttons.", "Give each of your button elements text that corresponds to their id." @@ -2131,7 +2101,6 @@ { "id": "bad87fee1348bd9aec908857", "title": "Use Comments to Clarify Code", - "difficulty": 2.29, "description": [ "When we start using jQuery, we will modify HTML elements without needing to actually change them in HTML.", "Let's make sure that everyone knows they shouldn't actually modify any of this code directly.", diff --git a/seed/challenges/getting-started.json b/seed/challenges/getting-started.json index 5ac330c4e3..d5f7163c68 100644 --- a/seed/challenges/getting-started.json +++ b/seed/challenges/getting-started.json @@ -5,7 +5,6 @@ { "id": "560add10cb82ac38a17513be", "title": "Learn how Free Code Camp Works", - "difficulty": 0.00, "challengeSeed": [], "description": [ [ @@ -62,7 +61,6 @@ { "id": "560add37cb82ac38a17513bf", "title": "Create a GitHub Account and Join our Chat Rooms", - "difficulty": 0.01, "challengeSeed": [], "description": [ [ @@ -137,7 +135,6 @@ { "id": "560add56cb82ac38a17513c0", "title": "Configure your Public Profile", - "difficulty": 0.02, "challengeSeed": [], "description": [ [ @@ -170,7 +167,6 @@ { "id": "560add65cb82ac38a17513c1", "title": "Try our Wiki and Camper News", - "difficulty": 0.03, "challengeSeed": [], "description": [ [ @@ -203,7 +199,6 @@ { "id": "560add71cb82ac38a17513c2", "title": "Join a Campsite in Your City", - "difficulty": 0.04, "challengeSeed": [], "description": [ [ @@ -236,7 +231,6 @@ { "id": "560add8ccb82ac38a17513c3", "title": "Join our Alumni Network and Commit to Your Goal", - "difficulty": 0.05, "challengeSeed": [], "description": [ [ @@ -269,7 +263,6 @@ { "id": "560add8ccb82ac38a17513c4", "title": "Learn What to Do If You Get Stuck", - "difficulty": 0.06, "challengeSeed": [], "description": [ [ diff --git a/seed/challenges/git.json b/seed/challenges/git.json index 4cb9c7c930..7c53503f0f 100644 --- a/seed/challenges/git.json +++ b/seed/challenges/git.json @@ -5,7 +5,6 @@ { "id": "bd7353d8c341eddeaeb5bd0f", "title": "Save your Code Revisions Forever with Git", - "difficulty": 0.01, "challengeSeed": ["133316034"], "description": [ "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", diff --git a/seed/challenges/hikes.json b/seed/challenges/hikes.json index e24da79d85..1f5d7f3113 100644 --- a/seed/challenges/hikes.json +++ b/seed/challenges/hikes.json @@ -5,7 +5,6 @@ { "id": "bd7128d8c441eddfbeb5bddf", "title": "Computer Basics 1: The 4 Basic Parts of a Computer", - "difficulty": 9.01, "challengeSeed": [ "132542064" ], @@ -45,7 +44,6 @@ { "id": "bd7127d8c441eddfbeb5bddf", "title": "Computer Basics 2: More Computer Hardware", - "difficulty": 9.02, "challengeSeed": [ "132542458" ], @@ -84,7 +82,6 @@ { "id": "bd7126d8c441eddfbeb5bddf", "title": "Computer Basics 3: Intro to Binary Code", - "difficulty": 9.03, "challengeSeed": [ "132542757" ], @@ -118,7 +115,6 @@ { "id": "bd7125d8c441eddfbeb5bddf", "title": "Computer Basics 4: Decoding a Binary Number", - "difficulty": 9.04, "challengeSeed": [ "132543332" ], @@ -154,7 +150,6 @@ { "id": "bd7124d8c441eddfbeb5bddf", "title": "Computer Basics 5: How To Measure Data Size", - "difficulty": 9.05, "challengeSeed": [ "132543959" ], @@ -193,7 +188,6 @@ { "id": "bd7123d8c441eddfbeb5bddf", "title": "Computer Basics 6: Measuring Data Speed", - "difficulty": 9.06, "challengeSeed": [ "132545171" ], @@ -230,7 +224,6 @@ { "id": "bd7122d8c441eddfbeb5bddf", "title": "Computer Basics 7: Binary Bytes", - "difficulty": 9.07, "challengeSeed": [ "132545417" ], @@ -264,7 +257,6 @@ { "id": "bd7121d8c441eddfbeb5bddf", "title": "Computer Basics 8: Types of Computers", - "difficulty": 9.08, "challengeSeed": [ "132546182" ], @@ -303,7 +295,6 @@ { "id": "bd7120d8c441eddfbeb5bddf", "title": "Computer Basics 9: More on the Motherboard", - "difficulty": 9.09, "challengeSeed": [ "132547285" ], @@ -344,7 +335,6 @@ { "id": "bd712fd8c441eddfbeb5bddf", "title": "Computer Basics 10: Data Networks", - "difficulty": 9.10, "challengeSeed": [ "132547590" ], @@ -384,7 +374,6 @@ { "id": "bd712ed8c441eddfbeb5bddf", "title": "Computer Basics 11: IP Addresses", - "difficulty": 9.11, "challengeSeed": [ "132548071" ], @@ -423,7 +412,6 @@ { "id": "bd712dd8c441eddfbeb5bddf", "title": "Computer Basics 12: How the Internet Works", - "difficulty": 9.12, "challengeSeed": [ "132548579" ], @@ -462,7 +450,6 @@ { "id": "bd712cd8c441eddfbeb5bddf", "title": "Computer Basics 13: Software", - "difficulty": 9.13, "challengeSeed": [ "132548908" ], @@ -495,7 +482,6 @@ { "id": "bd712bd8c441eddfbeb5bddf", "title": "What Do Programmers Do?", - "difficulty": 9.14, "challengeSeed": [ "133166912" ], @@ -532,7 +518,6 @@ { "id": "bd712ad8c441eddfbeb5bddf", "title": "Console and Logging", - "difficulty": 9.15, "challengeSeed": [ "133170880" ], @@ -569,7 +554,6 @@ { "id": "bd7119d8c441eddfbeb5bddf", "title": "Variables In Code", - "difficulty": 9.16, "challengeSeed": [ "133172920" ], @@ -602,7 +586,6 @@ { "id": "bd7029d8c441eddfbeb5bddf", "title": "Source Code", - "difficulty": 9.17, "challengeSeed": [ "133177129" ], @@ -647,7 +630,6 @@ { "id": "bd7129d8b441eddfbeb5bddf", "title": "Routers and Packets", - "difficulty": 9.18, "challengeSeed": [ "133181251" ], @@ -698,7 +680,6 @@ { "id": "bd7129d8a441eddfbeb5bddf", "title": "Hardware: Chips and Moore's Law", - "difficulty": 9.19, "challengeSeed": [ "133182057" ], @@ -735,7 +716,6 @@ { "id": "bd7129d80441eddfbeb5bddf", "title": "Analog vs Digital and File Compression", - "difficulty": 9.20, "challengeSeed": [ "133182587" ], @@ -774,7 +754,6 @@ { "id": "bd7129d89441eddfbeb5bddf", "title": "Computer Security", - "difficulty": 9.21, "challengeSeed": [ "133186284" ], diff --git a/seed/challenges/html5-and-css.json b/seed/challenges/html5-and-css.json index d865ce2d56..cdfbf6543c 100644 --- a/seed/challenges/html5-and-css.json +++ b/seed/challenges/html5-and-css.json @@ -5,7 +5,6 @@ { "id": "bd7123c8c441eddfaeb5bdef", "title": "Say Hello to HTML Elements", - "difficulty": 1.01, "description": [ "Welcome to Free Code Camp's first coding challenge!", "You can edit code in your text editor, which we've embedded into this web page.", @@ -54,8 +53,9 @@ { "id": "bad87fee1348bd9aedf0887a", "title": "Headline with the h2 Element", - "difficulty": 1.02, "description": [ + "Over the next few challenges, we'll build an HTML5 app that will look something like this:", + "\"A", "Add an h2 tag that says \"CatPhotoApp\" to create a second HTML element below your \"Hello World\" h1 element.", "The h2 element you enter will create an h2 element on the website.", "This element tells the browser how to render the text that it contains.", @@ -98,7 +98,6 @@ { "id": "bad87fee1348bd9aedf08801", "title": "Inform with the Paragraph Element", - "difficulty": 1.03, "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\".", @@ -139,7 +138,6 @@ { "id": "bad87fee1348bd9aedf08802", "title": "Uncomment HTML", - "difficulty": 1.04, "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.", @@ -189,7 +187,6 @@ { "id": "bad87fee1348bd9aedf08804", "title": "Comment out HTML", - "difficulty": 1.05, "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 -->.", @@ -236,7 +233,6 @@ { "id": "bad87fee1348bd9aedf08833", "title": "Fill in the Blank with Placeholder Text", - "difficulty": 1.06, "description": [ "Web developers traditionally use lorem ipsum text as placeholder text. It's called lorem ipsum text because those are the first two words of a famous passage by Cicero of Ancient Rome.", "lorem ipsum text has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web.", @@ -283,7 +279,6 @@ { "id": "bad87fed1348bd9aedf08833", "title": "Delete HTML Elements", - "difficulty": 1.07, "description": [ "Delete your h1 element so we can simplify our view.", "Our phone doesn't have much vertical space.", @@ -327,7 +322,6 @@ { "id": "bad87fee1348bd9aedf08803", "title": "Change the Color of Text", - "difficulty": 1.08, "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.", @@ -369,7 +363,6 @@ { "id": "bad87fee1348bd9aedf08805", "title": "Use CSS Selectors to Style Elements", - "difficulty": 1.09, "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.", @@ -424,7 +417,6 @@ { "id": "bad87fee1348bd9aecf08806", "title": "Use a CSS Class to Style an Element", - "difficulty": 1.11, "description": [ "Create a CSS class called red-text and apply it to your h2 element.", "Classes are reusable styles that can be added to HTML elements.", @@ -491,7 +483,6 @@ { "id": "bad87fee1348bd9aefe08806", "title": "Style Multiple Elements with a CSS Class", - "difficulty": 1.12, "description": [ "Apply the red-text class to your h2 and p elements.", "Remember that you can attach classes to HTML elements by using class=\"your-class-here\" within the relevant element's opening tag.", @@ -540,7 +531,6 @@ { "id": "bad87fee1348bd9aedf08806", "title": "Change the Font Size of an Element", - "difficulty": 1.13, "description": [ "Create a second p element with the following kitty ipsum text: Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.", "Then, inside your <style> element, set the font-size of all p elements to 16 pixels.", @@ -593,7 +583,6 @@ { "id": "bad87fee1348bd9aede08807", "title": "Set the Font Family of an Element", - "difficulty": 1.14, "description": [ "Make all of your p elements use the Monospace font.", "You can set an element's font by using the font-family property.", @@ -640,7 +629,6 @@ { "id": "bad87fee1348bd9aedf08807", "title": "Import a Google Font", - "difficulty": 1.15, "description": [ "Apply the font-family of Lobster to your h2 element.", "First, you'll need to make a call to Google to grab the Lobster font and load it into your HTML.", @@ -694,7 +682,6 @@ { "id": "bad87fee1348bd9aedf08808", "title": "Specify How Fonts Should Degrade", - "difficulty": 1.16, "description": [ "There are several default fonts that are available in all browsers. These include Monospace, Serif and Sans-Serif. Leave Lobster as the font-family for your h2 elements. Make them \"degrade\" to Monospace when Lobster isn't available.", "For example, if you wanted an element to use the Helvetica font, but also degrade to the Sans-Serif font when Helvetica wasn't available, you could use this CSS style: p { font-family: Helvetica, Sans-Serif; }.", @@ -752,7 +739,6 @@ { "id": "bad87fee1348bd9aedf08812", "title": "Add Images to your Website", - "difficulty": 1.17, "description": [ "You can add images to your website by using the img element, and point to a specific image's URL using the src attribute.", "An example of this would be <img src=\"http://www.your-image-source.com/your-image.jpg\">. Note that in most cases, img elements are self-closing.", @@ -807,7 +793,6 @@ { "id": "bad87fee1348bd9acdf08812", "title": "Size your Images", - "difficulty": 1.18, "description": [ "CSS has a property called width that controls an element's width. Just like with fonts, we'll use px (pixels) to specify the image's width.", "For example, if we wanted to create a CSS class called larger-image that gave HTML elements a width of 500 pixels, we'd use: <style> .larger-image { width: 500px; } </style>.", @@ -863,7 +848,6 @@ { "id": "bad87fee1348bd9bedf08813", "title": "Add Borders Around your Elements", - "difficulty": 1.19, "description": [ "CSS borders have properties like style, color and width.", "For example, if we wanted to create a red, 5 pixel border around an HTML element, we could use this class: <style> .thin-red-border { border-color: red; border-width: 5px; border-style: solid; } </style>.", @@ -927,7 +911,6 @@ { "id": "bad87fee1348bd9aedf08814", "title": "Add Rounded Corners with a Border Radius", - "difficulty": 1.20, "description": [ "Your cat photo currently has sharp corners. We can round out those corners with a CSS property called border-radius.", "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this property to your thick-green-border class and set it to 10px.", @@ -993,7 +976,6 @@ { "id": "bad87fee1348bd9aedf08815", "title": "Make Circular Images with a Border Radius", - "difficulty": 1.21, "description": [ "In addition to pixels, you can also specify a border-radius using a percentage.", "Give your cat photo a border-radius of 50%." @@ -1058,7 +1040,6 @@ { "id": "bad87fee1348bd9aedf08816", "title": "Link to External Pages with Anchor Elements", - "difficulty": 1.22, "description": [ "a elements, also known as anchor elements, are used to link to content outside of the current page.", "Here's a diagram of an a element. In this case, the a element is used in the middle of a paragraph element, which means the link will appear in the middle of a sentence.", @@ -1129,7 +1110,6 @@ { "id": "bad87fee1348bd9aede08817", "title": "Nest an Anchor Element within a Paragraph", - "difficulty": 1.23, "description": [ "Again, here's a diagram of an a element for your reference:", "\"a", @@ -1206,7 +1186,6 @@ { "id": "bad87fee1348bd9aedf08817", "title": "Make Dead Links using the Hash Symbol", - "difficulty": 1.24, "description": [ "Sometimes you want to add a elements to your website before you know where they will link.", "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", @@ -1275,7 +1254,6 @@ { "id": "bad87fee1348bd9aedf08820", "title": "Turn an Image into a Link", - "difficulty": 1.25, "description": [ "You can make elements into links by nesting them within an a element.", "Nest your image within an a element. Here's an example: <a href=\"#\"><img src=\"http://bit.ly/fcc-running-cats\"/></a>.", @@ -1348,7 +1326,6 @@ { "id": "bad87fee1348bd9aedf08818", "title": "Add Alt Text to an Image for Accessibility", - "difficulty": 1.26, "description": [ "alt attributes, also known as alt text, are what browsers will display if they fail to load the image. alt attributes are also important for blind or visually impaired users to understand what an image portrays. And search engines also look at alt attributes.", "In short, every image should have an alt attribute!", @@ -1419,7 +1396,6 @@ { "id": "bad87fee1348bd9aedf08827", "title": "Create a Bulleted Unordered List", - "difficulty": 1.27, "description": [ "HTML has a special element for creating unordered lists, or bullet point-style lists.", "Unordered lists start with a <ul> element. Then they contain some number of <li> elements.", @@ -1497,7 +1473,6 @@ { "id": "bad87fee1348bd9aedf08828", "title": "Create an Ordered List", - "difficulty": 1.28, "description": [ "HTML has a special element for creating ordered lists, or numbered-style lists.", "Ordered lists start with a <ol> element. Then they contain some number of <li> elements.", @@ -1583,7 +1558,6 @@ { "id": "bad87fee1348bd9aedf08829", "title": "Create a Text Field", - "difficulty": 1.29, "description": [ "Now let's create a web form.", "Text inputs are a convenient way to get input from your user.", @@ -1662,7 +1636,6 @@ { "id": "bad87fee1348bd9aedf08830", "title": "Add Placeholder Text to a Text Field", - "difficulty": 1.30, "description": [ "Your placeholder text is what appears in your text input before your user has inputed anything.", "You can create placeholder text like so: <input type=\"text\" placeholder=\"this is placeholder text\">.", @@ -1742,7 +1715,6 @@ { "id": "bad87fee1348bd9aede08830", "title": "Create a Form Element", - "difficulty": 1.31, "description": [ "You can build web forms that actually submit data to a server using nothing more than pure HTML. You can do this by specifying an action on your form element.", "For example: <form action=\"/url-where-you-want-to-submit-form-data\"></form>.", @@ -1823,7 +1795,6 @@ { "id": "bad87fee1348bd9aedd08830", "title": "Add a Submit Button to a Form", - "difficulty": 1.32, "description": [ "Let's add a submit button to your form. Clicking this button will send the data from your form to the URL you specified with your form's action attribute.", "Here's an example submit button: <button type=\"submit\">this button submits the form</button>.", @@ -1907,7 +1878,6 @@ { "id": "bad87fee1348bd9aedc08830", "title": "Use HTML5 to Require a Field", - "difficulty": 1.33, "description": [ "You can require specific form fields so that your user will not be able to submit your form until he or she has filled them out.", "For example, if you wanted to make a text input field required, you can just add the word required within your input element, you would use: <input type=\"text\" required>.", @@ -1989,7 +1959,6 @@ { "id": "bad87fee1348bd9aedf08834", "title": "Create a Set of Radio Buttons", - "difficulty": 1.34, "description": [ "You can use radio buttons for questions where you want the user to only give you one answer.", "Radio buttons are a type of input.", @@ -2082,7 +2051,6 @@ { "id": "bad87fee1348bd9aedf08835", "title": "Create a Set of Checkboxes", - "difficulty": 1.35, "description": [ "Forms commonly use checkboxes for questions that may have more than one answer.", "Checkboxes are a type of input.", @@ -2172,7 +2140,6 @@ { "id": "bad87fee1348bd9aedd08835", "title": "Check Radio Buttons and Checkboxes by Default", - "difficulty": 1.37, "description": [ "You can set a checkbox or radio button to be checked by default using the checked attribute.", "To do this, just add the word \"checked\" to the inside of an input element. For example, <input type=\"radio\" name=\"test-name\" checked>.", @@ -2260,7 +2227,6 @@ { "id": "bad87fee1348bd9aede08835", "title": "Nest Many Elements within a Single Div Element", - "difficulty": 1.38, "description": [ "The div element, also known as a division element, is a general purpose container for other elements.", "The div element is probably the most commonly used HTML element of all. It's useful for passing the CSS of its own class declarations down to all the elements that it contains.", @@ -2355,7 +2321,6 @@ { "id": "bad87fed1348bd9aede07836", "title": "Give a Background Color to a Div Element", - "difficulty": 1.39, "description": [ "You can set an element's background color with the background-color property.", "For example, if you wanted an element's background color to be green, you'd use .green-background { background-color: green; } within your style element.", @@ -2442,7 +2407,6 @@ { "id": "bad87eee1348bd9aede07836", "title": "Set the ID of an Element", - "difficulty": 1.391, "description": [ "In addition to classes, each HTML element can also have an id attribute.", "There are several benefits to using id attributes, and you'll learn more about them once you start using jQuery.", @@ -2533,7 +2497,6 @@ { "id": "bad87dee1348bd9aede07836", "title": "Use an ID Attribute to Style an Element", - "difficulty": 1.392, "description": [ "One cool thing about id attributes is that, like classes, you can style them using CSS.", "Here's an example of how you can take your element with the id attribute of cat-photo-element and give it the background color of green. In your style element: #cat-photo-element { background-color: green; }", @@ -2626,7 +2589,6 @@ { "id": "bad88fee1348bd9aedf08825", "title": "Adjusting the Padding of an Element", - "difficulty": 1.40, "description": [ "You may have already noticed this, but all HTML elements are essentially little rectangles.", "Three important properties control the space that surrounds each HTML element: padding, margin, and border.", @@ -2697,7 +2659,6 @@ { "id": "bad87fee1348bd9aedf08822", "title": "Adjust the Margin of an Element", - "difficulty": 1.41, "description": [ "An element's margin controls the amount of space between an element's border and surrounding elements.", "Here, we can see that the green box and the red box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", @@ -2768,7 +2729,6 @@ { "id": "bad87fee1348bd9aedf08823", "title": "Add a Negative Margin to an Element", - "difficulty": 1.42, "description": [ "An element's margin controls the amount of space between an element's border and surrounding elements.", "If you set an element's margin to a negative value, the element will grow larger.", @@ -2838,7 +2798,6 @@ { "id": "bad87fee1348bd9aedf08824", "title": "Add Different Padding to Each Side of an Element", - "difficulty": 1.43, "description": [ "Sometimes you will want to customize an element so that it has different padding on each of its sides.", "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left properties.", @@ -2910,7 +2869,6 @@ { "id": "bad87fee1248bd9aedf08824", "title": "Add Different Margins to Each Side of an Element", - "difficulty": 1.44, "description": [ "Give the green box a margin of 40px on its top and left side, but only 20px on its bottom and right side.", "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", @@ -2981,7 +2939,6 @@ { "id": "bad87fee1348bd9aedf08826", "title": "Use Clockwise Notation to Specify the Padding of an Element", - "difficulty": 1.44, "description": [ "Instead of specifying an element's padding-top, padding-right, padding-bottom, and padding-left properties, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;.", "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", @@ -3050,7 +3007,6 @@ { "id": "bad87fee1348bd9afdf08726", "title": "Use Clockwise Notation to Specify the Margin of an Element", - "difficulty": 1.45, "description": [ "Let's try this again, but with margin this time.", "Instead of specifying an element's margin-top, margin-right, margin-bottom, and margin-left properties, you can specify them all in one line, like this: margin: 10px 20px 10px 20px;.", @@ -3120,7 +3076,6 @@ { "id": "bad87fee1348bd9aedf08736", "title": "Style the HTML Body Element", - "difficulty": 1.46, "description": [ "Now let's start fresh and talk about CSS inheritance.", "Every HTML page has a body element.", @@ -3153,7 +3108,6 @@ { "id": "bad87fee1348bd9aedf08746", "title": "Inherit Styles from the Body Element", - "difficulty": 1.47, "description": [ "Now we've proven that every HTML page has a body element, and that its body element can also be styled with CSS.", "Remember, you can style your body element just like any other HTML element, and all your other elements will inherit your body element's styles.", @@ -3196,7 +3150,6 @@ { "id": "bad87fee1348bd9aedf08756", "title": "Prioritize One Style Over Another", - "difficulty": 1.48, "description": [ "Sometimes your HTML elements will receive multiple styles that conflict with one another.", "For example, your h1 element can't be both green and pink at the same time.", @@ -3236,7 +3189,6 @@ { "id": "bad87fee1348bd9aedf04756", "title": "Override Styles in Subsequent CSS", - "difficulty": 1.49, "description": [ "Our \"pink-text\" class overrode our body element's CSS declaration!", "We just proved that our classes will override the body element's CSS. So the next logical question is, what can we do to override our pink-text class?", @@ -3280,7 +3232,6 @@ { "id": "bad87fee1348bd8aedf06756", "title": "Override Class Declarations by Styling ID Attributes", - "difficulty": 1.52, "description": [ "We just proved that browsers read CSS from top to bottom. That means that, in the event of a conflict, the browser will use whichever CSS declaration came last.", "But we're not done yet. There are other ways that you can override CSS. Do you remember id attributes?", @@ -3331,7 +3282,6 @@ { "id": "bad87fee1348bd9aedf06756", "title": "Override Class Declarations with Inline Styles", - "difficulty": 1.52, "description": [ "So we've proven that id declarations override class declarations, regardless of where they are declared in your style element CSS.", "There are other ways that you can override CSS. Do you remember inline styles?", @@ -3382,7 +3332,6 @@ { "id": "bad87fee1348bd9aedf07756", "title": "Override All Other Styles by using Important", - "difficulty": 1.53, "description": [ "Yay! We just proved that in-line styles will override all the CSS declarations in your style element.", "But wait. There's one last way to override CSS. This is the most powerful method of all. But before we do it, let's talk about why you would ever want to override CSS.", @@ -3436,7 +3385,6 @@ { "id": "bad87fee1348bd9aedf08726", "title": "Use Hex Code for Specific Colors", - "difficulty": 1.54, "description": [ "Did you know there are other ways to represent colors in CSS? One of these ways is called hexadecimal code, or hex code for short.", "Decimal means the numbers zero through nine - the numbers that people use in everyday life. Hexadecimal includes these 10 numbers, plus the letters A, B, C, D, E and F. This means that Hexidecimal has a total of 16 possible values, instead of the 10 possible values that our normal base-10 number system gives us.", @@ -3472,7 +3420,6 @@ { "id": "bad87fee1348bd9aedf08725", "title": "Use Hex Code to Color Elements White", - "difficulty": 1.55, "description": [ "0 is the lowest number in hex code, and represents a complete absence of color.", "F is the highest number in hex code, and it represents the maximum possible brightness.", @@ -3507,7 +3454,6 @@ { "id": "bad87fee1348bd9aedf08724", "title": "Use Hex Code to Color Elements Red", - "difficulty": 1.56, "description": [ "You may be wondering why we use 6 digits to represent a color instead of just one or two. The answer is that using 6 digits gives us a huge variety.", "How many colors are possible? 16 values and 6 positions means we have 16 to the 6th power, or more than 16 million possible colors.", @@ -3544,7 +3490,6 @@ { "id": "bad87fee1348bd9aedf08723", "title": "Use Hex Code to Color Elements Green", - "difficulty": 1.57, "description": [ "Remember that hex code follows the red-green-blue, or rgb format. The first two digits of hex code represent the amount of red in the color. The third and fourth digit represent the amount of green. The fifth and sixth represent the amount of blue.", "So to get the absolute brightest green, you would just use F for the third and fourth digits (the highest possible value) and 0 for all the other digits (the lowest possible value).", @@ -3579,7 +3524,6 @@ { "id": "bad87fee1348bd9aedf08722", "title": "Use Hex Code to Color Elements Blue", - "difficulty": 1.58, "description": [ "Hex code follows the red-green-blue, or rgb format. The first two digits of hex code represent the amount of red in the color. The third and fourth digit represent the amount of green. The fifth and sixth represent the amount of blue.", "So to get the absolute brightest blue, we use F for the fifth and sixth digits (the highest possible value) and 0 for all the other digits (the lowest possible value).", @@ -3614,7 +3558,6 @@ { "id": "bad87fee1348bd9aedf08721", "title": "Use Hex Code to Mix Colors", - "difficulty": 1.59, "description": [ "From these three pure colors (red, green and blue), we can create 16 million other colors.", "For example, orange is pure red, mixed with some green, and no blue.", @@ -3649,7 +3592,6 @@ { "id": "bad87fee1348bd9aede08720", "title": "Use Hex Code to Color Elements Gray", - "difficulty": 1.60, "description": [ "From these three pure colors (red, green and blue), we can create 16 million other colors.", "We can also create different shades of gray by evenly mixing all three colors.", @@ -3684,7 +3626,6 @@ { "id": "bad87fee1348bd9aedf08720", "title": "Use Hex Code for Specific Shades of Gray", - "difficulty": 1.61, "description": [ "We can also create other shades of gray by evenly mixing all three colors. We can go very close to true black.", "Make the body element's background color a dark gray by giving it the hex code value of #111111." @@ -3718,7 +3659,6 @@ { "id": "bad87fee1348bd9aedf08719", "title": "Use Abbreviated Hex Code", - "difficulty": 1.62, "description": [ "Many people feel overwhelmed by the possibilities of more than 16 million colors. And it's difficult to remember hex code. Fortunately, you can shorten it.", "For example, red, which is #FF0000 in hex code, can be shortened to #F00. That is, one digit for red, one digit for green, one digit for blue.", @@ -3754,7 +3694,6 @@ { "id": "bad87fee1348bd9aede08718", "title": "Use RGB values to Color Elements", - "difficulty": 1.63, "description": [ "Another way you can represent colors in CSS is by using rgb values.", "RGB values look like this: rgb(0, 0, 0) for black and rgb(255, 255, 255) for white.", @@ -3791,7 +3730,6 @@ { "id": "bad88fee1348bd9aedf08726", "title": "Use RGB to Color Elements White", - "difficulty": 1.64, "description": [ "RGB values look like this: rgb(0, 0, 0) for black and rgb(255, 255, 255) for white.", "Instead of using six hexadecimal digits like you do with hex code, with rgb you specify the brightness of each color with a number between 0 and 255.", @@ -3826,7 +3764,6 @@ { "id": "bad89fee1348bd9aedf08724", "title": "Use RGB to Color Elements Red", - "difficulty": 1.65, "description": [ "Just like with hex code, you can represent different colors in RGB by using combinations of different values.", "These values follow the pattern of RGB: the first number represents red, the second number represents green, and the third number represents blue.", @@ -3861,7 +3798,6 @@ { "id": "bad80fee1348bd9aedf08723", "title": "Use RGB to Color Elements Green", - "difficulty": 1.66, "description": [ "Now change the body element's background color to the rgb value green: rgb(0, 255, 0)" ], @@ -3894,7 +3830,6 @@ { "id": "bad81fee1348bd9aedf08722", "title": "Use RGB to Color Elements Blue", - "difficulty": 1.67, "description": [ "Change the body element's background color to the RGB value blue: rgb(0, 0, 255)" ], @@ -3927,7 +3862,6 @@ { "id": "bad82fee1348bd9aedf08721", "title": "Use RGB to Mix Colors", - "difficulty": 1.68, "description": [ "Just like with hex code, you can mix colors in RGB by using combinations of different values.", "Change the body element's background color to the RGB value orange: rgb(255, 165, 0)" @@ -3961,7 +3895,6 @@ { "id": "bad83fee1348bd9aede08720", "title": "Use RGB to Color Elements Gray", - "difficulty": 1.69, "description": [ "With RGB values, we can make an element gray by using combinations of the same value for all three colors.", "Change the body element's background color to the RGB value for gray: rgb(128, 128, 128)" diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json index 684afd44e8..fc2c035374 100644 --- a/seed/challenges/intermediate-bonfires.json +++ b/seed/challenges/intermediate-bonfires.json @@ -5,7 +5,6 @@ { "id": "a3566b1109230028080c9345", "title": "Sum All Numbers in a Range", - "difficulty": "2.00", "description": [ "We'll pass you an array of two numbers. Return the sum of those two numbers and all numbers between them.", "The lowest number will not always come first.", @@ -46,7 +45,6 @@ { "id": "a5de63ebea8dbee56860f4f2", "title": "Diff Two Arrays", - "difficulty": "2.01", "description": [ "Compare two arrays and return a new array with any items not found in both of the original arrays.", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." @@ -99,7 +97,6 @@ "assert.deepEqual(convert(29), \"XXIX\", 'message: convert(29) should return \"XXIX\".');", "assert.deepEqual(convert(16), \"XVI\", 'message: convert(16) should return \"XVI\".');" ], - "difficulty": "2.02", "description": [ "Convert the given number into a roman numeral.", "All roman numerals answers should be provided in upper-case.", @@ -134,7 +131,6 @@ { "id": "a8e512fbe388ac2f9198f0fa", "title": "Where art thou", - "difficulty": "2.03", "description": [ "Make a function that looks through an array of objects (first argument) and returns an array of all objects that have matching property and value pairs (second argument). Each property and value pair of the source object has to be present in the object from the collection if it is to be included in the returned array.", "For example, if the first argument is [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], and the second argument is { last: \"Capulet\" }, then you must return the third object from the array (the first argument), because it contains the property and it's value, that was passed on as the second argument.", @@ -182,7 +178,6 @@ "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\".');" ], - "difficulty": "2.035", "description": [ "Perform a search and replace on the sentence using the arguments provided and return the new sentence.", "First argument is the sentence to perform the search and replace on.", @@ -226,7 +221,6 @@ "assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'message: translate(\"algorithm\") should return \"algorithmway\".');", "assert.deepEqual(translate(\"eight\"), \"eightway\", 'message: translate(\"eight\") should return \"eightway\".');" ], - "difficulty": "2.04", "description": [ "Translate the provided string to pig latin.", "Pig Latin takes the first consonant (or consonant cluster) of an English word, moves it to the end of the word and suffixes an \"ay\".", @@ -268,7 +262,6 @@ "assert.deepEqual(pair(\"TTGAG\"),[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]], 'message: pair(\"TTGAG\") should return [[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]].');", "assert.deepEqual(pair(\"CTCTA\"),[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]], 'message: pair(\"CTCTA\") should return [[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]].');" ], - "difficulty": "2.05", "description": [ "The DNA strand is missing the pairing element. Take each character, get its pair, and return the results as a 2d array.", "Base pairs are a pair of AT and CG. Match the missing element to the provided character.", @@ -304,7 +297,6 @@ { "id": "af7588ade1100bde429baf20", "title": "Missing letters", - "difficulty": "2.05", "description": [ "Find the missing letter in the passed letter range and return it.", "If all letters are present in the range, return undefined.", @@ -343,7 +335,6 @@ { "id": "a77dbc43c33f39daa4429b4f", "title": "Boo who", - "difficulty": "2.06", "description": [ "Check if a value is classified as a boolean primitive. Return true or false.", "Boolean primitives are true and false.", @@ -386,7 +377,6 @@ { "id": "a105e963526e7de52b219be9", "title": "Sorted Union", - "difficulty": "2.07", "description": [ "Write a function that takes two or more arrays and returns a new array of unique values in the order of the original provided arrays.", "In other words, all values present from all arrays should be included in their original order, but with no duplicates in the final array.", @@ -427,7 +417,6 @@ { "id": "a6b0bb188d873cb2c8729495", "title": "Convert HTML Entities", - "difficulty": "2.07", "description": [ "Convert the characters \"&\", \"<\", \">\", '\"' (double quote), and \"'\" (apostrophe), in a string to their corresponding HTML entities.", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." @@ -469,7 +458,6 @@ { "id": "a103376db3ba46b2d50db289", "title": "Spinal Tap Case", - "difficulty": "2.08", "description": [ "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes.", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." @@ -509,7 +497,6 @@ { "id": "a5229172f011153519423690", "title": "Sum All Odd Fibonacci Numbers", - "difficulty": "2.09", "description": [ "Return the sum of all odd Fibonacci numbers up to and including the passed number if it is a Fibonacci number.", "The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8, and each subsequent number is the sum of the previous two numbers.", @@ -550,7 +537,6 @@ { "id": "a3bfc1673c0526e06d3ac698", "title": "Sum All Primes", - "difficulty": "2.10", "description": [ "Sum all the prime numbers up to and including the provided number.", "A prime number is defined as having only two divisors, 1 and itself. For example, 2 is a prime number because it's only divisible by 1 and 2. 1 isn't a prime number, because it's only divisible by itself.", @@ -589,7 +575,6 @@ { "id": "ae9defd7acaf69703ab432ea", "title": "Smallest Common Multiple", - "difficulty": "2.11", "description": [ "Find the smallest common multiple of the provided parameters that can be evenly divided by both, as well as by all sequential numbers in the range between these parameters.", "The range will be an array of two numbers that will not necessarily be in numerical order.", @@ -629,7 +614,6 @@ { "id": "a6e40f1041b06c996f7b2406", "title": "Finders Keepers", - "difficulty": "2.12", "description": [ "Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument).", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." @@ -665,7 +649,6 @@ { "id": "a5deed1811a43193f9f1c841", "title": "Drop it", - "difficulty": "2.13", "description": [ "Drop the elements of an array (first argument), starting from the front, until the predicate (second argument) returns true.", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." @@ -704,7 +687,6 @@ { "id": "ab306dbdcc907c7ddfc30830", "title": "Steamroller", - "difficulty": "2.14", "description": [ "Flatten a nested array. You must account for varying levels of nesting.", "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." @@ -742,7 +724,6 @@ { "id": "a8d97bd4c764e91f9d2bda01", "title": "Binary Agents", - "difficulty": "2.15", "description": [ "Return an English translated sentence of the passed binary string.", "The binary string will be space separated.", @@ -779,7 +760,6 @@ { "id": "a10d2431ad0c6a099a4b8b52", "title": "Everything Be True", - "difficulty": "2.21", "description": [ "Check if the predicate (second argument) returns truthy (defined) for all elements of a collection (first argument).", "For this, check to see if the property defined in the second argument is present on every element of the collection.", @@ -819,7 +799,6 @@ { "id": "a97fd23d9b809dac9921074f", "title": "Arguments Optional", - "difficulty": "2.22", "description": [ "Create a function that sums two arguments together. If only one argument is provided, then return a function that expects one argument and returns the sum.", "For example, add(2, 3) should return 5, and add(2) should return a function.", diff --git a/seed/challenges/intermediate-ziplines.json b/seed/challenges/intermediate-ziplines.json index c119db33af..c702e91356 100644 --- a/seed/challenges/intermediate-ziplines.json +++ b/seed/challenges/intermediate-ziplines.json @@ -5,7 +5,6 @@ { "id": "bd7158d8c442eddfaeb5bd18", "title": "Stylize Stories on Camper News", - "difficulty": 1.02, "challengeSeed": ["126415129"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/MarufSarker/full/ZGPZLq/.", @@ -38,7 +37,6 @@ { "id": "bd7158d8c442eddfaeb5bd19", "title": "Build a Wikipedia Viewer", - "difficulty": 1.03, "challengeSeed": ["126415131"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/MwgQea.", @@ -71,7 +69,6 @@ { "id": "bd7158d8c442eddfaeb5bd17", "title": "Build a JavaScript Calculator", - "difficulty": 1.05, "challengeSeed": ["126411565"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/zxgaqw.", @@ -103,7 +100,6 @@ { "id": "bd7158d8c442eedfaeb5bd1c", "title": "Build a Tic Tac Toe Game", - "difficulty": 1.06, "challengeSeed": ["126415123"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/alex-dixon/full/JogOpQ/.", @@ -136,7 +132,6 @@ { "id": "bd7158d8c442eddfaeb5bd1c", "title": "Build a Simon Game", - "difficulty": 1.07, "challengeSeed": ["137213633"], "description": [ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/dting/full/QbRyqq/.", diff --git a/seed/challenges/jquery.json b/seed/challenges/jquery.json index 95214991e4..8e3566bca9 100644 --- a/seed/challenges/jquery.json +++ b/seed/challenges/jquery.json @@ -5,7 +5,6 @@ { "id": "bad87fee1348bd9acdd08826", "title": "Learn how Script Tags and Document Ready Work", - "difficulty": 3.01, "description": [ "Now we're ready to learn jQuery, the most popular JavaScript tool of all time. Don't worry about JavaScript itself - we will cover it soon.", "Before we can start using jQuery, we need to add some things to our HTML.", @@ -52,7 +51,6 @@ { "id": "bad87fee1348bd9bedc08826", "title": "Target HTML Elements with Selectors Using jQuery", - "difficulty": 3.02, "description": [ "Now we have a document ready function. We'll learn more about functions later. The important thing to know is that code you put inside this function will run as soon as your browser has loaded your page.", "This is important because without your document ready function, your code may run before your HTML is rendered, which would cause bugs.", @@ -102,7 +100,6 @@ { "id": "bad87fee1348bd9aedc08826", "title": "Target Elements by Class Using jQuery", - "difficulty": 3.03, "description": [ "You see how we made all of your button elements bounce? We selected them with $(\"button\"), then we added some CSS classes to them with .addClass(\"animated bounce\");.", "You just used jQuery's .addClass() function, which allows you to add classes to elements.", @@ -152,7 +149,6 @@ { "id": "bad87fee1348bd9aeda08826", "title": "Target Elements by ID Using jQuery", - "difficulty": 3.04, "description": [ "You can also target elements by their id attributes.", "First target your button element with the id target3 by using the $(\"#target3\") selector.", @@ -204,7 +200,6 @@ { "id": "bad87fee1348bd9aeda08726", "title": "Delete your jQuery Functions", - "difficulty": 3.05, "description": [ "These animations were cool at first, but now they're getting kind of distracting.", "Delete all three of these jQuery functions from your document ready function, but leave your document ready function itself intact." @@ -256,7 +251,6 @@ { "id": "bad87fee1348bd9aed908626", "title": "Target the same element with multiple jQuery Selectors", - "difficulty": 3.06, "description": [ "Now you know three ways of targeting elements: by type: $(\"button\"), by class: $(\".btn\"), and by id $(\"#target1\").", "Use each of these jQuery selectors to target your button element with the class btn and the id target1.", @@ -307,7 +301,6 @@ { "id": "bad87fee1348bd9aed918626", "title": "Remove Classes from an element with jQuery", - "difficulty": 3.07, "description": [ "In the same way you can add classes to an element with jQuery's addClass() function, you can remove them with jQuery's removeClass() function.", "Here's how you would do this for a specific button, add $(\"#target2\").removeClass(\"btn-default\");", @@ -358,7 +351,6 @@ { "id": "bad87fee1348bd9aed908826", "title": "Change the CSS of an Element Using jQuery", - "difficulty": 3.08, "description": [ "We can also change the CSS of an HTML element directly with jQuery.", "jQuery has a function called .css() that allows you to change the CSS of an element.", @@ -412,7 +404,6 @@ { "id": "bad87fee1348bd9aed808826", "title": "Disable an Element Using jQuery", - "difficulty": 3.09, "description": [ "You can also change the non-CSS properties of HTML elements with jQuery. For example, you can disable buttons.", "When you disable a button, it will become grayed-out and can no longer be clicked.", @@ -463,7 +454,6 @@ { "id": "bad87fee1348bd9aed708826", "title": "Remove an Element Using jQuery", - "difficulty": 3.10, "description": [ "Now let's remove an HTML element from your page using jQuery.", "jQuery has a function called .remove() that will remove an HTML element entirely", @@ -512,7 +502,6 @@ { "id": "bad87fee1348bd9aed608826", "title": "Use appendTo to Move Elements with jQuery", - "difficulty": 3.11, "description": [ "Now let's try moving elements from one div to another.", "jQuery has a function called appendTo() that allows you to select HTML elements and append them to another element.", @@ -564,7 +553,6 @@ { "id": "bad87fee1348bd9aed508826", "title": "Clone an Element Using jQuery", - "difficulty": 3.12, "description": [ "In addition to moving elements, you can also copy them from one place to another.", "jQuery has a function called clone() that makes a copy of an element.", @@ -618,7 +606,6 @@ { "id": "bad87fee1348bd9aed308826", "title": "Target the Parent of an Element Using jQuery", - "difficulty": 3.13, "description": [ "Every HTML element has a parent element from which it inherits properties.", "For example, your jQuery Playground h3 element has the parent element of <div class=\"container-fluid\">, which itself has the parent body.", @@ -674,7 +661,6 @@ { "id": "bad87fee1348bd9aed208826", "title": "Target the Children of an Element Using jQuery", - "difficulty": 3.14, "description": [ "Many HTML elements have children which inherit their properties from their parent HTML elements.", "For example, every HTML element is a child of your body element, and your \"jQuery Playground\" h3 element is a child of your <div class=\"container-fluid\"> element.", @@ -730,7 +716,6 @@ { "id": "bad87fee1348bd9aed108826", "title": "Target a Specific Child of an Element Using jQuery", - "difficulty": 3.15, "description": [ "You've seen why id attributes are so convenient for targeting with jQuery selectors. But you won't always have such neat ids to work with.", "Fortunately, jQuery has some other tricks for targeting the right elements.", @@ -787,7 +772,6 @@ { "id": "bad87fee1348bd9aed008826", "title": "Target Even Numbered Elements Using jQuery", - "difficulty": 3.16, "description": [ "You can also target all the even-numbered elements.", "Here's how you would target all the odd-numbered elements with class target and give them classes: $(\".target:odd\").addClass(\"animated shake\");", @@ -845,7 +829,6 @@ { "id": "bad87fee1348bd9aecb08826", "title": "Use jQuery to Modify the Entire Page", - "difficulty": 3.20, "description": [ "We're done playing with our jQuery playground. Let's tear it down!", "jQuery can target the body element as well.", diff --git a/seed/challenges/mongodb.json b/seed/challenges/mongodb.json index ad7961c8a8..d1ed0e65ed 100644 --- a/seed/challenges/mongodb.json +++ b/seed/challenges/mongodb.json @@ -5,7 +5,6 @@ { "id": "bd7243d8c341eddeaeb5bd0f", "title": "Store Data in MongoDB", - "difficulty": 0.01, "challengeSeed": ["133316035"], "description": [ "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", diff --git a/seed/challenges/nodejs-and-expressjs.json b/seed/challenges/nodejs-and-expressjs.json index b2fe33e477..1055a59221 100644 --- a/seed/challenges/nodejs-and-expressjs.json +++ b/seed/challenges/nodejs-and-expressjs.json @@ -5,7 +5,6 @@ { "id": "bd7153d8c441eddfaeb5bd0f", "title": "Manage Packages with NPM", - "difficulty": 0.39, "challengeSeed": ["126433450"], "description": [ "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", @@ -59,7 +58,6 @@ { "id": "bd7153d8c441eddfaeb5bdff", "title": "Start a Node.js Server", - "difficulty": 0.40, "challengeSeed": ["126411561"], "description": [ "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud. We'll do the first 7 steps of Node School's LearnYouNode challenges.", @@ -101,7 +99,6 @@ { "id": "bd7153d8c441eddfaeb5bdfe", "title": "Continue working with Node.js Servers", - "difficulty": 0.41, "challengeSeed": ["128836506"], "description": [ "Let's continue the LearnYouNode Node School challenge. For this Waypoint, we'll do challenges 8 through 10.", @@ -130,7 +127,6 @@ { "id": "bd7153d8c441eddfaeb5bdfd", "title": "Finish working with Node.js Servers", - "difficulty": 0.42, "challengeSeed": ["128836507"], "description": [ "Let's continue the LearnYouNode Node School challenge. For this Waypoint, we'll do challenges 11 through 13.", @@ -159,7 +155,6 @@ { "id": "bd7153d8c441eddfaeb5bd1f", "title": "Build Web Apps with Express.js", - "difficulty": 0.43, "challengeSeed": [ "126411559" ], diff --git a/seed/challenges/object-oriented-and-functional-programming.json b/seed/challenges/object-oriented-and-functional-programming.json index ea84d904db..5670520ce7 100644 --- a/seed/challenges/object-oriented-and-functional-programming.json +++ b/seed/challenges/object-oriented-and-functional-programming.json @@ -286,7 +286,6 @@ { "id": "cf1111c1c16feddfaeb2bdef", "title": "Reverse Arrays with .reverse", - "difficulty": 0, "description": [ "You can use the .reverse() function to reverse the contents of an array." ], @@ -310,7 +309,6 @@ { "id": "cf1111c1c16feddfaeb3bdef", "title": "Concatenate Strings with .concat", - "difficulty": 0, "description": [ ".concat() can be used to merge the contents of two arrays into one.", "array = array.concat(otherArray);" diff --git a/seed/challenges/upper-intermediate-bonfires.json b/seed/challenges/upper-intermediate-bonfires.json index 83e3584e5b..b1ee890d80 100644 --- a/seed/challenges/upper-intermediate-bonfires.json +++ b/seed/challenges/upper-intermediate-bonfires.json @@ -5,7 +5,6 @@ { "id": "a2f1d72d9b908d0bd72bb9f6", "title": "Make a Person", - "difficulty": "3.01", "description": [ "Fill in the object constructor with the methods specified in the tests.", "Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).", @@ -51,7 +50,6 @@ "id": "af4afb223120f7348cdfc9fd", "title": "Map the Debris", "dashedName": "bonfire-map-the-debris", - "difficulty": "3.02", "description": [ "Return a new array that transforms the element's average altitude into their orbital periods.", "The array will contain objects in the format {name: 'name', avgAlt: avgAlt}.", @@ -92,7 +90,6 @@ { "id": "a3f503de51cfab748ff001aa", "title": "Pairwise", - "difficulty": "3.03", "description": [ "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.", "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.", diff --git a/seed/under-construction/json-apis-and-ajax.json b/seed/under-construction/json-apis-and-ajax.json index ab12090b02..f45e7178ba 100644 --- a/seed/under-construction/json-apis-and-ajax.json +++ b/seed/under-construction/json-apis-and-ajax.json @@ -5,7 +5,6 @@ { "id": "bad87fed1348bd9aeca08826", "title": "Trigger on click Events with jQuery", - "difficulty": 3.19, "description": [ "With jQuery we are able to get data from APIs via Ajax", "This data normally comes in the form of JSON", @@ -106,7 +105,6 @@ { "id": "bad87fee1348bd9aeca08826", "title": "Displaying JSON data in HTML", - "difficulty": 3.19, "description": [ "JSON stands for \"JavaScript Object Notation\". It\"s how you create objects in JavaScript.", "JSON is a series of \"key-value pairs\". Everything on the left of the colon (:) is the \"key\" you use to unlock the \"value\" on the right of the colon." @@ -153,7 +151,6 @@ "id": "bad84fee1348bd9aecc48826", "title": "Read Data from an Element Using jQuery", "dashedName": "waypoint-read-data-from-an-element-using-jquery", - "difficulty": 3.17, "description": [ "Let's make everything roll with rollOut." ], @@ -192,7 +189,6 @@ "id": "bad84fee1348bd9aecc38826", "title": "Read Data from an Element Using jQuery", "dashedName": "waypoint-read-data-from-an-element-using-jquery", - "difficulty": 3.17, "description": [ "Let's make everything roll with rollOut." ], @@ -232,7 +228,6 @@ "id": "bad84fee1348bd9aecc28826", "title": "Read Data from an Element Using jQuery", "dashedName": "waypoint-read-data-from-an-element-using-jquery", - "difficulty": 3.17, "description": [ "Let's make everything roll with rollOut." ], @@ -272,7 +267,6 @@ "id": "bad84fee1348bd9aecc18826", "title": "Read Data from an Element Using jQuery", "dashedName": "waypoint-read-data-from-an-element-using-jquery", - "difficulty": 3.17, "description": [ ], @@ -312,7 +306,6 @@ "id": "bad87fee1348bd9aecc08826", "title": "Trigger onHover Events with jQuery", "dashedName": "waypoint-trigger-onhover-events-with-jquery", - "difficulty": 3.18, "description": [ ], @@ -330,7 +323,6 @@ "id": "bad87fee1348bd9aebc08826", "title": "Get Data from an URL Using jQuery", "dashedName": "waypoint-get-data-from-a-url-using-jquery", - "difficulty": 3.21, "description": [ ], @@ -364,7 +356,6 @@ "id": "bad87fee1348bd9ae9c08826", "title": "Loop through JSON Data Using jQuery", "dashedName": "waypoint-loop-through-json-data-using-jquery", - "difficulty": 3.22, "description": [ ], @@ -398,7 +389,6 @@ "id": "bad88fee1348bd9ae8c08726", "title": "Wire AJAX Call into a jQuery Click Event", "dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event", - "difficulty": 3.24, "description": [ "" ], @@ -432,7 +422,6 @@ "id": "bad88fee1348bd9ae8c08626", "title": "Wire AJAX Call into a jQuery Click Event", "dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event", - "difficulty": 3.24, "description": [ "" ], @@ -466,7 +455,6 @@ "id": "bad88fee1348bd9ae8c08526", "title": "Wire AJAX Call into a jQuery Click Event", "dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event", - "difficulty": 3.24, "description": [ "" ], @@ -500,7 +488,6 @@ "id": "bad88fee1348bd9ae8c08426", "title": "Wire AJAX Call into a jQuery Click Event", "dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event", - "difficulty": 3.24, "description": [ "" ], From 5c3973c36513b18a553e5767dd21d2b96ea7aea1 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Fri, 2 Oct 2015 10:50:35 -0700 Subject: [PATCH 60/63] Fix last completed logic bug This PR fixes a regression introduced in an earlier patch --- server/boot/challenge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/boot/challenge.js b/server/boot/challenge.js index b8b5ed60f4..15cb507855 100644 --- a/server/boot/challenge.js +++ b/server/boot/challenge.js @@ -557,7 +557,7 @@ module.exports = function(app) { const lastCompletedBlock = _.findLast(blocks, (block) => { return block.completed === 100; }); - lastCompleted = lastCompleted && lastCompletedBlock.name || null; + lastCompleted = lastCompletedBlock && lastCompletedBlock.name || null; }); Observable.combineLatest( From 86344d5c9e75b942e59a4e3b926d6641f301fcfd Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Fri, 2 Oct 2015 11:11:28 -0700 Subject: [PATCH 61/63] fix travis yaml and test challenges --- .travis.yml | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 26804033f5..b6bd11e2c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: node_js -services: - - mongodb - node_js: - - '0.10' \ No newline at end of file + - 'node' + - '1.6.4' + +sudo: false diff --git a/package.json b/package.json index f16e4bb9db..c3f7c0bebb 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "prestart-production": "bower cache clean && bower install && gulp build", "start-production": "node pm2Start", "lint": "eslint --ext=.js,.jsx .", - "test": "mocha --compilers js:babel/register" + "test": "gulp test-challenges" }, "license": "(BSD-3-Clause AND CC-BY-SA-4.0)", "dependencies": { From c688082ee48262e3f002cb5fa13567141610aca7 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Fri, 2 Oct 2015 11:44:29 -0700 Subject: [PATCH 62/63] add appropriate challenges to certificate challenges --- .../front-end-development-certificate.json | 195 +++++++++++++- .../full-stack-development-certificate.json | 255 +++++++++++++++++- 2 files changed, 448 insertions(+), 2 deletions(-) diff --git a/seed/challenges/front-end-development-certificate.json b/seed/challenges/front-end-development-certificate.json index fc34cac488..fa0bb1ce40 100644 --- a/seed/challenges/front-end-development-certificate.json +++ b/seed/challenges/front-end-development-certificate.json @@ -17,7 +17,200 @@ ], "type": "Waypoint", "challengeType": 7, - "tests": [], + "tests": [ + { + "id": "ad7123c8c441eddfaeb5bdef", + "title": "Meet Bonfire" + }, + { + "id": "a202eed8fc186c8434cb6d61", + "title": "Reverse a String" + }, + { + "id": "a302f7aae1aa3152a5b413bc", + "title": "Factorialize a Number" + }, + { + "id": "aaa48de84e1ecc7c742e1124", + "title": "Check for Palindromes" + }, + { + "id": "a26cbbe9ad8655a977e1ceb5", + "title": "Find the Longest Word in a String" + }, + { + "id": "ab6137d4e35944e21037b769", + "title": "Title Case a Sentence" + }, + { + "id": "a789b3483989747d63b0e427", + "title": "Return Largest Numbers in Arrays" + }, + { + "id": "acda2fb1324d9b0fa741e6b5", + "title": "Confirm the Ending" + }, + { + "id": "afcc8d540bea9ea2669306b6", + "title": "Repeat a string repeat a string" + }, + { + "id": "ac6993d51946422351508a41", + "title": "Truncate a string" + }, + { + "id": "a9bd25c716030ec90084d8a1", + "title": "Chunky Monkey" + }, + { + "id": "ab31c21b530c0dafa9e241ee", + "title": "Slasher Flick" + }, + { + "id": "af2170cad53daa0770fabdea", + "title": "Mutations" + }, + { + "id": "adf08ec01beb4f99fc7a68f2", + "title": "Falsy Bouncer" + }, + { + "id": "a39963a4c10bc8b4d4f06d7e", + "title": "Seek and Destroy" + }, + { + "id": "a24c1a4622e3c05097f71d67", + "title": "Where do I belong" + }, + { + "id": "a3566b1109230028080c9345", + "title": "Sum All Numbers in a Range" + }, + { + "id": "a5de63ebea8dbee56860f4f2", + "title": "Diff Two Arrays" + }, + { + "id": "a7f4d8f2483413a6ce226cac", + "title": "Roman Numeral Converter" + }, + { + "id": "a8e512fbe388ac2f9198f0fa", + "title": "Where art thou" + }, + { + "id": "a0b5010f579e69b815e7c5d6", + "title": "Search and Replace" + }, + { + "id": "aa7697ea2477d1316795783b", + "title": "Pig Latin" + }, + { + "id": "afd15382cdfb22c9efe8b7de", + "title": "DNA Pairing" + }, + { + "id": "af7588ade1100bde429baf20", + "title": "Missing letters" + }, + { + "id": "a77dbc43c33f39daa4429b4f", + "title": "Boo who" + }, + { + "id": "a105e963526e7de52b219be9", + "title": "Sorted Union" + }, + { + "id": "a6b0bb188d873cb2c8729495", + "title": "Convert HTML Entities" + }, + { + "id": "a103376db3ba46b2d50db289", + "title": "Spinal Tap Case" + }, + { + "id": "a5229172f011153519423690", + "title": "Sum All Odd Fibonacci Numbers" + }, + { + "id": "a3bfc1673c0526e06d3ac698", + "title": "Sum All Primes" + }, + { + "id": "ae9defd7acaf69703ab432ea", + "title": "Smallest Common Multiple" + }, + { + "id": "a6e40f1041b06c996f7b2406", + "title": "Finders Keepers" + }, + { + "id": "a5deed1811a43193f9f1c841", + "title": "Drop it" + }, + { + "id": "ab306dbdcc907c7ddfc30830", + "title": "Steamroller" + }, + { + "id": "a8d97bd4c764e91f9d2bda01", + "title": "Binary Agents" + }, + { + "id": "a10d2431ad0c6a099a4b8b52", + "title": "Everything Be True" + }, + { + "id": "a97fd23d9b809dac9921074f", + "title": "Arguments Optional" + }, + { + "id": "bd7158d8c442eddfbeb5bd1f", + "title": "Get Set for Ziplines" + }, + { + "id": "bd7158d8c242eddfaeb5bd13", + "title": "Build a Personal Portfolio Webpage" + }, + { + "id": "bd7158d8c442eddfaeb5bd13", + "title": "Build a Random Quote Machine" + }, + { + "id": "bd7158d8c442eddfaeb5bd0f", + "title": "Build a Pomodoro Clock" + }, + { + "id": "bd7158d8c442eddfaeb5bd17", + "title": "Build a JavaScript Calculator" + }, + { + "id": "bd7158d8c442eddfaeb5bd10", + "title": "Show the Local Weather" + }, + { + "id": "bd7158d8c442eddfaeb5bd1f", + "title": "Use the Twitch.tv JSON API" + }, + { + "id": "bd7158d8c442eddfaeb5bd18", + "title": "Stylize Stories on Camper News" + }, + { + "id": "bd7158d8c442eddfaeb5bd19", + "title": "Build a Wikipedia Viewer" + }, + { + "id": "bd7158d8c442eedfaeb5bd1c", + "title": "Build a Tic Tac Toe Game" + }, + { + "id": "bd7158d8c442eddfaeb5bd1c", + "title": "Build a Simon Game" + } + ], "nameCn": "", "descriptionCn": [], "nameFr": "", diff --git a/seed/challenges/full-stack-development-certificate.json b/seed/challenges/full-stack-development-certificate.json index edd2c5e932..901883aebc 100644 --- a/seed/challenges/full-stack-development-certificate.json +++ b/seed/challenges/full-stack-development-certificate.json @@ -17,7 +17,260 @@ ], "type": "Waypoint", "challengeType": 7, - "tests": [], + "tests": [ + { + "id": "ad7123c8c441eddfaeb5bdef", + "title": "Meet Bonfire" + }, + { + "id": "a202eed8fc186c8434cb6d61", + "title": "Reverse a String" + }, + { + "id": "a302f7aae1aa3152a5b413bc", + "title": "Factorialize a Number" + }, + { + "id": "aaa48de84e1ecc7c742e1124", + "title": "Check for Palindromes" + }, + { + "id": "a26cbbe9ad8655a977e1ceb5", + "title": "Find the Longest Word in a String" + }, + { + "id": "ab6137d4e35944e21037b769", + "title": "Title Case a Sentence" + }, + { + "id": "a789b3483989747d63b0e427", + "title": "Return Largest Numbers in Arrays" + }, + { + "id": "acda2fb1324d9b0fa741e6b5", + "title": "Confirm the Ending" + }, + { + "id": "afcc8d540bea9ea2669306b6", + "title": "Repeat a string repeat a string" + }, + { + "id": "ac6993d51946422351508a41", + "title": "Truncate a string" + }, + { + "id": "a9bd25c716030ec90084d8a1", + "title": "Chunky Monkey" + }, + { + "id": "ab31c21b530c0dafa9e241ee", + "title": "Slasher Flick" + }, + { + "id": "af2170cad53daa0770fabdea", + "title": "Mutations" + }, + { + "id": "adf08ec01beb4f99fc7a68f2", + "title": "Falsy Bouncer" + }, + { + "id": "a39963a4c10bc8b4d4f06d7e", + "title": "Seek and Destroy" + }, + { + "id": "a24c1a4622e3c05097f71d67", + "title": "Where do I belong" + }, + { + "id": "a3566b1109230028080c9345", + "title": "Sum All Numbers in a Range" + }, + { + "id": "a5de63ebea8dbee56860f4f2", + "title": "Diff Two Arrays" + }, + { + "id": "a7f4d8f2483413a6ce226cac", + "title": "Roman Numeral Converter" + }, + { + "id": "a8e512fbe388ac2f9198f0fa", + "title": "Where art thou" + }, + { + "id": "a0b5010f579e69b815e7c5d6", + "title": "Search and Replace" + }, + { + "id": "aa7697ea2477d1316795783b", + "title": "Pig Latin" + }, + { + "id": "afd15382cdfb22c9efe8b7de", + "title": "DNA Pairing" + }, + { + "id": "af7588ade1100bde429baf20", + "title": "Missing letters" + }, + { + "id": "a77dbc43c33f39daa4429b4f", + "title": "Boo who" + }, + { + "id": "a105e963526e7de52b219be9", + "title": "Sorted Union" + }, + { + "id": "a6b0bb188d873cb2c8729495", + "title": "Convert HTML Entities" + }, + { + "id": "a103376db3ba46b2d50db289", + "title": "Spinal Tap Case" + }, + { + "id": "a5229172f011153519423690", + "title": "Sum All Odd Fibonacci Numbers" + }, + { + "id": "a3bfc1673c0526e06d3ac698", + "title": "Sum All Primes" + }, + { + "id": "ae9defd7acaf69703ab432ea", + "title": "Smallest Common Multiple" + }, + { + "id": "a6e40f1041b06c996f7b2406", + "title": "Finders Keepers" + }, + { + "id": "a5deed1811a43193f9f1c841", + "title": "Drop it" + }, + { + "id": "ab306dbdcc907c7ddfc30830", + "title": "Steamroller" + }, + { + "id": "a8d97bd4c764e91f9d2bda01", + "title": "Binary Agents" + }, + { + "id": "a10d2431ad0c6a099a4b8b52", + "title": "Everything Be True" + }, + { + "id": "a97fd23d9b809dac9921074f", + "title": "Arguments Optional" + }, + { + "id": "bd7158d8c442eddfbeb5bd1f", + "title": "Get Set for Ziplines" + }, + { + "id": "bd7158d8c242eddfaeb5bd13", + "title": "Build a Personal Portfolio Webpage" + }, + { + "id": "bd7158d8c442eddfaeb5bd13", + "title": "Build a Random Quote Machine" + }, + { + "id": "bd7158d8c442eddfaeb5bd0f", + "title": "Build a Pomodoro Clock" + }, + { + "id": "bd7158d8c442eddfaeb5bd17", + "title": "Build a JavaScript Calculator" + }, + { + "id": "bd7158d8c442eddfaeb5bd10", + "title": "Show the Local Weather" + }, + { + "id": "bd7158d8c442eddfaeb5bd1f", + "title": "Use the Twitch.tv JSON API" + }, + { + "id": "bd7158d8c442eddfaeb5bd18", + "title": "Stylize Stories on Camper News" + }, + { + "id": "bd7158d8c442eddfaeb5bd19", + "title": "Build a Wikipedia Viewer" + }, + { + "id": "bd7158d8c442eedfaeb5bd1c", + "title": "Build a Tic Tac Toe Game" + }, + { + "id": "bd7158d8c442eddfaeb5bd1c", + "title": "Build a Simon Game" + }, + { + "id": "a2f1d72d9b908d0bd72bb9f6", + "title": "Make a Person" + }, + { + "id": "af4afb223120f7348cdfc9fd", + "title": "Map the Debris" + }, + { + "id": "a3f503de51cfab748ff001aa", + "title": "Pairwise" + }, + { + "id": "aff0395860f5d3034dc0bfc9", + "title": "Validate US Telephone Numbers" + }, + { + "id": "a3f503de51cf954ede28891d", + "title": "Symmetric Difference" + }, + { + "id": "aa2e6f85cab2ab736c9a9b24", + "title": "Exact Change" + }, + { + "id": "a56138aff60341a09ed6c480", + "title": "Inventory Update" + }, + { + "id": "a7bf700cd123b9a54eef01d5", + "title": "No repeats please" + }, + { + "id": "a19f0fbe1872186acd434d5a", + "title": "Friendly Date Ranges" + }, + { + "id": "bd7158d8c443eddfaeb5bcef", + "title": "Get Set for Basejumps" + }, + { + "id": "bd7158d8c443eddfaeb5bdef", + "title": "Build a Voting App" + }, + { + "id": "bd7158d8c443eddfaeb5bdff", + "title": "Build a Nightlife Coordination App" + }, + { + "id": "bd7158d8c443eddfaeb5bd0e", + "title": "Chart the Stock Market" + }, + { + "id": "bd7158d8c443eddfaeb5bd0f", + "title": "Manage a Book Trading Club" + }, + { + "id": "bd7158d8c443eddfaeb5bdee", + "title": "Build a Pinterest Clone" + } + ], "nameCn": "", "descriptionCn": [], "nameFr": "", From dc4f5212c280d91c969495a4864f4efb67ba7932 Mon Sep 17 00:00:00 2001 From: Joseph Breihan Date: Sun, 4 Oct 2015 23:20:09 -0400 Subject: [PATCH 63/63] Fix typo described in issue #3585 --- seed/challenges/object-oriented-and-functional-programming.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/object-oriented-and-functional-programming.json b/seed/challenges/object-oriented-and-functional-programming.json index 3d32886fac..2d8c22f32d 100644 --- a/seed/challenges/object-oriented-and-functional-programming.json +++ b/seed/challenges/object-oriented-and-functional-programming.json @@ -103,7 +103,7 @@ "assert(typeof(myBike.addUnit) === 'undefined', 'message: myBike.addUnit should remain undefined.');" ], "challengeSeed":[ - "//Let's create an object with a two functions. One attached as a property and one not.", + "//Let's create an object with two functions. One attached as a property and one not.", "var Car = function() {", " this.gear = 1;", " function addStyle(styleMe){",