한번씩 읽고 가세요.
“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”
- Frederick Philips Brooks
Mythical Man-Month 저자
728x90
미션 1 : 점수 결과 표시
cbtSubmit.addEventListener("click", answerQuiz)
제출하기 버튼을 눌렀을때 점수를 표시 해줘야하기 때문에 이벤트가 적용되어있는 answerQuiz에
document.querySelector(".cbt__result span").innerHTML = Math.ceil((quizScore / questionAll.length) *100) + "점"
를 넣어주었다.
그리고 출력 될 cbt__result span 이라는 창을 만들어 hide를 주어 숨겨놓은 다음 클릭 하면 나올수 있게
const cbtResult = document.querySelector(".cbt__result ").classList.remove("hide")
코드를 주었다.
미션 2 : 시간 초 0 추가 하기
const displayTime = () => {
if (questionTimeRemain <= 0) {
return "0분 00초";
} else {
let minutes = Math.floor(questionTimeRemain / 60);
let seconds = questionTimeRemain % 60 < 10 ? "0" + (questionTimeRemain % 60) : questionTimeRemain % 60;
return minutes + "분 " + seconds + "초";
//초의 단위가 한자리 수가 되면 앞에 0을 붙여주기
}
}
초의 단위가 10보다 아래로 내려가면 09초가 아닌 9초가 나오기 때문에 조건문을 사용해 second가 10 보다 작을때 앞에 0을 붙여주는 코드를 넣었다.
미션 3 : 이름 > 입력
당신의 이름은 <input type="text" class="name"> 입니다.<br>
인풋 박스를 선택자로 만들고
<div class="cbt__title">수험자 : <em class="cbt__name">김현빈</em></div>
cbt__name 부분에 넣을거기 때문에 이 친구도 선택자를 만들어준 후
cbtName.innerHTML = `${Name.value}`
input박스의 value 값을 cbt__name부분에 가져와 준다.
시작 버튼을 누르면 적용하기 때문에
const startQuiz = () => {
cbtStart.classList.add("hide") //모달창 제거
cbtName.innerHTML = `${Name.value}`
//시간 설정
questionTime = setInterval(reduceTime, 1000)
}
startQuiz함수에 넣어 실해시켜줍니다.
스크립트 코드
<script>
let questionAll = []; //모든 퀴즈 정보
const cbtQuiz = document.querySelector(".cbt__quiz")
const cbtOmr = document.querySelector(".cbt__omr")
const cbtSubmit = document.querySelector(".cbt__submit")
const cbtRest = document.querySelector(".cbt__rest")
const cbtLength = document.querySelector(".cbt__length")
const cbtBtn = document.querySelector(".minimal");
const cbtStart = document.querySelector(".cbt__start");
const cbtIndex = document.querySelector(".cbt__index");
const cbtIndex2 = document.querySelector(".cbt__index2");
const cbtViewSubject = document.querySelector(".cbt__view .subject");
const cbtHeader = document.querySelector(".cbt__header h2");
const cbtTime = document.querySelector(".cbt__time");
const cbtName = document.querySelector(".cbt__name");
const Name = document.querySelector(".name");
let quizCount = 0;
let quizScore = 0;
let querySelectorAll = []; //모든퀴즈 정보
let questionLength = 0; //전체 문제수
let questionRest = questionLength; //남은 문제수
let questionTime = "";
let questionTimeRemain = "10"
//시작하기
const startQuiz = () => {
cbtStart.classList.add("hide") //모달창 제거
cbtName.innerHTML = `${Name.value}`
//시간 설정
questionTime = setInterval(reduceTime, 1000)
}
//클릭시 시작
//데이터 불러오기
const dataQuestion = (value) => {
fetch(`https://kebab000.github.io/web2023/gineungsaJSON/${value}.json`)
.then(res => res.json()) //.then() .then () 체인 방식
.then(items => {
questionAll = items.map((item, index) => {
const formattedQuestion = {
question: item.question,
number: index + 1,
}
const answerChoices = [...item.incorrect_answers]; //오답 불러오기
formattedQuestion.answer = Math.round(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.question_desc = item.question_desc;
}
//문제의 대한 이미지 있으면 출력
if (item.hasOwnProperty("question_img")) {
formattedQuestion.question_img = item.question_img;
}
//장답 해설이 있으면 출력
if (item.hasOwnProperty("desc")) {
formattedQuestion.desc = item.desc;
}
return formattedQuestion;
})
newQuestion(); //문제만들기
//전체 문제수
questionLength = questionAll.length;
cbtLength.innerHTML = questionLength
cbtRest.innerHTML = questionLength
})
.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"><img src="https://kebab000.github.io/web2023/gineungsaJPG/${question.question_img}.jpg" alt=""></div>
<div class="cbt__question__desc">${question.question_desc}</div>
<div class="cbt__selects">
<input type="radio" id="select${number}_1" name="select${number}" value="${number}_1" onclick="answerSelect2(this)">
<label for="select${number}_1"><span>${question.choice1}</span></label>
<input type="radio" id="select${number}_2" name="select${number}" value="${number}_2" onclick="answerSelect2(this)">
<label for="select${number}_2"><span>${question.choice2}</span></label>
<input type="radio" id="select${number}_3" name="select${number}" value="${number}_3" onclick="answerSelect2(this)">
<label for="select${number}_3"><span>${question.choice3}</span></label>
<input type="radio" id="select${number}_4" name="select${number}" value="${number}_4" onclick="answerSelect2(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}_1" onclick="answerSelect(this)">
<label for="omr${number}_1">
<span class="label-inner">1</span>
</label>
<input type="radio" name="omr${number}" id="omr${number}_2" value="${number}_2" onclick="answerSelect(this)">
<label for="omr${number}_2">
<span class="label-inner">2</span>
</label>
<input type="radio" name="omr${number}" id="omr${number}_3" value="${number}_3" onclick="answerSelect(this)">
<label for="omr${number}_3">
<span class="label-inner">3</span>
</label>
<input type="radio" name="omr${number}" id=id="omr${number}_4" value="${number}_4" onclick="answerSelect(this)">
<label for="omr${number}_4">
<span class="label-inner">4</span>
</label>
</div>
`)
});
cbtQuiz.innerHTML = exam.join('');
cbtOmr.innerHTML = omr.join('');
document.querySelectorAll(".cbt__question__desc").forEach(desc => {
if (desc.innerHTML === "undefined") {
desc.classList.add("hide")
}
})
document.querySelectorAll(".cbt__question__img").forEach(img => {
let src = img.querySelector("img").src;
if (src.includes("undefined")) {
img.classList.add("hide")
}
})
// const questionzDesc = document.querySelectorAll(".cbt__question_desc");
// questionzDesc.forEach(e => {
// if(e.innerHTML == "undefined"){
// e.style.display = "none";
// }
// });
}
//정답 확인
const answerQuiz = () => {
const cbtResult = document.querySelector(".cbt__result ").classList.remove("hide")
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");
quizScore++
} 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");
}
document.querySelector(".cbt__result span").innerHTML = Math.ceil((quizScore / questionAll.length) *100) + "점"
});
}
// 보기 체크
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개
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 = () => {
// let selectedValue = cbtIndex.options[cbtIndex.selectedIndex].value;
// let selectText = cbtIndex.options[cbtIndex.selectedIndex].text;
// alert(selectText)
// }
// const changeSelect2 = () => {
// let selectedValue = cbtIndex2.options[cbtIndex2.selectedIndex].value;
// let selectText = cbtIndex2.options[cbtIndex2.selectedIndex].text;
// alert(selectText)
// }
//제목 선택
const changeSelect = (e) => {
let selectValue = e.value;
let selectText = e.options[e.selectedIndex].text;
console.log(selectValue)
console.log(selectText)
cbtViewSubject.innerHTML = selectText
cbtHeader.innerHTML = selectText
dataQuestion(selectValue)
}
//시간 설정
const reduceTime = () => {
questionTimeRemain--;
console.log("first")
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 < 10 ? "0" + (questionTimeRemain % 60) : questionTimeRemain % 60;
return minutes + "분 " + seconds + "초";
//초의 단위가 한자리 수가 되면 앞에 0을 붙여주기
}
}
//시험 끝
const endQuiz = () => {
alert("시험끝")
}
cbtBtn.addEventListener("click", startQuiz);
cbtSubmit.addEventListener("click", answerQuiz);
dataQuestion();
// 버블버튼
const bubbleBtn = () => {
// clips the value to given range
const clip = (v, min, max = Infinity) => {
if (v < min) return min;
else if (v > max) return max;
else return v;
};
// generated random value from given range
const randRange = (min, max) => Math.random() * max + min;
// create bubble on x and y position inside target with given hue theme
function bubble(x, y, rect, hue, target) {
// variables
const size = randRange(20, rect.width / 5);
const circleHue = hue + randRange(-20, 20);
const animDuration = randRange(clip(size ** 2 / 1000, 1), 6)
const zIndex = Math.random() < 0.1 ? 2 : -1;
// 원 만들기
const circle = document.createElement("span");
circle.className = "lit";
circle.style.left = x + "px";
circle.style.top = y + "px";
circle.style.width = size + "px";
circle.style.height = size + "px";
circle.style.background = `hsl(${circleHue}deg, 100%, 80%)`;
circle.style.zIndex = zIndex
circle.style.animationDuration = animDuration + "s";
target.appendChild(circle);
}
document.querySelectorAll("[data-lit-hue]").forEach((target) => {
const rect = target.getBoundingClientRect();
const hue = Number(target.getAttribute("data-lit-hue"));
const count = Number(target.getAttribute("data-lit-count") || 50);
for (let i = 0; i < count; i++) {
const x = randRange(0, rect.width);
const y = randRange(0, rect.height);
bubble(x, y, rect, hue, target);
}
});
}
bubbleBtn();