From 917a6630712bb48c2ab4a9e8238d75a1be44ffd5 Mon Sep 17 00:00:00 2001
From: kilyabin <65072190+kilyabin@users.noreply.github.com>
Date: Tue, 2 Dec 2025 01:21:09 +0400
Subject: [PATCH] =?UTF-8?q?important=20fix:=20=D0=98=D1=81=D0=BF=D1=80?=
=?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BF=D0=B0=D1=80=D1=81=D0=B8?=
=?UTF-8?q?=D0=BD=D0=B3=20=D0=B7=D0=B0=D0=BC=D0=B5=D0=BD=20'=D1=81=D0=B2?=
=?UTF-8?q?=D0=BE=D0=B1=D0=BE=D0=B4=D0=BD=D0=BE=D0=B5=20=D0=B2=D1=80=D0=B5?=
=?UTF-8?q?=D0=BC=D1=8F'=20=D0=BD=D0=B0=20=D0=BF=D0=B0=D1=80=D1=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Изменен порядок проверок: сначала определяется isChange, затем проверяется 'Свободное время'
- Добавлена специальная обработка замен 'свободное время' на пару
- Корректно извлекаются название предмета, преподаватель, адрес и кабинет из структуры HTML
- Теперь при замене отображаются все данные пары вместо 'Пары нет'
---
settings.json | 2 +-
src/app/parser/schedule.ts | 152 ++++++++++++++++++++++++++++------
src/shared/data/settings.json | 2 +-
3 files changed, 129 insertions(+), 27 deletions(-)
diff --git a/settings.json b/settings.json
index 4f76642..47db0d5 100644
--- a/settings.json
+++ b/settings.json
@@ -1,7 +1,7 @@
{
"weekNavigationEnabled": false,
"debug": {
- "forceCache": true,
+ "forceCache": false,
"forceEmpty": false,
"forceError": false,
"forceTimeout": false,
diff --git a/src/app/parser/schedule.ts b/src/app/parser/schedule.ts
index a236c48..d46bf95 100644
--- a/src/app/parser/schedule.ts
+++ b/src/app/parser/schedule.ts
@@ -239,9 +239,11 @@ const parseLesson = (row: Element): Lesson | null => {
try {
const cells = Array.from(row.querySelectorAll(':scope > td'))
- if (!cells[3] || cells[3].textContent?.trim() === 'Свободное время') return null
-
+
lesson.isChange = cells.every(td => td.getAttribute('bgcolor') === 'ffffbb')
+
+ // Пропускаем урок только если это НЕ замена И в ячейке "Свободное время"
+ if (!cells[3] || (!lesson.isChange && cells[3].textContent?.trim() === 'Свободное время')) return null
if (!cells[1] || !cells[1].childNodes[0]) {
return null
@@ -261,38 +263,138 @@ const parseLesson = (row: Element): Lesson | null => {
}
try {
- if (!cells[3].childNodes[0]) {
- throw new Error('Subject node not found')
- }
- lesson.subject = cells[3].childNodes[0].textContent!.trim()
-
- const teacherCell = cells[3].childNodes[2]
- if (teacherCell) {
- lesson.teacher = teacherCell.textContent!.trim()
+ const disciplineCell = cells[3]
+ if (!disciplineCell) {
+ throw new Error('Discipline cell not found')
}
- const placeCell = cells[3].childNodes[3]
-
- if (placeCell && placeCell.childNodes.length > 0) {
- const addressNode = placeCell.childNodes[1]
- const classroomNode = placeCell.childNodes[3]
+ const cellText = disciplineCell.textContent || ''
+ const cellHTML = disciplineCell.innerHTML || ''
+
+ // Проверяем, является ли это заменой "Свободное время" на пару
+ const isFreeTimeReplacement = lesson.isChange &&
+ (cellText.includes('Свободное время') && cellText.includes('Замена') && cellText.includes('на:'))
+
+ if (isFreeTimeReplacement) {
+ // Для замены "свободное время" на пару нужно парсить данные после "на:"
+ // Структура: "Замена Свободное время на:
название
преподаватель адрес
кабинет
- if (addressNode && classroomNode) {
- const address = addressNode.textContent?.trim()
- const classroomText = classroomNode.textContent?.trim()
- const classroomMatch = classroomText?.match(/^Кабинет: ([^ ]+)(-2)?$/)
+ // Используем HTML парсинг для извлечения данных после "на:"
+ const afterOnIndex = cellHTML.indexOf('на:')
+ if (afterOnIndex !== -1) {
+ const afterOn = cellHTML.substring(afterOnIndex + 3) // +3 для "на:"
- if (address && classroomMatch) {
- lesson.place = {
- address,
- classroom: classroomMatch[1]
+ // Пропускаем первый
(он идет сразу после "на:")
+ const firstBrIndex = afterOn.indexOf('
тега
+ const firstBrEnd = afterOn.indexOf('>', firstBrIndex) + 1
+ const afterFirstBr = afterOn.substring(firstBrEnd)
+
+ // Извлекаем название предмета (текст до следующего
)
+ const secondBrIndex = afterFirstBr.indexOf('
]+>/g, '').trim()
+
+ // Извлекаем преподавателя (текст между вторым
и или следующим
)
+ const secondBrEnd = afterFirstBr.indexOf('>', secondBrIndex) + 1
+ const afterSecondBr = afterFirstBr.substring(secondBrEnd)
+
+ const fontIndex = afterSecondBr.indexOf(']+>/g, '').trim()
+ } else {
+ // Если нет , преподаватель может быть до следующего
или до конца
+ const thirdBrIndex = afterSecondBr.indexOf('
]+>/g, '').trim()
+ } else {
+ lesson.teacher = afterSecondBr.replace(/<[^>]+>/g, '').trim()
+ }
+ }
+ } else {
+ // Если нет второго
, название предмета может быть до или до конца
+ const fontIndex = afterFirstBr.indexOf(']+>/g, '').trim()
+ } else {
+ lesson.subject = afterFirstBr.replace(/<[^>]+>/g, '').trim()
+ }
+ }
+ }
+
+ // Ищем адрес и кабинет внутри
+ const fontMatch = afterOn.match(/]*>([\s\S]*?)<\/font>/i)
+ if (fontMatch) {
+ const fontContent = fontMatch[1]
+ // Ищем паттерн:
адрес
Кабинет: номер
+ // Сначала убираем все теги и разбиваем по
+ const cleanContent = fontContent.replace(/<[^>]+>/g, '|').split('|').filter(p => p.trim())
+ // Ищем адрес (первая непустая часть) и кабинет (часть с "Кабинет:")
+ for (let i = 0; i < cleanContent.length; i++) {
+ const part = cleanContent[i].trim()
+ if (part && !part.includes('Кабинет:')) {
+ const nextPart = cleanContent[i + 1]?.trim() || ''
+ const classroomMatch = nextPart.match(/Кабинет:\s*([^\s]+)/i)
+ if (classroomMatch) {
+ lesson.place = {
+ address: part,
+ classroom: classroomMatch[1]
+ }
+ break
+ }
+ }
+ }
+ } else {
+ // Если нет , ищем адрес и кабинет напрямую в тексте после "на:"
+ const addressMatch = afterOn.match(/([^<]+?)(?:
]*>|\s+)Кабинет:\s*([^<\s]+)/i)
+ if (addressMatch) {
+ lesson.place = {
+ address: addressMatch[1].replace(/<[^>]+>/g, '').trim(),
+ classroom: addressMatch[2].trim()
+ }
+ }
+ }
+ }
+ } else {
+ // Обычный парсинг для нормальных пар
+ if (!disciplineCell.childNodes[0]) {
+ throw new Error('Subject node not found')
+ }
+ lesson.subject = disciplineCell.childNodes[0].textContent!.trim()
+
+ const teacherCell = disciplineCell.childNodes[2]
+ if (teacherCell) {
+ lesson.teacher = teacherCell.textContent!.trim()
+ }
+
+ const placeCell = disciplineCell.childNodes[3]
+
+ if (placeCell && placeCell.childNodes.length > 0) {
+ const addressNode = placeCell.childNodes[1]
+ const classroomNode = placeCell.childNodes[3]
+
+ if (addressNode && classroomNode) {
+ const address = addressNode.textContent?.trim()
+ const classroomText = classroomNode.textContent?.trim()
+ const classroomMatch = classroomText?.match(/^Кабинет: ([^ ]+)(-2)?$/)
+
+ if (address && classroomMatch) {
+ lesson.place = {
+ address,
+ classroom: classroomMatch[1]
+ }
}
}
}
}
} catch(e) {
- console.error('Error while parsing discipline', e, cells[3].textContent?.trim())
- lesson.fallbackDiscipline = cells[3].textContent?.trim()
+ console.error('Error while parsing discipline', e, cells[3]?.textContent?.trim())
+ lesson.fallbackDiscipline = cells[3]?.textContent?.trim()
}
if (cells[4]) {
diff --git a/src/shared/data/settings.json b/src/shared/data/settings.json
index 4f76642..47db0d5 100644
--- a/src/shared/data/settings.json
+++ b/src/shared/data/settings.json
@@ -1,7 +1,7 @@
{
"weekNavigationEnabled": false,
"debug": {
- "forceCache": true,
+ "forceCache": false,
"forceEmpty": false,
"forceError": false,
"forceTimeout": false,