Skip to content

Commit

Permalink
Merge patch commit
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed Sep 10, 2023
2 parents 91a9c63 + 15ca44e commit ff19d4d
Show file tree
Hide file tree
Showing 21 changed files with 228 additions and 37 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jeremyckahn/farmhand",
"version": "1.18.0",
"version": "1.18.1",
"publishConfig": {
"access": "public"
},
Expand Down
8 changes: 5 additions & 3 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,20 +260,22 @@ export const KEG_SPOILAGE_RATE_MULTIPLIER = 0.001
// NOTE: not all of these are implemented yet, these are for all the currently
// planned experience rewards
export const EXPERIENCE_VALUES = {
COMPOSTER_ACQUIRED: 10,
CELLAR_ACQUIRED: 10,
CELLAR_EXPANDED: 5,
COMPOSTER_ACQUIRED: 10,
COW_BRED: 1,
COW_PEN_ACQUIRED: 10,
COW_PEN_EXPANDED: 5,
COW_TRADED: 1,
FERMENTATION_RECIPE_MADE: 1,
FIELD_EXPANDED: 5,
ITEM_FORGED: 3,
FORGE_RECIPE_MADE: 3,
ITEM_SOLD: 1,
KEG_SOLD: 2,
KITCHEN_RECIPE_MADE: 2,
LOAN_PAID_OFF: 25,
NEW_YEAR: 5,
RAINBOW_COW_BRED: 2,
RECIPE_CRAFTED: 2,
RECYCLING_RECIPE_MADE: 1,
SMELTER_ACQUIRED: 10,
}
16 changes: 13 additions & 3 deletions src/game-logic/reducers/computeStateForNextDay.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { generateCow } from '../../utils'
import { generateValueAdjustments } from '../../common/utils'
import { EXPERIENCE_VALUES } from '../../constants'

