Stats activity

This commit is contained in:
Milos Kozak 2019-12-09 19:03:26 +01:00
parent a9e08bd08d
commit 1c0eb9f803
13 changed files with 208 additions and 22 deletions

View file

@ -77,6 +77,7 @@
<activity android:name=".plugins.pump.danaRS.activities.PairingHelperActivity" /> <activity android:name=".plugins.pump.danaRS.activities.PairingHelperActivity" />
<activity android:name=".activities.HistoryBrowseActivity" /> <activity android:name=".activities.HistoryBrowseActivity" />
<activity android:name=".activities.SurveyActivity" /> <activity android:name=".activities.SurveyActivity" />
<activity android:name=".activities.StatsActivity" />
<!-- Receive new BG readings from other local apps --> <!-- Receive new BG readings from other local apps -->
<receiver <receiver

View file

@ -41,6 +41,7 @@ import info.nightscout.androidaps.activities.HistoryBrowseActivity;
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
import info.nightscout.androidaps.activities.PreferencesActivity; import info.nightscout.androidaps.activities.PreferencesActivity;
import info.nightscout.androidaps.activities.SingleFragmentActivity; import info.nightscout.androidaps.activities.SingleFragmentActivity;
import info.nightscout.androidaps.activities.StatsActivity;
import info.nightscout.androidaps.activities.SurveyActivity; import info.nightscout.androidaps.activities.SurveyActivity;
import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
@ -347,6 +348,9 @@ public class MainActivity extends NoSplashAppCompatActivity {
case R.id.nav_survey: case R.id.nav_survey:
startActivity(new Intent(this, SurveyActivity.class)); startActivity(new Intent(this, SurveyActivity.class));
return true; return true;
case R.id.nav_stats:
startActivity(new Intent(this, StatsActivity.class));
return true;
} }
return actionBarDrawerToggle.onOptionsItemSelected(item); return actionBarDrawerToggle.onOptionsItemSelected(item);
} }

View file

@ -0,0 +1,31 @@
package info.nightscout.androidaps.activities
import android.os.Bundle
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.OKDialog
import info.nightscout.androidaps.utils.TddCalculator
import info.nightscout.androidaps.utils.TirCalculator
import kotlinx.android.synthetic.main.stats_activity.*
class StatsActivity : NoSplashAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.stats_activity)
stats_tdds.text = TddCalculator.stats()
stats_tir.text = TirCalculator.stats()
stats_activity.text = ActivityMonitor.stats()
ok.setOnClickListener { finish() }
stats_reset.setOnClickListener {
OKDialog.showConfirmation(this, MainApp.gs(R.string.doyouwantresetstats)) {
ActivityMonitor.reset()
recreate()
}
}
}
}

View file

