improve statistics

This commit is contained in:
2025-11-26 23:04:22 +01:00
parent bbf3b0ce8e
commit 7d480d6e1c
5 changed files with 429 additions and 156 deletions

View File

@@ -17,24 +17,39 @@ import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.formatter.ValueFormatter import com.github.mikephil.charting.formatter.ValueFormatter
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet import com.github.mikephil.charting.interfaces.datasets.IBarDataSet
import it.danieleverducci.lunatracker.entities.LunaEvent import it.danieleverducci.lunatracker.entities.LunaEvent
import utils.DateUtils.Companion.formatTimeDuration
import utils.NumericUtils import utils.NumericUtils
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import androidx.core.graphics.toColorInt
class StatisticsActivity : AppCompatActivity() { class StatisticsActivity : AppCompatActivity() {
lateinit var barChart: BarChart lateinit var barChart: BarChart
lateinit var noDataTextView: TextView lateinit var noDataTextView: TextView
lateinit var eventTypeSelection: Spinner lateinit var graphTypeSpinner: Spinner
lateinit var dataTypeSelection: Spinner //lateinit var dataTypeSelection: Spinner
lateinit var timeRangeSelection: Spinner lateinit var timeRangeSpinner: Spinner
enum class GraphType {
BOTTLE_EVENTS,
BOTTLE_SUM,
BOTTLE_SUM_AVERAGE,
SLEEP_SUM,
SLEEP_SUM_AVERAGE,
SLEEP_EVENTS,
SLEEP_PATTERN
}
enum class RangeType {
DAY,
WEEK,
MONTH
}
// default selection // default selection
var eventTypeSelectionValue = "BOTTLE" var graphTypeSelection = GraphType.SLEEP_SUM
var dataTypeSelectionValue = "AMOUNT" var timeRangeSelection = RangeType.DAY
var timeRangeSelectionValue = "DAY"
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -65,25 +80,38 @@ class StatisticsActivity : AppCompatActivity() {
barChart.xAxis.setDrawLabels(true) barChart.xAxis.setDrawLabels(true)
barChart.xAxis.setDrawAxisLine(false) barChart.xAxis.setDrawAxisLine(false)
eventTypeSelection = findViewById(R.id.type_selection) graphTypeSpinner = findViewById(R.id.type_selection)
dataTypeSelection = findViewById(R.id.data_selection) //dataTypeSelection = findViewById(R.id.data_selection)
timeRangeSelection = findViewById(R.id.time_selection) timeRangeSpinner = findViewById(R.id.time_selection)
setupSpinner(eventTypeSelectionValue, setupSpinner("SLEEP_SUM",
R.id.type_selection, R.id.type_selection,
R.array.StatisticsTypeLabels, R.array.StatisticsTypeLabels,
R.array.StatisticsTypeValues, R.array.StatisticsTypeValues,
object : SpinnerItemSelected { object : SpinnerItemSelected {
override fun call(newValue: String?) { override fun call(newValue: String?) {
if (newValue != null) { newValue ?: return
eventTypeSelectionValue = newValue graphTypeSelection = when (newValue) {
"BOTTLE_EVENTS" -> GraphType.BOTTLE_EVENTS
"BOTTLE_SUM" -> GraphType.BOTTLE_SUM
"BOTTLE_SUM_AVERAGE" -> GraphType.BOTTLE_SUM_AVERAGE
"SLEEP_SUM_AVERAGE" -> GraphType.SLEEP_SUM_AVERAGE
"SLEEP_SUM" -> GraphType.SLEEP_SUM
"SLEEP_SUM_AVERAGE" -> GraphType.SLEEP_SUM_AVERAGE
"SLEEP_EVENTS" -> GraphType.SLEEP_EVENTS
"SLEEP_PATTERN" -> GraphType.SLEEP_PATTERN
else -> {
Log.e(TAG, "Invalid graph type selection: $newValue")
return
}
}
//Log.d("event", "new value: $newValue") //Log.d("event", "new value: $newValue")
updateGraph() updateGraph()
} }
} }
}
) )
/*
setupSpinner(dataTypeSelectionValue, setupSpinner(dataTypeSelectionValue,
R.id.data_selection, R.id.data_selection,
R.array.StatisticsDataLabels, R.array.StatisticsDataLabels,
@@ -98,102 +126,168 @@ class StatisticsActivity : AppCompatActivity() {
} }
} }
) )
*/
setupSpinner(timeRangeSelectionValue, setupSpinner("DAY",
R.id.time_selection, R.id.time_selection,
R.array.StatisticsTimeLabels, R.array.StatisticsTimeLabels,
R.array.StatisticsTimeValues, R.array.StatisticsTimeValues,
object : SpinnerItemSelected { object : SpinnerItemSelected {
override fun call(newValue: String?) { override fun call(newValue: String?) {
if (newValue != null) { newValue ?: return
timeRangeSelectionValue = newValue timeRangeSelection = when (newValue) {
"DAY" -> RangeType.DAY
"WEEK" -> RangeType.WEEK
"MONTH" -> RangeType.MONTH
else -> {
Log.e(TAG, "Invalid time range selection: $newValue")
return
}
}
//Log.d("event", "new value: $newValue") //Log.d("event", "new value: $newValue")
updateGraph() updateGraph()
} }
} }
}
) )
updateGraph() updateGraph()
} }
fun updateGraph() { fun showSleepBarGraph(events: List<LunaEvent>, unixToSpan: (Long) -> Int, spanToUnix: (Int) -> Long) {
val eventType = when (eventTypeSelectionValue) { fun getEndTime(event: LunaEvent): Long {
"BOTTLE" -> LunaEvent.TYPE_BABY_BOTTLE if (event.quantity == 0) {
"SLEEP" -> LunaEvent.TYPE_SLEEP // sleep is still ongoing
else -> {
Log.e(TAG, "unhandled eventTypeSelectionValue: $eventTypeSelectionValue")
return
}
}
val allEvents = MainActivity.allEvents.filter { it.type == eventType }.sortedBy { it.time }
val values = ArrayList<BarEntry>()
val labels = ArrayList<String>()
val unixToSpan = when (timeRangeSelectionValue) {
"DAY" -> { unix: Long -> unixToDays(unix) }
"WEEK" -> { unix: Long -> unixToWeeks(unix) }
"MONTH" -> { unix: Long -> unixToMonths(unix) }
else -> {
Log.e(TAG, "Invalid timeRangeSelectionValue: $timeRangeSelectionValue")
return
}
}
val spanToUnix = when (timeRangeSelectionValue) {
"DAY" -> { span: Int -> daysToUnix(span) }
"WEEK" -> { span: Int -> weeksToUnix(span) }
"MONTH" -> { span: Int -> monthsToUnix(span) }
else -> {
Log.e(TAG, "Invalid timeRangeSelectionValue: $timeRangeSelectionValue")
return
}
}
fun spanToLabel(span: Int): String {
val dateTime = Calendar.getInstance() val dateTime = Calendar.getInstance()
dateTime.time = Date(1000 * spanToUnix(span)) return (dateTime.time.time / 1000) - event.time
val year = dateTime.get(Calendar.YEAR) } else {
val month = dateTime.get(Calendar.MONTH) + 1 // month starts at 0 return event.quantity.toLong()
val week = dateTime.get(Calendar.WEEK_OF_YEAR)
val day = dateTime.get(Calendar.DAY_OF_MONTH)
return when (timeRangeSelectionValue) {
"DAY" -> "$day/$month/$year"
"WEEK" -> "$week/$year"
"MONTH" -> "$month/$year"
else -> {
Log.e(TAG, "Invalid timeRangeSelectionValue: $timeRangeSelectionValue")
"?"
}
} }
} }
if (allEvents.isNotEmpty()) { data class SleepRange(val start: Long, val end: Long)
barChart.visibility = View.VISIBLE val ranges = arrayListOf<SleepRange>()
noDataTextView.visibility = View.GONE
// Transform events into time ranges.
// Merge overlapping times and extend
// ongoing sleep events until now.
val dateTime = Calendar.getInstance()
for (event in events) {
val endTime = if (event.quantity == 0) {
dateTime.time.time / 1000 // now
} else {
event.time + event.quantity
}
/*
// TODO: handle overlap
if (ranges.isNotEmpty()) {
val lastItem = ranges.lastItem()
if (lastItem.start)
if (lastItem.end <= event.time) {
// distinct
}
}
}
*/
ranges.add(SleepRange(event.time, endTime))
}
// unix time span of all events // unix time span of all events
val startUnix = allEvents.minOf { it.getStartTime() } val startUnix = events.minOf { it.time }
val endUnix = allEvents.maxOf { it.getEndTime() } val endUnix = events.maxOf { getEndTime(it) }
// convert to days, weeks or months // convert to days, weeks or months
val startSpan = unixToSpan(startUnix) val startSpan = unixToSpan(startUnix)
val endSpan = unixToSpan(endUnix) val endSpan = unixToSpan(endUnix)
//Log.d(TAG, "startUnix: $startUnix (${Date(1000 * startUnix)}), startSpan: $startSpan (${Date(1000 * spanToUnix(startSpan))}), endUnix: $endUnix (${Date(1000 * endUnix)}), endSpan: $endSpan (${Date(1000 * spanToUnix(endSpan))})") val values = ArrayList<BarEntry>()
for (span in startSpan..endSpan) {
fun countEvent(index: Int) {
// create initial values
while (index >= values.size) {
values.add(BarEntry(values.size.toFloat(), 0F)) values.add(BarEntry(values.size.toFloat(), 0F))
labels.add(spanToLabel(span))
} }
for (event in allEvents) { // update value
if (dataTypeSelectionValue == "AMOUNT") { values[index].y += 1F
if (eventTypeSelectionValue == "SLEEP") { }
fun accumulateValue(index: Int, value: Long) {
// create initial values
while (index >= values.size) {
values.add(BarEntry(values.size.toFloat(), 0F))
}
// update value
values[index].y += value.toFloat()
}
fun stackValue(index: Int, value: Long) {
// create initial values
while (index >= values.size) {
values.add(BarEntry(values.size.toFloat(), FloatArray(0)))
}
val x = values[index].x
val yVals = values[index].yVals
// update value
val newYVals = appendToFloatArray(yVals, value.toFloat())
values[index] = BarEntry(x, newYVals)
}
// awake/sleep
fun stackValuePattern(index: Int, spanBegin: Long, spanEnd: Long, begin: Long, end: Long) {
// create initial values
while (index >= values.size) {
values.add(BarEntry(values.size.toFloat(), FloatArray(0)))
}
assert(begin in spanBegin..spanEnd)
assert(end in spanBegin..spanEnd)
assert(begin <= end)
val x = values[index].x
val yVals = values[index].yVals // alternating sleep/awake durations
val y = yVals.fold(0F) { acc, next -> acc + next }
// y value is seconds when last awake
val awakeDuration = max(begin - spanBegin - y.toLong(), 0L)
val sleepDuration = end - begin
if ((awakeDuration + sleepDuration) > (spanEnd - spanBegin)) {
Log.e(TAG, "Invalid sleep duration, exceeds day/week or month bounds => ignore value")
return
}
// update value
val newYVals = appendToFloatArray(yVals, awakeDuration.toFloat(), sleepDuration.toFloat())
values[index] = BarEntry(x, newYVals)
}
/*
fun addStack24hCap(spanDuration: Long) {
// spanDuration is usually a day, week, month in seconds
Log.d(TAG, "spanDuration: $spanDuration, ${24*60*60}")
for (i in values.indices) {
val x = values[i].x
val yVals = values[i].yVals
val y = yVals.fold(0F) { acc, next -> acc + next }
val cap = spanDuration.toFloat() - y
if (cap >= 0F) {
// Add a cap value and an 0 value to keep the number of spans even.
// This is important, since we configure two colors and they will alternate.
val newYVals = appendToFloatArray(yVals, cap, 0F)
values[i] = BarEntry(x, newYVals)
} else {
Log.e(TAG, "Invalid remaining sleep duration, exceeds day/week or month bounds => ignore")
}
}
}
*/
for (range in ranges) {
// a sleep event can span to another day // a sleep event can span to another day
// distribute sleep time over the days // distribute sleep time over the days
val startUnix = event.getStartTime() val startUnix = range.start //event.time
val endUnix = event.getEndTime() val endUnix = range.end //getEndTime(event)
val begIndex = unixToSpan(startUnix) val begIndex = unixToSpan(startUnix)
val endIndex = unixToSpan(endUnix) val endIndex = unixToSpan(endUnix)
var mid = startUnix var mid = startUnix
@@ -203,37 +297,61 @@ class StatisticsActivity : AppCompatActivity() {
val spanBegin = spanToUnix(i) val spanBegin = spanToUnix(i)
val spanEnd = spanToUnix(i + 1) val spanEnd = spanToUnix(i + 1)
//Log.d(TAG, "mid: ${Date(mid * 1000)}, spanBegin: ${Date(spanBegin * 1000)}, spanEnd: ${Date(spanEnd * 1000)}, endUnix: ${Date(endUnix * 1000)}") //Log.d(TAG, "mid: ${Date(mid * 1000)}, spanBegin: ${Date(spanBegin * 1000)}, spanEnd: ${Date(spanEnd * 1000)}, endUnix: ${Date(endUnix * 1000)}")
val beg = max(mid, spanBegin) val sleepBegin = max(mid, spanBegin)
val end = min(endUnix, spanEnd) val sleepEnd = min(endUnix, spanEnd)
val index = i - startSpan val index = i - startSpan
val duration = end - beg val duration = sleepEnd - sleepBegin
//Log.d(TAG, "[$index] beg: ${Date(beg * 1000)}, end: ${Date(end * 1000)}, ${formatTimeDuration(this, duration)}") //Log.d(TAG, "[$index] sleepBegin: ${Date(sleepBegin * 1000)}, sleepEnd: ${Date(sleepEnd * 1000)}, ${formatTimeDuration(this, duration)}")
values[index].y += duration if (graphTypeSelection == GraphType.SLEEP_PATTERN) {
mid = end stackValuePattern(index, spanBegin, spanEnd, sleepBegin, sleepEnd)
} } else if (graphTypeSelection == GraphType.SLEEP_SUM) {
stackValue(index, duration)
} else if (graphTypeSelection == GraphType.SLEEP_SUM_AVERAGE) {
accumulateValue(index, duration)
} else if (graphTypeSelection == GraphType.SLEEP_EVENTS) {
countEvent(index)
} else { } else {
val index = unixToSpan(event.time) - startSpan Log.e(TAG, "Unexpected graph type.")
//Log.d(TAG, "[${index}] ${event.quantity}") return
values[index].y += event.quantity
}
} else {
val index = unixToSpan(event.time) - startSpan
values[index].y += 1
}
}
} else {
barChart.visibility = View.GONE
noDataTextView.visibility = View.VISIBLE
} }
barChart.xAxis.setLabelCount(min(values.size, 24)) mid = sleepEnd
}
// TODO: move addStack24h here, since the spans can have different length (edge case and does not really matter)
}
//addStack24hCap(spanToUnix(1) - spanToUnix(0))
// for debugging
for (value in values) {
val y = value.yVals.fold(0F) { acc, next -> acc + next }
val yVals = value.yVals.joinToString { it.toString() }
Log.d(TAG, "value: ${value.x} $y ($yVals)")
}
// list of dates
val labels = ArrayList<String>()
for (index in values.indices) {
labels.add(spanToLabel(spanToUnix(startSpan + index)))
}
val set1 = BarDataSet(values, "") val set1 = BarDataSet(values, "")
set1.setDrawValues(true) if (graphTypeSelection == GraphType.SLEEP_PATTERN) {
// awake phase color is transparent
set1.colors = arrayListOf("#00000000".toColorInt(), ColorTemplate.rgb("#72d7f5"))
set1.setDrawValues(false) // too many values => let's disable it
} else {
set1.setDrawValues(false)
}
set1.setDrawIcons(false) set1.setDrawIcons(false)
barChart.legend.isEnabled = false
barChart.xAxis.setLabelCount(min(values.size, 24))
val dataSets = ArrayList<IBarDataSet?>() val dataSets = ArrayList<IBarDataSet?>()
dataSets.add(set1) dataSets.add(set1)
@@ -242,17 +360,99 @@ class StatisticsActivity : AppCompatActivity() {
data.setValueFormatter(object : ValueFormatter() { data.setValueFormatter(object : ValueFormatter() {
override fun getFormattedValue(value: Float): String { override fun getFormattedValue(value: Float): String {
//Log.d(TAG, "getFormattedValue ${dataTypeSelectionValue} ${eventTypeSelectionValue}") //Log.d(TAG, "getFormattedValue ${dataTypeSelectionValue} ${eventTypeSelectionValue}")
return when (dataTypeSelectionValue) { return NumericUtils(applicationContext).formatEventQuantity(LunaEvent.TYPE_SLEEP, value.toInt())
"EVENT" -> value.toInt().toString()
"AMOUNT" -> when (eventTypeSelectionValue) {
"BOTTLE" -> NumericUtils(applicationContext).formatEventQuantity(LunaEvent.TYPE_BABY_BOTTLE, value.toInt())
"SLEEP" -> NumericUtils(applicationContext).formatEventQuantity(LunaEvent.TYPE_SLEEP, value.toInt())
else -> {
Log.e(TAG, "unhandled eventTypeSelectionValue: $eventTypeSelectionValue")
value.toInt().toString()
} }
} else -> { })
Log.e(TAG, "unhandled dataTypeSelectionValue: $dataTypeSelectionValue")
barChart.xAxis.valueFormatter = object: ValueFormatter() {
override fun getFormattedValue(value: Float): String {
return labels.getOrElse(value.toInt(), {"?"})
}
}
//data.setValueTextSize(12f)
barChart.setData(data)
barChart.invalidate()
}
fun showBottleBarGraph(events: List<LunaEvent>, unixToSpan: (Long) -> Int, spanToUnix: (Int) -> Long) {
// unix time span of all events
val startUnix = events.minOf { it.time }
val endUnix = events.maxOf { it.time }
// convert to days, weeks or months
val startSpan = unixToSpan(startUnix)
val endSpan = unixToSpan(endUnix)
val values = ArrayList<BarEntry>()
fun countValue(index: Int) {
// create initial values
while (index >= values.size) {
values.add(BarEntry(values.size.toFloat(), 0F))
}
// update value
values[index].y += 1F
}
fun accumulateValue(index: Int, duration: Long) {
// create initial values
while (index >= values.size) {
values.add(BarEntry(values.size.toFloat(), 0F))
}
// update value
values[index].y += duration.toFloat()
}
for (event in events) {
if (graphTypeSelection == GraphType.BOTTLE_EVENTS) {
val index = unixToSpan(event.time) - startSpan
countValue(index)
} else if (graphTypeSelection == GraphType.BOTTLE_SUM) {
val index = unixToSpan(event.time) - startSpan
//Log.d(TAG, "[${index}] ${event.quantity}")
accumulateValue(index, event.quantity.toLong())
} else {
Log.e(TAG, "unhandled graphTypeSelection")
return
}
}
// list of dates
val labels = ArrayList<String>()
for (index in values.indices) {
labels.add(spanToLabel(spanToUnix(startSpan + index)))
}
val set1 = BarDataSet(values, "")
set1.setDrawValues(true)
set1.setDrawIcons(false)
//showGraph(set1, valueLabels)
// for debugging
//val sum1 = allEvents.fold(0) { acc, event -> acc + event.quantity }
//val sum2 = values.fold(0F) { acc, item -> acc + item.y }
//Log.d(TAG, "sum1: $sum1, sum2: $sum2")
barChart.xAxis.setLabelCount(min(values.size, 24))
val dataSets = ArrayList<IBarDataSet?>()
dataSets.add(set1)
val data = BarData(dataSets)
data.setValueFormatter(object : ValueFormatter() {
override fun getFormattedValue(value: Float): String {
//Log.d(TAG, "getFormattedValue ${dataTypeSelectionValue} ${eventTypeSelectionValue}")
return when (graphTypeSelection) {
GraphType.BOTTLE_EVENTS -> value.toInt().toString()
GraphType.BOTTLE_SUM -> NumericUtils(applicationContext).formatEventQuantity(LunaEvent.TYPE_BABY_BOTTLE, value.toInt())
else -> {
Log.e(TAG, "unhandled graphTypeSelection")
value.toInt().toString() value.toInt().toString()
} }
} }
@@ -270,6 +470,64 @@ class StatisticsActivity : AppCompatActivity() {
barChart.invalidate() barChart.invalidate()
} }
fun spanToLabel(unixSeconds: Long): String {
val dateTime = Calendar.getInstance()
dateTime.time = Date(1000L * unixSeconds)
val year = dateTime.get(Calendar.YEAR)
val month = dateTime.get(Calendar.MONTH) + 1 // month starts at 0
val week = dateTime.get(Calendar.WEEK_OF_YEAR)
val day = dateTime.get(Calendar.DAY_OF_MONTH)
return when (timeRangeSelection) {
RangeType.DAY -> "$day/$month/$year"
RangeType.WEEK -> "$week/$year"
RangeType.MONTH -> "$month/$year"
}
}
fun updateGraph() {
val unixToSpan = when (timeRangeSelection) {
RangeType.DAY -> { unix: Long -> unixToDays(unix) }
RangeType.WEEK -> { unix: Long -> unixToWeeks(unix) }
RangeType.MONTH -> { unix: Long -> unixToMonths(unix) }
}
val spanToUnix = when (timeRangeSelection) {
RangeType.DAY -> { span: Int -> daysToUnix(span) }
RangeType.WEEK -> { span: Int -> weeksToUnix(span) }
RangeType.MONTH -> { span: Int -> monthsToUnix(span) }
}
val eventType = when (graphTypeSelection) {
GraphType.BOTTLE_EVENTS,
GraphType.BOTTLE_SUM,
GraphType.BOTTLE_SUM_AVERAGE -> LunaEvent.TYPE_BABY_BOTTLE
GraphType.SLEEP_SUM,
GraphType.SLEEP_SUM_AVERAGE,
GraphType.SLEEP_EVENTS,
GraphType.SLEEP_PATTERN -> LunaEvent.TYPE_SLEEP
}
val events = MainActivity.allEvents.filter { it.type == eventType }.sortedBy { it.time }
if (events.isEmpty()) {
barChart.visibility = View.GONE
noDataTextView.visibility = View.VISIBLE
} else {
barChart.visibility = View.VISIBLE
noDataTextView.visibility = View.GONE
when (graphTypeSelection) {
GraphType.BOTTLE_EVENTS,
GraphType.BOTTLE_SUM,
GraphType.BOTTLE_SUM_AVERAGE -> showBottleBarGraph(events, unixToSpan, spanToUnix)
GraphType.SLEEP_SUM,
GraphType.SLEEP_SUM_AVERAGE,
GraphType.SLEEP_EVENTS,
GraphType.SLEEP_PATTERN -> showSleepBarGraph(events, unixToSpan, spanToUnix)
}
}
}
private interface SpinnerItemSelected { private interface SpinnerItemSelected {
fun call(newValue: String?) fun call(newValue: String?)
} }
@@ -370,5 +628,19 @@ class StatisticsActivity : AppCompatActivity() {
dateTime.set(Calendar.SECOND, 0) dateTime.set(Calendar.SECOND, 0)
return dateTime.time.time / 1000 return dateTime.time.time / 1000
} }
fun appendToFloatArray(array: FloatArray, vararg values: Float): FloatArray {
// create new array
val newArray = FloatArray(array.size + values.size)
// copy old values
for (i in array.indices) {
newArray[i] = array[i]
}
// add new values
for (i in values.indices) {
newArray[array.size + i] = values[i]
}
return newArray
}
} }
} }

View File

@@ -59,7 +59,12 @@ class LunaEventRecyclerAdapter: RecyclerView.Adapter<LunaEventRecyclerAdapter.Lu
LunaEvent.TYPE_CUSTOM -> item.notes LunaEvent.TYPE_CUSTOM -> item.notes
else -> item.getTypeDescription(context) else -> item.getTypeDescription(context)
} }
holder.time.text = DateUtils.formatTimeAgo(context, item.getEndTime()) val endTime = if (item.type == LunaEvent.TYPE_SLEEP) {
item.quantity + item.time
} else {
item.time
}
holder.time.text = DateUtils.formatTimeAgo(context, endTime)
var quantityText = numericUtils.formatEventQuantity(item) var quantityText = numericUtils.formatEventQuantity(item)
// if the event is weight, show difference with the last one // if the event is weight, show difference with the last one

View File

@@ -94,18 +94,6 @@ class LunaEvent: Comparable<LunaEvent> {
this.quantity = quantity this.quantity = quantity
} }
fun getStartTime(): Long {
return time
}
fun getEndTime(): Long {
return if (type == TYPE_SLEEP) {
time + quantity
} else {
time
}
}
fun getTypeEmoji(context: Context): String { fun getTypeEmoji(context: Context): String {
return context.getString( return context.getString(
when (type) { when (type) {

View File

@@ -37,14 +37,14 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:layout_weight="1" /> android:layout_weight="1" />
<!--
<Spinner <Spinner
android:id="@+id/data_selection" android:id="@+id/data_selection"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:layout_weight="1"/> android:layout_weight="1"/>
-->
<Spinner <Spinner
android:id="@+id/time_selection" android:id="@+id/time_selection"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@@ -8,15 +8,23 @@
</string-array> </string-array>
<string-array name="StatisticsTypeLabels"> <string-array name="StatisticsTypeLabels">
<item>Bottle</item> <item>BOTTLE_EVENTS</item>
<item>Sleep</item> <item>BOTTLE_SUM</item>
<item>BOTTLE_SUM_AVERAGE</item>
<item>SLEEP_SUM_AVERAGE</item>
<item>SLEEP_EVENTS</item>
<item>SLEEP_PATTERN</item>
</string-array> </string-array>
<string-array name="StatisticsTypeValues"> <string-array name="StatisticsTypeValues">
<item>BOTTLE</item> <item>BOTTLE_EVENTS</item>
<item>SLEEP</item> <item>BOTTLE_SUM</item>
<item>BOTTLE_SUM_AVERAGE</item>
<item>SLEEP_SUM_AVERAGE</item>
<item>SLEEP_EVENTS</item>
<item>SLEEP_PATTERN</item>
</string-array> </string-array>
<!--
<string-array name="StatisticsDataLabels"> <string-array name="StatisticsDataLabels">
<item>Event</item> <item>Event</item>
<item>Amount</item> <item>Amount</item>
@@ -26,7 +34,7 @@
<item>EVENT</item> <item>EVENT</item>
<item>AMOUNT</item> <item>AMOUNT</item>
</string-array> </string-array>
-->
<string-array name="StatisticsTimeLabels"> <string-array name="StatisticsTimeLabels">
<item>Day</item> <item>Day</item>
<item>Week</item> <item>Week</item>