diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index bb471068..5c251a37 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -390,5 +390,5 @@ fun List.concat(delimiter: String? = null): CharSequence { } fun TextView.setText(@StringRes resid: Int, vararg formatArgs: Any) { - text = context.getString(resid, formatArgs) + text = context.getString(resid, *formatArgs) } \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusData.kt index a34ea854..940d48fe 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusData.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusData.kt @@ -80,6 +80,7 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) { data.startProgress(R.string.edziennik_progress_endpoint_timetable) LibrusApiTimetables(data, onSuccess) } + ENDPOINT_LIBRUS_API_NORMAL_GRADES -> { data.startProgress(R.string.edziennik_progress_endpoint_grades) LibrusApiGrades(data, onSuccess) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/api/LibrusApiTimetables.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/api/LibrusApiTimetables.kt index 61fd8c13..ceb4b2b2 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/api/LibrusApiTimetables.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/api/LibrusApiTimetables.kt @@ -1,54 +1,37 @@ /* - * Copyright (c) Kacper Ziubryniewicz 2019-11-10 + * Copyright (c) Kuba Szczodrzyński 2019-11-10. */ package pl.szczodrzynski.edziennik.api.v2.librus.data.api +import com.google.gson.JsonObject import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_TIMETABLES import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS +import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Time class LibrusApiTimetables(override val data: DataLibrus, - val onSuccess: () -> Unit) : LibrusApi(data) { + val onSuccess: () -> Unit) : LibrusApi(data) { companion object { const val TAG = "LibrusApiTimetables" } init { apiGet(TAG, "Timetables") { json -> - json.getJsonObject("Timetable")?.also { timetables -> - timetables.keySet().forEach { dateStr -> - val date = Date.fromY_m_d(dateStr) + val days = json.getJsonObject("Timetable") - timetables.getJsonArray(dateStr)?.asJsonObjectList()?.forEach { lesson -> - val lessonNumber = lesson.getInt("LessonNo") - val startTime = lesson.getString("HourFrom")?.let { Time.fromH_m(it) } - val endTime = lesson.getString("HourTo")?.let { Time.fromH_m(it) } - val teacherId = lesson.getJsonObject("Teacher")?.getLong("Id") - val subjectId = lesson.getJsonObject("Subject")?.getLong("Id") - val classId = lesson.getJsonObject("Class")?.getLong("Id") - val virtualClassId = lesson.getJsonObject("VirtualClass")?.getLong("Id") - val teamId = virtualClassId ?: classId - val classroomId = lesson.getJsonObject("Classroom")?.getLong("Id") - val classroom = data.classrooms.singleOrNull { it.id == classroomId }?.name - - val lessonObject = Lesson(profileId).apply { - this.date = date - this.lessonNumber = lessonNumber - this.startTime = startTime - this.endTime = endTime - this.teacherId = teacherId - this.subjectId = subjectId - this.teamId = teamId - this.classroom = classroom - } - - // TODO add to the database + days?.entrySet()?.forEach { (dateString, dayEl) -> + val lessonDate = dateString?.let { Date.fromY_m_d(it) } ?: return@forEach + val day = dayEl?.asJsonArray + day?.forEach { lessonRangeEl -> + val lessonRange = lessonRangeEl?.asJsonArray?.asJsonObjectList() + lessonRange?.forEachIndexed { index, lesson -> + parseLesson(lessonDate, lesson) } } } @@ -57,4 +40,126 @@ class LibrusApiTimetables(override val data: DataLibrus, onSuccess() } } + + private fun parseLesson(lessonDate: Date, lesson: JsonObject) { + val lessonObject = Lesson(profileId, lesson.hashCode().toLong()) + + val isSubstitution = lesson.getBoolean("IsSubstitutionClass") ?: false + val isCancelled = lesson.getBoolean("IsCanceled") ?: false + + val lessonNo = lesson.getInt("LessonNo") ?: return + val startTime = lesson.getString("HourFrom")?.let { Time.fromH_m(it) } ?: return + val endTime = lesson.getString("HourTo")?.let { Time.fromH_m(it) } ?: return + val subjectId = lesson.getJsonObject("Subject")?.getLong("Id") + val teacherId = lesson.getJsonObject("Teacher")?.getLong("Id") + val classroomId = lesson.getJsonObject("Classroom")?.getLong("Id") ?: -1 + val virtualClassId = lesson.getJsonObject("VirtualClass")?.getLong("Id") + val teamId = lesson.getJsonObject("Class")?.getLong("Id") ?: virtualClassId + + if (isSubstitution && isCancelled) { + // shifted lesson - source + val newDate = lesson.getString("NewDate")?.let { Date.fromY_m_d(it) } ?: return + val newLessonNo = lesson.getInt("NewLessonNo") ?: return + val newStartTime = lesson.getString("NewHourFrom")?.let { Time.fromH_m(it) } ?: return + val newEndTime = lesson.getString("NewHourTo")?.let { Time.fromH_m(it) } ?: return + val newSubjectId = lesson.getJsonObject("NewSubject")?.getLong("Id") + val newTeacherId = lesson.getJsonObject("NewTeacher")?.getLong("Id") + val newClassroomId = lesson.getJsonObject("NewClassroom")?.getLong("Id") ?: -1 + val newVirtualClassId = lesson.getJsonObject("NewVirtualClass")?.getLong("Id") + val newTeamId = lesson.getJsonObject("NewClass")?.getLong("Id") ?: newVirtualClassId + + lessonObject.let { + it.type = Lesson.TYPE_SHIFTED_SOURCE + it.oldDate = lessonDate + it.oldLessonNumber = lessonNo + it.oldStartTime = startTime + it.oldEndTime = endTime + it.oldSubjectId = subjectId + it.oldTeacherId = teacherId + it.oldTeamId = teamId + it.oldClassroom = data.classrooms[classroomId]?.name + + it.date = newDate + it.lessonNumber = newLessonNo + it.startTime = newStartTime + it.endTime = newEndTime + it.subjectId = newSubjectId + it.teacherId = newTeacherId + it.teamId = newTeamId + it.classroom = data.classrooms[newClassroomId]?.name + } + } + else if (isSubstitution) { + // lesson change OR shifted lesson - target + val oldDate = lesson.getString("OrgDate")?.let { Date.fromY_m_d(it) } ?: return + val oldLessonNo = lesson.getInt("OrgLessonNo") ?: return + val oldStartTime = lesson.getString("OrgHourFrom")?.let { Time.fromH_m(it) } ?: return + val oldEndTime = lesson.getString("OrgHourTo")?.let { Time.fromH_m(it) } ?: return + val oldSubjectId = lesson.getJsonObject("OrgSubject")?.getLong("Id") + val oldTeacherId = lesson.getJsonObject("OrgTeacher")?.getLong("Id") + val oldClassroomId = lesson.getJsonObject("OrgClassroom")?.getLong("Id") ?: -1 + val oldVirtualClassId = lesson.getJsonObject("OrgVirtualClass")?.getLong("Id") + val oldTeamId = lesson.getJsonObject("OrgClass")?.getLong("Id") ?: oldVirtualClassId + + lessonObject.let { + it.type = if (lessonDate == oldDate && lessonNo == oldLessonNo) Lesson.TYPE_CHANGE else Lesson.TYPE_SHIFTED_TARGET + it.oldDate = oldDate + it.oldLessonNumber = oldLessonNo + it.oldStartTime = oldStartTime + it.oldEndTime = oldEndTime + it.oldSubjectId = oldSubjectId + it.oldTeacherId = oldTeacherId + it.oldTeamId = oldTeamId + it.oldClassroom = data.classrooms[oldClassroomId]?.name + + it.date = lessonDate + it.lessonNumber = lessonNo + it.startTime = startTime + it.endTime = endTime + it.subjectId = subjectId + it.teacherId = teacherId + it.teamId = teamId + it.classroom = data.classrooms[classroomId]?.name + } + } + else if (isCancelled) { + lessonObject.let { + it.type = Lesson.TYPE_CANCELLED + it.oldDate = lessonDate + it.oldLessonNumber = lessonNo + it.oldStartTime = startTime + it.oldEndTime = endTime + it.oldSubjectId = subjectId + it.oldTeacherId = teacherId + it.oldTeamId = teamId + it.oldClassroom = data.classrooms[classroomId]?.name + } + } + else { + lessonObject.let { + it.type = Lesson.TYPE_NORMAL + it.date = lessonDate + it.lessonNumber = lessonNo + it.startTime = startTime + it.endTime = endTime + it.subjectId = subjectId + it.teacherId = teacherId + it.teamId = teamId + it.classroom = data.classrooms[classroomId]?.name + } + } + + if (lessonObject.type != Lesson.TYPE_NORMAL) { + data.metadataList.add( + Metadata( + data.profileId, + Metadata.TYPE_LESSON_CHANGE, + lessonObject.id, + data.profile?.empty ?: false, + data.profile?.empty ?: false, + System.currentTimeMillis() + )) + } + data.lessonNewList += lessonObject + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/LessonFull.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/LessonFull.kt index ee573ac2..2586ea4d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/LessonFull.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/LessonFull.kt @@ -17,6 +17,12 @@ class LessonFull(profileId: Int, id: Long) : Lesson(profileId, id) { return oldDate return date ?: oldDate } + val displayLessonNumber: Int? + get() { + if (type == TYPE_SHIFTED_SOURCE) + return oldLessonNumber + return lessonNumber ?: oldLessonNumber + } val displayStartTime: Time? get() { if (type == TYPE_SHIFTED_SOURCE) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt index ee565eff..f9ab8b84 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt @@ -35,7 +35,8 @@ interface TimetableDao { LEFT JOIN teachers AS oldT ON timetable.profileId = oldT.profileId AND timetable.oldTeacherId = oldT.teacherId LEFT JOIN teams AS oldG ON timetable.profileId = oldG.profileId AND timetable.oldTeamId = oldG.teamId LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId - WHERE timetable.profileId = :profileId AND (type != 3 AND date = :date) OR (type = 3 AND oldDate = :date) + WHERE timetable.profileId = :profileId AND (type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date) + ORDER BY type """) fun getForDate(profileId: Int, date: Date) : LiveData> } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/v2/day/TimetableDayFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/v2/day/TimetableDayFragment.kt index bc5637eb..817774cf 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/v2/day/TimetableDayFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/v2/day/TimetableDayFragment.kt @@ -122,7 +122,13 @@ class TimetableDayFragment(val date: Date) : Fragment() { }.concat(arrowRight) - lb.subjectName.text = lesson.displaySubjectName?.let { if (lesson.type == Lesson.TYPE_CANCELLED) it.asStrikethroughSpannable().asColoredSpannable(colorSecondary) else it } + lb.lessonNumber = lesson.displayLessonNumber + lb.subjectName.text = lesson.displaySubjectName?.let { + if (lesson.type == Lesson.TYPE_CANCELLED || lesson.type == Lesson.TYPE_SHIFTED_SOURCE) + it.asStrikethroughSpannable().asColoredSpannable(colorSecondary) + else + it + } lb.detailsFirst.text = listOfNotEmpty(timeRange, classroomInfo).concat(bullet) lb.detailsSecond.text = listOfNotEmpty(teacherInfo, teamInfo).concat(bullet) @@ -165,7 +171,55 @@ class TimetableDayFragment(val date: Date) : Fragment() { } lb.annotation.background.colorFilter = PorterDuffColorFilter( - getColorFromAttr(activity, R.attr.timetable_lesson_cancelled_color), + getColorFromAttr(activity, R.attr.timetable_lesson_change_color), + PorterDuff.Mode.SRC_ATOP + ) + } + Lesson.TYPE_SHIFTED_SOURCE -> { + lb.annotationVisible = true + if (lesson.date != lesson.oldDate) { + lb.annotation.setText( + R.string.timetable_lesson_shifted_other_day, + lesson.date?.stringY_m_d ?: "?", + lesson.startTime?.stringHM ?: "?" + ) + } + else if (lesson.startTime != lesson.oldStartTime) { + lb.annotation.setText( + R.string.timetable_lesson_shifted_same_day, + lesson.startTime?.stringHM ?: "?" + ) + } + else { + lb.annotation.setText(R.string.timetable_lesson_shifted) + } + + lb.annotation.background.colorFilter = PorterDuffColorFilter( + getColorFromAttr(activity, R.attr.timetable_lesson_shifted_source_color), + PorterDuff.Mode.SRC_ATOP + ) + } + Lesson.TYPE_SHIFTED_TARGET -> { + lb.annotationVisible = true + if (lesson.date != lesson.oldDate) { + lb.annotation.setText( + R.string.timetable_lesson_shifted_from_other_day, + lesson.oldDate?.stringY_m_d ?: "?", + lesson.oldStartTime?.stringHM ?: "?" + ) + } + else if (lesson.startTime != lesson.oldStartTime) { + lb.annotation.setText( + R.string.timetable_lesson_shifted_from_same_day, + lesson.oldStartTime?.stringHM ?: "?" + ) + } + else { + lb.annotation.setText(R.string.timetable_lesson_shifted_from) + } + + lb.annotation.background.colorFilter = PorterDuffColorFilter( + getColorFromAttr(activity, R.attr.timetable_lesson_shifted_target_color), PorterDuff.Mode.SRC_ATOP ) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Date.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Date.java index a4ab40fe..7877e1f9 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Date.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Date.java @@ -1,6 +1,7 @@ package pl.szczodrzynski.edziennik.utils.models; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import java.text.DateFormat; import java.util.Calendar; @@ -218,6 +219,11 @@ public class Date implements Comparable { return this.getValue() - o.getValue(); } + @Override + public boolean equals(@Nullable Object obj) { + return obj instanceof Date && this.getValue() == ((Date) obj).getValue(); + } + @Override public String toString() { return "Date{" + diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Time.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Time.java index 07b1c422..866b530d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Time.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Time.java @@ -1,5 +1,7 @@ package pl.szczodrzynski.edziennik.utils.models; +import androidx.annotation.Nullable; + import java.util.Calendar; public class Time { @@ -173,6 +175,11 @@ public class Time { return (currentTime.getValue() >= startTime.getValue() && currentTime.getValue() <= endTime.getValue()); } + @Override + public boolean equals(@Nullable Object obj) { + return obj instanceof Time && this.getValue() == ((Time) obj).getValue(); + } + @Override public String toString() { return "Time{" + diff --git a/app/src/main/res/layout/timetable_lesson.xml b/app/src/main/res/layout/timetable_lesson.xml index 47892c39..25a3db56 100644 --- a/app/src/main/res/layout/timetable_lesson.xml +++ b/app/src/main/res/layout/timetable_lesson.xml @@ -8,6 +8,9 @@ + + android:text="@{Integer.toString(lessonNumber)}" + android:textSize="28sp" + android:visibility="@{lessonNumber != null ? View.VISIBLE : View.GONE}" + tools:text="3"/> diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 972b8254..2fbb3d4e 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -6,5 +6,6 @@ - + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dd006b4d..bffcc7f6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -991,4 +991,8 @@ Zastępstwo: zamiast %s Lekcja przeniesiona na godz. %s Lekcja przeniesiona na %s, godz. %s + Lekcja przeniesiona z godz. %s + Lekcja przeniesiona z dnia %s, godz. %s + Lekcja przeniesiona na inny termin + Lekcja przeniesiona z innego terminu diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 6e2b64de..b2164075 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -99,7 +99,8 @@ @drawable/timetable_lesson_bg_light #9f9f9f #ffb300 - #4caf50 + #A1887F + #4caf50