major challenges refactor

commented out resetEditor in main
remove heatmap timout
This commit is contained in:
Berkeley Martinez
2015-06-20 19:52:37 -07:00
parent 4d2b0844ae
commit 03ea412b4a
5 changed files with 198 additions and 282 deletions

View File

@ -70,6 +70,7 @@
"node-slack": "0.0.7", "node-slack": "0.0.7",
"node-uuid": "^1.4.3", "node-uuid": "^1.4.3",
"nodemailer": "~1.3.0", "nodemailer": "~1.3.0",
"object.assign": "^3.0.0",
"passport-facebook": "^2.0.0", "passport-facebook": "^2.0.0",
"passport-google-oauth2": "^0.1.6", "passport-google-oauth2": "^0.1.6",
"passport-linkedin-oauth2": "^1.2.1", "passport-linkedin-oauth2": "^1.2.1",

View File

@ -331,6 +331,8 @@ $(document).ready(function() {
$('#story-submit').on('click', storySubmitButtonHandler); $('#story-submit').on('click', storySubmitButtonHandler);
// $('#reset-button').on('click', resetEditor);
var commentSubmitButtonHandler = function commentSubmitButtonHandler() { var commentSubmitButtonHandler = function commentSubmitButtonHandler() {
$('#comment-button').unbind('click'); $('#comment-button').unbind('click');
var data = $('#comment-box').val(); var data = $('#comment-box').val();

View File

@ -31,9 +31,15 @@
*/ */
var R = require('ramda'), var R = require('ramda'),
Rx = require('rx'),
assign = require('object.assign'),
debug = require('debug')('freecc:challenges'), debug = require('debug')('freecc:challenges'),
utils = require('../utils'), utils = require('../utils'),
// this would be so much cleaner with destructering...
saveUser = require('../utils/rx').saveUser, saveUser = require('../utils/rx').saveUser,
observableQueryFromModel = require('../utils/rx').observableQueryFromModel,
userMigration = require('../utils/middleware').userMigration, userMigration = require('../utils/middleware').userMigration,
ifNoUserRedirectTo = require('../utils/middleware').ifNoUserRedirectTo; ifNoUserRedirectTo = require('../utils/middleware').ifNoUserRedirectTo;
@ -55,6 +61,16 @@ function unDasherize(name) {
return ('' + name).replace(/\-/g, ' '); return ('' + name).replace(/\-/g, ' ');
} }
function updateUserProgress(user, challengeId, completedChallenge) {
var index = user.uncompletedChallenges.indexOf(challengeId);
if (index > -1) {
user.progressTimestamps.push(Date.now());
user.uncompletedChallenges.splice(index, 1);
}
user.completedChallenges.push(completedChallenge);
return user;
}
module.exports = function(app) { module.exports = function(app) {
var router = app.loopback.Router(); var router = app.loopback.Router();
var Challenge = app.models.Challenge; var Challenge = app.models.Challenge;
@ -143,6 +159,7 @@ module.exports = function(app) {
return elem; return elem;
} }
}); });
if (!req.user.currentChallenge) { if (!req.user.currentChallenge) {
req.user.currentChallenge = {}; req.user.currentChallenge = {};
req.user.currentChallenge.challengeId = challengeMapWithIds['0'][0]; req.user.currentChallenge.challengeId = challengeMapWithIds['0'][0];
@ -201,11 +218,11 @@ module.exports = function(app) {
challengeId: challenge.id, challengeId: challenge.id,
challengeName: challenge.name, challengeName: challenge.name,
dashedName: challenge.dashedName, dashedName: challenge.dashedName,
challengeBlock: R.head(R.flatten(Object.keys(challengeMapWithIds). challengeBlock: R.head(R.flatten(Object.keys(challengeMapWithIds)
map(function (key) { .map(function (key) {
return challengeMapWithIds[key] return challengeMapWithIds[key]
.filter(function (elem) { .filter(function (elem) {
return String(elem) === challenge.id; return elem === ('' + challenge.id);
}) })
.map(function () { .map(function () {
return key; return key;
@ -261,143 +278,124 @@ module.exports = function(app) {
} }
function completedBonfire(req, res, next) { function completedBonfire(req, res, next) {
var isCompletedWith = req.body.challengeInfo.completedWith || ''; debug('compltedBonfire');
var isCompletedDate = Math.round(+new Date()); var completedWith = req.body.challengeInfo.completedWith || false;
var challengeId = req.body.challengeInfo.challengeId; var challengeId = req.body.challengeInfo.challengeId;
var isSolution = req.body.challengeInfo.solution;
var challengeName = req.body.challengeInfo.challengeName;
if (isCompletedWith) { var challengeData = {
User.find({ id: challengeId,
where: { username: isCompletedWith.toLowerCase() }, name: req.body.challengeInfo.challengeName,
limit: 1 completedDate: Math.round(+new Date()),
}, function (err, pairedWith) { solution: req.body.challengeInfo.solution,
if (err) { return next(err); } challengeType: 5
};
var index = req.user.uncompletedChallenges.indexOf(challengeId); observableQueryFromModel(
if (index > -1) { User,
req.user.progressTimestamps.push(Date.now() || 0); 'findOne',
req.user.uncompletedChallenges.splice(index, 1); { where: { username: ('' + completedWith).toLowerCase() } }
} )
pairedWith = pairedWith.pop(); .doOnNext(function(pairedWith) {
debug('paired with ', pairedWith);
if (pairedWith) { if (pairedWith) {
updateUserProgress(
index = pairedWith.uncompletedChallenges.indexOf(challengeId); pairedWith,
if (index > -1) { challengeId,
pairedWith.progressTimestamps.push(Date.now() || 0); assign({ completedWith: req.user.id }, challengeData)
pairedWith.uncompletedChallenges.splice(index, 1); );
}
pairedWith.completedChallenges.push({
id: challengeId,
name: challengeName,
completedWith: req.user.id,
completedDate: isCompletedDate,
solution: isSolution,
challengeType: 5
});
req.user.completedChallenges.push({
id: challengeId,
name: challengeName,
completedWith: pairedWith.id,
completedDate: isCompletedDate,
solution: isSolution,
challengeType: 5
});
} }
// User said they paired, but pair wasn't found })
req.user.completedChallenges.push({ .withLatestFrom(
id: challengeId, Rx.Observable.just(req.user),
name: challengeName, function(pairedWith, user) {
completedWith: null, debug('yo');
completedDate: isCompletedDate, return {
solution: isSolution, user: user,
challengeType: 5 pairedWith: pairedWith
}); };
}
req.user.save(function (err, user) { )
if (err) { return next(err); } // side effects should always be done in do's and taps
.doOnNext(function(dats) {
if (pairedWith) { updateUserProgress(
pairedWith.save(function (err, paired) { dats.user,
if (err) { challengeId,
return next(err); dats.pairedWith ?
} // paired programmer found and adding to data
if (user && paired) { assign({ completedWith: dats.pairedWith.id }, challengeData) :
return res.send(true); // user said they paired, but pair wasn't found
} challengeData
}); );
} else if (user) { })
res.send(true); // not iterate users
.flatMap(function(dats) {
debug('flatmap');
return Rx.Observable.from([dats.user, dats.pairedWith]);
})
// save user
.flatMap(function(user) {
// save user will do nothing if user is falsey
debug('saving user', user.username);
return saveUser(user);
})
.subscribe(
function(user) {
debug('onNext');
if (user) {
debug('user %s saved', user.username);
} }
}); },
}); next,
} else { function() {
req.user.completedChallenges.push({ debug('completed');
id: challengeId, return res.status(200).send(true);
name: challengeName, }
completedWith: null, );
completedDate: isCompletedDate,
solution: isSolution,
challengeType: 5
});
var index = req.user.uncompletedChallenges.indexOf(challengeId);
if (index > -1) {
req.user.progressTimestamps.push(Date.now() || 0);
req.user.uncompletedChallenges.splice(index, 1);
}
req.user.save(function (err) {
if (err) { return next(err); }
res.send(true);
});
}
} }
function completedChallenge(req, res, next) { function completedChallenge(req, res, next) {
var isCompletedDate = Math.round(+new Date()); var completedDate = Math.round(+new Date());
var challengeId = req.body.challengeInfo.challengeId; var challengeId = req.body.challengeInfo.challengeId;
req.user.completedChallenges.push({ updateUserProgress(
id: challengeId, req.user,
completedDate: isCompletedDate, challengeId,
name: req.body.challengeInfo.challengeName, {
solution: null, id: challengeId,
githubLink: null, completedDate: completedDate,
verified: true name: req.body.challengeInfo.challengeName,
}); solution: null,
var index = req.user.uncompletedChallenges.indexOf(challengeId); githubLink: null,
verified: true
if (index > -1) {
req.user.progressTimestamps.push(Date.now() || 0);
req.user.uncompletedChallenges.splice(index, 1);
}
req.user.save(function (err, user) {
if (err) {
return next(err);
} }
if (user) { );
res.sendStatus(200);
} saveUser(req.user)
}); .subscribe(
function() { },
next,
function() {
res.sendStatus(200);
}
);
} }
function completedZiplineOrBasejump(req, res, next) { function completedZiplineOrBasejump(req, res, next) {
var isCompletedWith = req.body.challengeInfo.completedWith || false; var completedWith = req.body.challengeInfo.completedWith || false;
var isCompletedDate = Math.round(+new Date()); var completedDate = Math.round(+new Date());
var challengeId = req.body.challengeInfo.challengeId; var challengeId = req.body.challengeInfo.challengeId;
var solutionLink = req.body.challengeInfo.publicURL; var solutionLink = req.body.challengeInfo.publicURL;
var githubLink = req.body.challengeInfo.challengeType === '4'
? req.body.challengeInfo.githubURL : true; var githubLink = req.body.challengeInfo.challengeType === '4' ?
req.body.challengeInfo.githubURL :
true;
var challengeType = req.body.challengeInfo.challengeType === '4' ? var challengeType = req.body.challengeInfo.challengeType === '4' ?
4 : 3; 4 :
3;
if (!solutionLink || !githubLink) { if (!solutionLink || !githubLink) {
req.flash('errors', { req.flash('errors', {
msg: 'You haven\'t supplied the necessary URLs for us to inspect ' + msg: 'You haven\'t supplied the necessary URLs for us to inspect ' +
@ -406,93 +404,64 @@ module.exports = function(app) {
return res.sendStatus(403); return res.sendStatus(403);
} }
if (isCompletedWith) { var challengeData = {
User.find({ id: challengeId,
where: { username: isCompletedWith.toLowerCase() }, name: req.body.challengeInfo.challengeName,
limit: 1 completedDate: completedDate,
}, function (err, pairedWithFromMongo) { solution: solutionLink,
if (err) { return next(err); } githubLink: githubLink,
var index = req.user.uncompletedChallenges.indexOf(challengeId); challengeType: challengeType,
if (index > -1) { verified: false
req.user.progressTimestamps.push(Date.now() || 0); };
req.user.uncompletedChallenges.splice(index, 1);
observableQueryFromModel(
User,
'findOne',
{ where: { username: completedWith.toLowerCase() } }
)
.doOnNext(function(pairedWith) {
if (pairedWith) {
updateUserProgress(
pairedWith,
challengeId,
assign({ completedWith: req.user.id }, challengeData)
);
} }
var pairedWith = pairedWithFromMongo.pop(); })
.withLatestFrom(Rx.Observable.just(req.user), function(user, pairedWith) {
req.user.completedChallenges.push({ return {
id: challengeId, user: user,
name: req.body.challengeInfo.challengeName, pairedWith: pairedWith
completedWith: pairedWith.id, };
completedDate: isCompletedDate, })
solution: solutionLink, .doOnNext(function(dats) {
githubLink: githubLink, updateUserProgress(
challengeType: challengeType, dats.user,
verified: false challengeId,
}); dats.pairedWith ?
assign({ completedWith: dats.pairedWith.id }, challengeData) :
req.user.save(function (err, user) { challengeData
if (err) { return next(err); } );
})
if (req.user.id.toString() === pairedWith.id.toString()) { .flatMap(function(dats) {
return res.sendStatus(200); return Rx.Observable.from([dats.user, dats.pairedWith]);
})
// save users
.flatMap(function(user) {
// save user will do nothing if user is falsey
return saveUser(user);
})
.subscribe(
function(user) {
if (user) {
debug('user %s saved', user.username);
} }
index = pairedWith.uncompletedChallenges.indexOf(challengeId); },
if (index > -1) { next,
pairedWith.progressTimestamps.push(Date.now() || 0); function() {
pairedWith.uncompletedChallenges.splice(index, 1); return res.status(200).send(true);
}
pairedWith.completedChallenges.push({
id: challengeId,
name: req.body.challengeInfo.coursewareName,
completedWith: req.user.id,
completedDate: isCompletedDate,
solution: solutionLink,
githubLink: githubLink,
challengeType: challengeType,
verified: false
});
pairedWith.save(function (err, paired) {
if (err) {
return next(err);
}
if (user && paired) {
return res.sendStatus(200);
}
});
});
});
} else {
req.user.completedChallenges.push({
id: challengeId,
name: req.body.challengeInfo.challengeName,
completedWith: null,
completedDate: isCompletedDate,
solution: solutionLink,
githubLink: githubLink,
challengeType: challengeType,
verified: false
});
var index = req.user.uncompletedChallenges.indexOf(challengeId);
if (index > -1) {
req.user.progressTimestamps.push(Date.now() || 0);
req.user.uncompletedChallenges.splice(index, 1);
}
req.user.save(function (err, user) {
if (err) {
return next(err);
} }
// NOTE(berks): under certain conditions this will not close );
// the response.
if (user) {
return res.sendStatus(200);
}
});
}
} }
function challengeMap(req, res, next) { function challengeMap(req, res, next) {

View File

@ -4,7 +4,7 @@ var _ = require('lodash'),
crypto = require('crypto'), crypto = require('crypto'),
nodemailer = require('nodemailer'), nodemailer = require('nodemailer'),
moment = require('moment'), moment = require('moment'),
//debug = require('debug')('freecc:cntr:userController'), // debug = require('debug')('freecc:cntr:userController'),
secrets = require('../../config/secrets'); secrets = require('../../config/secrets');

View File

@ -47,88 +47,32 @@ block content
.background-svg.img-center .background-svg.img-center
.points-on-top .points-on-top
= "[ " + (progressTimestamps.length) + " ]" = "[ " + (progressTimestamps.length) + " ]"
.row
.col-xs-12
if (website1Title && website1Link && website1Image)
.row
.col-xs-12.col-md-5
img.img-center.img-responsive.portfolio-image(src=website1Image, alt="@#{username}'s #{website1Title}")
.col-xs-12.col-md-7
h3.text-center.wrappable.flat-top= website1Title
a.btn.btn-lg.btn-block.btn-info(href=website1Link, target='_blank')
i.fa.icon-beaker
| Try it out
br
if (website1Title && website1Link && !website1Image)
.col-xs-12.col-md-12
h3.text-center.wrappable.flat-top= website1Title
a.btn.btn-lg.btn-block.btn-info(href=website1Link, target='_blank')
i.fa.icon-beaker
| Try it out
br
if (website2Title && website2Link && website2Image)
.row
.col-xs-12.col-md-5
img.img-responsive.portfolio-image.img-center(src=website2Image, alt="@#{username}'s #{website2Title}")
.col-xs-12.col-md-7
h3.text-center.wrappable.flat-top= website2Title
a.btn.btn-lg.btn-block.btn-info(href=website2Link, target='_blank')
i.fa.icon-beaker
| Try it out
br
if (website2Title && website2Link && !website2Image)
.col-xs-12.col-md-12
h3.text-center.wrappable.flat-top= website2Title
a.btn.btn-lg.btn-block.btn-info(href=website2Link, target='_blank')
i.fa.icon-beaker
| Try it out
br
if (website3Title && website3Link && website3Image)
.row
.col-xs-12.col-md-5
img.img-responsive.portfolio-image.img-center(src=website3Image, alt="@#{username}'s #{website1Title}")
.col-xs-12.col-md-7
h3.text-center.wrappable.flat-top= website3Title
a.btn.btn-lg.btn-block.btn-info(href=website3Link, target='_blank')
i.fa.icon-beaker
| Try it out
if (website3Title && website3Link && !website3Image)
.col-xs-12.col-md-12
h3.text-center.wrappable.flat-top= website3Title
a.btn.btn-lg.btn-block.btn-info(href=website3Link, target='_blank')
i.fa.icon-beaker
| Try it out
.spacer .spacer
.hidden-xs.hidden-sm.col-md-12 .hidden-xs.hidden-sm.col-md-12
#cal-heatmap.d3-centered #cal-heatmap.d3-centered
script. script.
$(document).ready(function () { $(document).ready(function () {
setTimeout(function () { var cal = new CalHeatMap();
var cal = new CalHeatMap(); var calendar = !{JSON.stringify(calender)};
var calendar = !{JSON.stringify(calender)}; cal.init({
cal.init({ itemSelector: "#cal-heatmap",
itemSelector: "#cal-heatmap", domain: "month",
domain: "month", subDomain: "x_day",
subDomain: "x_day", domainGutter: 10,
domainGutter: 10, data: calendar,
data: calendar, cellSize: 15,
cellSize: 15, align: 'center',
align: 'center', cellRadius: 3,
cellRadius: 3, cellPadding: 2,
cellPadding: 2, tooltip: true,
tooltip: true, range: 6,
range: 6, start: new Date().setDate(new Date().getDate() - 150),
start: new Date().setDate(new Date().getDate() - 150), legendColors: ["#cccccc", "#215f1e"],
legendColors: ["#cccccc", "#215f1e"], legend: [1, 2, 3],
legend: [1, 2, 3], label: {
label: { position: "top"
position: "top" }
} });
});
}, 300);
}); });
.row .row
.hidden-xs.col-sm-12.text-center .hidden-xs.col-sm-12.text-center