자바스크립트

[JavaScript] 타이핑 측정하는 웹사이트 만들기

코딩하는둥이 2025. 2. 28. 13:48

타이핑 측정하는 웹사이트를 만들어보자!

 

기능 

 - 타이핑 력처리 

 - 타이머 기능

 - 정확도, 오류수, cpm ,wpm  계산

 - 타이머 기능

 - 인용구 표시 업데이트

 - 게임 시작 및 재시작

 

 

먼저 필요한 변수를 선언해준다.

// 초기 시간 설정
const TIME_LIMIT = 60;

// 인용구 리스트
const quotesArray = [
    'he realized what was happening and told the others.',
    'And in the end it turned out that the creature was her grandfather',
    'when the old man saw his granddaughter'
]


//사용할 변수들
const timerText = document.querySelector('.curr_time');
const accuracyText = document.querySelector('.curr_accuracy');
const errorText = document.querySelector('.curr_errors');
const cpmText = document.querySelector('.curr_cpm');
const wpmText = document.querySelector('.curr_wpm');
const quoteText = document.querySelector('.quote');
const inputArea = document.querySelector('.input_area');
const restartBtn = document.querySelector('.restart_btn');
const cpmGroup = document.querySelector('.cpm');
const wpmGroup = document.querySelector('.wpm');
const errorGroup = document.querySelector('.errors');
const accuracyGroup = document.querySelector('.accuracy');

let timeLeft = TIME_LIMIT;
let timeElapsed = 0;
let totalErrors = 0;
let errors = 0;
let accuracy = 0;
let characterTyped = 0;
let currentQuote = "";
let quoteNo = 0;
let timer = null;

 

먼저 타이머 기능부터 만듭니다.

function updateTimer() {
    if (timeLeft > 0) {
        // 현재 남은 시간을 줄이기
        timeLeft--;

        // 경과 시간을 늘리기
        timeElapsed++;

        // 타이머 텍스트 업데이트;
        timerText.textContent = timeLeft + "s";
    } else {
        // 게임을 끝내기
        finishGame();
    }
}

 

currentQuote에 빈 문자열이 들어가 있는데 quotesArray를 넣어주는 함수를 만듭니다. 그 후 ""로 잘라내서 각각의 배열로 만들어줍니다.

만약에 quoteNo가 순서대로 보여지도록 하지만 만약에 마지막 리스트가 아니면 다시 처음부터 가서 무한 반복이 됩니다. 

function updateQuote() {
    quoteText.textContent = null;
    currentQuote = quotesArray[quoteNo];

    // 각 문장을 분리하고요소를 만들기
    currentQuote.split("")
        .forEach(char => {
            const charSpan = document.createElement('span');
            charSpan.innerText = char;

            // 만든 요소를 quote에 넣어주기
            quoteText.appendChild(charSpan);
        })

    // quote를 순서대로 다음 것으로 넘기기
    if (quoteNo < quotesArray.length - 1) {
        quoteNo++;
    }
    // 만약 마지막 것이라면 처음 것을 다시 보여주기
    else {
        quoteNo = 0;
    }
}

 

유저가 입력하는 값을 split로 나눠줍니다. 그후 입력하는 총 문자의 수를 증가되도록하고 errors를 0을 선언합니다.

그 후 한 문자마다 맞았을 때는 correct_char를 css를 주고 틀렸을 때 incorrect_char를 css주고 오류수가 증가되도록합니다. 오류날 때마다 +1이 되기 때문에 erroerText에 오류난 개수를 더해줍니다. 마지막으로 정확도 텍스트를 연산해서 accuracyText에 넣어줍니다. 마지막으로 텍스트가 입력된 경우는 updateQutoe()를 호출해서 다시 새문장이 나오게 하고 총 오류 업데이트를 해주고 입력 영역 초기화해줍니다.

function processCurrentText() {

    // 현재 입력 텍스트를 가져와서 분할합니다.
    let currInput = inputArea.value;
    let currInputArray = currInput.split('');

    // ['h', 'e', 'l', , 'l', 'o'];
    // 입력된 총 문자 수 증가
    characterTyped++;

    errors = 0;

    let quoteSpanArray = quoteText.querySelectorAll('span');
    quoteSpanArray.forEach((char, index) => {
        let typedChar = currInputArray[index] // 각 문자를 가져옴
        console.log(typedChar);
        // 현재 입력되지 않은 문자
        if (!typedChar) {
            char.classList.remove('correct_char');
            char.classList.remove('incorrect_char');

            // 올바른 문자
        } else if (typedChar === char.innerText) {
            char.classList.add('correct_char');
            char.classList.remove('incorrect_char');

            // 잘못된 문자
        } else {
            char.classList.add('incorrect_char');
            char.classList.remove('correct_char');

            // 오류 수 증가
            errors++;
        }
    });

    // 오류 개수 표시
    errorText.textContent = totalErrors + errors;


    // 정확도 텍스트 업데이트
    let correctCharacters = (characterTyped - (totalErrors + errors));
    let accuracyVal = ((correctCharacters / characterTyped) * 100);
    accuracyText.textContent = Math.round(accuracyVal);

    // 현재 텍스트가 오류와 상관없이 완전히 입력된 경우
    if (currInput.length == currentQuote.length) {
        updateQuote();

        // 총 오류 업데이트
        totalErrors += errors;

        // 입력 영역 지우기
        inputArea.value = "";
    }
}

 

 

upadteQute를 초기화하여 quote를 업데이트해줍니다.

clearUnterval()를 사용해서 타이머를 초기화 해주고 1초에 한번씩 time가 업데이트 되도록 합니다.

function startGame() {
    resetValues();
    // quote 업데이트
    updateQuote();

    // 타이머 시작
    clearInterval(timer);
    timer = setInterval(updateTimer, 1000);

}

 

시작할 때 타이머를 초기화해줍니다.

function resetValues() {

    timeLeft = TIME_LIMIT;
    timeElapsed = 0;
    errors = 0;
    totalErrors = 0;
    accuracy = 0;
    characterTyped = 0;
    quoteNo = 0;
    inputArea.disabled = false;

    inputArea.value = '';

    quoteText.textContent = '아래를 클릭해서 게임을 시작하세요.';
    accuracyText.textContent = 100;
    timerText.textContent = timeLeft + 's';
    errorText.textContent = 0;
    restartBtn.style.display = 'none';
    cpmGroup.style.display = 'none';
    wpmGroup.style.display = 'none';
}

 

게임이 끝났을 때 입력 불가능하게 막고 마무리 텍스가 나오고 재시작 버튼이 나오게 됩니다. cpm, wpm 계산도 나오도록 연산해줍니다.

function finishGame() {
    clearInterval(timer);


    // 입력 영역 비활성화
    inputArea.disabled = true;

    // 마무리 텍스트 표시
    quoteText.textContent = "새 게임을 시작하려면 다시 시작을 클릭하세요.";

    // 재시작 버튼을 보여주기
    restartBtn.style.display = "block";

    // wpm    
    // word per minutes 

    // cpm 
    // characters per minutes

    // CPM WPM 계산하기
    cpm = Math.round(((characterTyped / timeElapsed) * 60));
    wpm = Math.round((((characterTyped / 5) / timeElapsed) * 60));

    cpmText.textContent = cpm;
    wpmText.textContent = wpm;

    cpmGroup.style.display = "block";
    wpmGroup.style.display = "block";
}