예제/퀴즈 이펙트

퀴즈 이펙트_여러문제의 객관식 문제 만들어 봅시다!

아라라_ 2023. 3. 26. 18:04

“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”

Frederick Philips Brooks
Mythical Man-Month 저자
728x90

 

선택자

const quizWrap = document .querySelector(".quiz__wrap");
let quizScore = 0;

 

 

문제 정보

// 문제정보
const quizinfo =[
    {
        infoType : "정보처리 기능사",
        infoTime : "2008년 4회",
        infoNumber : "20080401",
        infoQuestion : "일반적으로 digital type 의 양을 바르게 표현한 것은?",
        infoChoice : {
            1: "시간의 흐름",
            2: "연필의 갯수",
            3: "온도의 변화",
            4: "식물의 성장"
        },
        infoAnswer : "2",
        infoDesc : "연필은 1.5개가 존재 하지 않으므로 디지털입니다"
        // 문제1 end
    },{
        infoType : "정보처리 기능사",
        infoTime : "2008년 4회",
        infoNumber : "20080402",
        infoQuestion : "입력단자와 출력단자가 반대가 되는 즉 “0” 이면 “1”,“1” 이면 “0”이 되는 것은?",
        infoChoice : {
            1: "AND",
            2: "NOT",
            3: "OR",
            4: "Flip-Flop"
        },
        infoAnswer : "2",
        infoDesc : "서로 반대가 된다고 하였으므로 NOT 게이트 이며 플리플롭이라면 T 플리플롭입니다."
        // 문제2 end
    },{

                                            ...

    },{
        infoType : "정보처리 기능사",
        infoTime : "2008년 4회",
        infoNumber : "20080459",
        infoQuestion : "다음 중 정지위성의 위치는 지구 적도 상공 약 몇 [km]인가?",
        infoChoice : {
            1: "25000",
            2: "36000",
            3: "45000",
            4: "56000"
        },
        infoAnswer : "2",
        infoDesc : "적도상공 약 36000킬로미터"
    },{
        infoType : "정보처리 기능사",
        infoTime : "2008년 4회",
        infoNumber : "20080460",
        infoQuestion : "다음 중 데이터 통신의 에러제어 방식에 속하지 않는 것은?",
        infoChoice : {
            1: "반향검사",
            2: "검출후 재전송",
            3: "전진에러수정",
            4: "자동송출제어"
        },
        infoAnswer : "4",
        infoDesc : "반향(ECHO)검사, 검출후 재전송(ARQ, 자동 반복 요청), 전진에러수정(FEC), 해밍(Hamming)코드, CRC방식 등이 있습니다"
    }
]

문제를 배열안에있는 객체에 키값과 함께 넣습니다.

60문제 이므로 인덱스는60개고 각각 infoType, infoTime, infoNumber, infoQuestion, infoAnswer, infoDesc이라는 키에 각각의 내용을 지정합니다.

 

 

 

문제 출력

const updateQuiz = () => {
            const exam = [];

            quizinfo.forEach((question, number) => {
                exam.push(`
                    <div class="quiz">
                        <div class="quiz__header">
                            <h2 class="quiz__title">${question.infoType} ${question.infoTime}</h2>
                        </div>
                        <div class="quiz__main">
                            <div class="quiz__question"><em>${number+1}</em>. ${question.infoQuestion}</div>
                            <div class="quiz__view">
                                <div class="dog__wrap">
                                    <div class="true">정답입니다!</div>
                                    <div class="false">틀렸습니다!</div>
                                    <div class="card-container">
                                        <div class="dog">
                                            <div class="head">
                                                <div class="ears"></div>
                                                <div class="face"></div>
                                                <div class="eyes">
                                                    <div class="teardrop"></div>
                                                </div>
                                                <div class="nose"></div>
                                                <div class="mouth">
                                                    <div class="tongue"></div>
                                                </div>
                                                <div class="chin"></div>
                                            </div>
                                            <div class="body">
                                                <div class="tail"></div>
                                                <div class="legs"></div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="quiz__choice">
                                <label for="choice1${number}">
                                    <input type="radio" id="choice1${number}" name="chioce${number}" value="1">
                                    <span>${question.infoChoice[1]}</span>
                                </label>
                                <label for="choice2${number}">
                                    <input type="radio" id="choice2${number}" name="chioce${number}" value="2">
                                    <span>${question.infoChoice[2]}</span>
                                </label>
                                <label for="choice3${number}">
                                    <input type="radio" id="choice3${number}" name="chioce${number}" value="3">
                                    <span>${question.infoChoice[3]}</span>
                                </label>
                                <label for="choice4${number}">
                                    <input type="radio" id="choice4${number}" name="chioce${number}" value="4">
                                    <span>${question.infoChoice[4]}</span>
                                </label>
                            </div>
                            <div class="quiz__desc">정답은 <em>${question.infoAnswer}</em>번 입니다.<br>${question.infoDesc}</div>
                        </div>
                    </div>
                    `)

                });
        exam.push(`
            <div class="quiz__info">?? 점</div>
            <div class="quiz__check">정답 확인!</div>
        `)

    quizWrap.innerHTML = exam.join('');

    // 설명 숨기기
        document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "none");  // (),{}생략


}
updateQuiz();       //실행 함수가 어디인지에 따라 다르다