@ -20,9 +20,6 @@ import java.util.*
class SurveyActivity : NoSplashAppCompatActivity() { class SurveyActivity : NoSplashAppCompatActivity() {
private val log = LoggerFactory.getLogger(SurveyActivity::class.java) private val log = LoggerFactory.getLogger(SurveyActivity::class.java)
val lowMgdl = 3.9 * Constants.MMOLL_TO_MGDL
val highMgdl = 10.0 * Constants.MMOLL_TO_MGDL
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.survey_fragment) setContentView(R.layout.survey_fragment)
@ -33,15 +30,9 @@ class SurveyActivity : NoSplashAppCompatActivity() {
val profileList = profileStore?.getProfileList() ?: return val profileList = profileStore?.getProfileList() ?: return
survey_spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList) survey_spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
val tdds = TddCalculator.calculate(7) survey_tdds.text = TddCalculator.stats()
val averageTdd = TddCalculator.averageTDD(tdds) survey_tir.text = TirCalculator.stats()
survey_tdds.text = MainApp.gs(R.string.tdd) + ":\n" + TddCalculator.toText(tdds) + MainApp.gs(R.string.average) + ":\n" + averageTdd.toText() survey_activity.text = ActivityMonitor.stats()
val tirs = TirCalculator.calculate(7, lowMgdl, highMgdl)
val averageTir = TirCalculator.averageTIR(tirs)
survey_tir.text = "\n" + MainApp.gs(R.string.tir) + ":\n" + TirCalculator.toText(tirs) + MainApp.gs(R.string.average) + ":\n" + averageTir.toText()
survey_activity.text = "\n" + MainApp.gs(R.string.activitymonitor) + ":\n" + ActivityMonitor.toText()
survey_profile.setOnClickListener { survey_profile.setOnClickListener {
val age = SafeParse.stringToDouble(survey_age.text.toString()) val age = SafeParse.stringToDouble(survey_age.text.toString())

View file

@ -10,6 +10,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
import info.nightscout.androidaps.utils.DateUtil;
/** /**
* Created by mike on 20.09.2017. * Created by mike on 20.09.2017.
@ -60,6 +61,10 @@ public class TDD {
} }
public String toText() { public String toText() {
return MainApp.gs(R.string.tddformat, total, bolus, basal); return MainApp.gs(R.string.tddformat, DateUtil.dateStringShort(date), total, bolus, basal);
}
public String toText(int days) {
return MainApp.gs(R.string.tddformat, String.format("%d ", days) + MainApp.gs(R.string.days), total, bolus, basal);
} }
} }

View file

@ -3,6 +3,9 @@ package info.nightscout.androidaps.utils
import android.app.Activity import android.app.Activity
import android.app.Application import android.app.Application
import android.os.Bundle import android.os.Bundle
import android.text.Spanned
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.L import info.nightscout.androidaps.logging.L
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -50,15 +53,19 @@ object ActivityMonitor : Application.ActivityLifecycleCallbacks {
var result = "" var result = ""
for ((key, value) in keys) for ((key, value) in keys)
if (key.startsWith("Monitor") && key.endsWith("total")) { if (key.startsWith("Monitor") && key.endsWith("total")) {
val activity = key.split("_")[1] val activity = key.split("_")[1].replace("Activity", "")
val seconds = value as Long / 1000 val duration = DateUtil.niceTimeScalar(value as Long)
val start = SP.getLong(key.replace("total", "start"), 0) val start = SP.getLong(key.replace("total", "start"), 0)
val days = T.msecs(DateUtil.now() - start).days() val days = T.msecs(DateUtil.now() - start).days()
result += "$activity: $seconds s in $days days\n" result += "<b><span style=\"color:yellow\">$activity:</span></b> <b>$duration</b> in <b>$days</b> days<br>"
} }
return result return result
} }
fun stats() :Spanned {
return HtmlHelper.fromHtml("<br><b>" + MainApp.gs(R.string.activitymonitor) + ":</b><br>" + toText())
}
fun reset() { fun reset() {
val keys: Map<String, *> = SP.getAll() val keys: Map<String, *> = SP.getAll()
for ((key, _) in keys) for ((key, _) in keys)

View file

@ -117,6 +117,14 @@ public class DateUtil {
return df.format(mills); return df.format(mills);
} }
public static String dateStringShort(long mills) {
String format = "MM/dd";
if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) {
format = "dd/MM";
}
return new DateTime(mills).toString(DateTimeFormat.forPattern(format));
}
public static String timeString(Date date) { public static String timeString(Date date) {
String format = "hh:mma"; String format = "hh:mma";
if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) { if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) {

View file

@ -20,5 +20,7 @@ class TIR(val date: Long, val lowThreshold: Double, val highThreshold: Double) {
fun inRangePct() = if (count > 0) (inRange.toDouble() / count * 100.0).roundToInt() else 0 fun inRangePct() = if (count > 0) (inRange.toDouble() / count * 100.0).roundToInt() else 0
fun abovePct() = if (count > 0) (above.toDouble() / count * 100.0).roundToInt() else 0 fun abovePct() = if (count > 0) (above.toDouble() / count * 100.0).roundToInt() else 0
fun toText(): String = MainApp.gs(R.string.tirformat, DateUtil.dateString(date), belowPct(), inRangePct(), abovePct()) fun toText(): String = MainApp.gs(R.string.tirformat, DateUtil.dateStringShort(date), belowPct(), inRangePct(), abovePct())
fun toText(days: Int): String = MainApp.gs(R.string.tirformat, "%02d".format(days) + " " + MainApp.gs(R.string.days), belowPct(), inRangePct(), abovePct())
} }

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.utils package info.nightscout.androidaps.utils
import android.text.Spanned
import android.util.LongSparseArray import android.util.LongSparseArray
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
@ -60,10 +61,21 @@ object TddCalculator : TreatmentsPlugin() {
return totalTdd return totalTdd
} }
fun toText(tdds: LongSparseArray<TDD>) : String { fun stats(): Spanned {
val tdds = calculate(7)
val averageTdd = averageTDD(tdds)
return HtmlHelper.fromHtml(
"<b>" + MainApp.gs(R.string.tdd) + ":</b><br>" +
toText(tdds) +
"<b>" + MainApp.gs(R.string.average) + ":</b><br>" +
averageTdd.toText(tdds.size())
)
}
fun toText(tdds: LongSparseArray<TDD>): String {
var t = "" var t = ""
for (i in 0 until tdds.size()) { for (i in 0 until tdds.size()) {
t += "${tdds.valueAt(i).toText()}\n" t += "${tdds.valueAt(i).toText()}<br>"
} }
return t return t
} }

View file

@ -1,7 +1,11 @@
package info.nightscout.androidaps.utils package info.nightscout.androidaps.utils
import android.text.Spanned
import android.util.LongSparseArray import android.util.LongSparseArray
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
object TirCalculator { object TirCalculator {
fun calculate(days: Long, lowMgdl: Double, highMgdl: Double): LongSparseArray<TIR> { fun calculate(days: Long, lowMgdl: Double, highMgdl: Double): LongSparseArray<TIR> {
@ -42,10 +46,36 @@ object TirCalculator {
return totalTir return totalTir
} }
fun stats(): Spanned {
val lowTirMgdl = 3.9 * Constants.MMOLL_TO_MGDL
val highTirMgdl = 10.0 * Constants.MMOLL_TO_MGDL
val lowTitMgdl = 3.9 * Constants.MMOLL_TO_MGDL
val highTitMgdl = 7.8 * Constants.MMOLL_TO_MGDL
val tir7 = calculate(7, lowTirMgdl, highTirMgdl)
val averageTir7 = averageTIR(tir7)
val tir30 = calculate(30, lowTirMgdl, highTirMgdl)
val averageTir30 = averageTIR(tir30)
val tit7 = calculate(7, lowTitMgdl, highTitMgdl)
val averageTit7 = averageTIR(tit7)
val tit30 = calculate(30, lowTitMgdl, highTitMgdl)
val averageTit30 = averageTIR(tit30)
return HtmlHelper.fromHtml(
"<br><b>" + MainApp.gs(R.string.tir) + ":</b><br>" +
toText(tir7) +
"<br><b>" + MainApp.gs(R.string.average) + " (" + Profile.toCurrentUnitsString(lowTirMgdl) + "-" + Profile.toCurrentUnitsString(highTirMgdl) + "):</b><br>" +
averageTir7.toText(tir7.size()) + "<br>" +
averageTir30.toText(tir30.size()) +
"<br><b>" + MainApp.gs(R.string.average) + " (" + Profile.toCurrentUnitsString(lowTitMgdl) + "-" + Profile.toCurrentUnitsString(highTitMgdl) + "):</b><br>" +
averageTit7.toText(tit7.size()) + "<br>" +
averageTit30.toText(tit30.size())
)
}
fun toText(tirs: LongSparseArray<TIR>): String { fun toText(tirs: LongSparseArray<TIR>): String {
var t = "" var t = ""
for (i in 0 until tirs.size()) { for (i in 0 until tirs.size()) {
t += "${tirs.valueAt(i).toText()}\n" t += "${tirs.valueAt(i).toText()}<br>"
} }
return t return t
} }

View file

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activities.SurveyActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:paddingStart="10dp"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/statistics"
android:textAppearance="@style/TextAppearance.AppCompat.Display1" />
</LinearLayout>
<TextView
android:id="@+id/stats_tdds"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/stats_tir"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/stats_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/done_background"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="horizontal"
android:background="@android:color/transparent"
android:gravity="end|right"
android:layout_gravity="center_vertical"
android:paddingBottom="8dp">
<Button
android:id="@+id/stats_reset"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
style="@style/mdtp_ActionButton.Text"
android:text="@string/reset" />
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
style="@style/mdtp_ActionButton.Text"
android:text="@string/mdtp_ok" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View file

@ -18,6 +18,10 @@
android:id="@+id/nav_setupwizard" android:id="@+id/nav_setupwizard"
app:showAsAction="never" app:showAsAction="never"
android:title="@string/nav_setupwizard" /> android:title="@string/nav_setupwizard" />
<item
android:id="@+id/nav_stats"
app:showAsAction="never"
android:title="@string/statistics" />
<item <item
android:id="@+id/nav_survey" android:id="@+id/nav_survey"
app:showAsAction="never" app:showAsAction="never"

View file

@ -1671,11 +1671,13 @@
<string name="nav_survey">Survey</string> <string name="nav_survey">Survey</string>
<string name="invalidage">Invalid age entry</string> <string name="invalidage">Invalid age entry</string>
<string name="invalidweight">Invalid weight entry</string> <string name="invalidweight">Invalid weight entry</string>
<string name="tddformat">Total: %1$.2f Bolus: %2$.2f Basal: %3$.2f</string> <string name="tddformat"><![CDATA[<b>%1$s:</b> ∑: <b>%2$.2f</b> Bol: <b>%3$.2f</b> Bas: <b>%4$.2f</b>]]></string>
<string name="tirformat">%1$s: Low: %2$d%% In: %3$d%% High: %4$d%%</string> <string name="tirformat"><![CDATA[<b>%1$s:</b> Low: <b>%2$02d%%</b> In: <b>%3$02d%%</b> High: <b>%4$02d%%</b>]]></string>
<string name="average">Average</string> <string name="average">Average</string>
<string name="tdd">TDD</string> <string name="tdd">TDD</string>
<string name="tir">TIR</string> <string name="tir">TIR</string>
<string name="activitymonitor">Activity monitor</string> <string name="activitymonitor">Activity monitor</string>
<string name="doyouwantresetstats">Do you want to reset activity stats?</string>
<string name="statistics">Statistics</string>
</resources> </resources>