JAVASCRIPT

자바스크립트 퀴즈 이펙트 07

ture403 2023. 4. 3. 23:47

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90
반응형

완성된 화면입니다.

HTML 코드입니다.

<!DOCTYPE html>
<html lang="ko">
<head> 
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>퀴즈 이펙트07</title>

    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/quiz.css">

    <link rel="shortcut icon" type="image/x-icon" href="img/favicon.png"/>  
    <link rel="apple-touch-icon" sizes="114x114" href="img/favicon.png"/> 
    <link rel="apple-touch-icon" href="img/favicon.png"/>

</head>
<body>
    <header id="header">
        <h1><a href="../javascript14.html">Quiz</a> <em>객관식 확인 CBT 유형</em></h1>
        <ul>
            <li><a href="quizEffect01.html">1</a></li>
            <li><a href="quizEffect02.html">2</a></li> 
            <li><a href="quizEffect03.html">3</a></li>
            <li><a href="quizEffect04.html">4</a></li>
            <li><a href="quizEffect05.html">5</a></li>
            <li><a href="quizEffect06.html">6</a></li>
            <li class="active"><a href="quizEffect07.html">7</a></li>
        </ul>
    </header>
    <!-- //header -->

    <main id="main">
        <div class="quiz__wrap__cbt">
            <div class="cbt__header">
                <h2>2020년 1회 정보처리기능사 기출문제</h2>
            </div>
            <div class="cbt__conts">
                <div class="cbt__quiz">
                    <!-- <div class="cbt good">
                        <div class="cbt__question"><span>1</span>. 객체지향 프로그램에서 데이터를 추상화하는 단위는?</div>
                        <div class="cbt__question__img"><img src="img/gineungsaWD2023_01_01.jpg" alt="기능사"></div>
                        <div class="cbt__selects">
                            <input type="radio" id="select1">
                            <label for="select1"><span>클래스</span></label>
                            <input type="radio" id="select2">
                            <label for="select2"><span>메소드</span></label>
                            <input type="radio" id="select3">
                            <label for="select3"><span>상속</span></label>
                            <input type="radio" id="select4">
                            <label for="select4"><span>메시지</span></label>
                        </div>
                        <div class="cbt__desc">객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다.</div>
                        <div class="cbt__keyword">객체지향언어</div>
                    </div> -->
                </div>
            </div>
            <div class="cbt__aside">
                <div class="cbt__info">
                    <div>
                        <div class="cbt__title">수험자 : <em>홍길동</em></div>
                        <div class="cbt__score">
                            <span>전체 문제수 : <em class="mon">60</em>문항</span>
                            <span>남은 문제수 : <em class="mon2">59문항</em></span>
                        </div>
                    </div>
                </div>
                <div class="cbt__omr">
                    <!-- <div class="omr">
                        <strong>1</strong>
                        <input type="radio" id="omr0_1">
                        <label for="omr0_1">
                            <span class="label-inner">1</span>
                        </label>
                        <input type="radio" id="omr0_2">
                        <label for="omr0_2">
                            <span class="label-inner">2</span>
                        </label>
                        <input type="radio" id="omr0_3">
                        <label for="omr0_3">
                            <span class="label-inner">3</span>
                        </label>
                        <input type="radio" id="omr0_4">
                        <label for="omr0_4">
                            <span class="label-inner">4</span>
                        </label>
                    </div> -->
                </div>
            </div>
            <div class="cbt__submit">제출하기</div>
            <div class="cbt__time">59분 10초</div>
        </div>
    </main>
</body>

주석친 부분은 스크립트로 불러와서 문제를 입력할 부분 입니다. 

 

JS 코드입니다.

const cbt = document.querySelectorAll(".cbt");
const cbtQuiz = document.querySelector(".cbt__quiz");
const cbtOmr = document.querySelector(".cbt__omr");
const cbtSubmit = document.querySelector(".cbt__submit");
const ScoreEm = document.querySelector(".cbt__score .mon");
const ScoreEm2 = document.querySelector(".cbt__score .mon2");

let questionAll = [];  //모든 퀴즈 정보
let count = 0;
//데이터 가져오기
const dataQuestion = () => {
    fetch("json/gisa2020_01.json")
    .then(res => res.json())
    .then(items => {
        questionAll = items.map((item, index) => {
            const formattedQuestion = {
                question: item.question,
                number: index + 1
            }
            const answerChoices = [...item.incorrect_answers];  //오답 불러오기
            formattedQuestion.answer = Math.floor(Math.random() * answerChoices.length) + 1;
            answerChoices.splice(formattedQuestion.answer - 1, 0, item.correct_answer); 

            //보기를 추가
            answerChoices.forEach((choice, index) => {                  
                formattedQuestion["choice" + (index+1)] = choice;
            });

            //문제에 대한 해설이 있으면 출력
            if(item.hasOwnProperty("question_desc")){
                formattedQuestion.questionDesc = item.question_desc;
            }

            //문제에 대한 이미지가 있으면 출력
            if(item.hasOwnProperty("question_img")){
                formattedQuestion.questionImg = item.question_img;
            }

            //해설이 있으면 출력
            if(item.hasOwnProperty("desc")){
                formattedQuestion.desc = item.desc;
            }

            //console.log(formattedQuestion);

            return formattedQuestion;
        });
        newQuestion();  //문제 만들기

        //문제 총갯수
        ScoreEm.innerText= questionAll.length;
        ScoreEm2.textContent = questionAll.length+"문항";


    })
    .catch((err) => console.log(err));
}

