diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/HealthUiStateMapper.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/HealthUiStateMapper.kt index 47439d87d..86fb19817 100644 --- a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/HealthUiStateMapper.kt +++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/HealthUiStateMapper.kt @@ -7,6 +7,7 @@ import androidx.health.connect.client.records.HeartRateRecord import androidx.health.connect.client.records.Record import androidx.health.connect.client.records.WeightRecord import edu.stanford.spezi.core.utils.LocaleProvider +import edu.stanford.spezi.core.utils.extensions.roundToDecimalPlaces import java.time.DayOfWeek import java.time.Instant import java.time.LocalDate @@ -108,10 +109,10 @@ class HealthUiStateMapper @Inject constructor( private fun mapXValue(selectedTimeRange: TimeRange, zonedDateTime: ZonedDateTime): Float { return when (selectedTimeRange) { - TimeRange.DAILY -> ((zonedDateTime.year.toFloat() + (zonedDateTime.dayOfYear - 1) / 365f) * 10).roundToTwoDecimalPlaces() + TimeRange.DAILY -> ((zonedDateTime.year.toFloat() + (zonedDateTime.dayOfYear - 1) / 365f) * 10) TimeRange.WEEKLY -> (zonedDateTime.toEpochSecond() / (7 * 24 * 60 * 60)).toFloat() TimeRange.MONTHLY -> zonedDateTime.year.toFloat() + (zonedDateTime.monthValue - 1) / 12f - } + }.roundToDecimalPlaces(places = 2) } private fun groupRecordsByTimeRange( @@ -346,11 +347,6 @@ class HealthUiStateMapper @Inject constructor( return date.format(DateTimeFormatter.ofPattern(pattern)) } - @Suppress("MagicNumber") - private fun Float.roundToTwoDecimalPlaces(): Float { - return Math.round(this * 100) / 100.0f - } - private data class ValueUnit(val value: Double, val unit: String) private sealed interface EngageRecord { diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapper.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapper.kt index 0596ce64f..d80055fa6 100644 --- a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapper.kt +++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapper.kt @@ -4,6 +4,8 @@ import edu.stanford.bdh.engagehf.health.AggregatedHealthData import edu.stanford.bdh.engagehf.health.HealthUiStateMapper.Companion.EPOCH_SECONDS_DIVISOR import edu.stanford.bdh.engagehf.health.NewestHealthData import edu.stanford.bdh.engagehf.health.TableEntryData +import edu.stanford.spezi.core.logging.SpeziLogger +import edu.stanford.spezi.core.utils.extensions.roundToDecimalPlaces import java.time.ZoneId import java.time.ZonedDateTime import java.time.format.DateTimeFormatter @@ -38,18 +40,17 @@ class SymptomsUiStateMapper @Inject constructor() { val chartData = calculateChartData(symptomScoresByDay, selectedSymptomType) val tableData = mapTableData(symptomScores, selectedSymptomType) - val newestData = symptomScores.maxByOrNull { it.date } + val newestData = symptomScores.maxBy { it.date } val newestHealthData = NewestHealthData( formattedValue = when (selectedSymptomType) { - SymptomType.OVERALL -> newestData?.overallScore.toString() - SymptomType.PHYSICAL_LIMITS -> newestData?.physicalLimitsScore.toString() - SymptomType.SOCIAL_LIMITS -> newestData?.socialLimitsScore.toString() - SymptomType.QUALITY_OF_LIFE -> newestData?.qualityOfLifeScore.toString() - SymptomType.SPECIFIC_SYMPTOMS -> newestData?.specificSymptomsScore.toString() - SymptomType.DIZZINESS -> newestData?.dizzinessScore.toString() + SymptomType.OVERALL -> newestData.overallScore.toString() + SymptomType.PHYSICAL_LIMITS -> newestData.physicalLimitsScore.toString() + SymptomType.SOCIAL_LIMITS -> newestData.socialLimitsScore.toString() + SymptomType.QUALITY_OF_LIFE -> newestData.qualityOfLifeScore.toString() + SymptomType.SPECIFIC_SYMPTOMS -> newestData.specificSymptomsScore.toString() + SymptomType.DIZZINESS -> newestData.dizzinessScore.toString() } + "%", - formattedDate = newestData?.date?.format(dateTimeFormatter) - ?: "" + formattedDate = newestData.date.format(dateTimeFormatter) ) return SymptomsUiState.Success( @@ -116,9 +117,12 @@ class SymptomsUiStateMapper @Inject constructor() { }.average().toFloat() yValues.add(averageScore) - xValues.add(date.toInstant().epochSecond / EPOCH_SECONDS_DIVISOR) + val xValue = (date.toInstant().epochSecond / EPOCH_SECONDS_DIVISOR) + .roundToDecimalPlaces(2) + xValues.add(xValue) } + SpeziLogger.i { "XValues: $xValues" } return AggregatedHealthData( yValues = yValues, xValues = xValues, diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/extensions/Float.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/extensions/Float.kt new file mode 100644 index 000000000..4c4ccd1f9 --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/extensions/Float.kt @@ -0,0 +1,9 @@ +package edu.stanford.spezi.core.utils.extensions + +import kotlin.math.pow + +@Suppress("MagicNumber") +fun Float.roundToDecimalPlaces(places: Int): Float { + val factor = (10.0).pow(places).toFloat() + return Math.round(this * factor) / factor +} diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/FloatRoundingTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/FloatRoundingTest.kt new file mode 100644 index 000000000..9bb276658 --- /dev/null +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/FloatRoundingTest.kt @@ -0,0 +1,22 @@ +package edu.stanford.spezi.core.utils + +import com.google.common.truth.Truth.assertThat +import edu.stanford.spezi.core.utils.extensions.roundToDecimalPlaces +import org.junit.Test + +class FloatRoundingTest { + + @Test + fun `it should round correctly`() { + // given + val float = 1.111111f + val places = 3 + + // when + val result = float.roundToDecimalPlaces(places = places) + val decimalPlaces = "$result".split(".").last() + + // then + assertThat(decimalPlaces.length).isEqualTo(places) + } +}