170 lines
5.6 KiB
JavaScript
170 lines
5.6 KiB
JavaScript
let currentCard = null;
|
|
let attempts = 0;
|
|
let stats = { points: 0, total: 0 };
|
|
|
|
document.addEventListener('DOMContentLoaded', loadLessons);
|
|
|
|
function loadLessons() {
|
|
fetch('/api/lessons')
|
|
.then(res => res.json())
|
|
.then(lessons => {
|
|
const list = document.getElementById('lesson-list');
|
|
list.innerHTML = '';
|
|
lessons.forEach(l => {
|
|
const div = document.createElement('div');
|
|
div.className = 'lesson-item';
|
|
div.innerHTML = `
|
|
<input type="checkbox" id="l-${l}" value="${l}" onchange="updateStartBtn()">
|
|
<label for="l-${l}">${l}</label>
|
|
`;
|
|
list.appendChild(div);
|
|
});
|
|
});
|
|
}
|
|
|
|
function updateStartBtn() {
|
|
const checked = document.querySelectorAll('#lesson-list input:checked');
|
|
document.getElementById('btn-start').disabled = (checked.length === 0);
|
|
}
|
|
|
|
function startQuiz() {
|
|
stats = { points: 0, total: 0 };
|
|
updateStats();
|
|
document.getElementById('setup-screen').style.display = 'none';
|
|
document.getElementById('quiz-screen').style.display = 'flex';
|
|
nextQuestion();
|
|
}
|
|
|
|
function stopQuiz() {
|
|
document.getElementById('quiz-screen').style.display = 'none';
|
|
document.getElementById('setup-screen').style.display = 'block';
|
|
}
|
|
|
|
function nextQuestion() {
|
|
const btn = document.getElementById('btn-action');
|
|
btn.innerText = "Prüfen";
|
|
btn.onclick = checkAnswer;
|
|
btn.className = "action-btn primary";
|
|
document.getElementById('feedback').innerText = '';
|
|
|
|
const lids = Array.from(document.querySelectorAll('#lesson-list input:checked')).map(cb => cb.value);
|
|
const mid = document.getElementById('opt-middle').checked;
|
|
|
|
fetch('/api/question', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({ lessons: lids, askMiddle: mid })
|
|
})
|
|
.then(res => res.json())
|
|
.then(card => {
|
|
if(card.error) { alert(card.error); stopQuiz(); return; }
|
|
currentCard = card;
|
|
attempts = 0;
|
|
renderCard(card);
|
|
});
|
|
}
|
|
|
|
function renderCard(card) {
|
|
document.getElementById('latin-text').innerText = card.latin;
|
|
document.getElementById('hint-text').innerText = card.hint;
|
|
|
|
const container = document.getElementById('inputs-container');
|
|
container.innerHTML = '';
|
|
|
|
if (card.middle_req) {
|
|
const row = document.createElement('div');
|
|
row.className = 'input-row';
|
|
row.innerHTML = `
|
|
<span class="lbl">Form:</span>
|
|
<input type="text" class="quiz-input" data-type="middle" data-correct="${card.middle_correct}" placeholder="z.B. f, Gen">
|
|
`;
|
|
container.appendChild(row);
|
|
}
|
|
|
|
card.german_correct.forEach(ans => {
|
|
const row = document.createElement('div');
|
|
row.className = 'input-row';
|
|
row.innerHTML = `
|
|
<span class="lbl">Dt:</span>
|
|
<input type="text" class="quiz-input" data-type="german" data-correct="${ans}" placeholder="Bedeutung">
|
|
`;
|
|
container.appendChild(row);
|
|
});
|
|
const first = container.querySelector('input');
|
|
if(first) first.focus();
|
|
}
|
|
|
|
function checkAnswer() {
|
|
const inputs = document.querySelectorAll('.quiz-input');
|
|
const payload = [];
|
|
inputs.forEach(i => {
|
|
payload.push({
|
|
value: i.value,
|
|
correct: i.dataset.correct,
|
|
type: i.dataset.type || 'german'
|
|
});
|
|
});
|
|
attempts++;
|
|
|
|
fetch('/api/check', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({ inputs: payload, attempt: attempts })
|
|
})
|
|
.then(res => res.json())
|
|
.then(res => {
|
|
const fb = document.getElementById('feedback');
|
|
let globalMsg = "";
|
|
|
|
res.results.forEach((r, idx) => {
|
|
const el = inputs[idx];
|
|
el.classList.remove('wrong', 'correct', 'typo', 'incomplete');
|
|
if (r.status === 'correct') { el.classList.add('correct'); }
|
|
else if (r.status === 'typo') { el.classList.add('typo'); }
|
|
else if (r.status === 'incomplete') { el.classList.add('incomplete'); globalMsg = r.msg; }
|
|
else { el.classList.add('wrong'); }
|
|
});
|
|
|
|
if (res.all_correct) {
|
|
fb.innerText = "Alles richtig!";
|
|
fb.style.color = "green";
|
|
stats.points += res.score;
|
|
finishTurn();
|
|
} else {
|
|
if (res.has_incomplete) {
|
|
fb.innerText = globalMsg || "Unvollständig.";
|
|
fb.style.color = "#d39e00";
|
|
} else {
|
|
if (attempts >= 3) {
|
|
fb.innerText = "Leider nicht geschafft. Lösungen eingesetzt.";
|
|
fb.style.color = "red";
|
|
inputs.forEach(i => i.value = i.dataset.correct);
|
|
finishTurn();
|
|
} else {
|
|
fb.innerText = `Fehler. Versuch ${attempts}/3`;
|
|
fb.style.color = "orange";
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function finishTurn() {
|
|
stats.total++;
|
|
updateStats();
|
|
const btn = document.getElementById('btn-action');
|
|
btn.innerText = "Weiter";
|
|
btn.onclick = nextQuestion;
|
|
btn.focus();
|
|
}
|
|
|
|
function updateStats() {
|
|
let p = 0;
|
|
if (stats.total > 0) p = Math.round((stats.points / stats.total) * 100);
|
|
document.getElementById('progress-bar').style.width = `${p}%`;
|
|
document.getElementById('stats-text').innerText = `${p}% (${stats.points.toFixed(1)}/${stats.total})`;
|
|
}
|
|
|
|
document.addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter') document.getElementById('btn-action').click();
|
|
}); |