|
|
<!doctype html>
|
|
|
<html lang="ko">
|
|
|
<head>
|
|
|
<meta charset="utf-8"/>
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
|
<title>웹 퀴즈</title>
|
|
|
<style>
|
|
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
|
|
|
|
|
|
* {
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
body {
|
|
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
|
line-height: 1.6;
|
|
|
margin: 0;
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
color: #1a202c;
|
|
|
min-height: 100vh;
|
|
|
padding: 20px 0;
|
|
|
}
|
|
|
|
|
|
.container {
|
|
|
max-width: 800px;
|
|
|
margin: 0 auto;
|
|
|
padding: 0 20px;
|
|
|
}
|
|
|
|
|
|
.quiz-header {
|
|
|
background: rgba(255, 255, 255, 0.95);
|
|
|
backdrop-filter: blur(20px);
|
|
|
border-radius: 20px;
|
|
|
padding: 30px;
|
|
|
margin-bottom: 25px;
|
|
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
|
}
|
|
|
|
|
|
.quiz-title {
|
|
|
font-size: 28px;
|
|
|
font-weight: 700;
|
|
|
margin: 0 0 15px 0;
|
|
|
background: linear-gradient(135deg, #667eea, #764ba2);
|
|
|
-webkit-background-clip: text;
|
|
|
-webkit-text-fill-color: transparent;
|
|
|
background-clip: text;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.quiz-controls {
|
|
|
display: flex;
|
|
|
gap: 12px;
|
|
|
justify-content: center;
|
|
|
flex-wrap: wrap;
|
|
|
}
|
|
|
|
|
|
.btn {
|
|
|
background: linear-gradient(135deg, #667eea, #764ba2);
|
|
|
color: white;
|
|
|
border: none;
|
|
|
border-radius: 12px;
|
|
|
padding: 12px 24px;
|
|
|
cursor: pointer;
|
|
|
font-weight: 500;
|
|
|
font-size: 14px;
|
|
|
transition: all 0.3s ease;
|
|
|
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
|
|
|
}
|
|
|
|
|
|
.btn:hover:not(:disabled) {
|
|
|
transform: translateY(-2px);
|
|
|
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
|
|
|
}
|
|
|
|
|
|
.btn:disabled {
|
|
|
opacity: 0.5;
|
|
|
cursor: not-allowed;
|
|
|
transform: none;
|
|
|
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.2);
|
|
|
}
|
|
|
|
|
|
.status-bar {
|
|
|
background: rgba(255, 255, 255, 0.9);
|
|
|
backdrop-filter: blur(10px);
|
|
|
border-radius: 15px;
|
|
|
padding: 15px 25px;
|
|
|
margin-bottom: 20px;
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
|
|
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
|
}
|
|
|
|
|
|
.progress-info {
|
|
|
font-weight: 500;
|
|
|
color: #4a5568;
|
|
|
}
|
|
|
|
|
|
.score-display {
|
|
|
background: linear-gradient(135deg, #48bb78, #38a169);
|
|
|
color: white;
|
|
|
padding: 8px 16px;
|
|
|
border-radius: 20px;
|
|
|
font-weight: 600;
|
|
|
font-size: 14px;
|
|
|
box-shadow: 0 4px 12px rgba(72, 187, 120, 0.3);
|
|
|
}
|
|
|
|
|
|
.message-area {
|
|
|
min-height: 24px;
|
|
|
text-align: center;
|
|
|
font-weight: 500;
|
|
|
color: #e53e3e;
|
|
|
margin-bottom: 15px;
|
|
|
}
|
|
|
|
|
|
.card {
|
|
|
background: rgba(255, 255, 255, 0.95);
|
|
|
backdrop-filter: blur(20px);
|
|
|
border-radius: 20px;
|
|
|
padding: 30px;
|
|
|
margin: 20px 0;
|
|
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
|
transition: all 0.3s ease;
|
|
|
}
|
|
|
|
|
|
.card:hover {
|
|
|
transform: translateY(-2px);
|
|
|
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15);
|
|
|
}
|
|
|
|
|
|
.question-text {
|
|
|
font-size: 18px;
|
|
|
font-weight: 500;
|
|
|
line-height: 1.7;
|
|
|
margin-bottom: 25px;
|
|
|
color: #2d3748;
|
|
|
}
|
|
|
|
|
|
.choice-wrapper {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
margin: 12px 0;
|
|
|
}
|
|
|
|
|
|
.choice {
|
|
|
display: block;
|
|
|
border: 2px solid #e2e8f0;
|
|
|
border-radius: 12px;
|
|
|
padding: 16px 20px;
|
|
|
margin: 0;
|
|
|
background: white;
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s ease;
|
|
|
font-weight: 500;
|
|
|
color: #4a5568;
|
|
|
flex: 1;
|
|
|
}
|
|
|
|
|
|
.choice:hover {
|
|
|
border-color: #667eea;
|
|
|
background: #f7fafc;
|
|
|
transform: translateX(4px);
|
|
|
}
|
|
|
|
|
|
.choice.selected {
|
|
|
border-color: #667eea;
|
|
|
background: linear-gradient(135deg, #ebf4ff, #e6fffa);
|
|
|
color: #2b6cb0;
|
|
|
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);
|
|
|
}
|
|
|
|
|
|
.choice.correct {
|
|
|
border-color: #48bb78;
|
|
|
background: linear-gradient(135deg, #f0fff4, #c6f6d5);
|
|
|
color: #22543d;
|
|
|
box-shadow: 0 4px 12px rgba(72, 187, 120, 0.3);
|
|
|
}
|
|
|
|
|
|
.choice.wrong {
|
|
|
border-color: #f56565;
|
|
|
background: linear-gradient(135deg, #fff5f5, #fed7d7);
|
|
|
color: #742a2a;
|
|
|
box-shadow: 0 4px 12px rgba(245, 101, 101, 0.3);
|
|
|
}
|
|
|
|
|
|
.choice:disabled {
|
|
|
cursor: not-allowed;
|
|
|
}
|
|
|
|
|
|
.checkbox-input {
|
|
|
margin-right: 12px;
|
|
|
width: 18px;
|
|
|
height: 18px;
|
|
|
accent-color: #667eea;
|
|
|
}
|
|
|
|
|
|
.result-card {
|
|
|
background: rgba(255, 255, 255, 0.95);
|
|
|
backdrop-filter: blur(20px);
|
|
|
border-radius: 20px;
|
|
|
padding: 30px;
|
|
|
margin-top: 20px;
|
|
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
|
}
|
|
|
|
|
|
.result-status {
|
|
|
font-size: 20px;
|
|
|
font-weight: 700;
|
|
|
margin-bottom: 15px;
|
|
|
text-align: center;
|
|
|
padding: 15px;
|
|
|
border-radius: 12px;
|
|
|
}
|
|
|
|
|
|
.result-correct {
|
|
|
background: linear-gradient(135deg, #c6f6d5, #9ae6b4);
|
|
|
color: #22543d;
|
|
|
}
|
|
|
|
|
|
.result-wrong {
|
|
|
background: linear-gradient(135deg, #fed7d7, #fbb6ce);
|
|
|
color: #742a2a;
|
|
|
}
|
|
|
|
|
|
.answer-display {
|
|
|
font-size: 16px;
|
|
|
font-weight: 600;
|
|
|
margin: 15px 0;
|
|
|
padding: 15px;
|
|
|
background: #f7fafc;
|
|
|
border-radius: 10px;
|
|
|
border-left: 4px solid #667eea;
|
|
|
}
|
|
|
|
|
|
.explanation {
|
|
|
color: #718096;
|
|
|
font-size: 14px;
|
|
|
line-height: 1.6;
|
|
|
margin-top: 15px;
|
|
|
padding: 15px;
|
|
|
background: #f8f9fa;
|
|
|
border-radius: 10px;
|
|
|
border-left: 4px solid #a0aec0;
|
|
|
}
|
|
|
|
|
|
.meta-info {
|
|
|
color: #a0aec0;
|
|
|
font-size: 12px;
|
|
|
font-weight: 500;
|
|
|
margin-top: 20px;
|
|
|
text-align: center;
|
|
|
text-transform: uppercase;
|
|
|
letter-spacing: 0.5px;
|
|
|
}
|
|
|
|
|
|
.completion-card {
|
|
|
text-align: center;
|
|
|
background: linear-gradient(135deg, #667eea, #764ba2);
|
|
|
color: white;
|
|
|
border-radius: 20px;
|
|
|
padding: 40px;
|
|
|
box-shadow: 0 25px 50px rgba(102, 126, 234, 0.3);
|
|
|
}
|
|
|
|
|
|
.completion-title {
|
|
|
font-size: 32px;
|
|
|
font-weight: 700;
|
|
|
margin-bottom: 15px;
|
|
|
}
|
|
|
|
|
|
.completion-score {
|
|
|
font-size: 18px;
|
|
|
opacity: 0.9;
|
|
|
margin-bottom: 25px;
|
|
|
}
|
|
|
|
|
|
.restart-btn {
|
|
|
background: rgba(255, 255, 255, 0.2);
|
|
|
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
|
color: white;
|
|
|
padding: 15px 30px;
|
|
|
border-radius: 12px;
|
|
|
font-weight: 600;
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s ease;
|
|
|
}
|
|
|
|
|
|
.restart-btn:hover {
|
|
|
background: rgba(255, 255, 255, 0.3);
|
|
|
transform: translateY(-2px);
|
|
|
}
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
.container {
|
|
|
padding: 0 10px;
|
|
|
}
|
|
|
|
|
|
.quiz-header {
|
|
|
padding: 20px 15px;
|
|
|
margin-bottom: 15px;
|
|
|
}
|
|
|
|
|
|
.quiz-title {
|
|
|
font-size: 22px;
|
|
|
}
|
|
|
|
|
|
.quiz-controls {
|
|
|
gap: 8px;
|
|
|
}
|
|
|
|
|
|
.btn {
|
|
|
padding: 10px 18px;
|
|
|
font-size: 13px;
|
|
|
}
|
|
|
|
|
|
.status-bar {
|
|
|
padding: 12px 20px;
|
|
|
flex-direction: column;
|
|
|
gap: 10px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.card {
|
|
|
padding: 20px 15px;
|
|
|
margin: 15px 0;
|
|
|
}
|
|
|
|
|
|
.question-text {
|
|
|
font-size: 16px;
|
|
|
line-height: 1.6;
|
|
|
}
|
|
|
|
|
|
.choice-wrapper {
|
|
|
margin: 10px 0;
|
|
|
}
|
|
|
|
|
|
.choice {
|
|
|
padding: 14px 16px;
|
|
|
font-size: 14px;
|
|
|
line-height: 1.5;
|
|
|
}
|
|
|
|
|
|
.checkbox-input {
|
|
|
margin-right: 10px;
|
|
|
width: 16px;
|
|
|
height: 16px;
|
|
|
}
|
|
|
|
|
|
.result-card {
|
|
|
padding: 20px 15px;
|
|
|
}
|
|
|
|
|
|
.result-status {
|
|
|
font-size: 18px;
|
|
|
padding: 12px;
|
|
|
}
|
|
|
|
|
|
.answer-display {
|
|
|
font-size: 15px;
|
|
|
padding: 12px;
|
|
|
}
|
|
|
|
|
|
.explanation {
|
|
|
font-size: 13px;
|
|
|
padding: 12px;
|
|
|
}
|
|
|
|
|
|
.completion-card {
|
|
|
padding: 30px 20px;
|
|
|
}
|
|
|
|
|
|
.completion-title {
|
|
|
font-size: 26px;
|
|
|
}
|
|
|
|
|
|
.completion-score {
|
|
|
font-size: 16px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
body {
|
|
|
padding: 10px 0;
|
|
|
}
|
|
|
|
|
|
.container {
|
|
|
padding: 0 8px;
|
|
|
}
|
|
|
|
|
|
.quiz-header {
|
|
|
padding: 15px 12px;
|
|
|
}
|
|
|
|
|
|
.quiz-title {
|
|
|
font-size: 20px;
|
|
|
}
|
|
|
|
|
|
.btn {
|
|
|
padding: 8px 14px;
|
|
|
font-size: 12px;
|
|
|
}
|
|
|
|
|
|
.status-bar {
|
|
|
padding: 10px 15px;
|
|
|
}
|
|
|
|
|
|
.card {
|
|
|
padding: 15px 12px;
|
|
|
}
|
|
|
|
|
|
.question-text {
|
|
|
font-size: 15px;
|
|
|
}
|
|
|
|
|
|
.choice {
|
|
|
padding: 12px 14px;
|
|
|
font-size: 13px;
|
|
|
}
|
|
|
|
|
|
.checkbox-input {
|
|
|
width: 14px;
|
|
|
height: 14px;
|
|
|
}
|
|
|
|
|
|
.completion-title {
|
|
|
font-size: 24px;
|
|
|
}
|
|
|
|
|
|
.completion-score {
|
|
|
font-size: 15px;
|
|
|
}
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
<div class="container">
|
|
|
<div class="quiz-header">
|
|
|
<h1 class="quiz-title">인적자원관리 퀴즈</h1>
|
|
|
<div class="quiz-controls">
|
|
|
<button id="prev" class="btn">← 이전</button>
|
|
|
<button id="next" class="btn">다음 →</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="status-bar">
|
|
|
<div id="status" class="progress-info">문항 1/16</div>
|
|
|
<div class="score-display">점수: <span id="score-text">0</span></div>
|
|
|
</div>
|
|
|
|
|
|
<div id="message" class="message-area"></div>
|
|
|
<div id="quiz"></div>
|
|
|
</div>
|
|
|
<script>
|
|
|
let questions=[], idx=0, score=0, state=new Map(), finished=false;
|
|
|
function getState(i){ if(!state.has(i)) state.set(i,{selected:null, correct:false, revealed:false, scored:false}); return state.get(i); }
|
|
|
async function load(){
|
|
|
|
|
|
console.log('load() 함수가 호출되었습니다');
|
|
|
try{
|
|
|
const res=await fetch('questions.json',{cache:'no-store'});
|
|
|
if(!res.ok) throw new Error('HTTP '+res.status);
|
|
|
questions=await res.json();
|
|
|
}catch(e){
|
|
|
console.error('questions.json 로드 실패:', e);
|
|
|
const msg=document.getElementById('message');
|
|
|
if(msg) msg.textContent='문항 로드 실패: '+ (e && e.message ? e.message : e);
|
|
|
return;
|
|
|
}
|
|
|
idx=0; score=0; state.clear(); finished=false; render();
|
|
|
}
|
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
|
console.log('DOM 로드 완료');
|
|
|
if (typeof questions === 'undefined' || questions.length === 0) {
|
|
|
console.log('questions가 정의되지 않았거나 비어있음, load() 호출');
|
|
|
load();
|
|
|
} else {
|
|
|
console.log('questions 이미 정의됨, render() 호출');
|
|
|
render();
|
|
|
}
|
|
|
});
|
|
|
function normalize(s){return (s||'').toString().replace(/[\s ]+/g,'').toLowerCase();}
|
|
|
function escapeHtml(s){ const div=document.createElement('div'); div.textContent = (s ?? ''); return div.innerHTML; }
|
|
|
function render(){
|
|
|
const quiz=document.getElementById('quiz'); quiz.innerHTML='';
|
|
|
if(finished){
|
|
|
const done=document.createElement('div');
|
|
|
done.className='completion-card';
|
|
|
done.innerHTML = `
|
|
|
<div class="completion-title">퀴즈 완료! 🎉</div>
|
|
|
<div class="completion-score">최종 점수: ${score}/${questions.length} (${Math.round(score/questions.length*100)}%)</div>
|
|
|
<button class="restart-btn" onclick="restartQuiz()">다시 시작하기</button>
|
|
|
`;
|
|
|
quiz.appendChild(done);
|
|
|
|
|
|
const nextBtn=document.getElementById('next');
|
|
|
const prevBtn=document.getElementById('prev');
|
|
|
document.getElementById('status').textContent=`완료`;
|
|
|
document.getElementById('score-text').textContent=`${score}/${questions.length}`;
|
|
|
prevBtn.disabled = true;
|
|
|
nextBtn.textContent = '처음으로';
|
|
|
return;
|
|
|
}
|
|
|
const q=questions[idx]; const st=getState(idx);
|
|
|
|
|
|
const card=document.createElement('div'); card.className='card';
|
|
|
const questionDiv=document.createElement('div');
|
|
|
questionDiv.className='question-text';
|
|
|
questionDiv.textContent=q.prompt;
|
|
|
card.appendChild(questionDiv);
|
|
|
|
|
|
if(q.choices && q.choices.length){
|
|
|
const isMultiple = q.qtype === 'multiple';
|
|
|
|
|
|
q.choices.forEach((c,i)=>{
|
|
|
const wrapper=document.createElement('div');
|
|
|
wrapper.className='choice-wrapper';
|
|
|
|
|
|
if(isMultiple){
|
|
|
|
|
|
const checkbox=document.createElement('input');
|
|
|
checkbox.type='checkbox'; checkbox.id=`choice_${i}`; checkbox.value=c;
|
|
|
checkbox.className='checkbox-input';
|
|
|
|
|
|
const label=document.createElement('label');
|
|
|
label.htmlFor=`choice_${i}`; label.className='choice';
|
|
|
label.textContent=(i+1)+'. '+c;
|
|
|
|
|
|
if(!st.revealed){
|
|
|
checkbox.onchange=()=>selectMultiple(c, checkbox.checked);
|
|
|
if(st.selected && st.selected.includes && st.selected.includes(c)) {
|
|
|
checkbox.checked=true; label.classList.add('selected');
|
|
|
}
|
|
|
}else{
|
|
|
|
|
|
const isCorrect = Array.isArray(q.answer) ? q.answer.includes(c) : normalize(c)===normalize(q.answer);
|
|
|
if(isCorrect) label.classList.add('correct');
|
|
|
if(st.selected && st.selected.includes && st.selected.includes(c) && !isCorrect) label.classList.add('wrong');
|
|
|
checkbox.disabled=true;
|
|
|
}
|
|
|
|
|
|
wrapper.appendChild(checkbox); wrapper.appendChild(label);
|
|
|
}else{
|
|
|
|
|
|
const btn=document.createElement('button'); btn.className='choice'; btn.textContent=(i+1)+'. '+c;
|
|
|
if(!st.revealed){
|
|
|
btn.onclick=()=>select(c);
|
|
|
if(st.selected===c) btn.classList.add('selected');
|
|
|
}else{
|
|
|
|
|
|
const isCorrect = Array.isArray(q.answer) ? q.answer.includes(c) : normalize(c)===normalize(q.answer);
|
|
|
if(isCorrect) btn.classList.add('correct');
|
|
|
if(st.selected===c && !isCorrect) btn.classList.add('wrong');
|
|
|
btn.disabled=true;
|
|
|
}
|
|
|
wrapper.appendChild(btn);
|
|
|
}
|
|
|
|
|
|
card.appendChild(wrapper);
|
|
|
});
|
|
|
}else{
|
|
|
const input=document.createElement('input');
|
|
|
input.placeholder='정답 입력';
|
|
|
input.style='width:100%;padding:15px;border:2px solid #e2e8f0;border-radius:12px;margin-top:15px;font-size:16px;';
|
|
|
input.value = st.selected||'';
|
|
|
const check=document.createElement('button');
|
|
|
check.className='btn';
|
|
|
check.style='margin-top:15px;width:100%;';
|
|
|
check.textContent= st.revealed? '제출됨' : '제출';
|
|
|
if(!st.revealed){
|
|
|
check.onclick=()=>select(input.value.trim());
|
|
|
}else{
|
|
|
check.disabled=true;
|
|
|
}
|
|
|
card.appendChild(input); card.appendChild(check);
|
|
|
}
|
|
|
|
|
|
|
|
|
if(st.revealed){
|
|
|
const resultCard=document.createElement('div');
|
|
|
resultCard.className='result-card';
|
|
|
|
|
|
|
|
|
const resultDiv = document.createElement('div');
|
|
|
resultDiv.className = st.correct ? 'result-status result-correct' : 'result-status result-wrong';
|
|
|
resultDiv.textContent = st.correct ? '정답입니다! ✅' : '틀렸습니다! ❌';
|
|
|
resultCard.appendChild(resultDiv);
|
|
|
|
|
|
|
|
|
let answerText = '';
|
|
|
if(Array.isArray(q.answer)){
|
|
|
|
|
|
const answerNumbers = [];
|
|
|
q.answer.forEach(ans => {
|
|
|
const index = q.choices.findIndex(choice => normalize(choice) === normalize(ans));
|
|
|
if(index !== -1) answerNumbers.push(index + 1);
|
|
|
});
|
|
|
answerText = answerNumbers.join(', ');
|
|
|
}else{
|
|
|
|
|
|
const index = q.choices.findIndex(choice => normalize(choice) === normalize(q.answer));
|
|
|
answerText = index !== -1 ? (index + 1).toString() : '1';
|
|
|
}
|
|
|
|
|
|
const answerDiv = document.createElement('div');
|
|
|
answerDiv.className = 'answer-display';
|
|
|
answerDiv.innerHTML = `<strong>정답</strong>: ${answerText}`;
|
|
|
resultCard.appendChild(answerDiv);
|
|
|
|
|
|
|
|
|
if(q.explanation && q.explanation.toString().trim()){
|
|
|
const explanationDiv = document.createElement('div');
|
|
|
explanationDiv.className = 'explanation';
|
|
|
explanationDiv.innerHTML = `<strong>해설:</strong> ${escapeHtml(q.explanation.toString())}`;
|
|
|
resultCard.appendChild(explanationDiv);
|
|
|
}
|
|
|
|
|
|
card.appendChild(resultCard);
|
|
|
}
|
|
|
|
|
|
const meta=document.createElement('div');
|
|
|
meta.className='meta-info';
|
|
|
meta.textContent='유형: '+q.qtype.toUpperCase();
|
|
|
card.appendChild(meta);
|
|
|
|
|
|
quiz.appendChild(card);
|
|
|
|
|
|
const nextBtn=document.getElementById('next');
|
|
|
const prevBtn=document.getElementById('prev');
|
|
|
document.getElementById('status').textContent=`문항 ${idx+1}/${questions.length}`;
|
|
|
document.getElementById('score-text').textContent=`${score}/${questions.length}`;
|
|
|
prevBtn.disabled = idx===0;
|
|
|
nextBtn.textContent = st.revealed ? (idx===questions.length-1 ? '완료' : '다음 →') : '다음 →';
|
|
|
}
|
|
|
function selectMultiple(val, checked){
|
|
|
const q=questions[idx]; const st=getState(idx);
|
|
|
if(st.revealed) return;
|
|
|
|
|
|
if(!st.selected) st.selected = [];
|
|
|
if(!Array.isArray(st.selected)) st.selected = [];
|
|
|
|
|
|
if(checked){
|
|
|
if(!st.selected.includes(val)) st.selected.push(val);
|
|
|
}else{
|
|
|
st.selected = st.selected.filter(item => item !== val);
|
|
|
}
|
|
|
|
|
|
document.getElementById('message').textContent='';
|
|
|
render();
|
|
|
}
|
|
|
function select(val){
|
|
|
const q=questions[idx]; const st=getState(idx);
|
|
|
if(st.revealed) return;
|
|
|
st.selected = val;
|
|
|
st.correct = normalize(val)===normalize(q.answer);
|
|
|
document.getElementById('message').textContent='';
|
|
|
render();
|
|
|
}
|
|
|
function restartQuiz(){
|
|
|
idx=0; score=0; state.clear(); finished=false;
|
|
|
document.getElementById('message').textContent='';
|
|
|
render();
|
|
|
}
|
|
|
document.getElementById('prev').onclick=()=>{ if(finished) return; if(idx>0){ idx--; render(); }};
|
|
|
document.getElementById('next').onclick=()=>{
|
|
|
if(finished){ restartQuiz(); return; }
|
|
|
const st=getState(idx);
|
|
|
const q=questions[idx];
|
|
|
const msg=document.getElementById('message');
|
|
|
|
|
|
if(!st.revealed){
|
|
|
if(st.selected==null || (Array.isArray(st.selected) && st.selected.length===0)){
|
|
|
msg.textContent='먼저 답을 선택하세요.'; return;
|
|
|
}
|
|
|
|
|
|
|
|
|
st.revealed=true;
|
|
|
|
|
|
|
|
|
let isCorrect = false;
|
|
|
if(q.qtype === 'multiple'){
|
|
|
|
|
|
if(Array.isArray(q.answer) && Array.isArray(st.selected)){
|
|
|
const sortedAnswer = [...q.answer].sort();
|
|
|
const sortedSelected = [...st.selected].sort();
|
|
|
isCorrect = sortedAnswer.length === sortedSelected.length &&
|
|
|
sortedAnswer.every((ans, i) => normalize(ans) === normalize(sortedSelected[i]));
|
|
|
}
|
|
|
}else{
|
|
|
|
|
|
isCorrect = Array.isArray(q.answer) ?
|
|
|
q.answer.some(ans => normalize(st.selected) === normalize(ans)) :
|
|
|
normalize(st.selected) === normalize(q.answer);
|
|
|
}
|
|
|
|
|
|
st.correct = isCorrect;
|
|
|
if(st.correct && !st.scored){ score++; st.scored=true; }
|
|
|
render();
|
|
|
}else{
|
|
|
if(idx<questions.length-1){ idx++; render(); }
|
|
|
else { finished=true; render(); }
|
|
|
}
|
|
|
};
|
|
|
load();
|
|
|
</script>
|
|
|
</body></html> |