/** * TheCitadelofRicks * * Copyright 2019 * * 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.thecitadelofricks import org.mosad.thecitadelofricks.CacheController.Companion.courseList import org.mosad.thecitadelofricks.CacheController.Companion.mensaMenu import org.mosad.thecitadelofricks.CacheController.Companion.timetableList import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController import java.net.HttpURLConnection import java.net.URL import java.time.LocalDateTime import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashSet @RestController class APIController { private val logger: Logger = LoggerFactory.getLogger(APIController::class.java) private val cache = CacheController() private val apiVersion = "1.1.3" private val softwareVersion = "1.1.5" private val startTime = System.currentTimeMillis() / 1000 private var totalRequests = 0 private var mensaMenuRequests = 0 private var timetableRequests = ArrayList() @Deprecated("courses is replaced by courseList", replaceWith = ReplaceWith("courseList()")) @RequestMapping("/courses") fun courses(): CourseList { return courseList() } @RequestMapping("/courseList") fun courseList(): CourseList { logger.info("courseList request at ${LocalDateTime.now()}!") totalRequests++ return courseList } @RequestMapping("/mensamenu") fun mensamenu(): MensaMenu { logger.info("mensamenu request at ${LocalDateTime.now()}!") mensaMenuRequests++ totalRequests++ return mensaMenu } @RequestMapping("/timetable") fun timetable( @RequestParam(value = "courseName", defaultValue = "AI4") courseName: String, @RequestParam(value = "week", defaultValue = "0") week: Int ): TimetableCourseWeek { logger.info("timetable request at ${LocalDateTime.now()}!") updateTimetableRequests(courseName) totalRequests++ return cache.getTimetable(courseName, week) } @RequestMapping("/lessonSubjectList") fun lessonSubjectList( @RequestParam(value = "courseName", defaultValue = "AI4") courseName: String, @RequestParam(value = "week", defaultValue = "0") week: Int ): HashSet { logger.info("lessonSubjectList request at ${LocalDateTime.now()}!") totalRequests++ return getLessonSubjectList(courseName, week) } @RequestMapping("/lessons") fun lesson( @RequestParam(value = "courseName", defaultValue = "AI4") courseName: String, @RequestParam(value = "lessonSubject", defaultValue = "Mathematik 4") lessonSubject: String, @RequestParam(value = "week", defaultValue = "0") week: Int ): ArrayList { logger.info("lesson request at ${LocalDateTime.now()}!") totalRequests++ return getLesson(courseName, lessonSubject, week) } @RequestMapping("/status") fun status(): Status { return getStatus() } // non direct api functions /** * get every explicit lesson in a week * @param courseName the name of the course to be requested * @param weekIndex request week number (current week = 0) * @return a HashSet of explicit lessons for one week */ private fun getLessonSubjectList(courseName: String, weekIndex: Int): HashSet { val lessonSubjectList = ArrayList() // get every lesson subject for the given week val flatMap = cache.getTimetable(courseName, weekIndex).timetable.days.flatMap { it.timeslots.asIterable() } flatMap.forEach { it.stream().filter { x -> x.lessonSubject.isNotEmpty() }.findAny().ifPresent { x -> lessonSubjectList.add(x.lessonSubject) } } return HashSet(lessonSubjectList) } /** * get every explicit lesson in a week * @param courseName the name of the course to be requested * @param lessonSubject the lesson subject to be requested * @param weekIndex request week number (current week = 0) * @return a ArrayList of every lesson with lessonSubject for one week */ private fun getLesson(courseName: String, lessonSubject: String, weekIndex: Int): ArrayList { val lessonList = ArrayList() // get all lessons from the weeks timetable val flatMap = cache.getTimetable(courseName, weekIndex).timetable.days.flatMap { it.timeslots.asIterable() } flatMap.forEach { it.forEach { lesson -> if(lesson.lessonSubject.contains(lessonSubject)) { lessonList.add(lesson) } } //it.stream().filter { x -> x.lessonSubject.contains(lessonSubject) }.findAny().ifPresent { x -> println("${x.lessonSubject}, ${x.lessonTeacher}") } } return lessonList } /** * if a timetable is requested update the request counter */ private fun updateTimetableRequests(courseName: String) { timetableRequests.stream().filter { it.courseName == courseName }.findFirst().ifPresentOrElse({ it.requests++ }, { timetableRequests.add(TimetableCounter(courseName, 1)) }) } private fun getStatus(): Status { val currentTime = System.currentTimeMillis() / 1000 val minutes = (currentTime - startTime) % 3600 / 60 val hours = (currentTime - startTime) % 86400 / 3600 val days = (currentTime - startTime) / 86400 var hsoCode = 999 var swfrCode = 999 logger.info("status request at ${LocalDateTime.now()}!") try { val hsoURL = URL("https://www.hs-offenburg.de/") val swfrURL = URL("https://www.swfr.de/") var connection = hsoURL.openConnection() as HttpURLConnection connection.requestMethod = "HEAD" connection.connectTimeout = 15000 hsoCode = connection.responseCode connection = swfrURL.openConnection() as HttpURLConnection connection.connectTimeout = 15000 swfrCode = connection.responseCode } catch (e: Exception) { logger.error("Error while fetching url response codes!", e) } return Status( LocalDateTime.now(), "$days days, $hours:$minutes", apiVersion, softwareVersion, totalRequests, mensaMenuRequests, timetableRequests, timetableList.size, Date(courseList.meta.updateTime * 1000), Date(mensaMenu.meta.updateTime * 1000), hsoCode, swfrCode ) } }