javascript

quiz 유형 사이트 만들기- 07 ver3

grovy 2023. 4. 5. 19:48
728x90

퀴즈 사이트 만들기 !  ( 객관식유형 * 60문제 한번에 만들기+json형식 ) ver.3

어제 만든것에서 오늘은 좀더 소스를 다듬을거에요 

사용자 이름 입력 받는것 & timer 스크립트를 변경했어요 

 전체 소스는 요기 

주요 소스를 볼게요 ! 

 


<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">
				...
            </div>
            <div class="cbt__desc">객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다.</div>
            <div class="cbt__keyword">객체지향언어</div>
        </div> 
    </div>
</div>
<div class="cbt__aside">
    <div class="cbt__info">
        <div>
            <button class="cbt__submit">제출하기</button>
            <span class="cbt__time"></span>
        </div>
        <div>
            <div class="cbt__title">수험자 : <em class="cbt__name"></em></div>
            <div class="cbt__exam">
                <span>전체 문제수 : <em class="cbt__length">0</em>문항</span>
                <span>남은 문제수 : <em class="cbt__rest">0</em></span>
            </div>
            <div class="cbt__score hide"> 
                <span>점수 : <em >0</em></span>
            </div>
        </div>
    </div>
    <div class="cbt__omr">
        <div class="omr">
            <strong>1</strong>
            </label>
        </div>
    </div>
</div>
<div class="cbt__start"> 
    <div class="cbt__modal1">
        <h2>정보처리 & 웹디자인 기능사</h2>
        <div class="cbt__choice">
            <select name="cbtTime" id="cbtTime"  onchange="changeSelect(this)">
                <option value="gineungsaJC2005_02">정보처리기능사 2005년 2회</option>
                ....
                <option value="gineungsaJC2011_05">정보처리기능사 2011년 5회</option>
            </select>
            <select name="cbtTime" id="cbtTime"  onchange="changeSelect(this)">
                <option value="gineungsaWD2009_05">웹디자인기능사 2009년 5회</option>

                <option value="gineungsaWD2016_04">웹디자인기능사 2016년 4회</option>
            </select>
        </div>
        <div class="cbt__view">
            <input type="text" id='cbtUserName' autofocus placeholder="이름적어주세요"/>
            <span class="subject">과목을 선택하세요.</span>
        </div>
        <button class="cbt__start__btn">시작하기</button>
    </div>
</div>

위처럼 body영역엔 소스가 없고 

스크립트에서 소스를 cbt_quiz, cbt_omr에 소스를 뿌려 주는건 ver1과 동일해요 

모달창을 시작할때 실행되게끔 해놨어요 

 

오늘의 과제 

  1. 이름 입력
  2. 시간->0 일때 처리
  3. 점수결과

이름을 넣어주는 부분 깔끔하게 ! 

이름을 넣어주는 text박스의 값이 공백이면 ''이기 때문에 입력을 하지않을경우 바보라고 설정하고

입력받을경우 값을 넣어주도록했어요  

//이름가져오기 입력받은값을 가져오기 or 없으면 바보라고 출력되요 
let inputString = document.querySelector("#cbtUserName").value;
(inputString == '')?document.querySelector(".cbt__name").innerHTML = "바보" : document.querySelector(".cbt__name").innerHTML = inputString ;

남은시간이 0 일때 처리 & 타이머 종료시 처리 

// 1초마다 실행되게 setInterval함수를 썻어요 ! 
questionTime = setInterval(reduceTime,1000);

// 시간 설정
const reduceTime = () => {
    questionTimeRemain--;
    if(questionTimeRemain ==0)endQuiz();

    cbtCountTime.innerHTML=displayTime();
}
//시간표시
const displayTime = () =>{
    if(questionTimeRemain <=0){
        return "0분 00초"; 
    }else{
        let minutes = Math.floor(questionTimeRemain/60);
        let seconds = (Math.floor(questionTimeRemain%60)<=10)?"0"+Math.floor(questionTimeRemain%60):Math.floor(questionTimeRemain%60);
        return `${minutes}분 ${seconds}초 `;
        //초의 단위가 한자리일경우 앞에 0을 붙여주기
    }
}
// 시험 끝 
const endQuiz =()=>{
    answerQuiz();
    alert("시험끝");
}
//setInterval함수 종료 시키기 ! 
//clearInterval(questionTime);

