Files
vyatsu-schedule/app/src/main/java/agzam/vyatsu/data/remote/GroupsParser.kt
T

80 lines
3.9 KiB
Kotlin
Raw Normal View History

2026-09-02 23:47:00 +03:00
package agzam.vyatsu.data.remote
import agzam.vyatsu.domain.model.DateRange
import agzam.vyatsu.domain.model.Group
import agzam.vyatsu.domain.model.Season
import android.util.Log
import org.jsoup.Jsoup
/**
* Основано на https://github.com/alirzaev/vyatsu-schedule-backend/blob/master/utils/extractors.py
* @author Agzam
*/
object GroupsParser {
private val groupPattern = Regex("""/reports/schedule/Group/(\d{4,})_([12])_(\d{8})_(\d{8})\.pdf""")
private val shorthands = mapOf(
"Институт биологии и биотехнологии (факультет)(ОРУ)" to "ИББТ",
"Институт химии и экологии (факультет) (ОРУ)" to "ИнХимЭк",
"Факультет автоматики и вычислительной техники (ОРУ)" to "ФАВТ",
"Факультет истории, политических наук и культурологии (ОРУ)" to "ФИПНК",
"Факультет компьютерных и физико-математических наук (ОРУ)" to "ФКФМН",
"Факультет лингвистики (ОРУ)" to "ФЛ",
"Факультет менеджмента и сервиса (ОРУ)" to "ФМиС",
"Факультет педагогики и психологии (ОРУ)" to "ФПП",
"Факультет строительства и архитектуры (ОРУ)" to "ФСА",
"Факультет технологий, инжиниринга и дизайна (ОРУ)" to "ФТИД",
"Факультет физической культуры и спорта (ОРУ)" to "ФФКС",
"Факультет филологии и медиакоммуникаций (ОРУ)" to "ФФМ",
"Факультет экономики и финансов (ОРУ)" to "ФЭиФ",
"Электротехнический факультет (ОРУ)" to "ЭТФ",
"Юридический институт (факультет) (ОРУ)" to "ЮИ"
)
/**
* Извлекает список групп с HTML страницы
*/
fun parseGroups(html: String): List<Group> {
val doc = Jsoup.parse(html)
val container = doc.selectFirst("div.column-center_rasp") ?: return emptyList()
val tables = container.select("table[style~=border: none !important]")
return tables.flatMap { table ->
table.select("> tbody > tr, > tr").flatMap { row ->
val faculty = shortname(row.selectFirst("div.fak_name")?.text().orEmpty()) //
row.select("div.grpPeriod").map { grp ->
Group(
id = grp.attr("data-grp_period_id").dropLast(1),
name = removeParenthesized(grp.text()),
faculty = faculty
)
}
}
}
}
fun parseDateRanges(html: String): Map<String, Map<Season, List<DateRange>>> {
val result = HashMap<String, HashMap<Season, MutableList<DateRange>>>()
groupPattern.findAll(html).forEach { m ->
val groupId = m.groupValues[1]
val season = if (m.groupValues[2] == "1") Season.AUTUMN else Season.SPRING
val range = DateRange(m.groupValues[3], m.groupValues[4])
result
.getOrPut(groupId) { hashMapOf(Season.AUTUMN to mutableListOf(), Season.SPRING to mutableListOf()) }
.getOrPut(season) { mutableListOf() }
.add(range)
}
return result
}
private fun shortname(name: String): String {
val stripped = removeParenthesized(name)
val sh = shorthands[name]
return if (sh != null) "$sh ($stripped)" else stripped
}
private fun removeParenthesized(name: String): String = name.replace(Regex("""\(.*?\)\s?"""), "").trim()
}