diff --git a/src/hooks/useCursorPosition.ts b/src/hooks/useCursorPosition.ts index 9cfab2b..da9058b 100644 --- a/src/hooks/useCursorPosition.ts +++ b/src/hooks/useCursorPosition.ts @@ -1,4 +1,5 @@ import { useState } from 'react'; +import { CursorPosition } from './useKeyDown'; export const useCursorPosition = () => { const [cursorPosition, setCursorPosition] = useState(0); @@ -6,7 +7,7 @@ export const useCursorPosition = () => { const resetCursorPointer = () => setCursorPosition(0); const updateCursorPosition = (opt: 'increase' | 'decrease') => { - if (opt === 'increase') setCursorPosition((cursor) => cursor + 1); + if (opt === CursorPosition.INCREASE) setCursorPosition((cursor) => cursor + 1); else setCursorPosition((cursor) => cursor - 1); }; diff --git a/src/hooks/useKeyDown.ts b/src/hooks/useKeyDown.ts index 93a75b5..51f7425 100644 --- a/src/hooks/useKeyDown.ts +++ b/src/hooks/useKeyDown.ts @@ -3,10 +3,19 @@ import { useState, useEffect, useCallback } from 'react'; import { useCursorPosition } from './useCursorPosition'; import { isAllowedCode } from '../utils'; -type TypingState = 'idle' | 'start' | 'typing'; +export enum TypingState { + IDLE = 'idle', + START = 'start', + TYPING = 'typing', +} + +export enum CursorPosition { + INCREASE = 'increase', + DECREASE = 'decrease', +} export const useKeyDown = (active: boolean) => { - const [typingState, setTypingState] = useState('idle'); + const [typingState, setTypingState] = useState(TypingState.IDLE); const [charTyped, setCharTyped] = useState(''); const [totalCharacterTyped, setTotalCharacterTyped] = useState(''); @@ -23,18 +32,18 @@ export const useKeyDown = (active: boolean) => { setTotalCharacterTyped((prev) => prev.slice(0, totalCharacterTyped.length - 1) ); - updateCursorPosition('decrease'); + updateCursorPosition(CursorPosition.DECREASE); } return; } - if (typingState === 'idle') { - setTypingState('start'); + if (typingState === TypingState.IDLE) { + setTypingState(TypingState.START); } setCharTyped((prev) => prev + key); setTotalCharacterTyped((prev) => prev + key); - updateCursorPosition('increase'); + updateCursorPosition(CursorPosition.INCREASE); }, [ active, diff --git a/src/hooks/useSystem.ts b/src/hooks/useSystem.ts index 1b01ee2..06a0524 100644 --- a/src/hooks/useSystem.ts +++ b/src/hooks/useSystem.ts @@ -1,7 +1,6 @@ import { useCallback, useState } from 'react'; - -import { useCountdown } from './useCountdown'; -import { useKeyDown } from './useKeyDown'; +import { useTimer } from './useTimer'; +import { TypingState, useKeyDown } from './useKeyDown'; import { useLocalStorage } from './useLocalStorage'; import { useModal } from './useModal'; import { useWord } from './useWord'; @@ -28,11 +27,12 @@ export const useSystem = () => { typedHistory: '', }); - const { setLocalStorageValue, getLocalStorageValue } = useLocalStorage(); const [wordContainerFocused, setWordContainerFocused] = useState(false); - const [time, setTime] = useState(() => getLocalStorageValue('time') || 15000); - const { countdown, resetCountdown, startCountdown } = useCountdown(time); + + const { setLocalStorageValue } = useLocalStorage(); + const {time, setTime, countdown, resetCountdown, startCountdown } = useTimer(); const { word, updateWord, totalWord } = useWord(30); + const { modalIsOpen, aboutModal, openModal, closeModal } = useModal(); const { charTyped, typingState, @@ -43,14 +43,14 @@ export const useSystem = () => { setTotalCharacterTyped, setTypingState, } = useKeyDown(wordContainerFocused); - const { modalIsOpen, aboutModal, openModal, closeModal } = useModal(); + const restartTest = useCallback(() => { resetCountdown(); updateWord(true); resetCursorPointer(); resetCharTyped(); - setTypingState('idle'); + setTypingState(TypingState.IDLE); setTotalCharacterTyped(''); }, [ resetCountdown, @@ -62,13 +62,7 @@ export const useSystem = () => { ]); const checkCharacter = useCallback( - (index: number) => { - if (charTyped[index] === word[index]) { - return true; - } else { - return false; - } - }, + (index: number) => charTyped[index] === word[index], [charTyped, word] ); @@ -78,9 +72,9 @@ export const useSystem = () => { resetCursorPointer(); } - if (typingState === 'start') { + if (typingState === TypingState.START) { startCountdown(); - setTypingState('typing'); + setTypingState(TypingState.TYPING); } if (countdown === 0) { diff --git a/src/hooks/useTimer.ts b/src/hooks/useTimer.ts new file mode 100644 index 0000000..afa4bd6 --- /dev/null +++ b/src/hooks/useTimer.ts @@ -0,0 +1,17 @@ +import { useState } from 'react'; +import { useCountdown } from './useCountdown'; +import { useLocalStorage } from './useLocalStorage'; + +export const useTimer = () => { + const { getLocalStorageValue } = useLocalStorage(); + const [time, setTime] = useState(() => getLocalStorageValue('time') || 15000); + const { countdown, resetCountdown, startCountdown } = useCountdown(time); + + return { + time, + setTime, + countdown, + resetCountdown, + startCountdown, + }; +}; diff --git a/src/utils/index.ts b/src/utils/index.ts index c1bda27..5283ada 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -35,20 +35,12 @@ export const generateWord = (n: number): string => { return faker.word.words(n); }; -export const calculateAccuracy = (expectedWord: string, typedWord: string) => { - let correctChars = 0; - for (let i = 0; i < typedWord.length; i++) { - if (typedWord[i] === expectedWord[i]) { - correctChars++; - } - } +export const calculateAccuracy = (expectedWord: string, typedWord: string): AccuracyMetrics => { + const correctChars = typedWord.split('').filter((char, i) => char === expectedWord[i]).length; + const incorrectChars = typedWord.length - correctChars; + const accuracy = (correctChars / typedWord.length) * 100; - const accuracyMetrics: AccuracyMetrics = { - correctChars, - incorrectChars: typedWord.length - correctChars, - accuracy: (correctChars / typedWord.length) * 100, - }; - return accuracyMetrics; + return { correctChars, incorrectChars, accuracy }; }; export const calculateWPM = (