Merge remote-tracking branch 'upstream/staging' into staging

Conflicts:
	seed/challenges/html5-and-css.json
This commit is contained in:
dokkillo
2015-08-20 16:46:06 +02:00
13 changed files with 162 additions and 4136 deletions

View File

@ -685,7 +685,7 @@ thead {
padding-right: 10px;
&:hover {
padding-top: 14px;
padding-bottom: 14px;
padding-bottom: 12px;
color: #4a2b0f;
background-color: #eee;
text-decoration: none;

View File

@ -252,14 +252,15 @@ var allSeeds = '';
editorValue = (codeStorage.isAlive())? codeStorage.getEditorValue() : allSeeds;
editor.setValue(editorValue);
editor.setValue(editorValue.replace((/fccss/gi), '<script>').replace((/fcces/gi), '</script>'));
editor.refresh();
var resetEditor = function resetEditor() {
editor.setValue(allSeeds);
editor.setValue(allSeeds.replace((/fccss/gi), '<script>').replace((/fcces/gi), '</script>'));
updatePreview();
codeStorage.updateStorage();
};
/*
var challengeSeed = challengeSeed || null;
var allSeeds = '';
(function() {
@ -273,3 +274,4 @@ var allSeeds = '';
}, 200);
})();
})();
*/

View File

@ -159,33 +159,7 @@ $(document).ready(function() {
$('#complete-zipline-or-basejump-dialog').modal('show');
});
$('#completed-courseware-dialog').unbind('click');
$('#complete-courseware-dialog').on('hidden.bs.modal', function() {
editor.focus();
});
$('#completed-zipline-or-basejump').unbind('click');
$('#complete-zipline-or-basejump').on('hidden.bs.modal', function() {
editor.focus();
});
};
$(window).resize(function(){
reBindModals();
});
reBindModals();
var challengeTypes = {
'HTML_CSS_JQ': '0',
'JAVASCRIPT': '1',
'VIDEO': '2',
'ZIPLINE': '3',
'BASEJUMP': '4',
'BONFIRE': '5'
};
$('#next-courseware-button').unbind('click');
$('#next-courseware-button').on('click', function() {
$('#next-courseware-button').unbind('click');
if ($('.signup-btn-nav').length < 1) {
@ -262,23 +236,52 @@ $(document).ready(function() {
}
});
$('.next-challenge-button').unbind('click');
$('.next-challenge-button').on('click', function() {
l = location.pathname.split('/');
window.location = '/challenges/' + (parseInt(l[l.length - 1]) + 1);
});
// Bonfire instructions functions
$('#more-info').unbind('click');
$('#more-info').on('click', function() {
ga('send', 'event', 'Challenge', 'more-info', challengeName);
$('#brief-instructions').hide();
$('#long-instructions').show().removeClass('hide');
});
$('#less-info').unbind('click');
$('#less-info').on('click', function() {
$('#brief-instructions').show();
$('#long-instructions').hide();
});
$('#complete-courseware-dialog').on('hidden.bs.modal', function() {
editor.focus();
});
$('#complete-zipline-or-basejump').on('hidden.bs.modal', function() {
editor.focus();
});
};
$(window).resize(function(){
reBindModals();
});
reBindModals();
var challengeTypes = {
'HTML_CSS_JQ': '0',
'JAVASCRIPT': '1',
'VIDEO': '2',
'ZIPLINE': '3',
'BASEJUMP': '4',
'BONFIRE': '5'
};
function upvoteHandler(e) {
e.preventDefault();
var upvoteBtn = this;

View File

@ -113,7 +113,7 @@
"description": [
"<code>data structures</code> have <code>properties</code>. For example, <code>strings</code> have a property called <code>.length</code> that will tell you how many characters are in the string.",
"For example, if we created a variable <code>var firstName = \"Charles\"</code>, we could find out how long the string \"Charles\" is by using the <code>firstName.length</code> property.",
"Use the <code>.length</code> property to count the number of characters in the <code>lastNameLength</code> variable."
"Use the <code>.length</code> property to count the number of characters in the <code>lastName</code> variable."
],
"tests": [
"assert((function(){if(typeof(lastNameLength) !== \"undefined\" && typeof(lastNameLength) === \"number\" && lastNameLength === 8){return(true);}else{return(false);}})(), 'lastNameLength should be equal to eight.');",
@ -150,7 +150,7 @@
"<code>Bracket notation</code> is a way to get a character at a specific <code>index</code> within a string.",
"Computers don't start counting at 1 like humans do. They start at 0.",
"For example, the character at index 0 in the word \"Charles\" is \"C\". So if <code>var firstName = \"Charles\"</code>, you can get the value of the first letter of the string by using <code>firstName[0]</code>.",
"Use <code>bracket notation</code> to find the first character in a the <code>firstLetterOfLastName</code> variable.",
"Use <code>bracket notation</code> to find the first character in the <code>firstLetterOfLastName</code> variable.",
"Try looking at the <code>firstLetterOfFirstName</code> variable declaration if you get stuck."
],
"tests": [
@ -216,7 +216,7 @@
"In order to get the last letter of a string, you can subtract one from the string's length.",
"For example, if <code>var firstName = \"Charles\"</code>, you can get the value of the last letter of the string by using <code>firstName[firstName.length - 1]</code>.",
"Use <code>bracket notation</code> to find the last character in the <code>lastName</code> variable.",
"Try looking at the <code>lastLetterOfLastName</code> variable declaration if you get stuck."
"Try looking at the <code>lastLetterOfFirstName</code> variable declaration if you get stuck."
],
"tests": [
"assert(lastLetterOfLastName === \"e\", 'lastLetterOfLastName should be \"e\"');",
@ -496,7 +496,7 @@
"// Only change code above this line.",
"// We use this function to show you the value of your variable in your output box.",
"// You'll learn about functions soon.",
"if(typeof(myArray) !== \"undefined\" && typeof(data) !== \"undefined\"){(function(y,z){return('myArray = ' + JSON.stringify(y) + ', data = ' + JSON.stringify(z));})(myArray, data);}"
"if(typeof(myArray) !== \"undefined\" && typeof(myData) !== \"undefined\"){(function(y,z){return('myArray = ' + JSON.stringify(y) + ', myData = ' + JSON.stringify(z));})(myArray, myData);}"
],
"type": "waypoint",
"challengeType": 1
@ -755,7 +755,7 @@
"title": "Manipulate JavaScript Objects",
"difficulty":"9.9823",
"description":[
"There are many ways to add and add and remove properties from objects.",
"There are many ways to add and remove properties from objects.",
"For example, we can add properties to objects like this:",
"<code>myObject.myProperty = \"myValue\";</code>",
"We can also delete them like this:",
@ -832,7 +832,7 @@
"difficulty":"9.9825",
"description":[
"You can run the same code multiple times by using a loop.",
"Another type of JavaScript loop is called a \"while loop\" because it runs \"while\" something is true, and stops once that something is no longer true.",
"Another type of JavaScript loop is called a \"while loop\", because it runs \"while\" something is true and stops once that something is no longer true.",
"<code>var ourArray = [];</code>",
"<code>var i = 0;</code>",
"<code>while(i < 5) {</code>",
@ -859,7 +859,7 @@
"title": "Generate Random Fractions with JavaScript",
"difficulty":"9.9827",
"description":[
"Random numbers are useful for creating random behaviours and games.",
"Random numbers are useful for creating random behavior.",
"JavaScript has a <code>Math.random()</code> function that generates a random decimal number.",
"Use <code>Math.random()</code> to get <code>myFunction</code> to return a random number."
],
@ -956,16 +956,16 @@
"difficulty":"9.983",
"description":[
"We can use if statements in JavaScript to only execute code if a certain condition is met.",
"if statements require some sort of boolean condition evaluate.",
"if statements require some sort of boolean condition to evaluate.",
"Example:",
"<code> if (1 == 2) {</code>",
"<code> if (1 === 2) {</code>",
"<code>&thinsp;&thinsp;return(true);</code>",
"<code>}</code>",
"<code>else {</code>",
"<code>&thinsp;&thinsp;return(false);</code>",
"<code>}</code>",
"Let's use <code>if</code> and <code>else</code> statements to make a coin-flip game.",
"Create an <code>if-else statement</code> to return <code>heads</code> if the flip var is zero and to return <code>tails</code> if it's not."
"Create an <code>if-else statement</code> to return <code>heads</code> if the flip var is zero, or else return <code>tails</code> if it's not."
],
"tests":[
"assert((function(){if(myFunction() === \"heads\" || myFunction() === \"tails\"){return(true);}else{return(false);}})(), 'myFunction should either return heads or tails');",
@ -975,7 +975,7 @@
"challengeSeed":[
"function myFunction(){",
" var flip = Math.floor(Math.random() * (1 - 0 + 1)) + 0;",
" // Create and if else statement here to return \"heads\" if flip is 0. Otherwise return \"tails\".",
" // Create an if-else statement here to return \"heads\" if flip is 0. Otherwise return \"tails\".",
"",
" // Only change code below this line.",
"",
@ -1002,7 +1002,7 @@
"<code>g</code> means that we want to search the entire string for this pattern.",
"<code>i</code> means that we want to ignore the case (uppercase or lowercase) when searching for the pattern.",
"<code>Regular expressions</code> are usually surrounded by <code>/</code> symbols.",
"Let's try selecting all the occurances of the word <code>and</code> in the string <code>George Boole and Alan Turing went to the shop and got some milk</code>. We can do this by replacing the <code>.+</code> part of our regular expression with the current <code>regular expression</code> with the word <code>and</code>."
"Let's try selecting all the occurrences of the word <code>and</code> in the string <code>George Boole and Alan Turing went to the shop and got some milk</code>. We can do this by replacing the <code>.+</code> part of our regular expression with the current <code>regular expression</code> with the word <code>and</code>."
],
"tests":[
"assert(test==2, 'Your <code>regular expression</code> should find two occurrences of the word <code>and</code>');",
@ -1040,7 +1040,7 @@
],
"challengeSeed":[
"var test = (function() {",
" var testString = \"There's 3 cats but 4 dogs.\";",
" var testString = \"There are 3 cats but 4 dogs.\";",
"",
" // Only change code below this line.",
"",
@ -1093,12 +1093,12 @@
"You can invert any match by using the uppercase version of the selector <code>\\s</code> versus <code>\\S</code> for example."
],
"tests":[
"assert(test === 36, 'Your RegEx should have found seven spaces in the <code>testString</code>.');",
"assert(editor.getValue().match(/\\/\\\\S\\/gi/gi), 'You should be using the following expression <code>/\\+S/gi</code> to find the spaces in the <code>testString</code>.');"
"assert(test === 49, 'Your RegEx should have found forty nine non-space characters in the <code>testString</code>.');",
"assert(editor.getValue().match(/\\/\\\\S\\/gi/gi), 'You should be using the following expression <code>/\\S/gi</code> to find non-space characters in the <code>testString</code>.');"
],
"challengeSeed":[
"var test = (function(){",
" var testString = \"How many spaces are there in this sentence?\";",
" var testString = \"How many non-space characters are there in this sentence?\";",
"",
" // Only change code below this line.",
"",

View File

@ -48,11 +48,11 @@
"Here are the <a href='http://en.wikipedia.org/wiki/User_story' target='_blank'>user stories</a> you must enable, and optional bonus user stories:",
"<span class='text-info'>User Story:</span> As a user, I can access all of the portfolio webpage's content just by scrolling.",
"<span class='text-info'>User Story:</span> As a user, I can click different buttons that will take me to the portfolio creator's different social media pages.",
"<span class='text-info'>User Story:</span> As a user, I can see thumbnail images of different projects the portfolio creator has built (if you don't haven't built any websites before, use placeholders.)",
"<span class='text-info'>User Story:</span> As a user, I can see thumbnail images of different projects the portfolio creator has built (if you haven't built any websites before, use placeholders.)",
"<span class='text-info'>Bonus User Story:</span> As a user, I navigate to different sections of the webpage by clicking buttons in the navigation.",
"Don't worry if you don't have anything to showcase on your portfolio yet - you will build several several apps on the next few CodePen challenges, and can come back and update your portfolio later.",
"There are many great portfolio templates out there, but for this challenge, you'll need to build a portfolio page yourself. Using Bootstrap will make this much easier for you.",
"Note that CodePen.io overrides the Window.open() function, so if you want to open windows using jquery, you will need to target invisible anchor elements like this one: <code>&lt;a target='_blank'&rt;</a>.",
"Note that CodePen.io overrides the Window.open() function, so if you want to open windows using jquery, you will need to target invisible anchor elements like this one: <code>&lt;a target='_blank'&gt;</a></code>.",
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> 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, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.<br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"

View File

@ -133,7 +133,7 @@
"",
" <p>Click here for <a href=\"#\">cat photos</a>.</p>",
"",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"http://bit.ly/fcc-relaxing-cat\"></a>",
"",
" <p>Things cats love:</p>",
" <ul>",

File diff suppressed because it is too large Load Diff

View File

@ -263,7 +263,7 @@
],
"tests": [
"assert(editor.match(/\\$\\(.*button/g), 'Use the <code>$&#40\"button\"&#41</code> selector.')",
"assert(editor.match(/\\$\\(.*.btn/g), 'Use the <code>$&#40\".btn\"&#41</code> selector.')",
"assert(editor.match(/\\$\\(.*\\.btn/g), 'Use the <code>$&#40\".btn\"&#41</code> selector.')",
"assert(editor.match(/\\$\\(.*#target1/g), 'Use the <code>$&#40\"#target1\"&#41</code> selector.')",
"assert(editor.match(/addClass/g) && editor.match(/addClass/g).length > 2, 'Only add one class with each of your three selectors.')",
"assert($(\"#target1\").hasClass(\"animated\") && $(\"#target1\").hasClass(\"shake\") && $(\"#target1\").hasClass(\"btn-primary\"), 'Your <code>#target1</code> element should have the classes <code>animated</code>&#130; <code>shake</code> and <code>btn-primary</code>.')",
@ -314,7 +314,7 @@
],
"tests": [
"assert($(\".btn-default\").length === 0, 'Remove the <code>btn-default</code> class from all of your <code>button</code> elements.')",
"assert(editor.match(/btn btn-default/g), 'Only use jQuery to add these classes to the element.')"
"assert(editor.match(/btn btn-default/g), 'Only use jQuery to remove this class from the element.')"
],
"challengeSeed": [
"fccss",

View File

@ -17,7 +17,7 @@
"difficulty":0,
"description":[
"Before we dive into Object Oriented Programming, let's revisit JavaScript objects.",
"Give your <code>motorBike</code> object a <code>wheels</code>, <code>engine</code> and <code>seats</code> attribute and set them to numbers."
"Give your <code>motorBike</code> object a <code>wheels</code>, <code>engines</code> and <code>seats</code> attribute and set them to numbers."
],
"tests":[
"assert(typeof(motorBike.engines) === 'number', '<code>engines</code> should be have a <code>engines</code> attribute set to a number.');",
@ -54,7 +54,7 @@
"difficulty":0,
"description":[
"We are also able to create objects using <code>constructor</code> functions.",
"Give your <code>motorBike</code> object a <code>wheels</code>, <code>engine</code> and <code>seats</code> attribute and set them to numbers."
"Give your <code>motorBike</code> object a <code>wheels</code>, <code>engines</code> and <code>seats</code> attribute and set them to numbers."
],
"tests":[
"assert(typeof((new MotorBike()).engines) === 'number', '<code>engines</code> should be have a <code>engines</code> attribute set to a number.');",
@ -62,7 +62,7 @@
"assert(typeof((new MotorBike()).seats) === 'number', '<code>seats</code> should be have a <code>engines</code> attribute set to a number.');"
],
"challengeSeed":[
"// Let's add the properties engine and seats to the car in the same way that the property wheels has been added below. They should both be numbers.",
"// 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.",
"var Car = function() {",
" this.wheels = 4;",
" this.engines = 1;",

View File

@ -63,6 +63,7 @@ module.exports = function(app) {
const findChallenge$ = observeMethod(Challenge, 'find');
// create a stream of all the challenges
const challenge$ = findChallenge$(challengesQuery)
.doOnNext(() => debug('query challenges'))
.flatMap(challenges => Observable.from(challenges))
.shareReplay();
@ -128,18 +129,12 @@ module.exports = function(app) {
app.use(router);
function returnNextChallenge(req, res, next) {
// find the user's current challenge and block
// look in that block and find the index of their current challenge
// if index + 1 < block.challenges.length
// serve index + 1 challenge
// otherwise increment block key and serve the first challenge in that block
// unless the next block is undefined, which means no next block
let nextChallengeName = firstChallenge;
const challengeId = req.user.currentChallenge ?
req.user.currentChallenge.challengeId :
'bd7123c8c441eddfaeb5bdef';
// find challenge
return challenge$
.map(challenge => challenge.toJSON())

View File

@ -4,24 +4,36 @@ var _ = require('lodash'),
debug = require('debug')('freecc:cntr:userController');
const daysBetween = 1.5;
function calcCurrentStreak(cals) {
const revCals = cals.slice().reverse();
let streakBroken = false;
return revCals
const lastDayInStreak = revCals
.reduce((current, cal, index) => {
// if streak not borken and diff between this cal and the call after it
// is equal to zero
// moment.diff will return the days between rounded down
debug('cal', cal);
debug('broken', streakBroken);
const before = revCals[index === 0 ? 0 : index - 1];
if (
!streakBroken &&
moment(revCals[index === 0 ? 0 : index - 1]).diff(cal, 'days') === 0
moment(before).diff(cal, 'days', true) < daysBetween
) {
return current + 1;
return index;
}
return 1;
}, 1);
streakBroken = true;
return current;
}, 0);
const lastTimestamp = revCals[lastDayInStreak];
return Math.ceil(moment().diff(lastTimestamp, 'days', true));
}
// TODO(berks): calc longest streak
/*
function longestStreak(cals) {
}
*/
module.exports = function(app) {
var router = app.loopback.Router();
var User = app.models.User;
@ -129,9 +141,7 @@ module.exports = function(app) {
objOrNum :
objOrNum.timestamp;
})
.map(time => {
return moment(time).format('YYYY-MM-DD');
});
.sort();
user.currentStreak = calcCurrentStreak(cals);
@ -146,6 +156,9 @@ module.exports = function(app) {
objOrNum :
objOrNum.timestamp;
})
.filter((timestamp) => {
return !!timestamp;
})
.reduce((data, timeStamp) => {
data[(timeStamp / 1000)] = 1;
return data;

View File

@ -2,6 +2,14 @@
"initial:before": {
"loopback#favicon": {
"params": "$!../public/favicon.ico"
},
"loopback#static": {
"params": [
"$!../public",
{
"maxAge": "86400000"
}
]
}
},
"initial": {
@ -42,14 +50,6 @@
"routes": {
},
"files": {
"loopback#static": {
"params": [
"$!../public",
{
"maxAge": "86400000"
}
]
}
},
"final": {
},

View File

@ -19,7 +19,7 @@ script.
script(src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.js")
script.
if (typeof window.angular === 'undefined') {
document.write('<script src="/bower_components/angular/angular.min.js"><\/script>')
document.write('<script src="/bower_components/angular/angular.min.js"><\/script>');
}
script(src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap.min.js")
script.