232 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import _ from 'lodash';
 | |
| import { Observable } from 'rx';
 | |
| 
 | |
| import { unDasherize, nameify } from '../utils';
 | |
| import {
 | |
|   addNameIdMap as _addNameIdToMap,
 | |
|   checkMapData,
 | |
|   getFirstChallenge as _getFirstChallenge
 | |
| } from '../../common/utils/map.js';
 | |
| 
 | |
| const isDev = process.env.NODE_ENV !== 'production';
 | |
| const isBeta = !!process.env.BETA;
 | |
| const challengesRegex = /^(bonfire|waypoint|zipline|basejump|checkpoint)/i;
 | |
| const addNameIdMap = _.once(_addNameIdToMap);
 | |
| const getFirstChallenge = _.once(_getFirstChallenge);
 | |
| /*
 | |
|  * interface ChallengeMap {
 | |
|  *   result: {
 | |
|  *     superBlocks: [ ...superBlockDashedName: String ]
 | |
|  *    },
 | |
|  *   entities: {
 | |
|  *     superBlock: {
 | |
|  *       [ ...superBlockDashedName ]: SuperBlock
 | |
|  *     },
 | |
|  *     block: {
 | |
|  *       [ ...blockDashedNameg ]: Block,
 | |
|  *     challenge: {
 | |
|  *       [ ...challengeDashedNameg ]: Challenge
 | |
|  *     }
 | |
|  *   }
 | |
|  * }
 | |
|  */
 | |
| export function _cachedMap({ Block, Challenge }) {
 | |
|   const challenges = Challenge.find$({
 | |
|     order: ['order ASC', 'suborder ASC'],
 | |
|     where: { isPrivate: false }
 | |
|   });
 | |
|   const challengeMap = challenges.map(challenges =>
 | |
|     challenges
 | |
|       .map(challenge => challenge.toJSON())
 | |
|       .reduce((hash, challenge) => {
 | |
|         hash[challenge.dashedName] = challenge;
 | |
|         return hash;
 | |
|       }, {})
 | |
|   );
 | |
|   const blocks = Block.find$({
 | |
|     order: ['superOrder ASC', 'order ASC'],
 | |
|     where: { isPrivate: false }
 | |
|   });
 | |
|   const blockMap = Observable.combineLatest(
 | |
|     blocks.map(blocks =>
 | |
|       blocks
 | |
|         .map(block => block.toJSON())
 | |
|         .reduce((hash, block) => {
 | |
|           hash[block.dashedName] = block;
 | |
|           return hash;
 | |
|         }, {})
 | |
|     ),
 | |
|     challenges
 | |
|   ).map(([blocksMap, challenges]) => {
 | |
|     return challenges.reduce((blocksMap, challenge) => {
 | |
|       if (blocksMap[challenge.block].challenges) {
 | |
|         blocksMap[challenge.block].challenges.push(challenge.dashedName);
 | |
|       } else {
 | |
|         blocksMap[challenge.block] = {
 | |
|           ...blocksMap[challenge.block],
 | |
|           challenges: [challenge.dashedName]
 | |
|         };
 | |
|       }
 | |
|       return blocksMap;
 | |
|     }, blocksMap);
 | |
|   });
 | |
|   const superBlockMap = blocks.map(blocks =>
 | |
|     blocks.reduce((map, block) => {
 | |
|       if (map[block.superBlock] && map[block.superBlock].blocks) {
 | |
|         map[block.superBlock].blocks.push(block.dashedName);
 | |
|       } else {
 | |
|         map[block.superBlock] = {
 | |
|           title: _.startCase(block.superBlock),
 | |
|           order: block.superOrder,
 | |
|           name: nameify(_.startCase(block.superBlock)),
 | |
|           dashedName: block.superBlock,
 | |
|           blocks: [block.dashedName],
 | |
|           message: block.superBlockMessage
 | |
|         };
 | |
|       }
 | |
|       return map;
 | |
|     }, {})
 | |
|   );
 | |
|   const superBlocks = superBlockMap.map(superBlockMap => {
 | |
|     return Object.keys(superBlockMap)
 | |
|       .map(key => superBlockMap[key])
 | |
|       .map(({ dashedName }) => dashedName);
 | |
|   });
 | |
|   return Observable.combineLatest(
 | |
|     superBlockMap,
 | |
|     blockMap,
 | |
|     challengeMap,
 | |
|     superBlocks,
 | |
|     (superBlock, block, challenge, superBlocks) => ({
 | |
|       entities: {
 | |
|         superBlock,
 | |
|         block,
 | |
|         challenge
 | |
|       },
 | |
|       result: {
 | |
|         superBlocks
 | |
|       }
 | |
|     })
 | |
|   )
 | |
|     .do(checkMapData)
 | |
|     .shareReplay();
 | |
| }
 | |
