From 855d1915170e2225bce784fa9a338a9f1bd3608c Mon Sep 17 00:00:00 2001 From: Zuev Date: Fri, 14 Aug 2026 22:54:16 +0300 Subject: [PATCH] . --- docs/API.md | 22 +++++++++---- docs/BUSINESS_LOGIC.md | 15 +++++---- docs/FRONTEND.md | 19 ++++++----- frontend/admin/css/schedule-quality.css | 32 +++++++++++++++++++ frontend/admin/js/views/schedule-quality.js | 4 +-- frontend/admin/js/views/schedule.js | 20 ++++++++++++ frontend/admin/views/schedule-quality.html | 12 +++---- frontend/tests/schedule-quality.test.mjs | 10 +++--- frontend/tests/schedule-versions.test.mjs | 2 ++ ...΅ΡΡ‚Π²Π΅_расписания_Ссли_ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ_сниТаСт_ΠΎΡ†Π΅Π½ΠΊΡƒ.md | 17 ++++++++++ 10 files changed, 118 insertions(+), 35 deletions(-) create mode 100644 graphify-out/memory/query_20260812_184153_Π²_качСствС_расписания_Ссли_ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ_сниТаСт_ΠΎΡ†Π΅Π½ΠΊΡƒ.md 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(problem.scheduleRuleId || 'β€”'))}

${escapeHtml(problem.subjectName || problem.title)}

-

${escapeHtml(String(affectedLessonCount))} ${escapeHtml(lessonWord(affectedLessonCount))} ΡΠ½ΠΈΠΆΠ°ΡŽΡ‚ ΠΎΡ†Π΅Π½ΠΊΡƒ; суммарный ΡˆΡ‚Ρ€Π°Ρ„ βˆ’${escapeHtml(String(problem.penalty))}.

+

Π—Π°Ρ‚Ρ€ΠΎΠ½ΡƒΡ‚ΠΎ ${escapeHtml(String(affectedLessonCount))} ${escapeHtml(lessonWord(affectedLessonCount))}; суммарный ΡˆΡ‚Ρ€Π°Ρ„ βˆ’${escapeHtml(String(problem.penalty))}.

