forked from agzam/vyatsu-schedule
80 lines
3.9 KiB
Kotlin
80 lines
3.9 KiB
Kotlin
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()
|
||
|
|
}
|