refactor challenges

now only queries challenges on start up
use default scheduler for array manipulation
This commit is contained in:
Berkeley Martinez
2015-08-19 23:11:21 -07:00
parent 6d1d8a3e28
commit eaca9ef495

View File

@@ -1,6 +1,6 @@
import _ from 'lodash'; import _ from 'lodash';
import moment from 'moment'; import moment from 'moment';
import { Observable } from 'rx'; import { Observable, Scheduler } from 'rx';
import assign from 'object.assign'; import assign from 'object.assign';
import debugFactory from 'debug'; import debugFactory from 'debug';
import utils from '../utils'; import utils from '../utils';
@@ -18,11 +18,16 @@ import {
} from '../utils/middleware'; } from '../utils/middleware';
const debug = debugFactory('freecc:challenges'); const debug = debugFactory('freecc:challenges');
const challengeMapWithNames = utils.getChallengeMapWithNames();
const challengeMapWithIds = utils.getChallengeMapWithIds();
const challengeMapWithDashedNames = utils.getChallengeMapWithDashedNames();
const challengesRegex = /^(bonfire|waypoint|zipline|basejump)/i; const challengesRegex = /^(bonfire|waypoint|zipline|basejump)/i;
const firstChallenge = 'waypoint-say-hello-to-html-elements'; const firstChallenge = 'waypoint-say-hello-to-html-elements';
const challengeView = {
0: 'coursewares/showHTML',
1: 'coursewares/showJS',
2: 'coursewares/showVideo',
3: 'coursewares/showZiplineOrBasejump',
4: 'coursewares/showZiplineOrBasejump',
5: 'coursewares/showBonfire'
};
const dasherize = utils.dasherize; const dasherize = utils.dasherize;
const unDasherize = utils.unDasherize; const unDasherize = utils.unDasherize;
@@ -64,7 +69,12 @@ module.exports = function(app) {
// create a stream of all the challenges // create a stream of all the challenges
const challenge$ = findChallenge$(challengesQuery) const challenge$ = findChallenge$(challengesQuery)
.doOnNext(() => debug('query challenges')) .doOnNext(() => debug('query challenges'))
.flatMap(challenges => Observable.from(challenges)) .flatMap(challenges => Observable.from(
challenges,
null,
null,
Scheduler.default
))
.shareReplay(); .shareReplay();
// create a stream of challenge blocks // create a stream of challenge blocks
@@ -162,7 +172,12 @@ module.exports = function(app) {
.elementAt(blockIndex) .elementAt(blockIndex)
.flatMap(block => { .flatMap(block => {
// find where our challenge lies in the block // find where our challenge lies in the block
const challengeIndex$ = Observable.from(block.challenges) const challengeIndex$ = Observable.from(
block.challenges,
null,
null,
Scheduler.default
)
.findIndex(({ id }) => id === challengeId); .findIndex(({ id }) => id === challengeId);
// grab next challenge in this block // grab next challenge in this block
@@ -201,44 +216,53 @@ module.exports = function(app) {
res.redirect('/challenges/' + nextChallengeName); res.redirect('/challenges/' + nextChallengeName);
} }
); );
} }
function returnCurrentChallenge(req, res, next) { function returnCurrentChallenge(req, res, next) {
Observable.just(req.user)
.flatMap(user => {
if (!req.user.currentChallenge) { if (!req.user.currentChallenge) {
req.user.currentChallenge = {}; return challenge$
req.user.currentChallenge.challengeId = challengeMapWithIds['0'][0]; .first()
req.user.currentChallenge.challengeName = challengeMapWithNames['0'][0]; .flatMap(challenge => {
req.user.currentChallenge.dashedName = user.currentChallenge = {
challengeMapWithDashedNames['0'][0]; challengeId: challenge.id,
challengeName: challenge.name,
dashedName: challenge.dashedName
};
return saveUser(user);
});
} }
return Observable.just(user);
var nameString = req.user.currentChallenge.dashedName; })
.map(user => user.currentChallenge.dashedName)
saveUser(req.user)
.subscribe( .subscribe(
function() {}, function(challengeName) {
res.redirect('/challenges/' + challengeName);
},
next, next,
function() { function() {
res.redirect('/challenges/' + nameString);
} }
); );
} }
function returnIndividualChallenge(req, res, next) { function returnIndividualChallenge(req, res, next) {
var origChallengeName = req.params.challengeName; const origChallengeName = req.params.challengeName;
var unDashedName = unDasherize(origChallengeName); const unDashedName = unDasherize(origChallengeName);
var challengeName = challengesRegex.test(unDashedName) ? const challengeName = challengesRegex.test(unDashedName) ?
// remove first word if matches // remove first word if matches
unDashedName.split(' ').slice(1).join(' ') : unDashedName.split(' ').slice(1).join(' ') :
unDashedName; unDashedName;
debug('looking for ', challengeName); const testChallengeName = new RegExp(challengeName, 'i');
Challenge.findOne( debug('looking for %s', testChallengeName);
{ where: { name: { like: challengeName, options: 'i' } } }, challenge$
function(err, challenge) { .filter((challenge) => {
if (err) { return next(err); } return testChallengeName.test(challenge.name);
})
.lastOrDefault(null)
.flatMap(challenge => {
// Handle not found // Handle not found
if (!challenge) { if (!challenge) {
@@ -249,14 +273,14 @@ module.exports = function(app) {
origChallengeName + origChallengeName +
'` Please double check the name.' '` Please double check the name.'
}); });
return res.redirect('/challenges'); return Observable.just('/challenges');
}
// Redirect to full name if the user only entered a partial
if (dasherize(challenge.name) !== origChallengeName) {
debug('redirecting to fullname');
return res.redirect('/challenges/' + dasherize(challenge.name));
} }
if (dasherize(challenge.name) !== origChallengeName) {
return Observable.just('/challenges/' + dasherize(challenge.name));
}
if (challenge) {
if (req.user) { if (req.user) {
req.user.currentChallenge = { req.user.currentChallenge = {
challengeId: challenge.id, challengeId: challenge.id,
@@ -265,7 +289,9 @@ module.exports = function(app) {
}; };
} }
var commonLocals = { // save user does nothing if user does not exist
return saveUser(req.user)
.map(() => ({
title: challenge.name, title: challenge.name,
dashedName: origChallengeName, dashedName: origChallengeName,
name: challenge.name, name: challenge.name,
@@ -286,28 +312,21 @@ module.exports = function(app) {
MDNlinks: getMDNLinks(challenge.MDNlinks), MDNlinks: getMDNLinks(challenge.MDNlinks),
// htmls specific // htmls specific
environment: utils.whichEnvironment() environment: utils.whichEnvironment()
}; }));
// TODO Berkeley
var challengeView = {
0: 'coursewares/showHTML',
1: 'coursewares/showJS',
2: 'coursewares/showVideo',
3: 'coursewares/showZiplineOrBasejump',
4: 'coursewares/showZiplineOrBasejump',
5: 'coursewares/showBonfire'
};
saveUser(req.user)
.subscribe(
function() {},
next,
function() {
var view = challengeView[challenge.challengeType];
res.render(view, commonLocals);
} }
})
.subscribe(
function(data) {
if (typeof data === 'string') {
debug('redirecting to %s', data);
return res.redirect(data);
}
var view = challengeView[data.challengeType];
res.render(view, data);
},
next,
function() {}
); );
});
} }
function completedBonfire(req, res, next) { function completedBonfire(req, res, next) {
@@ -359,7 +378,7 @@ module.exports = function(app) {
challengeData challengeData
); );
}) })
// not iterate users // iterate users
.flatMap(function(dats) { .flatMap(function(dats) {
debug('flatmap'); debug('flatmap');
return Observable.from([dats.user, dats.pairedWith]); return Observable.from([dats.user, dats.pairedWith]);