${issueLabels.map(label => `${escapeHtml(label)}`).join('')} diff --git a/frontend/admin/js/views/schedule.js b/frontend/admin/js/views/schedule.js index bee4a44..dcce48d 100644 --- a/frontend/admin/js/views/schedule.js +++ b/frontend/admin/js/views/schedule.js @@ -491,12 +491,25 @@ export async function initSchedule() { } renderRules(); renderVisualSchedule(); + openRequestedRule(); } catch (error) { rulesTbody.innerHTML = `Ошибка Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ: ${escapeHtml(error.message)}`; setVisualState('Ошибка Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΏΡ€Π°Π²ΠΈΠ» расписания'); } } + function openRequestedRule() { + const requestedRuleId = localStorage.getItem('magistr.schedule.openRuleId'); + if (!requestedRuleId) return; + localStorage.removeItem('magistr.schedule.openRuleId'); + const rule = rules.find(item => String(item.id) === requestedRuleId); + if (!rule) { + showAlert('schedule-rule-alert', 'НС ΡƒΠ΄Π°Π»ΠΎΡΡŒ Π½Π°ΠΉΡ‚ΠΈ Π²Ρ‹Π±Ρ€Π°Π½Π½ΠΎΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ Π² этом расписании.', 'error'); + return; + } + fillRuleForm(rule); + } + function renderRules() { if (!rules.length) { rulesTbody.innerHTML = 'ΠŸΡ€Π°Π²ΠΈΠ»Π° расписания Π½Π΅ созданы'; @@ -2079,6 +2092,13 @@ export async function initSchedule() { return new Date(year, month - 1, day); } + function localIsoDate(date) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; + } + function compactWeekRanges(weeks, maxWeeks, parity) { const uniqueWeeks = [...new Set((weeks || []).map(Number).filter(Boolean))].sort((a, b) => a - b); if (!uniqueWeeks.length) return ''; diff --git a/frontend/admin/views/schedule-quality.html b/frontend/admin/views/schedule-quality.html index 5f61fbe..c8c9933 100644 --- a/frontend/admin/views/schedule-quality.html +++ b/frontend/admin/views/schedule-quality.html @@ -5,8 +5,8 @@

ΠšΠ°Ρ‡Π΅ΡΡ‚Π²ΠΎ Π²ΠΈΠ΄Π½ΠΎ Π΄ΠΎ пСрСстановок

Анализатор Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΎΠΊΠ½Π°, ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Π΅ Π΄Π½ΠΈ, Π½Π΅ΡƒΠ΄Π°Ρ‡Π½Ρ‹Π΅ Π°ΡƒΠ΄ΠΈΡ‚ΠΎΡ€ΠΈΠΈ ΠΈ Π½Π°Ρ€ΡƒΡˆΠ΅Π½ΠΈΡ - ΠΏΠΎΠΆΠ΅Π»Π°Π½ΠΈΠΉ. Π§Π΅Ρ€Π½ΠΎΠ²ΠΈΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ†Π΅Π½ΠΈΡ‚ΡŒ Π΄ΠΎ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ, Π½Π΅ показывая ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ΅ - расписаниС студСнтам ΠΈ прСподаватСлям. + ΠΏΠΎΠΆΠ΅Π»Π°Π½ΠΈΠΉ. ВсС ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½Ρ‹Π΅ занятия ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ ΠΏΠΎ ΠΏΡ€Π°Π²ΠΈΠ»Ρƒ, Π° ΠΈΡ… ΡˆΡ‚Ρ€Π°Ρ„Ρ‹ + ΡΡƒΠΌΠΌΠΈΡ€ΡƒΡŽΡ‚ΡΡ. Π§Π΅Ρ€Π½ΠΎΠ²ΠΈΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ†Π΅Π½ΠΈΡ‚ΡŒ Π΄ΠΎ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ.

@@ -55,8 +55,8 @@
- ΠšΠ°Ρ€Ρ‚Π° нСудобств -

Π§Ρ‚ΠΎ сниТаСт ΠΎΡ†Π΅Π½ΠΊΡƒ

+ ΠšΠ°Ρ€Ρ‚Π° ΠΏΡ€Π°Π²ΠΈΠ» +

ΠŸΡ€Π°Π²ΠΈΠ»Π°, ΡΠ½ΠΈΠΆΠ°ΡŽΡ‰ΠΈΠ΅ ΠΎΡ†Π΅Π½ΠΊΡƒ

@@ -89,8 +89,8 @@ diff --git a/frontend/tests/schedule-quality.test.mjs b/frontend/tests/schedule-quality.test.mjs index bdb44b7..0fb2155 100644 --- a/frontend/tests/schedule-quality.test.mjs +++ b/frontend/tests/schedule-quality.test.mjs @@ -17,7 +17,7 @@ test('ΠΎΡ†Π΅Π½ΠΊΠ° качСства ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ понятный Π΄ΠΈΠ°ΠΏΠ° test('Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ Π²Π°ΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΈ ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΡŽ', () => { const problems = [ - { type: 'GROUP_GAP', severity: 'HIGH' }, + { type: 'GROUP_GAP', problemTypes: ['GROUP_GAP', 'ROOM_OVERSIZED'], severity: 'HIGH' }, { type: 'ROOM_OVERSIZED', severity: 'LOW' }, { type: 'TEACHER_SOFT_UNWANTED', severity: 'HIGH' } ]; @@ -28,7 +28,7 @@ test('Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ Π² ); assert.deepEqual( filterQualityProblems(problems, '', 'ROOM'), - [problems[1]] + [problems[0], problems[1]] ); }); @@ -47,6 +47,8 @@ test('ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ ΠΈ Π²ΠΊΠ»Π°Π΄ΠΊΠ° Π°Π½Π°Π»ΠΈΠ·Π° ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ ΠΊ SP assert.doesNotMatch(capabilities, /DEPARTMENT:[\s\S]*schedule-quality/); assert.match(main, /'schedule-quality':[\s\S]*schedule-quality\.js/); assert.match(index, /data-tab="schedule-quality"/); - assert.match(view, /Π›ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΡ/); - assert.match(script, /ΠŸΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ послС подтвСрТдСния/); + assert.match(view, /ΠŸΡ€Π°Π²ΠΈΠ»Π°, ΡΠ½ΠΈΠΆΠ°ΡŽΡ‰ΠΈΠ΅ ΠΎΡ†Π΅Π½ΠΊΡƒ/); + assert.match(script, /Π˜Π·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ/); + assert.match(script, /magistr\.schedule\.openRuleId/); + assert.doesNotMatch(script, /quality\/recommendations/); }); diff --git a/frontend/tests/schedule-versions.test.mjs b/frontend/tests/schedule-versions.test.mjs index c4e864f..441905a 100644 --- a/frontend/tests/schedule-versions.test.mjs +++ b/frontend/tests/schedule-versions.test.mjs @@ -48,6 +48,8 @@ test('ΠΊΠΎΠ½Ρ‚ΡƒΡ€ вСрсий ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Ρ‘Π½ ΠΊ SPA, Π° конструкт assert.match(constructor, /scheduleVersionId:\s*Number\(scheduleVersionSelect\.value\)/); assert.match(constructor, /basedOnVersionId:\s*Number\(base\.id\)/); assert.match(constructor, /magistr\.schedule\.openVersionId/); + assert.match(constructor, /magistr\.schedule\.openRuleId/); + assert.match(constructor, /function localIsoDate\(date\)/); assert.match(constructor, /data-slot-id/); assert.match(view, /id="schedule-version-create-draft"/); assert.match(quality, /versionId=.*encodeURIComponent\(versionId\)/); diff --git a/graphify-out/memory/query_20260812_184153_Π²_качСствС_расписания_Ссли_ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ_сниТаСт_ΠΎΡ†Π΅Π½ΠΊΡƒ.md b/graphify-out/memory/query_20260812_184153_Π²_качСствС_расписания_Ссли_ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ_сниТаСт_ΠΎΡ†Π΅Π½ΠΊΡƒ.md new file mode 100644 index 0000000..05a5882 --- /dev/null +++ b/graphify-out/memory/query_20260812_184153_Π²_качСствС_расписания_Ссли_ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ_сниТаСт_ΠΎΡ†Π΅Π½ΠΊΡƒ.md @@ -0,0 +1,17 @@ +--- +type: "query" +date: "2026-08-12T18:41:53.854324+00:00" +question: "Π² качСствС расписания Ссли ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ сниТаСт ΠΎΡ†Π΅Π½ΠΊΡƒ качСства расписания - Ρ‚ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°ΡŽΡ‚ΡΡ всС ΠΏΠ°Ρ€Ρ‹ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ это качСство ΡΠ½ΠΈΠΆΠ°ΡŽΡ‚, Π° Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒΡΡ ΠΎΠ΄Π½ΠΎ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ ΠΏΠΎΠΌΠ΅Π½ΡΡ‚ΡŒ Π΅Π³ΠΎ, Π° Π½Π΅ ΠΊΠ°ΠΆΠ΄ΡƒΡŽ ΠΏΠ°Ρ€Ρƒ ΠΏΠΎ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ. Π±Π°Π»Π»Ρ‹ ΠΏΡ€ΠΈ этом Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΡƒΠΌΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π² зависимости ΠΎΡ‚ количСства ΠΏΠ°Ρ€ Π² ΠΏΡ€Π°Π²ΠΈΠ»Π΅" +contributor: "graphify" +outcome: "dead_end" +--- + +# Q: Π² качСствС расписания Ссли ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ сниТаСт ΠΎΡ†Π΅Π½ΠΊΡƒ качСства расписания - Ρ‚ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°ΡŽΡ‚ΡΡ всС ΠΏΠ°Ρ€Ρ‹ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ это качСство ΡΠ½ΠΈΠΆΠ°ΡŽΡ‚, Π° Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒΡΡ ΠΎΠ΄Π½ΠΎ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ ΠΏΠΎΠΌΠ΅Π½ΡΡ‚ΡŒ Π΅Π³ΠΎ, Π° Π½Π΅ ΠΊΠ°ΠΆΠ΄ΡƒΡŽ ΠΏΠ°Ρ€Ρƒ ΠΏΠΎ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ. Π±Π°Π»Π»Ρ‹ ΠΏΡ€ΠΈ этом Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΡƒΠΌΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π² зависимости ΠΎΡ‚ количСства ΠΏΠ°Ρ€ Π² ΠΏΡ€Π°Π²ΠΈΠ»Π΅ + +## Answer + +Query expanded to (from graph vocab, 7 tokens): [schedule, rule, lesson, service, dto, controller, generator]. Graph traversal returned generic Service nodes about authentication and tenant infrastructure and did not identify the quality-analysis flow, so the result was not used as source evidence. The implementation was verified directly in ScheduleQualityService, ScheduleQualityAnalysisDto, schedule-quality.js and schedule.js. + +## Outcome + +- Signal: dead_end \ No newline at end of file