From 74291d2299d931cc2d32b28b9317e079f0b5c34e Mon Sep 17 00:00:00 2001 From: Nathan Leniz Date: Wed, 21 Jan 2015 23:54:59 -0500 Subject: [PATCH] More bonfire improvements. Removed redundant console statements, improved test scraping, comment scraping included, better reset behavior --- models/Bonfire.js | 7 +- models/BonfireCompletion.js | 5 +- models/User.js | 3 +- public/js/lib/bonfire/bonfireFramework.js | 193 +++++++++ .../bonfire/{bonfire.js => bonfireInit.js} | 7 +- public/js/lib/bonfire/framework.js | 378 ------------------ .../{plugin_v0.1.1.js => plugin_v0.1.2.js} | 0 seed_data/bonfires.json | 47 ++- seed_data/seed_challenges.js | 21 +- views/bonfire/bonfire.jade | 4 +- 10 files changed, 250 insertions(+), 415 deletions(-) create mode 100644 public/js/lib/bonfire/bonfireFramework.js rename public/js/lib/bonfire/{bonfire.js => bonfireInit.js} (88%) delete mode 100644 public/js/lib/bonfire/framework.js rename public/js/lib/bonfire/{plugin_v0.1.1.js => plugin_v0.1.2.js} (100%) diff --git a/models/Bonfire.js b/models/Bonfire.js index 328417da3e..f7213c5872 100644 --- a/models/Bonfire.js +++ b/models/Bonfire.js @@ -6,9 +6,9 @@ var secrets = require('../config/secrets'); * @type {exports.Schema} */ -new Schema({ _id: String }) -var ObjectId = require('mongoose').Types.ObjectId; -var myObjectId = ObjectId.fromString('myhexstring'); +//new Schema({ _id: String }) +//var ObjectId = require('mongoose').Types.ObjectId; +//var myObjectId = ObjectId.fromString('myhexstring'); var bonfireSchema = new mongoose.Schema({ name: { @@ -21,7 +21,6 @@ var bonfireSchema = new mongoose.Schema({ privateTests: Array, challengeSeed: String, bonfireNumber: Number, - number: Number }); module.exports = mongoose.model('Bonfire', bonfireSchema); diff --git a/models/BonfireCompletion.js b/models/BonfireCompletion.js index 67ff2bb0e9..671c7ff4d9 100644 --- a/models/BonfireCompletion.js +++ b/models/BonfireCompletion.js @@ -3,11 +3,10 @@ var secrets = require('../config/secrets'); var bonfireCompletionSchema = new mongoose.Schema({ dateCompleted: Number, - camper1: String, - camper2: String, + completedWith: String, bonfireNumber: { bonfireNumber: Number, - bonfireId: ObjectId + bonfireId: String }, solution: String }); diff --git a/models/User.js b/models/User.js index 3b821416fe..582bd551e5 100644 --- a/models/User.js +++ b/models/User.js @@ -352,7 +352,8 @@ var userSchema = new mongoose.Schema({ } }, resetPasswordToken: String, - resetPasswordExpires: Date + resetPasswordExpires: Date, + bonfires: Array }); /** diff --git a/public/js/lib/bonfire/bonfireFramework.js b/public/js/lib/bonfire/bonfireFramework.js new file mode 100644 index 0000000000..68ad16b0be --- /dev/null +++ b/public/js/lib/bonfire/bonfireFramework.js @@ -0,0 +1,193 @@ +var widgets = []; +var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("codeEditor"), { + lineNumbers: true, + mode: "javascript", + theme: 'monokai', + runnable: true, + lint: true, + matchBrackets: true, + autoCloseBrackets: true, + cursorHeight: 0.85, + scrollbarStyle: 'null', + lineWrapping: true, + gutters: ["CodeMirror-lint-markers"], + onKeyEvent: doLinting, + extraKeys : { + "Ctrl-Enter" : function() { + bonfireExecute(); + return false; + } + } +}); +var editor = myCodeMirror; +myCodeMirror.setValue('/*Welcome to Bonfire, Free Code Camp\'s future CoderByte replacement.\n' + +'Please feel free to use Bonfire as an in-browser playground and linting tool.\n' + +'Note that you can also write tests using Chai.js by using the keywords assert and expect */\n\n' + +'function test() {\n' + +' assert(2 !== 3, "2 is not equal to 3");\n' + +' return [1,2,3].map(function(elem) {\n' + +' return elem * elem;\n' + +' });\n' + +'}\n' + +'expect(test()).to.be.a("array");\n\n' + +'assert.deepEqual(test(), [1,4,9]);\n\n' + +'test();'); +//myCodeMirror.setSize("100%", "100%"); + +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. Console.log() -type statements\n' + + ' * will appear in your browser\'s 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 doLinting = function () { + editor.operation(function () { + for (var i = 0; i < widgets.length; ++i) + editor.removeLineWidget(widgets[i]); + widgets.length = 0; + JSHINT(editor.getValue()); + for (var i = 0; i < JSHINT.errors.length; ++i) { + var err = JSHINT.errors[i]; + if (!err) continue; + var msg = document.createElement("div"); + var icon = msg.appendChild(document.createElement("span")); + icon.innerHTML = "!!"; + icon.className = "lint-error-icon"; + msg.appendChild(document.createTextNode(err.reason)); + msg.className = "lint-error"; + widgets.push(editor.addLineWidget(err.line - 1, msg, { + coverGutter: false, + noHScroll: true + })); + } + }); +}; + +var replaceQuotesInTests = function() { + tests.forEach(function(elt, ix, arr) { + arr[ix].text = arr[ix].text.replace(/\"/g,'\''); + }); +}; + +var tests; +var testSalt = Math.random(); + +var scrapeTests = function(userJavaScript) { + var counter = 0; + var regex = new RegExp(/(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)/); + var match = regex.exec(userJavaScript); + while (match != null) { + var replacement = '//' + counter + testSalt; + userJavaScript = userJavaScript.substring(0, match.index) + + replacement + + userJavaScript.substring(match.index + match[0].length); + + if (!tests) tests = []; + tests.push({"text": match[0], "line": counter, "err": null}); + counter++; + match = regex.exec(userJavaScript); + } + if (tests) replaceQuotesInTests(); + return userJavaScript; +}; + +function removeComments(userJavaScript) { + var regex = new RegExp(/(\/\*[^(\*\/)]*\*\/)|\/\/[^\n]*/g); + return userJavaScript.replace(regex, ''); +} + +function removeLogs(userJavaScript) { + return userJavaScript.replace(/(console\.[\w]+\s*\(.*\;)/g, ''); +} + +$('#submitButton').on('click', function () { + bonfireExecute(); +}); + +function bonfireExecute() { + tests = null; + $('#codeOutput').empty(); + var userJavaScript = myCodeMirror.getValue(); + userJavaScript = removeComments(userJavaScript); + userJavaScript = scrapeTests(userJavaScript); + submit(userJavaScript, function(cls, message) { + if (cls) { + codeOutput.setValue(message.error); + runTests('Error', null); + } else { + codeOutput.setValue(message.output); + message.input = removeLogs(message.input); + runTests(null, message); + } + }); +} + +var pushed = false; +var createTestDisplay = function() { + if (pushed) { + tests.pop(); + } + for (var i = 0; i < tests.length;i++) { + var test = tests[i]; + var testDoc = document.createElement("li"); + $(testDoc) + .addClass('list-group-item') + .addClass('well img-rounded') + .addClass('well-sm') + if (test.err != null) { + $(testDoc) + .html(test.text + "\n" + test.err) + .css("background-color", 'rgba(255,0,0,.2)') + .prependTo($('#testSuite')); + } else { + $(testDoc) + .html(test.text) + .css('background-color', 'rgba(0,255,0,.2)') + .appendTo($('#testSuite')); + } + }; +}; +var assert = chai.assert; +var expect = chai.expect; +var reassembleTest = function(test, data) { + var lineNum = test.line; + var regexp = new RegExp("\/\/" + lineNum + testSalt); + return data.input.replace(regexp, test.text); +}; +var runTests = function(err, data) { + pushed = false; + $('#testSuite').children().remove(); + if (err && tests) { + tests = [{text:"Program Execution Failure", err: "No tests were run."}]; + createTestDisplay(); + } else if (tests) { + tests.push(false); + pushed = true; + tests.forEach(function(test, ix, arr){ + try { + if (test) { + var output = eval(reassembleTest(test, data)); + } + } catch(error) { + console.log(error); + arr[ix].err = error.name + ":" + error.message; + console.log(arr); + } finally { + if (!test) { + //window.setTimeout(function() {createTestDisplay()},2000); + createTestDisplay(); + } + } + }); + } +}; \ No newline at end of file diff --git a/public/js/lib/bonfire/bonfire.js b/public/js/lib/bonfire/bonfireInit.js similarity index 88% rename from public/js/lib/bonfire/bonfire.js rename to public/js/lib/bonfire/bonfireInit.js index 19be8fb116..ee885599f9 100644 --- a/public/js/lib/bonfire/bonfire.js +++ b/public/js/lib/bonfire/bonfireInit.js @@ -46,6 +46,7 @@ var api = { reset(); } else { print(null, data); + reset(); } } }; @@ -66,18 +67,20 @@ var requests; // (re)initializes the plugin var reset = function() { requests = 0; - plugin = new jailed.Plugin(path+'plugin_v0.1.1.js', api); + plugin = new jailed.Plugin(path+'plugin_v0.1.2.js', api); plugin.whenDisconnected( function() { // give some time to handle the last responce setTimeout( function() { endLoading(); - codeOutput.setValue('Infinite loop detected!'); + console.log("resetting on fatal plugin error"); + codeOutput.setValue('Infinite loop or fatal error!'); reset(); }, 10); }); }; + // initialize everything var plugin = null; diff --git a/public/js/lib/bonfire/framework.js b/public/js/lib/bonfire/framework.js deleted file mode 100644 index 441cfe9305..0000000000 --- a/public/js/lib/bonfire/framework.js +++ /dev/null @@ -1,378 +0,0 @@ -var widgets = []; -var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("codeEditor"), { - lineNumbers: true, - mode: "javascript", - theme: 'monokai', - runnable: true, - lint: true, - matchBrackets: true, - autoCloseBrackets: true, - cursorHeight: 0.85, - scrollbarStyle: 'null', - lineWrapping: true, - gutters: ["CodeMirror-lint-markers"], - onKeyEvent: doLinting, - extraKeys : { - "Ctrl-Enter" : function() { - bonfireExecute(); - return false; - } - } -}); -var editor = myCodeMirror; -myCodeMirror.setValue('/*Welcome to Bonfire, Free Code Camp\'s future CoderByte replacement.\n' + -'Please feel free to use Bonfire as an in-browser playground and linting tool.\n' + -'Note that you can also write tests using Chai.js by using the keywords assert and expect */\n\n' + -'function test() {\n' + -' assert(2 !== 3, "2 is not equal to 3");\n' + -' return [1,2,3].map(function(elem) {\n' + -' return elem * elem;\n' + -' });\n' + -'}\n' + -'expect(test()).to.be.a("array");\n\n' + -'assert.deepEqual(test(), [1,4,9]);\n\n' + -'test();'); -//myCodeMirror.setSize("100%", "100%"); - -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. Console.log() -type statements\n' + - ' * will appear in your browser\'s 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 doLinting = function () { - editor.operation(function () { - for (var i = 0; i < widgets.length; ++i) - editor.removeLineWidget(widgets[i]); - widgets.length = 0; - JSHINT(editor.getValue()); - for (var i = 0; i < JSHINT.errors.length; ++i) { - var err = JSHINT.errors[i]; - if (!err) continue; - var msg = document.createElement("div"); - var icon = msg.appendChild(document.createElement("span")); - icon.innerHTML = "!!"; - icon.className = "lint-error-icon"; - msg.appendChild(document.createTextNode(err.reason)); - msg.className = "lint-error"; - widgets.push(editor.addLineWidget(err.line - 1, msg, { - coverGutter: false, - noHScroll: true - })); - } - }); -}; - -var replaceQuotesInTests = function() { - tests.forEach(function(elt, ix, arr) { - arr[ix].text = arr[ix].text.replace(/\"/g,'\''); - }); -}; - -var tests; -var testSalt = Math.random(); - -var scrapeTests = function(userJavaScript) { - var counter = 0; - var regex = new RegExp(/(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)/); - var match = regex.exec(userJavaScript); - while (match != null) { - var replacement = '//' + counter + testSalt; - userJavaScript = userJavaScript.substring(0, match.index) - + replacement - + userJavaScript.substring(match.index + match[0].length); - - if (!tests) tests = []; - tests.push({"text": match[0], "line": counter, "err": null}); - counter++; - match = regex.exec(userJavaScript); - } - replaceQuotesInTests(); - return userJavaScript; -}; - -$('#submitButton').on('click', function () { - bonfireExecute(); -}); - -function bonfireExecute() { - tests = undefined; - $('#codeOutput').empty(); - var userJavaScript = myCodeMirror.getValue(); - userJavaScript = scrapeTests(userJavaScript); - submit(userJavaScript, function(cls, message) { - if (cls) { - codeOutput.setValue(message.error); - runTests('Error', null); - } else { - codeOutput.setValue(message.output); - runTests(null, message); - } - }); -} - -var pushed = false; -var createTestDisplay = function() { - if (pushed) { - tests.pop(); - } - for (var i = 0; i < tests.length;i++) { - var test = tests[i]; - var testDoc = document.createElement("li"); - $(testDoc) - .addClass('list-group-item') - .addClass('well img-rounded') - .addClass('well-sm') - if (test.err != null) { - $(testDoc) - .html(test.text + "\n" + test.err) - .css("background-color", 'rgba(255,0,0,.2)') - .prependTo($('#testSuite')); - } else { - $(testDoc) - .html(test.text) - .css('background-color', 'rgba(0,255,0,.2)') - .appendTo($('#testSuite')); - } - }; -}; -var assert = chai.assert; -var expect = chai.expect; -var reassembleTest = function(test, data) { - var lineNum = test.line; - var regexp = new RegExp("\/\/" + lineNum + testSalt); - return data.input.replace(regexp, test.text); -}; -var runTests = function(err, data) { - pushed = false; - $('#testSuite').children().remove(); - if (err && tests) { - tests = [{text:"Program Execution Failure", err: "No tests were run."}]; - createTestDisplay(); - } else if (tests) { - tests.push(false); - pushed = true; - tests.forEach(function(test, ix, arr){ - try { - if (test) { - var output = eval(reassembleTest(test, data)); - } - } catch(error) { - console.log(error); - arr[ix].err = error.name + ":" + error.message; - console.log(arr); - } finally { - if (!test) { - //window.setTimeout(function() {createTestDisplay()},2000); - createTestDisplay(); - } - } - }); - } -}; - - -// var assert = chai.assert; -// var testResults = []; -// $('#runTests').on('click', function () { -// clearTestOutput(); -// var testCaseList = [], -// jsCode = myCodeMirror.getValue(); -// getTestSuite().each(function () { -// testCaseList.push([$(this).data("input"), $(this).data("output"), $(this)]); -// }); -// testCaseList.forEach(function (input) { -// var testCode = jsCode + "\n\n" + input[0] + ";"; -// //TODO use plugin for this with the rest as a callback? -// var output = eval(testCode); -// testEquality(output, input); -// }); -// // some timeout here? -// if (testResults.length === testCaseList.length) { -// var sum = testResults.reduce(function (a, b) { -// return a + b -// }); -// prependTestOutput("======Testing========\n" + Math.round(100 * sum / testResults.length) + "% tests passed\n"); -// } -// }); -// var testEquality = function (output, input) { -// try { -// switch (typeof output) { -// case 'object': -// assert.deepEqual(output, input[1]); -// break; -// case 'string': -// assert(output.localeCompare(input[1])); -// break -// default: -// assert.equal(output, input[1]); -// } -// appendTestOutput("\n" + createTestString(input[0], input[1]) + "\nTest passed!\n"); -// input[2].css("background-color", "rgba(0,255,0,.2)"); -// testResults.push(1); -// } catch (err) { -// input[2].css("background-color", "rgba(255,0,0,.2)"); -// appendTestOutput(createTestString(input[0], input[1])); -// appendTestOutput("Test failed: \nOutput was: " + output + "\nType of output was: " + (typeof output)); -// testResults.push(0); -// } -// }; -//$('#sideBySide').on('click', function () { -// var main = $('#mainEditorPanel'); -// if (main.hasClass('col-md-12')) { -// replaceColClz(main, 'md', 12, 6); -// replaceColClz(main, 'sm', 12, 6); -// $(this).text("Original Layout") -// } else { -// replaceColClz(main, 'md', 6, 12); -// replaceColClz(main, 'sm', 6, 12); -// $(this).text("Tests side by side") -// } -//}); -//var replaceColClz = function (elt, size, oldVal, newVal) { -// elt.removeClass('col-' + size + '-' + oldVal); -// elt.addClass('col-' + size + '-' + newVal); -//}; -//var getTestSuite = function () { -// return $('#testSuite').find('li'); -//}; -//var clearTestOutput = function () { -// testOutput.setValue(""); -//}; -var appendTestOutput = function (msg) { - writeToTest(msg, CodeMirror.Pos(editor.lastLine())); -}; -var prependTestOutput = function (msg) { - writeToTest(msg, CodeMirror.Pos(editor.firstLine())); -}; -var writeToTest = function (msg, location) { - testOutput.replaceRange("\n" + msg, location); -}; -//$('#addTest').on('click', function () { -// var functionName = $('#testFunctionName option:selected').text(); -// var inputs = []; -// var output; -// $('#testInputs').find('input').each(function () { -// if ($(this).val() != null && $(this).val().length !== 0) { -// inputs.push($(this).val()); -// } else { -// //var keepGoing = prompt("You have submitted a test with empty input. Enter yes to continue."); -// if (/yes/.test(keepGoing.toLowerCase())) { -// inputs.push($(this).val()); -// } else { -// return; -// } -// } -// }); -// output = $('#testOutputs').find('input').val(); -// var functionCall = functionName + "(" + inputs.join(",") + ")"; -// var test = document.createElement("li"); -// $(test) -// .addClass('list-group-item') -// .addClass('well') -// .addClass('well-sm') -// .attr({"data-input": functionCall, "data-output": output}) -// .html(createTestString(functionCall, output)) -// .appendTo($('#testSuite')); -// var closeLink = document.createElement('i'); -// var closeSpan = document.createElement('span'); -// $(closeSpan) -// .addClass("glyphicon glyphicon-remove-sign") -// //.css("float", "right") -// .click(function () { -// //var input = prompt("This will remove the test permanently.\n If you want to do this, type delete"); -// if (/delete/.test(input.toLowerCase())) { -// $(this).parent().remove(); -// } -// }).appendTo($(test)); -// //blank out the form -// $("#testCreateForm").find("input[type=text]").val(""); -//}); -//var createTestString = function (inputs, output) { -// return "Input: " + inputs + "\nExpect:" + output; -//}; -//var testOutput = CodeMirror.fromTextArea(document.getElementById("testOutput"), { -// lineNumbers: false, -// mode: "javascript", -// theme: 'monokai', -// readOnly: 'nocursor' -//}); -//testOutput.setSize("100%", 200); -//var createOptions = function (re, code) { -// var m = re.exec(code); -// while (m != null) { -// var functionName = m[1]; -// if (functionName !== undefined) { -// var option = document.createElement('option'); -// $(option) -// .html(functionName) -// .attr({"data-args": m[2]}) -// .appendTo($('#testFunctionName')); -// } -// m = re.exec(code); -// } -//}; -// $('#testFunctionName').on('change', function () { -// $('#testInputs').children().remove(); -// $('#testOutputs').children().remove(); -// var args = $('#testFunctionName option:selected').data("args"); -// var argArray = args.split(","); -// argArray.forEach(function (arg) { -// if (arg.length > 0) { -// createInputField('#testInputs', arg); -// } -// }); -// createInputField('#testOutputs', 'Expected output'); -// }); -// var createInputField = function (className, arg) { -// var inputDiv = document.createElement('div'); -// $(inputDiv) -// .addClass("control-group") -// .appendTo($(className)); -// var inputLabel = document.createElement('label'); -// $(inputLabel) -// .attr("for", "inputs") -// .html(arg) -// .addClass("col-xs-4 control-label") -// .appendTo($(inputDiv)); -// var textDiv = document.createElement('div'); -// $(textDiv) -// .addClass("col-xs-8 controls") -// .appendTo($(inputDiv)); -// var inputArea = document.createElement('input'); -// $(inputArea) -// .attr("type", "text") -// .addClass("form-control") -// .appendTo($(inputDiv)); -// $(document.createElement("br")).appendTo($(textDiv)); -// }; -// $('#testFunctionName').on('focus', function () { -// $('#testFunctionName').children().remove(); -// var blankOpt = document.createElement("option"); -// $(blankOpt).addClass("selected").appendTo($('#testFunctionName')); -// var re = /function\s+(\w+)\s*\(([\w\s,]*)\)/g; -// var code = myCodeMirror.getValue(); -// createOptions(re, code); -// re = /var (\w+)\s*=\s*function\s*\(([\s\w,]*)\)/g; -// createOptions(re, code); -// }); -// $('#hideTestCreate').on('click', function () { -// var testForm = $("#testCreateForm"); -// if (testForm.is(":visible")) { -// testForm.hide(); -// $(this).text("Create more tests"); -// } else { -// testForm.show(); -// $(this).text("Hide test creation dialogue") -// } -// }); \ No newline at end of file diff --git a/public/js/lib/bonfire/plugin_v0.1.1.js b/public/js/lib/bonfire/plugin_v0.1.2.js similarity index 100% rename from public/js/lib/bonfire/plugin_v0.1.1.js rename to public/js/lib/bonfire/plugin_v0.1.2.js diff --git a/seed_data/bonfires.json b/seed_data/bonfires.json index 6c43f02e31..a6bd8e2f0f 100644 --- a/seed_data/bonfires.json +++ b/seed_data/bonfires.json @@ -1,25 +1,28 @@ -{ - "name": "Palindrome Tester", - "difficulty": 1, // should be a range from 1-5 - "description": [ - "Your job is to determine if a provided string is a palindrome.", - "The definition of a palindrome can be found at http://en.wikipedia.org/wiki/Palindrome.", - "Strings will be passed in with varying formats, such as \"racecar\", \"RaceCar\", and \"race CAR\" among others.", - "Return true if the string is a palindrome, otherwise false" - ], - "publicTests": [ - "expect(palindrome(\"eye\")).to.be.a.(\"boolean\");", - "assert.deepEqual(palindrome(\"eye\"), true);", - "assert.deepEqual(palindrome(\"race car\"), true);", - "assert.deepEqual(palindrome(\"not a palindrome\"), false);" - ], - "privateTests": [ - "assert.deepEqual(palindrome(\"A man, a plan, a canal. Panama\"), true);", - "assert.deepEqual(palindrome(\"never odd or even\"), true);", - "assert.deepEqual(palindrome(\"nope\"), false);" - ], - "challengeSeed": "function palindrome(str) {\n // Good luck!\n return true;\n}\n\n" -} +[ + { + "name": "Palindrome Tester", + "difficulty": 1, // should be a range from 1-5 + "description": [ + "Your job is to determine if a provided string is a palindrome.", + "The definition of a palindrome can be found at http://en.wikipedia.org/wiki/Palindrome.", + "Strings will be passed in with varying formats, such as \"racecar\", \"RaceCar\", and \"race CAR\" among others.", + "Return true if the string is a palindrome, otherwise false" + ], + "publicTests": [ + "expect(palindrome(\"eye\")).to.be.a.(\"boolean\");", + "assert.deepEqual(palindrome(\"eye\"), true);", + "assert.deepEqual(palindrome(\"race car\"), true);", + "assert.deepEqual(palindrome(\"not a palindrome\"), false);" + ], + "privateTests": [ + "assert.deepEqual(palindrome(\"A man, a plan, a canal. Panama\"), true);", + "assert.deepEqual(palindrome(\"never odd or even\"), true);", + "assert.deepEqual(palindrome(\"nope\"), false);" + ], + "challengeSeed": "function palindrome(str) {\n // Good luck!\n return true;\n}\n\n", + "bonfireNumber": 1 + } +] /* "aaa48de84e1ecc7c742e1124" diff --git a/seed_data/seed_challenges.js b/seed_data/seed_challenges.js index 1d0ab0760d..54b9f619bd 100644 --- a/seed_data/seed_challenges.js +++ b/seed_data/seed_challenges.js @@ -1,8 +1,10 @@ require('dotenv').load(); var Challenge = require('../models/Challenge.js'), + Bonfire = require('../models/Bonfire.js'), mongoose = require('mongoose'), secrets = require('../config/secrets'), - challenges = require('./challenges.json'); + challenges = require('./challenges.json'), + bonfires = require('./bonfires.json'); mongoose.connect(secrets.db); @@ -16,8 +18,21 @@ Challenge.remove({}, function(err, data) { if (err) { console.log(err); } else { - console.log('Saved ', data); + console.log('Saved ', data); + } + }); +}); +Bonfire.remove({}, function(err, data) { + if (err) { + console.error(err); + } else { + console.log('Deleted ', data); + } + Bonfire.create(bonfires, function(err, data) { + if (err) { + console.log(err); + } else { + console.log('Saved ', data); } - process.exit(0); }); }); diff --git a/views/bonfire/bonfire.jade b/views/bonfire/bonfire.jade index 2d29a40a04..2619a1a693 100644 --- a/views/bonfire/bonfire.jade +++ b/views/bonfire/bonfire.jade @@ -13,7 +13,7 @@ block content link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono") script(src='/js/lib/codemirror/mode/javascript/javascript.js') script(src='js/lib/jailed/jailed.js') - script(src='/js/lib/bonfire/bonfire.js') + script(src='/js/lib/bonfire/bonfireInit.js') .row #mainEditorPanel.col-sm-12.col-md-7.col-xs-12 .panel.panel-primary.panel-bonfire @@ -36,4 +36,4 @@ block content br ul#testSuite.list-group br - script(src='/js/lib/bonfire/framework.js') \ No newline at end of file + script(src='/js/lib/bonfire/bonfireFramework.js') \ No newline at end of file