134 lines
3.8 KiB
JavaScript
134 lines
3.8 KiB
JavaScript
import { Observable } from 'rx';
|
|
import debug from 'debug';
|
|
import { unDasherize } from '../utils';
|
|
import { mapChallengeToLang, cachedMap, getMapForLang } from '../utils/map';
|
|
|
|
const isDev = process.env.NODE_ENV !== 'production';
|
|
const isBeta = !!process.env.BETA;
|
|
const challengesRegex = /^(bonfire|waypoint|zipline|basejump|checkpoint)/i;
|
|
const log = debug('fcc:services:map');
|
|
|
|
// if challenge is not isComingSoon or isBeta => load
|
|
// if challenge is commingSoon we are in beta||dev => load
|
|
// if challenge is beta and we are in beta||dev => load
|
|
// else hide
|
|
function loadComingSoonOrBetaChallenge({
|
|
isComingSoon,
|
|
isBeta: challengeIsBeta
|
|
}) {
|
|
return !(isComingSoon || challengeIsBeta) || isDev || isBeta;
|
|
}
|
|
|
|
function getFirstChallenge(challengeMap$) {
|
|
return challengeMap$
|
|
.map(({ entities: { superBlock, block, challenge }, result }) => {
|
|
return challenge[
|
|
block[
|
|
superBlock[
|
|
result[0]
|
|
].blocks[0]
|
|
].challenges[0]
|
|
];
|
|
});
|
|
}
|
|
|
|
// this is a hard search
|
|
// falls back to soft search
|
|
function getChallengeAndBlock(
|
|
challengeDashedName,
|
|
blockDashedName,
|
|
challengeMap$,
|
|
lang
|
|
) {
|
|
return challengeMap$
|
|
.flatMap(({ entities }) => {
|
|
const block = entities.block[blockDashedName];
|
|
const challenge = entities.challenge[challengeDashedName];
|
|
if (
|
|
!block ||
|
|
!challenge ||
|
|
!loadComingSoonOrBetaChallenge(challenge)
|
|
) {
|
|
return getChallengeByDashedName(
|
|
challengeDashedName,
|
|
challengeMap$,
|
|
lang
|
|
);
|
|
}
|
|
return Observable.just({
|
|
redirect: block.dashedName !== blockDashedName ?
|
|
`/challenges/${block.dashedName}/${challenge.dashedName}` :
|
|
false,
|
|
entities: {
|
|
challenge: {
|
|
[challenge.dashedName]: mapChallengeToLang(challenge, lang)
|
|
}
|
|
},
|
|
result: {
|
|
block: block.dashedName,
|
|
challenge: challenge.dashedName
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function getChallengeByDashedName(dashedName, challengeMap$, lang) {
|
|
const challengeName = unDasherize(dashedName)
|
|
.replace(challengesRegex, '');
|
|
const testChallengeName = new RegExp(challengeName, 'i');
|
|
log('looking for %s', testChallengeName);
|
|
|
|
return challengeMap$
|
|
.map(({ entities }) => entities.challenge)
|
|
.flatMap(challengeMap => {
|
|
return Observable.from(Object.keys(challengeMap))
|
|
.map(key => challengeMap[key]);
|
|
})
|
|
.filter(challenge => {
|
|
return loadComingSoonOrBetaChallenge(challenge) &&
|
|
testChallengeName.test(challenge.name);
|
|
})
|
|
.last({ defaultValue: null })
|
|
.flatMap(challengeOrNull => {
|
|
if (challengeOrNull) {
|
|
return Observable.just(challengeOrNull);
|
|
}
|
|
return getFirstChallenge(challengeMap$);
|
|
})
|
|
.map(challenge => ({
|
|
redirect:
|
|
`/challenges/${challenge.block}/${challenge.dashedName}`,
|
|
entities: {
|
|
challenge: {
|
|
[challenge.dashedName]: mapChallengeToLang(challenge, lang)
|
|
}
|
|
},
|
|
result: {
|
|
challenge: challenge.dashedName,
|
|
block: challenge.block
|
|
}
|
|
}));
|
|
}
|
|
|
|
export default function mapService(app) {
|
|
const Block = app.models.Block;
|
|
const challengeMap$ = cachedMap(Block);
|
|
return {
|
|
name: 'map',
|
|
read: (req, resource, { lang, block, dashedName } = {}, config, cb) => {
|
|
log(`${lang} language requested`);
|
|
if (block && dashedName) {
|
|
return getChallengeAndBlock(dashedName, block, challengeMap$, lang)
|
|
.subscribe(challenge => cb(null, challenge), cb);
|
|
}
|
|
if (dashedName) {
|
|
return getChallengeByDashedName(dashedName, challengeMap$, lang)
|
|
.subscribe(challenge => cb(null, challenge), cb);
|
|
}
|
|
return challengeMap$
|
|
.map(getMapForLang(lang))
|
|
.subscribe(map => cb(null, map), cb);
|
|
}
|
|
};
|
|
}
|