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

View File

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

View File

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

View File

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

View File

@ -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,
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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