diff --git a/docs/API.md b/docs/API.md index 42cf3bd..ba50e7a 100644 --- a/docs/API.md +++ b/docs/API.md @@ -894,7 +894,7 @@ API возвращает `409 Conflict`; соседние интервалы и | Метод | URL | Назначение | |-------|-----|------------| -| `GET` | `/api/edu-office/schedule/quality?semesterId=&versionId=` | Итоговая оценка, метрики и объяснимый список проблем выбранной версии | +| `GET` | `/api/edu-office/schedule/quality?semesterId=&versionId=` | Итоговая оценка, метрики и объяснимый список проблемных правил выбранной версии | | `GET` | `/api/edu-office/schedule/quality/recommendations?semesterId=&versionId=&scheduleRuleSlotId=&lessonDate=` | Проверенные локальные варианты улучшения опубликованного занятия | Доступ имеют только `ADMIN` и `EDUCATION_OFFICE`. `versionId` необязателен: без него @@ -921,7 +921,7 @@ override текущей публикации. Для них доступны о "score": 84, "rawPenalty": 17, "lessonCount": 36, - "totalProblemCount": 5, + "totalProblemCount": 1, "problemsTruncated": false, "metrics": [ { @@ -935,11 +935,16 @@ override текущей публикации. Для них доступны о ], "problems": [ { - "id": "GROUP_GAP:2026-09-14:31:18", + "id": "RULE:24", "type": "GROUP_GAP", "severity": "MEDIUM", - "title": "Окно в расписании группы", - "penalty": 2, + "title": "Правило «Архитектура систем» снижает качество", + "description": "3 занятия этого правила снижают оценку: Окно в расписании группы; Избыточно крупная аудитория", + "penalty": 8, + "scheduleRuleId": 24, + "affectedLessonCount": 3, + "problemTypes": ["GROUP_GAP", "ROOM_OVERSIZED"], + "issueLabels": ["Окно в расписании группы", "Избыточно крупная аудитория"], "scheduleRuleSlotId": 31, "lessonDate": "2026-09-14", "optimizable": true @@ -949,8 +954,11 @@ override текущей публикации. Для них доступны о ``` `score` находится в диапазоне от 0 до 100 и нормализует сумму объяснимых штрафов -относительно числа занятий. Поле `totalProblemCount` содержит полный размер результата, -а массив `problems` ограничен 300 элементами; `problemsTruncated` сообщает об усечении. +относительно числа занятий. Нарушения сначала рассчитываются для каждого фактического +занятия, затем объединяются по `scheduleRuleId`: `penalty` хранит сумму всех штрафов правила, +`affectedLessonCount` — число затронутых занятий, `problemTypes` и `issueLabels` — все его +категории и объяснения. Поле `totalProblemCount` содержит число проблемных правил, а массив +`problems` ограничен 300 элементами; `problemsTruncated` сообщает об усечении. Рекомендации подбирают другой эффективный временной слот того же учебного дня либо подходящую активную аудиторию. Занятия, уже закреплённые ручным override, исключаются. diff --git a/docs/BUSINESS_LOGIC.md b/docs/BUSINESS_LOGIC.md index f3564b3..7efdc65 100644 --- a/docs/BUSINESS_LOGIC.md +++ b/docs/BUSINESS_LOGIC.md @@ -435,9 +435,11 @@ constraint. При чтении API разворачивает периоды о Неравномерность дневной нагрузки выводится отдельной диагностической метрикой в процентах и не добавляет скрытого штрафа к итоговой оценке. -В ответе сохраняются исходный штраф, вклад каждого критерия и конкретные проблемы с -датой, занятием и затронутой сущностью. Это делает оценку воспроизводимой и позволяет -фильтровать проблемы по типу и серьёзности. +Внутренне штраф рассчитывается для каждого фактического занятия, поэтому повторяющиеся +пары одного правила увеличивают его вклад в оценку. Перед выдачей нарушения объединяются +по правилу: одна карточка содержит суммарный штраф, число затронутых занятий, все типы и +краткие причины. Это сохраняет воспроизводимость оценки, но направляет пользователя к +изменению базового правила вместо ручного исправления каждой пары. Для проблемы опубликованной версии помощник перебирает другие слоты эффективной сетки того же дня и активные аудитории достаточной вместимости. Каждый вариант повторно проходит @@ -445,9 +447,10 @@ constraint. При чтении API разворачивает периоды о показывает улучшения и компромиссы. Занятия с ручным override считаются закреплёнными и не получают рекомендаций. Применение возможно только после подтверждения пользователя через обычный механизм `schedule_overrides`; автоматической публикации и полного solver в MVP -нет. Для черновика доступны те же оценка, метрики и объяснимые проблемы, но рекомендации -не создаются: пользователь исправляет правила в изолированном конструкторе и повторяет -проверку до публикации. Архив анализируется только для чтения. +нет. Интерфейс анализа для опубликованной версии и черновика открывает выбранное правило +в конструкторе соответствующей версии; черновик остаётся изолированным до публикации. +Архив анализируется только для чтения. API локальных рекомендаций сохраняется для +совместимости и точечных сценариев, но реестр качества работает на уровне правил. ## Привязка преподаватель ↔ дисциплина diff --git a/docs/FRONTEND.md b/docs/FRONTEND.md index ebec528..9b62dc2 100644 --- a/docs/FRONTEND.md +++ b/docs/FRONTEND.md @@ -76,7 +76,7 @@ frontend/ │ │ ├── schedule-view.js # Просмотр расписаний и запуск разовой правки из карточки │ │ ├── schedule-override-panel.js # Боковая панель и реестр разовых изменений │ │ ├── teacher-absences.js # Отсутствия, согласование пожеланий и заявок на изменение -│ │ ├── schedule-quality.js # Оценка, фильтры и локальные рекомендации +│ │ ├── schedule-quality.js # Оценка, фильтры и переход к редактированию правил │ │ ├── schedule-versions.js # Черновики, публикация, восстановление, diff и аудит │ │ ├── schedule.js # Конструктор правил и подсказки пожеланий преподавателей │ │ ├── academic-calendar-grid.js # Расчёт ISO-недели дневной сетки @@ -182,7 +182,7 @@ frontend/ | `teacher-absences` | Запросы преподавателей: отсутствия и мастер замены, согласование семестровых пожеланий, заявки на перенос, аудиторию или отмену | `/api/teacher-absences`, `/api/teacher-preferences`, `/api/teacher-change-requests`, `/api/users/teachers` | | `schedule` | Конструктор правил: по умолчанию редактирует опубликованное расписание, позволяет переключиться на черновик или создать его из выбранной версии; содержит подсказки пожеланий и визуальную матрицу групп | `/api/admin/schedule-rules`, `/api/edu-office/schedule/versions`, `/api/teacher-preferences`, `/api/admin/time-slots`, `/api/admin/calendar/years`, `/api/lesson-types`, `/api/subgroups` | | `schedule-versions` | Контур публикации: текущая версия, черновики, diff, архив, восстановление и журнал | `/api/edu-office/schedule/versions` | -| `schedule-quality` | Диагностика выбранной версии семестра: оценка, метрики, фильтруемые проблемы; для публикации — подтверждаемое локальное улучшение | `/api/edu-office/schedule/quality`, `/api/edu-office/schedule/quality/recommendations`, `/api/edu-office/schedule/overrides` | +| `schedule-quality` | Диагностика выбранной версии семестра: оценка, метрики и проблемные правила с переходом к их редактированию | `/api/edu-office/schedule/quality`, `/api/admin/schedule-rules` | | `academic-calendar` | Учебные годы, семестры, создание календарных графиков, Excel-подобный редактор дневной сетки и привязка дисциплин к семестрам графика | `/api/admin/calendar`, `/api/admin/academic-calendars`, `/api/admin/academic-calendars/{id}/subjects`, `/api/admin/calendar/activity-types`, `/api/specialties`, `/api/specialties/{id}/profiles`, `/api/education-forms`, `/api/subjects` | | `auditorium-workload` | Динамическая загруженность аудиторий, преподавателей и кафедр: сводная матрица по дате или совмещённая таблица выбранной сущности по чётной/нечётной неделе | `/api/classrooms`, `/api/users/teachers`, `/api/departments`, `/api/admin/time-slots`, `/api/equipments`, `/api/groups`, `/api/schedule`, `/api/admin/calendar/years` | @@ -208,14 +208,13 @@ frontend/ действий. Каждая карточка показывает исходное и запрошенное состояние, результат предварительной проверки и хронологию решения. - Вкладка `schedule-quality` доступна администратору и учебному отделу. После выбора - семестра и версии она выводит круговую оценку от 0 до 100, карточки метрик и реестр проблем с - фильтрами по серьёзности и типу. Для проблемы, связанной с конкретным незакреплённым - занятием опубликованной версии, кнопка `Подобрать улучшение` запрашивает проверенные варианты времени и - аудитории. Карточка кандидата показывает изменение оценки, улучшения и компромиссы; - override создаётся только после явного подтверждения, затем анализ запускается заново. - Для `DRAFT` экран рассчитывает те же метрики и проблемы напрямую по правилам черновика, - но направляет пользователя в конструктор и не создаёт override. `ARCHIVED` анализируется - только для чтения. Экран не предлагает автоматически менять занятия, уже отредактированные вручную. + семестра и версии она выводит круговую оценку от 0 до 100, карточки метрик и реестр правил + с фильтрами по серьёзности и типу. Все проблемные занятия одного правила показаны одной + карточкой; в ней выводятся число затронутых занятий, категории и суммарный штраф. Кнопка + `Изменить правило` открывает выбранную версию в конструкторе и сразу заполняет форму этим + правилом. Сценарий одинаков для `PUBLISHED` и `DRAFT`; `ARCHIVED` анализируется только для + чтения. Переход между вкладками передаёт ID версии и правила через одноразовые ключи + `magistr.schedule.openVersionId` и `magistr.schedule.openRuleId` в `localStorage`. - Вкладка `schedule-versions` доступна администратору и учебному отделу и оформлена как отдельный контур публикации. Верхняя карточка показывает версию, которую видят конечные пользователи; ниже расположены черновики, сравнение правил и занятий, архив и журнал. diff --git a/frontend/admin/css/schedule-quality.css b/frontend/admin/css/schedule-quality.css index 1cdf65f..8821c68 100644 --- a/frontend/admin/css/schedule-quality.css +++ b/frontend/admin/css/schedule-quality.css @@ -503,6 +503,38 @@ font-size: 0.7rem; } +.quality-rule-issues, +.quality-rule-detail-list { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; +} + +.quality-rule-issues > span, +.quality-rule-detail-list > span { + padding: 0.22rem 0.45rem; + color: var(--text-secondary); + background: color-mix(in srgb, var(--quality-amber) 9%, transparent); + border: 1px solid color-mix(in srgb, var(--quality-amber) 24%, var(--bg-card-border)); + border-radius: 999px; + font-size: 0.66rem; + line-height: 1.2; +} + +.quality-rule-detail-list { + display: grid; + margin: 1rem 0; +} + +.quality-rule-detail-list > span { + border-radius: var(--radius-sm); + font-size: 0.76rem; +} + +.quality-edit-rule { + width: 100%; +} + .quality-penalty { color: var(--quality-red); font-family: Georgia, 'Times New Roman', serif; diff --git a/frontend/admin/js/views/schedule-quality.js b/frontend/admin/js/views/schedule-quality.js index 4314eb0..56605a9 100644 --- a/frontend/admin/js/views/schedule-quality.js +++ b/frontend/admin/js/views/schedule-quality.js @@ -186,7 +186,7 @@ function renderProblems() { `).join('')} Правило #${escapeHtml(String(problem.scheduleRuleId || '—'))} - · ${escapeHtml(String(affectedLessonCount))} ${escapeHtml(lessonWord(affectedLessonCount))} снижают оценку + · затронуто ${escapeHtml(String(affectedLessonCount))} ${escapeHtml(lessonWord(affectedLessonCount))} · суммарный штраф @@ -238,7 +238,7 @@ function renderRuleDetails(problem) {
${escapeHtml(String(affectedLessonCount))} ${escapeHtml(lessonWord(affectedLessonCount))} снижают оценку; суммарный штраф −${escapeHtml(String(problem.penalty))}.
+Затронуто ${escapeHtml(String(affectedLessonCount))} ${escapeHtml(lessonWord(affectedLessonCount))}; суммарный штраф −${escapeHtml(String(problem.penalty))}.
Анализатор находит окна, перегруженные дни, неудачные аудитории и нарушения - пожеланий. Черновик можно оценить до публикации, не показывая промежуточное - расписание студентам и преподавателям. + пожеланий. Все проблемные занятия объединяются по правилу, а их штрафы + суммируются. Черновик можно оценить до публикации.