edu-senex/edu/js/quiz.js

109 Zeilen
5,7 KiB
JavaScript

'use strict';
var Quiz = {
state: null,
render: function(params) {
var el = document.getElementById('content');
if (params[0] === 'play') { this.play(el, params[1] || ''); return; }
el.textContent = 'Lade...';
var self = this;
Promise.all([API.get('/decks'), API.get('/quiz/history')]).then(function(results) {
self.renderStart(el, results[0].decks, results[1].results);
}).catch(function(e) { el.textContent = e.message; });
},
renderStart: function(el, decks, history) {
var h = '<div class="page-header"><h1>Quiz</h1><p>Teste dein Wissen mit Multiple-Choice-Fragen</p></div>';
h += '<h3 style="margin-bottom:12px;">Deck waehlen</h3><div class="deck-grid">';
h += '<div class="deck-card" data-slug="all" style="border-color:var(--accent)"><div class="deck-name">Alle Decks</div><div class="deck-info">Querbeet aus allen Themen</div></div>';
decks.forEach(function(d) {
h += '<div class="deck-card" data-slug="' + d.slug + '"><div class="deck-name">' + Markdown.esc(d.name) + '</div><div class="deck-info">' + d.card_count + ' Karten</div></div>';
});
h += '</div>';
if (history.length > 0) {
h += '<h3 style="margin:24px 0 12px;">Letzte Ergebnisse</h3><table class="user-table"><thead><tr><th>Datum</th><th>Deck</th><th>Score</th><th>Richtig</th></tr></thead><tbody>';
history.forEach(function(r) {
h += '<tr><td>' + new Date(r.created_at).toLocaleDateString('de-DE') + '</td><td>' + (r.deck_slug || 'Alle') + '</td><td><strong>' + r.score_percent + '%</strong></td><td>' + r.correct_answers + '/' + r.total_questions + '</td></tr>';
});
h += '</tbody></table>';
}
el.innerHTML = h;
el.querySelectorAll('.deck-card').forEach(function(card) {
card.addEventListener('click', function() { location.hash = '#/quiz/play/' + card.dataset.slug; });
});
},
play: function(el, deck) {
el.textContent = 'Generiere Quiz...';
var self = this;
var slug = deck === 'all' ? '' : deck;
API.get('/quiz/generate?deck=' + slug + '&count=10').then(function(data) {
self.state = { questions: data.questions, index: 0, correct: 0, selected: -1, answered: false, deck: deck };
self.renderQuestion(el);
}).catch(function(e) { el.textContent = e.message; });
},
renderQuestion: function(el) {
var s = this.state;
if (s.index >= s.questions.length) { this.renderResult(el); return; }
var q = s.questions[s.index];
var h = '<a href="#/quiz" class="back-link">&larr; Abbrechen</a>';
h += '<div class="study-header"><span class="study-deck-name">' + Markdown.esc(q.deck_name || 'Quiz') + '</span>';
h += '<span class="study-counter">Frage ' + (s.index + 1) + ' / ' + s.questions.length + '</span></div>';
h += '<div class="progress-bar" style="margin-bottom:24px;"><div class="fill fill-accent" style="width:' + ((s.index / s.questions.length) * 100) + '%"></div></div>';
h += '<div class="flashcard"><div class="card-question">' + Markdown.render(q.question) + '</div><div style="margin-top:16px;">';
q.options.forEach(function(opt, i) {
var cls = 'quiz-option';
if (s.answered) {
if (i === q.correct_index) cls += ' correct';
else if (i === s.selected) cls += ' wrong';
} else if (i === s.selected) cls += ' selected';
h += '<button class="' + cls + '" data-idx="' + i + '"' + (s.answered ? ' disabled' : '') + '>' + Markdown.esc(opt) + '</button>';
});
h += '</div>';
if (s.answered) {
h += '<div class="card-answer" style="margin-top:16px;"><div class="card-answer-label">Erklaerung</div>' + Markdown.render(q.full_answer) + '</div>';
h += '<div style="text-align:center;margin-top:16px;"><button class="btn btn-primary" id="quiz-next">Weiter</button></div>';
}
h += '</div>';
el.innerHTML = h;
var self = this;
if (!s.answered) {
el.querySelectorAll('.quiz-option').forEach(function(btn) {
btn.addEventListener('click', function() { self.selectOption(parseInt(btn.dataset.idx)); });
});
} else {
document.getElementById('quiz-next').addEventListener('click', function() { self.next(); });
}
},
selectOption: function(index) {
var s = this.state;
if (s.answered) return;
s.selected = index;
if (index === s.questions[s.index].correct_index) s.correct++;
s.answered = true;
this.renderQuestion(document.getElementById('content'));
},
next: function() {
this.state.index++;
this.state.selected = -1;
this.state.answered = false;
this.renderQuestion(document.getElementById('content'));
},
renderResult: function(el) {
var s = this.state;
var total = s.questions.length;
var pct = Math.round((s.correct / total) * 100);
API.post('/quiz/submit', { deck: s.deck, total: total, correct: s.correct }).catch(function() {});
var color = pct >= 70 ? 'var(--green)' : pct >= 40 ? 'var(--orange)' : 'var(--red)';
var h = '<div style="text-align:center;padding:48px 0;"><h2>Quiz abgeschlossen!</h2><br>';
h += '<p style="font-size:48px;font-weight:bold;color:' + color + '">' + pct + '%</p>';
h += '<p style="color:var(--text-secondary);font-size:18px;">' + s.correct + ' von ' + total + ' richtig</p><br>';
h += '<a href="#/quiz" class="btn btn-primary">Neues Quiz</a></div>';
el.innerHTML = h;
}
};