Skip to content

Commit b42c810

Browse files
committed
✨ Add Moving Average Graph to "All Time" chart
Closes #776 Signed-off-by: Leonardo Colman Lopes <[email protected]>
1 parent 76c1853 commit b42c810

File tree

3 files changed

+42
-9
lines changed

3 files changed

+42
-9
lines changed

app/src/main/kotlin/br/com/colman/petals/statistics/graph/AllTimeGraph.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import androidx.compose.runtime.Composable
44
import androidx.compose.ui.res.stringResource
55
import br.com.colman.petals.R.string.grams_distribution_over_days_since_first_use
66
import br.com.colman.petals.statistics.graph.component.LineChart
7-
import br.com.colman.petals.statistics.graph.data.createAllTimeDistribution
7+
import br.com.colman.petals.statistics.graph.data.createAllTimeDistributionWithMovingAverage
88
import br.com.colman.petals.statistics.graph.formatter.DaysSinceFirstUseFormatter
99
import br.com.colman.petals.use.repository.Use
1010
import com.github.mikephil.charting.components.LimitLine
@@ -13,10 +13,10 @@ import java.time.YearMonth
1313
@Composable
1414
fun AllTimeGraph(uses: List<Use>, dateFormat: String) {
1515
val description = stringResource(grams_distribution_over_days_since_first_use)
16-
val gramsData = createAllTimeDistribution(uses)
16+
val gramsData = createAllTimeDistributionWithMovingAverage(uses)
1717
val gramsDataList = listOf(gramsData)
1818

19-
LineChart(gramsDataList, description, 5f) {
19+
LineChart(gramsDataList.flatten(), description, 5f) {
2020
axisMinimum = 1f
2121
labelCount = 5
2222
granularity = 1f

app/src/main/kotlin/br/com/colman/petals/statistics/graph/data/DistributionPerDaySinceFirstUse.kt

+37-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.compose.ui.graphics.Color
55
import androidx.compose.ui.graphics.Color.Companion.Gray
66
import androidx.compose.ui.graphics.toArgb
77
import androidx.compose.ui.res.stringResource
8+
import br.com.colman.petals.R
89
import br.com.colman.petals.R.string.grams_distribution_over_days_since_first_use
910
import br.com.colman.petals.statistics.graph.formatter.GramsValueFormatter
1011
import br.com.colman.petals.use.repository.Use
@@ -14,25 +15,41 @@ import java.math.BigDecimal
1415
import java.time.LocalDate.now
1516

1617
@Composable
17-
fun createAllTimeDistribution(uses: List<Use>): LineDataSet {
18-
val label = stringResource(grams_distribution_over_days_since_first_use)
19-
return createAllTimeLineDataSet(calculateAllTimeGramsDistribution(uses), label)
18+
fun createAllTimeDistributionWithMovingAverage(uses: List<Use>): List<LineDataSet> {
19+
val gramsLabel = stringResource(grams_distribution_over_days_since_first_use)
20+
val gramsDataSet = createAllTimeLineDataSet(calculateAllTimeGramsDistribution(uses), gramsLabel)
21+
22+
val movingAverageLabel = stringResource(R.string.moving_average_grams_distribution)
23+
val movingAverageDataSet = createAllTimeAverageDataSet(
24+
calculateMovingAverage(calculateAllTimeGramsDistribution(uses)),
25+
movingAverageLabel
26+
)
27+
28+
return listOf(gramsDataSet, movingAverageDataSet)
2029
}
2130

2231
fun createAllTimeLineDataSet(entryList: List<Entry>, label: String): LineDataSet {
2332
return LineDataSet(entryList, label).apply {
2433
valueFormatter = GramsValueFormatter
2534
lineWidth = 6f
26-
setDrawCircles(true)
2735
setDrawFilled(true)
28-
setDrawValues(true)
36+
setDrawCircles(false)
2937
fillColor = Color.Cyan.copy(alpha = 0.3f).toArgb()
3038
color = Color.Cyan.toArgb()
3139
valueTextColor = Gray.toArgb()
3240
valueTextSize = 14f
3341
}
3442
}
3543

44+
fun createAllTimeAverageDataSet(entryList: List<Entry>, label: String): LineDataSet {
45+
return LineDataSet(entryList, label).apply {
46+
setDrawValues(false)
47+
setDrawCircles(false)
48+
lineWidth = 6f
49+
color = Color.Green.toArgb()
50+
}
51+
}
52+
3653
private fun calculateAllTimeGramsDistribution(uses: List<Use>): List<Entry> {
3754
if (uses.isEmpty()) return emptyList()
3855

@@ -46,3 +63,18 @@ private fun calculateAllTimeGramsDistribution(uses: List<Use>): List<Entry> {
4663
Entry((day - firstUseDay).toFloat(), totalGrams.toFloat())
4764
}
4865
}
66+
67+
private fun calculateMovingAverage(entries: List<Entry>): List<Entry> {
68+
if (entries.isEmpty()) return emptyList()
69+
70+
val result = mutableListOf<Entry>()
71+
for (i in entries.indices) {
72+
val start = maxOf(0, i - 14 + 1)
73+
val end = i + 1
74+
val windowEntries = entries.subList(start, end)
75+
76+
val averageValue = windowEntries.map { it.y }.average().toFloat()
77+
result.add(Entry(entries[i].x, averageValue))
78+
}
79+
return result
80+
}

app/src/main/res/values/strings.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,12 @@
172172
<string name="no_break_period">No break period</string>
173173
<string name="hours_12">12 hours</string>
174174
<string name="hours_24">24 hours</string>
175-
<string name="grams_distribution_over_days_since_first_use">Grams distribution over days since first use</string>
175+
<string name="grams_distribution_over_days_since_first_use">Grams per Day</string>
176176
<plurals name="last_x_days">
177177
<item quantity="one">Last %s day</item>
178178
<item quantity="other">Last %s days</item>
179179
</plurals>
180180
<string name="language_label">App language</string>
181181
<string name="what_language_should_be_used">What language should be used</string>
182+
<string name="moving_average_grams_distribution">Average Grams per Day</string>
182183
</resources>

0 commit comments

Comments
 (0)