'use strict'; /* ────────────────────────────────────────────────────────────────── Variants view — port of the old /exam9 browser onto API + DB. Same UX as before: pick a variant from a grid overlay, then read conditions + reveal solutions. Progress (which variants have all solutions opened) is per-user via /api/exam-prep/attempts. ────────────────────────────────────────────────────────────────── */ (async function () { await EP.boot(); const examKey = EP.examKey; // Optional ?v=N in URL: open that variant initially const initialVariantFromQuery = (() => { const m = location.search.match(/[?&]v=(\d+)/); return m ? Number(m[1]) : null; })(); let variants = []; // [{ n, label, total, solved, viewed_sol }] let currentN = null; let currentTasks = null; // cache: { [variantN]: tasks[] } const tasksCache = new Map(); /* ── Load variants list ─────────────────────────────────────── */ try { const r = await EP.api.listVariants(examKey); variants = r.variants || []; } catch (e) { showError(`Не удалось загрузить варианты: ${e.message || e}`); return; } if (!variants.length) { showError('Варианты не найдены'); return; } /* ── DOM refs ───────────────────────────────────────────────── */ const main = document.getElementById('ep-main'); const pickerBtn = document.getElementById('vp-btn'); const pickerLabel = document.getElementById('vp-label'); const pickerOver = document.getElementById('vp-overlay'); const pickerGrid = document.getElementById('vp-grid'); /* ── Picker overlay ─────────────────────────────────────────── */ function buildGrid() { pickerGrid.innerHTML = variants.map(v => { let cls = ''; if (v.total > 0 && v.viewed_sol === v.total) cls = ' done'; else if (v.viewed_sol > 0) cls = ' partial'; const active = v.n === currentN ? ' active' : ''; const title = v.viewed_sol === v.total ? `${v.label} (все решения открыты)` : `${v.label} (${v.viewed_sol}/${v.total} решений открыто)`; return ``; }).join(''); pickerGrid.querySelectorAll('button[data-n]').forEach(b => { b.onclick = () => { selectVariant(Number(b.dataset.n)); closePicker(); }; }); } function openPicker() { buildGrid(); pickerOver.classList.add('visible'); pickerBtn.classList.add('open'); document.addEventListener('keydown', onEsc); } function closePicker() { pickerOver.classList.remove('visible'); pickerBtn.classList.remove('open'); document.removeEventListener('keydown', onEsc); } function onEsc(e) { if (e.key === 'Escape') closePicker(); } function onOverlayClick(e) { if (e.target === pickerOver) closePicker(); } pickerBtn.onclick = () => { if (pickerOver.classList.contains('visible')) closePicker(); else openPicker(); }; pickerOver.onclick = onOverlayClick; document.getElementById('vp-close').onclick = closePicker; /* ── Variant rendering ──────────────────────────────────────── */ async function selectVariant(n) { currentN = n; pickerLabel.textContent = `Вариант ${n}`; try { localStorage.setItem(`exam_prep_${examKey}_last_variant`, String(n)); } catch {} if (!tasksCache.has(n)) { main.innerHTML = `