Merge pull request 'Parse course name for room occupancies' (#30) from parse-lessoncourse into master

Reviewed-on: #30
This commit is contained in:
Jannik 2023-09-29 23:12:06 +02:00
commit 302e1c7307
4 changed files with 52 additions and 26 deletions

View File

@ -102,7 +102,7 @@ class APIController {
@RequestParam(value = "course", defaultValue = "AI4") courseName: String,
@RequestParam(value = "subject", defaultValue = "Mathematik 4") lessonSubject: String,
@RequestParam(value = "week", defaultValue = "0") week: Int
): ArrayList<Lesson> {
): ArrayList<LessonWithRoom> {
logger.info("lesson request at ${LocalDateTime.now()}!")
updateTimetableRequests(courseName)
return getLesson(courseName, lessonSubject, week)

View File

@ -49,7 +49,7 @@ data class MensaMenu(val meta: MensaMeta, val currentWeek: MensaWeek, val nextWe
data class CalendarWeek(val week: Int, val year: Int)
data class Lesson(
data class LessonWithRoom(
val lessonID: String,
val lessonSubject: String,
val lessonTeacher: String,
@ -57,13 +57,21 @@ data class Lesson(
val lessonRemark: String
)
data class TimetableDay(val timeslots: Array<ArrayList<Lesson>> = Array(6) { ArrayList<Lesson>() })
data class LessonWithCourse(
val lessonID: String,
val lessonSubject: String,
val lessonTeacher: String,
val lessonCourse: String,
val lessonRemark: String
)
data class TimetableWeek(val days: Array<TimetableDay> = Array(6) { TimetableDay() })
data class TimetableDay<Lesson>(val timeslots: Array<ArrayList<Lesson>> = Array(6) { ArrayList<Lesson>() })
data class TimetableWeek<Lesson>(val days: Array<TimetableDay<Lesson>> = Array(6) { TimetableDay() })
data class TimetableCourseMeta(var updateTime: Long = 0, val courseName: String = "", val weekIndex: Int = 0, var weekNumberYear: Int = 0, var year: Int = 0, val link: String = "")
data class TimetableCourseWeek(val meta: TimetableCourseMeta = TimetableCourseMeta(), var timetable: TimetableWeek = TimetableWeek())
data class TimetableCourseWeek(val meta: TimetableCourseMeta = TimetableCourseMeta(), var timetable: TimetableWeek<LessonWithRoom> = TimetableWeek())
// data classes for the room occupancy part
data class Room(val roomName: String, val roomLink: String)
@ -75,7 +83,7 @@ data class RoomsListRet(val meta: RoomsMeta = RoomsMeta(), val rooms: ArrayList<
data class RoomScheduleMeta(var updateTime: Long = 0, val roomName: String = "", val weekIndex: Int = 0, var weekNumberYear: Int = 0, var year: Int = 0, val link: String = "")
data class RoomScheduleWeekRet(val meta: RoomScheduleMeta = RoomScheduleMeta(), var timetable: TimetableWeek = TimetableWeek())
data class RoomScheduleWeekRet(val meta: RoomScheduleMeta = RoomScheduleMeta(), var timetable: TimetableWeek<LessonWithCourse> = TimetableWeek())
// data classes for the status part

View File

@ -27,9 +27,10 @@ import kotlinx.coroutines.*
import org.jsoup.Jsoup
import org.mosad.thecitadelofricks.*
import org.mosad.thecitadelofricks.hsoparser.CourseListParser
import org.mosad.thecitadelofricks.hsoparser.CourseTimetableParser
import org.mosad.thecitadelofricks.hsoparser.MensaParser
import org.mosad.thecitadelofricks.hsoparser.RoomListParser
import org.mosad.thecitadelofricks.hsoparser.TimetableParser
import org.mosad.thecitadelofricks.hsoparser.RoomTimetableParser
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.*
@ -41,7 +42,6 @@ import kotlin.collections.HashSet
import kotlin.concurrent.scheduleAtFixedRate
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes
import kotlin.time.ExperimentalTime
class CacheController {
@ -76,7 +76,7 @@ class CacheController {
val instr = CacheController::class.java.getResourceAsStream("/html/Timetable_normal-week.html")
val timetableParser =
TimetableParser(htmlDoc = Jsoup.parse(instr!!, "UTF-8", "https://www.hs-offenburg.de/"))
CourseTimetableParser(htmlDoc = Jsoup.parse(instr!!, "UTF-8", "https://www.hs-offenburg.de/"))
val timetableTest = timetableParser.parseTimeTable()
return TimetableCourseWeek(
@ -100,7 +100,7 @@ class CacheController {
?.replace("week=0", "week=$weekIndex") ?: ""
val currentTime = System.currentTimeMillis() / 1000
val timetableParser = TimetableParser(timetableLink)
val timetableParser = CourseTimetableParser(timetableLink)
val calendarWeek = timetableParser.parseCalendarWeek()
val timetable = timetableParser.parseTimeTable()
@ -142,8 +142,8 @@ class CacheController {
* @param weekIndex request week number (current week = 0)
* @return a ArrayList<[Lesson]> of every lesson with lessonSubject for one week
*/
fun getLesson(courseName: String, lessonSubject: String, weekIndex: Int): ArrayList<Lesson> {
val lessonList = ArrayList<Lesson>()
fun getLesson(courseName: String, lessonSubject: String, weekIndex: Int): ArrayList<LessonWithRoom> {
val lessonList = ArrayList<LessonWithRoom>()
// get all lessons from the weeks timetable
val flatMap = getTimetable(courseName, weekIndex).timetable.days.flatMap { it.timeslots.asIterable() }
@ -171,7 +171,7 @@ class CacheController {
?.replace("week=0", "week=$weekIndex") ?: ""
val currentTime = System.currentTimeMillis() / 1000
val roomScheduleParser = TimetableParser(roomScheduleLink)
val roomScheduleParser = RoomTimetableParser(roomScheduleLink)
val calendarWeek = roomScheduleParser.parseCalendarWeek()
val roomSchedule = roomScheduleParser.parseTimeTable()
@ -248,7 +248,7 @@ class CacheController {
try {
timetableList.forEach { timetableCourse ->
executor.execute {
val timetableParser = TimetableParser(timetableCourse.value.meta.link)
val timetableParser = CourseTimetableParser(timetableCourse.value.meta.link)
timetableCourse.value.timetable = timetableParser.parseTimeTable() ?: return@execute
timetableParser.parseCalendarWeek()?.also {
timetableCourse.value.meta.weekNumberYear = it.week
@ -294,7 +294,7 @@ class CacheController {
try {
roomScheduleList.forEach { roomSchedule ->
executor.execute {
val roomScheduleParser = TimetableParser(roomSchedule.value.meta.link)
val roomScheduleParser = RoomTimetableParser(roomSchedule.value.meta.link)
roomSchedule.value.timetable = roomScheduleParser.parseTimeTable() ?: return@execute
roomScheduleParser.parseCalendarWeek()?.also {
roomSchedule.value.meta.weekNumberYear = it.week

View File

@ -27,7 +27,8 @@ import kotlinx.coroutines.sync.Semaphore
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.mosad.thecitadelofricks.CalendarWeek
import org.mosad.thecitadelofricks.Lesson
import org.mosad.thecitadelofricks.LessonWithCourse
import org.mosad.thecitadelofricks.LessonWithRoom
import org.mosad.thecitadelofricks.TimetableWeek
import org.slf4j.LoggerFactory
@ -35,10 +36,13 @@ import org.slf4j.LoggerFactory
* @param timetableURL the URL of the timetable you want to get
* @param htmlDoc the html document to use (the timetableURL will be ignored if this value is present)
*/
class TimetableParser(timetableURL: String? = null, htmlDoc: Document? = null) {
sealed class TimetableParser<Lesson>(timetableURL: String? = null, htmlDoc: Document? = null) {
private var logger: org.slf4j.Logger = LoggerFactory.getLogger(TimetableParser::class.java)
private val days = arrayOf("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
abstract fun constructLesson(lessonID: String, lessonSubject: String, lessonTeacher: String, value4: String, lessonRemark: String): Lesson
abstract val value4Class: String
companion object {
val semaphore = Semaphore(3, 0)
}
@ -63,13 +67,13 @@ class TimetableParser(timetableURL: String? = null, htmlDoc: Document? = null) {
* the timetable is organised per row not per column;
* Mon 1, Tue 1, Wed 1, Thur 1, Fri 1, Sat 1, Mon 2 and so on
*/
fun parseTimeTable(): TimetableWeek? = htmlDoc?.let {
val timetableWeek = TimetableWeek()
fun parseTimeTable(): TimetableWeek<Lesson>? = htmlDoc?.let {
val timetableWeek = TimetableWeek<Lesson>()
val rows = it.select("table.timetable").select("tr[scope=\"row\"]")
var sDay = -1
var sRow = -1
var sLesson = Lesson("", "", "", "", "")
var sLesson = constructLesson("", "", "", "", "")
// get each row with index, reflects 1 timeslot per day
for ((rowIndex, row) in rows.withIndex()) {
@ -86,11 +90,11 @@ class TimetableParser(timetableURL: String? = null, htmlDoc: Document? = null) {
// adjust the following slot
sDay++
sLesson = Lesson(
sLesson = constructLesson(
"$day.$rowIndex.$lessonIndexDay",
element.select("div.lesson-subject").text(),
element.select("div.lesson-teacher").text(),
element.select("div.lesson-room").text(),
element.select("div.$value4Class").text(),
element.select("div.lesson-remark").text()
)
@ -101,11 +105,11 @@ class TimetableParser(timetableURL: String? = null, htmlDoc: Document? = null) {
} else {
timetableWeek.days[day].timeslots[rowIndex].add(
Lesson(
constructLesson(
"$day.$rowIndex.$lessonIndexDay",
element.select("div.lesson-subject").text(),
element.select("div.lesson-teacher").text(),
element.select("div.lesson-room").text(),
element.select("div.$value4Class").text(),
element.select("div.lesson-remark").text()
)
)
@ -146,7 +150,7 @@ class TimetableParser(timetableURL: String? = null, htmlDoc: Document? = null) {
* print a timetable
* @param timetable the timetable to print
*/
fun printTimetableWeek(timetable: TimetableWeek) {
fun printTimetableWeek(timetable: TimetableWeek<LessonWithRoom>) {
for (j in 0..5) print(days[j].padEnd(75, ' ') + " | ")
println()
for (j in 0..5) print("-".padEnd(76 + (j.toFloat().div(j).toInt()), '-') + "+")
@ -189,4 +193,18 @@ class TimetableParser(timetableURL: String? = null, htmlDoc: Document? = null) {
println(" \n")
}
}
}
class CourseTimetableParser(timetableURL: String? = null, htmlDoc: Document? = null) : TimetableParser<LessonWithRoom>(timetableURL, htmlDoc) {
override fun constructLesson(lessonID: String, lessonSubject: String, lessonTeacher: String, value4: String, lessonRemark: String)
= LessonWithRoom(lessonID, lessonSubject, lessonTeacher, value4, lessonRemark)
override val value4Class = "lesson-room"
}
class RoomTimetableParser(timetableURL: String? = null, htmlDoc: Document? = null) : TimetableParser<LessonWithCourse>(timetableURL, htmlDoc) {
override fun constructLesson(lessonID: String, lessonSubject: String, lessonTeacher: String, value4: String, lessonRemark: String)
= LessonWithCourse(lessonID, lessonSubject, lessonTeacher, value4, lessonRemark)
override val value4Class = "lesson-class"
}