histogram width divide by mode, not total #2
13 changed files with 95 additions and 140 deletions
21
package-lock.json
generated
21
package-lock.json
generated
|
@ -19,6 +19,7 @@
|
||||||
"@types/react-dom": "^17.0.11",
|
"@types/react-dom": "^17.0.11",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-countdown": "^2.3.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
"typescript": "^4.5.4",
|
"typescript": "^4.5.4",
|
||||||
|
@ -12901,6 +12902,18 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-countdown": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-countdown/-/react-countdown-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-Q4SADotHtgOxNWhDdvgupmKVL0pMB9DvoFcxv5AzjsxVhzOVxnttMbAywgqeOdruwEAmnPhOhNv/awAgkwru2w==",
|
||||||
|
"dependencies": {
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 15",
|
||||||
|
"react-dom": ">= 15"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-dev-utils": {
|
"node_modules/react-dev-utils": {
|
||||||
"version": "12.0.0",
|
"version": "12.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
|
||||||
|
@ -25058,6 +25071,14 @@
|
||||||
"whatwg-fetch": "^3.6.2"
|
"whatwg-fetch": "^3.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-countdown": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-countdown/-/react-countdown-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-Q4SADotHtgOxNWhDdvgupmKVL0pMB9DvoFcxv5AzjsxVhzOVxnttMbAywgqeOdruwEAmnPhOhNv/awAgkwru2w==",
|
||||||
|
"requires": {
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-dev-utils": {
|
"react-dev-utils": {
|
||||||
"version": "12.0.0",
|
"version": "12.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
"typescript": "^4.5.4",
|
"typescript": "^4.5.4",
|
||||||
"web-vitals": "^2.1.3"
|
"web-vitals": "^2.1.3",
|
||||||
|
"react-countdown": "^2.3.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
|
|
52
src/App.tsx
52
src/App.tsx
|
@ -6,8 +6,8 @@ import { Grid } from './components/grid/Grid'
|
||||||
import { Keyboard } from './components/keyboard/Keyboard'
|
import { Keyboard } from './components/keyboard/Keyboard'
|
||||||
import { AboutModal } from './components/modals/AboutModal'
|
import { AboutModal } from './components/modals/AboutModal'
|
||||||
import { InfoModal } from './components/modals/InfoModal'
|
import { InfoModal } from './components/modals/InfoModal'
|
||||||
import { WinModal } from './components/modals/WinModal'
|
|
||||||
import { StatsModal } from './components/modals/StatsModal'
|
import { StatsModal } from './components/modals/StatsModal'
|
||||||
|
import { WIN_MESSAGES } from './constants/strings'
|
||||||
import { isWordInWordList, isWinningWord, solution } from './lib/words'
|
import { isWordInWordList, isWinningWord, solution } from './lib/words'
|
||||||
import { addStatsForCompletedGame, loadStats } from './lib/stats'
|
import { addStatsForCompletedGame, loadStats } from './lib/stats'
|
||||||
import {
|
import {
|
||||||
|
@ -15,17 +15,18 @@ import {
|
||||||
saveGameStateToLocalStorage,
|
saveGameStateToLocalStorage,
|
||||||
} from './lib/localStorage'
|
} from './lib/localStorage'
|
||||||
|
|
||||||
|
const ALERT_TIME_MS = 2000;
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [currentGuess, setCurrentGuess] = useState('')
|
const [currentGuess, setCurrentGuess] = useState('')
|
||||||
const [isGameWon, setIsGameWon] = useState(false)
|
const [isGameWon, setIsGameWon] = useState(false)
|
||||||
const [isWinModalOpen, setIsWinModalOpen] = useState(false)
|
|
||||||
const [isInfoModalOpen, setIsInfoModalOpen] = useState(false)
|
const [isInfoModalOpen, setIsInfoModalOpen] = useState(false)
|
||||||
const [isAboutModalOpen, setIsAboutModalOpen] = useState(false)
|
const [isAboutModalOpen, setIsAboutModalOpen] = useState(false)
|
||||||
const [isNotEnoughLetters, setIsNotEnoughLetters] = useState(false)
|
const [isNotEnoughLetters, setIsNotEnoughLetters] = useState(false)
|
||||||
const [isStatsModalOpen, setIsStatsModalOpen] = useState(false)
|
const [isStatsModalOpen, setIsStatsModalOpen] = useState(false)
|
||||||
const [isWordNotFoundAlertOpen, setIsWordNotFoundAlertOpen] = useState(false)
|
const [isWordNotFoundAlertOpen, setIsWordNotFoundAlertOpen] = useState(false)
|
||||||
const [isGameLost, setIsGameLost] = useState(false)
|
const [isGameLost, setIsGameLost] = useState(false)
|
||||||
const [shareComplete, setShareComplete] = useState(false)
|
const [successAlert, setSuccessAlert] = useState('')
|
||||||
const [guesses, setGuesses] = useState<string[]>(() => {
|
const [guesses, setGuesses] = useState<string[]>(() => {
|
||||||
const loaded = loadGameStateFromLocalStorage()
|
const loaded = loadGameStateFromLocalStorage()
|
||||||
if (loaded?.solution !== solution) {
|
if (loaded?.solution !== solution) {
|
||||||
|
@ -49,9 +50,18 @@ function App() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isGameWon) {
|
if (isGameWon) {
|
||||||
setIsWinModalOpen(true)
|
setSuccessAlert(WIN_MESSAGES[Math.floor(Math.random()*WIN_MESSAGES.length)]);
|
||||||
|
setTimeout(() => {
|
||||||
|
setSuccessAlert('');
|
||||||
|
setIsStatsModalOpen(true);
|
||||||
|
}, ALERT_TIME_MS);
|
||||||
}
|
}
|
||||||
}, [isGameWon])
|
if (isGameLost) {
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsStatsModalOpen(true);
|
||||||
|
}, ALERT_TIME_MS);
|
||||||
|
}
|
||||||
|
}, [isGameWon, isGameLost])
|
||||||
|
|
||||||
const onChar = (value: string) => {
|
const onChar = (value: string) => {
|
||||||
if (currentGuess.length < 5 && guesses.length < 6 && !isGameWon) {
|
if (currentGuess.length < 5 && guesses.length < 6 && !isGameWon) {
|
||||||
|
@ -64,18 +74,19 @@ function App() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const onEnter = () => {
|
const onEnter = () => {
|
||||||
if (!(currentGuess.length === 5) && !isGameLost) {
|
if (isGameWon || isGameLost) { return; }
|
||||||
|
if (!(currentGuess.length === 5)) {
|
||||||
setIsNotEnoughLetters(true)
|
setIsNotEnoughLetters(true)
|
||||||
return setTimeout(() => {
|
return setTimeout(() => {
|
||||||
setIsNotEnoughLetters(false)
|
setIsNotEnoughLetters(false)
|
||||||
}, 2000)
|
}, ALERT_TIME_MS)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isWordInWordList(currentGuess)) {
|
if (!isWordInWordList(currentGuess)) {
|
||||||
setIsWordNotFoundAlertOpen(true)
|
setIsWordNotFoundAlertOpen(true)
|
||||||
return setTimeout(() => {
|
return setTimeout(() => {
|
||||||
setIsWordNotFoundAlertOpen(false)
|
setIsWordNotFoundAlertOpen(false)
|
||||||
}, 2000)
|
}, ALERT_TIME_MS)
|
||||||
}
|
}
|
||||||
|
|
||||||
const winningWord = isWinningWord(currentGuess)
|
const winningWord = isWinningWord(currentGuess)
|
||||||
|
@ -116,18 +127,6 @@ function App() {
|
||||||
onEnter={onEnter}
|
onEnter={onEnter}
|
||||||
guesses={guesses}
|
guesses={guesses}
|
||||||
/>
|
/>
|
||||||
<WinModal
|
|
||||||
isOpen={isWinModalOpen}
|
|
||||||
handleClose={() => setIsWinModalOpen(false)}
|
|
||||||
guesses={guesses}
|
|
||||||
handleShare={() => {
|
|
||||||
setIsWinModalOpen(false)
|
|
||||||
setShareComplete(true)
|
|
||||||
return setTimeout(() => {
|
|
||||||
setShareComplete(false)
|
|
||||||
}, 2000)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<InfoModal
|
<InfoModal
|
||||||
isOpen={isInfoModalOpen}
|
isOpen={isInfoModalOpen}
|
||||||
handleClose={() => setIsInfoModalOpen(false)}
|
handleClose={() => setIsInfoModalOpen(false)}
|
||||||
|
@ -135,7 +134,14 @@ function App() {
|
||||||
<StatsModal
|
<StatsModal
|
||||||
isOpen={isStatsModalOpen}
|
isOpen={isStatsModalOpen}
|
||||||
handleClose={() => setIsStatsModalOpen(false)}
|
handleClose={() => setIsStatsModalOpen(false)}
|
||||||
|
guesses={guesses}
|
||||||
gameStats={stats}
|
gameStats={stats}
|
||||||
|
isGameLost={isGameLost}
|
||||||
|
isGameWon={isGameWon}
|
||||||
|
handleShare={() => {
|
||||||
|
setSuccessAlert("Game copied to clipboard");
|
||||||
|
return setTimeout(() => setSuccessAlert(''), ALERT_TIME_MS);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<AboutModal
|
<AboutModal
|
||||||
isOpen={isAboutModalOpen}
|
isOpen={isAboutModalOpen}
|
||||||
|
@ -153,12 +159,12 @@ function App() {
|
||||||
<Alert message="Not enough letters" isOpen={isNotEnoughLetters} />
|
<Alert message="Not enough letters" isOpen={isNotEnoughLetters} />
|
||||||
<Alert message="Word not found" isOpen={isWordNotFoundAlertOpen} />
|
<Alert message="Word not found" isOpen={isWordNotFoundAlertOpen} />
|
||||||
<Alert
|
<Alert
|
||||||
message={`You lost, the word was ${solution}`}
|
message={`The word was ${solution}`}
|
||||||
isOpen={isGameLost}
|
isOpen={isGameLost}
|
||||||
/>
|
/>
|
||||||
<Alert
|
<Alert
|
||||||
message="Game copied to clipboard"
|
message={successAlert}
|
||||||
isOpen={shareComplete}
|
isOpen={successAlert!==''}
|
||||||
variant="success"
|
variant="success"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const Alert = ({ isOpen, message, variant = 'warning' }: Props) => {
|
||||||
'fixed top-20 left-1/2 transform -translate-x-1/2 max-w-sm w-full shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden',
|
'fixed top-20 left-1/2 transform -translate-x-1/2 max-w-sm w-full shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden',
|
||||||
{
|
{
|
||||||
'bg-rose-200': variant === 'warning',
|
'bg-rose-200': variant === 'warning',
|
||||||
'bg-green-200': variant === 'success',
|
'bg-green-200 z-20': variant === 'success',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
import { CharStatus } from '../../lib/statuses'
|
|
||||||
import classnames from 'classnames'
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
status: CharStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MiniCell = ({ status }: Props) => {
|
|
||||||
const classes = classnames(
|
|
||||||
'w-10 h-10 border-solid border-2 border-slate-200 flex items-center justify-center mx-0.5 text-lg font-bold rounded',
|
|
||||||
{
|
|
||||||
'bg-white': status === 'absent',
|
|
||||||
'bg-green-500': status === 'correct',
|
|
||||||
'bg-yellow-500': status === 'present',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className={classes}></div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
import { getGuessStatuses } from '../../lib/statuses'
|
|
||||||
import { MiniCell } from './MiniCell'
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
guess: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MiniCompletedRow = ({ guess }: Props) => {
|
|
||||||
const statuses = getGuessStatuses(guess)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex justify-center mb-1">
|
|
||||||
{guess.split('').map((letter, i) => (
|
|
||||||
<MiniCell key={i} status={statuses[i]} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { MiniCompletedRow } from './MiniCompletedRow'
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
guesses: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MiniGrid = ({ guesses }: Props) => {
|
|
||||||
return (
|
|
||||||
<div className="pb-6">
|
|
||||||
{guesses.map((guess, i) => (
|
|
||||||
<MiniCompletedRow key={i} guess={guess} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,15 +1,29 @@
|
||||||
|
import Countdown from "react-countdown"
|
||||||
import { StatBar } from '../stats/StatBar'
|
import { StatBar } from '../stats/StatBar'
|
||||||
import { Histogram } from '../stats/Histogram'
|
import { Histogram } from '../stats/Histogram'
|
||||||
import { GameStats } from '../../lib/localStorage'
|
import { GameStats } from '../../lib/localStorage'
|
||||||
|
import { shareStatus } from '../../lib/share'
|
||||||
|
import { tomorrow } from '../../lib/words'
|
||||||
import { BaseModal } from './BaseModal'
|
import { BaseModal } from './BaseModal'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
handleClose: () => void
|
handleClose: () => void
|
||||||
|
guesses: string[]
|
||||||
gameStats: GameStats
|
gameStats: GameStats
|
||||||
|
isGameLost: boolean
|
||||||
|
isGameWon: boolean
|
||||||
|
handleShare: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const StatsModal = ({ isOpen, handleClose, gameStats }: Props) => {
|
export const StatsModal = ({ isOpen, handleClose, guesses, gameStats, isGameLost, isGameWon, handleShare }: Props) => {
|
||||||
|
if (gameStats.totalGames <= 0) {
|
||||||
|
return (
|
||||||
|
<BaseModal title="Statistics" isOpen={isOpen} handleClose={handleClose}>
|
||||||
|
<StatBar gameStats={gameStats} />
|
||||||
|
</BaseModal>
|
||||||
|
)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<BaseModal title="Statistics" isOpen={isOpen} handleClose={handleClose}>
|
<BaseModal title="Statistics" isOpen={isOpen} handleClose={handleClose}>
|
||||||
<StatBar gameStats={gameStats} />
|
<StatBar gameStats={gameStats} />
|
||||||
|
@ -17,6 +31,24 @@ export const StatsModal = ({ isOpen, handleClose, gameStats }: Props) => {
|
||||||
Guess Distribution
|
Guess Distribution
|
||||||
</h4>
|
</h4>
|
||||||
<Histogram gameStats={gameStats} />
|
<Histogram gameStats={gameStats} />
|
||||||
|
{(isGameLost || isGameWon) &&
|
||||||
|
<div className="mt-5 sm:mt-6 columns-2">
|
||||||
|
<div>
|
||||||
|
<h5>New word in</h5>
|
||||||
|
<Countdown className="text-lg font-medium text-gray-900" date={tomorrow} daysInHours={true} />
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="mt-2 w-full rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:text-sm"
|
||||||
|
onClick={() => {
|
||||||
|
shareStatus(guesses, isGameLost)
|
||||||
|
handleShare()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Share
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
import { Dialog } from '@headlessui/react'
|
|
||||||
import { CheckIcon } from '@heroicons/react/outline'
|
|
||||||
import { MiniGrid } from '../mini-grid/MiniGrid'
|
|
||||||
import { shareStatus } from '../../lib/share'
|
|
||||||
import { BaseModal } from './BaseModal'
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
isOpen: boolean
|
|
||||||
handleClose: () => void
|
|
||||||
guesses: string[]
|
|
||||||
handleShare: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const WinModal = ({
|
|
||||||
isOpen,
|
|
||||||
handleClose,
|
|
||||||
guesses,
|
|
||||||
handleShare,
|
|
||||||
}: Props) => {
|
|
||||||
return (
|
|
||||||
<BaseModal title="You won!" isOpen={isOpen} handleClose={handleClose}>
|
|
||||||
<div>
|
|
||||||
<div className="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-green-100">
|
|
||||||
<CheckIcon className="h-6 w-6 text-green-600" aria-hidden="true" />
|
|
||||||
</div>
|
|
||||||
<div className="mt-3 text-center sm:mt-5">
|
|
||||||
<Dialog.Title
|
|
||||||
as="h3"
|
|
||||||
className="text-lg leading-6 font-medium text-gray-900"
|
|
||||||
>
|
|
||||||
You won!
|
|
||||||
</Dialog.Title>
|
|
||||||
<div className="mt-2">
|
|
||||||
<MiniGrid guesses={guesses} />
|
|
||||||
<p className="text-sm text-gray-500">Great job.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-5 sm:mt-6">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="inline-flex justify-center w-full rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:text-sm"
|
|
||||||
onClick={() => {
|
|
||||||
shareStatus(guesses)
|
|
||||||
handleShare()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Share
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</BaseModal>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -6,7 +6,8 @@ type Props = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Histogram = ({ gameStats }: Props) => {
|
export const Histogram = ({ gameStats }: Props) => {
|
||||||
const { totalGames, winDistribution } = gameStats
|
const winDistribution = gameStats.winDistribution
|
||||||
|
const maxValue = Math.max(...winDistribution)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="columns-1 justify-left m-2 text-sm">
|
<div className="columns-1 justify-left m-2 text-sm">
|
||||||
|
@ -14,7 +15,7 @@ export const Histogram = ({ gameStats }: Props) => {
|
||||||
<Progress
|
<Progress
|
||||||
key={i}
|
key={i}
|
||||||
index={i}
|
index={i}
|
||||||
size={95 * (value / totalGames)}
|
size={90 * (value / maxValue)}
|
||||||
label={String(value)}
|
label={String(value)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
1
src/constants/strings.ts
Normal file
1
src/constants/strings.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export const WIN_MESSAGES = ["Great Job!", "Awesome", "Well done!"];
|
|
@ -1,9 +1,9 @@
|
||||||
import { getGuessStatuses } from './statuses'
|
import { getGuessStatuses } from './statuses'
|
||||||
import { solutionIndex } from './words'
|
import { solutionIndex } from './words'
|
||||||
|
|
||||||
export const shareStatus = (guesses: string[]) => {
|
export const shareStatus = (guesses: string[], lost: boolean) => {
|
||||||
navigator.clipboard.writeText(
|
navigator.clipboard.writeText(
|
||||||
`Not Wordle ${solutionIndex} ${guesses.length}/6\n\n` +
|
`Not Wordle ${solutionIndex} ${lost?"X":guesses.length}/6\n\n` +
|
||||||
generateEmojiGrid(guesses)
|
generateEmojiGrid(guesses)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,13 @@ export const getWordOfDay = () => {
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
const msInDay = 86400000
|
const msInDay = 86400000
|
||||||
const index = Math.floor((now - epochMs) / msInDay)
|
const index = Math.floor((now - epochMs) / msInDay)
|
||||||
|
const nextday = (index+1)*msInDay + epochMs;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
solution: WORDS[index].toUpperCase(),
|
solution: WORDS[index].toUpperCase(),
|
||||||
solutionIndex: index,
|
solutionIndex: index,
|
||||||
|
tomorrow: nextday,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const { solution, solutionIndex } = getWordOfDay()
|
export const { solution, solutionIndex, tomorrow } = getWordOfDay()
|
||||||
|
|
Loading…
Add table
Reference in a new issue