[APIv2] Implement few Mobidziennik endpoints. Add grade category type.

This commit is contained in:
Kuba Szczodrzyński 2019-10-07 23:03:39 +02:00
parent 1b53c35ec5
commit 6127e574db
12 changed files with 227 additions and 30 deletions

View File

@ -19,8 +19,6 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
private const val TAG = "LibrusEndpoints" private const val TAG = "LibrusEndpoints"
} }
private var cancelled = false
init { init {
nextEndpoint(onSuccess) nextEndpoint(onSuccess)
} }
@ -31,7 +29,7 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
return return
} }
useEndpoint(data.targetEndpointIds.removeAt(0)) { useEndpoint(data.targetEndpointIds.removeAt(0)) {
if (cancelled) { if (data.cancelled) {
onSuccess() onSuccess()
return@useEndpoint return@useEndpoint
} }
@ -41,10 +39,6 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) { private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) {
Utils.d(TAG, "Using endpoint $endpointId") Utils.d(TAG, "Using endpoint $endpointId")
if (data.cancelled) {
Utils.d(TAG, "Skip endpoint $endpointId; cancelled")
return
}
when (endpointId) { when (endpointId) {
ENDPOINT_LIBRUS_API_ME -> { ENDPOINT_LIBRUS_API_ME -> {
data.startProgress(R.string.edziennik_progress_endpoint_student_info) data.startProgress(R.string.edziennik_progress_endpoint_student_info)
@ -55,7 +49,7 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
LibrusApiSchools(data) { onSuccess() } LibrusApiSchools(data) { onSuccess() }
} }
ENDPOINT_LIBRUS_API_NORMAL_GRADES -> { ENDPOINT_LIBRUS_API_NORMAL_GRADES -> {
data.startProgress(R.string.sync_action_syncing_grades) data.startProgress(R.string.edziennik_progress_endpoint_grades)
LibrusApiGrades(data) { onSuccess() } LibrusApiGrades(data) { onSuccess() }
} }
else -> onSuccess() else -> onSuccess()

View File

@ -32,7 +32,7 @@ class LibrusApiGrades(override val data: DataLibrus,
val teacherId = grade.get("AddedBy").asJsonObject.get("Id").asLong val teacherId = grade.get("AddedBy").asJsonObject.get("Id").asLong
val subjectId = grade.get("Subject").asJsonObject.get("Id").asLong val subjectId = grade.get("Subject").asJsonObject.get("Id").asLong
val category = data.gradeCategoryList.firstOrNull { it.categoryId == categoryId } val category = data.gradeCategories.singleOrNull { it.categoryId == categoryId }
val categoryName = category?.text ?: "" val categoryName = category?.text ?: ""
val color = category?.color ?: -1 val color = category?.color ?: -1
var weight = category?.weight ?: 0f var weight = category?.weight ?: 0f

View File

@ -13,6 +13,8 @@ import pl.szczodrzynski.edziennik.currentTimeUnix
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
import pl.szczodrzynski.edziennik.isNotNullNorEmpty import pl.szczodrzynski.edziennik.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) { class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
@ -76,4 +78,22 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
var webSessionIdExpiryTime: Long var webSessionIdExpiryTime: Long
get() { mWebSessionIdExpiryTime = mWebSessionIdExpiryTime ?: loginStore.getLoginData("sessionIDTime", 0L); return mWebSessionIdExpiryTime ?: 0L } get() { mWebSessionIdExpiryTime = mWebSessionIdExpiryTime ?: loginStore.getLoginData("sessionIDTime", 0L); return mWebSessionIdExpiryTime ?: 0L }
set(value) { loginStore.putLoginData("sessionIDTime", value); mWebSessionIdExpiryTime = value } set(value) { loginStore.putLoginData("sessionIDTime", value); mWebSessionIdExpiryTime = value }
val mobiLessons = mutableListOf<MobiLesson>()
data class MobiLesson(
var id: Long,
var subjectId: Long,
var teacherId: Long,
var teamId: Long,
var topic: String,
var date: Date,
var startTime: Time,
var endTime: Time,
var presentCount: Int,
var absentCount: Int,
var lessonNumber: Int,
var signed: String
)
} }

View File

@ -14,8 +14,6 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
private const val TAG = "MobidziennikData" private const val TAG = "MobidziennikData"
} }
private var cancelled = false
init { init {
nextEndpoint(onSuccess) nextEndpoint(onSuccess)
} }
@ -26,7 +24,7 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
return return
} }
useEndpoint(data.targetEndpointIds.removeAt(0)) { useEndpoint(data.targetEndpointIds.removeAt(0)) {
if (cancelled) { if (data.cancelled) {
onSuccess() onSuccess()
return@useEndpoint return@useEndpoint
} }

View File

@ -37,16 +37,18 @@ class MobidziennikApi(override val data: DataMobidziennik,
7 -> MobidziennikApiTeams(data, rows, null) 7 -> MobidziennikApiTeams(data, rows, null)
8 -> MobidziennikApiStudent(data, rows) 8 -> MobidziennikApiStudent(data, rows)
9 -> MobidziennikApiTeams(data, null, rows) 9 -> MobidziennikApiTeams(data, null, rows)
/*14 -> MobidziennikApiGradeCategories(data, rows) 14 -> MobidziennikApiGradeCategories(data, rows)
15 -> MobidziennikApiLessons(data, rows) 15 -> MobidziennikApiLessons(data, rows)
16 -> MobidziennikApiAttendance(data, rows) 16 -> MobidziennikApiAttendance(data, rows)
17 -> MobidziennikApiNotices(data, rows) /*17 -> MobidziennikApiNotices(data, rows)
18 -> MobidziennikApiGrades(data, rows) 18 -> MobidziennikApiGrades(data, rows)
21 -> MobidziennikApiEvents(data, rows) 21 -> MobidziennikApiEvents(data, rows)
23 -> MobidziennikApiHomework(data, rows) 23 -> MobidziennikApiHomework(data, rows)
24 -> MobidziennikApiTimetable(data, rows)*/ 24 -> MobidziennikApiTimetable(data, rows)*/
} }
} }
onSuccess()
} }
} }
} }

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-7.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata
import androidx.core.util.contains
import pl.szczodrzynski.edziennik.App.profileId
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.*
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
import pl.szczodrzynski.edziennik.utils.Utils.strToInt
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>) {
init { run {
for (row in rows) {
if (row.isEmpty())
continue
val cols = row.split("|")
val studentId = cols[2].toInt()
if (studentId != data.studentId)
return@run
val id = cols[0].toLong()
val lessonId = cols[1].toLong()
data.mobiLessons.singleOrNull { it.id == lessonId }?.let { lesson ->
val type = when (cols[4]) {
"2" -> TYPE_ABSENT
"5" -> TYPE_ABSENT_EXCUSED
"4" -> TYPE_RELEASED
else -> TYPE_PRESENT
}
val semester = data.profile?.dateToSemester(lesson.date) ?: 1
val attendanceObject = Attendance(
profileId,
id,
lesson.teacherId,
lesson.subjectId,
semester,
lesson.topic,
lesson.date,
lesson.startTime,
type)
data.attendanceList.add(attendanceObject)
data.metadataList.add(
Metadata(
profileId,
Metadata.TYPE_ATTENDANCE,
id,
data.profile?.empty ?: false,
data.profile?.empty ?: false,
System.currentTimeMillis()
))
}
}
}}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-7.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata
import android.graphics.Color
import androidx.core.util.contains
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
class MobidziennikApiGradeCategories(val data: DataMobidziennik, rows: List<String>) {
init {
for (row in rows) {
if (row.isEmpty())
continue
val cols = row.split("|")
val teamId = cols[1].toLong()
if (data.teamList.contains(teamId)) {
val id = cols[0].toLong()
val weight = cols[3].toFloat()
val color = Color.parseColor("#" + cols[6])
val category = cols[4]
val columns = cols[7].split(";")
data.gradeCategories.put(
id,
GradeCategory(
data.profileId,
id,
weight,
color,
category
).addColumns(columns)
)
}
}
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-7.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class MobidziennikApiLessons(val data: DataMobidziennik, rows: List<String>) {
init {
data.mobiLessons.clear()
for (row in rows) {
if (row.isEmpty())
continue
val cols = row.split("|")
val id = cols[0].toLong()
val subjectId = cols[1].toLong()
val teacherId = cols[2].toLong()
val teamId = cols[3].toLong()
val topic = cols[4]
val date = Date.fromYmd(cols[5])
val startTime = Time.fromYmdHm(cols[6])
val endTime = Time.fromYmdHm(cols[7])
val presentCount = cols[8].toInt()
val absentCount = cols[9].toInt()
val lessonNumber = cols[10].toInt()
val signed = cols[11]
val lesson = DataMobidziennik.MobiLesson(
id,
subjectId,
teacherId,
teamId,
topic,
date,
startTime,
endTime,
presentCount,
absentCount,
lessonNumber,
signed
)
data.mobiLessons.add(lesson)
}
}
}

View File

@ -5,14 +5,33 @@
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
class MobidziennikApiStudent(val data: DataMobidziennik, rows: List<String>) { class MobidziennikApiStudent(val data: DataMobidziennik, rows: List<String>) {
init { init { run {
for (row in rows) { if (rows.size < 2) {
if (row.isEmpty()) return@run
continue
// TODO
} }
val student1 = rows[0].split("|")
val student2 = rows[1].split("|")
// FROM OLD Mobidziennik API - this information seems to be unused
/*students.clear();
String[] student = table.split("\n");
for (int i = 0; i < student.length; i++) {
if (student[i].isEmpty()) {
continue;
} }
String[] student1 = student[i].split("\\|", Integer.MAX_VALUE);
String[] student2 = student[++i].split("\\|", Integer.MAX_VALUE);
students.put(strToInt(student1[0]), new Pair<>(student1, student2));
}
Pair<String[], String[]> studentData = students.get(studentId);
try {
profile.setAttendancePercentage(Float.parseFloat(studentData.second[1]));
}
catch (Exception e) {
e.printStackTrace();
}*/
}}
} }

View File

@ -2,13 +2,11 @@ package pl.szczodrzynski.edziennik.api.v2.models
import android.util.LongSparseArray import android.util.LongSparseArray
import android.util.SparseArray import android.util.SparseArray
import androidx.core.util.forEach
import androidx.core.util.isNotEmpty import androidx.core.util.isNotEmpty
import com.google.gson.JsonObject import com.google.gson.JsonObject
import im.wangchao.mhttp.Response import im.wangchao.mhttp.Response
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.api.v2.interfaces.EndpointCallback import pl.szczodrzynski.edziennik.api.v2.interfaces.EndpointCallback
import pl.szczodrzynski.edziennik.api.v2.librus.Librus
import pl.szczodrzynski.edziennik.data.api.AppError.* import pl.szczodrzynski.edziennik.data.api.AppError.*
import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement
import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer
@ -31,7 +29,6 @@ import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
import pl.szczodrzynski.edziennik.singleOrNull import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.toSparseArray import pl.szczodrzynski.edziennik.toSparseArray
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.values import pl.szczodrzynski.edziennik.values
@ -104,6 +101,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
val subjectList = LongSparseArray<Subject>() val subjectList = LongSparseArray<Subject>()
val teamList = LongSparseArray<Team>() val teamList = LongSparseArray<Team>()
val lessonRanges = SparseArray<LessonRange>() val lessonRanges = SparseArray<LessonRange>()
val gradeCategories = LongSparseArray<GradeCategory>()
private var mTeamClass: Team? = null private var mTeamClass: Team? = null
var teamClass: Team? var teamClass: Team?
@ -121,7 +119,6 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
val lessonChangeList = mutableListOf<LessonChange>() val lessonChangeList = mutableListOf<LessonChange>()
var gradesToRemove: DataRemoveModel? = null var gradesToRemove: DataRemoveModel? = null
val gradeCategoryList = mutableListOf<GradeCategory>()
val gradeList = mutableListOf<Grade>() val gradeList = mutableListOf<Grade>()
var eventsToRemove: DataRemoveModel? = null var eventsToRemove: DataRemoveModel? = null
@ -156,6 +153,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
db.subjectDao().getAllNow(profileId).toSparseArray(subjectList) { it.id } db.subjectDao().getAllNow(profileId).toSparseArray(subjectList) { it.id }
db.teamDao().getAllNow(profileId).toSparseArray(teamList) { it.id } db.teamDao().getAllNow(profileId).toSparseArray(teamList) { it.id }
db.lessonRangeDao().getAllNow(profileId).toSparseArray(lessonRanges) { it.lessonNumber } db.lessonRangeDao().getAllNow(profileId).toSparseArray(lessonRanges) { it.lessonNumber }
db.gradeCategoryDao().getAllNow(profileId).toSparseArray(gradeCategories) { it.categoryId }
} }
/*val teacher = teachers.byNameFirstLast("Jan Kowalski") ?: Teacher(1, 1, "", "").let { /*val teacher = teachers.byNameFirstLast("Jan Kowalski") ?: Teacher(1, 1, "", "").let {
@ -175,7 +173,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
lessonList.clear() lessonList.clear()
lessonChangeList.clear() lessonChangeList.clear()
gradeCategoryList.clear() gradeCategories.clear()
gradeList.clear() gradeList.clear()
eventTypeList.clear() eventTypeList.clear()
noticeList.clear() noticeList.clear()
@ -204,6 +202,8 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
db.teamDao().addAll(teamList.values()) db.teamDao().addAll(teamList.values())
db.lessonRangeDao().clear(profileId) db.lessonRangeDao().clear(profileId)
db.lessonRangeDao().addAll(lessonRanges.values()) db.lessonRangeDao().addAll(lessonRanges.values())
db.gradeCategoryDao().clear(profileId)
db.gradeCategoryDao().addAll(gradeCategories.values())
if (lessonList.isNotEmpty()) { if (lessonList.isNotEmpty()) {
db.lessonDao().clear(profile.id) db.lessonDao().clear(profile.id)
@ -211,8 +211,6 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
} }
if (lessonChangeList.isNotEmpty()) if (lessonChangeList.isNotEmpty())
db.lessonChangeDao().addAll(lessonChangeList) db.lessonChangeDao().addAll(lessonChangeList)
if (gradeCategoryList.isNotEmpty())
db.gradeCategoryDao().addAll(gradeCategoryList)
if (gradeList.isNotEmpty()) { if (gradeList.isNotEmpty()) {
db.gradeDao().clear(profile.id) db.gradeDao().clear(profile.id)
db.gradeDao().addAll(gradeList) db.gradeDao().addAll(gradeList)

View File

@ -87,7 +87,7 @@ import android.content.Context;
DebugLog.class, DebugLog.class,
EndpointTimer.class, EndpointTimer.class,
LessonRange.class, LessonRange.class,
Metadata.class}, version = 56) Metadata.class}, version = 57)
@TypeConverters({ @TypeConverters({
ConverterTime.class, ConverterTime.class,
ConverterDate.class, ConverterDate.class,
@ -591,6 +591,12 @@ public abstract class AppDb extends RoomDatabase {
")"); ")");
} }
}; };
private static final Migration MIGRATION_56_57 = new Migration(56, 57) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE gradeCategories ADD type INTEGER NOT NULL DEFAULT 0");
}
};
public static AppDb getDatabase(final Context context) { public static AppDb getDatabase(final Context context) {
@ -644,7 +650,8 @@ public abstract class AppDb extends RoomDatabase {
MIGRATION_52_53, MIGRATION_52_53,
MIGRATION_53_54, MIGRATION_53_54,
MIGRATION_54_55, MIGRATION_54_55,
MIGRATION_55_56 MIGRATION_55_56,
MIGRATION_56_57
) )
.allowMainThreadQueries() .allowMainThreadQueries()
//.fallbackToDestructiveMigration() //.fallbackToDestructiveMigration()

View File

@ -18,6 +18,13 @@ public class GradeCategory {
public float valueFrom = 0; public float valueFrom = 0;
public float valueTo = 0; public float valueTo = 0;
/**
* A general purpose category type.
*
* The Grade category is used only in API to cache the e-register's categories.
*/
public int type = 0;
public GradeCategory(int profileId, long categoryId, float weight, int color, String text) { public GradeCategory(int profileId, long categoryId, float weight, int color, String text) {
this.profileId = profileId; this.profileId = profileId;
this.categoryId = categoryId; this.categoryId = categoryId;