@@ -2,9 +2,11 @@ package de.koenidv.sph.parsing
22
33import android.annotation.SuppressLint
44import android.graphics.Color
5+ import android.util.Log
56import android.widget.Toast
67import androidx.core.graphics.toColorInt
78import de.koenidv.sph.R
9+ import de.koenidv.sph.SphPlanner.Companion.TAG
810import de.koenidv.sph.SphPlanner.Companion.applicationContext
911import de.koenidv.sph.database.CoursesDb
1012import de.koenidv.sph.objects.*
@@ -230,47 +232,56 @@ class RawParser {
230232 */
231233 fun parseCoursesFromStudygroups (rawResponse : String ): List <Course > {
232234 val courses = mutableListOf<Course >()
233- // Remove stuff we don't need
234- // There are multiple tables in this page, we'll just take the first one
235- val rawContent = rawResponse.substring(rawResponse.indexOf(" <tbody>" ) + 7 , rawResponse.indexOf(" </tbody>" ))
236235
237- /*
236+ // Return empty list if content is invalid
237+ try {
238+
239+ // Remove stuff we don't need
240+ // There are multiple tables in this page, we'll just take the first one
241+ val rawContent = rawResponse.substring(rawResponse.indexOf(" <tbody>" ) + 7 , rawResponse.indexOf(" </tbody>" ))
242+
243+ /*
238244 * It seems as if the sph id index is in the same order as the timetable
239245 * i.e. Q3Gvac03 - GYM is the 3rd History GK in the timetable
240246 * This means that the internal id's should be in the same order as they're taken from it
241247 * Let's just hope the best
242248 */
243249
244- val rawContents = rawContent.split(" <tr" ).toMutableList()
245- rawContents.removeFirst()
250+ val rawContents = rawContent.split(" <tr" ).toMutableList()
251+ rawContents.removeFirst()
252+
253+ var namedId: String
254+ var uniformNamedId: String
255+ var sphId: String
256+ var teacherId: String
257+ var internalId: String
258+ val nameColorMap = Utility ().parseStringArray(R .array.course_colors)
259+
260+ // Get data from each table row and save the courses
261+ for (entry in rawContents) {
262+ namedId = entry.substring(Utility ().ordinalIndexOf(entry, " <td>" , 1 ) + 4 , entry.indexOf(" <small>" ) - 1 ).trim()
263+ uniformNamedId = CourseParser ().parseNamedId(namedId)
264+ sphId = entry.substring(entry.indexOf(" <small>" ) + 8 , entry.indexOf(" </small>" ) - 1 )
265+ teacherId = entry.substring(Utility ().ordinalIndexOf(entry, " <td>" , 2 ))
266+ teacherId = teacherId.substring(teacherId.indexOf(" (" ) + 1 , teacherId.indexOf(" )" )).toLowerCase(Locale .ROOT )
267+ internalId = IdParser ().getCourseIdWithSph(sphId, teacherId, entry.contains(" LK" ))
246268
247- var namedId: String
248- var uniformNamedId: String
249- var sphId: String
250- var teacherId: String
251- var internalId: String
252- val nameColorMap = Utility ().parseStringArray(R .array.course_colors)
269+ courses.add(Course (
270+ courseId = internalId,
271+ sph_id = sphId,
272+ named_id = uniformNamedId,
273+ id_teacher = teacherId,
274+ fullname = CourseParser ().getFullnameFromInternald(internalId),
275+ isFavorite = true ,
276+ isLK = entry.contains(" LK" ),
277+ color = (nameColorMap[uniformNamedId.substring(0 , uniformNamedId.indexOf(" " ))]
278+ ? : nameColorMap[" default" ])!! .toColorInt()
279+ ))
280+ }
253281
254- // Get data from each table row and save the courses
255- for (entry in rawContents) {
256- namedId = entry.substring(Utility ().ordinalIndexOf(entry, " <td>" , 1 ) + 4 , entry.indexOf(" <small>" ) - 1 ).trim()
257- uniformNamedId = CourseParser ().parseNamedId(namedId)
258- sphId = entry.substring(entry.indexOf(" <small>" ) + 8 , entry.indexOf(" </small>" ) - 1 )
259- teacherId = entry.substring(Utility ().ordinalIndexOf(entry, " <td>" , 2 ))
260- teacherId = teacherId.substring(teacherId.indexOf(" (" ) + 1 , teacherId.indexOf(" )" )).toLowerCase(Locale .ROOT )
261- internalId = IdParser ().getCourseIdWithSph(sphId, teacherId, entry.contains(" LK" ))
262-
263- courses.add(Course (
264- courseId = internalId,
265- sph_id = sphId,
266- named_id = uniformNamedId,
267- id_teacher = teacherId,
268- fullname = CourseParser ().getFullnameFromInternald(internalId),
269- isFavorite = true ,
270- isLK = entry.contains(" LK" ),
271- color = (nameColorMap[namedId.substring(0 , namedId.indexOf(" " ))]
272- ? : nameColorMap[" default" ])!! .toColorInt()
273- ))
282+ } catch (e: StringIndexOutOfBoundsException ) {
283+ Log .d(TAG , " Studygroups parsing failed!" )
284+ Log .d(TAG , e.stackTraceToString())
274285 }
275286
276287 return courses
@@ -283,56 +294,93 @@ class RawParser {
283294 */
284295 fun parseCoursesFromPostsoverview (rawResponse : String ): List <Course > {
285296 val courses = mutableListOf<Course >()
286- // Remove stuff we don't need, get second menu <ul>
287- @Suppress(" VARIABLE_WITH_REDUNDANT_INITIALIZER" ) var rawContent = rawResponse.substring(rawResponse.indexOf(" <ul role=\" menu\" " ) + 15 )
288- rawContent = rawContent.substring(rawContent.indexOf(" <ul role=\" menu\" " ))
289- rawContent = rawContent.substring(0 , rawContent.indexOf(" </ul>" ))
290-
291- val rawContents = rawContent.split(" <li >" ).toMutableList()
292- rawContents.removeFirst() // Trash
293- rawContents.removeFirst() // Overview link
297+ // Get the courses table
298+ val table = Jsoup .parse(rawResponse).select(" #aktuell tbody" )
294299
295300 var courseName: String
296- var uniformCourseName : String
301+ var uniformNamedId : String
297302 var numberId: String
303+ var teacherId: String
304+ var isLK: Boolean
298305 var similiarCourses: List <Course >
299- // Get values from list
300- for (entry in rawContents) {
301- if (entry.contains(" a=sus_view&id=" )) {
302- numberId = entry.substring(entry.indexOf(" a=sus_view&id=" ) + 14 )
303- numberId = numberId.substring(0 , numberId.indexOf(" \" " ))
304- courseName = entry.substring(entry.indexOf(" </span>" ) + 7 , entry.indexOf(" </a>" )).trim()
305-
306- // todo create new courses with teacher_id instead of using old ones: might not be available
307-
308- // Make named id from post overview uniform
309- uniformCourseName = CourseParser ().parseNamedId(courseName)
310-
311- // Get courses that might be the same as this one
312- similiarCourses = CoursesDb .getInstance().getByNamedId(uniformCourseName).toMutableList()
313- if (courseName.contains(""" \(.*\)""" .toRegex())) { // if contains text in brackets
314- val courseToAdd = CoursesDb .getInstance().getBySphId(courseName.substring(courseName.indexOf(" (" ) + 1 , courseName.lastIndexOf(" )" )).replace(" -GYM" , " - GYM" ))
315- if (courseToAdd != null ) similiarCourses.add(courseToAdd)
316- }
306+ val nameColorMap = Utility ().parseStringArray(R .array.course_colors)
307+ // Get values from table
308+ for (row in table.select(" tr" )) {
309+ numberId = row.attr(" data-book" )
310+ courseName = row.select(" span.name" ).text()
311+ teacherId = row.select(" span.teacher button" )
312+ .first().ownText().toLowerCase(Locale .ROOT )
313+ isLK = courseName.contains(" LK" )
314+
315+ // Make named id from post overview uniform
316+ uniformNamedId = CourseParser ().parseNamedId(courseName)
317+
318+ // Get courses that might be the same as this one
319+ similiarCourses = CoursesDb .getInstance().getByNamedId(uniformNamedId).toMutableList()
320+
321+ // If no similiar course was found, try getting all courses with the same subject and teacher
322+ var courseIdPrefix: String? = null
323+ if (similiarCourses.isEmpty()) {
324+ courseIdPrefix = IdParser ().getCourseIdPrefixWithNamedId(uniformNamedId, teacherId)
325+ if (courseIdPrefix != null )
326+ similiarCourses.addAll(CoursesDb .getInstance().getByInternalPrefix(courseIdPrefix)
327+ .filter { it.isLK == null || it.isLK == isLK })
328+ }
317329
318- // Make sure no course is in the list twice
319- // This might happen because we add both by NamedId and SphId
320- similiarCourses = similiarCourses.distinct()
321330
322- when {
323- similiarCourses.size == 1 -> {
324- // Only one similiar course, this should be it.
325- similiarCourses[0 ].number_id = numberId
326- courses.add(similiarCourses[0 ])
327- }
328- similiarCourses.isEmpty() -> {
329- // todo create new course with this namedid & numberid
330- Toast .makeText(applicationContext(), " No valid course" , Toast .LENGTH_SHORT ).show()
331+ if (courseName.contains(""" \(.*\)""" .toRegex())) { // if contains text in brackets
332+ val courseToAdd = CoursesDb .getInstance().getBySphId(courseName.substring(courseName.indexOf(" (" ) + 1 , courseName.lastIndexOf(" )" )).replace(" -GYM" , " - GYM" ))
333+ if (courseToAdd != null ) similiarCourses.add(courseToAdd)
334+ }
335+
336+ // Make sure no course is in the list twice
337+ // This might happen because we add both by NamedId and SphId
338+ similiarCourses = similiarCourses.distinct()
339+
340+ when {
341+ similiarCourses.size == 1 -> {
342+ // Only one similiar course, this should be it.
343+ similiarCourses[0 ].apply {
344+ number_id = numberId
345+ named_id = uniformNamedId
346+ isFavorite = true
347+ fullname = CourseParser ().getFullnameFromInternald(similiarCourses[0 ].courseId)
348+ color = (nameColorMap[
349+ uniformNamedId
350+ .substring(0 , uniformNamedId.indexOf(" " ))]
351+ ? : nameColorMap[" default" ])!! .toColorInt()
331352 }
332- similiarCourses.size > 1 -> {
333- // todo handle multiple similiar courses
334- Toast .makeText(applicationContext(), " Too many courses" , Toast .LENGTH_SHORT ).show()
353+ courses.add(similiarCourses[0 ])
354+ }
355+ similiarCourses.isEmpty() -> {
356+ // Create new course with this namedid & numberid
357+ // If no course could be found, there is no other course with the same internal prefix
358+ // (We tried getting every course by that)
359+ // This means we can just use the prefix - if available with an index 1
360+ if (courseIdPrefix != null ) {
361+ courses.add(Course (
362+ courseId = courseIdPrefix + " _1" ,
363+ named_id = uniformNamedId,
364+ fullname = CourseParser ().getFullnameFromInternald(courseIdPrefix + " _1" ),
365+ number_id = numberId,
366+ id_teacher = teacherId,
367+ isFavorite = true ,
368+ isLK = isLK,
369+ color = (nameColorMap[
370+ uniformNamedId
371+ .substring(0 , uniformNamedId.indexOf(" " ))]
372+ ? : nameColorMap[" default" ])!! .toColorInt()
373+ ))
335374 }
375+ Log .d(TAG , " No valid course for $uniformNamedId " )
376+ }
377+ similiarCourses.size > 1 -> {
378+ // todo handle multiple similiar courses
379+ Toast .makeText(applicationContext(), " Too many courses" , Toast .LENGTH_LONG ).show()
380+ Log .d(TAG , " Too many courses for $uniformNamedId " )
381+ // currently adds first course
382+ similiarCourses[0 ].number_id = numberId
383+ courses.add(similiarCourses[0 ])
336384 }
337385 }
338386 }
0 commit comments