Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Commit

Permalink
Risk representation for the contact journal according to the newest t…
Browse files Browse the repository at this point in the history
…ech spec (EXPOSUREAPP-5413) (#2754)

* Sort events by trace location description

* Get trace location description from CheckInRepository

* Adjusted test to changes in view model, Use hardcoded date

* Adjusted test

* sourceCheck CleanUp

* LongParameterList handling

* Also check if description was mapped from check in

* avoid suppressing LongParameterLister

* ups

Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com>
  • Loading branch information
BMItr and harambasicluka authored Apr 7, 2021
1 parent 53cf44c commit 1fbf873
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem
import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem
import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem
import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem
import de.rki.coronawarnapp.eventregistration.checkins.CheckInRepository
import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
import de.rki.coronawarnapp.task.TaskController
import de.rki.coronawarnapp.util.TimeStamper
Expand Down Expand Up @@ -47,6 +48,7 @@ class ContactDiaryOverviewFragmentTest : BaseUITest() {
@MockK lateinit var riskLevelStorage: RiskLevelStorage
@MockK lateinit var timeStamper: TimeStamper
@MockK lateinit var exporter: ContactDiaryExporter
@MockK lateinit var checkInRepository: CheckInRepository

private lateinit var viewModel: ContactDiaryOverviewViewModel

Expand All @@ -63,6 +65,7 @@ class ContactDiaryOverviewFragmentTest : BaseUITest() {
contactDiaryRepository = contactDiaryRepository,
riskLevelStorage = riskLevelStorage,
timeStamper = timeStamper,
checkInRepository = checkInRepository,
exporter = exporter
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,14 @@ object DiaryData {

val HIGH_RISK_EVENT = RiskEventItem.Event(
name = HIGH_RISK_EVENT_LOCATION.name,
description = "2",
bulledPointColor = R.color.colorBulletPointHighRisk,
riskInfoAddition = R.string.contact_diary_trace_location_risk_high
)

val LOW_RISK_EVENT = RiskEventItem.Event(
name = LOW_RISK_EVENT_LOCATION.name,
description = "1",
bulledPointColor = R.color.colorBulletPointLowRisk,
riskInfoAddition = R.string.contact_diary_trace_location_risk_low
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.Contact
import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem
import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventItem
import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem
import de.rki.coronawarnapp.eventregistration.checkins.CheckIn
import de.rki.coronawarnapp.eventregistration.checkins.CheckInRepository
import de.rki.coronawarnapp.risk.RiskState
import de.rki.coronawarnapp.risk.TraceLocationCheckInRisk
import de.rki.coronawarnapp.risk.result.ExposureWindowDayRisk
Expand All @@ -29,10 +31,10 @@ import de.rki.coronawarnapp.task.common.DefaultTaskRequest
import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalDateUtc
import de.rki.coronawarnapp.util.TimeStamper
import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
import de.rki.coronawarnapp.util.flow.combine
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOf
import org.joda.time.LocalDate
Expand All @@ -44,6 +46,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(
contactDiaryRepository: ContactDiaryRepository,
riskLevelStorage: RiskLevelStorage,
timeStamper: TimeStamper,
checkInRepository: CheckInRepository,
private val exporter: ContactDiaryExporter
) : CWAViewModel(dispatcherProvider = dispatcherProvider) {

Expand All @@ -57,23 +60,25 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(

private val riskLevelPerDateFlow = riskLevelStorage.ewDayRiskStates
private val traceLocationCheckInRiskFlow = riskLevelStorage.traceLocationCheckInRiskStates
private val allCheckInsFlow = checkInRepository.allCheckIns

val listItems = combine(
flowOf(dates),
locationVisitsFlow,
personEncountersFlow,
riskLevelPerDateFlow,
traceLocationCheckInRiskFlow
) { dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList ->
traceLocationCheckInRiskFlow,
allCheckInsFlow
) { dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList, checkInList ->
mutableListOf<DiaryOverviewItem>().apply {
add(OverviewSubHeaderItem)
addAll(
createListItemList(
dateList,
dateList.createListItemList(
locationVisists,
personEncounters,
riskLevelPerDateList,
traceLocationCheckInRiskList
traceLocationCheckInRiskList,
checkInList
)
)
}.toList()
Expand All @@ -88,27 +93,29 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(
)
}

private fun createListItemList(
dateList: List<LocalDate>,
private fun List<LocalDate>.createListItemList(
visits: List<ContactDiaryLocationVisit>,
encounters: List<ContactDiaryPersonEncounter>,
riskLevelPerDateList: List<ExposureWindowDayRisk>,
traceLocationCheckInRiskList: List<TraceLocationCheckInRisk>
traceLocationCheckInRiskList: List<TraceLocationCheckInRisk>,
checkInList: List<CheckIn>
): List<DiaryOverviewItem> {
Timber.v(
"createListItemList(" +
"dateList=%s, " +
"visits=%s, " +
"encounters=%s, " +
"riskLevelPerDateList=%s, " +
"traceLocationCheckInRiskList=%s",
dateList,
"traceLocationCheckInRiskList=%s," +
"checkInList=%s",
this,
visits,
encounters,
riskLevelPerDateList,
traceLocationCheckInRiskList
traceLocationCheckInRiskList,
checkInList
)
return dateList.map { date ->
return map { date ->

val visitsForDate = visits.filter { it.date == date }
val encountersForDate = encounters.filter { it.date == date }
Expand All @@ -125,16 +132,16 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(
.firstOrNull { riskLevelPerDate -> riskLevelPerDate.localDateUtc == date }
?.toRisk(coreItemData.isNotEmpty())

val riskEventItem = visitsForDate
.map {
it to traceLocationCheckInRisksForDate.find {
checkInRisk ->
checkInRisk.checkInId == it.checkInID
val riskEventItem = traceLocationCheckInRisksForDate
.mapNotNull {
val locationVisit = visitsForDate.find { visit -> visit.checkInID == it.checkInId }
val checkIn = checkInList.find { checkIn -> checkIn.id == it.checkInId }

return@mapNotNull when (locationVisit != null && checkIn != null) {
true -> RiskEventDataHolder(it, locationVisit, checkIn)
else -> null
}
}
.toMap()
.filter { it.value != null }
.toRiskEventItem()
}.toRiskEventItem()

DayOverviewItem(
date = date,
Expand Down Expand Up @@ -187,10 +194,16 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(
type = ContactItem.Type.LOCATION
)

private fun Map<ContactDiaryLocationVisit, TraceLocationCheckInRisk?>.toRiskEventItem(): RiskEventItem? {
private data class RiskEventDataHolder(
val traceLocationCheckInRisk: TraceLocationCheckInRisk,
val locationVisit: ContactDiaryLocationVisit,
val checkIn: CheckIn
)

private fun List<RiskEventDataHolder>.toRiskEventItem(): RiskEventItem? {
if (isEmpty()) return null

val isHighRisk = values.any { it?.riskState == RiskState.INCREASED_RISK }
val isHighRisk = any { it.traceLocationCheckInRisk.riskState == RiskState.INCREASED_RISK }

val body: Int = R.string.contact_diary_trace_location_risk_body
val drawableID: Int
Expand All @@ -207,15 +220,13 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(
}
}

val events = mapNotNull { entry ->
if (entry.value == null) return null

val name = entry.key.contactDiaryLocation.locationName
val events = map { data ->
val name = data.locationVisit.contactDiaryLocation.locationName

val bulletPointColor: Int
var riskInfoAddition: Int?

when (entry.value?.riskState == RiskState.INCREASED_RISK) {
when (data.traceLocationCheckInRisk.riskState == RiskState.INCREASED_RISK) {
true -> {
bulletPointColor = R.color.colorBulletPointHighRisk
riskInfoAddition = R.string.contact_diary_trace_location_risk_high
Expand All @@ -228,8 +239,11 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(

if (size < 2) riskInfoAddition = null

val description = data.checkIn.description

RiskEventItem.Event(
name = name,
description = description,
bulledPointColor = bulletPointColor,
riskInfoAddition = riskInfoAddition
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,48 @@
package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent

import android.view.ViewGroup
import androidx.recyclerview.widget.SortedList
import androidx.recyclerview.widget.SortedListAdapterCallback
import de.rki.coronawarnapp.R
import de.rki.coronawarnapp.contactdiary.util.clearAndAddAll
import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEventListItemBinding
import de.rki.coronawarnapp.ui.lists.BaseAdapter
import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat
import de.rki.coronawarnapp.util.lists.BindableVH

class RiskEventAdapter : BaseAdapter<RiskEventAdapter.RiskEventListItemVH>() {

private val events: MutableList<RiskEventItem.Event> = mutableListOf()
private val events: SortedList<RiskEventItem.Event> = SortedList(
RiskEventItem.Event::class.java,
SortedList.BatchedCallback(
object : SortedListAdapterCallback<RiskEventItem.Event>(
this
) {
override fun compare(o1: RiskEventItem.Event, o2: RiskEventItem.Event): Int =
o1.description.compareTo(o2.description)

override fun areContentsTheSame(oldItem: RiskEventItem.Event?, newItem: RiskEventItem.Event?): Boolean =
oldItem == newItem

override fun areItemsTheSame(item1: RiskEventItem.Event?, item2: RiskEventItem.Event?): Boolean =
item1 == item2
}
)
)

override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): RiskEventListItemVH = RiskEventListItemVH(parent)

override fun onBindBaseVH(holder: RiskEventListItemVH, position: Int, payloads: MutableList<Any>) =
holder.bind(events[position], payloads)

override fun getItemCount(): Int = events.size
override fun getItemCount(): Int = events.size()

fun setItems(events: List<RiskEventItem.Event>) {
this.events.clearAndAddAll(events)
notifyDataSetChanged()
this.events.apply {
beginBatchedUpdates()
clear()
addAll(events)
endBatchedUpdates()
}
}

inner class RiskEventListItemVH(parent: ViewGroup) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ data class RiskEventItem(

data class Event(
val name: String,
val description: String,
@ColorRes val bulledPointColor: Int,
@StringRes val riskInfoAddition: Int? = null
)
Expand Down
Loading

0 comments on commit 1fbf873

Please sign in to comment.