From d063805c0c41665dbdcac175d447d6e156dfa61c Mon Sep 17 00:00:00 2001 From: Michael Urich <80188367+mturich@users.noreply.github.com> Date: Mon, 11 Jul 2022 07:44:46 +0200 Subject: [PATCH 1/7] first test intoduced --- src/components/App.tsx | 12 +++--- src/components/{ => Dimention}/Dimension.tsx | 2 +- .../DisplayAntimatter.tsx | 2 +- .../{ => GameResetBtns}/GameResets.tsx | 4 +- src/components/{ => Tickspeed}/TickSpeed.tsx | 38 +++++++++---------- .../Tickspeed/getCostForPurchaseQty.test.tsx | 17 +++++++++ .../Tickspeed/getCostForPurchaseQty.tsx | 7 ++++ .../Tickspeed/maxPurchaseQty.test.ts | 18 +++++++++ src/components/Tickspeed/maxPurchaseQty.ts | 10 +++++ .../getMaxPurchaseQtyRecursive.test.ts | 13 ------- src/components/getMaxPurchaseQtyRecursive.ts | 7 ---- .../useLocalStorage.tsx} | 3 +- 12 files changed, 81 insertions(+), 52 deletions(-) rename src/components/{ => Dimention}/Dimension.tsx (97%) rename src/components/{ => DisplayAntimatter}/DisplayAntimatter.tsx (87%) rename src/components/{ => GameResetBtns}/GameResets.tsx (95%) rename src/components/{ => Tickspeed}/TickSpeed.tsx (70%) create mode 100644 src/components/Tickspeed/getCostForPurchaseQty.test.tsx create mode 100644 src/components/Tickspeed/getCostForPurchaseQty.tsx create mode 100644 src/components/Tickspeed/maxPurchaseQty.test.ts create mode 100644 src/components/Tickspeed/maxPurchaseQty.ts delete mode 100644 src/components/getMaxPurchaseQtyRecursive.test.ts delete mode 100644 src/components/getMaxPurchaseQtyRecursive.ts rename src/{components/useSaveToLocalStorage.tsx => customeHooks/useLocalStorage.tsx} (93%) diff --git a/src/components/App.tsx b/src/components/App.tsx index f44f9e2..5c93dfd 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,13 +1,13 @@ import { useState, useEffect, useRef } from 'react'; import '../styles/App.css'; -import Dimension from './Dimension'; -import GameResets from './GameResets'; -import Tickspeed from './TickSpeed'; +import Dimension from './Dimention/Dimension'; +import GameResets from './GameResetBtns/GameResets'; +import Tickspeed from './Tickspeed/TickSpeed'; import { GameState, Dim } from '../common/GameStateInterface'; import initialGameState from '../common/initialGameState'; -import DisplayAntimatter from './DisplayAntimatter'; -import { useSaveToLocalStorage } from './useSaveToLocalStorage'; +import DisplayAntimatter from './DisplayAntimatter/DisplayAntimatter'; +import { useLocalStorage } from '../customeHooks/useLocalStorage'; function App() { const [gameState, setGameState] = useState(() => @@ -17,7 +17,7 @@ function App() { const timerExpiredCallback = useRef(() => {}); const clockSpeedRef = useRef(2000); const timerIdRef = useRef(-1); - useSaveToLocalStorage(gameState, setGameState); + useLocalStorage(gameState, setGameState); timerExpiredCallback.current = () => { setGameState((prevGS: GameState) => ({ diff --git a/src/components/Dimension.tsx b/src/components/Dimention/Dimension.tsx similarity index 97% rename from src/components/Dimension.tsx rename to src/components/Dimention/Dimension.tsx index e06022d..c195cf5 100644 --- a/src/components/Dimension.tsx +++ b/src/components/Dimention/Dimension.tsx @@ -1,4 +1,4 @@ -import { GameState, DimProps, Dim } from '../common/GameStateInterface'; +import { GameState, DimProps, Dim } from '../../common/GameStateInterface'; export default function Dimension(props: DimProps) { const { nthDim, gs, setGameState } = props; diff --git a/src/components/DisplayAntimatter.tsx b/src/components/DisplayAntimatter/DisplayAntimatter.tsx similarity index 87% rename from src/components/DisplayAntimatter.tsx rename to src/components/DisplayAntimatter/DisplayAntimatter.tsx index 4e4c685..750a861 100644 --- a/src/components/DisplayAntimatter.tsx +++ b/src/components/DisplayAntimatter/DisplayAntimatter.tsx @@ -1,4 +1,4 @@ -import { GameState } from '../common/GameStateInterface'; +import { GameState } from '../../common/GameStateInterface'; export default function DisplayAntimatter(props: { gameState: GameState }) { const { gameState } = props; diff --git a/src/components/GameResets.tsx b/src/components/GameResetBtns/GameResets.tsx similarity index 95% rename from src/components/GameResets.tsx rename to src/components/GameResetBtns/GameResets.tsx index cdb2364..71db95b 100644 --- a/src/components/GameResets.tsx +++ b/src/components/GameResetBtns/GameResets.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react'; -import { GameState } from '../common/GameStateInterface'; -import initialGameState from '../common/initialGameState'; +import { GameState } from '../../common/GameStateInterface'; +import initialGameState from '../../common/initialGameState'; export default function GameResets(props: { gameState: GameState; setGameState: any }) { const { gameState, setGameState } = props; diff --git a/src/components/TickSpeed.tsx b/src/components/Tickspeed/TickSpeed.tsx similarity index 70% rename from src/components/TickSpeed.tsx rename to src/components/Tickspeed/TickSpeed.tsx index 0111ad1..db66e73 100644 --- a/src/components/TickSpeed.tsx +++ b/src/components/Tickspeed/TickSpeed.tsx @@ -1,5 +1,7 @@ import { useRef, useEffect, useState } from 'react'; -import { GameState } from '../common/GameStateInterface'; +import { GameState } from '../../common/GameStateInterface'; +import { getCostForPurchaseQty } from './getCostForPurchaseQty'; +import { maxPurchaseQty } from './maxPurchaseQty'; export default function Tickspeed(props: { gameState: GameState; @@ -20,38 +22,32 @@ export default function Tickspeed(props: { })); }; - const getMaxPurchaseQtyRecursive = (price: number, antimatter: number, quantity = 0): number => { - if (antimatter < price) { - return quantity - } else { - return getMaxPurchaseQtyRecursive(price * 10, antimatter - price, quantity + 1); - } - }; + const maxPurchasableQuantity = maxPurchaseQty({ + cost: gameState.tickspeedPrice, + balance: gameState.antimatter, + qty: 0, + }); - const maxPurchasableQuantity = getMaxPurchaseQtyRecursive( - gameState.tickspeedPrice, - gameState.antimatter, - 0 - ); - - const getCostForPurchaseQty = (firstCost: number, quantity: number): number => { + /* const getCostForPurchaseQty = (firstCost: number, quantity: number): number => { if (quantity == 1) { return firstCost; } else { - return firstCost + getCostForPurchaseQty(firstCost * 10, quantity - 1); - } - } + return firstCost + getCostForPurchaseQty(firstCost * 10, quantity - 1); + } + }; */ const handleBuyMaxClick = () => { - clockSpeedRef.current = clockSpeedRef.current * (1 - gameState.tickspeedDeceaseRate) ** maxPurchasableQuantity; + clockSpeedRef.current = + clockSpeedRef.current * (1 - gameState.tickspeedDeceaseRate) ** maxPurchasableQuantity; setGameState((prevGS: GameState) => ({ ...prevGS, - antimatter: prevGS.antimatter - getCostForPurchaseQty(maxPurchasableQuantity, prevGS.tickspeedPrice), + antimatter: + prevGS.antimatter - + getCostForPurchaseQty(maxPurchasableQuantity, prevGS.tickspeedPrice), tickspeedPrice: prevGS.tickspeedPrice * 10 ** maxPurchasableQuantity, })); }; - return (

{`The current clockspeed is ${clockSpeedRef.current.toFixed( diff --git a/src/components/Tickspeed/getCostForPurchaseQty.test.tsx b/src/components/Tickspeed/getCostForPurchaseQty.test.tsx new file mode 100644 index 0000000..3a4c67f --- /dev/null +++ b/src/components/Tickspeed/getCostForPurchaseQty.test.tsx @@ -0,0 +1,17 @@ +import { describe, expect, it } from 'vitest'; +import { getCostForPurchaseQty } from './getCostForPurchaseQty'; + +describe('getCostForPurchaseQty', () => { + it('if nothing is bought, there is no cost increase', () => { + expect(getCostForPurchaseQty(10, 0)).toEqual(0); + }); + it('if 1 Qty is bought, the cost is the initial cost', () => { + expect(getCostForPurchaseQty(10, 1)).toEqual(10); + }); + it('if 2 Qty are bought, the cost is the initial cost + 10 *initial cost', () => { + expect(getCostForPurchaseQty(10, 2)).toEqual(110); + }); + it('if 5 Qty are bought, the cost is the initial cost + 10 *initial cost + ... + 10^5*initial cost', () => { + expect(getCostForPurchaseQty(10, 2)).toEqual(111110); + }); +}); diff --git a/src/components/Tickspeed/getCostForPurchaseQty.tsx b/src/components/Tickspeed/getCostForPurchaseQty.tsx new file mode 100644 index 0000000..295c8f4 --- /dev/null +++ b/src/components/Tickspeed/getCostForPurchaseQty.tsx @@ -0,0 +1,7 @@ +export const getCostForPurchaseQty = (firstCost: number, quantity: number): number => { + if (quantity === 0) return 0; + else if (quantity === 1) { + return firstCost; + } else return firstCost + getCostForPurchaseQty(firstCost * 10, quantity - 1) +}; + \ No newline at end of file diff --git a/src/components/Tickspeed/maxPurchaseQty.test.ts b/src/components/Tickspeed/maxPurchaseQty.test.ts new file mode 100644 index 0000000..3f03b45 --- /dev/null +++ b/src/components/Tickspeed/maxPurchaseQty.test.ts @@ -0,0 +1,18 @@ +import { maxPurchaseQty } from './maxPurchaseQty'; +import { describe, expect, it } from 'vitest'; + +describe('maxPurchaseQty', () => { + it('return zero if we have no money', () => { + expect(maxPurchaseQty({ cost: 1234242, balance: 0, qty: 0 })).toEqual(0); + }); + it('return one if we can afford only one', () => { + expect(maxPurchaseQty({ cost: 10, balance: 100, qty: 0 })).toEqual(1); + }); + + it('return 2 if we can afford only 2', () => { + expect(maxPurchaseQty({ cost: 10, balance: 110, qty: 0 })).toEqual(2); + }); + it('return 3 if we can afford only 3', () => { + expect(maxPurchaseQty({ cost: 10, balance: 1110, qty: 0 })).toEqual(3); + }); +}); diff --git a/src/components/Tickspeed/maxPurchaseQty.ts b/src/components/Tickspeed/maxPurchaseQty.ts new file mode 100644 index 0000000..4024c59 --- /dev/null +++ b/src/components/Tickspeed/maxPurchaseQty.ts @@ -0,0 +1,10 @@ +interface maxPurchaseQtyInterface { + cost: number; + balance: number; + qty: number; +} + +export const maxPurchaseQty = ({ cost, balance, qty = 0 }: maxPurchaseQtyInterface): number => { + if (cost > balance) return qty; + else return maxPurchaseQty({ cost: cost * 10, balance: balance - cost, qty: qty + 1 }); +}; diff --git a/src/components/getMaxPurchaseQtyRecursive.test.ts b/src/components/getMaxPurchaseQtyRecursive.test.ts deleted file mode 100644 index 0e45733..0000000 --- a/src/components/getMaxPurchaseQtyRecursive.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { maxPurchaseQty } from "./getMaxPurchaseQtyRecursive"; -import {describe, expect, it} from "vitest"; - -describe("getMaxPurchaseQtyRecursive ", ()=>{ - - it('return zero if we have no money', () => { - expect(maxPurchaseQty({cost: 1234242, balance: 0})).toEqual(0) - }) - it('return one if we can afoard only one', () => { - expect(maxPurchaseQty({ cost: 100, balance: 100})).toEqual(1) - }) - -}); diff --git a/src/components/getMaxPurchaseQtyRecursive.ts b/src/components/getMaxPurchaseQtyRecursive.ts deleted file mode 100644 index cc9a8e3..0000000 --- a/src/components/getMaxPurchaseQtyRecursive.ts +++ /dev/null @@ -1,7 +0,0 @@ - - -export const maxPurchaseQty = ({cost, balance}) => { - - return 0; - -}; diff --git a/src/components/useSaveToLocalStorage.tsx b/src/customeHooks/useLocalStorage.tsx similarity index 93% rename from src/components/useSaveToLocalStorage.tsx rename to src/customeHooks/useLocalStorage.tsx index 67fba85..097d9ef 100644 --- a/src/components/useSaveToLocalStorage.tsx +++ b/src/customeHooks/useLocalStorage.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef } from 'react'; import { Dim, GameState } from '../common/GameStateInterface'; -export function useSaveToLocalStorage(gameState: GameState, setGameState) { +export function useLocalStorage(gameState: GameState, setGameState:Function):void { const saveLocStorageRef = useRef(-1); const displayLocStorageRef = useRef(-1); @@ -21,6 +21,7 @@ export function useSaveToLocalStorage(gameState: GameState, setGameState) { saveDateRecursive(gameState); }, [gameState]); + // this prints the saved object from local storage. It is just for dev. No final purpose /* useEffect(() => { From 6d355a00d4f84d9723ee3f5872cfcd2be7e5d3bc Mon Sep 17 00:00:00 2001 From: Michael Urich <80188367+mturich@users.noreply.github.com> Date: Mon, 11 Jul 2022 13:43:18 +0200 Subject: [PATCH 2/7] changed strucutre of the project --- src/components/App.tsx | 13 +++-- src/components/Tickspeed/TickSpeed.tsx | 49 ++++++++----------- .../Tickspeed/calcMaxPurchasableQty.test.ts | 19 +++++++ .../Tickspeed/calcMaxPurchasableQty.ts | 10 ++++ .../Tickspeed/maxPurchaseQty.test.ts | 18 ------- src/components/Tickspeed/maxPurchaseQty.ts | 10 ---- 6 files changed, 55 insertions(+), 64 deletions(-) create mode 100644 src/components/Tickspeed/calcMaxPurchasableQty.test.ts create mode 100644 src/components/Tickspeed/calcMaxPurchasableQty.ts delete mode 100644 src/components/Tickspeed/maxPurchaseQty.test.ts delete mode 100644 src/components/Tickspeed/maxPurchaseQty.ts diff --git a/src/components/App.tsx b/src/components/App.tsx index 5c93dfd..e32e68b 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -3,19 +3,18 @@ import '../styles/App.css'; import Dimension from './Dimention/Dimension'; import GameResets from './GameResetBtns/GameResets'; import Tickspeed from './Tickspeed/TickSpeed'; +import DisplayAntimatter from './DisplayAntimatter/DisplayAntimatter'; +import initialGameState from '../common/initialGameState'; import { GameState, Dim } from '../common/GameStateInterface'; -import initialGameState from '../common/initialGameState'; -import DisplayAntimatter from './DisplayAntimatter/DisplayAntimatter'; import { useLocalStorage } from '../customeHooks/useLocalStorage'; function App() { const [gameState, setGameState] = useState(() => JSON.parse(localStorage.getItem('data') || initialGameState) ); - /* JSON.parse(localStorage.getItem('data')) */ const timerExpiredCallback = useRef(() => {}); - const clockSpeedRef = useRef(2000); + const tickspeedRef = useRef(2000); const timerIdRef = useRef(-1); useLocalStorage(gameState, setGameState); @@ -41,7 +40,7 @@ function App() { timerIdRef.current = setTimeout(() => { timerExpiredCallback.current(); startTimer(); - }, clockSpeedRef.current); + }, tickspeedRef.current); }; startTimer(); @@ -56,7 +55,7 @@ function App() { + tickspeedRef={tickspeedRef}> {`First Dimension Cost: ${gameState.dims[0].dimPrice}`} @@ -98,7 +97,7 @@ function App() { {`Eight Dimension Cost: ${gameState.dims[2].dimPrice}`} )} - +



diff --git a/src/components/Tickspeed/TickSpeed.tsx b/src/components/Tickspeed/TickSpeed.tsx index db66e73..42c412f 100644 --- a/src/components/Tickspeed/TickSpeed.tsx +++ b/src/components/Tickspeed/TickSpeed.tsx @@ -1,56 +1,47 @@ import { useRef, useEffect, useState } from 'react'; import { GameState } from '../../common/GameStateInterface'; import { getCostForPurchaseQty } from './getCostForPurchaseQty'; -import { maxPurchaseQty } from './maxPurchaseQty'; +import { calcMaxPurchasableQty } from './calcMaxPurchasableQty'; export default function Tickspeed(props: { gameState: GameState; - setGameState: any; - clockSpeedRef: any; + setGameState: Function; + tickspeedRef: any; }) { - const { gameState, setGameState, clockSpeedRef } = props; + const { gameState, setGameState, tickspeedRef } = props; const [buyMax, setBuyMax] = useState( Math.log10(gameState.antimatter / gameState.tickspeedPrice) ); - // const maxPossibleBuys = useRef(~~Math.log10(gameState.antimatter / gameState.tickspeedPrice)); + + // calculte the maximal purchasable + const maxPurchaseQtys = calcMaxPurchasableQty({ + cost: gameState.tickspeedPrice, + balance: gameState.antimatter, + qty: 0, + }); + const purchasePrice = getCostForPurchaseQty(gameState.tickspeedPrice, maxPurchaseQtys); + const handleTickBtnClick = () => { - clockSpeedRef.current = clockSpeedRef.current * (1 - gameState.tickspeedDeceaseRate); + tickspeedRef.current = tickspeedRef.current * (1 - gameState.tickspeedDeceaseRate); setGameState((prevGS: GameState) => ({ ...prevGS, antimatter: prevGS.antimatter - prevGS.tickspeedPrice, tickspeedPrice: prevGS.tickspeedPrice * 10, })); }; - - const maxPurchasableQuantity = maxPurchaseQty({ - cost: gameState.tickspeedPrice, - balance: gameState.antimatter, - qty: 0, - }); - - /* const getCostForPurchaseQty = (firstCost: number, quantity: number): number => { - if (quantity == 1) { - return firstCost; - } else { - return firstCost + getCostForPurchaseQty(firstCost * 10, quantity - 1); - } - }; */ - const handleBuyMaxClick = () => { - clockSpeedRef.current = - clockSpeedRef.current * (1 - gameState.tickspeedDeceaseRate) ** maxPurchasableQuantity; + tickspeedRef.current = + tickspeedRef.current * (1 - gameState.tickspeedDeceaseRate) ** maxPurchaseQtys; setGameState((prevGS: GameState) => ({ ...prevGS, - antimatter: - prevGS.antimatter - - getCostForPurchaseQty(maxPurchasableQuantity, prevGS.tickspeedPrice), - tickspeedPrice: prevGS.tickspeedPrice * 10 ** maxPurchasableQuantity, + antimatter: prevGS.antimatter - purchasePrice, + tickspeedPrice: prevGS.tickspeedPrice * 10 ** maxPurchaseQtys, })); }; return (
-

{`The current clockspeed is ${clockSpeedRef.current.toFixed( +

{`The current clockspeed is ${tickspeedRef.current.toFixed( 0 )} ms. Reduce the tickspeed by ${gameState.tickspeedDeceaseRate * 100}%.`}

@@ -64,7 +55,7 @@ export default function Tickspeed(props: { className='btn' onClick={handleBuyMaxClick} disabled={gameState.antimatter < gameState.tickspeedPrice}> - Buy Max ({maxPurchasableQuantity}) + Buy Max ({maxPurchaseQtys})
diff --git a/src/components/Tickspeed/calcMaxPurchasableQty.test.ts b/src/components/Tickspeed/calcMaxPurchasableQty.test.ts new file mode 100644 index 0000000..862afff --- /dev/null +++ b/src/components/Tickspeed/calcMaxPurchasableQty.test.ts @@ -0,0 +1,19 @@ +import { calcMaxPurchasableQty } from './calcMaxPurchasableQty'; +import { describe, expect, it } from 'vitest'; + +describe('maxPurchaseQty', () => { + it('return zero if we have no money', () => { + expect(calcMaxPurchasableQty({ cost: 1234242, balance: 0, qty: 0 })).toEqual(0); + }); + it('return one if we can afford only one', () => { + expect(calcMaxPurchasableQty({ cost: 10, balance: 100, qty: 0 })).toEqual(1); + }); + + it('return 2 if we can afford only 2', () => { + expect(calcMaxPurchasableQty({ cost: 10, balance: 110, qty: 0 })).toEqual(2); + }); + it('return 3 if we can afford only 3', () => { + expect(calcMaxPurchasableQty + ({ cost: 10, balance: 1110, qty: 0 })).toEqual(3); + }); +}); diff --git a/src/components/Tickspeed/calcMaxPurchasableQty.ts b/src/components/Tickspeed/calcMaxPurchasableQty.ts new file mode 100644 index 0000000..95f23c0 --- /dev/null +++ b/src/components/Tickspeed/calcMaxPurchasableQty.ts @@ -0,0 +1,10 @@ +interface calcMaxPurchasableQtyInterface { + cost: number; + balance: number; + qty: number; +} + +export const calcMaxPurchasableQty = ({ cost, balance, qty = 0 }: calcMaxPurchasableQtyInterface): number => { + if (cost > balance) return qty; + else return calcMaxPurchasableQty({ cost: cost * 10, balance: balance - cost, qty: qty + 1 }); +}; diff --git a/src/components/Tickspeed/maxPurchaseQty.test.ts b/src/components/Tickspeed/maxPurchaseQty.test.ts deleted file mode 100644 index 3f03b45..0000000 --- a/src/components/Tickspeed/maxPurchaseQty.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { maxPurchaseQty } from './maxPurchaseQty'; -import { describe, expect, it } from 'vitest'; - -describe('maxPurchaseQty', () => { - it('return zero if we have no money', () => { - expect(maxPurchaseQty({ cost: 1234242, balance: 0, qty: 0 })).toEqual(0); - }); - it('return one if we can afford only one', () => { - expect(maxPurchaseQty({ cost: 10, balance: 100, qty: 0 })).toEqual(1); - }); - - it('return 2 if we can afford only 2', () => { - expect(maxPurchaseQty({ cost: 10, balance: 110, qty: 0 })).toEqual(2); - }); - it('return 3 if we can afford only 3', () => { - expect(maxPurchaseQty({ cost: 10, balance: 1110, qty: 0 })).toEqual(3); - }); -}); diff --git a/src/components/Tickspeed/maxPurchaseQty.ts b/src/components/Tickspeed/maxPurchaseQty.ts deleted file mode 100644 index 4024c59..0000000 --- a/src/components/Tickspeed/maxPurchaseQty.ts +++ /dev/null @@ -1,10 +0,0 @@ -interface maxPurchaseQtyInterface { - cost: number; - balance: number; - qty: number; -} - -export const maxPurchaseQty = ({ cost, balance, qty = 0 }: maxPurchaseQtyInterface): number => { - if (cost > balance) return qty; - else return maxPurchaseQty({ cost: cost * 10, balance: balance - cost, qty: qty + 1 }); -}; From 9b18b0b5c549064620fe18abdb49cfccf7791900 Mon Sep 17 00:00:00 2001 From: Michael Urich <80188367+mturich@users.noreply.github.com> Date: Mon, 11 Jul 2022 14:43:42 +0200 Subject: [PATCH 3/7] first Refactoring for useReducer; Dimension works --- src/common/GameStateInterface.ts | 2 +- src/components/App.tsx | 137 ++++++++++++++++--------- src/components/Dimention/Dimension.tsx | 44 ++------ 3 files changed, 99 insertions(+), 84 deletions(-) diff --git a/src/common/GameStateInterface.ts b/src/common/GameStateInterface.ts index a14c3c7..8d988f4 100644 --- a/src/common/GameStateInterface.ts +++ b/src/common/GameStateInterface.ts @@ -20,6 +20,6 @@ export interface Dim { export type DimProps = { nthDim: number; gs: GameState; - setGameState: (fn: (gameState: GameState) => void) => void; + dispatch: Function; children: string; }; diff --git a/src/components/App.tsx b/src/components/App.tsx index e32e68b..e02b7bd 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from 'react'; +import { useState, useEffect, useRef, useReducer } from 'react'; import '../styles/App.css'; import Dimension from './Dimention/Dimension'; import GameResets from './GameResetBtns/GameResets'; @@ -9,31 +9,74 @@ import initialGameState from '../common/initialGameState'; import { GameState, Dim } from '../common/GameStateInterface'; import { useLocalStorage } from '../customeHooks/useLocalStorage'; +export const ACTIONS = { + TIMER_CALLBACK: 'TIMER_CALLBACK', + UPDATE_DIM: 'UPDATE_DIM', + UPDATE_10TH_DIM: 'UPDATE_10TH_DIM', +}; + +function reducer(state: GameState, action: { type: string; payload?: any }) { + switch (action.type) { + case ACTIONS.TIMER_CALLBACK: + return { + ...state, + antimatter: state.antimatter + state.dims[0].dimCount * state.dims[0].dimFactor, + dims: state.dims.map((dim: Dim, index: number) => { + return { + ...dim, + dimCount: + dim.dimCount + + ((state.dims[index + 1]?.dimCount ?? 0) * + (state.dims[index + 1]?.dimFactor ?? 0)) / + Math.pow(10, index + 1), + }; + }), + }; + case ACTIONS.UPDATE_DIM: + return { + ...state, + antimatter: + state.antimatter - + state.dims[action.payload.nthDim].dimPrice * action.payload.quantity, + dims: state.dims.map((dim: Dim) => { + if (dim.nthDim !== action.payload.nthDim) return dim; + return { + ...dim, + dimCount: dim.dimCount + action.payload.quantity, + dimFactorCount: dim.dimFactorCount + action.payload.quantity, + }; + }), + }; + case ACTIONS.UPDATE_10TH_DIM: + return { + ...state, + dims: state.dims.map((dim: Dim) => { + if (dim.nthDim !== action.payload.nthDim) return dim; + return { + ...dim, + dimPrice: dim.dimPrice * 10, + dimFactor: dim.dimFactor * 2, + dimFactorCount: 0, + }; + }), + }; + default: + return state; + } +} + function App() { - const [gameState, setGameState] = useState(() => + const [state, dispatch] = useReducer( + reducer, JSON.parse(localStorage.getItem('data') || initialGameState) ); + const timerExpiredCallback = useRef(() => {}); const tickspeedRef = useRef(2000); const timerIdRef = useRef(-1); - useLocalStorage(gameState, setGameState); + useLocalStorage(state, dispatch); - timerExpiredCallback.current = () => { - setGameState((prevGS: GameState) => ({ - ...prevGS, - antimatter: prevGS.antimatter + prevGS.dims[0].dimCount * prevGS.dims[0].dimFactor, - dims: gameState.dims.map((dim: Dim, index: number) => { - return { - ...dim, - dimCount: - dim.dimCount + - ((gameState.dims[index + 1]?.dimCount ?? 0) * - (gameState.dims[index + 1]?.dimFactor ?? 0)) / - Math.pow(10, index + 1), - }; - }), - })); - }; + timerExpiredCallback.current = () => dispatch({ type: ACTIONS.TIMER_CALLBACK }); useEffect(() => { const startTimer = () => { @@ -50,58 +93,58 @@ function App() { return (
- - + + {/* + gameState={state} + dispatch={dispatch} + tickspeedRef={tickspeedRef}> */} - - {`First Dimension Cost: ${gameState.dims[0].dimPrice}`} + + {`First Dimension Cost: ${state.dims[0].dimPrice}`} - - {`Second Dimension Cost: ${gameState.dims[1].dimPrice}`} + + {`Second Dimension Cost: ${state.dims[1].dimPrice}`} { //the 3. dimension must be unlocked } - {gameState.resetGameCounter > 2 && ( - - {`Third Dimension Cost: ${gameState.dims[2].dimPrice}`} + {state.resetGameCounter > 2 && ( + + {`Third Dimension Cost: ${state.dims[2].dimPrice}`} )} - {gameState.resetGameCounter > 3 && ( - - {`Forth Dimension Cost: ${gameState.dims[2].dimPrice}`} + {state.resetGameCounter > 3 && ( + + {`Forth Dimension Cost: ${state.dims[2].dimPrice}`} )} - {gameState.resetGameCounter > 4 && ( - - {`Fifth Dimension Cost: ${gameState.dims[2].dimPrice}`} + {state.resetGameCounter > 4 && ( + + {`Fifth Dimension Cost: ${state.dims[2].dimPrice}`} )} - {gameState.resetGameCounter > 5 && ( - - {`Sixth Dimension Cost: ${gameState.dims[2].dimPrice}`} + {state.resetGameCounter > 5 && ( + + {`Sixth Dimension Cost: ${state.dims[2].dimPrice}`} )} - {gameState.resetGameCounter > 6 && ( - - {`Seventh Dimension Cost: ${gameState.dims[2].dimPrice}`} + {state.resetGameCounter > 6 && ( + + {`Seventh Dimension Cost: ${state.dims[2].dimPrice}`} )} - {gameState.resetGameCounter > 7 && ( - - {`Eight Dimension Cost: ${gameState.dims[2].dimPrice}`} + {state.resetGameCounter > 7 && ( + + {`Eight Dimension Cost: ${state.dims[2].dimPrice}`} )}

- + {/* */}
); } diff --git a/src/components/Dimention/Dimension.tsx b/src/components/Dimention/Dimension.tsx index c195cf5..59a2913 100644 --- a/src/components/Dimention/Dimension.tsx +++ b/src/components/Dimention/Dimension.tsx @@ -1,49 +1,21 @@ -import { GameState, DimProps, Dim } from '../../common/GameStateInterface'; +import { DimProps } from '../../common/GameStateInterface'; +import { ACTIONS } from '../App'; export default function Dimension(props: DimProps) { - const { nthDim, gs, setGameState } = props; + const { nthDim, gs, dispatch } = props; const handleDimBuy = (quantity: number) => { - const newDim = [gs.dims[nthDim].dimCount + quantity]; - if (gs.antimatter >= gs.dims[nthDim].dimPrice) { - /* - setDimCount(dimCount => dimCount + quantity); - setAntimatter(prevValue => prevValue - price * quantity); - setDimFactorCount(prevCount => prevCount + 1); */ - setGameState((prevGS: GameState) => ({ - ...prevGS, - antimatter: prevGS.antimatter - prevGS.dims[nthDim].dimPrice * quantity, - dims: prevGS.dims.map((dim: Dim, index: number) => { - if (dim.nthDim !== nthDim) return dim; - return { - ...dim, - dimCount: dim.dimCount + quantity, - dimFactorCount: dim.dimFactorCount + quantity, - }; - }), - })); + dispatch({ type: ACTIONS.UPDATE_DIM, payload: { nthDim: nthDim, quantity: quantity } }); } if ( ((gs.dims[nthDim].dimCount + 1) % 10 === 0 && gs.dims[nthDim].dimCount > 1) || quantity === 10 ) { - /* - setPrice(prevPrice => prevPrice * 10); - setFactor(prevFactor => prevFactor * 2) - setDimFactorCount(0) */ - setGameState((prevGS: GameState) => ({ - ...prevGS, - dims: prevGS.dims.map((dim: Dim, index: number) => { - if (dim.nthDim !== nthDim) return dim; - return { - ...dim, - dimPrice: dim.dimPrice * 10, - dimFactor: dim.dimFactor * 2, - dimFactorCount: 0, - }; - }), - })); + dispatch({ + type: ACTIONS.UPDATE_10TH_DIM, + payload: { nthDim: nthDim, quantity: quantity }, + }); } }; From 99ed941336603cb063a175633a54939f6e08443e Mon Sep 17 00:00:00 2001 From: Michael Urich <80188367+mturich@users.noreply.github.com> Date: Mon, 11 Jul 2022 15:07:01 +0200 Subject: [PATCH 4/7] useReducer implementation finished --- src/common/reducer.tsx | 98 +++++++++++++++++++++ src/components/App.tsx | 66 ++------------ src/components/Dimention/Dimension.tsx | 2 +- src/components/GameResetBtns/GameResets.tsx | 55 +++++------- src/components/Tickspeed/TickSpeed.tsx | 49 ++++------- 5 files changed, 145 insertions(+), 125 deletions(-) create mode 100644 src/common/reducer.tsx diff --git a/src/common/reducer.tsx b/src/common/reducer.tsx new file mode 100644 index 0000000..43171c8 --- /dev/null +++ b/src/common/reducer.tsx @@ -0,0 +1,98 @@ +import { Dim, GameState } from './GameStateInterface'; +import initialGameState from './initialGameState'; + +export const ACTIONS = { + TIMER_CALLBACK: 'TIMER_CALLBACK', + UPDATE_DIM: 'UPDATE_DIM', + UPDATE_10TH_DIM: 'UPDATE_10TH_DIM', + UPDATE_TICKSPEED_ONCE: 'UPDATE_TICKSPEED_ONCE', + UPDATE_TICKSPEED_MAX: 'UPDATE_TICKSPEED_MAX', + RESET_TO_UNLOCK_DIM: 'RESET_TO_UNLOCK_DIM', + RESET_TO_UNLOCK_TICKSPEED: 'RESET_TO_UNLOCK_TICKSPEED', + RESET_TO_INITIAL_VALUES: 'RESET_TO_INITIAL_VALUES', +}; + +export function reducer(state: GameState, action: { type: string; payload?: any }) { + switch (action.type) { + case ACTIONS.TIMER_CALLBACK: + return { + ...state, + antimatter: state.antimatter + state.dims[0].dimCount * state.dims[0].dimFactor, + dims: state.dims.map((dim: Dim, index: number) => { + return { + ...dim, + dimCount: + dim.dimCount + + ((state.dims[index + 1]?.dimCount ?? 0) * + (state.dims[index + 1]?.dimFactor ?? 0)) / + Math.pow(10, index + 1), + }; + }), + }; + + case ACTIONS.UPDATE_DIM: + return { + ...state, + antimatter: + state.antimatter - + state.dims[action.payload.nthDim].dimPrice * action.payload.quantity, + dims: state.dims.map((dim: Dim) => { + if (dim.nthDim !== action.payload.nthDim) return dim; + return { + ...dim, + dimCount: dim.dimCount + action.payload.quantity, + dimFactorCount: dim.dimFactorCount + action.payload.quantity, + }; + }), + }; + + case ACTIONS.UPDATE_10TH_DIM: + return { + ...state, + dims: state.dims.map((dim: Dim) => { + if (dim.nthDim !== action.payload.nthDim) return dim; + return { + ...dim, + dimPrice: dim.dimPrice * 10, + dimFactor: dim.dimFactor * 2, + dimFactorCount: 0, + }; + }), + }; + + case ACTIONS.UPDATE_TICKSPEED_ONCE: + return { + ...state, + antimatter: state.antimatter - state.tickspeedPrice, + tickspeedPrice: state.tickspeedPrice * 10, + }; + case ACTIONS.UPDATE_TICKSPEED_MAX: + return { + ...state, + antimatter: state.antimatter - action.payload.purchasePrice, + tickspeedPrice: state.tickspeedPrice * 10 ** action.payload.maxPurchaseQtys, + }; + + case ACTIONS.RESET_TO_UNLOCK_DIM: + return { + ...JSON.parse(initialGameState), + galaxyCounter: state.galaxyCounter, + resetGameCounter: state.resetGameCounter + 1, + lastSavedTime: state.lastSavedTime, + }; + + case ACTIONS.RESET_TO_UNLOCK_TICKSPEED: + return { + ...JSON.parse(initialGameState), + galaxyCounter: state.galaxyCounter + 1, + tickspeedDeceaseRate: 0.12, + resetGameCounter: state.resetGameCounter, + lastSavedTime: state.lastSavedTime, + }; + + case ACTIONS.RESET_TO_INITIAL_VALUES: + return JSON.parse(initialGameState); + default: + return state; + } +} diff --git a/src/components/App.tsx b/src/components/App.tsx index e02b7bd..189e245 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -6,64 +6,8 @@ import Tickspeed from './Tickspeed/TickSpeed'; import DisplayAntimatter from './DisplayAntimatter/DisplayAntimatter'; import initialGameState from '../common/initialGameState'; -import { GameState, Dim } from '../common/GameStateInterface'; import { useLocalStorage } from '../customeHooks/useLocalStorage'; - -export const ACTIONS = { - TIMER_CALLBACK: 'TIMER_CALLBACK', - UPDATE_DIM: 'UPDATE_DIM', - UPDATE_10TH_DIM: 'UPDATE_10TH_DIM', -}; - -function reducer(state: GameState, action: { type: string; payload?: any }) { - switch (action.type) { - case ACTIONS.TIMER_CALLBACK: - return { - ...state, - antimatter: state.antimatter + state.dims[0].dimCount * state.dims[0].dimFactor, - dims: state.dims.map((dim: Dim, index: number) => { - return { - ...dim, - dimCount: - dim.dimCount + - ((state.dims[index + 1]?.dimCount ?? 0) * - (state.dims[index + 1]?.dimFactor ?? 0)) / - Math.pow(10, index + 1), - }; - }), - }; - case ACTIONS.UPDATE_DIM: - return { - ...state, - antimatter: - state.antimatter - - state.dims[action.payload.nthDim].dimPrice * action.payload.quantity, - dims: state.dims.map((dim: Dim) => { - if (dim.nthDim !== action.payload.nthDim) return dim; - return { - ...dim, - dimCount: dim.dimCount + action.payload.quantity, - dimFactorCount: dim.dimFactorCount + action.payload.quantity, - }; - }), - }; - case ACTIONS.UPDATE_10TH_DIM: - return { - ...state, - dims: state.dims.map((dim: Dim) => { - if (dim.nthDim !== action.payload.nthDim) return dim; - return { - ...dim, - dimPrice: dim.dimPrice * 10, - dimFactor: dim.dimFactor * 2, - dimFactorCount: 0, - }; - }), - }; - default: - return state; - } -} +import { ACTIONS, reducer } from '../common/reducer'; function App() { const [state, dispatch] = useReducer( @@ -94,11 +38,11 @@ function App() { return (
- {/* + */} + tickspeedRef={tickspeedRef}> {`First Dimension Cost: ${state.dims[0].dimPrice}`} @@ -144,7 +88,7 @@ function App() {

- {/* */} +
); } diff --git a/src/components/Dimention/Dimension.tsx b/src/components/Dimention/Dimension.tsx index 59a2913..0d099a4 100644 --- a/src/components/Dimention/Dimension.tsx +++ b/src/components/Dimention/Dimension.tsx @@ -1,5 +1,5 @@ import { DimProps } from '../../common/GameStateInterface'; -import { ACTIONS } from '../App'; +import { ACTIONS } from '../../common/reducer'; export default function Dimension(props: DimProps) { const { nthDim, gs, dispatch } = props; diff --git a/src/components/GameResetBtns/GameResets.tsx b/src/components/GameResetBtns/GameResets.tsx index 71db95b..f68a4b2 100644 --- a/src/components/GameResetBtns/GameResets.tsx +++ b/src/components/GameResetBtns/GameResets.tsx @@ -1,60 +1,49 @@ import { useEffect, useRef } from 'react'; import { GameState } from '../../common/GameStateInterface'; import initialGameState from '../../common/initialGameState'; +import { ACTIONS } from '../../common/reducer'; -export default function GameResets(props: { gameState: GameState; setGameState: any }) { - const { gameState, setGameState } = props; - const resetGameCounterRef = useRef(gameState.resetGameCounter); +export default function GameResets(props: { gs: GameState; dispatch: Function }) { + const { gs, dispatch } = props; + const resetGameCounterRef = useRef(gs.resetGameCounter); useEffect(() => { - resetGameCounterRef.current = gameState.resetGameCounter; - }, [gameState.resetGameCounter]); + resetGameCounterRef.current = gs.resetGameCounter; + }, [gs.resetGameCounter]); const handleResetGameClick = () => { - setGameState((prevGS: GameState) => ({ - ...JSON.parse(initialGameState), - galaxyCounter: prevGS.galaxyCounter, - resetGameCounter: prevGS.resetGameCounter + 1, - lastSavedTime: prevGS.lastSavedTime, - })); + dispatch({ type: ACTIONS.RESET_TO_UNLOCK_DIM }); }; const handleGalaxyBtn = () => { - setGameState((prevGS: GameState) => ({ - ...JSON.parse(initialGameState), - galaxyCounter: prevGS.galaxyCounter + 1, - tickspeedDeceaseRate: 0.12, - resetGameCounter: prevGS.resetGameCounter, - lastSavedTime: prevGS.lastSavedTime, - })); + dispatch({ type: ACTIONS.RESET_TO_UNLOCK_TICKSPEED }); }; const disableResetBtn = () => { - if ( - gameState.resetGameCounter < 7 && - gameState.dims[gameState.resetGameCounter - 1].dimCount < 20 - ) - return true; + if (gs.resetGameCounter < 7 && gs.dims[gs.resetGameCounter - 1].dimCount < 20) return true; else return false; }; return ( <>
-

{`Dimension Shift (${gameState.resetGameCounter}) `}

-

{`requires 20 ${gameState.resetGameCounter}. Dimension `}

-
-

{`Antimatter Galaxies (${gameState.galaxyCounter})`}

+

{`Antimatter Galaxies (${gs.galaxyCounter})`}

{`requires 80 8. Dimension `}

-
@@ -63,7 +52,7 @@ export default function GameResets(props: { gameState: GameState; setGameState:

{`resets everything`}

diff --git a/src/components/Tickspeed/TickSpeed.tsx b/src/components/Tickspeed/TickSpeed.tsx index 42c412f..a8a10cc 100644 --- a/src/components/Tickspeed/TickSpeed.tsx +++ b/src/components/Tickspeed/TickSpeed.tsx @@ -1,60 +1,49 @@ -import { useRef, useEffect, useState } from 'react'; +import { useState } from 'react'; import { GameState } from '../../common/GameStateInterface'; import { getCostForPurchaseQty } from './getCostForPurchaseQty'; import { calcMaxPurchasableQty } from './calcMaxPurchasableQty'; +import { ACTIONS } from '../../common/reducer'; -export default function Tickspeed(props: { - gameState: GameState; - setGameState: Function; - tickspeedRef: any; -}) { - const { gameState, setGameState, tickspeedRef } = props; - const [buyMax, setBuyMax] = useState( - Math.log10(gameState.antimatter / gameState.tickspeedPrice) - ); +export default function Tickspeed(props: { gs: GameState; dispatch: Function; tickspeedRef: any }) { + const { gs, dispatch, tickspeedRef } = props; // calculte the maximal purchasable const maxPurchaseQtys = calcMaxPurchasableQty({ - cost: gameState.tickspeedPrice, - balance: gameState.antimatter, + cost: gs.tickspeedPrice, + balance: gs.antimatter, qty: 0, }); - const purchasePrice = getCostForPurchaseQty(gameState.tickspeedPrice, maxPurchaseQtys); - + const purchasePrice = getCostForPurchaseQty(gs.tickspeedPrice, maxPurchaseQtys); + const handleTickBtnClick = () => { - tickspeedRef.current = tickspeedRef.current * (1 - gameState.tickspeedDeceaseRate); - setGameState((prevGS: GameState) => ({ - ...prevGS, - antimatter: prevGS.antimatter - prevGS.tickspeedPrice, - tickspeedPrice: prevGS.tickspeedPrice * 10, - })); + tickspeedRef.current = tickspeedRef.current * (1 - gs.tickspeedDeceaseRate); + dispatch({ type: ACTIONS.UPDATE_TICKSPEED_ONCE }); }; const handleBuyMaxClick = () => { tickspeedRef.current = - tickspeedRef.current * (1 - gameState.tickspeedDeceaseRate) ** maxPurchaseQtys; - setGameState((prevGS: GameState) => ({ - ...prevGS, - antimatter: prevGS.antimatter - purchasePrice, - tickspeedPrice: prevGS.tickspeedPrice * 10 ** maxPurchaseQtys, - })); + tickspeedRef.current * (1 - gs.tickspeedDeceaseRate) ** maxPurchaseQtys; + dispatch({ + type: ACTIONS.UPDATE_TICKSPEED_MAX, + payload: { maxPurchaseQtys: maxPurchaseQtys, purchasePrice: purchasePrice }, + }); }; return (

{`The current clockspeed is ${tickspeedRef.current.toFixed( 0 - )} ms. Reduce the tickspeed by ${gameState.tickspeedDeceaseRate * 100}%.`}

+ )} ms. Reduce the tickspeed by ${gs.tickspeedDeceaseRate * 100}%.`}

From 60bb079a90e7561730499ed35083799bdbf681b8 Mon Sep 17 00:00:00 2001 From: Michael Urich <80188367+mturich@users.noreply.github.com> Date: Tue, 12 Jul 2022 14:09:23 +0200 Subject: [PATCH 5/7] bugs solved, notification when game is saved --- package.json | 1 + src/common/initialGameState.ts | 2 +- src/common/reducer.tsx | 13 +- src/components/App.tsx | 23 +++- src/components/GameResetBtns/GameResets.tsx | 33 +++-- src/components/Tickspeed/TickSpeed.tsx | 2 +- src/customeHooks/useLocalStorage.tsx | 26 +--- src/styles/App.css | 128 +++++++++++++++++++- yarn.lock | 5 + 9 files changed, 190 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index aec91fa..25edcaf 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "test": "vitest" }, "dependencies": { + "clsx": "^1.2.1", "react": "^18.0.0", "react-dom": "^18.0.0" }, diff --git a/src/common/initialGameState.ts b/src/common/initialGameState.ts index 08e6dba..79be01f 100644 --- a/src/common/initialGameState.ts +++ b/src/common/initialGameState.ts @@ -6,7 +6,7 @@ let initialGameState: GameState = { tickspeedDeceaseRate: 0.11, resetGameCounter: 2, galaxyCounter: 0, - lastSavedTime: 0, + lastSavedTime: Date.now(), dims: [ { nthDim: 0, diff --git a/src/common/reducer.tsx b/src/common/reducer.tsx index 43171c8..0b510b5 100644 --- a/src/common/reducer.tsx +++ b/src/common/reducer.tsx @@ -10,6 +10,8 @@ export const ACTIONS = { RESET_TO_UNLOCK_DIM: 'RESET_TO_UNLOCK_DIM', RESET_TO_UNLOCK_TICKSPEED: 'RESET_TO_UNLOCK_TICKSPEED', RESET_TO_INITIAL_VALUES: 'RESET_TO_INITIAL_VALUES', + POP_UP: 'POP_UP', + SAVE_DATA: 'SAVE_DATA', }; export function reducer(state: GameState, action: { type: string; payload?: any }) { @@ -77,6 +79,7 @@ export function reducer(state: GameState, action: { type: string; payload?: any return { ...JSON.parse(initialGameState), galaxyCounter: state.galaxyCounter, + tickspeedDeceaseRate: state.tickspeedDeceaseRate, resetGameCounter: state.resetGameCounter + 1, lastSavedTime: state.lastSavedTime, }; @@ -85,13 +88,19 @@ export function reducer(state: GameState, action: { type: string; payload?: any return { ...JSON.parse(initialGameState), galaxyCounter: state.galaxyCounter + 1, - tickspeedDeceaseRate: 0.12, - resetGameCounter: state.resetGameCounter, + tickspeedDeceaseRate: state.tickspeedDeceaseRate * 1.1, lastSavedTime: state.lastSavedTime, }; case ACTIONS.RESET_TO_INITIAL_VALUES: return JSON.parse(initialGameState); + + case ACTIONS.SAVE_DATA: + return { + ...state, + lastSavedTime: Date.now(), + }; + default: return state; } diff --git a/src/components/App.tsx b/src/components/App.tsx index 189e245..6b119ea 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -14,7 +14,7 @@ function App() { reducer, JSON.parse(localStorage.getItem('data') || initialGameState) ); - + const [saveTag, setSaveTag] = useState('gameSaved centered'); const timerExpiredCallback = useRef(() => {}); const tickspeedRef = useRef(2000); const timerIdRef = useRef(-1); @@ -24,7 +24,7 @@ function App() { useEffect(() => { const startTimer = () => { - timerIdRef.current = setTimeout(() => { + timerIdRef.current = window.setTimeout(() => { timerExpiredCallback.current(); startTimer(); }, tickspeedRef.current); @@ -34,11 +34,27 @@ function App() { // if we ever unmount / destroy this component instance, clear the timeout return () => clearTimeout(timerIdRef.current); }, []); + /* const classesSnackbar = clsx({ + "gameSaved": true, + "centered": true, + "visible": Date.now() <= state.lastSavedTime + 3 * 1000 ? true: false, + }) */ + + useEffect(() => { + if (Date.now() <= state.lastSavedTime + 3 * 1000) setSaveTag('gameSaved centered visible'); + else setSaveTag('gameSaved centered'); + }); return (
+
+
+
Game saved!
+
+
+ { @@ -32,19 +33,15 @@ export default function GameResets(props: { gs: GameState; dispatch: Function })

{`Antimatter Galaxies (${gs.galaxyCounter})`}

{`requires 80 8. Dimension `}

-
@@ -52,11 +49,29 @@ export default function GameResets(props: { gs: GameState; dispatch: Function })

{`resets everything`}

+ {popUp && ( +
+
+ + +
+
+ )} ); } diff --git a/src/components/Tickspeed/TickSpeed.tsx b/src/components/Tickspeed/TickSpeed.tsx index a8a10cc..b87a4ad 100644 --- a/src/components/Tickspeed/TickSpeed.tsx +++ b/src/components/Tickspeed/TickSpeed.tsx @@ -32,7 +32,7 @@ export default function Tickspeed(props: { gs: GameState; dispatch: Function; ti

{`The current clockspeed is ${tickspeedRef.current.toFixed( 0 - )} ms. Reduce the tickspeed by ${gs.tickspeedDeceaseRate * 100}%.`}

+ )} ms. Reduce the tickspeed by ${(gs.tickspeedDeceaseRate* 100).toFixed(1)}%.`}