Add support for attendance summary via eduOne
This commit is contained in:
parent
fd5eb26a9d
commit
3c7d8b9545
6 changed files with 200 additions and 2 deletions
|
@ -356,7 +356,10 @@ class Scrapper {
|
||||||
suspend fun getAttendanceSummary(subjectId: Int? = -1): List<AttendanceSummary> {
|
suspend fun getAttendanceSummary(subjectId: Int? = -1): List<AttendanceSummary> {
|
||||||
if (diaryId == 0) return emptyList()
|
if (diaryId == 0) return emptyList()
|
||||||
|
|
||||||
return student.getAttendanceSummary(subjectId)
|
return when (isEduOne) {
|
||||||
|
true -> studentPlus.getAttendanceSummary(studentId, diaryId, unitId)
|
||||||
|
else -> student.getAttendanceSummary(subjectId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun excuseForAbsence(absents: List<Absent>, content: String? = null): Boolean {
|
suspend fun excuseForAbsence(absents: List<Absent>, content: String? = null): Boolean {
|
||||||
|
|
|
@ -1,22 +1,30 @@
|
||||||
package io.github.wulkanowy.sdk.scrapper.attendance
|
package io.github.wulkanowy.sdk.scrapper.attendance
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.JsonNames
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
internal class AttendanceSummaryResponse {
|
internal class AttendanceSummaryResponse {
|
||||||
|
|
||||||
@SerialName("Statystyki")
|
@SerialName("Statystyki")
|
||||||
|
@JsonNames("statystyki")
|
||||||
var items: List<Summary> = emptyList()
|
var items: List<Summary> = emptyList()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Summary(
|
data class Summary(
|
||||||
|
|
||||||
@SerialName("Id")
|
@SerialName("Id")
|
||||||
|
@JsonNames("kategoriaFrekwencji")
|
||||||
val id: Int,
|
val id: Int,
|
||||||
|
|
||||||
|
@SerialName("miesiace")
|
||||||
|
val months: List<AttendanceSummaryMonth> = emptyList(),
|
||||||
|
|
||||||
@SerialName("NazwaTypuFrekwencji")
|
@SerialName("NazwaTypuFrekwencji")
|
||||||
val type: String,
|
val type: String = "",
|
||||||
|
|
||||||
@SerialName("Wrzesien")
|
@SerialName("Wrzesien")
|
||||||
val september: Int?,
|
val september: Int?,
|
||||||
|
@ -55,6 +63,15 @@ internal class AttendanceSummaryResponse {
|
||||||
val august: Int?,
|
val august: Int?,
|
||||||
|
|
||||||
@SerialName("Razem")
|
@SerialName("Razem")
|
||||||
|
@JsonNames("razem")
|
||||||
val total: Int?,
|
val total: Int?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
internal data class AttendanceSummaryMonth(
|
||||||
|
@SerialName("miesiac")
|
||||||
|
val month: Int,
|
||||||
|
@SerialName("wartosc")
|
||||||
|
val value: Int,
|
||||||
|
)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusePlusRequest
|
||||||
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusePlusRequestItem
|
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusePlusRequestItem
|
||||||
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusePlusResponseItem
|
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusePlusResponseItem
|
||||||
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusesPlusResponse
|
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusesPlusResponse
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceSummary
|
||||||
import io.github.wulkanowy.sdk.scrapper.attendance.SentExcuseStatus
|
import io.github.wulkanowy.sdk.scrapper.attendance.SentExcuseStatus
|
||||||
import io.github.wulkanowy.sdk.scrapper.exams.Exam
|
import io.github.wulkanowy.sdk.scrapper.exams.Exam
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
|
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
|
||||||
|
@ -26,6 +27,7 @@ import io.github.wulkanowy.sdk.scrapper.toFormat
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
import java.time.Month
|
||||||
|
|
||||||
internal class StudentPlusRepository(
|
internal class StudentPlusRepository(
|
||||||
private val api: StudentPlusService,
|
private val api: StudentPlusService,
|
||||||
|
@ -87,6 +89,36 @@ internal class StudentPlusRepository(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getAttendanceSummary(studentId: Int, diaryId: Int, unitId: Int): List<AttendanceSummary> {
|
||||||
|
val summaries = api.getAttendanceSummary(getEncodedKey(studentId, diaryId, unitId))
|
||||||
|
|
||||||
|
val stats = summaries.items.associate { it.id to it.months }
|
||||||
|
val getMonthValue = fun(type: Int, month: Int): Int {
|
||||||
|
return stats[type]?.find { it.month == month }?.value ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return (1..12).map {
|
||||||
|
AttendanceSummary(
|
||||||
|
month = Month.of(it),
|
||||||
|
presence = getMonthValue(AttendanceCategory.PRESENCE.id, it),
|
||||||
|
absence = getMonthValue(AttendanceCategory.ABSENCE_UNEXCUSED.id, it),
|
||||||
|
absenceExcused = getMonthValue(AttendanceCategory.ABSENCE_EXCUSED.id, it),
|
||||||
|
absenceForSchoolReasons = getMonthValue(AttendanceCategory.ABSENCE_FOR_SCHOOL_REASONS.id, it),
|
||||||
|
lateness = getMonthValue(AttendanceCategory.UNEXCUSED_LATENESS.id, it),
|
||||||
|
latenessExcused = getMonthValue(AttendanceCategory.EXCUSED_LATENESS.id, it),
|
||||||
|
exemption = getMonthValue(AttendanceCategory.EXEMPTION.id, it),
|
||||||
|
)
|
||||||
|
}.filterNot { summary ->
|
||||||
|
summary.absence == 0 &&
|
||||||
|
summary.absenceExcused == 0 &&
|
||||||
|
summary.absenceForSchoolReasons == 0 &&
|
||||||
|
summary.exemption == 0 &&
|
||||||
|
summary.lateness == 0 &&
|
||||||
|
summary.latenessExcused == 0 &&
|
||||||
|
summary.presence == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun Attendance.getMatchingExcuse(sentExcuses: AttendanceExcusesPlusResponse): AttendanceExcusePlusResponseItem? {
|
private fun Attendance.getMatchingExcuse(sentExcuses: AttendanceExcusesPlusResponse): AttendanceExcusePlusResponseItem? {
|
||||||
return sentExcuses.excuses.find { excuse ->
|
return sentExcuses.excuses.find { excuse ->
|
||||||
excuse.dayDate == date && (excuse.lessonNumber == number || excuse.lessonNumber == null)
|
excuse.dayDate == date && (excuse.lessonNumber == number || excuse.lessonNumber == null)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.sdk.scrapper.service
|
||||||
import io.github.wulkanowy.sdk.scrapper.attendance.Attendance
|
import io.github.wulkanowy.sdk.scrapper.attendance.Attendance
|
||||||
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusePlusRequest
|
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusePlusRequest
|
||||||
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusesPlusResponse
|
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceExcusesPlusResponse
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceSummaryResponse
|
||||||
import io.github.wulkanowy.sdk.scrapper.conferences.Conference
|
import io.github.wulkanowy.sdk.scrapper.conferences.Conference
|
||||||
import io.github.wulkanowy.sdk.scrapper.exams.ExamDetailsPlus
|
import io.github.wulkanowy.sdk.scrapper.exams.ExamDetailsPlus
|
||||||
import io.github.wulkanowy.sdk.scrapper.grades.GradeSemester
|
import io.github.wulkanowy.sdk.scrapper.grades.GradeSemester
|
||||||
|
@ -50,6 +51,11 @@ internal interface StudentPlusService {
|
||||||
@POST("api/Usprawiedliwienia")
|
@POST("api/Usprawiedliwienia")
|
||||||
suspend fun excuseForAbsence(@Body body: AttendanceExcusePlusRequest): Response<Unit>
|
suspend fun excuseForAbsence(@Body body: AttendanceExcusePlusRequest): Response<Unit>
|
||||||
|
|
||||||
|
@POST("api/FrekwencjaStatystyki")
|
||||||
|
suspend fun getAttendanceSummary(
|
||||||
|
@Query("key") key: String,
|
||||||
|
): AttendanceSummaryResponse
|
||||||
|
|
||||||
@GET("api/ZarejestrowaneUrzadzenia")
|
@GET("api/ZarejestrowaneUrzadzenia")
|
||||||
suspend fun getRegisteredDevices(): List<Device>
|
suspend fun getRegisteredDevices(): List<Device>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package io.github.wulkanowy.sdk.scrapper.attendance
|
||||||
|
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import java.time.Month
|
||||||
|
|
||||||
|
class AttendanceSummaryPlusTest : BaseLocalTest() {
|
||||||
|
|
||||||
|
private val attendance by lazy {
|
||||||
|
runBlocking {
|
||||||
|
getStudentPlusRepo(AttendanceSummaryPlusTest::class.java, "FrekwencjaStatystyki.json")
|
||||||
|
.getAttendanceSummary(1, 2, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getAllTest() {
|
||||||
|
val items = attendance
|
||||||
|
assertEquals(1, items.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun attendance_march() {
|
||||||
|
with(attendance[0]) {
|
||||||
|
assertEquals(Month.MARCH, month)
|
||||||
|
assertEquals(1, presence)
|
||||||
|
assertEquals(2, absence)
|
||||||
|
assertEquals(3, absenceExcused)
|
||||||
|
assertEquals(6, absenceForSchoolReasons)
|
||||||
|
assertEquals(4, lateness)
|
||||||
|
assertEquals(5, latenessExcused)
|
||||||
|
assertEquals(2, exemption)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
{
|
||||||
|
"podsumowanie": 76.19,
|
||||||
|
"statystyki": [
|
||||||
|
{
|
||||||
|
"kategoriaFrekwencji": 1,
|
||||||
|
"miesiace": [
|
||||||
|
{
|
||||||
|
"miesiac": 3,
|
||||||
|
"wartosc": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"okresy": [
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"razem": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kategoriaFrekwencji": 2,
|
||||||
|
"miesiace": [
|
||||||
|
{
|
||||||
|
"miesiac": 3,
|
||||||
|
"wartosc": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"okresy": [
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"razem": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kategoriaFrekwencji": 3,
|
||||||
|
"miesiace": [
|
||||||
|
{
|
||||||
|
"miesiac": 3,
|
||||||
|
"wartosc": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"okresy": [
|
||||||
|
0,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"razem": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kategoriaFrekwencji": 6,
|
||||||
|
"miesiace": [
|
||||||
|
{
|
||||||
|
"miesiac": 3,
|
||||||
|
"wartosc": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"okresy": [
|
||||||
|
0,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"razem": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kategoriaFrekwencji": 4,
|
||||||
|
"miesiace": [
|
||||||
|
{
|
||||||
|
"miesiac": 3,
|
||||||
|
"wartosc": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"okresy": [
|
||||||
|
0,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"razem": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kategoriaFrekwencji": 5,
|
||||||
|
"miesiace": [
|
||||||
|
{
|
||||||
|
"miesiac": 3,
|
||||||
|
"wartosc": 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"okresy": [
|
||||||
|
0,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"razem": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kategoriaFrekwencji": 7,
|
||||||
|
"miesiace": [
|
||||||
|
{
|
||||||
|
"miesiac": 3,
|
||||||
|
"wartosc": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"okresy": [
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"razem": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue