@ -20,33 +20,30 @@
*
* /
package org.mosad.seil0.projectlaogai.controller
package org.mosad.seil0.projectlaogai.controller.cache
import android.content.Context
import android.util.Log
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonParser
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.*
import org.mosad.seil0.projectlaogai.controller.PreferencesController
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.TCoRAPIController
import org.mosad.seil0.projectlaogai.util.*
import java.io.*
import java.util.*
import kotlin.Exception
import kotlin.collections.ArrayList
/ * *
* TODO rework
* * move all write functions from TCorController to CacheController
* * init : check for blocking updates , read all data from cache , check for non blocking update
* * [ x ] save needed data to validate cache in separate file
* * new functions :
* * [ x ] updateTimetable ( ) : get Timetable object from TCoRController , write object to file
* * [ x ] updateMensa ( ) : get MensaMenu object from TCoRController , write object to file
* * [ ] save additional subject and lessons
* The cacheController reads and updates the cache files .
* It contains the courseList and mensaMenu object , all timetable objects
* are located in TimetableController .
* /
class CacheController ( cont : Context ) {
@ -67,6 +64,7 @@ class CacheController(cont: Context) {
GlobalScope . launch ( Dispatchers . Default ) { updateMensaMenu ( context ) . join ( ) }
}
// check if we need to update the timetable before displaying it
cal . time = Date ( timetableCacheTime * 1000 )
// if a) it`s monday and the last cache update was not on a sunday or b) the cache is older than 24hr, update blocking
@ -94,8 +92,7 @@ class CacheController(cont: Context) {
updateMensaMenu ( context )
if ( currentTime - timetableCacheTime > 10800 ) {
updateTimetable ( cCourse . courseName , 0 , context )
updateTimetable ( cCourse . courseName , 1 , context )
TimetableController . update ( context )
}
}
@ -163,7 +160,7 @@ class CacheController(cont: Context) {
try {
timetable = TCoRAPIController . getTimetable ( courseName , week )
} catch ( ex : Exception ) {
Log . e ( className , "could not load timetable from tcor" , ex )
Log . e ( className , "could not load timetable $courseName[$week] from tcor" , ex )
}
// update timetable in TTC
@ -180,6 +177,42 @@ class CacheController(cont: Context) {
}
}
/ * *
* update all additional subject lessons , async
* /
fun updateAdditionalLessons ( context : Context ) : Job {
val fileLessons = File ( context . filesDir , "additional_lessons.json" )
return GlobalScope . launch ( Dispatchers . IO ) {
TimetableController . subjectMap . forEach { ( courseName , subjects ) - >
// update all subjects for a course
subjects . forEach { subject - >
try {
TCoRAPIController . getLessons ( courseName , subject , 0 ) . forEach { lesson - >
TimetableController . addLesson ( courseName , subject , lesson )
}
} catch ( ex : Exception ) {
Log . e ( className , "could not load $courseName: $subject" , ex )
}
}
}
save ( fileLessons , Gson ( ) . toJson ( TimetableController . lessonMap ) )
}
}
/ * *
* save changes in lessonMap and subjectMap ,
* called on addSubject or removeSubject
* /
fun saveAdditionalSubjects ( context : Context ) {
val fileLessons = File ( context . filesDir , "additional_lessons.json" )
val fileSubjects = File ( context . filesDir , "additional_subjects.json" )
save ( fileLessons , Gson ( ) . toJson ( TimetableController . lessonMap ) )
save ( fileSubjects , Gson ( ) . toJson ( TimetableController . subjectMap ) )
}
private fun save ( file : File , text : String ) {
try {
val writer = BufferedWriter ( FileWriter ( file ) )
@ -188,7 +221,6 @@ class CacheController(cont: Context) {
} catch ( ex : Exception ) {
Log . e ( className , "failed to write file \"${file.absoluteFile}\"" , ex )
}
}
}
@ -199,36 +231,41 @@ class CacheController(cont: Context) {
* /
private fun readStartCache ( courseName : String ) {
try {
readCoursesList ( context )
readCoursesList ( )
} catch ( ex : Exception ) {
Log . e ( className , "Error while reading the course list" , ex )
}
try {
readMensa ( context )
readMensa ( )
} catch ( ex : Exception ) {
Log . e ( className , "Error while reading the mensa menu" , ex )
}
try {
readTimetable ( courseName , 0 , context )
readTimetable ( courseName , 0 )
} catch ( ex : Exception ) {
Log . e ( className , "Error while reading timetable week 0" , ex )
}
try {
readTimetable ( courseName , 1 , context )
readTimetable ( courseName , 1 )
} catch ( ex : Exception ) {
Log . e ( className , "Error while reading timetable week 1" , ex )
}
try {
readAdditionalSubjects ( )
} catch ( ex : Exception ) {
Log . e ( className , "Error while reading additional subjects" , ex )
}
}
/ * *
* read the courses list from the cached file
* add them to the coursesList object
* /
private fun readCoursesList ( context : Context ) {
private fun readCoursesList ( ) {
val file = File ( context . filesDir , "courses.json" )
// make sure the file exists
@ -246,7 +283,7 @@ class CacheController(cont: Context) {
* get the MensaMenu object from the cached json ,
* if cache is empty create the cache file
* /
private fun readMensa ( context : Context ) {
private fun readMensa ( ) {
val file = File ( context . filesDir , "mensa.json" )
// make sure the file exists
@ -265,7 +302,7 @@ class CacheController(cont: Context) {
* @param courseName the course name ( e . g AI1 )
* @param week the week to read ( 0 for the current and so on )
* /
private fun readTimetable ( courseName : String , week : Int , context : Context ) {
private fun readTimetable ( courseName : String , week : Int ) {
val file = File ( context . filesDir , "timetable-$courseName-$week.json" )
// if the file does not exist, call updateTimetable blocking and return
@ -300,4 +337,39 @@ class CacheController(cont: Context) {
}
}
private fun readAdditionalSubjects ( ) {
val fileLessons = File ( context . filesDir , "additional_lessons.json" )
val fileSubjects = File ( context . filesDir , "additional_subjects.json" )
// make sure the file exists
if ( ! fileLessons . exists ( ) | | ! fileSubjects . exists ( ) ) {
return
}
// clear the maps before loading, just to be save
TimetableController . lessonMap . clear ( )
TimetableController . subjectMap . clear ( )
// read subjects and lessons from cache file
FileReader ( fileLessons ) . use {
TimetableController . lessonMap . putAll (
GsonBuilder ( ) . create ( )
. fromJson ( BufferedReader ( it ) . readLine ( ) , object : TypeToken < HashMap < String , Lesson > > ( ) { } . type )
)
}
FileReader ( fileSubjects ) . use {
TimetableController . subjectMap . putAll (
GsonBuilder ( ) . create ( )
. fromJson ( BufferedReader ( it ) . readLine ( ) , HashMap < String , ArrayList < String > > ( ) . javaClass )
)
}
// add lessons to timetable
TimetableController . lessonMap . forEach { ( _ , lesson ) - >
TimetableController . addLessonToTimetable ( lesson )
}
}
}