fix: wrong parsed teacher schedule

This commit is contained in:
2026-10-08 01:42:26 +03:00
parent ae0fea1ea6
commit c7298c0c84
4 changed files with 3306 additions and 10 deletions
@@ -23,9 +23,18 @@ object TeacherScheduleParser {
data class ParsedTeacherSchedule(val teachers: List<String>, val days: List<Day>)
/**
* Столбец расписания преподавателя: имя и абсолютный индекс ячейки в шапке.
* Индекс нужен для точного выравнивания с рядами данных — в шапке могут
* присутствовать пустые колонки-разделители, которые не должны сдвигать
* соответствие «преподаватель → столбец».
*/
private data class Column(val teacher: String, val headerIndex: Int)
fun parse(html: String): ParsedTeacherSchedule {
val doc = Jsoup.parse(html)
var headerFound = false
var columns: List<Column> = emptyList()
var teachers: List<String> = emptyList()
val days = mutableListOf<Day>()
var currentDate: LocalDate? = null
@@ -43,10 +52,12 @@ object TeacherScheduleParser {
val first = cellText(tds[0])
val second = cellText(tds[1])
if (!headerFound && first == "День" && second == "Интервал") {
teachers = tds.drop(2)
.map { cellText(it.selectFirst("span") ?: it) }
.filter { it.isNotEmpty() }
.distinct()
columns = tds.mapIndexedNotNull { index, td ->
if (index < 2) return@mapIndexedNotNull null
val name = cellText(td.selectFirst("span") ?: td)
if (name.isEmpty()) null else Column(name, index)
}.distinctBy { it.teacher }
teachers = columns.map { it.teacher }
headerFound = true
continue
}
@@ -58,7 +69,7 @@ object TeacherScheduleParser {
currentIntervals = mutableListOf()
}
if (intervalMatch != null && currentIntervals != null) {
parseIntervalRow(tds, intervalMatch, if (dayMatch != null) 2 else 1, teachers, currentIntervals!!)
parseIntervalRow(tds, intervalMatch, dayMatch != null, columns, currentIntervals!!)
}
}
flushDay()
@@ -83,16 +94,20 @@ object TeacherScheduleParser {
private fun parseIntervalRow(
tds: List<Element>,
intervalMatch: MatchResult,
startCol: Int,
teachers: List<String>,
dayRow: Boolean,
columns: List<Column>,
intervals: MutableList<TimeSlot>
) {
val start = LocalTime.parse(intervalMatch.groupValues[1])
val end = LocalTime.parse(intervalMatch.groupValues[2])
val lessons = mutableListOf<Lesson>()
for (i in teachers.indices) {
val cell = tds.getOrNull(startCol + i) ?: continue
lessons += parseCell(cell, teachers[i])
for (column in columns) {
// Ряд с днём содержит обе ведущие ячейки (День, Интервал) и совпадает
// по индексам с шапкой; ряд только с интервалом пропускает ячейку дня
// (rowspan) — его ячейки сдвинуты на одну позицию влево.
val dataIndex = if (dayRow) column.headerIndex else column.headerIndex - 1
val cell = tds.getOrNull(dataIndex) ?: continue
lessons += parseCell(cell, column.teacher)
}
if (lessons.isNotEmpty()) intervals.add(TimeSlot(start, end, lessons))
}