퀴즈 이펙트 ( 7-3 ) cbt
퀴즈 이펙트 ( 7-3 ) json 연동과 cbt연동 완성입니다.
[ json파일 연동 완료 ]
추가 VSCode
<div class="cbt__view">
당신의 이름은 <input type="text" class="name">입니다.<br>
당신은 <span class="subject">웹디자인 기능사시험</span>을 선택했습니다.
</div>
<button class="ctb__start__btn">시작하기</button>
모달창에 이름을 입력할 수 있는 input 창과, 어떤 기능사 종류를 골랐는지 나타내는 span을 추가했습니다.
추가 script
const cbtScore = document.querySelector(".cbt__score");
const cbtName = document.querySelector(".cbt__name");
const cbtViewInput = document.querySelector(".cbt__view input");
const cbtViewSubject = document.querySelector(".cbt__view .subject");
const cbtHeader = document.querySelector(".cbt__header h2");
const cbtTime = document.querySelector(".cbt__time");
const cbtBtn = document.querySelector(".ctb__start__btn");
const cbtStart = document.querySelector(".cbt__start");
let quizScore = 0;
let questionAll = []; //모든 퀴즈 정보
let questionLength = 0; //전체 문제수
let questionRest = questionLength; //남은 문제수
let questionTime = "";
let questionTimeRemain = "3600";
const startQuiz = () => {
//모달창 닫기
cbtStart.classList.add("hide");
//이름적을시 이름표
cbtName.innerText = cbtViewInput.value;
if(cbtViewInput.value == ""){
cbtName.innerText = "바보"
}
//초 세기
questionTime = setInterval(reduceTime, 1000);
}
cbtBtn.addEventListener("click", startQuiz);
선택자 추가
const cbtScore = document.querySelector(".cbt__score"); 점수
const cbtName = document.querySelector(".cbt__name"); 이름
const cbtViewInput = document.querySelector(".cbt__view input"); 이름입력
const cbtViewSubject = document.querySelector(".cbt__view .subject"); 기능사 종류
const cbtHeader = document.querySelector(".cbt__header h2"); 제목
const cbtTime = document.querySelector(".cbt__time"); 타이머
const cbtBtn = document.querySelector(".ctb__start__btn"); 모달창 시작버튼
const cbtStart = document.querySelector(".cbt__start"); 모달창
let quizScore = 0; //최종점수
let questionAll = []; //모든 퀴즈 정보
let questionLength = 0; //전체 문제수
let questionRest = questionLength; //남은 문제수
let questionTime = ""; //setInterval 메서드를 위한 변수
let questionTimeRemain = "3600"; //남은 시간(3600 = 1시간)\
startQuiz 함수는 모달창 버튼이 클릭될 시 실행되며, 실행 될 시 모달창이 닫히며 인풋값에 적힌 값이 이름이 되고
타이머가 흐르기 시작합니다.
setInterval은 자바스크립트에서 제공하는 함수 중 하나로, 지정된 시간 간격마다 반복적으로 코드를 실행할 수 있게 해줍니다.
setInterval 함수는 다음과 같은 인자를 받습니다
첫 번째 인자는 실행할 코드 또는 함수를 담고 있는 문자열 또는 함수 객체입니다.
두 번째 인자는 실행 간격을 나타내는 시간(ms)입니다.
세 번째 인자는 선택적으로 반복적으로 실행할 횟수를 나타내는 정수입니다. 이 인자가 생략되면 함수는 무한히 반복됩니다.
setInterval 함수는 일반적으로 타이머 기능을 구현하거나 반복적으로 어떤 작업을 수행해야 할 때 사용됩니다. 예를 들어, 웹 페이지에서 특정 내용을 주기적으로 업데이트하거나, 게임에서 적이 이동하는 애니메이션을 구현할 때 setInterval 함수를 사용할 수 있습니다.
//정답 확인
const answerQuiz = () => {
const cbtSelect = document.querySelectorAll(".cbt__selects");
questionAll.forEach((question, number) => {
const quizSelectWrap = cbtSelect[number];
const userSelector = `input[name=select${number}]:checked`;
const userAnswer = (quizSelectWrap.querySelector(userSelector) || {}).value;
const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;
const score = Math.ceil(quizScore / questionAll.length) * 100;
if(numberAnswer == question.Answer){
console.log("O");
cbtSelect[number].parentElement.classList.add("good");
quizScore++
} else {
console.log("X")
cbtSelect[number].parentElement.classList.add("bad");
//오답일 경우 정답 표시
const label = cbtSelect[number].querySelectorAll("label");
label[question.Answer-1].classList.add("correct");
}
//설명 숨기기
const quizDesc = document.querySelectorAll(".cbt__desc");
if(quizDesc[number].innerHTML == "undefined"){
quizDesc[number].classList.add("hide");
} else {
quizDesc[number].classList.remove("hide");
}
//점수 표시
if(score >=60){
document.querySelector(".score").innerHTML = `총 점수: ${score}점! <br>잘하셨어요!`;
clearInterval(questionTime);
} else {
document.querySelector(".score").innerHTML = `총 점수: ${score}점 <br> 공부하세요!!`;
clearInterval(questionTime);
}
});
}
cbtSubmit.addEventListener("click", answerQuiz);
cbtSubmit 제출하기 버튼을 누를시 answerQuiz 함수가 실행 됩니다.
사용자가 선택한 답변이 정답과 일치하는 경우 "O"를 출력하고, good 클래스를 가진 부모 요소에 addClass 메소드를 사용하여 스타일을 추가합니다. 또한 퀴즈 점수를 증가시킵니다.
사용자가 선택한 답변이 정답과 다른 경우 "X"를 출력하고, bad 클래스를 가진 부모 요소에 addClass 메소드를 사용하여 스타일을 추가합니다. 이때, querySelectorAll() 메소드를 사용하여 정답을 표시합니다.
.cbt__desc 클래스를 가진 요소들을 선택하고, 해당 요소가 "undefined"인 경우 hide 클래스를 추가하여 숨깁니다.
점수를 계산하고, score 변수에 저장합니다.
점수에 따라 innerHTML 속성을 사용하여 화면에 표시하고 clearInterval() 메소드를 사용하여 시간 제한을 중지합니다.
//보기 체크
const answerSelect2 = (elem) => {
const answer = elem.value;
const answerNum = answer.split("_"); //보기 눌렀을시 [문제번호_보기번호] 를 _기준으로 나눔
const select = document.querySelectorAll(".cbt__omr .omr"); //전체 문항 수 100개
const label = select[answerNum[0]].querySelectorAll("input"); //보기 4개, input아래엔 .cbt__omr, .cbt__quiz 클래스가 다 있음.
label[answerNum[1]-1].checked = true;
const answerInputs = document.querySelectorAll(".cbt__selects input:checked"); //보기를 체크했을 시
cbtRest.innerHTML = questionLength - answerInputs.length; //총 문제수 - 보기 체크 수 = 남은 문제 수
}
//보기 체크2
const answerSelect = (elem) => {
const answer = elem.value;
const answerNum = answer.split("_"); //보기 눌렀을시 [문제번호_보기번호] 를 _기준으로 나눔
const select = document.querySelectorAll(".cbt__quiz .cbt"); //전체 문항 수 100개
const label = select[answerNum[0]].querySelectorAll("input"); //보기 4개
label[answerNum[1]-1].checked = true;
const answerInputs = document.querySelectorAll(".cbt__selects input:checked"); //보기를 체크했을 시
cbtRest.innerHTML = questionLength - answerInputs.length; //총 문제수 - 보기 체크 수 = 남은 문제 수
}
//문제 선택
const changeSelect = (e) => {
let selectValue = e.value;
let selectText = e.options[e.selectedIndex].text;
cbtViewSubject.innerText = selectText;
cbtHeader.innerText = selectText;
dataQuestion(selectValue);
}
// 시간 설정
const reduceTime = () => {
questionTimeRemain--;
if(questionTimeRemain == 0) endQuiz();
cbtTime.innerText = displayTime();
}
//시간 표시
const displayTime = () => {
if(questionTimeRemain <=0){
return "0분 00초";
} else {
let minutes = Math.floor(questionTimeRemain / 60);
let seconds = questionTimeRemain % 60;
return minutes + "분 " + seconds.toString().padStart(2, '0') + "초 "; //padStart 초앞에 0뜨게 하기
//초의 단위가 한자리 수가 되면 앞에 0을 붙여주기
}
}
//시험 끝
const endQuiz = () => {
alert("시험이 끝났습니다.");
clearInterval(questionTime);
}
answerSelect()와 answerSelect2() : 문제의 보기를 클릭했을 때 보기를 체크하도록 하는 함수입니다. answer 변수에는 문제번호와 보기번호가 합쳐져서 들어온 문자열이 있습니다. answerNum 변수는 이 문자열을 문제번호와 보기번호로 분리합니다. 그리고 querySelectorAll 함수를 이용하여 문제번호에 해당하는 문제를 선택하고, 그 안에서 보기번호에 해당하는 보기를 선택하게 됩니다. 이를 통해 보기를 클릭하면 해당 보기가 체크되도록 합니다. 마지막으로 cbtRest 변수를 이용하여 남은 문제 수를 계산합니다.
changeSelect() : 문항을 선택했을 때 실행되는 함수입니다. e 매개변수는 선택된 option 요소입니다. 선택된 값에 해당하는 문제들을 가져오기 위해 dataQuestion() 함수를 호출합니다.
reduceTime() : 시간이 경과할 때마다 호출되는 함수로, 남은 시간을 1초씩 감소시킵니다. 남은 시간이 0초가 되면 endQuiz() 함수를 호출합니다.
displayTime() : 시간을 분과 초 단위로 표시하는 함수입니다. questionTimeRemain 변수에 저장된 시간 정보를 분과 초로 분리하고, 이를 문자열로 만들어 반환합니다.
endQuiz() : 시험이 끝났을 때 실행되는 함수입니다. 경고창을 띄우고, 시간 제한 타이머를 중지시킵니다.