diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/usos/data/api/UsosApiExamReports.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/usos/data/api/UsosApiExamReports.kt index 48f461b4..f1e44b16 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/usos/data/api/UsosApiExamReports.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/usos/data/api/UsosApiExamReports.kt @@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.usos.data.UsosApi import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel import pl.szczodrzynski.edziennik.data.db.entity.Grade import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL +import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NO_GRADE import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.enums.MetadataType @@ -40,13 +41,13 @@ class UsosApiExamReports( tag = TAG, service = "examrep/user2", fields = listOf( + "id", "type_description", "course_unit" to listOf("id", "course_name"), "sessions" to listOf( + "number", "description", "issuer_grades" to listOf( - "exam_id", - "exam_session_number", "value_symbol", // "value_description", "passes", @@ -93,6 +94,8 @@ class UsosApiExamReports( } private fun processExamReport(termId: String, courseId: String, examReport: JsonObject) { + val examId = examReport.getString("id")?.toIntOrNull() + ?: return val typeDescription = examReport.getLangString("type_description") val courseUnit = examReport.getJsonObject("course_unit") ?: return @@ -103,16 +106,26 @@ class UsosApiExamReports( val sessions = examReport.getJsonArray("sessions") ?: return + val gradeCategory = data.gradeCategories[courseUnitId] + val classType = gradeCategory?.columns?.get(0) + + val subject = data.getSubject( + id = null, + name = courseName, + shortName = courseId, + ) + + var hasGrade = false + for (sessionEl in sessions) { if (!sessionEl.isJsonObject) continue val session = sessionEl.asJsonObject + val sessionNumber = session.getInt("number") ?: continue val sessionDescription = session.getLangString("description") - val issuerGrade = session.getJsonObject("issuer_grades") ?: continue + val issuerGrade = session.getJsonObject("issuer_grades") - val examId = issuerGrade.getInt("exam_id") ?: continue - val sessionNumber = issuerGrade.getInt("exam_session_number") ?: continue val valueSymbol = issuerGrade.getString("value_symbol") ?: continue val passes = issuerGrade.getBoolean("passes") val countsIntoAverage = issuerGrade.getString("counts_into_average") ?: "T" @@ -121,8 +134,6 @@ class UsosApiExamReports( ?.getLong("id") ?: -1L val comment = issuerGrade.getString("comment") - val gradeCategory = data.gradeCategories[courseUnitId] - val classType = gradeCategory?.columns?.get(0) val value = valueSymbol.toFloatOrNull() ?: 0.0f if (termId !in data.termNames) { @@ -142,13 +153,10 @@ class UsosApiExamReports( comment = termId, semester = 1, teacherId = modificationAuthorId, - subjectId = data.getSubject( - id = null, - name = courseName, - shortName = courseId, - ).id, + subjectId = subject.id, addedDate = Date.fromIso(dateModified), ) + hasGrade = true if (sessionNumber > 1) { val origId = examId * 10L + sessionNumber - 1 @@ -170,5 +178,35 @@ class UsosApiExamReports( ) ) } + + if (!hasGrade) { + // add an "empty" grade for the exam + val gradeObject = Grade( + profileId = profileId, + id = examId * 10L, + name = "...", + type = TYPE_NO_GRADE, + value = 0.0f, + weight = 0.0f, + color = 0xFFBABABD.toInt(), + category = typeDescription, + description = classType, + comment = termId, + semester = 1, + teacherId = -1L, + subjectId = subject.id, + addedDate = 0, + ) + data.gradeList.add(gradeObject) + data.metadataList.add( + Metadata( + profileId, + MetadataType.GRADE, + gradeObject.id, + true, + true, + ) + ) + } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Grade.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Grade.kt index 5bf3bd86..5e54dc61 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Grade.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Grade.kt @@ -55,6 +55,7 @@ open class Grade( const val TYPE_DESCRIPTIVE = 30 const val TYPE_DESCRIPTIVE_TEXT = 31 const val TYPE_TEXT = 40 + const val TYPE_NO_GRADE = 100 } @ColumnInfo(name = "gradeValueMax") diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/GradesAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/GradesAdapter.kt index e91c2e83..3979903d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/GradesAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/GradesAdapter.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.Job import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.db.entity.Grade +import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NO_GRADE import pl.szczodrzynski.edziennik.data.db.full.GradeFull import pl.szczodrzynski.edziennik.ext.onClick import pl.szczodrzynski.edziennik.ext.startCoroutineTimer @@ -235,10 +236,13 @@ class GradesAdapter( } } - if (item !is GradeFull || onGradeClick != null) + if (item !is GradeFull || (onGradeClick != null && item.type != TYPE_NO_GRADE)) { holder.itemView.setOnClickListener(onClickListener) - else + holder.itemView.isEnabled = true + } else { holder.itemView.setOnClickListener(null) + holder.itemView.isEnabled = false + } } fun notifyItemChanged(model: Any) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/GradesListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/GradesListFragment.kt index 2a15246e..ff9a843a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/GradesListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/GradesListFragment.kt @@ -18,6 +18,7 @@ import com.mikepenz.iconics.typeface.library.community.material.CommunityMateria import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.db.entity.Grade +import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NO_GRADE import pl.szczodrzynski.edziennik.data.db.enums.MetadataType import pl.szczodrzynski.edziennik.data.db.full.GradeFull import pl.szczodrzynski.edziennik.databinding.GradesListFragmentBinding @@ -305,18 +306,24 @@ class GradesListFragment : Fragment(), CoroutineScope { val semesterCount = mutableListOf() val totalSum = mutableListOf() val totalCount = mutableListOf() - val ectsPoints = mutableMapOf() + val ectsPoints = mutableMapOf, Float>() for (grade in grades) { + val pointsPair = grade.subjectId to grade.comment + if (grade.type == TYPE_NO_GRADE) + // reset points if there's an exam that isn't passed yet + ectsPoints[pointsPair] = 0.0f + if (grade.value == 0.0f || grade.weight == 0.0f) continue totalSum.add(grade.value * grade.weight) totalCount.add(grade.weight) + if (grade.value < 3.0) // exam not passed, reset points for this subject - ectsPoints[grade.subjectId] = 0.0f - else if (grade.subjectId !in ectsPoints) + ectsPoints[pointsPair] = 0.0f + else if (pointsPair !in ectsPoints) // no points for this subject, simply assign - ectsPoints[grade.subjectId] = grade.weight + ectsPoints[pointsPair] = grade.weight if (filterTermId != null && grade.comment != filterTermId) continue diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/viewholder/GradeViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/viewholder/GradeViewHolder.kt index 85684886..7c53880e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/viewholder/GradeViewHolder.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/grades/viewholder/GradeViewHolder.kt @@ -11,6 +11,7 @@ import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NO_GRADE import pl.szczodrzynski.edziennik.data.db.full.GradeFull import pl.szczodrzynski.edziennik.databinding.GradesItemGradeBinding import pl.szczodrzynski.edziennik.ui.grades.GradesAdapter @@ -59,9 +60,12 @@ class GradeViewHolder( b.gradeWeight.isVisible = weightText != null b.gradeTeacherName.text = grade.teacherName - b.gradeAddedDate.text = Date.fromMillis(grade.addedDate).let { - it.getRelativeString(app, 5) ?: it.formattedStringShort - } + if (grade.addedDate == 0L || grade.type == TYPE_NO_GRADE) + b.gradeAddedDate.text = null + else + b.gradeAddedDate.text = Date.fromMillis(grade.addedDate).let { + it.getRelativeString(app, 5) ?: it.formattedStringShort + } b.unread.isVisible = grade.showAsUnseen if (!grade.seen) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/home/cards/HomeGradesCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/home/cards/HomeGradesCard.kt index c64f2cc3..0d8d7e47 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/home/cards/HomeGradesCard.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/home/cards/HomeGradesCard.kt @@ -25,6 +25,7 @@ import kotlinx.coroutines.Job import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NO_GRADE import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Subject import pl.szczodrzynski.edziennik.data.db.full.GradeFull @@ -70,7 +71,7 @@ class HomeGradesCard( app.db.gradeDao().getAllFromDate(profile.id, sevenDaysAgo).observe(fragment, Observer { grades.apply { clear() - addAll(it) + addAll(it.filter { it.type != TYPE_NO_GRADE }) } update() }) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/GradesManager.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/GradesManager.kt index b381eb88..b8f152a0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/GradesManager.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/GradesManager.kt @@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.db.entity.Grade import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL +import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NO_GRADE import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_POINT_AVG import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_POINT_SUM import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_FINAL @@ -90,6 +91,7 @@ class GradesManager(val app: App) : CoroutineScope { else context.getString(R.string.grades_weight_format, format.format(grade.weight)) TYPE_POINT_AVG -> context.getString(R.string.grades_max_points_format, format.format(grade.valueMax)) + TYPE_NO_GRADE -> context.getString(R.string.grades_weight_no_grade) else -> null } diff --git a/app/src/main/res/layout/grades_item_stats.xml b/app/src/main/res/layout/grades_item_stats.xml index da99c686..84c05383 100644 --- a/app/src/main/res/layout/grades_item_stats.xml +++ b/app/src/main/res/layout/grades_item_stats.xml @@ -350,16 +350,14 @@ android:layout_width="1dp" android:layout_height="match_parent" android:layout_marginTop="8dp" - android:background="@drawable/divider" - android:visibility="gone" /> + android:background="@drawable/divider" /> + android:orientation="vertical"> wartość: %s waga %s nie liczona do śr. + brak oceny koniec roku: %s koniec roku: %s%% koniec roku: %spkt