@jeremyckahn/farmhand 1.22.0 → 1.22.2
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.
- package/dist/assets/{index-DgErVmlw.js → index-C_BBT4NW.js} +4 -4
- package/dist/assets/{index-DgErVmlw.js.map → index-C_BBT4NW.js.map} +1 -1
- package/dist/index.html +1 -1
- package/dist/service-worker.js +1 -1
- package/dist/service-worker.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AppBar/AppBar.test.tsx +4 -4
- package/src/components/Item/Item.test.tsx +9 -9
- package/src/components/Stage/Stage.test.tsx +2 -2
- package/src/game-logic/reducers/sellItem.test.ts +13 -13
- package/src/shell/bootup.test.ts +6 -1
- package/src/test-utils/ui.ts +6 -1
- package/src/utils/getCurrentSeason.test.ts +6 -6
- package/src/utils/getCurrentSeason.ts +6 -1
- package/src/utils/getDayOfSeason.test.ts +4 -4
- package/src/utils/getDayOfSeason.ts +4 -1
package/dist/index.html
CHANGED
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
gtag('config', analyticsID)
|
|
76
76
|
})()
|
|
77
77
|
</script>
|
|
78
|
-
<script type="module" crossorigin src="./assets/index-
|
|
78
|
+
<script type="module" crossorigin src="./assets/index-C_BBT4NW.js"></script>
|
|
79
79
|
<link rel="stylesheet" crossorigin href="./assets/index-CNcrTYN-.css">
|
|
80
80
|
<link rel="manifest" href="./manifest.webmanifest"></head>
|
|
81
81
|
<body>
|
package/dist/service-worker.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,o)=>{const r=e||("document"in self?document.currentScript.src:"")||location.href;if(s[r])return;let d={};const l=e=>i(e,r),t={module:{uri:r},exports:d,require:l};s[r]=Promise.all(n.map(e=>t[e]||l(e))).then(e=>(o(...e),d))}}define(["./workbox-2fbc6a65"],function(e){"use strict";self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.precacheAndRoute([{url:"index.html",revision:"
|
|
1
|
+
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,o)=>{const r=e||("document"in self?document.currentScript.src:"")||location.href;if(s[r])return;let d={};const l=e=>i(e,r),t={module:{uri:r},exports:d,require:l};s[r]=Promise.all(n.map(e=>t[e]||l(e))).then(e=>(o(...e),d))}}define(["./workbox-2fbc6a65"],function(e){"use strict";self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.precacheAndRoute([{url:"index.html",revision:"b549ee2133c12f6a96628689440ee32d"},{url:"electron.js",revision:"b0456826f47539f6c1957c3add5eb959"},{url:"assets/workbox-window.prod.es5-Bd17z0YL.js",revision:null},{url:"assets/index-C_BBT4NW.js",revision:null},{url:"assets/index-CNcrTYN-.css",revision:null},{url:"favicon.ico",revision:"445bb19d4a8fd46eb433dd43cbdce691"},{url:"logo192.png",revision:"70746d790b8990639d1390337d77d81a"},{url:"logo512.png",revision:"b044ab46b3f33f0e2d313d961bf1f654"},{url:"logoMaskable.png",revision:"23be58ccf16df9f43658aad3da30056d"},{url:"manifest.webmanifest",revision:"3ad071a00582451c9cdeb827b37b9ebe"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
|
|
2
2
|
//# sourceMappingURL=service-worker.js.map
|
|
3
3
|
//# sourceMappingURL=service-worker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-worker.js","sources":["../../../../../tmp/
|
|
1
|
+
{"version":3,"file":"service-worker.js","sources":["../../../../../tmp/44ebbc81530230699b16f7f886c50e94/service-worker.js"],"sourcesContent":["import {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {registerRoute as workbox_routing_registerRoute} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-routing/registerRoute.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/home/runner/work/farmhand/farmhand/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\nself.addEventListener('message', (event) => {\n if (event.data && event.data.type === 'SKIP_WAITING') {\n self.skipWaiting();\n }\n});\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"index.html\",\n \"revision\": \"b549ee2133c12f6a96628689440ee32d\"\n },\n {\n \"url\": \"electron.js\",\n \"revision\": \"b0456826f47539f6c1957c3add5eb959\"\n },\n {\n \"url\": \"assets/workbox-window.prod.es5-Bd17z0YL.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-C_BBT4NW.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-CNcrTYN-.css\",\n \"revision\": null\n },\n {\n \"url\": \"favicon.ico\",\n \"revision\": \"445bb19d4a8fd46eb433dd43cbdce691\"\n },\n {\n \"url\": \"logo192.png\",\n \"revision\": \"70746d790b8990639d1390337d77d81a\"\n },\n {\n \"url\": \"logo512.png\",\n \"revision\": \"b044ab46b3f33f0e2d313d961bf1f654\"\n },\n {\n \"url\": \"logoMaskable.png\",\n \"revision\": \"23be58ccf16df9f43658aad3da30056d\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"3ad071a00582451c9cdeb827b37b9ebe\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();workbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"index.html\")));\n\n\n"],"names":["self","addEventListener","event","data","type","skipWaiting","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches","workbox_routing_registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL"],"mappings":"inBAmBAA,KAAKC,iBAAiB,UAAYC,IAC5BA,EAAMC,MAA4B,iBAApBD,EAAMC,KAAKC,MAC3BJ,KAAKK,gBASTC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,MAEd,CACED,IAAO,2BACPC,SAAY,MAEd,CACED,IAAO,4BACPC,SAAY,MAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,qCAEb,CAAA,GACHC,EAAAA,wBAA2CC,EAAAA,cAA8B,IAAIC,EAAAA,gBAAgCC,0BAA2C"}
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@ import { noop } from '../../utils/noop.js'
|
|
|
7
7
|
import { AppBar } from './AppBar.js'
|
|
8
8
|
|
|
9
9
|
const defaultProps = {
|
|
10
|
-
dayCount:
|
|
10
|
+
dayCount: 1,
|
|
11
11
|
handleClickNotificationIndicator: noop,
|
|
12
12
|
money: 0,
|
|
13
13
|
showNotifications: false,
|
|
@@ -34,19 +34,19 @@ test('displays money amount', () => {
|
|
|
34
34
|
})
|
|
35
35
|
|
|
36
36
|
test('displays the current day and season', () => {
|
|
37
|
-
render(<AppBar {...defaultProps} dayCount={
|
|
37
|
+
render(<AppBar {...defaultProps} dayCount={1} />)
|
|
38
38
|
|
|
39
39
|
expect(screen.getByText('Day 1 of Spring')).toBeInTheDocument()
|
|
40
40
|
})
|
|
41
41
|
|
|
42
42
|
test('displays the correct day and season after the season boundary', () => {
|
|
43
|
-
render(<AppBar {...defaultProps} dayCount={
|
|
43
|
+
render(<AppBar {...defaultProps} dayCount={16} />)
|
|
44
44
|
|
|
45
45
|
expect(screen.getByText('Day 1 of Summer')).toBeInTheDocument()
|
|
46
46
|
})
|
|
47
47
|
|
|
48
48
|
test('displays the correct day count partway through a season', () => {
|
|
49
|
-
render(<AppBar {...defaultProps} dayCount={
|
|
49
|
+
render(<AppBar {...defaultProps} dayCount={6} />)
|
|
50
50
|
|
|
51
51
|
expect(screen.getByText('Day 6 of Spring')).toBeInTheDocument()
|
|
52
52
|
})
|
|
@@ -15,7 +15,7 @@ vitest.mock('../../data/maps.js')
|
|
|
15
15
|
describe('Item', () => {
|
|
16
16
|
const baseProps = {
|
|
17
17
|
completedAchievements: {},
|
|
18
|
-
dayCount:
|
|
18
|
+
dayCount: 1,
|
|
19
19
|
historicalValueAdjustments: [],
|
|
20
20
|
inventory: [],
|
|
21
21
|
inventoryLimit: INFINITE_STORAGE_LIMIT,
|
|
@@ -148,7 +148,7 @@ describe('Item', () => {
|
|
|
148
148
|
<Item
|
|
149
149
|
{...{
|
|
150
150
|
...baseProps,
|
|
151
|
-
dayCount:
|
|
151
|
+
dayCount: 1,
|
|
152
152
|
isSellView: true,
|
|
153
153
|
item: testItem({ id, highDemandSeasons: [season.SPRING] }),
|
|
154
154
|
playerInventoryQuantities: { [id]: 4 },
|
|
@@ -166,7 +166,7 @@ describe('Item', () => {
|
|
|
166
166
|
<Item
|
|
167
167
|
{...{
|
|
168
168
|
...baseProps,
|
|
169
|
-
dayCount:
|
|
169
|
+
dayCount: 1,
|
|
170
170
|
isSellView: true,
|
|
171
171
|
item: testItem({ id, lowDemandSeasons: [season.SPRING] }),
|
|
172
172
|
playerInventoryQuantities: { [id]: 4 },
|
|
@@ -184,7 +184,7 @@ describe('Item', () => {
|
|
|
184
184
|
<Item
|
|
185
185
|
{...{
|
|
186
186
|
...baseProps,
|
|
187
|
-
dayCount:
|
|
187
|
+
dayCount: 1,
|
|
188
188
|
isSellView: true,
|
|
189
189
|
item: testItem({ id, highDemandSeasons: [season.SUMMER] }),
|
|
190
190
|
playerInventoryQuantities: { [id]: 4 },
|
|
@@ -197,14 +197,14 @@ describe('Item', () => {
|
|
|
197
197
|
})
|
|
198
198
|
|
|
199
199
|
test('shows no indicator for a seed sold in the shop, even during its high demand season', () => {
|
|
200
|
-
// dayCount
|
|
200
|
+
// dayCount 1 is SPRING, carrotSeed's configured high demand season,
|
|
201
201
|
// but the seasonal price bonus never applies to shop-sold items
|
|
202
202
|
// (see the #140 guard), so the label must not appear either.
|
|
203
203
|
render(
|
|
204
204
|
<Item
|
|
205
205
|
{...{
|
|
206
206
|
...baseProps,
|
|
207
|
-
dayCount:
|
|
207
|
+
dayCount: 1,
|
|
208
208
|
isSellView: true,
|
|
209
209
|
item: carrotSeed,
|
|
210
210
|
playerInventoryQuantities: { [carrotSeed.id]: 4 },
|
|
@@ -225,7 +225,7 @@ describe('Item', () => {
|
|
|
225
225
|
<Item
|
|
226
226
|
{...{
|
|
227
227
|
...baseProps,
|
|
228
|
-
dayCount:
|
|
228
|
+
dayCount: 1,
|
|
229
229
|
isSellView: true,
|
|
230
230
|
adjustedValue: 10,
|
|
231
231
|
item: testItem({ id, highDemandSeasons: [season.SPRING] }),
|
|
@@ -246,7 +246,7 @@ describe('Item', () => {
|
|
|
246
246
|
<Item
|
|
247
247
|
{...{
|
|
248
248
|
...baseProps,
|
|
249
|
-
dayCount:
|
|
249
|
+
dayCount: 1,
|
|
250
250
|
isSellView: true,
|
|
251
251
|
adjustedValue: 10,
|
|
252
252
|
item: testItem({ id, lowDemandSeasons: [season.SPRING] }),
|
|
@@ -267,7 +267,7 @@ describe('Item', () => {
|
|
|
267
267
|
<Item
|
|
268
268
|
{...{
|
|
269
269
|
...baseProps,
|
|
270
|
-
dayCount:
|
|
270
|
+
dayCount: 1,
|
|
271
271
|
isSellView: true,
|
|
272
272
|
adjustedValue: 10,
|
|
273
273
|
item: testItem({ id, highDemandSeasons: [season.SUMMER] }),
|
|
@@ -40,7 +40,7 @@ vi.mock('../Cellar/index.js', () => ({
|
|
|
40
40
|
}))
|
|
41
41
|
|
|
42
42
|
const defaultProps = {
|
|
43
|
-
dayCount:
|
|
43
|
+
dayCount: 1,
|
|
44
44
|
field: [[]],
|
|
45
45
|
stageFocus: stageFocusType.FIELD,
|
|
46
46
|
viewTitle: 'Test View',
|
|
@@ -156,7 +156,7 @@ describe('Stage', () => {
|
|
|
156
156
|
|
|
157
157
|
describe('seasonal visual filter', () => {
|
|
158
158
|
test('applies no filter during spring on the Field screen', () => {
|
|
159
|
-
renderWithContext({ stageFocus: stageFocusType.FIELD, dayCount:
|
|
159
|
+
renderWithContext({ stageFocus: stageFocusType.FIELD, dayCount: 1 })
|
|
160
160
|
|
|
161
161
|
expect(document.querySelector('.stage-background')).toHaveStyle(
|
|
162
162
|
'filter: none'
|
|
@@ -11,7 +11,7 @@ describe('sellItem', () => {
|
|
|
11
11
|
const state = sellItem(
|
|
12
12
|
testState({
|
|
13
13
|
// Chosen so carrot's SPRING high-demand seasonal bonus doesn't apply.
|
|
14
|
-
dayCount:
|
|
14
|
+
dayCount: 16,
|
|
15
15
|
inventory: [{ id: carrot.id, quantity: 1 }],
|
|
16
16
|
itemsSold: {},
|
|
17
17
|
loanBalance: 0,
|
|
@@ -59,7 +59,7 @@ describe('sellItem', () => {
|
|
|
59
59
|
const state = sellItem(
|
|
60
60
|
testState({
|
|
61
61
|
// Chosen so carrot's SPRING high-demand seasonal bonus doesn't apply.
|
|
62
|
-
dayCount:
|
|
62
|
+
dayCount: 16,
|
|
63
63
|
inventory: [{ id: carrot.id, quantity: 1 }],
|
|
64
64
|
itemsSold: {},
|
|
65
65
|
loanBalance: 0,
|
|
@@ -113,7 +113,7 @@ describe('sellItem', () => {
|
|
|
113
113
|
const { learnedRecipes } = sellItem(
|
|
114
114
|
testState({
|
|
115
115
|
// Chosen so carrot's SPRING high-demand seasonal bonus doesn't apply.
|
|
116
|
-
dayCount:
|
|
116
|
+
dayCount: 16,
|
|
117
117
|
inventory: [{ id: carrot.id, quantity: 2 }],
|
|
118
118
|
itemsSold: {},
|
|
119
119
|
loanBalance: 0,
|
|
@@ -172,7 +172,7 @@ describe('sellItem', () => {
|
|
|
172
172
|
state = sellItem(
|
|
173
173
|
testState({
|
|
174
174
|
// Chosen so carrot's SPRING high-demand seasonal bonus doesn't apply.
|
|
175
|
-
dayCount:
|
|
175
|
+
dayCount: 16,
|
|
176
176
|
inventory: [{ id: carrot.id, quantity: 3 }],
|
|
177
177
|
itemsSold: {},
|
|
178
178
|
loanBalance: 100,
|
|
@@ -199,7 +199,7 @@ describe('sellItem', () => {
|
|
|
199
199
|
state = sellItem(
|
|
200
200
|
testState({
|
|
201
201
|
// Chosen so carrot's SPRING high-demand seasonal bonus doesn't apply.
|
|
202
|
-
dayCount:
|
|
202
|
+
dayCount: 16,
|
|
203
203
|
experience: 0,
|
|
204
204
|
inventory: [{ id: carrot.id, quantity: 3 }],
|
|
205
205
|
itemsSold: {},
|
|
@@ -276,10 +276,10 @@ describe('sellItem', () => {
|
|
|
276
276
|
|
|
277
277
|
describe('seasonal demand', () => {
|
|
278
278
|
test('applies a high demand bonus during a crop high demand season', () => {
|
|
279
|
-
// dayCount
|
|
279
|
+
// dayCount 1 is SPRING, carrot's configured high demand season.
|
|
280
280
|
const state = sellItem(
|
|
281
281
|
testState({
|
|
282
|
-
dayCount:
|
|
282
|
+
dayCount: 1,
|
|
283
283
|
inventory: [{ id: carrot.id, quantity: 1 }],
|
|
284
284
|
itemsSold: {},
|
|
285
285
|
loanBalance: 0,
|
|
@@ -298,14 +298,14 @@ describe('sellItem', () => {
|
|
|
298
298
|
})
|
|
299
299
|
|
|
300
300
|
test('bases loan garnishment on the seasonally-adjusted sale price, not the base price', () => {
|
|
301
|
-
// dayCount
|
|
301
|
+
// dayCount 1 is SPRING, carrot's configured high demand season, so the
|
|
302
302
|
// $25 base value sells for $30. Garnishment is 5% of that $30 (=
|
|
303
303
|
// $1.50), not 5% of the un-boosted $25 (= $1.25) - otherwise the
|
|
304
304
|
// effective garnishment rate would drift with the season instead of
|
|
305
305
|
// staying at a flat LOAN_GARNISHMENT_RATE.
|
|
306
306
|
const state = sellItem(
|
|
307
307
|
testState({
|
|
308
|
-
dayCount:
|
|
308
|
+
dayCount: 1,
|
|
309
309
|
inventory: [{ id: carrot.id, quantity: 1 }],
|
|
310
310
|
itemsSold: {},
|
|
311
311
|
loanBalance: 100,
|
|
@@ -325,10 +325,10 @@ describe('sellItem', () => {
|
|
|
325
325
|
})
|
|
326
326
|
|
|
327
327
|
test('applies a low demand penalty during a crop low demand season', () => {
|
|
328
|
-
// dayCount
|
|
328
|
+
// dayCount 1 is SPRING, corn's configured low demand season.
|
|
329
329
|
const state = sellItem(
|
|
330
330
|
testState({
|
|
331
|
-
dayCount:
|
|
331
|
+
dayCount: 1,
|
|
332
332
|
inventory: [{ id: corn.id, quantity: 1 }],
|
|
333
333
|
itemsSold: {},
|
|
334
334
|
loanBalance: 0,
|
|
@@ -347,11 +347,11 @@ describe('sellItem', () => {
|
|
|
347
347
|
})
|
|
348
348
|
|
|
349
349
|
test('does not apply the seasonal multiplier to seed sales', () => {
|
|
350
|
-
// dayCount
|
|
350
|
+
// dayCount 1 is SPRING, which is carrot's high demand season, but this
|
|
351
351
|
// must not apply to selling the seed - see the #140 guard in Item.tsx.
|
|
352
352
|
const state = sellItem(
|
|
353
353
|
testState({
|
|
354
|
-
dayCount:
|
|
354
|
+
dayCount: 1,
|
|
355
355
|
inventory: [{ id: carrotSeed.id, quantity: 1 }],
|
|
356
356
|
itemsSold: {},
|
|
357
357
|
loanBalance: 0,
|
package/src/shell/bootup.test.ts
CHANGED
|
@@ -23,7 +23,12 @@ describe('bootup', () => {
|
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
await waitFor(() => {
|
|
26
|
-
expect(
|
|
26
|
+
expect(
|
|
27
|
+
screen.getByText('Day 10', {
|
|
28
|
+
exact: false,
|
|
29
|
+
selector: '.day-and-progress-container span',
|
|
30
|
+
})
|
|
31
|
+
).toBeInTheDocument()
|
|
27
32
|
})
|
|
28
33
|
})
|
|
29
34
|
|
package/src/test-utils/ui.ts
CHANGED
|
@@ -3,7 +3,12 @@ import userEvent from '@testing-library/user-event'
|
|
|
3
3
|
|
|
4
4
|
export const waitForBoot = () =>
|
|
5
5
|
waitFor(() => {
|
|
6
|
-
expect(
|
|
6
|
+
expect(
|
|
7
|
+
screen.getByText('Day 1', {
|
|
8
|
+
exact: false,
|
|
9
|
+
selector: '.day-and-progress-container span',
|
|
10
|
+
})
|
|
11
|
+
).toBeInTheDocument()
|
|
7
12
|
})
|
|
8
13
|
|
|
9
14
|
export const endDay = async () => {
|
|
@@ -4,12 +4,12 @@ import { getCurrentSeason } from './getCurrentSeason.js'
|
|
|
4
4
|
|
|
5
5
|
describe('getCurrentSeason', () => {
|
|
6
6
|
test.each([
|
|
7
|
-
['returns SPRING for day
|
|
8
|
-
['returns SPRING for the last day of spring',
|
|
9
|
-
['returns SUMMER for the first day of summer',
|
|
10
|
-
['returns FALL for the first day of fall',
|
|
11
|
-
['returns WINTER for the first day of winter',
|
|
12
|
-
['wraps back around to SPRING after a full year',
|
|
7
|
+
['returns SPRING for day 1', 1, season.SPRING],
|
|
8
|
+
['returns SPRING for the last day of spring', 15, season.SPRING],
|
|
9
|
+
['returns SUMMER for the first day of summer', 16, season.SUMMER],
|
|
10
|
+
['returns FALL for the first day of fall', 31, season.FALL],
|
|
11
|
+
['returns WINTER for the first day of winter', 46, season.WINTER],
|
|
12
|
+
['wraps back around to SPRING after a full year', 61, season.SPRING],
|
|
13
13
|
] as const)('%s', (_description, dayCount, expectedSeason) => {
|
|
14
14
|
expect(getCurrentSeason(dayCount)).toEqual(expectedSeason)
|
|
15
15
|
})
|
|
@@ -2,5 +2,10 @@ import { season } from '../enums.js'
|
|
|
2
2
|
import { SEASON_ORDER } from '../data/seasons.js'
|
|
3
3
|
import { SEASON_LENGTH_DAYS } from '../constants.js'
|
|
4
4
|
|
|
5
|
+
// dayCount is 1-indexed (the first day of the game is dayCount === 1, per
|
|
6
|
+
// computeStateForNextDay.ts), so it must be shifted to 0-indexed before
|
|
7
|
+
// dividing into season-length chunks.
|
|
5
8
|
export const getCurrentSeason = (dayCount: number): season =>
|
|
6
|
-
SEASON_ORDER[
|
|
9
|
+
SEASON_ORDER[
|
|
10
|
+
Math.floor((dayCount - 1) / SEASON_LENGTH_DAYS) % SEASON_ORDER.length
|
|
11
|
+
]
|
|
@@ -2,18 +2,18 @@ import { getDayOfSeason } from './getDayOfSeason.js'
|
|
|
2
2
|
|
|
3
3
|
describe('getDayOfSeason', () => {
|
|
4
4
|
test('returns 1 for the first day of a season', () => {
|
|
5
|
-
expect(getDayOfSeason(
|
|
5
|
+
expect(getDayOfSeason(1)).toEqual(1)
|
|
6
6
|
})
|
|
7
7
|
|
|
8
8
|
test('returns the season length for the last day of a season', () => {
|
|
9
|
-
expect(getDayOfSeason(
|
|
9
|
+
expect(getDayOfSeason(15)).toEqual(15)
|
|
10
10
|
})
|
|
11
11
|
|
|
12
12
|
test('resets to 1 on the first day of the next season', () => {
|
|
13
|
-
expect(getDayOfSeason(
|
|
13
|
+
expect(getDayOfSeason(16)).toEqual(1)
|
|
14
14
|
})
|
|
15
15
|
|
|
16
16
|
test('continues counting in later seasons', () => {
|
|
17
|
-
expect(getDayOfSeason(
|
|
17
|
+
expect(getDayOfSeason(33)).toEqual(3)
|
|
18
18
|
})
|
|
19
19
|
})
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { SEASON_LENGTH_DAYS } from '../constants.js'
|
|
2
2
|
|
|
3
|
+
// dayCount is 1-indexed (the first day of the game is dayCount === 1, per
|
|
4
|
+
// computeStateForNextDay.ts), so it must be shifted to 0-indexed before
|
|
5
|
+
// taking the modulus.
|
|
3
6
|
export const getDayOfSeason = (dayCount: number): number =>
|
|
4
|
-
(dayCount % SEASON_LENGTH_DAYS) + 1
|
|
7
|
+
((dayCount - 1) % SEASON_LENGTH_DAYS) + 1
|