const password = sessionStorage.getItem("teacherPassword") || ""; const $ = id => document.getElementById(id); if (!password) window.location.replace("index.html"); function formatDate(value) { if (!value) return "Нет данных"; const normalized = String(value).replace(/T(\d{2})-(\d{2})-(\d{2})$/, "T$1:$2:$3"); const date = new Date(normalized); return Number.isNaN(date.getTime()) ? value : date.toLocaleString("ru-RU"); } function formatRemaining(attempt) { const seconds = Math.max(0, attempt.remaining_seconds || 0); return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, "0")}`; } function escapeHtml(value) { return String(value ?? "").replace(/[&<>"']/g, char => ({"&":"&","<":"<",">":">",'"':""","'":"'"}[char])); } async function loadMonitor() { try { const [activeResponse, completedResponse, configResponse] = await Promise.all([ fetch(`/teacher/active_attempts?password=${encodeURIComponent(password)}`), fetch(`/teacher/results?password=${encodeURIComponent(password)}`), fetch(`/get_config?password=${encodeURIComponent(password)}`) ]); if (!activeResponse.ok || !completedResponse.ok || !configResponse.ok) { sessionStorage.removeItem("teacherPassword"); window.location.replace("index.html"); return; } const active = await activeResponse.json(); const completed = await completedResponse.json(); const config = await configResponse.json(); if (config.error) { sessionStorage.removeItem("teacherPassword"); window.location.replace("index.html"); return; } const gradeThresholds = config.grade_thresholds || {"3": 52, "4": 68, "5": 84}; $("active-count").textContent = active.length; $("updated").textContent = `Обновлено: ${new Date().toLocaleTimeString("ru-RU")}`; $("active-rows").innerHTML = active.length ? active.map(attempt => `${escapeHtml(attempt.student)}${formatDate(attempt.start_time)}${attempt.answered} из ${attempt.total}${attempt.correct}${attempt.incorrect}${formatRemaining(attempt)}на связи`).join("") : 'Сейчас никто не проходит тест.'; $("completed-rows").innerHTML = completed.length ? completed.map(result => { const grade = getGrade(result.correct_percent, gradeThresholds); return `${escapeHtml(result.student)}${result.correct_percent}%${grade}${formatDate(result.end_time)}`; }).join("") : 'Завершённых тестов пока нет.'; } catch (error) { $("updated").textContent = "Не удалось обновить монитор"; } } loadMonitor(); setInterval(loadMonitor, 5000); function getGrade(percent, thresholds) { const score = Number(percent) || 0; if (score >= Number(thresholds["5"])) return 5; if (score >= Number(thresholds["4"])) return 4; if (score >= Number(thresholds["3"])) return 3; return 2; }