fix: double attendance + add: fake 100% attendance

This commit is contained in:
sadorowo 2024-01-03 19:24:53 +01:00
parent d0d3b11662
commit 83cf39a28c
16 changed files with 81 additions and 29 deletions

@ -19,8 +19,7 @@ interface AttendanceDao : BaseDao<Attendance> {
end: LocalDate end: LocalDate
): Flow<List<Attendance>> ): Flow<List<Attendance>>
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :start AND date <= :end" + @Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :start AND date <= :end AND (presence OR excused)")
" AND (presence OR excused)")
fun loadAllCensored( fun loadAllCensored(
diaryId: Int, diaryId: Int,
studentId: Int, studentId: Int,

@ -13,8 +13,14 @@ import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.utils.* import io.github.wulkanowy.utils.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import timber.log.Timber
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.LocalTime import java.time.LocalTime
@ -50,20 +56,26 @@ class AttendanceRepository @Inject constructor(
it.isEmpty() || forceRefresh || isExpired it.isEmpty() || forceRefresh || isExpired
}, },
query = { query = {
val badAttendanceHidden = preferencesRepository val badAttendanceHidden = false
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.BAD_ATTENDANCE)
if (badAttendanceHidden) { if (badAttendanceHidden) {
attendanceDb.loadAllCensored(semester.diaryId, semester.studentId, start, end) attendanceDb.loadAllCensored(
semester.diaryId,
semester.studentId,
start.monday,
end.sunday
)
} else { } else {
attendanceDb.loadAll(semester.diaryId, semester.studentId, start, end) attendanceDb.loadAll(
semester.diaryId,
semester.studentId,
start.monday,
end.sunday
)
} }
}, },
fetch = { fetch = {
val badAttendanceHidden = preferencesRepository val badAttendanceHidden = false
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.BAD_ATTENDANCE)
val lessons = withContext(Dispatchers.IO) { val lessons = withContext(Dispatchers.IO) {
timetableDb.load( timetableDb.load(
@ -71,17 +83,13 @@ class AttendanceRepository @Inject constructor(
) )
} }
val attendance = sdk.init(student) sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
.getAttendance(start.monday, end.sunday) .getAttendance(start.monday, end.sunday)
.filter { attendance ->
val censoredAttendance = if (badAttendanceHidden) { !badAttendanceHidden ||
attendance.filter { it.presence || it.excused } (attendance.presence || attendance.excused)
} else { }.mapToEntities(semester, lessons)
attendance
}
censoredAttendance.mapToEntities(semester, lessons)
}, },
saveFetchResult = { old, new -> saveFetchResult = { old, new ->
attendanceDb.deleteAll(old uniqueSubtract new) attendanceDb.deleteAll(old uniqueSubtract new)

@ -5,17 +5,25 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.AttendanceSummary import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.databinding.ItemAttendanceSummaryBinding import io.github.wulkanowy.databinding.ItemAttendanceSummaryBinding
import io.github.wulkanowy.databinding.ScrollableHeaderAttendanceSummaryBinding import io.github.wulkanowy.databinding.ScrollableHeaderAttendanceSummaryBinding
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.utils.calculatePercentage import io.github.wulkanowy.utils.calculatePercentage
import io.github.wulkanowy.utils.getFormattedName import io.github.wulkanowy.utils.getFormattedName
import java.time.Month import java.time.Month
import java.util.Locale import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
class AttendanceSummaryAdapter @Inject constructor() : class AttendanceSummaryAdapter @Inject constructor(
private val preferencesRepository: PreferencesRepository
) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() { RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val fake = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.ATTENDANCE)
private enum class ViewType(val id: Int) { private enum class ViewType(val id: Int) {
HEADER(1), HEADER(1),
ITEM(2) ITEM(2)
@ -48,7 +56,7 @@ class AttendanceSummaryAdapter @Inject constructor() :
} }
private fun bindHeaderViewHolder(binding: ScrollableHeaderAttendanceSummaryBinding) { private fun bindHeaderViewHolder(binding: ScrollableHeaderAttendanceSummaryBinding) {
binding.attendanceSummaryScrollableHeaderPercentage.text = formatPercentage(items.calculatePercentage()) binding.attendanceSummaryScrollableHeaderPercentage.text = formatPercentage(items.calculatePercentage(fake))
} }
private fun bindItemViewHolder(binding: ItemAttendanceSummaryBinding, position: Int) { private fun bindItemViewHolder(binding: ItemAttendanceSummaryBinding, position: Int) {
@ -60,8 +68,8 @@ class AttendanceSummaryAdapter @Inject constructor() :
else -> item.month.getFormattedName() else -> item.month.getFormattedName()
} }
attendanceSummaryPercentage.text = when (position) { attendanceSummaryPercentage.text = when (position) {
-1 -> formatPercentage(items.calculatePercentage()) -1 -> formatPercentage(items.calculatePercentage(fake))
else -> formatPercentage(item.calculatePercentage()) else -> formatPercentage(item.calculatePercentage(fake))
} }
attendanceSummaryPresent.text = item.presence.toString() attendanceSummaryPresent.text = item.presence.toString()

@ -151,7 +151,8 @@ sealed class DashboardItem(val type: Type) {
enum class HiddenSettingTile { enum class HiddenSettingTile {
BAD_GRADES, BAD_GRADES,
BAD_ATTENDANCE, BAD_ATTENDANCE,
NOTES NOTES,
ATTENDANCE,
} }
} }

@ -120,14 +120,27 @@ class DashboardPresenter @Inject constructor(
dashboardItemLoadedList.find { it is DashboardItem.HorizontalGroup } as DashboardItem.HorizontalGroup? dashboardItemLoadedList.find { it is DashboardItem.HorizontalGroup } as DashboardItem.HorizontalGroup?
if (horizontalGroup != null) { if (horizontalGroup != null) {
val fakeAttendance = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.ATTENDANCE)
val isLuckyNumberToLoad = DashboardItem.Tile.LUCKY_NUMBER in tilesToLoad val isLuckyNumberToLoad = DashboardItem.Tile.LUCKY_NUMBER in tilesToLoad
val isMessagesToLoad = DashboardItem.Tile.MESSAGES in tilesToLoad val isMessagesToLoad = DashboardItem.Tile.MESSAGES in tilesToLoad
val isAttendanceToLoad = DashboardItem.Tile.ATTENDANCE in tilesToLoad val isAttendanceToLoad = DashboardItem.Tile.ATTENDANCE in tilesToLoad
val horizontalGroupIndex = dashboardItemLoadedList.indexOf(horizontalGroup) val horizontalGroupIndex = dashboardItemLoadedList.indexOf(horizontalGroup)
// Fake 100% attendance if tweak is enabled
val newHorizontalGroup = horizontalGroup.copy( val newHorizontalGroup = horizontalGroup.copy(
attendancePercentage = horizontalGroup.attendancePercentage.takeIf { isAttendanceToLoad }, attendancePercentage = if (fakeAttendance) {
DashboardItem.HorizontalGroup.Cell(
data = 100.0,
error = false,
isLoading = false,
)
} else {
horizontalGroup.attendancePercentage.takeIf { isAttendanceToLoad }
},
unreadMessagesCount = horizontalGroup.unreadMessagesCount.takeIf { isMessagesToLoad }, unreadMessagesCount = horizontalGroup.unreadMessagesCount.takeIf { isMessagesToLoad },
luckyNumber = horizontalGroup.luckyNumber.takeIf { isLuckyNumberToLoad } luckyNumber = horizontalGroup.luckyNumber.takeIf { isLuckyNumberToLoad }
) )
@ -232,6 +245,10 @@ class DashboardPresenter @Inject constructor(
private fun loadHorizontalGroup(student: Student, forceRefresh: Boolean) { private fun loadHorizontalGroup(student: Student, forceRefresh: Boolean) {
flow { flow {
val fake = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.ATTENDANCE)
val selectedTiles = preferencesRepository.selectedDashboardTiles val selectedTiles = preferencesRepository.selectedDashboardTiles
val flowSuccess = flowOf(Resource.Success(null)) val flowSuccess = flowOf(Resource.Success(null))
@ -283,7 +300,7 @@ class DashboardPresenter @Inject constructor(
} else null } else null
}, },
attendancePercentage = DashboardItem.HorizontalGroup.Cell( attendancePercentage = DashboardItem.HorizontalGroup.Cell(
data = attendanceResource.dataOrNull?.calculatePercentage(), data = attendanceResource.dataOrNull?.calculatePercentage(fake),
error = attendanceResource.errorOrNull != null, error = attendanceResource.errorOrNull != null,
isLoading = attendanceResource is Resource.Loading, isLoading = attendanceResource is Resource.Loading,
), ),

@ -19,10 +19,18 @@ private inline val AttendanceSummary.allAbsences: Double
inline val Attendance.isExcusableOrNotExcused: Boolean inline val Attendance.isExcusableOrNotExcused: Boolean
get() = (excusable || ((absence || lateness) && !excused)) && excuseStatus == null get() = (excusable || ((absence || lateness) && !excused)) && excuseStatus == null
fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences) fun AttendanceSummary.calculatePercentage(fake: Boolean = false) = if (fake) {
100.0
} else {
calculatePercentage(allPresences, allAbsences)
}
fun List<AttendanceSummary>.calculatePercentage(): Double { fun List<AttendanceSummary>.calculatePercentage(fake: Boolean = false): Double {
return calculatePercentage(sumOf { it.allPresences }, sumOf { it.allAbsences }) return if (fake) {
100.0
} else {
calculatePercentage(sumOf { it.allPresences }, sumOf { it.allAbsences })
}
} }
private fun calculatePercentage(presence: Double, absence: Double): Double { private fun calculatePercentage(presence: Double, absence: Double): Double {

@ -72,5 +72,6 @@
<item>Špatné hodnocení</item> <item>Špatné hodnocení</item>
<item>Špatná účast</item> <item>Špatná účast</item>
<item>Poznámky</item> <item>Poznámky</item>
<item>Falešná 100% účast</item>
</string-array> </string-array>
</resources> </resources>

@ -71,5 +71,6 @@
<item>Bad grades</item> <item>Bad grades</item>
<item>Bad attendance</item> <item>Bad attendance</item>
<item>Notes</item> <item>Notes</item>
<item>Fake 100% attendance</item>
</string-array> </string-array>
</resources> </resources>

@ -71,5 +71,6 @@
<item>Schlechte Noten</item> <item>Schlechte Noten</item>
<item>Schlechte Anwesenheit</item> <item>Schlechte Anwesenheit</item>
<item>Notizen</item> <item>Notizen</item>
<item>Vorgetäuschte 100-prozentige Anwesenheit</item>
</string-array> </string-array>
</resources> </resources>

@ -71,5 +71,6 @@
<item>Bad grades</item> <item>Bad grades</item>
<item>Bad attendance</item> <item>Bad attendance</item>
<item>Notes</item> <item>Notes</item>
<item>Fake 100% attendance</item>
</string-array> </string-array>
</resources> </resources>

@ -71,5 +71,6 @@
<item>Bad grades</item> <item>Bad grades</item>
<item>Bad attendance</item> <item>Bad attendance</item>
<item>Notes</item> <item>Notes</item>
<item>Fake 100% attendance</item>
</string-array> </string-array>
</resources> </resources>

@ -71,5 +71,6 @@
<item>Słabe oceny</item> <item>Słabe oceny</item>
<item>Słaba frekwencja</item> <item>Słaba frekwencja</item>
<item>Uwagi</item> <item>Uwagi</item>
<item>Fałszywa 100% frekwencja</item>
</string-array> </string-array>
</resources> </resources>

@ -71,5 +71,6 @@
<item>Плохие оценки</item> <item>Плохие оценки</item>
<item>Плохая посещаемость</item> <item>Плохая посещаемость</item>
<item>Примечания</item> <item>Примечания</item>
<item>Фейковая 100% посещаемость</item>
</string-array> </string-array>
</resources> </resources>

@ -71,5 +71,6 @@
<item>Zlé známky</item> <item>Zlé známky</item>
<item>Zlá účasť</item> <item>Zlá účasť</item>
<item>Poznámky</item> <item>Poznámky</item>
<item>Falošná 100% účasť</item>
</string-array> </string-array>
</resources> </resources>

@ -71,5 +71,6 @@
<item>Погані оцінки</item> <item>Погані оцінки</item>
<item>Погана відвідуваність</item> <item>Погана відвідуваність</item>
<item>Примітки</item> <item>Примітки</item>
<item>Фальшива 100% явка</item>
</string-array> </string-array>
</resources> </resources>

@ -161,10 +161,12 @@
<item>Bad grades</item> <item>Bad grades</item>
<item>Bad attendance</item> <item>Bad attendance</item>
<item>Notes</item> <item>Notes</item>
<item>Fake 100% attendance</item>
</string-array> </string-array>
<string-array name="hidden_settings_values" translatable="false"> <string-array name="hidden_settings_values" translatable="false">
<item>BAD_GRADES</item> <item>BAD_GRADES</item>
<item>BAD_ATTENDANCE</item> <item>BAD_ATTENDANCE</item>
<item>NOTES</item> <item>NOTES</item>
<item>ATTENDANCE</item>
</string-array> </string-array>
</resources> </resources>