Памятка для разработчика админки 2035. Сервис не рисует карту — только отдаёт готовую матрицу. UI, цвета, PNG/PDF — на стороне админки.
LMS backend ──POST /api/lms/session-ip-events──► anomaly-service (логины / IP) LMS frontend ──sdk.js → /api/sdk/*──────────────► anomaly-service (activeTime, задания, ИИ) Админка LMS ◄──GET /api/admin/heatmap─────────── anomaly-service (сетка для отрисовки)
Источники: backend LMS,
frontend SDK.
Markdown: docs/lms-admin-heatmap.md.
Authorization: Bearer <ADMIN_API_KEY>
Ключ выдаёт команда anomaly-service (ADMIN_API_KEY).
Не путать с LMS_TO_ANOMALY_API_KEY и SDK_API_KEY.
GET https://<anomaly-host>/api/admin/heatmap
| Параметр | Обязательный | Описание |
|---|---|---|
metric |
нет | Показатель. По умолчанию activeTime |
granularity |
нет | Ось X. По умолчанию day |
from / to |
нет | YYYY-MM-DD. Без них — последние 30 дней |
courseId / groupId / moduleId |
нет | Фильтры. Справочники курсов/групп — из LMS |
from/to API режет окно до 30 дней.
Для «весь курс / всё демо» передавайте явный диапазон.
metric| Значение | Что в ячейке | Источник |
|---|---|---|
logins |
число входов | session_started |
activeTime |
секунды активной работы | ActivitySummary.activeSeconds |
completedAssignments |
число сдач заданий | assignment_submitted |
aiAssistantRequests |
число обращений к ИИ | ai_assistant_request |
granularity| Значение | Колонки |
|---|---|
day |
один день = одна колонка |
week |
неделя (пн–вс, UTC), ключ = дата понедельника |
month |
месяц, ключ = YYYY-MM-01 |
module |
сейчас как day; фильтр модуля — через moduleId |
{
"metric": "activeTime",
"granularity": "day",
"from": "2026-07-01",
"to": "2026-07-31",
"columns": [
{ "key": "2026-07-01", "label": "01.07" },
{ "key": "2026-07-02", "label": "02.07" }
],
"rows": [
{
"studentId": "12345",
"studentName": "Иванов Иван",
"groupId": "group-001",
"groupTitle": "Поток 1",
"values": { "2026-07-01": 3600, "2026-07-02": 1200 },
"buckets": { "2026-07-01": 5, "2026-07-02": 2 }
}
],
"legend": { "min": 0, "max": 3600, "buckets": 5 }
}
| Элемент UI | Поле ответа |
|---|---|
| Заголовки колонок (ось X) | columns[].label |
| Ключ ячейки | columns[].key |
| Строки (ученики) | rows[] |
| Подпись строки | studentName (fallback: studentId) |
| Число / tooltip | rows[].values[column.key] → иначе 0 |
| Интенсивность цвета | buckets[key] (0..5) или value / legend.max |
for (const row of data.rows) {
for (const col of data.columns) {
const value = row.values[col.key] ?? 0;
const bucket = row.buckets[col.key] ?? 0; // 0..5
// cell background = palette[bucket]
// cell text / title = value
}
}
legend.max (как на /heatmap.html).
UI: курс · группа · модуль · период · гранулярность · метрика. Сетка: строки = ученики, колонки = периоды, ячейки = value + цвет.
GET /api/admin/heatmap?metric=activeTime&granularity=day&from=2026-07-01&to=2026-07-31&courseId=python-basic-2026&groupId=group-001 Authorization: Bearer <ADMIN_API_KEY>
Картинку делайте во фронте админки (html-to-image / html2canvas + jsPDF). Backend отдаёт только JSON.
GET /api/admin/exports/heatmap.json Authorization: Bearer <ADMIN_API_KEY>
Для экспорта «как на экране» лучше снова вызвать
GET /api/admin/heatmap с теми же query и снять DOM.
from/to (иначе только последние 30 дней)courseId / groupId совпадают с теми, что в событияхheatmap или
all, затем период июль 2026