문제를 출력하기 위해 html로 문제 출력할 준비를 했지만 이번에는 exam이라는 배열에 push()을 사용하여 넣습니다. 60문제를 만들기 위해서는 여러번 만들 수가 없기 때문에 forEach()로 문제 정보를 받아오면 그 갯수 만큼 만들수 있도록 할수 있습니다.

그리고 점수를 보여주고 확인하는 버튼을 push()을 사용하여 넣습니다.

그 후 join을 사용하여 사이에 ,을 없앱니다.

설명을 숨기기 위해 querySelectorAll로 .quiz__desc를 모두 선택하여 forEach()을 사용하여 한번에 여러개의 문제에 적용하여 설명을 숨깁니다.

 

 

정답확인 / 설명 보이기/점수 보이기


// 정답 확인
const answerQuiz = () => {
    const quizChoices = document.querySelectorAll(".quiz__choice");

    // 사용자가 체크한 정답 == 문제 정답(forEach)
    quizinfo.forEach((question, number) => {
        const userSelector = `input[name=chioce${number}]:checked`;     
        const quizSelectorWrap = quizChoices[number];
        const userAnswer = (quizSelectorWrap.querySelector(userSelector) || {}).value;
        const dogwrap = quizWrap.querySelectorAll(".dog__wrap");

        if(userAnswer == question.infoAnswer){
            console.log("정답")
            dogwrap[number].classList.add("like");
            quizScore++;
        } else{
            console.log("오답")
            dogwrap[number].classList.add("dislike");
            //
        }
    });

    // 설명 보이기
    document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "block");  // (),{}생략

    // 점수 보이기
    document.querySelector(".quiz__info").innerHTML = Math.ceil((quizScore / quizinfo.length)*100) + "점";
}

// 정답 클릭
document.querySelector(".quiz__check").addEventListener("click", answerQuiz)

이제 정답을 확인하기 위해 

우선 모든 선택지에대한 선택자를 변수로 지정합니다. 

여러개이기 때문에 quizinfo로 여러개의 문제를 forEach()로 반복하여 적용합니다.

선택지가 체크되었는지에대한 값을 변수에 저장하고 이를 여러문제의 여러개의 선택지를 넣기 위해 choice옆에 숫자말고 객체리터럴인 ${number}을 사용하여 선택지를 문제별로도 구분짓게 됩니다.

이제 빈값이 나왔을때 null로 박이 반환되는데 이때 빈객체({})가 사용되어 에러가 발생하는것을 방지합니다.이 때 value속성에 접근하는 것에 대해 에러가 발생하지 않도록합니다.

모든 .dog__wrap에 class를 추가하도록 하는데 정답일때 like가 추가되고 오답일 경우에 dislike가 추가되어 강아지가 다르게 반응하도록 합니다.

 

정답이든 아니든 무조건 설명과 점수가 나오도록 이번 함수 밖에 적용하여 보이도록 합니다.

이때 점수는 Math.ceil()을 사용하여 올림된 정수형의 점수를 반환합니다.

(quizScore / quizinfo.length)*100는 문제당 점수를 배정하여 100점중 몇점인지 지정합니다.

 

마지막으로 정답을 클릭하면 점수가 나오도록 addEventListener를 사용하여 click했을때 모든것이 발생되도록 이벤트를 지정합니다.

 

 

참고

https://jo0132.github.io/web2023/javascript/quiz/quizEffect05.html

 

퀴즈 이펙트05

 

jo0132.github.io

https://github.com/jo0132/web2023/blob/main/javascript/quiz/quizEffect05.html

 

GitHub - jo0132/web2023: 수업시간에 배운 수업 예제입니다.

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

github.com