@jeremyckahn/farmhand 1.23.2 → 1.23.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/README.md +1 -0
  2. package/dist/assets/{index-DNPchtK9.js → index-Dihg7UqQ.js} +15 -15
  3. package/dist/assets/{index-DNPchtK9.js.map → index-Dihg7UqQ.js.map} +1 -1
  4. package/dist/index.html +1 -1
  5. package/dist/service-worker.js +1 -1
  6. package/dist/service-worker.js.map +1 -1
  7. package/package.json +4 -5
  8. package/src/common/services/randomNumber.test.ts +61 -1
  9. package/src/common/services/randomNumber.ts +36 -1
  10. package/src/common/utils.ts +22 -13
  11. package/src/components/AccountingView/AccountingView.tsx +4 -12
  12. package/src/components/Achievement/Achievement.tsx +0 -13
  13. package/src/components/AchievementsView/AchievementsView.tsx +2 -7
  14. package/src/components/AnimatedNumber/AnimatedNumber.tsx +0 -6
  15. package/src/components/AppBar/AppBar.tsx +0 -10
  16. package/src/components/Cellar/Cellar.tsx +0 -2
  17. package/src/components/Cellar/CellarInventoryTabPanel.tsx +0 -6
  18. package/src/components/Cellar/FermentationTabPanel.tsx +0 -6
  19. package/src/components/Cellar/Keg.tsx +0 -5
  20. package/src/components/Cellar/TabPanel/index.tsx +0 -7
  21. package/src/components/Cellar/WinemakingTabPanel.tsx +0 -6
  22. package/src/components/ContextPane/ContextPane.tsx +0 -6
  23. package/src/components/CowCard/Bloodline/Bloodline.tsx +0 -5
  24. package/src/components/CowCard/CowCard.tsx +0 -26
  25. package/src/components/CowCard/Subheader/Subheader.tsx +11 -26
  26. package/src/components/CowPen/CowPen.tsx +4 -15
  27. package/src/components/CowPenContextMenu/CowPenContextMenu.tsx +0 -16
  28. package/src/components/CowPenContextMenu/TabPanel/index.tsx +0 -7
  29. package/src/components/Farmhand/Farmhand.context.tsx +4 -3
  30. package/src/components/Farmhand/Farmhand.tsx +4 -11
  31. package/src/components/Farmhand/FarmhandReducers.tsx +1 -2
  32. package/src/components/Farmhand/FarmhandService.test.ts +6 -9
  33. package/src/components/Farmhand/hooks/useFarmhandDayAdvancement.ts +2 -6
  34. package/src/components/Farmhand/hooks/useFarmhandNetwork.test.ts +2 -2
  35. package/src/components/Farmhand/hooks/useFarmhandNetwork.ts +15 -31
  36. package/src/components/Farmhand/useFarmhand.test.ts +7 -5
  37. package/src/components/Farmhand/useFarmhand.ts +12 -13
  38. package/src/components/FermentationRecipeList/FermentationRecipe.tsx +0 -5
  39. package/src/components/FermentationRecipeList/FermentationRecipeList.test.tsx +10 -11
  40. package/src/components/FermentationRecipeList/FermentationRecipeList.tsx +2 -3
  41. package/src/components/Field/Field.tsx +13 -48
  42. package/src/components/Forest/Forest.tsx +10 -7
  43. package/src/components/ForestPlot/ForestPlot.tsx +5 -5
  44. package/src/components/ForestQuickSelect/ForestQuickSelect.tsx +0 -12
  45. package/src/components/Home/Home.tsx +0 -6
  46. package/src/components/Home/SnowBackground.tsx +1 -1
  47. package/src/components/IngredientsList/IngredientsList.tsx +0 -7
  48. package/src/components/Inventory/Inventory.test.tsx +4 -4
  49. package/src/components/Inventory/Inventory.tsx +3 -11
  50. package/src/components/Item/Item.tsx +0 -21
  51. package/src/components/ItemList/ItemList.tsx +4 -11
  52. package/src/components/KeybindingsView/KeybindingsView.tsx +0 -2
  53. package/src/components/LogView/LogView.tsx +0 -6
  54. package/src/components/Navigation/DayAndProgressContainer.tsx +0 -7
  55. package/src/components/Navigation/Navigation.tsx +0 -23
  56. package/src/components/NotificationSystem/NotificationSystem.test.tsx +4 -1
  57. package/src/components/NotificationSystem/NotificationSystem.tsx +5 -12
  58. package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.test.tsx +2 -2
  59. package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.tsx +0 -11
  60. package/src/components/OnlinePeersView/OnlinePeersView.tsx +0 -10
  61. package/src/components/Plot/Plot.tsx +3 -3
  62. package/src/components/PriceEventView/PriceEventView.tsx +0 -6
  63. package/src/components/ProgressBar/ProgressBar.tsx +0 -5
  64. package/src/components/QuantityInput/QuantityInput.tsx +0 -9
  65. package/src/components/QuickSelect/QuickSelect.tsx +0 -10
  66. package/src/components/Recipe/Recipe.tsx +0 -9
  67. package/src/components/RecipeList/RecipeList.tsx +0 -6
  68. package/src/components/SearchBar/SearchBar.tsx +0 -6
  69. package/src/components/SettingsView/RandomSeedInput.test.tsx +2 -4
  70. package/src/components/SettingsView/RandomSeedInput.tsx +5 -8
  71. package/src/components/SettingsView/SettingsView.test.tsx +21 -0
  72. package/src/components/SettingsView/SettingsView.tsx +24 -16
  73. package/src/components/Shop/Shop.tsx +0 -20
  74. package/src/components/Shop/TabPanel/index.tsx +0 -7
  75. package/src/components/Stage/Stage.tsx +11 -20
  76. package/src/components/StatsView/StatsView.tsx +0 -15
  77. package/src/components/TierPurchase/TierPurchase.tsx +0 -12
  78. package/src/components/Toolbelt/Toolbelt.tsx +5 -10
  79. package/src/components/UpgradePurchase/UpgradePurchase.tsx +0 -10
  80. package/src/components/WineRecipeList/WineRecipe.test.tsx +2 -2
  81. package/src/components/WineRecipeList/WineRecipe.tsx +0 -5
  82. package/src/components/WineRecipeList/WineRecipeList.tsx +2 -3
  83. package/src/components/Workshop/ForgeTabPanel.tsx +0 -8
  84. package/src/components/Workshop/KitchenTabPanel.tsx +0 -7
  85. package/src/components/Workshop/RecyclingTabPanel.tsx +0 -7
  86. package/src/components/Workshop/TabPanel/index.tsx +0 -7
  87. package/src/components/Workshop/WoodChipperTabPanel.tsx +0 -7
  88. package/src/components/Workshop/Workshop.tsx +0 -9
  89. package/src/components/Workshop/getUpgradesAvailable.ts +1 -1
  90. package/src/constants.ts +18 -13
  91. package/src/data/crops/grape.ts +13 -15
  92. package/src/data/maps.test.ts +3 -4
  93. package/src/data/maps.ts +27 -29
  94. package/src/enums.ts +47 -19
  95. package/src/factories/OreFactory.ts +2 -1
  96. package/src/farmhand.d.ts +2 -3
  97. package/src/game-logic/reducers/applyPrecipitation.ts +4 -4
  98. package/src/game-logic/reducers/generatePriceEvents.ts +6 -3
  99. package/src/game-logic/reducers/harvestForestPlot.ts +1 -2
  100. package/src/game-logic/reducers/makeFermentationRecipe.ts +2 -3
  101. package/src/game-logic/reducers/minePlot.test.ts +2 -2
  102. package/src/game-logic/reducers/minePlot.ts +1 -1
  103. package/src/game-logic/reducers/processCowFertilizerProduction.test.ts +16 -14
  104. package/src/game-logic/reducers/processFeedingCows.test.ts +2 -5
  105. package/src/game-logic/reducers/purchaseCow.ts +2 -7
  106. package/src/game-logic/reducers/updateAchievements.ts +1 -1
  107. package/src/game-logic/reducers/updateFinancialRecords.test.ts +21 -25
  108. package/src/game-logic/reducers/updateFinancialRecords.ts +2 -5
  109. package/src/game-logic/reducers/updateInventoryRecordsForNextDay.test.ts +12 -14
  110. package/src/handlers/ui-events.test.ts +44 -42
  111. package/src/handlers/ui-events.tsx +10 -0
  112. package/src/hooks/usePrefersReducedMotion.ts +10 -6
  113. package/src/mui-theme.ts +4 -3
  114. package/src/scripts/generate-crop-table.ts +3 -2
  115. package/src/styles/sx.ts +29 -25
  116. package/src/test-utils/index.ts +1 -0
  117. package/src/utils/chooseRandom.ts +4 -1
  118. package/src/utils/chooseRandomIndex.ts +6 -2
  119. package/src/utils/getCowImage.ts +22 -16
  120. package/src/utils/getMaxYieldOfFermentationRecipe.ts +2 -2
  121. package/src/utils/getPeerMetadata.ts +1 -1
  122. package/src/utils/getPlotImage.test.ts +14 -14
  123. package/src/utils/getPlotImage.ts +10 -10
  124. package/src/utils/getRandomUnlockedCrop.ts +5 -3
  125. package/src/utils/getRandomizedLifespan.test.ts +2 -8
  126. package/src/utils/getValueAdjustmentStream.test.ts +9 -0
  127. package/src/utils/getValueAdjustmentStream.ts +5 -0
  128. package/src/utils/isItemAFarmProduct.ts +2 -2
  129. package/src/utils/shouldPrecipitateToday.ts +3 -1
  130. package/src/utils/shouldStormToday.ts +2 -1
  131. package/src/utils/transformStateDataForImport.ts +3 -5
