){ const flatAnswers = []; q.verbs.forEach(v=> v.forms.forEach((f,pi)=> { flatAnswers[v===q.verbs[0]?pi:flatAnswers.length]=null; })); q.verbs.forEach((v, vi)=>{ v.forms.forEach((form, pi)=>{ const i = vi*q.pronouns.length + pi; total++; const inp = document.querySelector(`input.blank[data-q="${key}"][data-i="${i}"]`); const ok = checkAnswer(inp.value, [form]); inp.classList.remove('correct','incorrect'); inp.classList.add(ok?'correct':'incorrect'); if(!ok) inp.title = 'Правильно: ' + form; else inp.title = ''; if(ok) correct++; }); }); } else if(q.type==='task'){ // tasks are self-assessed via checkbox, not part of auto score } }); st.score = {correct, total}; saveState(); updateScoreDisplay(st.score); renderNav(); renderOverview(); } function updateScoreDisplay(score){ const el = document.getElementById('score-display'); if(!el) return; if(score.total===0){ el.innerHTML = `— в этом тесте нет заданий с проверяемым ответом`; el.className = 'score-display'; return; } const pct = Math.round(score.correct/score.total*100); el.className = 'score-display ' + (pct>=70 ? 'pass':'fail'); el.innerHTML = `${pct}% ${score.correct} из ${score.total} правильно · ${pct>=70?'зачёт':'нужно повторить тему'}`; } function resetTest(t){ state[t.id] = {answers:{}, taskDone:{}, score:null, attempted:false}; saveState(); render(); } /* ========================================================= MAIN RENDER ========================================================= */ function render(){ renderNav(); renderOverview(); if(currentId === 'final'){ renderFinal(); } else { const t = TESTS.find(x=>x.id===currentId); renderTest(t); } } (async function init(){ await loadState(); render(); })(); mar