Skip to content

Commit 178515a

Browse files
committed
show decimal values for tag values in detailed statistics
1 parent ec17d19 commit 178515a

File tree

3 files changed

+42
-26
lines changed

3 files changed

+42
-26
lines changed

core/src/main/java/com/example/util/simpletimetracker/core/extension/StringExtensions.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@ package com.example.util.simpletimetracker.core.extension
33
import android.text.Html.TagHandler
44
import android.text.Spanned
55
import androidx.core.text.HtmlCompat
6+
import androidx.core.text.parseAsHtml
67

78
fun String.fromHtml(tagHandler: TagHandler? = null): Spanned {
8-
return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_LEGACY, null, tagHandler)
9+
return this.parseAsHtml(HtmlCompat.FROM_HTML_MODE_LEGACY, null, tagHandler)
910
}
1011

1112
fun String.trimIfNotBlank(): String {
1213
return if (this.isNotBlank()) return this.trim() else this
14+
}
15+
16+
fun String.removeTrailingZeroes(): String {
17+
return (if ('.' in this) trimEnd('0') else this).trimEnd('.')
1318
}

features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/mapper/StatisticsDetailTagValuesViewDataMapper.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.example.util.simpletimetracker.feature_statistics_detail.mapper
22

3+
import com.example.util.simpletimetracker.core.extension.removeTrailingZeroes
34
import com.example.util.simpletimetracker.core.repo.ResourceRepo
45
import com.example.util.simpletimetracker.domain.statistics.model.RangeLength
56
import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType
@@ -139,29 +140,29 @@ class StatisticsDetailTagValuesViewDataMapper @Inject constructor(
139140
val emptyValue by lazy { resourceRepo.getString(R.string.statistics_detail_empty) }
140141

141142
val barValues = goalData.map { bar -> bar.totalDuration }
142-
val minValue = barValues.minOrNull()?.div(TAG_VALUE_PRECISION)
143-
val maxValue = barValues.maxOrNull()?.div(TAG_VALUE_PRECISION)
144-
val total = barValues.sum() / TAG_VALUE_PRECISION
143+
val minValue = barValues.minOrNull()?.toFloat()?.div(TAG_VALUE_PRECISION)
144+
val maxValue = barValues.maxOrNull()?.toFloat()?.div(TAG_VALUE_PRECISION)
145+
val total = barValues.sum().toFloat() / TAG_VALUE_PRECISION
145146

146147
return listOf(
147148
StatisticsDetailCardInternalViewData(
148-
value = minValue?.toString() ?: emptyValue,
149+
value = minValue?.toString()?.removeTrailingZeroes() ?: emptyValue,
149150
valueChange = StatisticsDetailCardInternalViewData.ValueChange.None,
150151
secondValue = "",
151152
description = resourceRepo.getString(R.string.records_filter_duration_min),
152153
titleTextSizeSp = 14,
153154
subtitleTextSizeSp = 12,
154155
),
155156
StatisticsDetailCardInternalViewData(
156-
value = total.toString(),
157+
value = total.toString().removeTrailingZeroes(),
157158
valueChange = StatisticsDetailCardInternalViewData.ValueChange.None,
158159
secondValue = "",
159160
description = resourceRepo.getString(R.string.statistics_detail_total_duration),
160161
titleTextSizeSp = 14,
161162
subtitleTextSizeSp = 12,
162163
),
163164
StatisticsDetailCardInternalViewData(
164-
value = maxValue?.toString() ?: emptyValue,
165+
value = maxValue?.toString()?.removeTrailingZeroes() ?: emptyValue,
165166
valueChange = StatisticsDetailCardInternalViewData.ValueChange.None,
166167
secondValue = "",
167168
description = resourceRepo.getString(R.string.records_filter_duration_max),

features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/mapper/StatisticsDetailViewDataMapper.kt

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.example.util.simpletimetracker.feature_statistics_detail.mapper
22

33
import android.annotation.SuppressLint
44
import android.graphics.Color
5+
import com.example.util.simpletimetracker.core.extension.removeTrailingZeroes
56
import com.example.util.simpletimetracker.core.mapper.CategoryViewDataMapper
67
import com.example.util.simpletimetracker.core.mapper.ColorMapper
78
import com.example.util.simpletimetracker.core.mapper.IconMapper
@@ -481,23 +482,33 @@ class StatisticsDetailViewDataMapper @Inject constructor(
481482
// No reason to show average of one value.
482483
if (data.size < 2 && compareData.size < 2) return "" to emptyList()
483484

484-
// TODO TAG show decimal values?
485-
fun getAverage(data: List<ChartBarDataDuration>): Long {
486-
if (data.isEmpty()) return 0L
487-
return data.sumOf { it.durations.sumOf { it.first } } / data.size
485+
// TODO TAG show decimal on selected bar
486+
fun getAverage(data: List<ChartBarDataDuration>): Float {
487+
if (data.isEmpty()) return 0f
488+
val sum = data.sumOf { point -> point.durations.sumOf { it.first } }.toFloat()
489+
return sum / data.size
488490
}
489491

490-
fun formatInterval(
491-
interval: Long,
492-
): String {
492+
@SuppressLint("DefaultLocale")
493+
fun formatDecimalValue(value: Float): String {
494+
val abs = abs(value)
495+
return when {
496+
abs >= 1000f -> value.toLong().toString()
497+
abs >= 100f -> String.format("%.1f", abs)
498+
abs >= 10f -> String.format("%.2f", abs)
499+
else -> String.format("%.3f", abs)
500+
}.toString().removeTrailingZeroes()
501+
}
502+
503+
fun formatInterval(interval: Float): String {
493504
return when (chartMode) {
494505
ChartMode.DURATIONS -> timeMapper.formatInterval(
495-
interval = interval,
506+
interval = interval.toLong(),
496507
forceSeconds = showSeconds,
497508
useProportionalMinutes = useProportionalMinutes,
498509
)
499-
ChartMode.COUNTS -> interval.toString()
500-
ChartMode.TAG_VALUE -> (interval / TAG_VALUE_PRECISION).toString()
510+
ChartMode.COUNTS -> formatDecimalValue(interval)
511+
ChartMode.TAG_VALUE -> formatDecimalValue(interval / TAG_VALUE_PRECISION)
501512
}
502513
}
503514

@@ -580,8 +591,8 @@ class StatisticsDetailViewDataMapper @Inject constructor(
580591
}
581592

582593
private fun mapValueChange(
583-
average: Long,
584-
prevAverage: Long,
594+
average: Float,
595+
prevAverage: Float,
585596
rangeLength: RangeLength,
586597
isDarkTheme: Boolean,
587598
): StatisticsDetailCardInternalViewData.ValueChange {
@@ -590,15 +601,14 @@ class StatisticsDetailViewDataMapper @Inject constructor(
590601
}
591602

592603
val change: Float = when {
593-
prevAverage.orZero() == 0L && average.orZero() == 0L -> 0f
594-
prevAverage.orZero() == 0L && average.orZero() > 0L -> 100f
595-
prevAverage.orZero() == 0L && average.orZero() < 0L -> -100f
596-
prevAverage != 0L -> {
597-
(average.orZero() - prevAverage) * 100f / abs(prevAverage)
598-
}
604+
prevAverage.orZero() == 0f && average.orZero() == 0f -> 0f
605+
prevAverage.orZero() == 0f && average.orZero() > 0f -> 100f
606+
prevAverage.orZero() == 0f && average.orZero() < 0f -> -100f
607+
prevAverage != 0f -> (average.orZero() - prevAverage) * 100f / abs(prevAverage)
599608
else -> 0f
600609
}
601610

611+
// Lowest precision is one decimal.
602612
@SuppressLint("DefaultLocale")
603613
fun formatChange(value: Float): String {
604614
val abs = abs(value)
@@ -641,7 +651,7 @@ class StatisticsDetailViewDataMapper @Inject constructor(
641651
return when (chartMode) {
642652
ChartMode.DURATIONS -> formatInterval(interval, isMinutes)
643653
ChartMode.COUNTS -> interval.toFloat()
644-
ChartMode.TAG_VALUE -> (interval / TAG_VALUE_PRECISION).toFloat()
654+
ChartMode.TAG_VALUE -> interval.toFloat() / TAG_VALUE_PRECISION
645655
}
646656
}
647657

0 commit comments

Comments
 (0)