1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-20 01:19:08 -05:00

Show points sum in grades details (#664)

This commit is contained in:
Mikołaj Pich 2020-01-26 02:16:05 +01:00 committed by Rafał Borcz
parent 1999cd6eaf
commit ae9b616896
12 changed files with 76 additions and 50 deletions

View File

@ -18,7 +18,11 @@ class GradeAverageProvider @Inject constructor(
private val gradeSummaryRepository: GradeSummaryRepository
) {
fun getGradeAverage(student: Student, semesters: List<Semester>, selectedSemesterId: Int, forceRefresh: Boolean): Single<Map<String, Double>> {
private val plusModifier = preferencesRepository.gradePlusModifier
private val minusModifier = preferencesRepository.gradeMinusModifier
fun getGradeAverage(student: Student, semesters: List<Semester>, selectedSemesterId: Int, forceRefresh: Boolean): Single<List<Triple<String, Double, String>>> {
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<Semester>, semesterId: Int, forceRefresh: Boolean): Single<Map<String, Double>> {
private fun getAllYearAverage(student: Student, semesters: List<Semester>, semesterId: Int, forceRefresh: Boolean): Single<List<Triple<String, Double, String>>> {
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<Semester>, semesterId: Int, forceRefresh: Boolean): Single<Map<String, Double>> {
private fun getOnlyOneSemesterAverage(student: Student, semesters: List<Semester>, semesterId: Int, forceRefresh: Boolean): Single<List<Triple<String, Double, String>>> {
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<Map<String, Double>> {
private fun getAverageFromGradeSummary(selectedSemester: Semester, forceRefresh: Boolean): Maybe<List<Triple<String, Double, String>>> {
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 }
}

View File

@ -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)

View File

@ -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<GradeDetailsHeader.ViewHolder, GradeDetailsItem>() {
@ -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)

View File

@ -180,22 +180,24 @@ class GradeDetailsPresenter @Inject constructor(
}
}
private fun createGradeItems(items: Map<String, List<Grade>>, averages: Map<String, Double>): List<GradeDetailsHeader> {
private fun createGradeItems(items: Map<String, List<Grade>>, averages: List<Triple<String, Double, String>>): List<GradeDetailsHeader> {
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),

View File

@ -14,6 +14,8 @@ interface GradeDetailsView : BaseView {
val averageString: String
val pointsSumString: String
val weightString: String
val noDescriptionString: String

View File

@ -115,27 +115,26 @@ class GradeSummaryPresenter @Inject constructor(
disposable.clear()
}
private fun createGradeSummaryItemsAndHeader(gradesSummary: List<GradeSummary>, averages: Map<String, Double>)
: Pair<List<GradeSummaryItem>, GradeSummaryScrollableHeader> {
return averages.filterValues { value -> value != 0.0 }
private fun createGradeSummaryItemsAndHeader(gradesSummary: List<GradeSummary>, averages: List<Triple<String, Double, String>>): Pair<List<GradeSummaryItem>, 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<String, Double>): Boolean {
private fun checkEmpty(gradeSummary: GradeSummary, averages: List<Triple<String, Double, String>>): Boolean {
return gradeSummary.run {
finalGrade.isBlank() && predictedGrade.isBlank() && averages[subject] == null
finalGrade.isBlank() && predictedGrade.isBlank() && averages.singleOrNull { it.first == subject } == null
}
}

View File

@ -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" />

View File

@ -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">
<TextView
android:id="@+id/gradeHeaderSubject"
@ -35,6 +35,20 @@
android:textSize="12sp"
tools:text="Average: 6,00" />
<TextView
android:id="@+id/gradeHeaderPointsSum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/gradeHeaderSubject"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_toEndOf="@+id/gradeHeaderAverage"
android:layout_toRightOf="@+id/gradeHeaderAverage"
android:textColor="?android:textColorSecondary"
android:textSize="12sp"
tools:text="Points: 123/200 (61,5%)" />
<TextView
android:id="@+id/gradeHeaderNumber"
android:layout_width="wrap_content"
@ -43,8 +57,8 @@
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_toEndOf="@+id/gradeHeaderAverage"
android:layout_toRightOf="@+id/gradeHeaderAverage"
android:layout_toEndOf="@+id/gradeHeaderPointsSum"
android:layout_toRightOf="@+id/gradeHeaderPointsSum"
android:textColor="?android:textColorSecondary"
android:textSize="12sp"
tools:text="12 grades" />
@ -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"

View File

@ -72,6 +72,7 @@
<string name="grade_no_new_items">Brak nowych ocen</string>
<string name="grade_number_new_items">Ilość nowych ocen: %1$d</string>
<string name="grade_average">Średnia: %1$.2f</string>
<string name="grade_points_sum">Punkty: %s</string>
<string name="grade_no_average">Brak średniej</string>
<string name="grade_predicted">Przewidywana: %1$s</string>
<string name="grade_final">Końcowa: %1$s</string>

View File

@ -72,6 +72,7 @@
<string name="grade_no_new_items">Новые оценки отсутствуют</string>
<string name="grade_number_new_items">Количество новых оценок: %1$d</string>
<string name="grade_average">Средняя оценка: %1$.2f</string>
<string name="grade_points_sum">точек: %s</string>
<string name="grade_no_average">Средняя оценка отсутствует</string>
<string name="grade_predicted">Ожидаемая оценка: %1$s</string>
<string name="grade_final">Итоговая оценка: %1$s</string>

View File

@ -74,6 +74,7 @@
<string name="grade_no_new_items">No new grades</string>
<string name="grade_number_new_items">Number of new ratings: %1$d</string>
<string name="grade_average">Average: %1$.2f</string>
<string name="grade_points_sum">Points: %s</string>
<string name="grade_no_average">No average</string>
<string name="grade_predicted">Predicted: %1$s</string>
<string name="grade_final">Final: %1$s</string>

View File

@ -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 {