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 => `