//문제 만들기
const newQuestion = () => {
    const exam = [];
    const omr = [];
    questionAll.forEach((question, number) => {
        exam.push(`
            <div class="cbt">
                <div class="cbt__question"><span>${question.number}</span>. ${question.question}</div>
                <div class="cbt__question__img"></div>
                <div class="cbt__selects">
                    <input type="radio" id="select${number}_1" name="select${number}" value="${number+1}_1" onclick="answerSelect(this)">
                    <label for="select${number}_1"><span>${question.choice1}</span></label>
                    <input type="radio" id="select${number}_2" name="select${number}" value="${number+1}_2" onclick="answerSelect(this)">
                    <label for="select${number}_2"><span>${question.choice2}</span></label>
                    <input type="radio" id="select${number}_3" name="select${number}" value="${number+1}_3" onclick="answerSelect(this)">
                    <label for="select${number}_3"><span>${question.choice3}</span></label>
                    <input type="radio" id="select${number}_4" name="select${number}" value="${number+1}_4" onclick="answerSelect(this)">
                    <label for="select${number}_4"><span>${question.choice4}</span></label>
                </div>
                <div class="cbt__desc hide">${question.desc}</div>
            </div>
        `);

        omr.push(`
            <div class="omr">
                <strong>${question.number}</strong>
                <input type="radio" name="omr${number}" id="omr${number}_1" value="${number}_0">
                <label for="omr${number}_1"><span class="label-inner">1</span></label>
                <input type="radio" name="omr${number}" id="omr${number}_2" value="${number}_1">
                <label for="omr${number}_2"><span class="label-inner">2</span></label>
                <input type="radio" name="omr${number}" id="omr${number}_3" value="${number}_2">
                <label for="omr${number}_3"><span class="label-inner">3</span></label>
                <input type="radio" name="omr${number}" id="omr${number}_4" value="${number}_3">
                <label for="omr${number}_4"><span class="label-inner">4</span></label>
            </div>
        `)
    });
    cbtQuiz.innerHTML = exam.join('');
    cbtOmr.innerHTML = omr.join('');

}
//정답 확인
const answerQuiz = () => {
    const cbtSelects = document.querySelectorAll(".cbt__selects");
    questionAll.forEach((question, number) => {
        const quizSelectsWrap = cbtSelects[number];
        const userSelector = `input[name=select${number}]:checked`;
        const userAnswer = (quizSelectsWrap.querySelector(userSelector) || {}).value;
        const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;

        if(numberAnswer == question.answer){
            console.log("정답입니다.");
            cbtSelects[number].parentElement.classList.add("good");
            count++;
        } else {
            console.log("오답입니다.")
            cbtSelects[number].parentElement.classList.add("bad");

            // 오답일경우 정답표시
            const label = cbtSelects[number].querySelectorAll("label");
            label[question.answer-1].classList.add("correct");
        }

        const quizDesc = document.querySelectorAll(".cbt__desc");

        if(quizDesc[number].innerText == "undefined" ){
            quizDesc[number].classList.add("hide");
        } else {
            quizDesc[number].classList.remove("hide");
        }
    });
}
const answerSelect = (e) => {
    const countInput = document.querySelectorAll("input[type='radio']");
    let inputcount = 0;
    countInput.forEach((input)=>{
        if(input.checked) {
            inputcount++;
        }
    })
    ScoreEm2.textContent = questionAll.length - inputcount +"문항";
}

cbtSubmit.addEventListener("click", answerQuiz);
dataQuestion();
  • HTML 문서에서 class 이름이 cbt인 요소들을 선택하여 cbt라는 이름으로 저장합니다.
  • HTML 문서에서 class 이름이 cbt__quiz, cbt__omr, cbt__submit, cbt__score .mon, cbt__score .mon2인 요소들을 선택하여 각각 cbtQuiz, cbtOmr, cbtSubmit, ScoreEm, ScoreEm2라는 이름으로 저장합니다.
  • questionAll이라는 이름의 빈 배열을 생성합니다.
  • dataQuestion이라는 이름의 함수를 호출합니다. 이 함수는 fetch() 메소드를 사용하여 JSON 파일을 가져오고, 가져온 데이터를 가공하여 questionAll 배열에 저장합니다.
  • newQuestion이라는 이름의 함수를 호출합니다. 이 함수는 questionAll 배열을 순회하면서, 각각의 문제에 대한 HTML 코드를 생성합니다. 각각의 HTML 코드는 exam 배열과 omr 배열에 저장됩니다. 마지막으로 exam 배열과 omr 배열을 cbtQuiz와 cbtOmr 요소의 innerHTML 속성에 할당하여 문제와 보기를 출력합니다.
  • answerQuiz라는 이름의 함수를 호출합니다. 이 함수는 각각의 문제에 대한 사용자의 답안을 확인합니다.
  • answerSelect라는 input 박스가 선택 됬을대 남은 문항을 체그하는 함수 입니다.
  • input type=radio인지  확인하고 그걸 forEach로 돌려서 각 요소에 checked가 붙은 것에 inputcount 값을 증가시켜서 배열에 담았습니다.
  • 글 ScoreEm2 에 총갯수에서 증가된값을 빼서 텍스트를 입력했습니다.

완성된 코드입니다.

https://github.com/ture403/web2023/blob/main/javascript/quiz/quizEffect07.html

 

GitHub - ture403/web2023: 수업시간예제입니다.

수업시간예제입니다. Contribute to ture403/web2023 development by creating an account on GitHub.

github.com

완성된 화면 입니다.

https://ture403.github.io/web2023/javascript/quiz/quizEffect07.html

 

퀴즈 이펙트07

수험자 : 홍길동 전체 문제수 : 60문항 남은 문제수 : 59문항

ture403.github.io

전에있던 퀴즈 이펙트 06번입니다.

https://ture403.tistory.com/57