From df8d0057cfd18c38f1c8c3d00d15bb04a50e3cb2 Mon Sep 17 00:00:00 2001
From: BMItter <46747780+BMItter@users.noreply.github.com>
Date: Thu, 19 Nov 2020 19:16:28 +0100
Subject: [PATCH] ENFv2 - Refactor testmenu to use exposure window
 (EXPOSUREAPP-3845) (#1675)

* Show aggregated risk result in testmenu riskCalculationFragment

* Use extention fun to build string for aggregated result

* Show exposure window count and exposure windows as json

+ fixed a layoutbug with cut off

* satisfy lint

* Use real values

* Connected ExposureResultStore

* ENF v2 Calculation adjusted Testmenu Entry for v2

* Adjusted to ExposureResultStore changes

* Added logs

* Removed and adjusted some old stuff

* Made backend parameters a little bit better readable

* its better this way

* Created additional risk calc info

* Refactoring

* sourcecheck clean
---
 .../ui/TestRiskLevelCalculationFragment.kt    |  65 +-----
 ...iskLevelCalculationFragmentCWAViewModel.kt | 214 +++++++-----------
 .../fragment_test_risk_level_calculation.xml  |  60 +----
 .../storage/RiskLevelRepository.kt            |   2 +-
 4 files changed, 112 insertions(+), 229 deletions(-)

diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt
index 9c8a948bb..b0e40407c 100644
--- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt
+++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt
@@ -1,18 +1,13 @@
 package de.rki.coronawarnapp.test.risklevel.ui
 
-import android.content.Intent
 import android.os.Bundle
 import android.view.View
 import android.widget.Toast
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.navigation.fragment.navArgs
-import com.google.zxing.integration.android.IntentIntegrator
-import com.google.zxing.integration.android.IntentResult
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentTestRiskLevelCalculationBinding
-import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange
-import de.rki.coronawarnapp.sharing.ExposureSharingService
 import de.rki.coronawarnapp.test.menu.ui.TestMenuItem
 import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel
 import de.rki.coronawarnapp.util.di.AutoInject
@@ -20,7 +15,6 @@ import de.rki.coronawarnapp.util.ui.observe2
 import de.rki.coronawarnapp.util.ui.viewBindingLazy
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider
 import de.rki.coronawarnapp.util.viewmodel.cwaViewModelsAssisted
-import timber.log.Timber
 import javax.inject.Inject
 
 @Suppress("LongMethod")
@@ -55,7 +49,6 @@ class TestRiskLevelCalculationFragment : Fragment(R.layout.fragment_test_risk_le
         }
 
         binding.buttonRetrieveDiagnosisKeys.setOnClickListener { vm.retrieveDiagnosisKeys() }
-        binding.buttonProvideKeyViaQr.setOnClickListener { vm.scanLocalQRCodeAndProvide() }
         binding.buttonCalculateRiskLevel.setOnClickListener { vm.calculateRiskLevel() }
         binding.buttonClearDiagnosisKeyCache.setOnClickListener { vm.clearKeyCache() }
 
@@ -67,66 +60,32 @@ class TestRiskLevelCalculationFragment : Fragment(R.layout.fragment_test_risk_le
             ).show()
         }
 
