forked from github/wulkanowy-mirror
Show points sum in grades details (#664)
This commit is contained in:
parent
1999cd6eaf
commit
ae9b616896
@ -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 }
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -14,6 +14,8 @@ interface GradeDetailsView : BaseView {
|
||||
|
||||
val averageString: String
|
||||
|
||||
val pointsSumString: String
|
||||
|
||||
val weightString: String
|
||||
|
||||
val noDescriptionString: String
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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" />
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user