diff --git a/app/src/main/java/com/denizk0461/studip/data/Misc.kt b/app/src/main/java/com/denizk0461/studip/data/Extensions.kt similarity index 95% rename from app/src/main/java/com/denizk0461/studip/data/Misc.kt rename to app/src/main/java/com/denizk0461/studip/data/Extensions.kt index 1179fc3..d6ea87d 100644 --- a/app/src/main/java/com/denizk0461/studip/data/Misc.kt +++ b/app/src/main/java/com/denizk0461/studip/data/Extensions.kt @@ -18,8 +18,8 @@ import com.denizk0461.studip.sheet.TextSheet import com.google.android.material.snackbar.Snackbar import kotlin.jvm.Throws -/** - * Miscellaneous functions and variables that don't belong into any specific class. +/* + * Miscellaneous common functions and variables used in many classes. */ /** @@ -112,10 +112,9 @@ fun SwipeRefreshLayout.setRainbowProgressCircle() { } /** - * Provides a conversion method between a timestamp ending in a full hour, and one with an academic - * quarter applied. + * Timeslots for which a conversion to an academic quarter is applicable. */ -val timeslotsAcademicQuarter: List = listOf( +val timeslotsForAcademicQuarter: List = listOf( "0:00", "2:00", "4:00", diff --git a/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt b/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt index 978a9e3..569799f 100644 --- a/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt +++ b/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt @@ -4,6 +4,8 @@ import android.app.Application import com.denizk0461.studip.db.AppRepository import com.denizk0461.studip.model.StudIPEvent import org.jsoup.Jsoup +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element import java.io.IOException import kotlin.jvm.Throws @@ -35,26 +37,13 @@ class StudIPParser(application: Application) { val newEvents = mutableListOf() /* - * Fetch all columns from Monday through Friday to parse and assign the events of each day - * individually and accordingly. - * TODO this must be dynamic. As it is, it assumes that the first day is always Monday, - * which needs not be the case. The timetable can be customised by the user by removing - * days. Also, Sunday is treated as the first day in Stud.IP FOR SOME REASON, so the app - * needs to handle this appropriately. + * Iterate through all columns to parse and assign the events of each day individually and + * accordingly. */ - val columns = arrayOf( - doc.getElementById("calendar_view_1_column_0"), - doc.getElementById("calendar_view_1_column_1"), - doc.getElementById("calendar_view_1_column_2"), - doc.getElementById("calendar_view_1_column_3"), - doc.getElementById("calendar_view_1_column_4"), - ) - - // Iterate through each day - columns.forEachIndexed { index, element -> + doc.getDateIndices().forEach { (index, element) -> // Iterate through all events scheduled for a given day - element?.getElementsByClass("schedule_entry")?.forEach { entry -> + element.getElementsByClass("schedule_entry").forEach { entry -> /* * Retrieve the event's header. This will contain the event's title as well as the * lecturers holding the event. @@ -112,4 +101,51 @@ class StudIPParser(application: Application) { // After fetching has finished, save the list of new items into persistent storage repo.insertEvents(newEvents) } + + /** + * Finds and returns all columns that are present in the given timetable and maps them to their + * respective date indices (0 = Monday, 4 = Friday, 6 = Sunday). Returns an empty list if no + * elements could be found. + * + * @return table columns paired with their day indices + */ + private fun Document.getDateIndices(): List> { + // Create list to insert values into + val list = mutableListOf>() + + // Find headers that include day information for every schedule column + val headers = getElementById("schedule_data") + ?.getElementsByTag("thead") + ?.get(0) + ?.getElementsByTag("td") ?: return list + + // Iterate through all headers + for (index in 1 until headers.size) { + + /* + * Check which days are present. Two strings are provided to ensure this process works + * no matter whether the user has set their Stud.IP to English or German. Only these two + * languages because Stud.IP doesn't seem to support any other languages. + */ + val dayIndex = when (headers[index].text()) { + "Mon.", "Mo" -> 0 + "Tue.", "Di" -> 1 + "Wed.", "Mi" -> 2 + "Thu.", "Do" -> 3 + "Fri.", "Fr" -> 4 + "Sat.", "Sa" -> 5 + "Sun.", "So" -> 6 + else -> continue + } + + // Add the days found to the list + list.add(Pair( + dayIndex, + getElementById("calendar_view_1_column_${dayIndex}") ?: continue, + )) + } + + // Return the list of columns + return list + } } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/sheet/ScheduleUpdateSheet.kt b/app/src/main/java/com/denizk0461/studip/sheet/ScheduleUpdateSheet.kt index 5cc3df3..d917e92 100644 --- a/app/src/main/java/com/denizk0461/studip/sheet/ScheduleUpdateSheet.kt +++ b/app/src/main/java/com/denizk0461/studip/sheet/ScheduleUpdateSheet.kt @@ -12,7 +12,7 @@ import com.denizk0461.studip.data.getTimestampAcademicQuarterEnd import com.denizk0461.studip.data.getTimestampAcademicQuarterStart import com.denizk0461.studip.data.parseToMinutes import com.denizk0461.studip.data.showToast -import com.denizk0461.studip.data.timeslotsAcademicQuarter +import com.denizk0461.studip.data.timeslotsForAcademicQuarter import com.denizk0461.studip.data.viewBinding import com.denizk0461.studip.databinding.SheetScheduleUpdateBinding import com.denizk0461.studip.dialog.TimePickerFragment @@ -95,8 +95,8 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update), TimePicker } binding.buttonAcademicQuarter.visibility = getVisibilityForAcademicQuarter( - timeslotsAcademicQuarter.contains(timeslotStart), - timeslotsAcademicQuarter.contains(timeslotEnd), + timeslotsForAcademicQuarter.contains(timeslotStart), + timeslotsForAcademicQuarter.contains(timeslotEnd), ) // Prepare timestamp buttons @@ -212,8 +212,8 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update), TimePicker // Set appropriate visibility to the academic quarter button TransitionManager.beginDelayedTransition(binding.sheet.parent as ViewGroup) binding.buttonAcademicQuarter.visibility = getVisibilityForAcademicQuarter( - timeslotsAcademicQuarter.contains(timeslotStart), - timeslotsAcademicQuarter.contains(timeslotEnd), + timeslotsForAcademicQuarter.contains(timeslotStart), + timeslotsForAcademicQuarter.contains(timeslotEnd), ) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 55354ed..73cea8a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -192,12 +192,9 @@ with ♡️ from Bremen-Osterholz\nmade by denizk0461 \\__* - in our hearts, she lives forevermore it\'s only real when it hurts - can\'t go back in time – every second is a new one - doctor, i am the great clown Pagliacci + can\'t go back in time, every second is a new one if we only had one more day, what is the last thing you\'d say? love with your heart, use your head for everything else - if I die, I hope I\'m buried in a forest – that is, if any of it\'s left \ No newline at end of file