// 요기는 저가 짠 소스에용 변수값을 --하는는 위 소스가 좀더 가독성이 좋네용 

// 시험시간20분계산 분 * 초 * 1000 1분의1초
const countTime = 20 * 60 * 1000+1500;

// 끝나는 기준 시간(현재 시간 + 20분+2000)을 계산 updateTimer 불러올때 +1.5초추가 해서계산
// 끝나는 기준시간이에용 고정값인 시간입니다. 
let endTime = Date.now() + countTime;

function updateTimer() {
    // 남은 시간을 계산합니다.
    const leftTime = endTime - Date.now();

    // 시, 분, 초를 계산합니다. 시간은 쓰지않아서 주석처리 시험시간은 20분으로 설정!
    // const hours = Math.floor(leftTime / countTime);
    const minutes = Math.floor((leftTime % countTime) / (60 * 1000));
    const seconds = Math.floor((leftTime % (60 * 1000)) / 1000);

    // 타이머를 화면에 출력합니다.
    cbtCountTime.innerText=`${minutes}분 ${seconds}초`;
    // 남은 시간이 없으면 타이머를 멈춥니다.
    if (leftTime <= 0){
    	//setInterval을 종료할땐 clearInterval(timer) 이런형식으로해요 
        //timer함수선언해서 요값이 들거가 있는거에요 
        clearInterval(timer);
        
        //시간종료 제출하기 & 시간대신 시간초과ㅜ표시
        answerQuiz();
        cbtCountTime.innerText=`시간초과ㅜ`;
    }
}
// setInterval을 이용하면 1초마다 타이머가 실행되게할수있어요

alert("시험끝") 으로 처리를 하고

answerQuiz()을 실행하여 채점을 하도록했습니다. 

 

또한 

setInterval() 메서드를 종료시켜야 해서 
clearInterval(questionTime) 요부분을 채점할경우 실행되게 했어요 ! 

정답 확인하기 & 점수 확인

const answerQuiz = () =>{
	//모든 체크 답안 가져오기 
    const cbtSelects = document.querySelectorAll(".cbt__selects");
    
    //모든 정보를 가져와서 forEach로 값을 비교할거에요
    questionAll.forEach((question, number) =>{
        const quizSelectsWrap = cbtSelects[number];
        const userSelector = `input[name=select${number}]:checked`;
        
		//객관식 보기 문제에 체크유무 상관없이 값을 가져오기
        const userAnswer = (quizSelectsWrap.querySelector(userSelector)||{}).value;
		//userAnswer의 값유무에 따라 slice하여 값을 가져와요 없으면 undefined
        const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;
        
        //정답을 가져와서 비교해요 그리고 정답일경우 cbtQuizScore를 증가시켜요! 
        if(Number(numberAnswer)+1 == question.Answer){
            cbtSelects[number].parentElement.classList.add("good");
            cbtQuizScore++;
        }else{
            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");
        }
    });
    // 점수 입력 
    cbtScore.querySelector("em").innerHTML =Math.floor(cbtQuizScore/questionAll.length*100)+" 점";
    // 남은문항 & 전체문항 삭제 & 점수 보이기 
    cbtExam.classList.add("hide");
    cbtScore.classList.remove("hide");
    //타이머종료 & 타이머 문구 시험종료로 변경
    cbtCountTime.innerHTML=" &nbsp;시험종료 !";
    clearInterval(questionTime);
    
    
}

cbtQuizScore를 증가시켜 점수를 구하는 로직을 마지막에 추가시켜줬어요 

 

오늘두 고생하셨습니다.