From ae9b6168962f074fa4c2c0c768781fc224d282be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 26 Jan 2020 02:16:05 +0100 Subject: [PATCH] Show points sum in grades details (#664) --- .../ui/modules/grade/GradeAverageProvider.kt | 22 +++++++------- .../grade/details/GradeDetailsFragment.kt | 3 ++ .../grade/details/GradeDetailsHeader.kt | 3 ++ .../grade/details/GradeDetailsPresenter.kt | 16 +++++----- .../modules/grade/details/GradeDetailsView.kt | 2 ++ .../grade/summary/GradeSummaryPresenter.kt | 17 +++++------ .../main/res/layout/fragment_attendance.xml | 2 +- .../main/res/layout/header_grade_details.xml | 30 ++++++++++++++----- app/src/main/res/values-pl/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + .../modules/grade/GradeAverageProviderTest.kt | 28 ++++++++--------- 12 files changed, 76 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt index 88635c37b..37bba4d43 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt @@ -18,7 +18,11 @@ class GradeAverageProvider @Inject constructor( private val gradeSummaryRepository: GradeSummaryRepository ) { - fun getGradeAverage(student: Student, semesters: List, selectedSemesterId: Int, forceRefresh: Boolean): Single> { + private val plusModifier = preferencesRepository.gradePlusModifier + + private val minusModifier = preferencesRepository.gradeMinusModifier + + fun getGradeAverage(student: Student, semesters: List, selectedSemesterId: Int, forceRefresh: Boolean): Single>> { return when (preferencesRepository.gradeAverageMode) { "all_year" -> getAllYearAverage(student, semesters, selectedSemesterId, forceRefresh) "only_one_semester" -> getOnlyOneSemesterAverage(student, semesters, selectedSemesterId, forceRefresh) @@ -26,11 +30,9 @@ class GradeAverageProvider @Inject constructor( } } - private fun getAllYearAverage(student: Student, semesters: List, semesterId: Int, forceRefresh: Boolean): Single> { + private fun getAllYearAverage(student: Student, semesters: List, semesterId: Int, forceRefresh: Boolean): Single>> { val selectedSemester = semesters.single { it.semesterId == semesterId } val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 } - val plusModifier = preferencesRepository.gradePlusModifier - val minusModifier = preferencesRepository.gradeMinusModifier return getAverageFromGradeSummary(selectedSemester, forceRefresh) .switchIfEmpty(gradeRepository.getGrades(student, selectedSemester, forceRefresh) @@ -43,30 +45,28 @@ class GradeAverageProvider @Inject constructor( }.map { grades -> grades.map { if (student.loginMode == Sdk.Mode.SCRAPPER.name) it.changeModifier(plusModifier, minusModifier) else it } .groupBy { it.subject } - .mapValues { it.value.calcAverage() } + .map { Triple(it.key, it.value.calcAverage(), "") } }) } - private fun getOnlyOneSemesterAverage(student: Student, semesters: List, semesterId: Int, forceRefresh: Boolean): Single> { + private fun getOnlyOneSemesterAverage(student: Student, semesters: List, semesterId: Int, forceRefresh: Boolean): Single>> { val selectedSemester = semesters.single { it.semesterId == semesterId } - val plusModifier = preferencesRepository.gradePlusModifier - val minusModifier = preferencesRepository.gradeMinusModifier return getAverageFromGradeSummary(selectedSemester, forceRefresh) .switchIfEmpty(gradeRepository.getGrades(student, selectedSemester, forceRefresh) .map { grades -> grades.map { if (student.loginMode == Sdk.Mode.SCRAPPER.name) it.changeModifier(plusModifier, minusModifier) else it } .groupBy { it.subject } - .mapValues { it.value.calcAverage() } + .map { Triple(it.key, it.value.calcAverage(), "") } }) } - private fun getAverageFromGradeSummary(selectedSemester: Semester, forceRefresh: Boolean): Maybe> { + private fun getAverageFromGradeSummary(selectedSemester: Semester, forceRefresh: Boolean): Maybe>> { return gradeSummaryRepository.getGradesSummary(selectedSemester, forceRefresh) .toMaybe() .flatMap { if (it.any { summary -> summary.average != .0 }) { - Maybe.just(it.map { summary -> summary.subject to summary.average }.toMap()) + Maybe.just(it.map { summary -> Triple(summary.subject, summary.average, summary.pointsSum) }) } else Maybe.empty() }.filter { !preferencesRepository.gradeAverageForceCalc } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt index 195ae11df..9505d354f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt @@ -45,6 +45,9 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh override val averageString: String get() = getString(R.string.grade_average) + override val pointsSumString: String + get() = getString(R.string.grade_points_sum) + override val weightString: String get() = getString(R.string.grade_weight) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsHeader.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsHeader.kt index 9ed412808..4a34a1457 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsHeader.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsHeader.kt @@ -15,6 +15,7 @@ class GradeDetailsHeader( private val subject: String, private val number: String, private val average: String, + private val pointsSum: String, var newGrades: Int, private val isExpandable: Boolean ) : AbstractExpandableItem() { @@ -36,6 +37,8 @@ class GradeDetailsHeader( maxLines = if (isExpanded) 2 else 1 } gradeHeaderAverage.text = average + gradeHeaderPointsSum.text = pointsSum + gradeHeaderPointsSum.visibility = if (pointsSum.isNotEmpty()) VISIBLE else GONE gradeHeaderNumber.text = number gradeHeaderNote.visibility = if (newGrades > 0) VISIBLE else GONE if (newGrades > 0) gradeHeaderNote.text = newGrades.toString(10) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt index 647047c69..a9e5b2b7d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt @@ -180,22 +180,24 @@ class GradeDetailsPresenter @Inject constructor( } } - private fun createGradeItems(items: Map>, averages: Map): List { + private fun createGradeItems(items: Map>, averages: List>): List { val isGradeExpandable = preferencesRepository.isGradeExpandable val gradeColorTheme = preferencesRepository.gradeColorTheme val noDescriptionString = view?.noDescriptionString.orEmpty() val weightString = view?.weightString.orEmpty() + val pointsSumString = view?.pointsSumString.orEmpty() - return items.map { + return items.map { subject -> GradeDetailsHeader( - subject = it.key, - average = formatAverage(averages[it.key]), - number = view?.getGradeNumberString(it.value.size).orEmpty(), - newGrades = it.value.filter { grade -> !grade.isRead }.size, + subject = subject.key, + average = formatAverage(averages.singleOrNull { subject.key == it.first }?.second), + pointsSum = averages.singleOrNull { subject.key == it.first }?.takeIf { it.third.isNotEmpty() }?.let { pointsSumString.format(it.third) }.orEmpty(), + number = view?.getGradeNumberString(subject.value.size).orEmpty(), + newGrades = subject.value.filter { grade -> !grade.isRead }.size, isExpandable = isGradeExpandable ).apply { - subItems = it.value.map { item -> + subItems = subject.value.map { item -> GradeDetailsItem( grade = item, valueBgColor = item.getBackgroundColor(gradeColorTheme), diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt index dad4ac6eb..e2977bcbe 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt @@ -14,6 +14,8 @@ interface GradeDetailsView : BaseView { val averageString: String + val pointsSumString: String + val weightString: String val noDescriptionString: String diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt index 1aaa9d097..5f4412773 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt @@ -115,27 +115,26 @@ class GradeSummaryPresenter @Inject constructor( disposable.clear() } - private fun createGradeSummaryItemsAndHeader(gradesSummary: List, averages: Map) - : Pair, GradeSummaryScrollableHeader> { - return averages.filterValues { value -> value != 0.0 } + private fun createGradeSummaryItemsAndHeader(gradesSummary: List, averages: List>): Pair, GradeSummaryScrollableHeader> { + return averages.filter { value -> value.second != 0.0 } .let { filteredAverages -> gradesSummary.filter { !checkEmpty(it, filteredAverages) } - .map { + .map { gradeSummary -> GradeSummaryItem( - summary = it, - average = formatAverage(filteredAverages.getOrElse(it.subject) { 0.0 }, "") + summary = gradeSummary, + average = formatAverage(filteredAverages.singleOrNull { gradeSummary.subject == it.first }?.second ?: .0, "") ) }.let { it to GradeSummaryScrollableHeader( formatAverage(gradesSummary.calcAverage()), - formatAverage(filteredAverages.values.average())) + formatAverage(filteredAverages.map { values -> values.second }.average())) } } } - private fun checkEmpty(gradeSummary: GradeSummary, averages: Map): Boolean { + private fun checkEmpty(gradeSummary: GradeSummary, averages: List>): Boolean { return gradeSummary.run { - finalGrade.isBlank() && predictedGrade.isBlank() && averages[subject] == null + finalGrade.isBlank() && predictedGrade.isBlank() && averages.singleOrNull { it.first == subject } == null } } diff --git a/app/src/main/res/layout/fragment_attendance.xml b/app/src/main/res/layout/fragment_attendance.xml index 47561c456..cd8b60364 100644 --- a/app/src/main/res/layout/fragment_attendance.xml +++ b/app/src/main/res/layout/fragment_attendance.xml @@ -64,9 +64,9 @@ android:layout_margin="16dp" android:clickable="true" android:focusable="true" + android:text="@string/attendance_excuse_title" android:tint="?colorOnSecondary" android:visibility="gone" - android:text="@string/attendance_excuse_title" app:icon="@drawable/ic_all_done_all" tools:visibility="visible" /> diff --git a/app/src/main/res/layout/header_grade_details.xml b/app/src/main/res/layout/header_grade_details.xml index bb78a2898..75e01745f 100644 --- a/app/src/main/res/layout/header_grade_details.xml +++ b/app/src/main/res/layout/header_grade_details.xml @@ -4,13 +4,13 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?selectableItemBackground" + android:paddingStart="16dp" android:paddingLeft="16dp" android:paddingTop="10dp" + android:paddingEnd="12dp" android:paddingRight="14dp" android:paddingBottom="10dp" - tools:context=".ui.modules.grade.details.GradeDetailsHeader" - android:paddingEnd="12dp" - android:paddingStart="16dp"> + tools:context=".ui.modules.grade.details.GradeDetailsHeader"> + + @@ -53,13 +67,13 @@ android:id="@+id/gradeHeaderNote" android:layout_width="wrap_content" android:layout_height="20dp" + android:layout_alignParentEnd="true" + android:layout_alignParentRight="true" + android:layout_marginTop="10dp" android:background="@drawable/background_header_note" android:gravity="center" android:minWidth="20dp" - android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:paddingLeft="5dp" - android:layout_marginTop="10dp" android:paddingRight="5dp" android:textColor="?colorOnPrimary" android:textSize="14sp" diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index f5f9f45d1..5a1ac4704 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -72,6 +72,7 @@ Brak nowych ocen Ilość nowych ocen: %1$d Średnia: %1$.2f + Punkty: %s Brak średniej Przewidywana: %1$s Końcowa: %1$s diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 062386dc3..5698b35a2 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -72,6 +72,7 @@ Новые оценки отсутствуют Количество новых оценок: %1$d Средняя оценка: %1$.2f + точек: %s Средняя оценка отсутствует Ожидаемая оценка: %1$s Итоговая оценка: %1$s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 08b17825a..3fa133c9f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -74,6 +74,7 @@ No new grades Number of new ratings: %1$d Average: %1$.2f + Points: %s No average Predicted: %1$s Final: %1$s diff --git a/app/src/test/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProviderTest.kt b/app/src/test/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProviderTest.kt index 56b1e66f8..432ca6d99 100644 --- a/app/src/test/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProviderTest.kt +++ b/app/src/test/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProviderTest.kt @@ -80,8 +80,8 @@ class GradeAverageProviderTest { .blockingGet() assertEquals(2, averages.size) - assertEquals(2.5, averages["Matematyka"]) - assertEquals(3.0, averages["Fizyka"]) + assertEquals(2.5, averages.single { it.first == "Matematyka" }.second, .0) + assertEquals(3.0, averages.single { it.first == "Fizyka" }.second, .0) } @Test @@ -93,7 +93,7 @@ class GradeAverageProviderTest { val averages = gradeAverageProvider.getGradeAverage(student, semesters, semesters[2].semesterId, true) .blockingGet() - assertEquals(3.5, averages["Język polski"]) + assertEquals(3.5, averages.single { it.first == "Język polski" }.second, .0) } @Test @@ -105,7 +105,7 @@ class GradeAverageProviderTest { val averages = gradeAverageProvider.getGradeAverage(student.copy(loginMode = Sdk.Mode.API.name), semesters, semesters[2].semesterId, true) .blockingGet() - assertEquals(3.375, averages["Język polski"]) + assertEquals(3.375, averages.single { it.first == "Język polski" }.second, .0) } @Test @@ -117,7 +117,7 @@ class GradeAverageProviderTest { val averages = gradeAverageProvider.getGradeAverage(student.copy(loginMode = Sdk.Mode.SCRAPPER.name), semesters, semesters[2].semesterId, true) .blockingGet() - assertEquals(3.5, averages["Język polski"]) + assertEquals(3.5, averages.single { it.first == "Język polski" }.second, .0) } @Test @@ -129,7 +129,7 @@ class GradeAverageProviderTest { val averages = gradeAverageProvider.getGradeAverage(student.copy(loginMode = Sdk.Mode.HYBRID.name), semesters, semesters[2].semesterId, true) .blockingGet() - assertEquals(3.375, averages["Język polski"]) + assertEquals(3.375, averages.single { it.first == "Język polski" }.second, .0) } @Test @@ -141,8 +141,8 @@ class GradeAverageProviderTest { .blockingGet() assertEquals(2, averages.size) - assertEquals(3.5, averages["Matematyka"]) - assertEquals(3.5, averages["Fizyka"]) + assertEquals(3.5, averages.single { it.first == "Matematyka" }.second, .0) + assertEquals(3.5, averages.single { it.first == "Fizyka" }.second, .0) } @Test @@ -155,8 +155,8 @@ class GradeAverageProviderTest { .blockingGet() assertEquals(2, averages.size) - assertEquals(3.0, averages["Matematyka"]) - assertEquals(3.25, averages["Fizyka"]) + assertEquals(3.0, averages.single { it.first == "Matematyka" }.second, .0) + assertEquals(3.25, averages.single { it.first == "Fizyka" }.second, .0) } @Test(expected = IllegalArgumentException::class) @@ -179,8 +179,8 @@ class GradeAverageProviderTest { .blockingGet() assertEquals(2, averages.size) - assertEquals(3.1, averages["Matematyka"]) - assertEquals(3.26, averages["Fizyka"]) + assertEquals(3.1, averages.single { it.first == "Matematyka" }.second, .0) + assertEquals(3.26, averages.single { it.first == "Fizyka" }.second, .0) } @Test @@ -197,8 +197,8 @@ class GradeAverageProviderTest { .blockingGet() assertEquals(2, averages.size) - assertEquals(3.0, averages["Matematyka"]) - assertEquals(3.25, averages["Fizyka"]) + assertEquals(3.0, averages.single { it.first == "Matematyka" }.second, .0) + assertEquals(3.25, averages.single { it.first == "Fizyka" }.second, .0) } private fun getGrade(semesterId: Int, subject: String, value: Double, modifier: Double = 0.0): Grade {