package/src/data/maps.ts CHANGED
@@ -47,7 +47,7 @@ export const recipeCategories: Record<
47
47
  export const recipesMap: Record<string, farmhand.recipe> = {}
48
48
 
49
49
  for (const recipeId of Object.keys(recipes)) {
50
- const recipe = ((recipes as unknown) as Record<string, farmhand.recipe>)[
50
+ const recipe = (recipes as unknown as Record<string, farmhand.recipe>)[
51
51
  recipeId
52
52
  ]
53
53
 
@@ -59,10 +59,12 @@ export const upgradesMap: Record<string, farmhand.upgradesMetadatum> = {}
59
59
 
60
60
  for (let toolType of Object.keys(upgrades)) {
61
61
  for (let upgrade of Object.values(
62
- ((upgrades as unknown) as Record<
63
- string,
64
- Record<string, farmhand.upgradesMetadatum>
65
- >)[toolType]
62
+ (
63
+ upgrades as unknown as Record<
64
+ string,
65
+ Record<string, farmhand.upgradesMetadatum>
66
+ >
67
+ )[toolType]
66
68
  )) {
67
69
  upgradesMap[upgrade.id] = upgrade
68
70
  }
@@ -74,36 +76,32 @@ export const itemsMap: Record<string, farmhand.item> = {
74
76
  ...upgradesMap,
75
77
  }
76
78
 
77
- export const fermentableItemsMap: Record<
78
- string,
79
- farmhand.item
80
- > = Object.fromEntries(
81
- Object.entries(itemsMap).filter(([itemId]) => {
82
- const item = itemsMap[itemId]
79
+ export const fermentableItemsMap: Record<string, farmhand.item> =
80
+ Object.fromEntries(
81
+ Object.entries(itemsMap).filter(([itemId]) => {
82
+ const item = itemsMap[itemId]
83
83
 
84
- return 'daysToFerment' in item
85
- })
86
- )
84
+ return 'daysToFerment' in item
85
+ })
86
+ )
87
87
 
88
- export const cropItemIdToSeedItemMap: Record<
89
- string,
90
- farmhand.seedItem
91
- > = Object.entries(baseItemsMap).reduce<Record<string, farmhand.seedItem>>(
92
- (acc, [itemId, item]) => {
93
- const { growsInto } = item as { growsInto?: string | string[] }
88
+ export const cropItemIdToSeedItemMap: Record<string, farmhand.seedItem> =
89
+ Object.entries(baseItemsMap).reduce<Record<string, farmhand.seedItem>>(
90
+ (acc, [itemId, item]) => {
91
+ const { growsInto } = item as { growsInto?: string | string[] }
94
92
 
95
- if (growsInto) {
96
- const variants = Array.isArray(growsInto) ? growsInto : [growsInto]
93
+ if (growsInto) {
94
+ const variants = Array.isArray(growsInto) ? growsInto : [growsInto]
97
95
 
98
- for (const variantId of variants) {
99
- acc[variantId] = baseItemsMap[itemId] as farmhand.seedItem
96
+ for (const variantId of variants) {
97
+ acc[variantId] = baseItemsMap[itemId] as farmhand.seedItem
98
+ }
100
99
  }
101
- }
102
100
 
103
- return acc
104
- },
105
- {}
106
- )
101
+ return acc
102
+ },
103
+ {}
104
+ )
107
105
 
108
106
  export const cropTypeToIdMap: Record<string, string | Array<string>> = {
109
107
  [ASPARAGUS]: 'asparagus',
package/src/enums.ts CHANGED
@@ -27,7 +27,7 @@ export const cropType = {
27
27
  WEED: 'WEED',
28
28
  } as const
29
29
 
30
- export type cropType = typeof cropType[keyof typeof cropType]
30
+ export type cropType = (typeof cropType)[keyof typeof cropType]
31
31
 
32
32
  /**
33
33
  * @property farmhand.module:enums.recipeType
@@ -42,7 +42,7 @@ export const recipeType = {
42
42
  WOOD_CHIPPER: 'WOOD_CHIPPER',
43
43
  } as const
44
44
 
45
- export type recipeType = typeof recipeType[keyof typeof recipeType]
45
+ export type recipeType = (typeof recipeType)[keyof typeof recipeType]
46
46
 
47
47
  /**
48
48
  * @property farmhand.module:enums.fieldMode
@@ -63,7 +63,7 @@ export const fieldMode = {
63
63
  WATER: 'WATER',
64
64
  } as const
65
65
 
66
- export type fieldMode = typeof fieldMode[keyof typeof fieldMode]
66
+ export type fieldMode = (typeof fieldMode)[keyof typeof fieldMode]
67
67
 
68
68
  /**
69
69
  * @property farmhand.module:enums.stageFocusType
@@ -81,7 +81,8 @@ export const stageFocusType = {
81
81
  CELLAR: 'CELLAR',
82
82
  } as const
83
83
 
84
- export type stageFocusType = typeof stageFocusType[keyof typeof stageFocusType]
84
+ export type stageFocusType =
85
+ (typeof stageFocusType)[keyof typeof stageFocusType]
85
86
 
86
87
  /**
87
88
  * @property farmhand.module:enums.cropLifeStage
@@ -93,7 +94,7 @@ export const cropLifeStage = {
93
94
  GROWN: 'GROWN',
94
95
  } as const
95
96
 
96
- export type cropLifeStage = typeof cropLifeStage[keyof typeof cropLifeStage]
97
+ export type cropLifeStage = (typeof cropLifeStage)[keyof typeof cropLifeStage]
97
98
 
98
99
  /**
99
100
  * Tree-only extension of cropLifeStage. DEAD is deliberately not part of
@@ -107,7 +108,7 @@ export const treeLifeStage = {
107
108
  DEAD: 'DEAD',
108
109
  } as const
109
110
 
110
- export type treeLifeStage = typeof treeLifeStage[keyof typeof treeLifeStage]
111
+ export type treeLifeStage = (typeof treeLifeStage)[keyof typeof treeLifeStage]
111
112
 
112
113
  /**
113
114
  * @property farmhand.module:enums.itemType
@@ -133,7 +134,7 @@ export const itemType = {
133
134
  WOOD: 'WOOD',
134
135
  } as const
135
136
 
136
- export type itemType = typeof itemType[keyof typeof itemType]
137
+ export type itemType = (typeof itemType)[keyof typeof itemType]
137
138
 
138
139
  /**
139
140
  * @property farmhand.module:enums.treeType
@@ -144,7 +145,7 @@ export const treeType = {
144
145
  BANANA: 'BANANA',
145
146
  } as const
146
147
 
147
- export type treeType = typeof treeType[keyof typeof treeType]
148
+ export type treeType = (typeof treeType)[keyof typeof treeType]
148
149
 
149
150
  /**
150
151
  * @property farmhand.module:enums.fertilizerType
@@ -156,7 +157,8 @@ export const fertilizerType = {
156
157
  RAINBOW: 'RAINBOW',
157
158
  } as const
158
159
 
159
- export type fertilizerType = typeof fertilizerType[keyof typeof fertilizerType]
160
+ export type fertilizerType =
161
+ (typeof fertilizerType)[keyof typeof fertilizerType]
160
162
 
161
163
  /**
162
164
  * @property farmhand.module:enums.genders
@@ -167,7 +169,7 @@ export const genders = {
167
169
  MALE: 'MALE',
168
170
  } as const
169
171
 
170
- export type genders = typeof genders[keyof typeof genders]
172
+ export type genders = (typeof genders)[keyof typeof genders]
171
173
 
172
174
  /**
173
175
  * @property farmhand.module:enums.cowColors
@@ -184,7 +186,7 @@ export const cowColors = {
184
186
  YELLOW: 'YELLOW',
185
187
  } as const
186
188
 
187
- export type cowColors = typeof cowColors[keyof typeof cowColors]
189
+ export type cowColors = (typeof cowColors)[keyof typeof cowColors]
188
190
 
189
191
  const { RAINBOW, ...standardCowColors } = cowColors
190
192
 
@@ -206,7 +208,7 @@ export const dialogView = {
206
208
  STATS: 'STATS',
207
209
  } as const
208
210
 
209
- export type dialogView = typeof dialogView[keyof typeof dialogView]
211
+ export type dialogView = (typeof dialogView)[keyof typeof dialogView]
210
212
 
211
213
  /**
212
214
  * @property farmhand.module:enums.toolType
@@ -221,7 +223,7 @@ export const toolType = {
221
223
  WATERING_CAN: 'WATERING_CAN',
222
224
  } as const
223
225
 
224
- export type toolType = typeof toolType[keyof typeof toolType]
226
+ export type toolType = (typeof toolType)[keyof typeof toolType]
225
227
 
226
228
  /**
227
229
  * @property farmhand.module:enums.toolLevel
@@ -236,7 +238,7 @@ export const toolLevel = {
236
238
  GOLD: 'GOLD',
237
239
  } as const
238
240
 
239
- export type toolLevel = typeof toolLevel[keyof typeof toolLevel]
241
+ export type toolLevel = (typeof toolLevel)[keyof typeof toolLevel]
240
242
 
241
243
  /**
242
244
  * @property farmhand.module:enums.notificationSeverity
@@ -249,7 +251,8 @@ export const notificationSeverity = {
249
251
  ERROR: 'error',
250
252
  } as const
251
253
 
252
- export type notificationSeverity = typeof notificationSeverity[keyof typeof notificationSeverity]
254
+ export type notificationSeverity =
255
+ (typeof notificationSeverity)[keyof typeof notificationSeverity]
253
256
 
254
257
  /**
255
258
  * @property farmhand.module:enums.cowTradeRejectionReason
@@ -259,7 +262,8 @@ export const cowTradeRejectionReason = {
259
262
  REQUESTED_COW_UNAVAILABLE: 'REQUESTED_COW_UNAVAILABLE',
260
263
  } as const
261
264
 
262
- export type cowTradeRejectionReason = typeof cowTradeRejectionReason[keyof typeof cowTradeRejectionReason]
265
+ export type cowTradeRejectionReason =
266
+ (typeof cowTradeRejectionReason)[keyof typeof cowTradeRejectionReason]
263
267
 
264
268
  /**
265
269
  * @property farmhand.module:enums.cropFamily
@@ -270,7 +274,7 @@ export const cropFamily = {
270
274
  GRAPE: 'GRAPE',
271
275
  } as const
272
276
 
273
- export type cropFamily = typeof cropFamily[keyof typeof cropFamily]
277
+ export type cropFamily = (typeof cropFamily)[keyof typeof cropFamily]
274
278
 
275
279
  /**
276
280
  * @property farmhand.module:enums.grapeVariety
@@ -290,7 +294,7 @@ export const grapeVariety = {
290
294
  NEBBIOLO: 'NEBBIOLO',
291
295
  } as const
292
296
 
293
- export type grapeVariety = typeof grapeVariety[keyof typeof grapeVariety]
297
+ export type grapeVariety = (typeof grapeVariety)[keyof typeof grapeVariety]
294
298
 
295
299
  /**
296
300
  * @property farmhand.module:enums.season
@@ -303,4 +307,28 @@ export const season = {
303
307
  WINTER: 'WINTER',
304
308
  } as const
305
309
 
306
- export type season = typeof season[keyof typeof season]
310
+ export type season = (typeof season)[keyof typeof season]
311
+
312
+ /**
313
+ * Names of the random number streams that game logic draws from. A stream
314
+ * name identifies where a value is drawn so that it can be forced with
315
+ * RandomNumberService#queueRandomNumbers (e.g. in E2E tests).
316
+ * @property farmhand.module:enums.randomStream
317
+ * @enum
318
+ */
319
+ export const randomStream = {
320
+ PRECIPITATION: 'precipitation',
321
+ STORM: 'storm',
322
+ PRICE_EVENT_CHANCE: 'priceEventChance',
323
+ PRICE_EVENT_CROP: 'priceEventCrop',
324
+ PRICE_EVENT_TYPE: 'priceEventType',
325
+ } as const
326
+
327
+ /**
328
+ * The stream for an item's price adjustment (see generateValueAdjustments in
329
+ * src/common/utils.ts). Create one with getValueAdjustmentStream.
330
+ */
331
+ export type valueAdjustmentStream = `valueAdjustment:${string}`
332
+
333
+ export type randomStream =
334
+ (typeof randomStream)[keyof typeof randomStream] | valueAdjustmentStream
@@ -9,7 +9,8 @@ const SPAWNABLE_ORES = [goldOre, ironOre, bronzeOre, silverOre]
9
9
  * @constructor
10
10
  */
11
11
  export default class OreFactory extends Factory {
12
- oreOptions: Array<{ ore: typeof SPAWNABLE_ORES[number]; weight: number }> = []
12
+ oreOptions: Array<{ ore: (typeof SPAWNABLE_ORES)[number]; weight: number }> =
13
+ []
13
14
 
14
15
  constructor() {
15
16
  super()
package/src/farmhand.d.ts CHANGED
@@ -181,9 +181,7 @@ declare namespace farmhand {
181
181
 
182
182
  type achievementCondition = (state: state, prevState?: state) => boolean
183
183
  type achievementReward = (state: state) => state
184
- type achievementProgress = (
185
- state: state
186
- ) => {
184
+ type achievementProgress = (state: state) => {
187
185
  currentValue: number
188
186
  goal: number
189
187
  }
@@ -403,6 +401,7 @@ declare namespace farmhand {
403
401
  latestNotification?: notification | null
404
402
  newDayNotifications: notification[]
405
403
  notificationLog: notificationLogEntry[]
404
+ notificationDuration: number
406
405
  /**
407
406
  * Keys are (Trystero) peer ids, values are their respective metadata or null.
408
407
  */
@@ -83,13 +83,13 @@ export const applyPrecipitation = (state: farmhand.state): farmhand.state => {
83
83
  message: anyRodWasDestroyed
84
84
  ? LIGHTNING_ROD_DESTROYED_MESSAGE
85
85
  : anyRodWasReplanted
86
- ? LIGHTNING_ROD_REPLANTED_MESSAGE
87
- : LIGHTNING_ROD_STRUCK_MESSAGE,
86
+ ? LIGHTNING_ROD_REPLANTED_MESSAGE
87
+ : LIGHTNING_ROD_STRUCK_MESSAGE,
88
88
  severity: anyRodWasDestroyed
89
89
  ? 'error'
90
90
  : anyRodWasReplanted
91
- ? 'success'
92
- : 'info',
91
+ ? 'success'
92
+ : 'info',
93
93
  }
94
94
  } else if (fieldHasScarecrow(field)) {
95
95
  notification = {
@@ -6,6 +6,7 @@ import { getLevelEntitlements } from '../../utils/getLevelEntitlements.js'
6
6
  import { PRICE_EVENT_CHANCE } from '../../constants.js'
7
7
  import { PRICE_CRASH, PRICE_SURGE } from '../../templates.js'
8
8
  import { random } from '../../common/utils.js'
9
+ import { randomStream } from '../../enums.js'
9
10
 
10
11
  import { createPriceEvent } from './createPriceEvent.js'
11
12
 
@@ -20,13 +21,14 @@ export const generatePriceEvents = (state: farmhand.state): farmhand.state => {
20
21
 
21
22
  // TODO: Use isRandomNumberLessThan here once it supports an exclusive
22
23
  // less-than check.
23
- if (random() < PRICE_EVENT_CHANCE) {
24
+ if (random(randomStream.PRICE_EVENT_CHANCE) < PRICE_EVENT_CHANCE) {
24
25
  const { items: unlockedItems } = getLevelEntitlements(
25
26
  levelAchieved(state.experience)
26
27
  )
27
28
 
28
29
  const cropItem = getRandomUnlockedCrop(
29
- filterItemIdsToSeeds(Object.keys(unlockedItems))
30
+ filterItemIdsToSeeds(Object.keys(unlockedItems)),
31
+ randomStream.PRICE_EVENT_CROP
30
32
  )
31
33
  const { id } = cropItem
32
34
 
@@ -35,7 +37,8 @@ export const generatePriceEvents = (state: farmhand.state): farmhand.state => {
35
37
  )
36
38
 
37
39
  if (!doesPriceEventAlreadyExist) {
38
- const priceEventType = random() < 0.5 ? TYPE_CRASH : TYPE_SURGE
40
+ const priceEventType =
41
+ random(randomStream.PRICE_EVENT_TYPE) < 0.5 ? TYPE_CRASH : TYPE_SURGE
39
42
 
40
43
  priceEvent = createPriceEvent(
41
44
  state,
@@ -50,8 +50,7 @@ export const harvestForestPlot = (
50
50
  ...state,
51
51
  treeFruitsHarvested: {
52
52
  ...state.treeFruitsHarvested,
53
- [item.id]:
54
- (state.treeFruitsHarvested[item.id] || 0) + receivedFruitYield,
53
+ [item.id]: (state.treeFruitsHarvested[item.id] || 0) + receivedFruitYield,
55
54
  },
56
55
  }
57
56
 
@@ -35,9 +35,8 @@ export const makeFermentationRecipe = (
35
35
  state = addKegToCellarInventory(state, keg)
36
36
  }
37
37
 
38
- const saltRequirements = getSaltRequirementsForFermentationRecipe(
39
- fermentationRecipe
40
- )
38
+ const saltRequirements =
39
+ getSaltRequirementsForFermentationRecipe(fermentationRecipe)
41
40
 
42
41
  state = decrementItemFromInventory(state, fermentationRecipe.id, howMany)
43
42
 
@@ -11,9 +11,9 @@ describe('minePlot', () => {
11
11
 
12
12
  beforeAll(() => {
13
13
  vitest.spyOn(randomNumberService, 'generateRandomNumber').mockReturnValue(1)
14
- vitest.spyOn(ResourceFactory, 'instance').mockReturnValue(({
14
+ vitest.spyOn(ResourceFactory, 'instance').mockReturnValue({
15
15
  generateResources: () => [goldOre],
16
- } as unknown) as typeof ResourceFactory.prototype)
16
+ } as unknown as typeof ResourceFactory.prototype)
17
17
 
18
18
  gameState = minePlot(
19
19
  testState({
@@ -29,7 +29,7 @@ export const minePlot = (
29
29
  }
30
30
 
31
31
  const shovelLevel = state.toolLevels[toolType.SHOVEL]
32
- const factory = (ResourceFactory.instance() as unknown) as {
32
+ const factory = ResourceFactory.instance() as unknown as {
33
33
  generateResources: (l: number) => farmhand.item[]
34
34
  }
35
35
  const spawnedResources = factory.generateResources(shovelLevel as any)
@@ -53,7 +53,8 @@ describe('processCowFertilizerProduction', () => {
53
53
  state.cowInventory = [
54
54
  generateCow({
55
55
  color: standardCowColors.WHITE,
56
- daysSinceProducingFertilizer: COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
56
+ daysSinceProducingFertilizer:
57
+ COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
57
58
  gender: genders.MALE,
58
59
  }),
59
60
  ]
@@ -85,12 +86,14 @@ describe('processCowFertilizerProduction', () => {
85
86
  state.cowInventory = [
86
87
  generateCow({
87
88
  color: standardCowColors.WHITE,
88
- daysSinceProducingFertilizer: COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
89
+ daysSinceProducingFertilizer:
90
+ COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
89
91
  gender: genders.MALE,
90
92
  }),
91
93
  generateCow({
92
94
  color: standardCowColors.WHITE,
93
- daysSinceProducingFertilizer: COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
95
+ daysSinceProducingFertilizer:
96
+ COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
94
97
  gender: genders.MALE,
95
98
  }),
96
99
  ]
@@ -122,14 +125,14 @@ describe('processCowFertilizerProduction', () => {
122
125
  state.cowInventory = [
123
126
  generateCow({
124
127
  color: cowColors.RAINBOW,
125
- daysSinceProducingFertilizer: COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
128
+ daysSinceProducingFertilizer:
129
+ COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
126
130
  gender: genders.MALE,
127
131
  }),
128
132
  ]
129
133
 
130
- const { hasProducedRainbowFertilizer } = processCowFertilizerProduction(
131
- state
132
- )
134
+ const { hasProducedRainbowFertilizer } =
135
+ processCowFertilizerProduction(state)
133
136
 
134
137
  expect(hasProducedRainbowFertilizer).toBe(true)
135
138
  })
@@ -141,14 +144,14 @@ describe('processCowFertilizerProduction', () => {
141
144
  state.cowInventory = [
142
145
  generateCow({
143
146
  color: standardCowColors.WHITE,
144
- daysSinceProducingFertilizer: COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
147
+ daysSinceProducingFertilizer:
148
+ COW_FERTILIZER_PRODUCTION_RATE_SLOWEST,
145
149
  gender: genders.MALE,
146
150
  }),
147
151
  ]
148
152
 
149
- const { hasProducedRainbowFertilizer } = processCowFertilizerProduction(
150
- state
151
- )
153
+ const { hasProducedRainbowFertilizer } =
154
+ processCowFertilizerProduction(state)
152
155
 
153
156
  expect(hasProducedRainbowFertilizer).toBe(false)
154
157
  })
@@ -159,9 +162,8 @@ describe('processCowFertilizerProduction', () => {
159
162
  state.hasProducedRainbowFertilizer = true
160
163
  state.cowInventory = []
161
164
 
162
- const { hasProducedRainbowFertilizer } = processCowFertilizerProduction(
163
- state
164
- )
165
+ const { hasProducedRainbowFertilizer } =
166
+ processCowFertilizerProduction(state)
165
167
 
166
168
  expect(hasProducedRainbowFertilizer).toBe(true)
167
169
  })
@@ -74,11 +74,8 @@ describe('processFeedingCows', () => {
74
74
  describe('there are more cows to feed than feed units', () => {
75
75
  test('units are distributed to cows and remainder goes hungry', () => {
76
76
  state.inventory = [{ id: COW_FEED_ITEM_ID, quantity: 1 }]
77
- const {
78
- cowInventory,
79
- inventory,
80
- newDayNotifications,
81
- } = processFeedingCows(state)
77
+ const { cowInventory, inventory, newDayNotifications } =
78
+ processFeedingCows(state)
82
79
 
83
80
  expect(cowInventory[0].weightMultiplier).toEqual(
84
81
  1 + COW_WEIGHT_MULTIPLIER_FEED_BENEFIT
@@ -9,13 +9,8 @@ export const purchaseCow = (
9
9
  state: farmhand.state,
10
10
  cow: farmhand.cow
11
11
  ): farmhand.state => {
12
- const {
13
- cowInventory,
14
- cowColorsPurchased,
15
- playerId,
16
- money,
17
- purchasedCowPen,
18
- } = state
12
+ const { cowInventory, cowColorsPurchased, playerId, money, purchasedCowPen } =
13
+ state
19
14
  const { color } = cow
20
15
  const cowValue = getCowValue(cow, false)
21
16
 
@@ -10,7 +10,7 @@ export const updateAchievements = (
10
10
  achievements.reduce(
11
11
  (
12
12
  reducerState: farmhand.state,
13
- achievement: Omit<typeof achievements[number], 'condition'> & {
13
+ achievement: Omit<(typeof achievements)[number], 'condition'> & {
14
14
  condition: (s: farmhand.state, ps: farmhand.state) => boolean
15
15
  }
16
16
  ) => {
@@ -37,17 +37,15 @@ describe('updateFinancialRecords', () => {
37
37
  })
38
38
 
39
39
  test('truncates logs', () => {
40
- const {
41
- historicalDailyLosses,
42
- historicalDailyRevenue,
43
- } = updateFinancialRecords(
44
- testState({
45
- historicalDailyLosses: [-1, -2, -3, -4, -5, -6, -7],
46
- historicalDailyRevenue: [1, 2, 3, 4, 5, 6, 7],
47
- todaysLosses: -5,
48
- todaysRevenue: 10,
49
- })
50
- )
40
+ const { historicalDailyLosses, historicalDailyRevenue } =
41
+ updateFinancialRecords(
42
+ testState({
43
+ historicalDailyLosses: [-1, -2, -3, -4, -5, -6, -7],
44
+ historicalDailyRevenue: [1, 2, 3, 4, 5, 6, 7],
45
+ todaysLosses: -5,
46
+ todaysRevenue: 10,
47
+ })
48
+ )
51
49
 
52
50
  expect(historicalDailyLosses).toEqual([-5, -1, -2, -3, -4, -5, -6])
53
51
  expect(historicalDailyRevenue).toEqual([10, 1, 2, 3, 4, 5, 6])
@@ -55,20 +53,18 @@ describe('updateFinancialRecords', () => {
55
53
 
56
54
  describe('profitabilityStreak', () => {
57
55
  test('unprofitable day resets streak', () => {
58
- const {
59
- profitabilityStreak,
60
- recordProfitabilityStreak,
61
- } = updateFinancialRecords(
62
- testState({
63
- historicalDailyLosses: [],
64
- historicalDailyRevenue: [],
65
- profitabilityStreak: 10,
66
- record7dayProfitAverage: 0,
67
- recordProfitabilityStreak: 10,
68
- todaysLosses: -10,
69
- todaysRevenue: 10,
70
- })
71
- )
56
+ const { profitabilityStreak, recordProfitabilityStreak } =
57
+ updateFinancialRecords(
58
+ testState({
59
+ historicalDailyLosses: [],
60
+ historicalDailyRevenue: [],
61
+ profitabilityStreak: 10,
62
+ record7dayProfitAverage: 0,
63
+ recordProfitabilityStreak: 10,
64
+ todaysLosses: -10,
65
+ todaysRevenue: 10,
66
+ })
67
+ )
72
68
 
73
69
  expect(profitabilityStreak).toEqual(0)
74
70
  expect(recordProfitabilityStreak).toEqual(10)
@@ -13,11 +13,8 @@ export const updateFinancialRecords = (
13
13
  record7dayProfitAverage,
14
14
  recordProfitabilityStreak,
15
15
  } = state
16
- let {
17
- historicalDailyLosses,
18
- historicalDailyRevenue,
19
- recordSingleDayProfit,
20
- } = state
16
+ let { historicalDailyLosses, historicalDailyRevenue, recordSingleDayProfit } =
17
+ state
21
18
 
22
19
  historicalDailyLosses = [todaysLosses, ...historicalDailyLosses].slice(
23
20
  0,
@@ -4,20 +4,18 @@ import { updateInventoryRecordsForNextDay } from './updateInventoryRecordsForNex
4
4
 
5
5
  describe('updateInventoryRecordsForNextDay', () => {
6
6
  test('records inventory records for next day', () => {
7
- const {
8
- todaysPurchases,
9
- todaysStartingInventory,
10
- } = updateInventoryRecordsForNextDay(
11
- testState({
12
- inventory: [
13
- { id: 'sample-item-1', quantity: 2 },
14
- { id: 'sample-item-2', quantity: 5 },
15
- ],
16
- todaysPurchases: {
17
- 'sample-item-3': 3,
18
- },
19
- })
20
- )
7
+ const { todaysPurchases, todaysStartingInventory } =
8
+ updateInventoryRecordsForNextDay(
9
+ testState({
10
+ inventory: [
11
+ { id: 'sample-item-1', quantity: 2 },
12
+ { id: 'sample-item-2', quantity: 5 },
13
+ ],
14
+ todaysPurchases: {
15
+ 'sample-item-3': 3,
16
+ },
17
+ })
18
+ )
21
19
 
22
20
  expect(todaysPurchases).toEqual({})
23
21
  expect(todaysStartingInventory).toEqual({