/** * ProjectLaogai * * Copyright 2019-2020 * * 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 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.Companion.cCourse import org.mosad.seil0.projectlaogai.hsoparser.Course import org.mosad.seil0.projectlaogai.hsoparser.MensaMenu import org.mosad.seil0.projectlaogai.hsoparser.TimetableCourseWeek import java.io.BufferedReader import java.io.File import java.io.FileReader import java.util.* import kotlin.collections.ArrayList class CacheController(cont: Context) { private val className = "CacheController" private val context = cont init { val cal = Calendar.getInstance() val currentDay = Calendar.getInstance().get(Calendar.DAY_OF_WEEK) val currentTime = System.currentTimeMillis() / 1000 // check if we need to update the mensa data before displaying it readMensa(context) cal.time = Date(mensaMenu.meta.updateTime * 1000) // if a) it's monday and the last cache update was on sunday or b) the cache is older than 24hr, update blocking if ((currentDay == Calendar.MONDAY && cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) || (currentTime - mensaMenu.meta.updateTime) > 86400) { Log.i(className, "update mensa blocking") GlobalScope.launch(Dispatchers.Default) { TCoRAPIController.getMensa(context).join() } } // check if we need to update the timetables before displaying them readTimetable(cCourse.courseName, 0, context) cal.time = Date(timetables[0].meta.updateTime * 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 if ((currentDay == Calendar.MONDAY && cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) || (currentTime - timetables[0].meta.updateTime) > 86400) { Log.i(className, "updating timetable after sunday!") GlobalScope.launch(Dispatchers.Default) { val threads = listOf( TCoRAPIController.getTimetable(cCourse.courseName, 0, context), TCoRAPIController.getTimetable(cCourse.courseName, 1, context) ) threads.joinAll() } TCoRAPIController.getTimetable(cCourse.courseName, 0, context) TCoRAPIController.getTimetable(cCourse.courseName, 1, context) } // check if an update is necessary, not blocking if (currentTime - PreferencesController.coursesCacheTime > 86400) TCoRAPIController.getCoursesList(context) if (currentTime - PreferencesController.mensaCacheTime > 10800) TCoRAPIController.getMensa(context) if (currentTime - PreferencesController.timetableCacheTime > 10800) { TCoRAPIController.getTimetable(cCourse.courseName, 0, context) TCoRAPIController.getTimetable(cCourse.courseName, 1, context) } readStartCache(cCourse.courseName) } companion object { var coursesList = ArrayList() var timetables = ArrayList() var mensaMenu = MensaMenu() /** * read the courses list from the cached file * add them to the coursesList object */ private fun readCoursesList(context: Context) { val file = File(context.filesDir, "courses.json") // make sure the file exists if (!file.exists()) runBlocking { TCoRAPIController.getCoursesList(context).join() } val fileReader = FileReader(file) val bufferedReader = BufferedReader(fileReader) val coursesObject = JsonParser.parseString(bufferedReader.readLine()).asJsonObject coursesList = Gson().fromJson( coursesObject.getAsJsonArray("courses"), object : TypeToken>() {}.type ) } /** * get the MensaMenu object from the cached json, * if cache is empty create the cache file */ fun readMensa(context: Context) { val file = File(context.filesDir, "mensa.json") // make sure the file exists if (!file.exists()) runBlocking { TCoRAPIController.getMensa(context).join() } val fileReader = FileReader(file) val bufferedReader = BufferedReader(fileReader) val mensaObject = JsonParser.parseString(bufferedReader.readLine()).asJsonObject mensaMenu = GsonBuilder().create().fromJson(mensaObject, MensaMenu().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, context: Context) { val file = File(context.filesDir, "timetable-$courseName-$week.json") // make sure the file exists if (!file.exists()) runBlocking { TCoRAPIController.getTimetable(courseName, week, context).join() } val fileReader = FileReader(file) val bufferedReader = BufferedReader(fileReader) val timetableObject = JsonParser.parseString(bufferedReader.readLine()).asJsonObject // make sure you add the single weeks in the exact order! if (timetables.size > week) { timetables[week] = (Gson().fromJson(timetableObject, TimetableCourseWeek().javaClass)) } else { timetables.add(Gson().fromJson(timetableObject, TimetableCourseWeek().javaClass)) } } } /** * read coursesList, mensa (current and next week), timetable (current and next week) * @param courseName the course name (e.g AI1) */ private fun readStartCache(courseName: String) { readCoursesList(context) readMensa(context) readTimetable(courseName, 0, context) readTimetable(courseName, 1, context) } }