-        vm.riskScoreState.observe2(this) { state ->
-            binding.labelRiskScore.text = state.riskScoreMsg
-            binding.labelBackendParameters.text = state.backendParameters
-            binding.labelExposureSummary.text = state.exposureSummary
-            binding.labelFormula.text = state.formula
-            binding.labelExposureInfo.text = state.exposureInfo
+        vm.additionalRiskCalcInfo.observe2(this) {
+            binding.labelRiskAdditionalInfo.text = it
         }
-        vm.startENFObserver()
 
-        vm.apiKeysProvidedEvent.observe2(this) { event ->
-            Toast.makeText(
-                requireContext(),
-                "Provided ${event.keyCount} keys to Google API",
-                Toast.LENGTH_SHORT
-            ).show()
+        vm.aggregatedRiskResult.observe2(this) {
+            binding.labelAggregatedRiskResult.text = it
         }
 
-        vm.startLocalQRCodeScanEvent.observe2(this) {
-            IntentIntegrator.forSupportFragment(this)
-                .setOrientationLocked(false)
-                .setBeepEnabled(false)
-                .initiateScan()
+        vm.exposureWindowCountString.observe2(this) {
+            binding.labelExposureWindowCount.text = it
         }
-    }
-
-    override fun onResume() {
-        super.onResume()
-        vm.calculateRiskLevel()
-    }
-
-    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
-        val result: IntentResult =
-            IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
-                ?: return super.onActivityResult(requestCode, resultCode, data)
 
-        if (result.contents == null) {
-            Toast.makeText(requireContext(), "Cancelled", Toast.LENGTH_LONG).show()
-            return
+        vm.exposureWindows.observe2(this) {
+            binding.labelExposureWindows.text = it
         }
 
-        ExposureSharingService.getOthersKeys(result.contents) { key: AppleLegacyKeyExchange.Key? ->
-            Timber.i("Keys scanned: %s", key)
-            if (key == null) {
-                Toast.makeText(
-                    requireContext(), "No Key data found in QR code", Toast.LENGTH_SHORT
-                ).show()
-                return@getOthersKeys Unit
-            }
-
-            val text = binding.transmissionNumber.text.toString()
-            val number = if (!text.isBlank()) Integer.valueOf(text) else 5
-            vm.provideDiagnosisKey(number, key)
+        vm.backendParameters.observe2(this) {
+            binding.labelBackendParameters.text = it
         }
     }
 
     companion object {
         val TAG: String = TestRiskLevelCalculationFragment::class.simpleName!!
         val MENU_ITEM = TestMenuItem(
-            title = "Risklevel Calculation",
-            description = "Risklevel calculation related test options.",
+            title = "ENF v2 Calculation",
+            description = "Window Mode related overview.",
             targetId = R.id.test_risklevel_calculation_fragment
         )
     }
diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt
index 67d68216e..24e49d875 100644
--- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt
+++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt
@@ -1,24 +1,23 @@
 package de.rki.coronawarnapp.test.risklevel.ui
 
 import android.content.Context
-import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.SavedStateHandle
 import androidx.lifecycle.asLiveData
+import com.google.gson.Gson
 import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
 import de.rki.coronawarnapp.appconfig.AppConfigProvider
+import de.rki.coronawarnapp.appconfig.ConfigData
 import de.rki.coronawarnapp.diagnosiskeys.download.DownloadDiagnosisKeysTask
 import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository
 import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.reporting.report
-import de.rki.coronawarnapp.nearby.ENFClient
 import de.rki.coronawarnapp.risk.ExposureResult
 import de.rki.coronawarnapp.risk.ExposureResultStore
 import de.rki.coronawarnapp.risk.RiskLevel
 import de.rki.coronawarnapp.risk.RiskLevelTask
-import de.rki.coronawarnapp.risk.RiskLevels
 import de.rki.coronawarnapp.risk.TimeVariables
-import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange
+import de.rki.coronawarnapp.risk.result.AggregatedRiskResult
 import de.rki.coronawarnapp.storage.AppDatabase
 import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.storage.RiskLevelRepository
@@ -27,11 +26,11 @@ import de.rki.coronawarnapp.task.TaskController
 import de.rki.coronawarnapp.task.common.DefaultTaskRequest
 import de.rki.coronawarnapp.task.submitBlocking
 import de.rki.coronawarnapp.ui.tracing.card.TracingCardStateProvider
-import de.rki.coronawarnapp.util.KeyFileHelper
 import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess
 import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
 import de.rki.coronawarnapp.util.di.AppContext
 import de.rki.coronawarnapp.util.security.SecurityHelper
+import de.rki.coronawarnapp.util.serialization.BaseGson
 import de.rki.coronawarnapp.util.ui.SingleLiveEvent
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory
@@ -39,9 +38,8 @@ import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.sample
 import kotlinx.coroutines.withContext
+import org.joda.time.Instant
 import timber.log.Timber
-import java.io.File
-import java.util.UUID
 import java.util.concurrent.TimeUnit
 
 class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
@@ -49,21 +47,25 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
     @Assisted private val exampleArg: String?,
     @AppContext private val context: Context, // App context
     dispatcherProvider: DispatcherProvider,
-    private val enfClient: ENFClient,
-    private val riskLevels: RiskLevels,
     private val taskController: TaskController,
     private val keyCacheRepository: KeyCacheRepository,
     private val appConfigProvider: AppConfigProvider,
     tracingCardStateProvider: TracingCardStateProvider,
+    @BaseGson private val gson: Gson,
     private val exposureResultStore: ExposureResultStore
 ) : CWAViewModel(
     dispatcherProvider = dispatcherProvider
 ) {
 
+    init {
+        Timber.d("CWAViewModel: %s", this)
+        Timber.d("SavedStateHandle: %s", handle)
+        Timber.d("Example arg: %s", exampleArg)
+    }
+
     val startLocalQRCodeScanEvent = SingleLiveEvent<Unit>()
     val riskLevelResetEvent = SingleLiveEvent<Unit>()
-    val apiKeysProvidedEvent = SingleLiveEvent<DiagnosisKeyProvidedEvent>()
-    val riskScoreState = MutableLiveData<RiskScoreState>(RiskScoreState())
+
     val showRiskStatusCard = SubmissionRepository.deviceUIStateFlow.map {
         it.withSuccess(false) { true }
     }.asLiveData(dispatcherProvider.Default)
@@ -72,13 +74,79 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
         .sample(150L)
         .asLiveData(dispatcherProvider.Default)
 
-    init {
-        Timber.d("CWAViewModel: %s", this)
-        Timber.d("SavedStateHandle: %s", handle)
-        Timber.d("Example arg: %s", exampleArg)
-    }
+    val exposureWindowCountString = exposureResultStore
+        .entities
+        .map { "Retrieved ${it.exposureWindows.size} Exposure Windows" }
+        .asLiveData()
+
+    val exposureWindows = exposureResultStore
+        .entities
+        .map { if (it.exposureWindows.isEmpty()) "Exposure windows list is empty" else gson.toJson(it.exposureWindows) }
+        .asLiveData()
+
+    val aggregatedRiskResult = exposureResultStore
+        .entities
+        .map { if (it.aggregatedRiskResult != null) it.aggregatedRiskResult.toReadableString() else "Aggregated risk result is not available" }
+        .asLiveData()
+
+    private fun AggregatedRiskResult.toReadableString(): String = StringBuilder()
+        .appendLine("Total RiskLevel: $totalRiskLevel")
+        .appendLine("Total Minimum Distinct Encounters With High Risk: $totalMinimumDistinctEncountersWithHighRisk")
+        .appendLine("Total Minimum Distinct Encounters With Low Risk: $totalMinimumDistinctEncountersWithLowRisk")
+        .appendLine("Most Recent Date With High Risk: $mostRecentDateWithHighRisk")
+        .appendLine("Most Recent Date With Low Risk: $mostRecentDateWithLowRisk")
+        .appendLine("Number of Days With High Risk: $numberOfDaysWithHighRisk")
+        .appendLine("Number of Days With Low Risk: $numberOfDaysWithLowRisk")
+        .toString()
+
+    val backendParameters = appConfigProvider
+        .currentConfig
+        .map { it.toReadableString() }
+        .asLiveData()
+
+    private fun ConfigData.toReadableString(): String = StringBuilder()
+        .appendLine("Transmission RiskLevel Multiplier: $transmissionRiskLevelMultiplier")
+        .appendLine()
+        .appendLine("Minutes At Attenuation Filters:")
+        .appendLine(minutesAtAttenuationFilters)
+        .appendLine()
+        .appendLine("Minutes At Attenuation Weights:")
+        .appendLine(minutesAtAttenuationWeights)
+        .appendLine()
+        .appendLine("Transmission RiskLevel Encoding:")
+        .appendLine(transmissionRiskLevelEncoding)
+        .appendLine()
+        .appendLine("Transmission RiskLevel Filters:")
+        .appendLine(transmissionRiskLevelFilters)
+        .appendLine()
+        .appendLine("Normalized Time Per Exposure Window To RiskLevel Mapping:")
+        .appendLine(normalizedTimePerExposureWindowToRiskLevelMapping)
+        .appendLine()
+        .appendLine("Normalized Time Per Day To RiskLevel Mapping List:")
+        .appendLine(normalizedTimePerDayToRiskLevelMappingList)
+        .toString()
+
+    // Only update when risk level gets updated
+    val additionalRiskCalcInfo = RiskLevelRepository
+        .riskLevelScore
+        .map { createAdditionalRiskCalcInfo(it) }
+        .asLiveData()
+
+    private suspend fun createAdditionalRiskCalcInfo(riskLevelScore: Int): String = StringBuilder()
+        .appendLine("Risk Level: ${RiskLevel.forValue(riskLevelScore)}")
+        .appendLine("Last successful Risk Level: ${RiskLevelRepository.getLastSuccessfullyCalculatedScore()}")
+        .appendLine("Last Time Server Fetch: ${LocalData.lastTimeDiagnosisKeysFromServerFetch()}")
+        .appendLine("Tracing Duration: ${TimeUnit.MILLISECONDS.toDays(TimeVariables.getTimeActiveTracingDuration())} days")
+        .appendLine("Tracing Duration in last 14 days: ${TimeVariables.getActiveTracingDaysInRetentionPeriod()} days")
+        .appendLine(
+            "Last time risk level calculation ${
+                LocalData.lastTimeRiskLevelCalculation()?.let { Instant.ofEpochMilli(it) }
+            }"
+        )
+        .toString()
 
     fun retrieveDiagnosisKeys() {
+        Timber.d("Starting download diagnosis keys task")
         launch {
             taskController.submitBlocking(
                 DefaultTaskRequest(
@@ -87,11 +155,11 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
                     originTag = "TestRiskLevelCalculationFragmentCWAViewModel.retrieveDiagnosisKeys()"
                 )
             )
-            calculateRiskLevel()
         }
     }
 
     fun calculateRiskLevel() {
+        Timber.d("Starting calculate risk task")
         taskController.submit(
             DefaultTaskRequest(
                 RiskLevelTask::class,
@@ -101,6 +169,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
     }
 
     fun resetRiskLevel() {
+        Timber.d("Resetting risk level")
         launch {
             withContext(Dispatchers.IO) {
                 try {
@@ -125,117 +194,8 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
         }
     }
 
-    data class RiskScoreState(
-        val riskScoreMsg: String = "",
-        val backendParameters: String = "",
-        val exposureSummary: String = "",
-        val formula: String = "",
-        val exposureInfo: String = ""
-    )
-
-    fun startENFObserver() {
-        launch {
-            try {
-                val appConfig = appConfigProvider.getAppConfig()
-
-                var workState = riskScoreState.value!!
-
-                val exposureWindows = enfClient.exposureWindows()
-
-                val riskResultsPerWindow =
-                    exposureWindows.mapNotNull { window ->
-                        riskLevels.calculateRisk(appConfig, window)?.let { window to it }
-                    }.toMap()
-
-                val aggregatedResult = riskLevels.aggregateResults(appConfig, riskResultsPerWindow)
-
-                val riskAsString = "Level: ${RiskLevelRepository.getLastCalculatedScore()}\n" +
-                    "Last successful Level: " +
-                    "${LocalData.lastSuccessfullyCalculatedRiskLevel()}\n" +
-                    "Calculated Score: ${aggregatedResult}\n" +
-                    "Last Time Server Fetch: ${LocalData.lastTimeDiagnosisKeysFromServerFetch()}\n" +
-                    "Tracing Duration: " +
-                    "${TimeUnit.MILLISECONDS.toDays(TimeVariables.getTimeActiveTracingDuration())} days \n" +
-                    "Tracing Duration in last 14 days: " +
-                    "${TimeVariables.getActiveTracingDaysInRetentionPeriod()} days \n" +
-                    "Last time risk level calculation ${LocalData.lastTimeRiskLevelCalculation()}"
-
-                workState = workState.copy(riskScoreMsg = riskAsString)
-
-                val configAsString =
-                    "Transmission RiskLevel Multiplier: ${appConfig.transmissionRiskLevelMultiplier}\n" +
-                        "Minutes At Attenuation Filters: ${appConfig.minutesAtAttenuationFilters}\n" +
-                        "Minutes At Attenuation Weights: ${appConfig.minutesAtAttenuationWeights}" +
-                        "Transmission RiskLevel Encoding: ${appConfig.transmissionRiskLevelEncoding}" +
-                        "Transmission RiskLevel Filters: ${appConfig.transmissionRiskLevelFilters}" +
-                        "Normalized Time Per Exposure Window To RiskLevel Mapping: ${appConfig.normalizedTimePerExposureWindowToRiskLevelMapping}" +
-                        "Normalized Time Per Day To RiskLevel Mapping List: ${appConfig.normalizedTimePerDayToRiskLevelMappingList}"
-                workState = workState.copy(backendParameters = configAsString)
-
-                val summaryAsString =
-                    "Total RiskLevel: ${aggregatedResult.totalRiskLevel}" +
-                        "Total Minimum Distinct Encounters With High Risk: ${aggregatedResult.totalMinimumDistinctEncountersWithHighRisk}" +
-                        "Total Minimum Distinct Encounters With Low Risk: ${aggregatedResult.totalMinimumDistinctEncountersWithLowRisk}" +
-                        "Most Recent Date With High Risk: ${aggregatedResult.mostRecentDateWithHighRisk}" +
-                        "Most Recent Date With Low Risk: ${aggregatedResult.mostRecentDateWithLowRisk}"
-
-                workState = workState.copy(exposureSummary = summaryAsString)
-
-                riskScoreState.postValue(workState)
-            } catch (e: Exception) {
-                e.report(ExceptionCategory.EXPOSURENOTIFICATION)
-            }
-        }
-    }
-
-    data class DiagnosisKeyProvidedEvent(
-        val keyCount: Int
-    )
-
-    fun provideDiagnosisKey(transmissionNumber: Int, key: AppleLegacyKeyExchange.Key) {
-        val appleKeyList = mutableListOf<AppleLegacyKeyExchange.Key>()
-
-        AppleLegacyKeyExchange.Key.newBuilder()
-            .setKeyData(key.keyData)
-            .setRollingPeriod(144)
-            .setRollingStartNumber(key.rollingStartNumber)
-            .setTransmissionRiskLevel(transmissionNumber)
-            .build()
-            .also { appleKeyList.add(it) }
-
-        val appleFiles = listOf(
-            AppleLegacyKeyExchange.File.newBuilder()
-                .addAllKeys(appleKeyList)
-                .build()
-        )
-
-        val dir = File(File(context.getExternalFilesDir(null), "key-export"), UUID.randomUUID().toString())
-        dir.mkdirs()
-
-        var googleFileList: List<File>
-        launch {
-            googleFileList = KeyFileHelper.asyncCreateExportFiles(appleFiles, dir)
-
-            Timber.i("Provide ${googleFileList.count()} files with ${appleKeyList.size} keys")
-            try {
-                // only testing implementation: this is used to wait for the broadcastreceiver of the OS / EN API
-                enfClient.provideDiagnosisKeys(googleFileList)
-                apiKeysProvidedEvent.postValue(
-                    DiagnosisKeyProvidedEvent(
-                        keyCount = appleFiles.size
-                    )
-                )
-            } catch (e: Exception) {
-                e.report(ExceptionCategory.EXPOSURENOTIFICATION)
-            }
-        }
-    }
-
-    fun scanLocalQRCodeAndProvide() {
-        startLocalQRCodeScanEvent.postValue(Unit)
-    }
-
     fun clearKeyCache() {
+        Timber.d("Clearing key cache")
         launch { keyCacheRepository.clear() }
     }
 
diff --git a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml
index a58a1ff43..7d94e7c3d 100644
--- a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml
+++ b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml
@@ -32,7 +32,6 @@
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_margin="@dimen/spacing_normal"
             android:orientation="vertical">
 
             <TextView
@@ -60,34 +59,6 @@
 
             </FrameLayout>
 
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:orientation="horizontal">
-
-                <TextView
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="Transmission Risk Level for scan: " />
-
-                <EditText
-                    android:id="@+id/transmission_number"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:ems="10"
-                    android:inputType="number"
-                    android:text="5" />
-            </LinearLayout>
-
-            <Button
-                android:id="@+id/button_provide_key_via_qr"
-                style="@style/buttonPrimary"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginBottom="@dimen/spacing_normal"
-                android:text="Scan Local QR Code" />
-
             <Button
                 android:id="@+id/button_retrieve_diagnosis_keys"
                 style="@style/buttonPrimary"
@@ -121,30 +92,30 @@
                 android:text="Clear Diagnosis-Key cache" />
 
             <TextView
-                android:id="@+id/label_exposure_summary_title"
+                android:id="@+id/label_aggregated_risk_result_title"
                 style="@style/headline6"
                 android:accessibilityHeading="true"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="@dimen/spacing_normal"
-                android:text="Exposure Summary" />
+                android:text="Aggregated Risk Result" />
 
             <TextView
-                android:id="@+id/label_exposure_summary"
+                android:id="@+id/label_aggregated_risk_result"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="-" />
 
             <TextView
-                android:id="@+id/label_risk_score_title"
+                android:id="@+id/label_risk_additional_info_title"
                 style="@style/headline6"
                 android:accessibilityHeading="true"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="Risk Score" />
+                android:text="Risk Calculation Additional Information" />
 
             <TextView
-                android:id="@+id/label_risk_score"
+                android:id="@+id/label_risk_additional_info"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="-" />
@@ -164,31 +135,24 @@
                 android:text="-" />
 
             <TextView
-                android:id="@+id/label_formula_title"
+                android:id="@+id/label_exposure_window_title"
                 style="@style/headline6"
                 android:accessibilityHeading="true"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="Used Formula" />
+                android:text="Exposure Windows" />
 
             <TextView
-                android:id="@+id/label_formula"
+                android:id="@+id/label_exposure_window_count"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="-" />
 
             <TextView
-                android:id="@+id/label_exposure_info_title"
-                style="@style/headline6"
-                android:accessibilityHeading="true"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="Exposure Information" />
-
-            <TextView
-                android:id="@+id/label_exposure_info"
-                android:layout_width="match_parent"
+                android:id="@+id/label_exposure_windows"
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:paddingTop="5dp"
                 android:text="-" />
 
         </LinearLayout>
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/RiskLevelRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/RiskLevelRepository.kt
index 7b5b24702..62db1f8e7 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/RiskLevelRepository.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/RiskLevelRepository.kt
@@ -80,7 +80,7 @@ object RiskLevelRepository {
      *
      * @return
      */
-    private fun getLastSuccessfullyCalculatedScore(): RiskLevel =
+    fun getLastSuccessfullyCalculatedScore(): RiskLevel =
         LocalData.lastSuccessfullyCalculatedRiskLevel()
 
     /**
-- 
GitLab