import { addExperience } from './addExperience'
import { applyLoanInterest } from './applyLoanInterest'
import { computeCowInventoryForNextDay } from './computeCowInventoryForNextDay'
import { generatePriceEvents } from './generatePriceEvents'
Expand Down Expand Up @@ -36,8 +38,8 @@ const adjustItemValues = state => ({
* @param {farmhand.state} state
* @returns {farmhand.state}
*/
export const computeStateForNextDay = (state, isFirstDay = false) =>
(isFirstDay
export const computeStateForNextDay = (state, isFirstDay = false) => {
const reducers = isFirstDay
? [processField]
: [
computeCowInventoryForNextDay,
Expand All @@ -58,11 +60,19 @@ export const computeStateForNextDay = (state, isFirstDay = false) =>
applyLoanInterest,
rotateNotificationLogs,
]
)

state = reducers
.concat([adjustItemValues])
.reduce((acc, fn) => fn({ ...acc }), {
...state,
cowForSale: generateCow(),
dayCount: state.dayCount + 1,
todaysNotifications: [],
})

if (state.dayCount % 365 === 0) {
state = addExperience(state, EXPERIENCE_VALUES.NEW_YEAR)
}

return state
}
50 changes: 40 additions & 10 deletions src/game-logic/reducers/computeStateForNextDay.test.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
import { shapeOf, testCrop } from '../../test-utils'
import { generateCow } from '../../utils'
import { EXPERIENCE_VALUES } from '../../constants'

import { computeStateForNextDay } from './computeStateForNextDay'

jest.mock('../../data/maps')

describe('computeStateForNextDay', () => {
let state

beforeEach(() => {
jest.spyOn(Math, 'random').mockReturnValue(0.75)
})

test('computes state for next day', () => {
const {
cowForSale,
dayCount,
field: [firstRow],
valueAdjustments,
todaysNotifications,
} = computeStateForNextDay({
state = {
cowBreedingPen: { cowId1: null, cowId2: null, daysUntilBirth: -1 },
dayCount: 1,
field: [
Expand All @@ -30,6 +25,7 @@ describe('computeStateForNextDay', () => {
],
cellarInventory: [],
cowInventory: [],
experience: 0,
historicalDailyLosses: [],
historicalDailyRevenue: [],
inventory: [],
Expand All @@ -43,7 +39,17 @@ describe('computeStateForNextDay', () => {
record7dayProfitAverage: 0,
recordProfitabilityStreak: 0,
todaysNotifications: [{ message: 'some message', severity: 'info' }],
})
}
})

test('computes state for next day', () => {
const {
cowForSale,
dayCount,
field: [firstRow],
valueAdjustments,
todaysNotifications,
} = computeStateForNextDay(state)

expect(shapeOf(cowForSale)).toEqual(shapeOf(generateCow()))
expect(dayCount).toEqual(2)
Expand All @@ -54,4 +60,28 @@ describe('computeStateForNextDay', () => {
expect(firstRow[0].daysOld).toBe(1)
expect(todaysNotifications).toBeEmpty()
})

describe('new year experience', () => {
const ONE_YEAR = 365

test.each([1, 5, 100, 363, 365, 730])(
'it does not add any experience on day %s',
dayCount => {
const { experience } = computeStateForNextDay({ ...state, dayCount })

expect(experience).toEqual(0)
}
)

test.each([
ONE_YEAR - 1,
ONE_YEAR * 2 - 1,
ONE_YEAR * 3 - 1,
ONE_YEAR * 4 - 1,
])('it adds experience on day %s', dayCount => {
const { experience } = computeStateForNextDay({ ...state, dayCount })

expect(experience).toEqual(EXPERIENCE_VALUES.NEW_YEAR)
})
})
})
14 changes: 14 additions & 0 deletions src/game-logic/reducers/makeRecipe.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { canMakeRecipe } from '../../utils'

import { recipeType } from '../../enums'

import { EXPERIENCE_VALUES } from '../../constants'

import { addItemToInventory } from './addItemToInventory'
import { addExperience } from './addExperience'
import { decrementItemFromInventory } from './decrementItemFromInventory'

const EXPERIENCE_FOR_RECIPE = {
[recipeType.FERMENTATION]: EXPERIENCE_VALUES.FERMENTATION_RECIPE_MADE,
[recipeType.FORGE]: EXPERIENCE_VALUES.FORGE_RECIPE_MADE,
[recipeType.KITCHEN]: EXPERIENCE_VALUES.KITCHEN_RECIPE_MADE,
[recipeType.RECYCLING]: EXPERIENCE_VALUES.RECYCLING_RECIPE_MADE,
}

/**
* @param {farmhand.state} state
* @param {farmhand.recipe} recipe
Expand All @@ -14,6 +26,8 @@ export const makeRecipe = (state, recipe, howMany = 1) => {
return state
}

state = addExperience(state, EXPERIENCE_FOR_RECIPE[recipe.recipeType] || 0)

state = Object.keys(recipe.ingredients).reduce(
(state, ingredientId) =>
decrementItemFromInventory(
Expand Down
29 changes: 28 additions & 1 deletion src/game-logic/reducers/makeRecipe.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { sampleRecipe1 } from '../../data/recipes'

import { INFINITE_STORAGE_LIMIT } from '../../constants'
import { EXPERIENCE_VALUES, INFINITE_STORAGE_LIMIT } from '../../constants'

import { recipeType } from '../../enums'

import { makeRecipe } from './makeRecipe'

Expand Down Expand Up @@ -37,4 +39,29 @@ describe('makeRecipe', () => {
])
})
})

describe('experience', () => {
let state

beforeEach(() => {
state = {
experience: 0,
inventory: [],
}
})

test.each([
[recipeType.FERMENTATION, EXPERIENCE_VALUES.FERMENTATION_RECIPE_MADE],
[recipeType.FORGE, EXPERIENCE_VALUES.FORGE_RECIPE_MADE],
[recipeType.KITCHEN, EXPERIENCE_VALUES.KITCHEN_RECIPE_MADE],
[recipeType.RECYCLING, EXPERIENCE_VALUES.RECYCLING_RECIPE_MADE],
])('adds experience for a %s recipe', (recipeType, experienceValue) => {
const { experience } = makeRecipe(state, {
ingredients: {},
recipeType,
})

expect(experience).toEqual(experienceValue)
})
})
})
14 changes: 13 additions & 1 deletion src/game-logic/reducers/processCowBreeding.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { findCowById, generateOffspringCow } from '../../utils'
import { cowColors } from '../../enums'
import {
EXPERIENCE_VALUES,
COW_GESTATION_PERIOD_DAYS,
COW_MINIMUM_HAPPINESS_TO_BREED,
PURCHASEABLE_COW_PENS,
} from '../../constants'
import { COW_BORN_MESSAGE } from '../../templates'

import { addExperience } from './addExperience'

/**
* @param {farmhand.state} state
* @returns {farmhand.state}
Expand Down Expand Up @@ -43,9 +47,17 @@ export const processCowBreeding = state => {
cowInventory.length < PURCHASEABLE_COW_PENS.get(purchasedCowPen).cows &&
daysUntilBirth === 0

let offspringCow =
const offspringCow =
shouldGenerateOffspring && generateOffspringCow(cow1, cow2, id)

if (offspringCow) {
const experienceGained =
offspringCow.color === cowColors.RAINBOW
? EXPERIENCE_VALUES.RAINBOW_COW_BRED
: EXPERIENCE_VALUES.COW_BRED
state = addExperience(state, experienceGained)
}

return {
...state,
cowInventory: shouldGenerateOffspring
Expand Down
16 changes: 13 additions & 3 deletions src/game-logic/reducers/processCowBreeding.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
EXPERIENCE_VALUES,
COW_GESTATION_PERIOD_DAYS,
PURCHASEABLE_COW_PENS,
} from '../../constants'
Expand Down Expand Up @@ -96,19 +97,28 @@ describe('processCowBreeding', () => {

describe('daysUntilBirth === 1', () => {
describe('there is space in cowInventory', () => {
test('adds offspring cow to cowInventory', () => {
const { cowInventory } = processCowBreeding({
let newState

beforeEach(() => {
newState = processCowBreeding({
cowBreedingPen: {
cowId1: maleCow1.id,
cowId2: femaleCow.id,
daysUntilBirth: 1,
},
cowInventory: [maleCow1, femaleCow],
experience: 0,
newDayNotifications: [],
purchasedCowPen: 1,
})
})

test('adds offspring cow to cowInventory', () => {
expect(newState.cowInventory).toHaveLength(3)
})

expect(cowInventory).toHaveLength(3)
test('adds experience', () => {
expect(newState.experience).toEqual(EXPERIENCE_VALUES.COW_BRED)
})
})

Expand Down
1 change: 1 addition & 0 deletions src/game-logic/reducers/processLevelUp.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ describe('processLevelUp', () => {
itemUnlockLevels: {},
}))
jest.mock('../../constants', () => ({
...jest.requireActual('../../constants'),
INITIAL_SPRINKLER_RANGE: 1,
SPRINKLER_ITEM_ID: 'sprinkler',
}))
Expand Down
9 changes: 8 additions & 1 deletion src/game-logic/reducers/purchaseCellar.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { moneyTotal } from '../../utils'
import { PURCHASEABLE_CELLARS } from '../../constants'
import { EXPERIENCE_VALUES, PURCHASEABLE_CELLARS } from '../../constants'

import { CELLAR_PURCHASED } from '../../templates'

import { addExperience } from './addExperience'
import { showNotification } from './showNotification'

/**
Expand All @@ -21,6 +22,12 @@ export const purchaseCellar = (state, cellarId) => {

state = showNotification(state, CELLAR_PURCHASED`${space}`, 'success')

const experienceEarned =
cellarId > 1
? EXPERIENCE_VALUES.CELLAR_EXPANDED
: EXPERIENCE_VALUES.CELLAR_ACQUIRED
state = addExperience(state, experienceEarned)

return {
...state,
purchasedCellar: cellarId,
Expand Down
20 changes: 19 additions & 1 deletion src/game-logic/reducers/purchaseCellar.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PURCHASEABLE_CELLARS } from '../../constants'
import { EXPERIENCE_VALUES, PURCHASEABLE_CELLARS } from '../../constants'

import { purchaseCellar } from './purchaseCellar'

Expand Down Expand Up @@ -33,4 +33,22 @@ describe('purchaseCellar', () => {
'Purchased a cellar with capacity for 10 kegs! View your keg inventory by going to the "Cellar" page.'
)
})

test('adds experience when acquired', () => {
const { experience } = purchaseCellar(
{ experience: 0, todaysNotifications: [] },
1
)

expect(experience).toEqual(EXPERIENCE_VALUES.CELLAR_ACQUIRED)
})

test('adds experience when expanded', () => {
const { experience } = purchaseCellar(
{ experience: 0, todaysNotifications: [] },
2
)

expect(experience).toEqual(EXPERIENCE_VALUES.CELLAR_EXPANDED)
})
})
4 changes: 3 additions & 1 deletion src/game-logic/reducers/purchaseComposter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { moneyTotal } from '../../utils'
import { PURCHASEABLE_COMPOSTERS } from '../../constants'
import { EXPERIENCE_VALUES, PURCHASEABLE_COMPOSTERS } from '../../constants'
import { RECYCLING_AVAILABLE_NOTIFICATION } from '../../strings'

import { addExperience } from './addExperience'
import { showNotification } from './showNotification'
import { updateLearnedRecipes } from './updateLearnedRecipes'

Expand All @@ -22,6 +23,7 @@ export const purchaseComposter = (state, composterId) => {
}

state = showNotification(state, RECYCLING_AVAILABLE_NOTIFICATION)
state = addExperience(state, EXPERIENCE_VALUES.COMPOSTER_ACQUIRED)

return updateLearnedRecipes(state)
}
Loading

1 comment on commit ff19d4d

@vercel
Copy link

@vercel vercel bot commented on ff19d4d Sep 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.