| 
 | |
| export const cachedMap = _.once(_cachedMap);
 | |
| 
 | |
| // type ObjectId: String;
 | |
| // getChallengeById(
 | |
| //   map: Observable[map],
 | |
| //   id: ObjectId
 | |
| // ) => Observable[Challenge] | Void;
 | |
| export function getChallengeById(map, id) {
 | |
|   return Observable.if(
 | |
|     () => !id,
 | |
|     map.map(getFirstChallenge),
 | |
|     map.map(addNameIdMap).map(map => {
 | |
|       const {
 | |
|         entities: { challenge: challengeMap, challengeIdToName }
 | |
|       } = map;
 | |
|       let finalChallenge;
 | |
|       const dashedName = challengeIdToName[id];
 | |
|       finalChallenge = challengeMap[dashedName];
 | |
|       if (!finalChallenge) {
 | |
|         finalChallenge = getFirstChallenge(map);
 | |
|       }
 | |
|       return finalChallenge;
 | |
|     })
 | |
|   );
 | |
| }
 | |
| 
 | |
| export function getChallengeInfo(map) {
 | |
|   return map
 | |
|     .map(addNameIdMap)
 | |
|     .map(({ entities: { challenge: challengeMap, challengeIdToName } }) => ({
 | |
|       challengeMap,
 | |
|       challengeIdToName
 | |
|     }));
 | |
| }
 | |
| 
 | |
| // if challenge is not isComingSoon or isBeta => load
 | |
| // if challenge is ComingSoon 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;
 | |
| }
 | |
| 
 | |
| // this is a hard search
 | |
| // falls back to soft search
 | |
| export function getChallenge(challengeDashedName, blockDashedName, map) {
 | |
|   return map.flatMap(({ entities, result: { superBlocks } }) => {
 | |
|     const superBlock = entities.superBlock;
 | |
|     const block = entities.block[blockDashedName];
 | |
|     const challenge = entities.challenge[challengeDashedName];
 | |
|     return Observable.if(
 | |
|       () =>
 | |
|         !blockDashedName ||
 | |
|         !block ||
 | |
|         !challenge ||
 | |
|         !loadComingSoonOrBetaChallenge(challenge),
 | |
|       getChallengeByDashedName(challengeDashedName, map),
 | |
|       Observable.just({ block, challenge })
 | |
|     ).map(({ challenge, block }) => ({
 | |
|       redirect:
 | |
|         challenge.block !== blockDashedName
 | |
|           ? `/challenges/${block.dashedName}/${challenge.dashedName}`
 | |
|           : false,
 | |
|       entities: {
 | |
|         superBlock,
 | |
|         challenge: {
 | |
|           [challenge.dashedName]: challenge
 | |
|         }
 | |
|       },
 | |
|       result: {
 | |
|         block: block.dashedName,
 | |
|         challenge: challenge.dashedName,
 | |
|         superBlocks
 | |
|       }
 | |
|     }));
 | |
|   });
 | |
| }
 | |
| 
 | |
| export function getBlockForChallenge(map, challenge) {
 | |
|   return map.map(({ entities: { block } }) => block[challenge.block]);
 | |
| }
 | |
| 
 | |
| export function getChallengeByDashedName(dashedName, map) {
 | |
|   const challengeName = unDasherize(dashedName).replace(challengesRegex, '');
 | |
|   const testChallengeName = new RegExp(challengeName, 'i');
 | |
| 
 | |
|   return map
 | |
|     .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 => {
 | |
|       return Observable.if(
 | |
|         () => !!challengeOrNull,
 | |
|         Observable.just(challengeOrNull),
 | |
|         map.map(getFirstChallenge)
 | |
|       );
 | |
|     })
 | |
|     .flatMap(challenge => {
 | |
|       return getBlockForChallenge(map, challenge).map(block => ({
 | |
|         challenge,
 | |
|         block
 | |
|       }));
 | |
|     });
 | |
| }
 |