[UI/Grades] Add config options for university grades

This commit is contained in:
Kuba Szczodrzyński 2025-02-01 23:00:21 +01:00
parent 29971777a7
commit db444d89f0
No known key found for this signature in database
GPG Key ID: 43037AC62A600562
6 changed files with 132 additions and 15 deletions

View File

@ -4,6 +4,7 @@
package pl.szczodrzynski.edziennik.config
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.UNIVERSITY_AVERAGE_MODE_ECTS
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_ALL_GRADES
@ -15,8 +16,11 @@ class ProfileConfigGrades(base: ProfileConfig) {
var dontCountEnabled by base.config<Boolean>(false)
var dontCountGrades by base.config<List<String>> { listOf() }
var hideImproved by base.config<Boolean>(false)
var hideNoGrade by base.config<Boolean>(false)
var hideSticksFromOld by base.config<Boolean>(false)
var minusValue by base.config<Float?>(null)
var plusValue by base.config<Float?>(null)
var yearAverageMode by base.config<Int>(YEAR_ALL_GRADES)
var universityAverageMode by base.config<Int>(UNIVERSITY_AVERAGE_MODE_ECTS)
var countEctsInProgress by base.config<Boolean>(false)
}

View File

@ -21,6 +21,8 @@ import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_M
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.ORDER_BY_DATE_DESC
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.ORDER_BY_SUBJECT_ASC
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.UNIVERSITY_AVERAGE_MODE_ECTS
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.UNIVERSITY_AVERAGE_MODE_SIMPLE
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_1_AVG_2_AVG
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_1_AVG_2_SEM
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_1_SEM_2_AVG
@ -47,6 +49,8 @@ class GradesConfigDialog(
@SuppressLint("SetTextI18n")
override suspend fun loadConfig() {
b.isUniversity = app.gradesManager.isUniversity
b.customPlusCheckBox.isChecked = app.profile.config.grades.plusValue != null
b.customPlusValue.isVisible = b.customPlusCheckBox.isChecked
b.customMinusCheckBox.isChecked = app.profile.config.grades.minusValue != null
@ -76,10 +80,18 @@ class GradesConfigDialog(
else -> null
}?.isChecked = true
when (app.profile.config.grades.universityAverageMode) {
UNIVERSITY_AVERAGE_MODE_ECTS -> b.gradeUniversityAverageMode1
UNIVERSITY_AVERAGE_MODE_SIMPLE -> b.gradeUniversityAverageMode0
else -> null
}?.isChecked = true
b.dontCountGrades.isChecked =
app.profile.config.grades.dontCountEnabled && app.profile.config.grades.dontCountGrades.isNotEmpty()
b.hideImproved.isChecked = app.profile.config.grades.hideImproved
b.hideNoGrade.isChecked = app.profile.config.grades.hideNoGrade
b.averageWithoutWeight.isChecked = app.profile.config.grades.averageWithoutWeight
b.countEctsInProgress.isChecked = app.profile.config.grades.countEctsInProgress
if (app.profile.config.grades.dontCountGrades.isEmpty()) {
b.dontCountGradesText.setText("nb, 0, bz, bd")
@ -149,10 +161,21 @@ class GradesConfigDialog(
app.profile.config.grades.yearAverageMode = YEAR_1_SEM_2_SEM
}
b.gradeUniversityAverageMode1.setOnSelectedListener {
app.profile.config.grades.universityAverageMode = UNIVERSITY_AVERAGE_MODE_ECTS
}
b.gradeUniversityAverageMode0.setOnSelectedListener {
app.profile.config.grades.universityAverageMode = UNIVERSITY_AVERAGE_MODE_SIMPLE
}
b.hideImproved.onChange { _, isChecked -> app.profile.config.grades.hideImproved = isChecked }
b.hideNoGrade.onChange { _, isChecked -> app.profile.config.grades.hideNoGrade = isChecked }
b.averageWithoutWeight.onChange { _, isChecked ->
app.profile.config.grades.averageWithoutWeight = isChecked
}
b.countEctsInProgress.onChange { _, isChecked ->
app.profile.config.grades.countEctsInProgress = isChecked
}
b.averageWithoutWeightHelp.onClick {
MaterialAlertDialogBuilder(activity)

View File

@ -31,6 +31,8 @@ import pl.szczodrzynski.edziennik.ui.grades.models.GradesStats
import pl.szczodrzynski.edziennik.ui.grades.models.GradesSubject
import pl.szczodrzynski.edziennik.utils.TextInputDropDown
import pl.szczodrzynski.edziennik.utils.managers.GradesManager
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.UNIVERSITY_AVERAGE_MODE_ECTS
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.UNIVERSITY_AVERAGE_MODE_SIMPLE
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
import kotlin.coroutines.CoroutineContext
@ -222,7 +224,9 @@ class GradesListFragment : Fragment(), CoroutineScope {
val isUniversity = manager.isUniversity
val filterTermId = b.semesterDropdown.selected?.tag
val hideImproved = manager.hideImproved
val hideNoGrade = app.profile.config.grades.hideNoGrade
val countEctsInProgress = app.profile.config.grades.countEctsInProgress
val universityAverageMode = app.profile.config.grades.universityAverageMode
// grades returned by the query are ordered
// by the subject ID, so it's easier and probably
@ -231,6 +235,9 @@ class GradesListFragment : Fragment(), CoroutineScope {
if (isUniversity && filterTermId != null && grade.comment != filterTermId)
continue
if (hideNoGrade && grade.type == TYPE_NO_GRADE)
continue
/*if (grade.parentId != null && grade.parentId != -1L)
continue // the grade is hidden as a new, improved one is available*/
if (grade.subjectId != subjectId) {
@ -309,13 +316,16 @@ class GradesListFragment : Fragment(), CoroutineScope {
val ectsPoints = mutableMapOf<Pair<Long, String?>, Float>()
for (grade in grades) {
val pointsPair = grade.subjectId to grade.comment
if (grade.type == TYPE_NO_GRADE)
if (grade.type == TYPE_NO_GRADE && !countEctsInProgress)
// 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)
if (universityAverageMode == UNIVERSITY_AVERAGE_MODE_ECTS)
totalSum.add(grade.value * grade.weight)
else
totalSum.add(grade.value)
totalCount.add(grade.weight)
if (grade.value < 3.0)
@ -328,11 +338,22 @@ class GradesListFragment : Fragment(), CoroutineScope {
if (filterTermId != null && grade.comment != filterTermId)
continue
semesterSum.add(grade.value * grade.weight)
if (universityAverageMode == UNIVERSITY_AVERAGE_MODE_ECTS)
semesterSum.add(grade.value * grade.weight)
else
semesterSum.add(grade.value)
semesterCount.add(grade.weight)
}
stats.universitySem = semesterSum.sum() / semesterCount.sum()
stats.universityTotal = totalSum.sum() / totalCount.sum()
when (universityAverageMode) {
UNIVERSITY_AVERAGE_MODE_SIMPLE -> {
stats.universitySem = semesterSum.sum() / semesterCount.size
stats.universityTotal = totalSum.sum() / totalCount.size
}
UNIVERSITY_AVERAGE_MODE_ECTS -> {
stats.universitySem = semesterSum.sum() / semesterCount.sum()
stats.universityTotal = totalSum.sum() / totalCount.sum()
}
}
stats.universityEcts = ectsPoints.values.sum()
return (items + stats).toMutableList()
}

View File

@ -44,6 +44,8 @@ class GradesManager(val app: App) : CoroutineScope {
const val YEAR_ALL_GRADES = 4
const val COLOR_MODE_DEFAULT = 0
const val COLOR_MODE_WEIGHTED = 1
const val UNIVERSITY_AVERAGE_MODE_SIMPLE = 0
const val UNIVERSITY_AVERAGE_MODE_ECTS = 1
}
private val job = Job()

View File

@ -6,6 +6,14 @@
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="isUniversity"
type="boolean" />
</data>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
@ -19,16 +27,18 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"
android:layout_marginTop="16dp"
style="@style/TextAppearance.AppCompat.Small"
android:text="@string/grades_config_title"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
android:orientation="horizontal"
android:isVisible="@{!isUniversity}">
<CheckBox
android:id="@+id/customPlusCheckBox"
@ -54,7 +64,8 @@
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:gravity="center_vertical"
android:orientation="horizontal">
android:orientation="horizontal"
android:isVisible="@{!isUniversity}">
<CheckBox
android:id="@+id/customMinusCheckBox"
@ -79,14 +90,16 @@
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="6dp"
android:background="@drawable/divider"/>
android:background="@drawable/divider"
android:isVisible="@{!isUniversity}" />
<CheckBox
android:id="@+id/dontCountGrades"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="0dp"
android:text="@string/grades_config_dont_count_grades"/>
android:text="@string/grades_config_dont_count_grades"
android:isVisible="@{!isUniversity}" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
@ -94,7 +107,8 @@
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:hint="@string/grades_config_dont_count_hint"
app:placeholderText="@string/grades_config_dont_count_placeholder"
android:enabled="@{dontCountGrades.checked}">
android:enabled="@{dontCountGrades.checked}"
android:isVisible="@{!isUniversity}">
<pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
android:id="@+id/dontCountGradesText"
@ -111,10 +125,19 @@
android:minHeight="32dp"
android:text="@string/grades_config_dont_show_improved"/>
<CheckBox
android:id="@+id/hideNoGrade"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="32dp"
android:text="@string/grades_config_hide_no_grade"
android:isVisible="@{isUniversity}" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:isVisible="@{!isUniversity}">
<CheckBox
android:id="@+id/averageWithoutWeight"
@ -136,6 +159,14 @@
tools:src="@android:drawable/ic_menu_help" />
</LinearLayout>
<CheckBox
android:id="@+id/countEctsInProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="32dp"
android:text="@string/grades_config_ects_in_progress"
android:isVisible="@{isUniversity}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -195,11 +226,13 @@
android:layout_marginTop="8dp"
android:layout_marginBottom="4dp"
style="@style/TextAppearance.AppCompat.Small"
android:text="@string/menu_grades_average_mode"/>
android:text="@string/menu_grades_average_mode"
android:isVisible="@{!isUniversity}" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:isVisible="@{!isUniversity}">
<RadioButton
android:id="@+id/gradeAverageMode4"
@ -236,6 +269,35 @@
android:minHeight="0dp"
android:text="@string/settings_register_avg_mode_3"/>
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="4dp"
style="@style/TextAppearance.AppCompat.Small"
android:text="@string/menu_grades_university_average_mode"
android:isVisible="@{isUniversity}" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isVisible="@{isUniversity}">
<RadioButton
android:id="@+id/gradeUniversityAverageMode1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="0dp"
android:text="@string/settings_register_university_avg_mode_1"/>
<RadioButton
android:id="@+id/gradeUniversityAverageMode0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="0dp"
android:text="@string/settings_register_university_avg_mode_0"/>
</RadioGroup>
</LinearLayout>
</ScrollView>
</layout>

View File

@ -445,6 +445,8 @@
<string name="grades_config_dont_count_hint">Oceny oddziel przecinkiem</string>
<string name="grades_config_dont_count_placeholder">Podaj oceny…</string>
<string name="grades_config_dont_show_improved">Ukrywaj oceny poprawione z listy</string>
<string name="grades_config_ects_in_progress">Licz ECTS przed zaliczeniem całego przedmiotu</string>
<string name="grades_config_hide_no_grade">Ukrywaj pozycje \"brak oceny\"</string>
<string name="grades_config_minus_value">Własna wartość minusa</string>
<string name="grades_config_plus_value">Własna wartość plusa</string>
<string name="grades_config_title">Konfiguracja ocen</string>
@ -695,6 +697,7 @@
<string name="menu_grades_config">Ustawienia ocen</string>
<string name="menu_grades_editor">Symulator edycji ocen</string>
<string name="menu_grades_sort_mode">Sortuj oceny</string>
<string name="menu_grades_university_average_mode">Sposób obliczania średniej za studia</string>
<string name="menu_help">Pomoc</string>
<string name="menu_home_page">Strona główna</string>
<string name="menu_homework">Zadania domowe</string>
@ -976,6 +979,8 @@
<string name="settings_register_dont_count_zero_text">Nie wliczaj oceny 0 do średniej</string>
<string name="settings_register_login_not_implemented_text">Ten e-dziennik nie został jeszcze zaimplementowany w aplikacji.</string>
<string name="settings_register_show_teacher_absences_text">Pokazuj nieobecności nauczycieli w Terminarzu</string>
<string name="settings_register_university_avg_mode_0">Średnia arytmetyczna ocen</string>
<string name="settings_register_university_avg_mode_1">Średnia ważona ocen (ECTS = waga)</string>
<string name="settings_sync_customize_endpoint_announcements">Tablica ogłoszeń</string>
<string name="settings_sync_customize_endpoint_attendance">Obecności/nieobecności</string>
<string name="settings_sync_customize_endpoint_class_free_days">Dni wolne klasy</string>