From e0e2f3b2ef534f9cd43d37b4980ce58446715c92 Mon Sep 17 00:00:00 2001 From: ashastral Date: Sun, 27 Feb 2022 23:52:20 -0800 Subject: [PATCH] extract settings stuff to localStorage, store daily game stats & preserve try count --- web-optimle/www/src/Game.tsx | 74 +++++++++++++++++++++++++---- web-optimle/www/src/index.tsx | 30 ++---------- web-optimle/www/src/localstorage.ts | 23 +++++++++ 3 files changed, 92 insertions(+), 35 deletions(-) create mode 100644 web-optimle/www/src/localstorage.ts diff --git a/web-optimle/www/src/Game.tsx b/web-optimle/www/src/Game.tsx index 9d4f8ed..1ec1ec9 100644 --- a/web-optimle/www/src/Game.tsx +++ b/web-optimle/www/src/Game.tsx @@ -9,6 +9,8 @@ import { COMMON_WORDS, UNCOMMON_WORDS } from './dictionary'; import * as PUZZLES from './puzzles.json'; import { Row, RowState } from './Row'; import { Keyboard } from './Keyboard'; +import { useLocalStorage } from './localstorage'; + const MAX_GUESSES = 2; const WORD_LENGTH = 5; const EPOCH = new Date(2022, 1, 27); @@ -27,18 +29,25 @@ interface GameProps { type History = GuessResult[]; +type DailyStats = { + tries: number, + won: boolean, + winningGuesses?: GuessResult[], +}; + export function Game(props: GameProps) { - const puzzle = useMemo(() => { + const day = useMemo(() => { let date = new Date(); date.setHours(date.getHours() - 6); // treat 6 AM as the start of the day date.setHours(0); // now set it to midnight of the day - const day = Math.round((date.getTime() - EPOCH.getTime()) / (24 * 60 * 60 * 1000)); - return PUZZLES[day]; + return Math.round((date.getTime() - EPOCH.getTime()) / (24 * 60 * 60 * 1000)); }, []); + const puzzle = PUZZLES[day]; const [gameState, setGameState] = useState(GameState.Playing); const [guesses, setGuesses] = useState([...puzzle.history]); const [currentGuess, setCurrentGuess] = useState(""); - const [tryNumber, setTryNumber] = useState(1); + const [dailyStats, setDailyStats] = useLocalStorage<{ [key: number]: DailyStats }>("dailyTries", {}); + const [todayStats, setTodayStats] = useState({ tries: 1, won: false }); const [hint, setHint] = useState(

Try to guarantee a win in 2 guesses! @@ -51,12 +60,38 @@ export function Game(props: GameProps) { setGuesses([...puzzle.history]); setCurrentGuess(""); setGameState(GameState.Playing); - setTryNumber((x) => x + 1); + setTodayStats((oldStats) => ({ + ...oldStats, + tries: oldStats.tries + 1, + })); }, []); + useEffect(() => { + const storedTodayStats = dailyStats[day]; + if (storedTodayStats !== undefined) { + setTodayStats(storedTodayStats); + if (storedTodayStats.won) { + setGameState(GameState.Won); + setHint("You already won today's puzzle!"); + if (storedTodayStats.winningGuesses) { + setGuesses([ + ...puzzle.history, + ...storedTodayStats.winningGuesses, + ]); + } + } + } + }, []); + useEffect(() => { + setDailyStats({ + ...dailyStats, + [day]: todayStats, + }); + }, [todayStats]); + async function share(copiedHint: string, text?: string) { const url = window.location.origin + window.location.pathname; - const body = `${text}\n\n${url}`; + const body = `${text}\n${url}`; if ( /android|iphone|ipad|ipod|webos/i.test(navigator.userAgent) && !/firefox/i.test(navigator.userAgent) @@ -123,12 +158,20 @@ export function Game(props: GameProps) { setCurrentGuess(""); if (matches.every((m) => m === 2)) { - if (tryNumber === 1) { + if (todayStats.tries === 1) { setHint("You won on your first try! Amazing job."); } else { - setHint(`You won in ${tryNumber} tries! Great job.`); + setHint(`You won in ${todayStats.tries} tries! Great job.`); } setGameState(GameState.Won); + setTodayStats((oldStats) => ({ + ...oldStats, + won: true, + winningGuesses: [ + ...guesses.slice(puzzle.history.length), + result, + ], + })) } else if (guesses.length + 1 === puzzle.history.length + MAX_GUESSES) { setHint(

Not quite! The answer could've been {game.possible_word().toUpperCase()}. (Enter to try again)

); setGameState(GameState.Lost); @@ -216,10 +259,21 @@ export function Game(props: GameProps) { {gameState === GameState.Won && (