@ -13,7 +13,7 @@ android {
 | 
			
		||||
        minSdkVersion 21
 | 
			
		||||
        targetSdkVersion 28
 | 
			
		||||
        versionCode 11
 | 
			
		||||
        versionName "0.3.90"
 | 
			
		||||
        versionName "0.3.95"
 | 
			
		||||
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 | 
			
		||||
    }
 | 
			
		||||
    buildTypes {
 | 
			
		||||
@ -33,11 +33,11 @@ dependencies {
 | 
			
		||||
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
 | 
			
		||||
    implementation 'com.google.android.material:material:1.0.0'
 | 
			
		||||
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
 | 
			
		||||
    implementation 'org.jsoup:jsoup:1.11.3'
 | 
			
		||||
    implementation 'org.jetbrains.anko:anko-commons:0.10.8'
 | 
			
		||||
    implementation 'com.afollestad:aesthetic:1.0.0-beta05'
 | 
			
		||||
    implementation 'com.afollestad.material-dialogs:core:2.0.3'
 | 
			
		||||
    implementation 'com.afollestad.material-dialogs:color:2.0.3'
 | 
			
		||||
    implementation 'com.google.code.gson:gson:2.8.5'
 | 
			
		||||
 | 
			
		||||
    testImplementation 'junit:junit:4.12'
 | 
			
		||||
    androidTestImplementation 'androidx.test:runner:1.1.1'
 | 
			
		||||
 | 
			
		||||
@ -32,29 +32,23 @@ import androidx.core.view.GravityCompat
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import androidx.fragment.app.FragmentTransaction
 | 
			
		||||
import com.afollestad.aesthetic.Aesthetic
 | 
			
		||||
import com.afollestad.materialdialogs.MaterialDialog
 | 
			
		||||
import com.google.android.material.navigation.NavigationView
 | 
			
		||||
import kotlinx.android.synthetic.main.activity_main.*
 | 
			
		||||
import kotlinx.android.synthetic.main.app_bar_main.*
 | 
			
		||||
import org.jetbrains.anko.doAsync
 | 
			
		||||
import org.jetbrains.anko.uiThread
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cColorAccent
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cColorPrimary
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cCourse
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cCourseTTLinkList
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableCurrentWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableNextWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cMenusCurrentWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cMenusNextWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorAccent
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorPrimary
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.coursesCacheTime
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.mensaCacheTime
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.timetableCacheTime
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.CacheController
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
 | 
			
		||||
import org.mosad.seil0.projectlaogai.fragments.*
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.MensaParser
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.TimeTableParser
 | 
			
		||||
import kotlin.system.measureTimeMillis
 | 
			
		||||
 | 
			
		||||
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
 | 
			
		||||
 | 
			
		||||
    private val mensaParser = MensaParser()
 | 
			
		||||
    private val timeTableParser = TimeTableParser()
 | 
			
		||||
    private var activeFragment: Fragment = HomeFragment() // the currently active fragment, home at the start
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
@ -75,6 +69,8 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
 | 
			
		||||
                colorAccent(Color.parseColor("#FF1744"))
 | 
			
		||||
                apply()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // TODO show a course selection
 | 
			
		||||
        } else {
 | 
			
		||||
            Aesthetic.config {
 | 
			
		||||
                colorPrimary(cColorPrimary)
 | 
			
		||||
@ -164,62 +160,31 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
 | 
			
		||||
     * load the mensa menus of the current week
 | 
			
		||||
     */
 | 
			
		||||
    private fun load() {
 | 
			
		||||
        val menuLinkCurrentWeek = "https://www.swfr.de/de/essen-trinken/speiseplaene/mensa-offenburg/"
 | 
			
		||||
        // load the settings
 | 
			
		||||
        PreferencesController.load(this) // this must be finished before doing anything else
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * load mensa, course timetable and courselist from the swfr/hso website
 | 
			
		||||
         * TODO make an API see https://git.mosad.xyz/Seil0/TheCitadelofRicks
 | 
			
		||||
         */
 | 
			
		||||
        val time = measureTimeMillis {
 | 
			
		||||
        val startupTime = measureTimeMillis {
 | 
			
		||||
 | 
			
		||||
            /* getting the course list should be faster than the timetable,
 | 
			
		||||
             * we need have time until the user opens the dialog
 | 
			
		||||
             */
 | 
			
		||||
            doAsync {
 | 
			
		||||
                cCourseTTLinkList = timeTableParser.getCourseTTLinks()
 | 
			
		||||
            // get the cached files
 | 
			
		||||
            val cache = CacheController(this)
 | 
			
		||||
            cache.readStartCache(cCourse.courseName)
 | 
			
		||||
 | 
			
		||||
            // check if an update is necessary
 | 
			
		||||
            val tcor = TCoRAPIController(this)
 | 
			
		||||
            val currentTime = System.currentTimeMillis() / 1000
 | 
			
		||||
 | 
			
		||||
            if(currentTime - coursesCacheTime > 86400)
 | 
			
		||||
                tcor.getCoursesList()
 | 
			
		||||
 | 
			
		||||
            if(currentTime - mensaCacheTime > 10800)
 | 
			
		||||
                tcor.getMensa()
 | 
			
		||||
 | 
			
		||||
            if(currentTime - timetableCacheTime > 10800) {
 | 
			
		||||
                tcor.getTimetable(cCourse.courseName, 0)
 | 
			
		||||
                tcor.getTimetable(cCourse.courseName, 1)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val jobMenusCurrentWeek = doAsync {
 | 
			
		||||
                cMenusCurrentWeek = mensaParser.getMensaMenu(menuLinkCurrentWeek)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val jobMenusNextWeek = doAsync {
 | 
			
		||||
                cMenusNextWeek = mensaParser.getMensaMenu(mensaParser.getMenuLinkNextWeek(menuLinkCurrentWeek))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val jobTTCurrentWeek = doAsync {
 | 
			
		||||
                try {
 | 
			
		||||
                    cTimeTableCurrentWeek = timeTableParser.getTimeTable(cCourse.courseLink)
 | 
			
		||||
                    timeTableParser.printTimeTableWeek(cTimeTableCurrentWeek)
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
 | 
			
		||||
                    uiThread {
 | 
			
		||||
                        MaterialDialog(this@MainActivity)
 | 
			
		||||
                            .title(R.string.error)
 | 
			
		||||
                            .message(R.string.no_tt_error)
 | 
			
		||||
                            .show()
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    e.stackTrace
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val jobTTNextWeek = doAsync {
 | 
			
		||||
                try {
 | 
			
		||||
                    cTimeTableNextWeek = timeTableParser.getTimeTable(cCourse.courseLink.replace("week=0","week=1"))
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    e.stackTrace
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            jobMenusCurrentWeek.get()
 | 
			
		||||
            jobMenusNextWeek.get()
 | 
			
		||||
            jobTTCurrentWeek.get()
 | 
			
		||||
            jobTTNextWeek.get()
 | 
			
		||||
        }
 | 
			
		||||
        println("Completed in $time ms")
 | 
			
		||||
        println("Completed in $startupTime ms")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,122 @@
 | 
			
		||||
/**
 | 
			
		||||
 * ProjectLaogai
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2019  <seil0@mosad.xyz>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | 
			
		||||
 * MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.mosad.seil0.projectlaogai.controller
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import com.google.gson.Gson
 | 
			
		||||
import com.google.gson.JsonParser
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.Course
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.MensaWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.TimetableWeek
 | 
			
		||||
import java.io.BufferedReader
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.io.FileReader
 | 
			
		||||
import com.google.gson.reflect.TypeToken
 | 
			
		||||
 | 
			
		||||
class CacheController(cont: Context) {
 | 
			
		||||
 | 
			
		||||
    private val context = cont
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        var coursesList = ArrayList<Course>()
 | 
			
		||||
        var mensaCurrentWeek = MensaWeek()
 | 
			
		||||
        var mensaNextWeek = MensaWeek()
 | 
			
		||||
        var timetables = ArrayList<TimetableWeek>()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * read coursesList, mensa (current and next week), timetable (current and next week)
 | 
			
		||||
     * @param courseName the course name (e.g AI1)
 | 
			
		||||
     */
 | 
			
		||||
    fun readStartCache(courseName: String) {
 | 
			
		||||
        readCoursesList()
 | 
			
		||||
        readMensa()
 | 
			
		||||
        readTimetable(courseName, 0)
 | 
			
		||||
        readTimetable(courseName, 1)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * read the courses list from the cached file
 | 
			
		||||
     * add them to the coursesList object
 | 
			
		||||
     */
 | 
			
		||||
    fun readCoursesList() {
 | 
			
		||||
        val file = File(context.filesDir, "courses.json")
 | 
			
		||||
 | 
			
		||||
        // make sure the file exists
 | 
			
		||||
        if (!file.exists())
 | 
			
		||||
            TCoRAPIController(context).getCoursesList().get()
 | 
			
		||||
 | 
			
		||||
        val fileReader = FileReader(file)
 | 
			
		||||
        val bufferedReader = BufferedReader(fileReader)
 | 
			
		||||
        val coursesObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject
 | 
			
		||||
 | 
			
		||||
        coursesList = Gson().fromJson(coursesObject.getAsJsonArray("courses"), object : TypeToken<List<Course>>() {}.type)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * read current and next weeks mensa menus from the cached file
 | 
			
		||||
     */
 | 
			
		||||
    fun readMensa() {
 | 
			
		||||
        val file = File(context.filesDir, "mensa.json")
 | 
			
		||||
 | 
			
		||||
        // make sure the file exists
 | 
			
		||||
        if (!file.exists()) {
 | 
			
		||||
            TCoRAPIController(context).getMensa().get()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        val fileReader = FileReader(file)
 | 
			
		||||
        val bufferedReader = BufferedReader(fileReader)
 | 
			
		||||
        val mensaObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject
 | 
			
		||||
 | 
			
		||||
        val currentWeek = mensaObject.getAsJsonObject("currentWeek")
 | 
			
		||||
        val nextWeek = mensaObject.getAsJsonObject("nextWeek")
 | 
			
		||||
 | 
			
		||||
        mensaCurrentWeek = Gson().fromJson(currentWeek, MensaWeek().javaClass)
 | 
			
		||||
        mensaNextWeek = Gson().fromJson(nextWeek, MensaWeek().javaClass)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * read the weeks timetable from the cached file
 | 
			
		||||
     * @param courseName the course name (e.g AI1)
 | 
			
		||||
     * @param week the week to read (0 for the current and so on)
 | 
			
		||||
     */
 | 
			
		||||
    fun readTimetable(courseName: String, week: Int) {
 | 
			
		||||
        val file = File(context.filesDir, "timetable-$courseName-$week.json")
 | 
			
		||||
 | 
			
		||||
        // make sure the file exists
 | 
			
		||||
        if (!file.exists())
 | 
			
		||||
            TCoRAPIController(context).getTimetable(courseName, week).get()
 | 
			
		||||
 | 
			
		||||
        val fileReader = FileReader(file)
 | 
			
		||||
        val bufferedReader = BufferedReader(fileReader)
 | 
			
		||||
        val timetableObject = JsonParser().parse(bufferedReader.readLine()).asJsonObject
 | 
			
		||||
 | 
			
		||||
        // make sure you add the single weeks in the exact order!
 | 
			
		||||
        if (timetables.size == week) {
 | 
			
		||||
            timetables.add(Gson().fromJson(timetableObject.getAsJsonObject("timetable"), TimetableWeek().javaClass))
 | 
			
		||||
        } else if (timetables.size >= week) {
 | 
			
		||||
            timetables[week] = Gson().fromJson(timetableObject.getAsJsonObject("timetable"), TimetableWeek().javaClass)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -20,14 +20,13 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.mosad.seil0.projectlaogai
 | 
			
		||||
package org.mosad.seil0.projectlaogai.controller
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.graphics.Color
 | 
			
		||||
import org.jetbrains.anko.defaultSharedPreferences
 | 
			
		||||
import org.mosad.seil0.projectlaogai.R
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.Course
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.MealWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.TimeTable
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The PreferencesController class
 | 
			
		||||
@ -36,11 +35,9 @@ import org.mosad.seil0.projectlaogai.hsoparser.TimeTable
 | 
			
		||||
class PreferencesController {
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        var cCourseTTLinkList = ArrayList<Course>()
 | 
			
		||||
        var cMenusCurrentWeek = MealWeek()
 | 
			
		||||
        var cMenusNextWeek = MealWeek()
 | 
			
		||||
        var cTimeTableCurrentWeek = TimeTable()
 | 
			
		||||
        var cTimeTableNextWeek = TimeTable()
 | 
			
		||||
        var coursesCacheTime: Long = 0
 | 
			
		||||
        var mensaCacheTime: Long = 0
 | 
			
		||||
        var timetableCacheTime: Long = 0
 | 
			
		||||
        var cColorPrimary: Int = Color.BLACK
 | 
			
		||||
        var cColorAccent: Int = Color.BLACK
 | 
			
		||||
        var cCourse = Course("https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0", "AI3")
 | 
			
		||||
@ -48,9 +45,23 @@ class PreferencesController {
 | 
			
		||||
 | 
			
		||||
        // the save function
 | 
			
		||||
        fun save(context: Context) {
 | 
			
		||||
            //println(cCourse.courseLink)
 | 
			
		||||
            // save the course
 | 
			
		||||
            val sharedPref = context.defaultSharedPreferences
 | 
			
		||||
 | 
			
		||||
            // save the update times (cache)
 | 
			
		||||
            with (sharedPref.edit()) {
 | 
			
		||||
                putLong(context.getString(R.string.save_key_coursesCacheTime),
 | 
			
		||||
                    coursesCacheTime
 | 
			
		||||
                )
 | 
			
		||||
                putLong(context.getString(R.string.save_key_mensaCacheTime),
 | 
			
		||||
                    mensaCacheTime
 | 
			
		||||
                )
 | 
			
		||||
                putLong(context.getString(R.string.save_key_timetableCacheTime),
 | 
			
		||||
                    timetableCacheTime
 | 
			
		||||
                )
 | 
			
		||||
                apply()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // save the course
 | 
			
		||||
            with (sharedPref.edit()) {
 | 
			
		||||
                putString(context.getString(R.string.save_key_course), cCourse.courseName)
 | 
			
		||||
                putString(context.getString(R.string.save_key_courseTTLink), cCourse.courseLink)
 | 
			
		||||
@ -59,19 +70,25 @@ class PreferencesController {
 | 
			
		||||
 | 
			
		||||
            // save the primary color
 | 
			
		||||
            with (sharedPref.edit()) {
 | 
			
		||||
                putInt(context.getString(R.string.save_key_colorPrimary), cColorPrimary)
 | 
			
		||||
                putInt(context.getString(R.string.save_key_colorPrimary),
 | 
			
		||||
                    cColorPrimary
 | 
			
		||||
                )
 | 
			
		||||
                apply()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // save the accent color
 | 
			
		||||
            with (sharedPref.edit()) {
 | 
			
		||||
                putInt(context.getString(R.string.save_key_colorAccent), cColorAccent)
 | 
			
		||||
                putInt(context.getString(R.string.save_key_colorAccent),
 | 
			
		||||
                    cColorAccent
 | 
			
		||||
                )
 | 
			
		||||
                apply()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // save showBuffet
 | 
			
		||||
            with (sharedPref.edit()) {
 | 
			
		||||
                putBoolean(context.getString(R.string.save_key_showBuffet), cShowBuffet)
 | 
			
		||||
                putBoolean(context.getString(R.string.save_key_showBuffet),
 | 
			
		||||
                    cShowBuffet
 | 
			
		||||
                )
 | 
			
		||||
                apply()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -79,19 +96,37 @@ class PreferencesController {
 | 
			
		||||
 | 
			
		||||
        // the load function
 | 
			
		||||
        fun load(context: Context) {
 | 
			
		||||
            // load saved course
 | 
			
		||||
            val sharedPref = context.defaultSharedPreferences
 | 
			
		||||
 | 
			
		||||
            // load the update times (cache)
 | 
			
		||||
            coursesCacheTime = sharedPref.getLong(context.getString(
 | 
			
		||||
                R.string.save_key_coursesCacheTime
 | 
			
		||||
            ), 0)
 | 
			
		||||
            mensaCacheTime = sharedPref.getLong(context.getString(
 | 
			
		||||
                R.string.save_key_mensaCacheTime
 | 
			
		||||
            ), 0)
 | 
			
		||||
            timetableCacheTime = sharedPref.getLong(context.getString(
 | 
			
		||||
                R.string.save_key_timetableCacheTime
 | 
			
		||||
            ), 0)
 | 
			
		||||
 | 
			
		||||
            // load saved course
 | 
			
		||||
            cCourse = Course(
 | 
			
		||||
                sharedPref.getString(context.getString(R.string.save_key_courseTTLink), "https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0")!!,
 | 
			
		||||
                sharedPref.getString(context.getString(R.string.save_key_course), "AI3")!!
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            // load saved colors
 | 
			
		||||
            cColorPrimary = sharedPref.getInt(context.getString(R.string.save_key_colorPrimary), Color.BLACK)
 | 
			
		||||
            cColorAccent = sharedPref.getInt(context.getString(R.string.save_key_colorAccent), Color.parseColor("#FF1744"))
 | 
			
		||||
            cColorPrimary = sharedPref.getInt(context.getString(
 | 
			
		||||
                R.string.save_key_colorPrimary
 | 
			
		||||
            ), Color.BLACK)
 | 
			
		||||
            cColorAccent = sharedPref.getInt(context.getString(
 | 
			
		||||
                R.string.save_key_colorAccent
 | 
			
		||||
            ), Color.parseColor("#FF1744"))
 | 
			
		||||
 | 
			
		||||
            // load showBuffet
 | 
			
		||||
            cShowBuffet = sharedPref.getBoolean(context.getString(R.string.save_key_showBuffet), true)
 | 
			
		||||
            cShowBuffet = sharedPref.getBoolean(context.getString(
 | 
			
		||||
                R.string.save_key_showBuffet
 | 
			
		||||
            ), true)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,96 @@
 | 
			
		||||
/**
 | 
			
		||||
 * ProjectLaogai
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2019  <seil0@mosad.xyz>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | 
			
		||||
 * MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.mosad.seil0.projectlaogai.controller
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import org.jetbrains.anko.doAsync
 | 
			
		||||
import org.json.JSONObject
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.coursesCacheTime
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.mensaCacheTime
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.timetableCacheTime
 | 
			
		||||
import java.io.*
 | 
			
		||||
import java.net.URL
 | 
			
		||||
 | 
			
		||||
class TCoRAPIController(cont: Context) {
 | 
			
		||||
    private val context = cont
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get the json object from tcor api and write it as file (cache)
 | 
			
		||||
     */
 | 
			
		||||
    fun getCoursesList() = doAsync {
 | 
			
		||||
        val url = URL("https://tcor.mosad.xyz/courses")
 | 
			
		||||
        val file = File(context.filesDir, "courses.json")
 | 
			
		||||
 | 
			
		||||
        // read data from the API
 | 
			
		||||
        val coursesObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
 | 
			
		||||
 | 
			
		||||
        // write the json object to a file
 | 
			
		||||
        val writer = BufferedWriter(FileWriter(file))
 | 
			
		||||
        writer.write(coursesObject.toString())
 | 
			
		||||
        writer.close()
 | 
			
		||||
 | 
			
		||||
        // update cache time
 | 
			
		||||
        coursesCacheTime = System.currentTimeMillis() / 1000
 | 
			
		||||
        PreferencesController.save(context)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get the json object from tcor api and write it as file (cache)
 | 
			
		||||
     */
 | 
			
		||||
    fun getMensa() = doAsync {
 | 
			
		||||
        val url = URL("https://tcor.mosad.xyz/mensamenu")
 | 
			
		||||
        val file = File(context.filesDir, "mensa.json")
 | 
			
		||||
 | 
			
		||||
        // read data from the API
 | 
			
		||||
        val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
 | 
			
		||||
 | 
			
		||||
        // write the json object to a file
 | 
			
		||||
        val writer = BufferedWriter(FileWriter(file))
 | 
			
		||||
        writer.write(mensaObject.toString())
 | 
			
		||||
        writer.close()
 | 
			
		||||
 | 
			
		||||
        // update cache time
 | 
			
		||||
        mensaCacheTime = System.currentTimeMillis() / 1000
 | 
			
		||||
        PreferencesController.save(context)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get the json object from tcor api and write it as file (cache)
 | 
			
		||||
     */
 | 
			
		||||
    fun getTimetable(courseName: String, week: Int) = doAsync {
 | 
			
		||||
        val url = URL("https://tcor.mosad.xyz/timetable?courseName=$courseName&week=$week")
 | 
			
		||||
        val file = File(context.filesDir, "timetable-$courseName-$week.json")
 | 
			
		||||
 | 
			
		||||
        // read data from the API
 | 
			
		||||
        val mensaObject = JSONObject(url.readText()) //JSONObject(inReader.readLine())
 | 
			
		||||
 | 
			
		||||
        // write the json object to a file
 | 
			
		||||
        val writer = BufferedWriter(FileWriter(file))
 | 
			
		||||
        writer.write(mensaObject.toString())
 | 
			
		||||
        writer.close()
 | 
			
		||||
 | 
			
		||||
        // update cache time
 | 
			
		||||
        timetableCacheTime = System.currentTimeMillis() / 1000
 | 
			
		||||
        PreferencesController.save(context)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -32,10 +32,12 @@ import com.afollestad.materialdialogs.MaterialDialog
 | 
			
		||||
import kotlinx.android.synthetic.main.fragment_home.*
 | 
			
		||||
import org.jetbrains.anko.doAsync
 | 
			
		||||
import org.jetbrains.anko.uiThread
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableCurrentWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cMenusCurrentWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.R
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.*
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaCurrentWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.DataTypes
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.Meal
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.NotRetardedCalendar
 | 
			
		||||
import org.mosad.seil0.projectlaogai.uicomponents.LessonCardView
 | 
			
		||||
import org.mosad.seil0.projectlaogai.uicomponents.LessonTextView
 | 
			
		||||
import java.util.*
 | 
			
		||||
@ -68,14 +70,14 @@ class HomeFragment : Fragment() {
 | 
			
		||||
     */
 | 
			
		||||
    private fun addCurrentMensaMenu() {
 | 
			
		||||
        doAsync {
 | 
			
		||||
            val dayMenus: ArrayList<Meal>
 | 
			
		||||
            val dayMeals: ArrayList<Meal>
 | 
			
		||||
            val cal = Calendar.getInstance()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (cal.get(Calendar.HOUR_OF_DAY) < 15) {
 | 
			
		||||
                dayMenus = cMenusCurrentWeek.day[NotRetardedCalendar().getDayOfWeekIndex()]
 | 
			
		||||
                dayMeals = mensaCurrentWeek.days[NotRetardedCalendar().getDayOfWeekIndex()].meals
 | 
			
		||||
            } else {
 | 
			
		||||
                dayMenus = cMenusCurrentWeek.day[NotRetardedCalendar().getTomorrowWeekIndex()]
 | 
			
		||||
                dayMeals = mensaCurrentWeek.days[NotRetardedCalendar().getTomorrowWeekIndex()].meals
 | 
			
		||||
                uiThread {
 | 
			
		||||
                    txtView_Menu1Heading.text = resources.getString(R.string.meal_1_tomorrow)
 | 
			
		||||
                    txtView_Menu2Heading.text = resources.getString(R.string.meal_2_tomorrow)
 | 
			
		||||
@ -84,19 +86,19 @@ class HomeFragment : Fragment() {
 | 
			
		||||
 | 
			
		||||
            uiThread {
 | 
			
		||||
 | 
			
		||||
                if (dayMenus.size >= 2) {
 | 
			
		||||
                if (dayMeals.size >= 2) {
 | 
			
		||||
                    // get the index of the first meal, not a "Schneller Teller"
 | 
			
		||||
                    loop@ for ((i, meal) in dayMenus.withIndex()) {
 | 
			
		||||
                    loop@ for ((i, meal) in dayMeals.withIndex()) {
 | 
			
		||||
                        if (meal.heading.contains("Essen")) {
 | 
			
		||||
                            for ((j, part) in dayMenus[i].parts.withIndex()) {
 | 
			
		||||
                            for ((j, part) in dayMeals[i].parts.withIndex()) {
 | 
			
		||||
                                txtViewMenu1.append(part)
 | 
			
		||||
                                if (j < (dayMenus[i].parts.size - 2))
 | 
			
		||||
                                if (j < (dayMeals[i].parts.size - 2))
 | 
			
		||||
                                    txtViewMenu1.append("\n")
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            for ((j, part) in dayMenus[i + 1].parts.withIndex()) {
 | 
			
		||||
                            for ((j, part) in dayMeals[i + 1].parts.withIndex()) {
 | 
			
		||||
                                txtViewMenu2.append(part)
 | 
			
		||||
                                if (j < (dayMenus[i + 1].parts.size - 2))
 | 
			
		||||
                                if (j < (dayMeals[i + 1].parts.size - 2))
 | 
			
		||||
                                    txtViewMenu2.append("\n")
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
@ -124,9 +126,9 @@ class HomeFragment : Fragment() {
 | 
			
		||||
    private fun addCurrentTimeTable() {
 | 
			
		||||
        val dayIndex = NotRetardedCalendar().getDayOfWeekIndex()
 | 
			
		||||
 | 
			
		||||
        if (cTimeTableCurrentWeek.days.isNotEmpty() && dayIndex < 6) {
 | 
			
		||||
        if (timetables[0].days.isNotEmpty() && dayIndex < 6) {
 | 
			
		||||
 | 
			
		||||
            val timeTableDay = cTimeTableCurrentWeek.days[dayIndex]
 | 
			
		||||
            val timeTableDay = timetables[0].days[dayIndex]
 | 
			
		||||
 | 
			
		||||
            // for all timeslots of the day
 | 
			
		||||
            for ((i, timeslot) in timeTableDay.timeslots.withIndex()) {
 | 
			
		||||
 | 
			
		||||
@ -23,18 +23,18 @@
 | 
			
		||||
package org.mosad.seil0.projectlaogai.fragments
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import android.widget.LinearLayout
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import org.jetbrains.anko.doAsync
 | 
			
		||||
import org.jetbrains.anko.uiThread
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cMenusCurrentWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cMenusNextWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cShowBuffet
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cShowBuffet
 | 
			
		||||
import org.mosad.seil0.projectlaogai.R
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.MealWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaCurrentWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.mensaNextWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.MensaWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.NotRetardedCalendar
 | 
			
		||||
import org.mosad.seil0.projectlaogai.uicomponents.MensaDayCardView
 | 
			
		||||
import org.mosad.seil0.projectlaogai.uicomponents.MenuCardView
 | 
			
		||||
@ -55,10 +55,10 @@ class MensaFragment : Fragment() {
 | 
			
		||||
 | 
			
		||||
        // add the current week (week starts on sunday)
 | 
			
		||||
        val dayCurrent =  if(NotRetardedCalendar().getDayOfWeekIndex() == 6) 0 else NotRetardedCalendar().getDayOfWeekIndex()
 | 
			
		||||
        addWeek(cMenusCurrentWeek, dayCurrent)
 | 
			
		||||
        addWeek(mensaCurrentWeek, dayCurrent)
 | 
			
		||||
 | 
			
		||||
        // add the next week
 | 
			
		||||
        addWeek(cMenusNextWeek, 0)
 | 
			
		||||
        addWeek(mensaNextWeek, 0)
 | 
			
		||||
 | 
			
		||||
        return view
 | 
			
		||||
    }
 | 
			
		||||
@ -66,7 +66,7 @@ class MensaFragment : Fragment() {
 | 
			
		||||
    /**
 | 
			
		||||
     * add all menus from dayStart to Friday for a given week
 | 
			
		||||
     */
 | 
			
		||||
    private fun addWeek(menusWeek: MealWeek, dayStart: Int) {
 | 
			
		||||
    private fun addWeek(menusWeek: MensaWeek, dayStart: Int) {
 | 
			
		||||
 | 
			
		||||
        doAsync {
 | 
			
		||||
 | 
			
		||||
@ -76,7 +76,7 @@ class MensaFragment : Fragment() {
 | 
			
		||||
 | 
			
		||||
                    val cardViewMensaDay = MensaDayCardView(context!!, null)
 | 
			
		||||
 | 
			
		||||
                    for (meal in menusWeek.day[dayIndex]) {
 | 
			
		||||
                    for (meal in menusWeek.days[dayIndex].meals) {
 | 
			
		||||
                        val menuViewMenu = MenuCardView(context!!, null)
 | 
			
		||||
                        menuViewMenu.setMenuHeading(meal.heading)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -37,17 +37,16 @@ import com.afollestad.materialdialogs.list.listItems
 | 
			
		||||
import kotlinx.android.synthetic.main.fragment_settings.*
 | 
			
		||||
import org.jetbrains.anko.doAsync
 | 
			
		||||
import org.jetbrains.anko.uiThread
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cColorPrimary
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cColorAccent
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cCourse
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cCourseTTLinkList
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cShowBuffet
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableCurrentWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableNextWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorAccent
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorPrimary
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cShowBuffet
 | 
			
		||||
import org.mosad.seil0.projectlaogai.R
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.CacheController
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.coursesList
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.DataTypes
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.TimeTableParser
 | 
			
		||||
import java.util.*
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -97,13 +96,13 @@ class SettingsFragment : Fragment() {
 | 
			
		||||
 | 
			
		||||
        linLayoutCourse.setOnClickListener {
 | 
			
		||||
            // open a new dialog
 | 
			
		||||
            val courseList = ArrayList<String>()
 | 
			
		||||
            val courseNameList = ArrayList<String>()
 | 
			
		||||
 | 
			
		||||
            cCourseTTLinkList.forEach { (_, course) ->
 | 
			
		||||
                courseList.add(course)
 | 
			
		||||
            coursesList.forEach { (_, courseName) ->
 | 
			
		||||
                courseNameList.add(courseName)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            MaterialDialog(context!!).listItems(items = courseList) { _, index, text ->
 | 
			
		||||
            MaterialDialog(context!!).listItems(items = courseNameList) { _, index, text ->
 | 
			
		||||
                txtView_Course.text = text // update txtView
 | 
			
		||||
 | 
			
		||||
                val dialog = MaterialDialog(context!!).cancelable(false)
 | 
			
		||||
@ -112,12 +111,15 @@ class SettingsFragment : Fragment() {
 | 
			
		||||
                dialog.show()
 | 
			
		||||
 | 
			
		||||
                doAsync {
 | 
			
		||||
                    cCourse = cCourseTTLinkList[index] // set the course
 | 
			
		||||
                    cCourse = coursesList[index] // set the course
 | 
			
		||||
                    PreferencesController.save(context!!)
 | 
			
		||||
 | 
			
		||||
                    // update current & next weeks timetable
 | 
			
		||||
                    cTimeTableCurrentWeek = TimeTableParser().getTimeTable(cCourse.courseLink)
 | 
			
		||||
                    cTimeTableNextWeek = TimeTableParser().getTimeTable(cCourse.courseLink.replace("week=0","week=1"))
 | 
			
		||||
                    TCoRAPIController(context!!).getTimetable(cCourse.courseName, 0)
 | 
			
		||||
                    TCoRAPIController(context!!).getTimetable(cCourse.courseName, 1)
 | 
			
		||||
 | 
			
		||||
                    CacheController(context!!).readTimetable(cCourse.courseName, 0)
 | 
			
		||||
                    CacheController(context!!).readTimetable(cCourse.courseName, 1)
 | 
			
		||||
 | 
			
		||||
                    uiThread {
 | 
			
		||||
                        dialog.dismiss()
 | 
			
		||||
 | 
			
		||||
@ -30,9 +30,8 @@ import android.widget.LinearLayout
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import org.jetbrains.anko.doAsync
 | 
			
		||||
import org.jetbrains.anko.uiThread
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableCurrentWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.PreferencesController.Companion.cTimeTableNextWeek
 | 
			
		||||
import org.mosad.seil0.projectlaogai.R
 | 
			
		||||
import org.mosad.seil0.projectlaogai.controller.CacheController.Companion.timetables
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.DataTypes
 | 
			
		||||
import org.mosad.seil0.projectlaogai.hsoparser.NotRetardedCalendar
 | 
			
		||||
import org.mosad.seil0.projectlaogai.uicomponents.LessonCardView
 | 
			
		||||
@ -55,7 +54,7 @@ class TimeTableFragment : Fragment() {
 | 
			
		||||
 | 
			
		||||
        linLayoutTTFragment = view.findViewById(R.id.linLayout_TTFragment)
 | 
			
		||||
 | 
			
		||||
        if (cTimeTableCurrentWeek.days.isNotEmpty()) {
 | 
			
		||||
        if (timetables[0].days.isNotEmpty()) {
 | 
			
		||||
            addCurrentWeek()
 | 
			
		||||
        } else {
 | 
			
		||||
            // TODO show card with error msg
 | 
			
		||||
@ -82,7 +81,7 @@ class TimeTableFragment : Fragment() {
 | 
			
		||||
                    cardViewTimeTableDay.setDayHeading(formatter.format(calendar.time))
 | 
			
		||||
 | 
			
		||||
                    // for each timeslot of the day
 | 
			
		||||
                    for ((i, timeslot) in cTimeTableCurrentWeek.days[day].timeslots.withIndex()) {
 | 
			
		||||
                    for ((i, timeslot) in timetables[0].days[day].timeslots.withIndex()) {
 | 
			
		||||
                        val lessonCardView = LessonCardView(context!!, null)
 | 
			
		||||
                        lessonCardView.getTxtViewTime().text = DataTypes().getTime()[i]
 | 
			
		||||
 | 
			
		||||
@ -119,7 +118,7 @@ class TimeTableFragment : Fragment() {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // add next weeks days, max number  = dayIndex, if timetable was loaded
 | 
			
		||||
                if (cTimeTableNextWeek.days.isNotEmpty()) {
 | 
			
		||||
                if (timetables[1].days.isNotEmpty()) {
 | 
			
		||||
                    calendar.add(Calendar.DATE, 1) // before this we are at a sunday (no lecture on sundays!)
 | 
			
		||||
 | 
			
		||||
                    for (day in 0..(dayIndex - 1)) {
 | 
			
		||||
@ -128,7 +127,7 @@ class TimeTableFragment : Fragment() {
 | 
			
		||||
                        cardViewTimeTableDay.setDayHeading(formatter.format(calendar.time))
 | 
			
		||||
 | 
			
		||||
                        // for each timeslot of the day
 | 
			
		||||
                        for ((i, timeslot) in cTimeTableNextWeek.days[day].timeslots.withIndex()) {
 | 
			
		||||
                        for ((i, timeslot) in timetables[1].days[day].timeslots.withIndex()) {
 | 
			
		||||
                            val lessonCardView = LessonCardView(context!!, null)
 | 
			
		||||
                            lessonCardView.getTxtViewTime().text = DataTypes().getTime()[i]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -115,10 +115,16 @@ data class Course(val courseLink: String, val courseName: String)
 | 
			
		||||
 | 
			
		||||
data class Meal(val day: String, val heading: String, val parts: ArrayList<String>, val additives: String)
 | 
			
		||||
 | 
			
		||||
data class MealWeek(val day: Array<ArrayList<Meal>> = Array(7) { ArrayList<Meal>() })
 | 
			
		||||
data class Meals(val meals: ArrayList<Meal>)
 | 
			
		||||
 | 
			
		||||
data class MensaWeek(val days: Array<Meals> = Array(7) { Meals(ArrayList()) })
 | 
			
		||||
 | 
			
		||||
data class MealWeek(val day: Array<ArrayList<Meal>> = Array(7) { ArrayList<Meal>() }) // TODO remove
 | 
			
		||||
 | 
			
		||||
data class Lesson(val lessonSubject: String, val lessonTeacher: String, val lessonRoom:String, val lessonRemark: String)
 | 
			
		||||
 | 
			
		||||
data class TimeTableDay( val timeslots: Array<ArrayList<Lesson>> = Array(6) { ArrayList<Lesson>()})
 | 
			
		||||
data class TimetableDay( val timeslots: Array<ArrayList<Lesson>> = Array(6) { ArrayList<Lesson>()})
 | 
			
		||||
 | 
			
		||||
data class TimeTable(val days: Array<TimeTableDay> = Array(6) { TimeTableDay() })
 | 
			
		||||
data class TimetableWeek(val days: Array<TimetableDay> = Array(6) { TimetableDay() })
 | 
			
		||||
 | 
			
		||||
data class TimeTable(val days: Array<TimetableDay> = Array(6) { TimetableDay() }) // TODO remove
 | 
			
		||||
@ -1,78 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * ProjectLaogai
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2019  <seil0@mosad.xyz>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | 
			
		||||
 * MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.mosad.seil0.projectlaogai.hsoparser
 | 
			
		||||
 | 
			
		||||
import org.jsoup.Jsoup
 | 
			
		||||
import java.util.*
 | 
			
		||||
import kotlin.collections.ArrayList
 | 
			
		||||
 | 
			
		||||
class MensaParser {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * returns the mensa menu for the a week
 | 
			
		||||
     */
 | 
			
		||||
    fun getMensaMenu(menuLink: String): MealWeek {
 | 
			
		||||
        val mealList = ArrayList<Meal>()
 | 
			
		||||
        val mealWeekList = MealWeek()
 | 
			
		||||
        val menuHTML = Jsoup.connect(menuLink).get()
 | 
			
		||||
 | 
			
		||||
        menuHTML.select("#speiseplan-tabs").select("div.tab-content").select("div.menu-tagesplan").forEachIndexed { dayIndex, day ->
 | 
			
		||||
            val strDay = day.select("h3").text()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            day.select("div.menu-info").forEachIndexed { mealIndex, meal ->
 | 
			
		||||
                val heading = day.select("h4")[mealIndex].text()
 | 
			
		||||
                val parts = ArrayList(meal.html().substringBefore("<br>\n").replace("<br>", " ").split("\n"))
 | 
			
		||||
                val additives = meal.select("span.show-with-allergenes").text()
 | 
			
		||||
 | 
			
		||||
                mealWeekList.day[dayIndex].add(Meal(strDay, heading, parts, additives))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (i in 0 .. (day.select("div.row  h4").size - 1)) {
 | 
			
		||||
                try {
 | 
			
		||||
                    val heading = day.select("div.row  h4")[i].text()
 | 
			
		||||
                    val parts = ArrayList<String>(day.select("div.row").select("div.menu-info")[i].html().substringBefore("<span").replace("<br>", " ").split("\n"))
 | 
			
		||||
                    val additives = day.select("div.row").select("div.menu-info")[i].select("span.show-with-allergenes").text()
 | 
			
		||||
 | 
			
		||||
                    mealList.add(Meal(strDay, heading, parts, additives))
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    //println("Oooups! Something went wrong: ${e.printStackTrace()}")
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Mon to Sat (0 - 5)
 | 
			
		||||
        //println(mealWeekList.day[4])
 | 
			
		||||
 | 
			
		||||
        return  mealWeekList
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * return the link of the menus of the next week
 | 
			
		||||
     */
 | 
			
		||||
    fun getMenuLinkNextWeek(menuLink: String): String {
 | 
			
		||||
        val menuHTML = Jsoup.connect(menuLink).get()
 | 
			
		||||
 | 
			
		||||
        return "https://www.swfr.de" + menuHTML.select("#speiseplan-tabs").select("a.next-week").attr("href")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,146 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * ProjectLaogai
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2019  <seil0@mosad.xyz>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | 
			
		||||
 * MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.mosad.seil0.projectlaogai.hsoparser
 | 
			
		||||
 | 
			
		||||
import org.jsoup.Jsoup
 | 
			
		||||
 | 
			
		||||
class TimeTableParser {
 | 
			
		||||
    private val days = arrayOf("Monday", "Tuesday" ,"Wednesday", "Thursday", "Friday", "Saturday")
 | 
			
		||||
    private var courseTTLinkList = ArrayList<Course>()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get the timetable from the given url
 | 
			
		||||
     * 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 getTimeTable(courseTTURL: String): TimeTable {
 | 
			
		||||
        var timeTableWeek = TimeTable() // this must be a var!
 | 
			
		||||
        val scheduleHTML = Jsoup.connect(courseTTURL).get()
 | 
			
		||||
 | 
			
		||||
        //val week = scheduleHTML.select("h1.timetable-caption").text()
 | 
			
		||||
        //println("$week successful!\n")
 | 
			
		||||
 | 
			
		||||
        val rows= scheduleHTML.select("table.timetable").select("tr[scope=\"row\"]")
 | 
			
		||||
        var sDay = -1
 | 
			
		||||
        var sRow = -1
 | 
			
		||||
        var sLesson = Lesson("", "", "", "")
 | 
			
		||||
 | 
			
		||||
        // get each row with index, reflects 1 timeslot per day
 | 
			
		||||
        for ((rowIndex, row) in rows.withIndex()) {
 | 
			
		||||
            var day = 0
 | 
			
		||||
 | 
			
		||||
            // elements are now all lessons, including empty ones
 | 
			
		||||
            row.select("td.lastcol, td[style]").forEach { element ->
 | 
			
		||||
 | 
			
		||||
                // if there is a lecture with rowspan="2", we need to shift everything by one to the left. This is stupid and ugly there needs to bee an API
 | 
			
		||||
                if ((sDay > -1 && sRow > -1) && (sDay == day && ((sRow + 1) == rowIndex))) {
 | 
			
		||||
                    // we found a lecture that is longer than 1 lesson
 | 
			
		||||
                    timeTableWeek.days[day].timeslots[rowIndex].add(sLesson) // this just works if there is one lecture per slot
 | 
			
		||||
 | 
			
		||||
                    // adjust the following slot
 | 
			
		||||
                    sDay++
 | 
			
		||||
                    sLesson = Lesson(element.select("div.lesson-subject").text(), element.select("div.lesson-teacher").text(), element.select("div.lesson-room").text(), element.select("div.lesson-remark").text())
 | 
			
		||||
 | 
			
		||||
                    // adjust the slot directly as we don't get there anymore
 | 
			
		||||
                    if(sDay == 5) {
 | 
			
		||||
                        timeTableWeek.days[day + 1].timeslots[rowIndex].add(sLesson)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                } else {
 | 
			
		||||
                    timeTableWeek.days[day].timeslots[rowIndex].add(Lesson(element.select("div.lesson-subject").text(), element.select("div.lesson-teacher").text(), element.select("div.lesson-room").text(), element.select("div.lesson-remark").text()))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // we found a lecture with rowspan="2", save day, row and lesson for later adjustment
 | 
			
		||||
                if(element.toString().contains("rowspan=\"2\"")) {
 | 
			
		||||
                    sDay = day
 | 
			
		||||
                    sRow = rowIndex
 | 
			
		||||
                    sLesson = timeTableWeek.days[day].timeslots[rowIndex].get(index = 0)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if(element.hasClass("lastcol")) day++
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        printTimeTableWeek(timeTableWeek)
 | 
			
		||||
 | 
			
		||||
        return timeTableWeek
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * parse all courses from the courses site at https://www.hs-offenburg.de/studium/vorlesungsplaene/
 | 
			
		||||
     */
 | 
			
		||||
    fun getCourseTTLinks(): ArrayList<Course> {
 | 
			
		||||
        val courseHTML = Jsoup.connect("https://www.hs-offenburg.de/studium/vorlesungsplaene/").get()
 | 
			
		||||
 | 
			
		||||
        courseHTML.select("ul.index-group").select("li.Class").select("a[href]").forEachIndexed { _, element ->
 | 
			
		||||
            courseTTLinkList.add(Course(element.attr("href").replace("http", "https"),element.text()))
 | 
			
		||||
        }
 | 
			
		||||
        return courseTTLinkList
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Suppress("unused")
 | 
			
		||||
    fun printTimeTableWeek(timetable: TimeTable) {
 | 
			
		||||
        for (j in 0..5) print(days[j].padEnd(75 ,' ') + " | ")
 | 
			
		||||
        println()
 | 
			
		||||
        for (j in 0..5) print("-".padEnd(76 + (j.toFloat().div(j).toInt()), '-') + "+")
 | 
			
		||||
        println()
 | 
			
		||||
 | 
			
		||||
        // the timeslot
 | 
			
		||||
        for (i in 0..5) {
 | 
			
		||||
 | 
			
		||||
            for (j in 0..5) {
 | 
			
		||||
                val ldiff = if (timetable.days[j].timeslots[i].size == 0) 1 else timetable.days[j].timeslots[i].size
 | 
			
		||||
 | 
			
		||||
                for (lesson in timetable.days[j].timeslots[i]) print(lesson.lessonSubject.padEnd(75/ldiff ,' '))
 | 
			
		||||
                if (ldiff == 2) print(" ")
 | 
			
		||||
                print(" | ")
 | 
			
		||||
            }
 | 
			
		||||
            println()
 | 
			
		||||
 | 
			
		||||
            for (j in 0..5) {
 | 
			
		||||
                val ldiff = if (timetable.days[j].timeslots[i].size == 0) 1 else timetable.days[j].timeslots[i].size
 | 
			
		||||
 | 
			
		||||
                for (lesson in timetable.days[j].timeslots[i]) print(lesson.lessonTeacher.padEnd(75/ldiff ,' '))
 | 
			
		||||
                if (ldiff == 2) print(" ")
 | 
			
		||||
                print(" | ")
 | 
			
		||||
            }
 | 
			
		||||
            println()
 | 
			
		||||
 | 
			
		||||
            for (j in 0..5) {
 | 
			
		||||
                val ldiff = if (timetable.days[j].timeslots[i].size == 0) 1 else timetable.days[j].timeslots[i].size
 | 
			
		||||
 | 
			
		||||
                for (lesson in timetable.days[j].timeslots[i]) print(lesson.lessonRoom.padEnd(75/ldiff ,' '))
 | 
			
		||||
                if (ldiff == 2) print(" ")
 | 
			
		||||
                print(" | ")
 | 
			
		||||
            }
 | 
			
		||||
            println()
 | 
			
		||||
 | 
			
		||||
            for (j in 0..5) print("-".padEnd(76 + (j.toFloat().div(j).toInt()), '-') + "+")
 | 
			
		||||
            println()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        println(" \n")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
    <string name="app_name" translatable="false">Project Laogai</string>
 | 
			
		||||
    <string name="navigation_drawer_open">Open navigation drawer</string>
 | 
			
		||||
    <string name="navigation_drawer_close">Close navigation drawer</string>
 | 
			
		||||
    <string name="nav_header_title" translatable="false">hso App 0.3.90</string>
 | 
			
		||||
    <string name="nav_header_title" translatable="false">hso App 0.3.95</string>
 | 
			
		||||
    <string name="nav_header_subtitle" translatable="false">seil0@mosad.xyz</string>
 | 
			
		||||
    <string name="nav_header_desc" translatable="false">Project Laogai</string>
 | 
			
		||||
 | 
			
		||||
@ -40,7 +40,7 @@
 | 
			
		||||
    <string name="accent_color_desc">The accent color, default is indigo.</string>
 | 
			
		||||
    <string name="show_buffet">always show buffet</string>
 | 
			
		||||
    <string name="select">select</string>
 | 
			
		||||
    <string name="version" translatable="false">version 0.3.90</string>
 | 
			
		||||
    <string name="version" translatable="false">version 0.3.95</string>
 | 
			
		||||
    <string name="about">about</string>
 | 
			
		||||
    <string name="about_txtView" translatable="false">hso App by @Seil0</string>
 | 
			
		||||
    <string name="about_text" translatable="false">"This software is made by @Seil0 and is published under the terms and conditions of GPL 3. For further information visit \ngit.mosad.xyz/Seil0/ProjectLaogai \n\n© 2018-2019 seil0@mosad.xyz "</string>
 | 
			
		||||
@ -53,5 +53,8 @@
 | 
			
		||||
    <string name="save_key_colorPrimary" translatable="false">org.mosad.seil0.projectlaogai.colorPrimary</string>
 | 
			
		||||
    <string name="save_key_colorAccent" translatable="false">org.mosad.seil0.projectlaogai.colorAccent</string>
 | 
			
		||||
    <string name="save_key_showBuffet" translatable="false">org.mosad.seil0.projectlaogai.showBuffet</string>
 | 
			
		||||
    <string name="save_key_coursesCacheTime" translatable="false">org.mosad.seil0.projectlaogai.coursesCacheTime</string>
 | 
			
		||||
    <string name="save_key_mensaCacheTime" translatable="false">org.mosad.seil0.projectlaogai.mensaCacheTime</string>
 | 
			
		||||
    <string name="save_key_timetableCacheTime" translatable="false">org.mosad.seil0.projectlaogai.timetableCacheTime</string>
 | 
			
		||||
 | 
			
		||||
</resources>
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user