diff --git a/website/common/script/content/constants/schedule.js b/website/common/script/content/constants/schedule.js index c7bf10fa69..1347ebcf8f 100644 --- a/website/common/script/content/constants/schedule.js +++ b/website/common/script/content/constants/schedule.js @@ -1,4 +1,5 @@ import moment from 'moment'; +import SEASONAL_SETS from './seasonalSets'; function backgroundMatcher (month1, month2, oddYear) { return function call (key) { @@ -601,13 +602,34 @@ export const MONTHLY_SCHEDULE = { export const GALA_SWITCHOVER_DAY = 21; export const GALA_SCHEDULE = { - 0: [], - 1: [], - 2: [], - 3: [], + 0: [ + { + type: 'seasonalGear', + matcher: inListMatcher(SEASONAL_SETS.winter), + }, + ], + 1: [ + { + type: 'seasonalGear', + matcher: inListMatcher(SEASONAL_SETS.spring), + }, + ], + 2: [ + { + type: 'seasonalGear', + matcher: inListMatcher(SEASONAL_SETS.fall), + }, + ], + 3: [ + { + type: 'seasonalGear', + matcher: inListMatcher(SEASONAL_SETS.summer), + }, + ], }; export function assembleScheduledMatchers (date) { + console.log('Assembling new Schedule!'); const items = []; const month = date instanceof moment ? date.month() : date.getMonth(); const todayDay = date instanceof moment ? date.date() : date.getDate(); @@ -630,3 +652,24 @@ export function assembleScheduledMatchers (date) { items.push(...GALA_SCHEDULE[parseInt((galaCount / 12) * galaMonth, 10)]); return items; } + +let cachedScheduleMatchers = null; + +export function getScheduleMatchingGroup (type, date) { + if (!cachedScheduleMatchers) { + cachedScheduleMatchers = {}; + assembleScheduledMatchers(date !== undefined ? date : new Date()).forEach(matcher => { + if (cachedScheduleMatchers[matcher.type]) { + cachedScheduleMatchers[matcher.type].matchers.push(matcher.matcher); + } else { + cachedScheduleMatchers[matcher.type] = { + matchers: [matcher.matcher], + match (key) { + return this.matchers.every(m => m(key)); + }, + }; + } + }); + } + return cachedScheduleMatchers[type]; +} diff --git a/website/common/script/content/index.js b/website/common/script/content/index.js index 3dae798ddb..2d1793ab7f 100644 --- a/website/common/script/content/index.js +++ b/website/common/script/content/index.js @@ -33,7 +33,7 @@ import gemsBlock from './gems'; import faq from './faq'; import timeTravelers from './time-travelers'; -import { assembleScheduledMatchers } from './constants/schedule'; +import { getScheduleMatchingGroup } from './constants/schedule'; import loginIncentives from './loginIncentives'; @@ -730,6 +730,6 @@ api.faq = faq; api.loginIncentives = loginIncentives(api); -api.assembleScheduledMatchers = assembleScheduledMatchers; +api.getScheduleMatchingGroup = getScheduleMatchingGroup; export default api; diff --git a/website/common/script/content/time-travelers.js b/website/common/script/content/time-travelers.js index cc717dbd46..2af2aaadbc 100644 --- a/website/common/script/content/time-travelers.js +++ b/website/common/script/content/time-travelers.js @@ -7,7 +7,7 @@ import moment from 'moment'; import mysterySets from './mystery-sets'; import gear from './gear'; -import { assembleScheduledMatchers } from './constants/schedule'; +import { getScheduleMatchingGroup } from './constants/schedule'; const mystery = mysterySets; @@ -19,7 +19,7 @@ each(mystery, (v, k) => { }); const timeTravelerStore = (user, date) => { - const availabilityMatchers = assembleScheduledMatchers(date).filter(matcher => matcher.type === 'timeTravelers').map(matcher => matcher.matcher); + const availabilityMatchers = getScheduleMatchingGroup('timeTravelers', date); let ownedKeys; const { owned } = user.items.gear; const { mysteryItems } = user.purchased.plan; @@ -31,7 +31,7 @@ const timeTravelerStore = (user, date) => { k !== 'wondercon' && ownedKeys.indexOf(v.items[0].key) === -1 && (moment(k).isAfter('3000-01-01') - || availabilityMatchers.map(matcher => matcher(k)).every(matcher => matcher === true)) + || availabilityMatchers.match(k)) ) { m[k] = v; } diff --git a/website/common/script/libs/shops.js b/website/common/script/libs/shops.js index aea59c3894..1dc5c0e9f8 100644 --- a/website/common/script/libs/shops.js +++ b/website/common/script/libs/shops.js @@ -17,7 +17,7 @@ import featuredItems from '../content/shop-featuredItems'; import getOfficialPinnedItems from './getOfficialPinnedItems'; import { getClassName } from './getClassName'; -import { assembleScheduledMatchers } from '../content/constants/schedule'; +import { getScheduleMatchingGroup } from '../content/constants/schedule'; const shops = {}; @@ -71,10 +71,10 @@ shops.getMarketCategories = function getMarket (user, language) { text: i18n.t('magicHatchingPotions', language), notes: i18n.t('premiumPotionNoDropExplanation', language), }; - const matchers = assembleScheduledMatchers(new Date()).filter(matcher => matcher.type === 'premiumHatchingPotions').map(matcher => matcher.matcher); + const matchers = getScheduleMatchingGroup('premiumHatchingPotions'); premiumHatchingPotionsCategory.items = sortBy(values(content.hatchingPotions) .filter(hp => hp.limited - && matchers.map(matcher => matcher(hp.key)).every(matcher => matcher === true)) + && matchers.match(hp.key)) .map(premiumHatchingPotion => getItemInfo(user, 'premiumHatchingPotion', premiumHatchingPotion, officialPinnedItems, language)), 'key'); if (premiumHatchingPotionsCategory.items.length > 0) { categories.push(premiumHatchingPotionsCategory); @@ -267,18 +267,16 @@ shops.getQuestShopCategories = function getQuestShopCategories (user, language) * ] * */ - const scheduledMatchers = assembleScheduledMatchers(new Date()); const bundleCategory = { identifier: 'bundle', text: i18n.t('questBundles', language), }; - const bundleMatchers = scheduledMatchers.filter(matcher => matcher.type === 'bundles').map(matcher => matcher.matcher); - console.log(bundleMatchers); + const bundleMatchers = getScheduleMatchingGroup('bundles'); bundleCategory.items = sortBy(values(content.bundles) .filter(bundle => bundle.type === 'quests' - && bundleMatchers.map(matcher => matcher(bundle.key)).every(matcher => matcher === true)) + && bundleMatchers.match(bundle.key)) .map(bundle => getItemInfo(user, 'bundles', bundle, officialPinnedItems, language))); if (bundleCategory.items.length > 0) { @@ -295,10 +293,8 @@ shops.getQuestShopCategories = function getQuestShopCategories (user, language) .filter(quest => quest.canBuy(user) && quest.category === type); if (type === 'pet' || type === 'hatchingPotion') { - const matchers = scheduledMatchers - .filter(matcher => matcher.type === `${type}Quests`).map(matcher => matcher.matcher); - filteredQuests = filteredQuests.filter(quest => matchers.map(matcher => matcher(quest.key)) - .every(matcher => matcher === true)); + const matchers = getScheduleMatchingGroup(`${type}Quests`); + filteredQuests = filteredQuests.filter(quest => matchers.match(quest.key)); } category.items = filteredQuests.map(quest => getItemInfo(user, 'quests', quest, officialPinnedItems, language)); @@ -544,9 +540,9 @@ shops.getBackgroundShopSets = function getBackgroundShopSets (language) { const sets = []; const officialPinnedItems = getOfficialPinnedItems(); - const matchers = assembleScheduledMatchers(new Date()).filter(matcher => matcher.type === 'backgrounds').map(matcher => matcher.matcher); + const matchers = getScheduleMatchingGroup('backgrounds'); eachRight(content.backgrounds, (group, key) => { - if (matchers.map(matcher => matcher(key)).every(matcher => matcher === true)) { + if (matchers.match(key)) { const set = { identifier: key, text: i18n.t(key, language), diff --git a/website/common/script/ops/buy/buyQuestGem.js b/website/common/script/ops/buy/buyQuestGem.js index 392b8b5ebd..dbc5c100cf 100644 --- a/website/common/script/ops/buy/buyQuestGem.js +++ b/website/common/script/ops/buy/buyQuestGem.js @@ -8,7 +8,7 @@ import content from '../../content/index'; import { errorMessage } from '../../libs/errorMessage'; import { AbstractGemItemOperation } from './abstractBuyOperation'; -import { assembleScheduledMatchers } from '../../content/constants/schedule'; +import { getScheduleMatchingGroup } from '../../content/constants/schedule'; export class BuyQuestWithGemOperation extends AbstractGemItemOperation { // eslint-disable-line import/prefer-default-export, max-len multiplePurchaseAllowed () { // eslint-disable-line class-methods-use-this @@ -52,9 +52,8 @@ export class BuyQuestWithGemOperation extends AbstractGemItemOperation { // esli } } - const matchers = assembleScheduledMatchers(new Date()).filter(matcher => matcher.type === `${item.category}Quests`).map(matcher => matcher.matcher); - console.log(item, matchers); - if (matchers.length && !matchers.some(matcher => matcher(item.key))) { + const matchers = getScheduleMatchingGroup(`${item.category}Quests`); + if (matchers.match(item.key)) { throw new NotAuthorized(this.i18n('notAvailable', { key: item.key })); } diff --git a/website/common/script/ops/buy/purchase.js b/website/common/script/ops/buy/purchase.js index c1989e33f6..e28f64c3b3 100644 --- a/website/common/script/ops/buy/purchase.js +++ b/website/common/script/ops/buy/purchase.js @@ -13,7 +13,7 @@ import { import { removeItemByPath } from '../pinnedGearUtils'; import getItemInfo from '../../libs/getItemInfo'; import updateUserBalance from '../updateUserBalance'; -import { assembleScheduledMatchers } from '../../content/constants/schedule'; +import { getScheduleMatchingGroup } from '../../content/constants/schedule'; function getItemAndPrice (user, type, key, req) { let item; @@ -55,8 +55,8 @@ async function purchaseItem (user, item, price, type, key) { if (user.markModified) user.markModified('items.gear.owned'); } else if (type === 'bundles') { const subType = item.type; - const matchers = assembleScheduledMatchers(new Date()).filter(matcher => matcher.type === 'bundles').map(matcher => matcher.matcher); - if (matchers.length && !matchers.some(matcher => matcher(item.key))) { + const matchers = getScheduleMatchingGroup('bundles'); + if (!matchers.match(item.key)) { throw new NotAuthorized(i18n.t('notAvailable', { key: item.key })); } forEach(item.bundleKeys, bundledKey => { @@ -102,8 +102,8 @@ export default async function purchase (user, req = {}, analytics) { const { price, item } = getItemAndPrice(user, type, key, req); if (item.type === 'hatchingPotion' && item.premium === true) { - const matchers = assembleScheduledMatchers(new Date()).filter(matcher => matcher.type === 'premiumHatchingPotions').map(matcher => matcher.matcher); - if (matchers.length && !matchers.some(matcher => matcher(item.key))) { + const matchers = getScheduleMatchingGroup('premiumHatchingPotions'); + if (!matchers.match(item.key)) { throw new NotAuthorized(i18n.t('messageNotAvailable', req.language)); } } else if (!item.canBuy(user)) { diff --git a/website/common/script/ops/unlock.js b/website/common/script/ops/unlock.js index 3cc4b4cf01..a5b0b89cad 100644 --- a/website/common/script/ops/unlock.js +++ b/website/common/script/ops/unlock.js @@ -7,7 +7,7 @@ import { removeItemByPath } from './pinnedGearUtils'; import getItemInfo from '../libs/getItemInfo'; import content from '../content/index'; import updateUserBalance from './updateUserBalance'; -import { assembleScheduledMatchers } from '../content/constants/schedule'; +import { getScheduleMatchingGroup } from '../content/constants/schedule'; const incentiveBackgrounds = ['blue', 'green', 'red', 'purple', 'yellow']; @@ -225,12 +225,8 @@ export default async function unlock (user, req = {}, analytics) { const { set, items, paths } = getSet(setType, firstPath, req); if (isBackground) { - const matchers = assembleScheduledMatchers(new Date()) - .filter(matcher => matcher.type === 'backgrounds') - .map(matcher => matcher.matcher); - const isAvailable = matchers.map(matcher => matcher(set.key)) - .every(matcher => matcher === true); - if (!isAvailable) { + const matchers = getScheduleMatchingGroup('backgrounds'); + if (!matchers.match(set.key)) { throw new NotAuthorized(i18n.t('notAvailable', req.language)); } }