From acf55de975ab9184471ef5678b5177a8ce8e5def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Mon, 20 Aug 2018 20:31:27 +0200 Subject: [PATCH] Add attendance --- .../io/github/wulkanowy/api/Constants.kt | 2 +- .../wulkanowy/api/attendance/Attendance.kt | 28 +++++++++++ .../api/attendance/AttendanceResponse.kt | 25 ++++++++++ .../api/interfaces/StudentAndParentApi.kt | 3 +- .../repository/StudentAndParentRepository.kt | 13 ++++- .../io/github/wulkanowy/api/VulcanTest.kt | 49 +++++++++++++++---- 6 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 src/main/kotlin/io/github/wulkanowy/api/attendance/Attendance.kt create mode 100644 src/main/kotlin/io/github/wulkanowy/api/attendance/AttendanceResponse.kt diff --git a/src/main/kotlin/io/github/wulkanowy/api/Constants.kt b/src/main/kotlin/io/github/wulkanowy/api/Constants.kt index c46910e9..6a60e1e6 100644 --- a/src/main/kotlin/io/github/wulkanowy/api/Constants.kt +++ b/src/main/kotlin/io/github/wulkanowy/api/Constants.kt @@ -1,3 +1,3 @@ package io.github.wulkanowy.api -const val DATE_FORMAT = "dd.MM.yyyy" \ No newline at end of file +const val DATE_FORMAT = "dd.MM.yyyy" diff --git a/src/main/kotlin/io/github/wulkanowy/api/attendance/Attendance.kt b/src/main/kotlin/io/github/wulkanowy/api/attendance/Attendance.kt new file mode 100644 index 00000000..e0bddc78 --- /dev/null +++ b/src/main/kotlin/io/github/wulkanowy/api/attendance/Attendance.kt @@ -0,0 +1,28 @@ +package io.github.wulkanowy.api.attendance + +import pl.droidsonroids.jspoon.annotation.Selector +import java.util.* + +class Attendance { + + var number: Int = 0 + + lateinit var date: Date + + @Selector("span") + lateinit var subject: String + + @Selector("div", attr = "class") + lateinit var type: String + + object Types { + const val NOT_EXIST = "x-sp-nieobecny-w-oddziale" + const val PRESENCE = "x-obecnosc" + const val ABSENCE_UNEXCUSED = "x-nieobecnosc-nieuspr" + const val ABSENCE_EXCUSED = "x-nieobecnosc-uspr" + const val ABSENCE_FOR_SCHOOL_REASONS = "x-nieobecnosc-przycz-szkol" + const val UNEXCUSED_LATENESS = "x-sp-nieusprawiedliwione" + const val EXCUSED_LATENESS = "x-sp-spr" + const val EXEMPTION = "x-sp-zwolnienie" + } +} diff --git a/src/main/kotlin/io/github/wulkanowy/api/attendance/AttendanceResponse.kt b/src/main/kotlin/io/github/wulkanowy/api/attendance/AttendanceResponse.kt new file mode 100644 index 00000000..7bef2a22 --- /dev/null +++ b/src/main/kotlin/io/github/wulkanowy/api/attendance/AttendanceResponse.kt @@ -0,0 +1,25 @@ +package io.github.wulkanowy.api.attendance + +import io.github.wulkanowy.api.DATE_FORMAT +import pl.droidsonroids.jspoon.annotation.Format +import pl.droidsonroids.jspoon.annotation.Selector +import java.util.* + +class AttendanceResponse { + + @Selector(".presentData thead th:not(:first-of-type)", regex = "\\s(.*)") + @Format(value = DATE_FORMAT) + lateinit var days: List + + @Selector(".presentData tbody tr") + lateinit var rows: List + + class AttendanceRow { + + @Selector("td", index = 0) + var number: Int = 0 + + @Selector("td:not(:first-of-type)") + lateinit var lessons: List + } +} diff --git a/src/main/kotlin/io/github/wulkanowy/api/interfaces/StudentAndParentApi.kt b/src/main/kotlin/io/github/wulkanowy/api/interfaces/StudentAndParentApi.kt index 8a55316b..868cd838 100644 --- a/src/main/kotlin/io/github/wulkanowy/api/interfaces/StudentAndParentApi.kt +++ b/src/main/kotlin/io/github/wulkanowy/api/interfaces/StudentAndParentApi.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.api.interfaces +import io.github.wulkanowy.api.attendance.AttendanceResponse import io.github.wulkanowy.api.grades.GradesResponse import io.github.wulkanowy.api.notes.NotesResponse import io.reactivex.Observable @@ -9,7 +10,7 @@ import retrofit2.http.Query interface StudentAndParentApi { @GET("Frekwencja.mvc") - fun getAttendance(@Query("data") date: String) + fun getAttendance(@Query("data") date: String): Observable @GET("Sprawdziany.mvc/Terminarz?rodzajWidoku=2") fun getExams(@Query("date") date: String) diff --git a/src/main/kotlin/io/github/wulkanowy/api/repository/StudentAndParentRepository.kt b/src/main/kotlin/io/github/wulkanowy/api/repository/StudentAndParentRepository.kt index 4e16bbb4..0b8623bc 100644 --- a/src/main/kotlin/io/github/wulkanowy/api/repository/StudentAndParentRepository.kt +++ b/src/main/kotlin/io/github/wulkanowy/api/repository/StudentAndParentRepository.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.api.repository +import io.github.wulkanowy.api.attendance.Attendance import io.github.wulkanowy.api.grades.Grade import io.github.wulkanowy.api.interfaces.StudentAndParentApi import io.github.wulkanowy.api.notes.Note @@ -40,7 +41,17 @@ class StudentAndParentRepository(private val host: String, } } - fun getAttendance(startDate: String) = api.getAttendance(startDate) + fun getAttendance(startDate: String): Observable> { + return api.getAttendance(startDate).map { res -> + res.rows.map { row -> + row.lessons.mapIndexed { i, it -> + it.date = res.days[i] + it.number = row.number + it + } + }.flatten() + } + } fun getHomework(startDate: String) = api.getHomework(startDate) diff --git a/src/test/kotlin/io/github/wulkanowy/api/VulcanTest.kt b/src/test/kotlin/io/github/wulkanowy/api/VulcanTest.kt index 76f68273..ee9d8a56 100644 --- a/src/test/kotlin/io/github/wulkanowy/api/VulcanTest.kt +++ b/src/test/kotlin/io/github/wulkanowy/api/VulcanTest.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.api +import io.github.wulkanowy.api.attendance.Attendance import io.github.wulkanowy.api.grades.Grade import io.github.wulkanowy.api.interceptor.LoginInterceptor import io.github.wulkanowy.api.notes.Note @@ -47,13 +48,37 @@ class VulcanTest { ) } + @Test fun attendanceTest() { + val attendance = snp.getAttendance("636697786721570000") + val attendanceObserver = TestObserver>() + attendance.subscribe(attendanceObserver) + attendanceObserver.assertComplete() + + val values = attendanceObserver.values()[0] + + assertEquals(0, values[0].number) + assertEquals("Fizyka", values[0].subject) + assertEquals(getDate(2018, 8, 13), values[0].date) + + assertEquals(Attendance.Types.PRESENCE, values[0].type) + assertEquals(Attendance.Types.ABSENCE_UNEXCUSED, values[1].type) + assertEquals(Attendance.Types.ABSENCE_EXCUSED, values[2].type) + assertEquals(Attendance.Types.ABSENCE_FOR_SCHOOL_REASONS, values[3].type) + assertEquals(Attendance.Types.UNEXCUSED_LATENESS, values[4].type) + + assertEquals(Attendance.Types.EXCUSED_LATENESS, values[5].type) + assertEquals(Attendance.Types.EXEMPTION, values[6].type) + + assertEquals(1, values[5].number) + } + @Test fun notesTest() { val notes = snp.getNotes() - val notesSubscriber = TestObserver>() - notes.subscribe(notesSubscriber) - notesSubscriber.assertComplete() + val notesObserver = TestObserver>() + notes.subscribe(notesObserver) + notesObserver.assertComplete() - val values = notesSubscriber.values()[0] + val values = notesObserver.values()[0] assertEquals("Janusz Tracz", values[0].teacher) assertEquals("Udział w konkursie szkolnym +20 pkt", values[0].category) @@ -62,11 +87,11 @@ class VulcanTest { @Test fun gradesTest() { val grades = snp.getGrades(123) - val gradesSubscriber = TestObserver>() - grades.subscribe(gradesSubscriber) - gradesSubscriber.assertComplete() + val gradesObserver = TestObserver>() + grades.subscribe(gradesObserver) + gradesObserver.assertComplete() - val values = gradesSubscriber.values()[0] + val values = gradesObserver.values()[0] assertEquals("Zajęcia z wychowawcą", values[0].subject) assertEquals("5", values[0].value) @@ -74,12 +99,16 @@ class VulcanTest { assertEquals("A1", values[0].symbol) assertEquals("Dzień Kobiet w naszej klasie", values[0].description) assertEquals("1.00", values[0].weight) - assertEquals(Date.from(LocalDate.of(2017, 3, 21) - .atStartOfDay(ZoneId.systemDefault()).toInstant()), values[0].date) + assertEquals(getDate(2017, 3, 21), values[0].date) assertEquals("Patryk Maciejewski", values[0].teacher) assertEquals("STR", values[4].symbol) assertEquals("", values[4].description) } + private fun getDate(year: Int, month: Int, day: Int): Date { + return Date.from(LocalDate.of(year, month, day) + .atStartOfDay(ZoneId.systemDefault()).toInstant()) + } + }