feat(challenge): Initial build of the challenge service

This commit is contained in:
Stuart Taylor
2018-02-23 12:20:13 +00:00
committed by Stuart Taylor
parent d17c2d33eb
commit a7587ed6f0
14 changed files with 263 additions and 83 deletions

View File

@@ -2,14 +2,19 @@ import Fetchr from 'fetchr';
import getUserServices from '../services/user';
import getMapServices from '../services/map';
import getMapUiServices from '../services/mapUi';
import getChallengesForBlockService from '../services/challenge';
export default function bootServices(app) {
const userServices = getUserServices(app);
const mapServices = getMapServices(app);
const mapUiServices = getMapUiServices(app);
Fetchr.registerFetcher(userServices);
Fetchr.registerFetcher(mapServices);
Fetchr.registerFetcher(mapUiServices);
const user = getUserServices(app);
const map = getMapServices(app);
const mapUi = getMapUiServices(app);
const challenge = getChallengesForBlockService(app);
Fetchr.registerFetcher(user);
Fetchr.registerFetcher(map);
Fetchr.registerFetcher(mapUi);
Fetchr.registerFetcher(challenge);
app.use('/services', Fetchr.middleware());
}

View File

@@ -0,0 +1,53 @@
import debug from 'debug';
import { pickBy } from 'lodash';
import { Observable } from 'rx';
import { cachedMap, getMapForLang } from '../utils/map';
import { shapeChallenges } from '../../common/app/redux/utils';
const log = debug('fcc:services:challenge');
const isDev = debug.enabled('fcc:*');
export default function getChallengesForBlock(app) {
const challengeMap = cachedMap(app.models);
return {
name: 'challenges-for-block',
read: function readChallengesForBlock(
req,
resource,
{ blockName, lang = 'en' } = {},
config,
cb
) {
log(`sourcing challenges for the ${blockName} block`);
return challengeMap.map(getMapForLang(lang))
.flatMap(({
result: { superBlocks },
entities: {
block: fullBlockMap,
challenge: challengeMap
}
}) => {
const requestedChallenges = pickBy(
challengeMap,
ch => ch.block === blockName
);
const entities = {
block: {
[blockName]: fullBlockMap[blockName]
},
challenge: requestedChallenges
};
const { challenge, block } = shapeChallenges(entities, isDev);
return Observable.of({
result: { superBlocks },
entities: { challenge, block }
});
})
.subscribe(
result => cb(null, result),
cb
);
}
};
}

View File

@@ -5,12 +5,18 @@ import { cachedMap, getMapForLang } from '../utils/map';
const log = debug('fcc:services:mapUi');
export default function mapUiService(app) {
const supportedLangMap = {};
const challengeMap = cachedMap(app.models);
return {
name: 'map-ui',
read: function readMapUi(req, resource, { lang = 'en' } = {}, config, cb) {
log(`generating mapUi for ${lang}`);
if (lang in supportedLangMap) {
log(`using cache for ${lang} map`);
return cb(null, supportedLangMap[lang]);
}
return challengeMap.map(getMapForLang(lang))
.flatMap(({
result: { superBlocks },
@@ -34,19 +40,39 @@ export default function mapUiService(app) {
}, {});
const challengeMap = Object.keys(fullChallengeMap)
.map(challenge => fullChallengeMap[challenge])
.reduce((map, { dashedName, name, id}) => {
map[dashedName] = {name, dashedName, id};
.reduce((map, challenge) => {
const {
dashedName,
id,
title,
name,
block,
isLocked,
isComingSoon,
isBeta
} = challenge;
map[dashedName] = {
dashedName,
id,
title,
name,
block,
isLocked,
isComingSoon,
isBeta
};
return map;
}, {});
return Observable.of({
const mapUi = {
result: { superBlocks },
entities: {
superBlock: superBlockMap,
block: blockMap,
challenge: challengeMap
}
});
};
supportedLangMap[lang] = mapUi;
return Observable.of(mapUi);
}).subscribe(
mapUi => cb(null, mapUi ),
err => { log(err); return cb(err); }

View File

@@ -154,6 +154,58 @@ export function getMapForLang(lang) {
};
}
export function generateMapForLang(
superBlocks,
fullSuperBlockMap,
fullBlockMap,
fullChallengeMap
) {
const superBlockMap = superBlocks
.map(superBlock => fullSuperBlockMap[superBlock])
.reduce((map, { dashedName, blocks, title }) => {
map[dashedName] = { blocks, title, dashedName};
return map;
}, {});
const blockMap = Object.keys(fullBlockMap)
.map(block => fullBlockMap[block])
.reduce((map, { dashedName, title, time, challenges }) => {
map[dashedName] = { dashedName, title, time, challenges };
return map;
}, {});
const challengeMap = Object.keys(fullChallengeMap)
.map(challenge => fullChallengeMap[challenge])
.reduce((map, challenge) => {
const {
dashedName,
id,
title,
block,
isLocked,
isComingSoon,
isBeta
} = challenge;
map[dashedName] = {
dashedName,
id,
title,
block,
isLocked,
isComingSoon,
isBeta
};
return map;
}, {});
return {
result: { superBlocks },
entities: {
superBlock: superBlockMap,
block: blockMap,
challenge: challengeMap
}
};
}
// type ObjectId: String;
// getChallengeById(
// map: Observable[map],