feat(remote): add jsoup TeacherScheduleParser

This commit is contained in:
2026-09-19 14:47:55 +03:00
parent 458e4c4e69
commit 32c2b60afa
5 changed files with 331 additions and 7 deletions
@@ -0,0 +1,86 @@
package agzam.vyatsu
import agzam.vyatsu.data.remote.TeacherScheduleParser
import agzam.vyatsu.domain.model.LessonType
import java.time.LocalDate
import java.time.LocalTime
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
class TeacherScheduleParserTest {
private fun fixture(): String =
checkNotNull(javaClass.getResourceAsStream("/prepod.html"))
.readBytes().toString(Charsets.UTF_8)
@Test
fun teachersHeaderParsedInOrderAndDeduped() {
val parsed = TeacherScheduleParser.parse(fixture())
assertEquals(listOf("Лелекова Е.В.", "Иванов И.И.", "Петрова А.С."), parsed.teachers)
}
@Test
fun daysWithCorrectDates() {
val parsed = TeacherScheduleParser.parse(fixture())
assertEquals(2, parsed.days.size)
assertEquals(LocalDate.of(2026, 9, 14), parsed.days[0].date)
assertEquals(LocalDate.of(2026, 9, 15), parsed.days[1].date)
}
@Test
fun intervalTimesParsed() {
val parsed = TeacherScheduleParser.parse(fixture())
val day0 = parsed.days[0]
assertEquals(2, day0.intervals.size)
assertEquals(LocalTime.of(8, 20), day0.intervals[0].start)
assertEquals(LocalTime.of(9, 50), day0.intervals[0].end)
assertEquals(LocalTime.of(10, 0), day0.intervals[1].start)
assertEquals(LocalTime.of(11, 30), day0.intervals[1].end)
}
@Test
fun multiGroupCellSplitsIntoPerGroupLessons() {
val parsed = TeacherScheduleParser.parse(fixture())
val cell = parsed.days[0].intervals[0].lessons.filter { it.teacher == "Лелекова Е.В." }
assertEquals(2, cell.size)
val lesson0 = cell[0]
val lesson1 = cell[1]
assertEquals("Бб-1101-04-00", lesson0.group)
assertNull(lesson0.subgroup)
assertEquals("01 подгруппа", lesson1.subgroup)
assertEquals("4-302", lesson0.room)
assertEquals("Биоразнообразие", lesson0.subject)
assertEquals(LessonType.LECTURE, lesson0.type)
assertEquals("Лелекова Е.В.", lesson0.teacher)
}
@Test
fun emptyCellContributesNoLesson() {
val parsed = TeacherScheduleParser.parse(fixture())
val threeSlots = (0..6).map { slot ->
parsed.days[0].intervals.firstOrNull { it.start.hour == 8 && it.start.minute == 20 } ?: return@map true
}
val petrovLessons = parsed.days[0].intervals[0].lessons.filter { it.teacher == "Петрова А.С." }
assertEquals(0, petrovLessons.size)
assertTrue(threeSlots.isEmpty() || threeSlots.size == 7)
}
@Test
fun noRoomCellKeepsRawAndNullRoom() {
val parsed = TeacherScheduleParser.parse(fixture())
val cell = parsed.days[0].intervals[1].lessons.filter { it.teacher == "Лелекова Е.В." }
assertEquals(2, cell.size)
assertNull(cell[0].room)
assertTrue(cell[0].raw.contains("Бб-1101-04-00"))
assertNull(cell[0].subject)
}
@Test
fun exactTotalLessonCount() {
val parsed = TeacherScheduleParser.parse(fixture())
val total = parsed.days.sumOf { day -> day.intervals.sumOf { it.lessons.size } }
assertEquals(11, total)
}
}