From 45e6dc1c2f4ebd3bfad04df172737902927137a4 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Sat, 13 Mar 2021 16:05:18 +0100 Subject: [PATCH 01/17] Map presence tracing configuration parameters --- .../appconfig/AppConfigModule.kt | 5 ++ .../appconfig/PresenceTracingConfig.kt | 13 +++ .../PresenceTracingConfigContainer.kt | 10 +++ ...nceTracingRiskCalculationParamContainer.kt | 10 +++ ...PresenceTracingSubmissionParamContainer.kt | 12 +++ .../appconfig/mapping/ConfigMapping.kt | 5 +- .../appconfig/mapping/ConfigParser.kt | 5 +- .../appconfig/mapping/DefaultConfigMapping.kt | 4 +- .../mapping/PresenceTracingConfigMapper.kt | 84 +++++++++++++++++++ 9 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingConfig.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingConfigContainer.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingRiskCalculationParamContainer.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingSubmissionParamContainer.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/AppConfigModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/AppConfigModule.kt index 09353815926..cf775d6f57f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/AppConfigModule.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/AppConfigModule.kt @@ -9,6 +9,7 @@ import de.rki.coronawarnapp.appconfig.mapping.ExposureDetectionConfigMapper import de.rki.coronawarnapp.appconfig.mapping.ExposureWindowRiskCalculationConfigMapper import de.rki.coronawarnapp.appconfig.mapping.KeyDownloadParametersMapper import de.rki.coronawarnapp.appconfig.mapping.LogUploadConfigMapper +import de.rki.coronawarnapp.appconfig.mapping.PresenceTracingConfigMapper import de.rki.coronawarnapp.appconfig.mapping.SurveyConfigMapper import de.rki.coronawarnapp.environment.download.DownloadCDNHttpClient import de.rki.coronawarnapp.environment.download.DownloadCDNServerUrl @@ -78,6 +79,10 @@ class AppConfigModule { fun logUploadMapper(mapper: LogUploadConfigMapper): LogUploadConfig.Mapper = mapper + @Provides + fun presenceTracingMapper(mapper: PresenceTracingConfigMapper): + PresenceTracingConfig.Mapper = mapper + companion object { private val HTTP_TIMEOUT_APPCONFIG = Duration.standardSeconds(10) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingConfig.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingConfig.kt new file mode 100644 index 00000000000..5eaee0af486 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingConfig.kt @@ -0,0 +1,13 @@ +package de.rki.coronawarnapp.appconfig + +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel +import de.rki.coronawarnapp.appconfig.mapping.ConfigMapper + +interface PresenceTracingConfig { + val qrCodeErrorCorrectionLevel: ErrorCorrectionLevel + val revokedTraceLocationVersions: List + val riskCalculationParameters: PresenceTracingRiskCalculationParamContainer + val submissionParameters: PresenceTracingSubmissionParamContainer + + interface Mapper : ConfigMapper +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingConfigContainer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingConfigContainer.kt new file mode 100644 index 00000000000..0067d966bf2 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingConfigContainer.kt @@ -0,0 +1,10 @@ +package de.rki.coronawarnapp.appconfig + +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel + +data class PresenceTracingConfigContainer( + override val qrCodeErrorCorrectionLevel: ErrorCorrectionLevel, + override val revokedTraceLocationVersions: List, + override val riskCalculationParameters: PresenceTracingRiskCalculationParamContainer, + override val submissionParameters: PresenceTracingSubmissionParamContainer +) : PresenceTracingConfig diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingRiskCalculationParamContainer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingRiskCalculationParamContainer.kt new file mode 100644 index 00000000000..b50b4432397 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingRiskCalculationParamContainer.kt @@ -0,0 +1,10 @@ +package de.rki.coronawarnapp.appconfig + +import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass.NormalizedTimeToRiskLevelMapping +import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass.TransmissionRiskValueMapping + +data class PresenceTracingRiskCalculationParamContainer( + val transmissionRiskValueMapping: List, + val normalizedTimePerCheckInToRiskLevelMapping: List, + val normalizedTimePerDayToRiskLevelMapping: List +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingSubmissionParamContainer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingSubmissionParamContainer.kt new file mode 100644 index 00000000000..1fdae47dac0 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/PresenceTracingSubmissionParamContainer.kt @@ -0,0 +1,12 @@ +package de.rki.coronawarnapp.appconfig + +import de.rki.coronawarnapp.server.protocols.internal.v2 + .PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters.DurationFilter + +import de.rki.coronawarnapp.server.protocols.internal.v2 + .PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters.AerosoleDecayFunctionLinear + +data class PresenceTracingSubmissionParamContainer( + val durationFilters: List, + val aerosoleDecayLinearFunctions: List +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigMapping.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigMapping.kt index 92a3d6849f6..bad36b65aff 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigMapping.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigMapping.kt @@ -6,6 +6,7 @@ import de.rki.coronawarnapp.appconfig.ExposureDetectionConfig import de.rki.coronawarnapp.appconfig.ExposureWindowRiskCalculationConfig import de.rki.coronawarnapp.appconfig.KeyDownloadConfig import de.rki.coronawarnapp.appconfig.LogUploadConfig +import de.rki.coronawarnapp.appconfig.PresenceTracingConfig import de.rki.coronawarnapp.appconfig.SurveyConfig import de.rki.coronawarnapp.server.protocols.internal.v2.AppConfigAndroid @@ -17,10 +18,8 @@ interface ConfigMapping : @Deprecated("Try to access a more specific config type, avoid the RAW variant.") val rawConfig: AppConfigAndroid.ApplicationConfigurationAndroid - val survey: SurveyConfig - val analytics: AnalyticsConfig - val logUpload: LogUploadConfig + val presenceTracing: PresenceTracingConfig } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParser.kt index e9bf15f00f3..43d06fb9c43 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParser.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParser.kt @@ -7,6 +7,7 @@ import de.rki.coronawarnapp.appconfig.ExposureDetectionConfig import de.rki.coronawarnapp.appconfig.ExposureWindowRiskCalculationConfig import de.rki.coronawarnapp.appconfig.KeyDownloadConfig import de.rki.coronawarnapp.appconfig.LogUploadConfig +import de.rki.coronawarnapp.appconfig.PresenceTracingConfig import de.rki.coronawarnapp.appconfig.SurveyConfig import de.rki.coronawarnapp.server.protocols.internal.v2.AppConfigAndroid import timber.log.Timber @@ -21,6 +22,7 @@ class ConfigParser @Inject constructor( private val surveyConfigMapper: SurveyConfig.Mapper, private val analyticsConfigMapper: AnalyticsConfig.Mapper, private val logUploadConfigMapper: LogUploadConfig.Mapper, + private val presenceTracingConfigMapper: PresenceTracingConfig.Mapper, ) { fun parse(configBytes: ByteArray): ConfigMapping = try { @@ -33,7 +35,8 @@ class ConfigParser @Inject constructor( exposureWindowRiskCalculationConfig = exposureWindowRiskCalculationConfigMapper.map(it), survey = surveyConfigMapper.map(it), analytics = analyticsConfigMapper.map(it), - logUpload = logUploadConfigMapper.map(it) + logUpload = logUploadConfigMapper.map(it), + presenceTracing=presenceTracingConfigMapper.map(it) ) } } catch (e: Exception) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/DefaultConfigMapping.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/DefaultConfigMapping.kt index 9ebbe211688..cdebdff80bd 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/DefaultConfigMapping.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/DefaultConfigMapping.kt @@ -6,6 +6,7 @@ import de.rki.coronawarnapp.appconfig.ExposureDetectionConfig import de.rki.coronawarnapp.appconfig.ExposureWindowRiskCalculationConfig import de.rki.coronawarnapp.appconfig.KeyDownloadConfig import de.rki.coronawarnapp.appconfig.LogUploadConfig +import de.rki.coronawarnapp.appconfig.PresenceTracingConfig import de.rki.coronawarnapp.appconfig.SurveyConfig import de.rki.coronawarnapp.server.protocols.internal.v2.AppConfigAndroid @@ -17,7 +18,8 @@ data class DefaultConfigMapping( val exposureWindowRiskCalculationConfig: ExposureWindowRiskCalculationConfig, override val survey: SurveyConfig, override val analytics: AnalyticsConfig, - override val logUpload: LogUploadConfig + override val logUpload: LogUploadConfig, + override val presenceTracing: PresenceTracingConfig, ) : ConfigMapping, CWAConfig by cwaConfig, KeyDownloadConfig by keyDownloadConfig, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt new file mode 100644 index 00000000000..44ac086e4e5 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt @@ -0,0 +1,84 @@ +package de.rki.coronawarnapp.appconfig.mapping + +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel +import dagger.Reusable +import de.rki.coronawarnapp.appconfig.PresenceTracingConfig +import de.rki.coronawarnapp.appconfig.PresenceTracingConfigContainer +import de.rki.coronawarnapp.appconfig.PresenceTracingRiskCalculationParamContainer +import de.rki.coronawarnapp.appconfig.PresenceTracingSubmissionParamContainer +import de.rki.coronawarnapp.server.protocols.internal.v2.AppConfigAndroid +import de.rki.coronawarnapp.server.protocols.internal.v2 +.PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters +import de.rki.coronawarnapp.server.protocols.internal.v2 +.PresenceTracingParametersOuterClass.PresenceTracingRiskCalculationParameters +import de.rki.coronawarnapp.server.protocols.internal.v2 +.PresenceTracingParametersOuterClass.PresenceTracingParameters.QRCodeErrorCorrectionLevel +import timber.log.Timber +import javax.inject.Inject + +@Reusable +class PresenceTracingConfigMapper @Inject constructor() : PresenceTracingConfig.Mapper { + override fun map(rawConfig: AppConfigAndroid.ApplicationConfigurationAndroid): PresenceTracingConfig { + val hasPresenceTracingConfig = rawConfig.hasPresenceTracingParameters() && + rawConfig.presenceTracingParameters.hasRiskCalculationParameters() && + rawConfig.presenceTracingParameters.hasSubmissionParameters() + + if (!hasPresenceTracingConfig) { + Timber.w("AppConfig does not have PresenceTracingParameters") + return PresenceTracingConfigContainer( + qrCodeErrorCorrectionLevel = ErrorCorrectionLevel.L, + revokedTraceLocationVersions = emptyList(), + riskCalculationParameters = emptyTracingRiskCalculationParamContainer(), + submissionParameters = emptyPresenceTracingSubmissionParamContainer() + ) + } + + return rawConfig.presenceTracingConfig() + } + + private fun emptyPresenceTracingSubmissionParamContainer() = + PresenceTracingSubmissionParamContainer( + durationFilters = emptyList(), + aerosoleDecayLinearFunctions = emptyList() + ) + + private fun emptyTracingRiskCalculationParamContainer() = + PresenceTracingRiskCalculationParamContainer( + transmissionRiskValueMapping = emptyList(), + normalizedTimePerCheckInToRiskLevelMapping = emptyList(), + normalizedTimePerDayToRiskLevelMapping = emptyList() + ) + + private fun PresenceTracingSubmissionParameters.mapSubmissionParameters() = + PresenceTracingSubmissionParamContainer( + durationFilters = durationFiltersList, + aerosoleDecayLinearFunctions = aerosoleDecayLinearFunctionsList + ) + + private fun PresenceTracingRiskCalculationParameters.mapRiskCalculationParameters() = + PresenceTracingRiskCalculationParamContainer( + transmissionRiskValueMapping = transmissionRiskValueMappingList, + normalizedTimePerCheckInToRiskLevelMapping = normalizedTimePerCheckInToRiskLevelMappingList, + normalizedTimePerDayToRiskLevelMapping = normalizedTimePerDayToRiskLevelMappingList + ) + + private fun QRCodeErrorCorrectionLevel.mapErrorCorrection(): ErrorCorrectionLevel = + when (this) { + QRCodeErrorCorrectionLevel.LOW -> ErrorCorrectionLevel.L + QRCodeErrorCorrectionLevel.MEDIUM -> ErrorCorrectionLevel.M + QRCodeErrorCorrectionLevel.HIGH -> ErrorCorrectionLevel.H + QRCodeErrorCorrectionLevel.QUANTILE -> ErrorCorrectionLevel.Q + // Default correction error level in zxing + QRCodeErrorCorrectionLevel.UNRECOGNIZED -> ErrorCorrectionLevel.L + } + + private fun AppConfigAndroid.ApplicationConfigurationAndroid.presenceTracingConfig() = + presenceTracingParameters.run { + PresenceTracingConfigContainer( + qrCodeErrorCorrectionLevel = qrCodeErrorCorrectionLevel.mapErrorCorrection(), + revokedTraceLocationVersions = revokedTraceLocationVersionsList, + riskCalculationParameters = riskCalculationParameters.mapRiskCalculationParameters(), + submissionParameters = submissionParameters.mapSubmissionParameters() + ) + } +} From edb9ea964dad9ed3d3538a9a5b415ac4c7f80ad1 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Sat, 13 Mar 2021 17:35:19 +0100 Subject: [PATCH 02/17] Give priority to config values --- .../mapping/PresenceTracingConfigMapper.kt | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt index 44ac086e4e5..090a2e9f7ef 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt @@ -19,30 +19,26 @@ import javax.inject.Inject @Reusable class PresenceTracingConfigMapper @Inject constructor() : PresenceTracingConfig.Mapper { override fun map(rawConfig: AppConfigAndroid.ApplicationConfigurationAndroid): PresenceTracingConfig { - val hasPresenceTracingConfig = rawConfig.hasPresenceTracingParameters() && - rawConfig.presenceTracingParameters.hasRiskCalculationParameters() && - rawConfig.presenceTracingParameters.hasSubmissionParameters() - - if (!hasPresenceTracingConfig) { + if (!rawConfig.hasPresenceTracingParameters()) { Timber.w("AppConfig does not have PresenceTracingParameters") return PresenceTracingConfigContainer( - qrCodeErrorCorrectionLevel = ErrorCorrectionLevel.L, + qrCodeErrorCorrectionLevel = ErrorCorrectionLevel.H, revokedTraceLocationVersions = emptyList(), - riskCalculationParameters = emptyTracingRiskCalculationParamContainer(), - submissionParameters = emptyPresenceTracingSubmissionParamContainer() + riskCalculationParameters = emptyRiskCalculationParameters(), + submissionParameters = emptySubmissionParameters() ) } - return rawConfig.presenceTracingConfig() + return rawConfig.presenceTracingConfig().also { Timber.i("PresenceTracingConfig: $it") } } - private fun emptyPresenceTracingSubmissionParamContainer() = + private fun emptySubmissionParameters() = PresenceTracingSubmissionParamContainer( durationFilters = emptyList(), aerosoleDecayLinearFunctions = emptyList() ) - private fun emptyTracingRiskCalculationParamContainer() = + private fun emptyRiskCalculationParameters() = PresenceTracingRiskCalculationParamContainer( transmissionRiskValueMapping = emptyList(), normalizedTimePerCheckInToRiskLevelMapping = emptyList(), @@ -68,17 +64,30 @@ class PresenceTracingConfigMapper @Inject constructor() : PresenceTracingConfig. QRCodeErrorCorrectionLevel.MEDIUM -> ErrorCorrectionLevel.M QRCodeErrorCorrectionLevel.HIGH -> ErrorCorrectionLevel.H QRCodeErrorCorrectionLevel.QUANTILE -> ErrorCorrectionLevel.Q - // Default correction error level in zxing - QRCodeErrorCorrectionLevel.UNRECOGNIZED -> ErrorCorrectionLevel.L + else -> ErrorCorrectionLevel.H } private fun AppConfigAndroid.ApplicationConfigurationAndroid.presenceTracingConfig() = presenceTracingParameters.run { + val riskCalculationParameters = if (hasRiskCalculationParameters()) { + riskCalculationParameters.mapRiskCalculationParameters() + } else { + Timber.w("RiskCalculationParameters are missing") + emptyRiskCalculationParameters() + } + + val submissionParameters = if (hasSubmissionParameters()) { + submissionParameters.mapSubmissionParameters() + } else { + Timber.w("SubmissionParameters are missing") + emptySubmissionParameters() + } + PresenceTracingConfigContainer( qrCodeErrorCorrectionLevel = qrCodeErrorCorrectionLevel.mapErrorCorrection(), - revokedTraceLocationVersions = revokedTraceLocationVersionsList, - riskCalculationParameters = riskCalculationParameters.mapRiskCalculationParameters(), - submissionParameters = submissionParameters.mapSubmissionParameters() + revokedTraceLocationVersions = revokedTraceLocationVersionsList.orEmpty(), + riskCalculationParameters = riskCalculationParameters, + submissionParameters = submissionParameters ) } } From 373436c6a35d69c9c90922146aa248b054ef2ddd Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Sat, 13 Mar 2021 17:51:48 +0100 Subject: [PATCH 03/17] Use presence tracing config in QR Code creation --- .../ui/qrcode/QrCodeCreationTestViewModel.kt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt index 6dd59f2e683..c197bc28d88 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt @@ -13,6 +13,8 @@ import com.google.zxing.common.BitMatrix import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import de.rki.coronawarnapp.appconfig.AppConfigProvider +import de.rki.coronawarnapp.server.protocols.internal.AppConfig import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.files.FileSharing @@ -26,7 +28,8 @@ import java.io.FileOutputStream class QrCodeCreationTestViewModel @AssistedInject constructor( private val dispatcher: DispatcherProvider, private val fileSharing: FileSharing, - @AppContext private val context: Context + @AppContext private val context: Context, + private val appConfigProvider: AppConfigProvider, ) : CWAViewModel(dispatcher) { val qrCodeBitmap = SingleLiveEvent() @@ -82,10 +85,15 @@ class QrCodeCreationTestViewModel @AssistedInject constructor( return File(dir, "CoronaWarnApp-Event.pdf") } - private fun encodeAsBitmap(input: String, size: Int = 1000): Bitmap? { + private suspend fun encodeAsBitmap(input: String, size: Int = 1000): Bitmap? { return try { + val qrCodeErrorCorrectionLevel = appConfigProvider + .getAppConfig() + .presenceTracing + .qrCodeErrorCorrectionLevel + Timber.i("QrCodeErrorCorrectionLevel: $qrCodeErrorCorrectionLevel") val hints = mapOf( - EncodeHintType.ERROR_CORRECTION to ErrorCorrectionLevel.H + EncodeHintType.ERROR_CORRECTION to qrCodeErrorCorrectionLevel // This is not required in the specs and it should not be enabled // it is causing crash on older Android versions ex:API 23 // EncodeHintType.CHARACTER_SET to Charsets.UTF_8 From b7d5d14b55fd045ebdf4d6edc37e2144d913e97d Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 09:31:02 +0100 Subject: [PATCH 04/17] lint --- .../checkins/qrcode/DefaultQRCodeVerifierTest.kt | 2 -- .../ui/qrcode/QrCodeCreationTestViewModel.kt | 2 -- .../de/rki/coronawarnapp/appconfig/mapping/ConfigParser.kt | 2 +- .../appconfig/mapping/PresenceTracingConfigMapper.kt | 6 +++--- .../eventregistration/events/DefaultTraceLocationKtTest.kt | 2 +- .../storage/entity/TraceLocationConvertersTest.kt | 2 +- .../storage/entity/TraceLocationEntityTest.kt | 2 +- 7 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest.kt index 5e837010548..83f1ef19923 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest.kt @@ -1,8 +1,6 @@ package de.rki.coronawarnapp.eventregistration.checkins.qrcode import de.rki.coronawarnapp.environment.EnvironmentSetup -import de.rki.coronawarnapp.eventregistration.common.decodeBase32 -import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass import de.rki.coronawarnapp.util.security.SignatureValidation import io.kotest.assertions.throwables.shouldNotThrowAny import io.kotest.assertions.throwables.shouldThrow diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt index c197bc28d88..268db7561ee 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt @@ -10,11 +10,9 @@ import com.google.zxing.BarcodeFormat import com.google.zxing.EncodeHintType import com.google.zxing.MultiFormatWriter import com.google.zxing.common.BitMatrix -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import de.rki.coronawarnapp.appconfig.AppConfigProvider -import de.rki.coronawarnapp.server.protocols.internal.AppConfig import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.files.FileSharing diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParser.kt index 43d06fb9c43..de22141776d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParser.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParser.kt @@ -36,7 +36,7 @@ class ConfigParser @Inject constructor( survey = surveyConfigMapper.map(it), analytics = analyticsConfigMapper.map(it), logUpload = logUploadConfigMapper.map(it), - presenceTracing=presenceTracingConfigMapper.map(it) + presenceTracing = presenceTracingConfigMapper.map(it) ) } } catch (e: Exception) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt index 090a2e9f7ef..a25ebee282d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/mapping/PresenceTracingConfigMapper.kt @@ -8,11 +8,11 @@ import de.rki.coronawarnapp.appconfig.PresenceTracingRiskCalculationParamContain import de.rki.coronawarnapp.appconfig.PresenceTracingSubmissionParamContainer import de.rki.coronawarnapp.server.protocols.internal.v2.AppConfigAndroid import de.rki.coronawarnapp.server.protocols.internal.v2 -.PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters + .PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters import de.rki.coronawarnapp.server.protocols.internal.v2 -.PresenceTracingParametersOuterClass.PresenceTracingRiskCalculationParameters + .PresenceTracingParametersOuterClass.PresenceTracingRiskCalculationParameters import de.rki.coronawarnapp.server.protocols.internal.v2 -.PresenceTracingParametersOuterClass.PresenceTracingParameters.QRCodeErrorCorrectionLevel + .PresenceTracingParametersOuterClass.PresenceTracingParameters.QRCodeErrorCorrectionLevel import timber.log.Timber import javax.inject.Inject diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocationKtTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocationKtTest.kt index 7aefa48ae7e..4b624abcb3a 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocationKtTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocationKtTest.kt @@ -108,4 +108,4 @@ internal class DefaultTraceLocationKtTest : BaseTest() { ) ) } -} \ No newline at end of file +} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationConvertersTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationConvertersTest.kt index b11ff01460a..24260f9a924 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationConvertersTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationConvertersTest.kt @@ -26,4 +26,4 @@ internal class TraceLocationConvertersTest : BaseTest() { fromTraceLocationType(TraceLocation.Type.TEMPORARY_OTHER) shouldBe 2 } } -} \ No newline at end of file +} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntityTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntityTest.kt index e796c1838e3..df49201e4cd 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntityTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntityTest.kt @@ -58,4 +58,4 @@ internal class TraceLocationEntityTest : BaseTest() { signature = "signature" ) } -} \ No newline at end of file +} From f91cbbe17c660687d3fe337fdbf0991d0a14f59f Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 09:48:06 +0100 Subject: [PATCH 05/17] Fix tests --- .../rki/coronawarnapp/appconfig/mapping/ConfigParserTest.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParserTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParserTest.kt index ab457e8182c..6f605d32f8f 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParserTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/mapping/ConfigParserTest.kt @@ -7,6 +7,7 @@ import de.rki.coronawarnapp.appconfig.ExposureDetectionConfig import de.rki.coronawarnapp.appconfig.ExposureWindowRiskCalculationConfig import de.rki.coronawarnapp.appconfig.KeyDownloadConfig import de.rki.coronawarnapp.appconfig.LogUploadConfig +import de.rki.coronawarnapp.appconfig.PresenceTracingConfig import de.rki.coronawarnapp.appconfig.SurveyConfig import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe @@ -30,6 +31,7 @@ class ConfigParserTest : BaseTest() { @MockK lateinit var surveyConfigMapper: SurveyConfig.Mapper @MockK lateinit var analyticsConfigMapper: AnalyticsConfig.Mapper @MockK lateinit var logUploadConfigMapper: LogUploadConfig.Mapper + @MockK lateinit var presenceTracingConfigMapper: PresenceTracingConfig.Mapper private val appConfig171 = File("src/test/resources/appconfig_1_7_1.bin") private val appConfig180 = File("src/test/resources/appconfig_1_8_0.bin") @@ -45,6 +47,7 @@ class ConfigParserTest : BaseTest() { every { surveyConfigMapper.map(any()) } returns mockk() every { analyticsConfigMapper.map(any()) } returns mockk() every { logUploadConfigMapper.map(any()) } returns mockk() + every { presenceTracingConfigMapper.map(any()) } returns mockk() appConfig171.exists() shouldBe true appConfig180.exists() shouldBe true @@ -57,7 +60,8 @@ class ConfigParserTest : BaseTest() { exposureWindowRiskCalculationConfigMapper = exposureWindowRiskCalculationConfigMapper, surveyConfigMapper = surveyConfigMapper, analyticsConfigMapper = analyticsConfigMapper, - logUploadConfigMapper = logUploadConfigMapper + logUploadConfigMapper = logUploadConfigMapper, + presenceTracingConfigMapper = presenceTracingConfigMapper ) @Test From 89afdeb26fc607ecfef30a5c4412dcdf2fa18399 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 11:05:03 +0100 Subject: [PATCH 06/17] Create TimeIntervalDeriver.kt --- .../checkins/derivetime/TimeIntervalDeriver.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt new file mode 100644 index 00000000000..a5e4724097c --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt @@ -0,0 +1,11 @@ +package de.rki.coronawarnapp.eventregistration.checkins.derivetime + +private const val INTERVAL_LENGTH_IN_SECONDS = 10 * 60 +fun alignToInterval(timestamp:Long) = (timestamp / INTERVAL_LENGTH_IN_SECONDS) * INTERVAL_LENGTH_IN_SECONDS +//fun inRange (range, value:Int ) => { +// if (range.minExclusive === true && value <= range.min) return false +// else if (range.minExclusive !== true && value < range.min) return false +// if (range.maxExclusive === true && value >= range.max) return false +// else if (range.maxExclusive !== true && value > range.max) return false +// return true +//} From fc972d1870862ed45f7c7d0397ad3282c8e86dc8 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 12:10:35 +0100 Subject: [PATCH 07/17] Implement time deriver --- .../derivetime/TimeIntervalDeriver.kt | 78 ++++++++++++++++--- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt index a5e4724097c..56f64b428c8 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt @@ -1,11 +1,71 @@ package de.rki.coronawarnapp.eventregistration.checkins.derivetime -private const val INTERVAL_LENGTH_IN_SECONDS = 10 * 60 -fun alignToInterval(timestamp:Long) = (timestamp / INTERVAL_LENGTH_IN_SECONDS) * INTERVAL_LENGTH_IN_SECONDS -//fun inRange (range, value:Int ) => { -// if (range.minExclusive === true && value <= range.min) return false -// else if (range.minExclusive !== true && value < range.min) return false -// if (range.maxExclusive === true && value >= range.max) return false -// else if (range.maxExclusive !== true && value > range.max) return false -// return true -//} +import de.rki.coronawarnapp.appconfig.PresenceTracingSubmissionParamContainer +import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass.Range +import timber.log.Timber +import java.util.concurrent.TimeUnit +import kotlin.math.max +import kotlin.math.roundToLong + +private const val MINUTES_INTERVAL = 10L + +private fun minutesInSeconds(minutes: Long) = TimeUnit.MINUTES.toSeconds(minutes) + +private fun alignToInterval(timestamp: Long): Long { + val minutesInSeconds = minutesInSeconds(MINUTES_INTERVAL) + return (timestamp / minutesInSeconds) * minutesInSeconds +} + +private fun Range.inRange(value: Long): Boolean { + if (minExclusive && value <= min) return false + else if (!minExclusive && value < min) return false + + if (maxExclusive && value >= max) return false + else if (!maxExclusive && value > max) return false + + return true +} + +fun PresenceTracingSubmissionParamContainer.deriveTime( + startTimestamp: Long, + endTimestamp: Long +): Pair? { + val durationInSeconds = max(0, endTimestamp - startTimestamp) + val durationInMinutes = TimeUnit.SECONDS.toMinutes(durationInSeconds) + Timber.d("durationInSeconds: $durationInSeconds") + + val dropDueToDuration = durationFilters.any { durationFilter -> + durationFilter.dropIfMinutesInRange.inRange(durationInMinutes) + } + + Timber.d("dropDueToDuration: $dropDueToDuration") + if (dropDueToDuration) return null + + val aerosoleDecayInSeconds = aerosoleDecayLinearFunctions.filter { aerosole -> + aerosole.minutesRange.inRange(durationInMinutes) + }.map { aerosole -> + aerosole.slope * durationInSeconds + minutesInSeconds(aerosole.intercept.toLong()) + }.firstOrNull() ?: 0.0 //default: zero, i.e. 'no decay' + + val relevantEndTimestamp = endTimestamp + aerosoleDecayInSeconds + val relevantStartIntervalTimestamp = alignToInterval(startTimestamp) + val relevantEndIntervalTimestamp = alignToInterval(relevantEndTimestamp.toLong()) + + val overlapWithStartInterval = relevantStartIntervalTimestamp + MINUTES_INTERVAL - startTimestamp + val overlapWithEndInterval = relevantEndTimestamp - relevantEndIntervalTimestamp + Timber.d("overlapWithStartInterval: $overlapWithStartInterval") + Timber.d("overlapWithEndInterval: $overlapWithEndInterval") + + val targetDurationInSeconds = + ((durationInSeconds + aerosoleDecayInSeconds) / MINUTES_INTERVAL).roundToLong() * MINUTES_INTERVAL + Timber.d("targetDurationInSeconds: $targetDurationInSeconds") + + return if (overlapWithEndInterval > overlapWithStartInterval) { + val newEndTimestamp = relevantEndIntervalTimestamp + MINUTES_INTERVAL + val newStartTimestamp = newEndTimestamp - targetDurationInSeconds + newStartTimestamp to newEndTimestamp + } else { + val newEndTimestamp = relevantStartIntervalTimestamp + targetDurationInSeconds + relevantStartIntervalTimestamp to newEndTimestamp + } +} From 9331a8488d0c5c8d8ae3409dc8a5728b25fbee5c Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 12:10:51 +0100 Subject: [PATCH 08/17] Add test class --- .../derivetime/TimeIntervalDeriverTest.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt new file mode 100644 index 00000000000..e0bdb378d2c --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt @@ -0,0 +1,23 @@ +package de.rki.coronawarnapp.eventregistration.checkins.derivetime + +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* +import testhelpers.BaseTest + +internal class TimeIntervalDeriverTest : BaseTest() { + + @BeforeEach + fun setUp() { + } + + @AfterEach + fun tearDown() { + } + + @Test + fun deriveTime() { + } +} \ No newline at end of file From a0fcedcf13d829ca0fc41341dc482d95467786c3 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 16:37:46 +0100 Subject: [PATCH 09/17] Adjustment --- .../derivetime/TimeIntervalDeriver.kt | 62 +++++++++++-------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt index 56f64b428c8..0ddb4516a43 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt @@ -7,23 +7,30 @@ import java.util.concurrent.TimeUnit import kotlin.math.max import kotlin.math.roundToLong -private const val MINUTES_INTERVAL = 10L +private val INTERVAL_LENGTH_IN_SECONDS = TimeUnit.MINUTES.toSeconds(10L) -private fun minutesInSeconds(minutes: Long) = TimeUnit.MINUTES.toSeconds(minutes) - -private fun alignToInterval(timestamp: Long): Long { - val minutesInSeconds = minutesInSeconds(MINUTES_INTERVAL) - return (timestamp / minutesInSeconds) * minutesInSeconds -} +private fun alignToInterval(timestamp: Long) = + (timestamp / INTERVAL_LENGTH_IN_SECONDS) * INTERVAL_LENGTH_IN_SECONDS private fun Range.inRange(value: Long): Boolean { - if (minExclusive && value <= min) return false - else if (!minExclusive && value < min) return false - - if (maxExclusive && value >= max) return false - else if (!maxExclusive && value > max) return false + val inRage = when { + minExclusive && value <= min -> false + !minExclusive && value < min -> false + maxExclusive && value >= max -> false + !maxExclusive && value > max -> false + else -> true + } - return true + Timber.d( + "Value:%s isInRange:%s - Range{min:%s,max:%s,minExclusive:%s,maxExclusive:%s}", + value, + inRage, + min, + max, + minExclusive, + maxExclusive + ) + return inRage } fun PresenceTracingSubmissionParamContainer.deriveTime( @@ -31,40 +38,45 @@ fun PresenceTracingSubmissionParamContainer.deriveTime( endTimestamp: Long ): Pair? { val durationInSeconds = max(0, endTimestamp - startTimestamp) - val durationInMinutes = TimeUnit.SECONDS.toMinutes(durationInSeconds) Timber.d("durationInSeconds: $durationInSeconds") + val durationInMinutes = TimeUnit.SECONDS.toMinutes(durationInSeconds) + Timber.d("durationInMinutes: $durationInMinutes") + val dropDueToDuration = durationFilters.any { durationFilter -> durationFilter.dropIfMinutesInRange.inRange(durationInMinutes) } - Timber.d("dropDueToDuration: $dropDueToDuration") if (dropDueToDuration) return null - val aerosoleDecayInSeconds = aerosoleDecayLinearFunctions.filter { aerosole -> + val aerosoleDecays = aerosoleDecayLinearFunctions.filter { aerosole -> aerosole.minutesRange.inRange(durationInMinutes) }.map { aerosole -> - aerosole.slope * durationInSeconds + minutesInSeconds(aerosole.intercept.toLong()) - }.firstOrNull() ?: 0.0 //default: zero, i.e. 'no decay' + aerosole.slope * durationInSeconds + TimeUnit.MINUTES.toSeconds(aerosole.intercept.toLong()) + } + Timber.d("aerosoleDecays:$aerosoleDecays") + val aerosoleDecayInSeconds = aerosoleDecays.firstOrNull() ?: 0.0 // Default: zero, i.e. 'no decay' + Timber.d("aerosoleDecayInSeconds: $aerosoleDecayInSeconds") - val relevantEndTimestamp = endTimestamp + aerosoleDecayInSeconds + val relevantEndTimestamp = endTimestamp + aerosoleDecayInSeconds.toLong() val relevantStartIntervalTimestamp = alignToInterval(startTimestamp) - val relevantEndIntervalTimestamp = alignToInterval(relevantEndTimestamp.toLong()) - - val overlapWithStartInterval = relevantStartIntervalTimestamp + MINUTES_INTERVAL - startTimestamp + val relevantEndIntervalTimestamp = alignToInterval(relevantEndTimestamp) + val overlapWithStartInterval = relevantStartIntervalTimestamp + INTERVAL_LENGTH_IN_SECONDS - startTimestamp val overlapWithEndInterval = relevantEndTimestamp - relevantEndIntervalTimestamp Timber.d("overlapWithStartInterval: $overlapWithStartInterval") Timber.d("overlapWithEndInterval: $overlapWithEndInterval") val targetDurationInSeconds = - ((durationInSeconds + aerosoleDecayInSeconds) / MINUTES_INTERVAL).roundToLong() * MINUTES_INTERVAL - Timber.d("targetDurationInSeconds: $targetDurationInSeconds") + ((durationInSeconds + aerosoleDecayInSeconds) / INTERVAL_LENGTH_IN_SECONDS).roundToLong() * INTERVAL_LENGTH_IN_SECONDS + Timber.d("targetDurationInSeconds:$targetDurationInSeconds") return if (overlapWithEndInterval > overlapWithStartInterval) { - val newEndTimestamp = relevantEndIntervalTimestamp + MINUTES_INTERVAL + Timber.d("overlapWithEndInterval: $overlapWithEndInterval > overlapWithStartInterval: $overlapWithStartInterval") + val newEndTimestamp = relevantEndIntervalTimestamp + INTERVAL_LENGTH_IN_SECONDS val newStartTimestamp = newEndTimestamp - targetDurationInSeconds newStartTimestamp to newEndTimestamp } else { + Timber.d("overlapWithEndInterval: $overlapWithEndInterval > overlapWithStartInterval: $overlapWithStartInterval") val newEndTimestamp = relevantStartIntervalTimestamp + targetDurationInSeconds relevantStartIntervalTimestamp to newEndTimestamp } From 774a5aa72c9235fb7fb7f38213a836304bee79a2 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 16:38:01 +0100 Subject: [PATCH 10/17] Add test scenarios --- .../derivetime/TimeIntervalDeriverTest.kt | 271 +++++++++++++++++- 1 file changed, 263 insertions(+), 8 deletions(-) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt index e0bdb378d2c..0d2e7552a82 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt @@ -1,23 +1,278 @@ package de.rki.coronawarnapp.eventregistration.checkins.derivetime -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeEach +import de.rki.coronawarnapp.appconfig.PresenceTracingSubmissionParamContainer +import de.rki.coronawarnapp.server.protocols.internal.v2 +.PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters.DurationFilter +import de.rki.coronawarnapp.server.protocols.internal.v2 +.PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters.AerosoleDecayFunctionLinear +import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass.Range +import io.kotest.matchers.shouldBe +import org.joda.time.DateTime +import org.joda.time.format.DateTimeFormat +import org.joda.time.format.DateTimeFormatter import org.junit.jupiter.api.Test -import org.junit.jupiter.api.Assertions.* import testhelpers.BaseTest +import java.util.concurrent.TimeUnit +/** + * Test scenarios reference: [https://github.com/corona-warn-app/cwa-app-tech-spec/blob/ + * proposal/event-registration-mvp/test-cases/pt-derive-time-interval-data.json] + */ internal class TimeIntervalDeriverTest : BaseTest() { - @BeforeEach - fun setUp() { + /* "defaultConfiguration": { + "durationFilters": [ + { + "dropIfDurationInRange": { + "min": 0, + "max": 10, + "maxExclusive": true + } + } + ], + "aerosoleDecayTime": [ + { + "durationRange": { + "min": 0, + "max": 30 + }, + "slope": 1, + "intercept": 0 + }, + { + "durationRange": { + "min": 30, + "max": 9999, + "minExclusive": true + }, + "slope": 0, + "intercept": 30 + } + ] + } */ + + private val timeFormat: DateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm Z") + private val presenceTracingConfig = PresenceTracingSubmissionParamContainer( + durationFilters = listOf( + DurationFilter.newBuilder() + .setDropIfMinutesInRange( + Range.newBuilder() + .setMin(0.0) + .setMax(10.0) + .setMaxExclusive(true) + .build() + ) + .build() + ), + aerosoleDecayLinearFunctions = listOf( + AerosoleDecayFunctionLinear.newBuilder() + .setMinutesRange( + Range.newBuilder() + .setMin(0.0) + .setMax(30.0) + .build() + ) + .setSlope(1.0) + .setIntercept(0.0) + .build(), + AerosoleDecayFunctionLinear.newBuilder() + .setMinutesRange( + Range.newBuilder() + .setMin(30.0) + .setMax(9999.0) + .setMinExclusive(true) + .build() + ) + .setSlope(0.0) + .setIntercept(30.0) + .build() + ) + ) + + @Test + fun `Scenario 1`() { + /* + "description": "Scenario 1", + "startDateStr": "2021-03-04 10:21+01:00", + "endDateStr": "2021-03-04 10:29+01:00", + "expStartDateStr": null, + "expEndDateStr": null + */ + presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:21 +01:00"), + timeInSeconds("2021-03-04 10:29 +01:00") + ) shouldBe null + } + + @Test + fun `Scenario 2`() { + /* + "description": "Scenario 2", + "startDateStr": "2021-03-04 10:20+01:00", + "endDateStr": "2021-03-04 10:30+01:00", + "expStartDateStr": "2021-03-04 10:20+01:00", + "expEndDateStr": "2021-03-04 10:40+01:00" + */ + val (startTime, endTime) = presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:20 +01:00"), + timeInSeconds("2021-03-04 10:30 +01:00") + )!! + + timeToString(startTime) shouldBe "2021-03-04 10:20 +0100" + timeToString(endTime) shouldBe "2021-03-04 10:40 +0100" + } + + @Test + fun `Scenario 3`() { + /* + "description": "Scenario 3", + "startDateStr": "2021-03-04 10:21+01:00", + "endDateStr": "2021-03-04 10:31+01:00", + "expStartDateStr": "2021-03-04 10:20+01:00", + "expEndDateStr": "2021-03-04 10:40+01:00" + */ + val (startTime, endTime) = presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:21 +01:00"), + timeInSeconds("2021-03-04 10:31 +01:00") + )!! + + timeToString(startTime) shouldBe "2021-03-04 10:20 +0100" + timeToString(endTime) shouldBe "2021-03-04 10:40 +0100" + } + + @Test + fun `Scenario 4`() { + /* + "description": "Scenario 4", + "startDateStr": "2021-03-04 10:26+01:00", + "endDateStr": "2021-03-04 10:36+01:00", + "expStartDateStr": "2021-03-04 10:30+01:00", + "expEndDateStr": "2021-03-04 10:50+01:00" + */ + val (startTime, endTime) = presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:26 +01:00"), + timeInSeconds("2021-03-04 10:36 +01:00") + )!! + + timeToString(startTime) shouldBe "2021-03-04 10:30 +0100" + timeToString(endTime) shouldBe "2021-03-04 10:50 +0100" + } + + @Test + fun `Scenario 5`() { + /* + "description": "Scenario 5", + "startDateStr": "2021-03-04 10:21+01:00", + "endDateStr": "2021-03-04 10:33+01:00", + "expStartDateStr": "2021-03-04 10:20+01:00", + "expEndDateStr": "2021-03-04 10:40+01:00" + */ + val (startTime, endTime) = presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:21 +01:00"), + timeInSeconds("2021-03-04 10:33 +01:00") + )!! + + timeToString(startTime) shouldBe "2021-03-04 10:20 +0100" + timeToString(endTime) shouldBe "2021-03-04 10:40 +0100" } - @AfterEach - fun tearDown() { + @Test + fun `Scenario 6`() { + /* + "description": "Scenario 6", + "startDateStr": "2021-03-04 10:24+01:00", + "endDateStr": "2021-03-04 10:36+01:00", + "expStartDateStr": "2021-03-04 10:30+01:00", + "expEndDateStr": "2021-03-04 10:50+01:00" + */ + val (startTime, endTime) = presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:24 +01:00"), + timeInSeconds("2021-03-04 10:36 +01:00") + )!! + + timeToString(startTime) shouldBe "2021-03-04 10:30 +0100" + timeToString(endTime) shouldBe "2021-03-04 10:50 +0100" + } + + @Test + fun `Scenario 7`() { + /* + "description": "Scenario 7", + "startDateStr": "2021-03-04 10:25+01:00", + "endDateStr": "2021-03-04 10:39+01:00", + "expStartDateStr": "2021-03-04 10:20+01:00", + "expEndDateStr": "2021-03-04 10:50+01:00" + */ + val (startTime, endTime) = presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:25 +01:00"), + timeInSeconds("2021-03-04 10:39 +01:00") + )!! + + timeToString(startTime) shouldBe "2021-03-04 10:20 +0100" + timeToString(endTime) shouldBe "2021-03-04 10:50 +0100" + } + + @Test + fun `Scenario 8`() { + /* + "description": "Scenario 8", + "startDateStr": "2021-03-04 10:28+01:00", + "endDateStr": "2021-03-04 10:42+01:00", + "expStartDateStr": "2021-03-04 10:30+01:00", + "expEndDateStr": "2021-03-04 11:00+01:00" + */ + val (startTime, endTime) = presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:28 +01:00"), + timeInSeconds("2021-03-04 10:42 +01:00") + )!! + + timeToString(startTime) shouldBe "2021-03-04 10:30 +0100" + timeToString(endTime) shouldBe "2021-03-04 11:00 +0100" } @Test - fun deriveTime() { + fun `Scenario 9`() { + /* + "description": "Scenario 9", + "startDateStr": "2021-03-04 10:25+01:00", + "endDateStr": "2021-03-04 10:40+01:00", + "expStartDateStr": "2021-03-04 10:20+01:00", + "expEndDateStr": "2021-03-04 10:50+01:00" + */ + val (startTime, endTime) = presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:25 +01:00"), + timeInSeconds("2021-03-04 10:40 +01:00") + )!! + + timeToString(startTime) shouldBe "2021-03-04 10:20 +0100" + timeToString(endTime) shouldBe "2021-03-04 10:50 +0100" + } + + @Test + fun `Scenario 10`() { + /* + "description": "Scenario 10", + "startDateStr": "2021-03-04 10:22+01:00", + "endDateStr": "2021-03-04 11:12+01:00", + "expStartDateStr": "2021-03-04 10:20+01:00", + "expEndDateStr": "2021-03-04 11:40+01:00" + */ + val (startTime, endTime) = presenceTracingConfig.deriveTime( + timeInSeconds("2021-03-04 10:22 +01:00"), + timeInSeconds("2021-03-04 11:12 +01:00") + )!! + + timeToString(startTime) shouldBe "2021-03-04 10:20 +0100" + timeToString(endTime) shouldBe "2021-03-04 11:40 +0100" + } + + private fun timeInSeconds(dateTime: String): Long { + val millis = timeFormat.parseDateTime(dateTime).millis + return TimeUnit.MILLISECONDS.toSeconds(millis) + } + + private fun timeToString(timeInSecond: Long): String { + return DateTime(TimeUnit.SECONDS.toMillis(timeInSecond)).toString(timeFormat) } } \ No newline at end of file From 6200391a5cbeac02117d1080e22c7f5af69602dd Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 16:48:52 +0100 Subject: [PATCH 11/17] detekt --- .../checkins/derivetime/TimeIntervalDeriver.kt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt index 0ddb4516a43..76a7c22ebe6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt @@ -67,16 +67,26 @@ fun PresenceTracingSubmissionParamContainer.deriveTime( Timber.d("overlapWithEndInterval: $overlapWithEndInterval") val targetDurationInSeconds = - ((durationInSeconds + aerosoleDecayInSeconds) / INTERVAL_LENGTH_IN_SECONDS).roundToLong() * INTERVAL_LENGTH_IN_SECONDS + ((durationInSeconds + aerosoleDecayInSeconds) / INTERVAL_LENGTH_IN_SECONDS).roundToLong() * + INTERVAL_LENGTH_IN_SECONDS + Timber.d("targetDurationInSeconds:$targetDurationInSeconds") return if (overlapWithEndInterval > overlapWithStartInterval) { - Timber.d("overlapWithEndInterval: $overlapWithEndInterval > overlapWithStartInterval: $overlapWithStartInterval") + Timber.d( + "overlapWithEndInterval:%s > overlapWithStartInterval:%s", + overlapWithEndInterval, + overlapWithStartInterval + ) val newEndTimestamp = relevantEndIntervalTimestamp + INTERVAL_LENGTH_IN_SECONDS val newStartTimestamp = newEndTimestamp - targetDurationInSeconds newStartTimestamp to newEndTimestamp } else { - Timber.d("overlapWithEndInterval: $overlapWithEndInterval > overlapWithStartInterval: $overlapWithStartInterval") + Timber.d( + "overlapWithEndInterval:%s, overlapWithStartInterval:%s", + overlapWithEndInterval, + overlapWithStartInterval + ) val newEndTimestamp = relevantStartIntervalTimestamp + targetDurationInSeconds relevantStartIntervalTimestamp to newEndTimestamp } From 28302c6a7365fc1b555c6d4b822b82faf3fada82 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 17:26:02 +0100 Subject: [PATCH 12/17] Specify locale --- .../checkins/derivetime/TimeIntervalDeriverTest.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt index 0d2e7552a82..a42e4619f2f 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt @@ -13,6 +13,7 @@ import org.joda.time.format.DateTimeFormatter import org.junit.jupiter.api.Test import testhelpers.BaseTest +import java.util.Locale import java.util.concurrent.TimeUnit /** @@ -53,6 +54,7 @@ internal class TimeIntervalDeriverTest : BaseTest() { } */ private val timeFormat: DateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm Z") + .withLocale(Locale.GERMAN) private val presenceTracingConfig = PresenceTracingSubmissionParamContainer( durationFilters = listOf( DurationFilter.newBuilder() @@ -275,4 +277,4 @@ internal class TimeIntervalDeriverTest : BaseTest() { private fun timeToString(timeInSecond: Long): String { return DateTime(TimeUnit.SECONDS.toMillis(timeInSecond)).toString(timeFormat) } -} \ No newline at end of file +} From bfea9f0bf6c7ebc4c7ad69180d2cdad12d5ae226 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Mon, 15 Mar 2021 17:34:32 +0100 Subject: [PATCH 13/17] Set time zone --- .../checkins/derivetime/TimeIntervalDeriverTest.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt index a42e4619f2f..ce9db2f1c8e 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt @@ -8,6 +8,7 @@ import de.rki.coronawarnapp.server.protocols.internal.v2 import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass.Range import io.kotest.matchers.shouldBe import org.joda.time.DateTime +import org.joda.time.DateTimeZone import org.joda.time.format.DateTimeFormat import org.joda.time.format.DateTimeFormatter import org.junit.jupiter.api.Test @@ -54,7 +55,8 @@ internal class TimeIntervalDeriverTest : BaseTest() { } */ private val timeFormat: DateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm Z") - .withLocale(Locale.GERMAN) + .withZone(DateTimeZone.forID("Europe/Berlin")) + private val presenceTracingConfig = PresenceTracingSubmissionParamContainer( durationFilters = listOf( DurationFilter.newBuilder() From b8fffd17147924a2419fb5a095bff8fe981c9a60 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Tue, 16 Mar 2021 12:47:33 +0100 Subject: [PATCH 14/17] Make inRange public --- .../de/rki/coronawarnapp/risk/DefaultRiskLevels.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt index 85fd30cce11..07dc8684624 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt @@ -173,11 +173,11 @@ class DefaultRiskLevels @Inject constructor() : RiskLevels { // 6. Determine `Total Risk` val totalRiskLevel = if (exposureHistory.any { - it.riskLevel == RiskCalculationParametersOuterClass - .NormalizedTimeToRiskLevelMapping - .RiskLevel - .HIGH - } + it.riskLevel == RiskCalculationParametersOuterClass + .NormalizedTimeToRiskLevelMapping + .RiskLevel + .HIGH + } ) { RiskCalculationParametersOuterClass.NormalizedTimeToRiskLevelMapping.RiskLevel.HIGH } else { @@ -310,7 +310,7 @@ class DefaultRiskLevels @Inject constructor() : RiskLevels { "The Report Type returned by the ENF is not known" ) - private fun RiskCalculationParametersOuterClass.Range.inRange(value: T): Boolean = + fun RiskCalculationParametersOuterClass.Range.inRange(value: T): Boolean = when { minExclusive && value.toDouble() <= min -> false !minExclusive && value.toDouble() < min -> false From c26696e7da60a1e24f27629f01a53127504e3d51 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Tue, 16 Mar 2021 12:50:01 +0100 Subject: [PATCH 15/17] Use common in Range - specify the timestamp in seconds --- .../derivetime/TimeIntervalDeriver.kt | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt index 76a7c22ebe6..c6b784da0ea 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt @@ -1,7 +1,7 @@ package de.rki.coronawarnapp.eventregistration.checkins.derivetime import de.rki.coronawarnapp.appconfig.PresenceTracingSubmissionParamContainer -import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass.Range +import de.rki.coronawarnapp.risk.DefaultRiskLevels.Companion.inRange import timber.log.Timber import java.util.concurrent.TimeUnit import kotlin.math.max @@ -12,32 +12,16 @@ private val INTERVAL_LENGTH_IN_SECONDS = TimeUnit.MINUTES.toSeconds(10L) private fun alignToInterval(timestamp: Long) = (timestamp / INTERVAL_LENGTH_IN_SECONDS) * INTERVAL_LENGTH_IN_SECONDS -private fun Range.inRange(value: Long): Boolean { - val inRage = when { - minExclusive && value <= min -> false - !minExclusive && value < min -> false - maxExclusive && value >= max -> false - !maxExclusive && value > max -> false - else -> true - } - - Timber.d( - "Value:%s isInRange:%s - Range{min:%s,max:%s,minExclusive:%s,maxExclusive:%s}", - value, - inRage, - min, - max, - minExclusive, - maxExclusive - ) - return inRage -} - +/** + * Derive CheckIn start and end times + * @param startTimestampInSeconds [Long] timestamp in seconds + * @param endTimestampInSeconds [Long] timestamp in seconds + */ fun PresenceTracingSubmissionParamContainer.deriveTime( - startTimestamp: Long, - endTimestamp: Long + startTimestampInSeconds: Long, + endTimestampInSeconds: Long ): Pair? { - val durationInSeconds = max(0, endTimestamp - startTimestamp) + val durationInSeconds = max(0, endTimestampInSeconds - startTimestampInSeconds) Timber.d("durationInSeconds: $durationInSeconds") val durationInMinutes = TimeUnit.SECONDS.toMinutes(durationInSeconds) @@ -58,10 +42,10 @@ fun PresenceTracingSubmissionParamContainer.deriveTime( val aerosoleDecayInSeconds = aerosoleDecays.firstOrNull() ?: 0.0 // Default: zero, i.e. 'no decay' Timber.d("aerosoleDecayInSeconds: $aerosoleDecayInSeconds") - val relevantEndTimestamp = endTimestamp + aerosoleDecayInSeconds.toLong() - val relevantStartIntervalTimestamp = alignToInterval(startTimestamp) + val relevantEndTimestamp = endTimestampInSeconds + aerosoleDecayInSeconds.toLong() + val relevantStartIntervalTimestamp = alignToInterval(startTimestampInSeconds) val relevantEndIntervalTimestamp = alignToInterval(relevantEndTimestamp) - val overlapWithStartInterval = relevantStartIntervalTimestamp + INTERVAL_LENGTH_IN_SECONDS - startTimestamp + val overlapWithStartInterval = relevantStartIntervalTimestamp + INTERVAL_LENGTH_IN_SECONDS - startTimestampInSeconds val overlapWithEndInterval = relevantEndTimestamp - relevantEndIntervalTimestamp Timber.d("overlapWithStartInterval: $overlapWithStartInterval") Timber.d("overlapWithEndInterval: $overlapWithEndInterval") From 49356a996861a3cf48b84aefffeafa147096ff41 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Tue, 16 Mar 2021 12:53:57 +0100 Subject: [PATCH 16/17] lint --- .../de/rki/coronawarnapp/risk/DefaultRiskLevels.kt | 10 +++++----- .../checkins/derivetime/TimeIntervalDeriverTest.kt | 7 +++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt index 07dc8684624..b7d4b469423 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt @@ -173,11 +173,11 @@ class DefaultRiskLevels @Inject constructor() : RiskLevels { // 6. Determine `Total Risk` val totalRiskLevel = if (exposureHistory.any { - it.riskLevel == RiskCalculationParametersOuterClass - .NormalizedTimeToRiskLevelMapping - .RiskLevel - .HIGH - } + it.riskLevel == RiskCalculationParametersOuterClass + .NormalizedTimeToRiskLevelMapping + .RiskLevel + .HIGH + } ) { RiskCalculationParametersOuterClass.NormalizedTimeToRiskLevelMapping.RiskLevel.HIGH } else { diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt index ce9db2f1c8e..eed36da372c 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriverTest.kt @@ -2,9 +2,9 @@ package de.rki.coronawarnapp.eventregistration.checkins.derivetime import de.rki.coronawarnapp.appconfig.PresenceTracingSubmissionParamContainer import de.rki.coronawarnapp.server.protocols.internal.v2 -.PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters.DurationFilter + .PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters.DurationFilter import de.rki.coronawarnapp.server.protocols.internal.v2 -.PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters.AerosoleDecayFunctionLinear + .PresenceTracingParametersOuterClass.PresenceTracingSubmissionParameters.AerosoleDecayFunctionLinear import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass.Range import io.kotest.matchers.shouldBe import org.joda.time.DateTime @@ -14,7 +14,6 @@ import org.joda.time.format.DateTimeFormatter import org.junit.jupiter.api.Test import testhelpers.BaseTest -import java.util.Locale import java.util.concurrent.TimeUnit /** @@ -56,7 +55,7 @@ internal class TimeIntervalDeriverTest : BaseTest() { private val timeFormat: DateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm Z") .withZone(DateTimeZone.forID("Europe/Berlin")) - + private val presenceTracingConfig = PresenceTracingSubmissionParamContainer( durationFilters = listOf( DurationFilter.newBuilder() From 9084884b7f40e1a40588022eeb9f5fe6b019f276 Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli Date: Wed, 17 Mar 2021 15:26:56 +0100 Subject: [PATCH 17/17] Explicit types --- .../checkins/derivetime/TimeIntervalDeriver.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt index c6b784da0ea..ddde8f6ad28 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/derivetime/TimeIntervalDeriver.kt @@ -27,19 +27,19 @@ fun PresenceTracingSubmissionParamContainer.deriveTime( val durationInMinutes = TimeUnit.SECONDS.toMinutes(durationInSeconds) Timber.d("durationInMinutes: $durationInMinutes") - val dropDueToDuration = durationFilters.any { durationFilter -> + val dropDueToDuration: Boolean = durationFilters.any { durationFilter -> durationFilter.dropIfMinutesInRange.inRange(durationInMinutes) } Timber.d("dropDueToDuration: $dropDueToDuration") if (dropDueToDuration) return null - val aerosoleDecays = aerosoleDecayLinearFunctions.filter { aerosole -> + val aerosoleDecays: List = aerosoleDecayLinearFunctions.filter { aerosole -> aerosole.minutesRange.inRange(durationInMinutes) }.map { aerosole -> aerosole.slope * durationInSeconds + TimeUnit.MINUTES.toSeconds(aerosole.intercept.toLong()) } Timber.d("aerosoleDecays:$aerosoleDecays") - val aerosoleDecayInSeconds = aerosoleDecays.firstOrNull() ?: 0.0 // Default: zero, i.e. 'no decay' + val aerosoleDecayInSeconds: Double = aerosoleDecays.firstOrNull() ?: 0.0 // Default: zero, i.e. 'no decay' Timber.d("aerosoleDecayInSeconds: $aerosoleDecayInSeconds") val relevantEndTimestamp = endTimestampInSeconds + aerosoleDecayInSeconds.toLong()