diff --git a/src/data/achievements.js b/src/data/achievements.js index 1b19c7d88..1e4eb45a0 100644 --- a/src/data/achievements.js +++ b/src/data/achievements.js @@ -2,7 +2,6 @@ import { addItemToInventory } from '../game-logic/reducers/' import { doesPlotContainCrop, dollarString, - findInField, getCropLifeStage, getProfitRecord, integerString, @@ -11,6 +10,7 @@ import { percentageString, } from '../utils' import { memoize } from '../utils/memoize' +import { findInField } from '../utils/findInField' import { cropLifeStage, standardCowColors } from '../enums' import { COW_FEED_ITEM_ID, I_AM_RICH_BONUSES } from '../constants' diff --git a/src/game-logic/reducers/applyCrows.test.js b/src/game-logic/reducers/applyCrows.test.js index aef142e36..80a93f10f 100644 --- a/src/game-logic/reducers/applyCrows.test.js +++ b/src/game-logic/reducers/applyCrows.test.js @@ -1,5 +1,5 @@ -import { findInField } from '../../utils' import { MAX_CROWS, SCARECROW_ITEM_ID } from '../../constants' +import { findInField } from '../../utils/findInField' import { randomNumberService } from '../../common/services/randomNumber' diff --git a/src/game-logic/reducers/helpers.js b/src/game-logic/reducers/helpers.js index 47022f39f..845f6cafc 100644 --- a/src/game-logic/reducers/helpers.js +++ b/src/game-logic/reducers/helpers.js @@ -1,7 +1,8 @@ import { itemType } from '../../enums' import { SCARECROW_ITEM_ID } from '../../constants' -import { findInField, getPlotContentType } from '../../utils' +import { getPlotContentType } from '../../utils' +import { findInField } from '../../utils/findInField' // This file is designed to contain common logic that is needed across multiple // reducers. diff --git a/src/utils/findInField.js b/src/utils/findInField.js new file mode 100644 index 000000000..7cdeb6943 --- /dev/null +++ b/src/utils/findInField.js @@ -0,0 +1,26 @@ +/** @typedef {import("../index").farmhand.plotContent} farmhand.plotContent */ +import { memoize } from './memoize' + +import { memoizationSerializer } from './' + +export const findInField = memoize( + /** + * @param {(?farmhand.plotContent)[][]} field + * @param {function(?farmhand.plotContent): boolean} condition + * @returns {?farmhand.plotContent} + */ + (field, condition) => { + for (const row of field) { + for (const plot of row) { + if (condition(plot)) { + return plot + } + } + } + + return null + }, + { + serializer: memoizationSerializer, + } +) diff --git a/src/utils/findInField.test.js b/src/utils/findInField.test.js new file mode 100644 index 000000000..2bab29cdb --- /dev/null +++ b/src/utils/findInField.test.js @@ -0,0 +1,33 @@ +/** + * @typedef {import("../components/Farmhand/Farmhand").farmhand.state['field']} farmhand.state.field + */ + +import { carrot, pumpkin } from '../data/crops' + +import { findInField } from './findInField' + +const carrotPlot = { + itemId: carrot.id, + fertilizerType: 'NONE', +} + +describe('findInField', () => { + /** @type farmhand.state.field} */ + const field = [[null, carrotPlot, null]] + + test('returns the desired plot from the field', () => { + const foundPlot = findInField(field, plot => { + return plot?.itemId === carrot.id + }) + + expect(foundPlot).toEqual(carrotPlot) + }) + + test('yields null if desired plot is not in the field', () => { + const foundPlot = findInField(field, plot => { + return plot?.itemId === pumpkin.id + }) + + expect(foundPlot).toEqual(null) + }) +}) diff --git a/src/utils/index.js b/src/utils/index.js index 8fa17ebbb..ed7d3e570 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -138,7 +138,7 @@ export const chooseRandom = list => list[chooseRandomIndex(list)] * accept function arguments. * @param {any[]} args */ -const memoizationSerializer = args => +export const memoizationSerializer = args => JSON.stringify( [...args].map(arg => (typeof arg === 'function' ? arg.toString() : arg)) ) @@ -714,25 +714,6 @@ export const getPriceEventForCrop = cropItem => ({ getCropLifecycleDuration(cropItem) - PRICE_EVENT_STANDARD_DURATION_DECREASE, }) -export const findInField = memoize( - /** - * @param {(?farmhand.plotContent)[][]} field - * @param {function(?farmhand.plotContent): boolean} condition - * @returns {?farmhand.plotContent} - */ - (field, condition) => { - const [plot = null] = - field.find(row => { - return row.find(condition) - }) ?? [] - - return plot - }, - { - serializer: memoizationSerializer, - } -) - export const doesMenuObstructStage = () => window.innerWidth < BREAKPOINTS.MD const itemTypesToShowInReverse = new Set([itemType.MILK])