StatsActivity formatting

This commit is contained in:
Milos Kozak 2022-03-21 19:23:37 +01:00
parent 3885b5560b
commit 9b7c6d83bb
13 changed files with 310 additions and 152 deletions

View file

@ -7,6 +7,7 @@ import android.text.Editable
import android.text.TextWatcher
import android.view.Menu
import android.widget.PopupMenu
import android.widget.TextView
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.data.PureProfile
@ -66,6 +67,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
private lateinit var binding: ActivityProfilehelperBinding
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityProfilehelperBinding.inflate(layoutInflater)
@ -78,11 +80,11 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
switchTab(1, typeSelected[1])
}
binding.profiletype.setOnClickListener {
PopupMenu(this, binding.profiletype).apply {
binding.profileType.setOnClickListener {
PopupMenu(this, binding.profileType).apply {
menuInflater.inflate(R.menu.menu_profilehelper, menu)
setOnMenuItemClickListener { item ->
binding.profiletype.setText(item.title)
binding.profileType.setText(item.title)
when (item.itemId) {
R.id.menu_default -> switchTab(tabSelected, ProfileType.MOTOL_DEFAULT)
R.id.menu_default_dpv -> switchTab(tabSelected, ProfileType.DPV_DEFAULT)
@ -129,7 +131,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
}
// Default profile
binding.copytolocalprofile.setOnClickListener {
binding.copyToLocalProfile.setOnClickListener {
storeValues()
val age = ageUsed[tabSelected]
val weight = weightUsed[tabSelected]
@ -167,20 +169,22 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
}
})
binding.basalpctfromtdd.setParams(32.0, 32.0, 37.0, 1.0, DecimalFormat("0"), false, null)
binding.basalPctFromTdd.setParams(32.0, 32.0, 37.0, 1.0, DecimalFormat("0"), false, null)
@SuppressLint("SetTextI18n")
binding.tdds.text = getString(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress)
binding.tdds.addView(TextView(this).apply { text = rh.gs(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress) })
Thread {
val tdds = tddCalculator.stats()
runOnUiThread { binding.tdds.text = tdds }
val tdds = tddCalculator.stats(this)
runOnUiThread {
binding.tdds.removeAllViews()
binding.tdds.addView(tdds)
}
}.start()
// Current profile
binding.currentProfileText.text = profileFunction.getProfileName()
// General
binding.compareprofile.setOnClickListener {
binding.compareProfiles.setOnClickListener {
storeValues()
for (i in 0..1) {
if (typeSelected[i] == ProfileType.MOTOL_DEFAULT) {
@ -241,7 +245,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
binding.age.editText?.id?.let { binding.ageLabel.labelFor = it }
binding.tdd.editText?.id?.let { binding.tddLabel.labelFor = it }
binding.weight.editText?.id?.let { binding.weightLabel.labelFor = it }
binding.basalpctfromtdd.editText?.id?.let { binding.basalpctfromtddLabel.labelFor = it }
binding.basalPctFromTdd.editText?.id?.let { binding.basalPctFromTddLabel.labelFor = it }
switchTab(0, typeSelected[0], false)
}
@ -272,7 +276,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
ageUsed[tabSelected] = binding.age.value
weightUsed[tabSelected] = binding.weight.value
tddUsed[tabSelected] = binding.tdd.value
pctUsed[tabSelected] = binding.basalpctfromtdd.value
pctUsed[tabSelected] = binding.basalPctFromTdd.value
}
private fun switchTab(tab: Int, newContent: ProfileType, storeOld: Boolean = true) {
@ -282,10 +286,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
tabSelected = tab
typeSelected[tabSelected] = newContent
binding.profiletypeTitle.defaultHintTextColor = ColorStateList.valueOf(rh.gc(if (tab == 0) R.color.helperProfile else R.color.examinedProfile))
binding.profileTypeTitle.defaultHintTextColor = ColorStateList.valueOf(rh.gc(if (tab == 0) R.color.helperProfile else R.color.examinedProfile))
// show new content
binding.profiletype.setText(
binding.profileType.setText(
when (typeSelected[tabSelected]) {
ProfileType.MOTOL_DEFAULT -> rh.gs(R.string.motoldefaultprofile)
ProfileType.DPV_DEFAULT -> rh.gs(R.string.dpvdefaultprofile)
@ -303,9 +307,9 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
binding.age.value = ageUsed[tabSelected]
binding.weight.value = weightUsed[tabSelected]
binding.tdd.value = tddUsed[tabSelected]
binding.basalpctfromtdd.value = pctUsed[tabSelected]
binding.basalPctFromTdd.value = pctUsed[tabSelected]
binding.basalpctfromtddRow.visibility = (newContent == ProfileType.DPV_DEFAULT).toVisibility()
binding.basalPctFromTddRow.visibility = (newContent == ProfileType.DPV_DEFAULT).toVisibility()
if (profileList.isNotEmpty())
binding.availableProfileList.setText(profileList[profileUsed[tabSelected]].toString())
if (profileSwitch.isNotEmpty())

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.activities
import android.annotation.SuppressLint
import android.os.Bundle
import android.widget.TextView
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
@ -9,7 +10,6 @@ import info.nightscout.androidaps.databinding.ActivityStatsBinding
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.androidaps.utils.stats.TirCalculator
import javax.inject.Inject
@ -29,21 +29,30 @@ class StatsActivity : NoSplashAppCompatActivity() {
binding = ActivityStatsBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.tdds.text = getString(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress)
binding.tir.text = getString(R.string.tir) + ": " + rh.gs(R.string.calculation_in_progress)
binding.activity.text = rh.gs(R.string.activitymonitor) + ": " + rh.gs(R.string.calculation_in_progress)
binding.tdds.addView(TextView(this).apply { text = getString(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress) })
binding.tir.addView(TextView(this).apply { text = getString(R.string.tir) + ": " + rh.gs(R.string.calculation_in_progress) })
binding.activity.addView(TextView(this).apply { text = getString(R.string.activitymonitor) + ": " + rh.gs(R.string.calculation_in_progress) })
Thread {
val tdds = tddCalculator.stats()
runOnUiThread { binding.tdds.text = tdds }
val tdds = tddCalculator.stats(this)
runOnUiThread {
binding.tdds.removeAllViews()
binding.tdds.addView(tdds)
}
}.start()
Thread {
val tir = tirCalculator.stats()
runOnUiThread { binding.tir.text = tir }
val tir = tirCalculator.stats(this)
runOnUiThread {
binding.tir.removeAllViews()
binding.tir.addView(tir)
}
}.start()
Thread {
val activity = activityMonitor.stats()
runOnUiThread { binding.activity.text = activity }
val activity = activityMonitor.stats(this)
runOnUiThread {
binding.activity.removeAllViews()
binding.activity.addView(activity)
}
}.start()
binding.ok.setOnClickListener { finish() }

View file

@ -43,9 +43,9 @@ class SurveyActivity : NoSplashAppCompatActivity() {
val profileList = profileStore?.getProfileList() ?: return
binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
binding.tdds.text = tddCalculator.stats()
binding.tir.text = tirCalculator.stats()
binding.activity.text = activityMonitor.stats()
//binding.tdds.text = tddCalculator.stats()
//binding.tir.text = tirCalculator.stats()
//binding.activity.text = activityMonitor.stats()
binding.profile.setOnClickListener {
val age = SafeParse.stringToDouble(binding.age.text.toString())

View file

@ -2,14 +2,20 @@ package info.nightscout.androidaps.utils
import android.app.Activity
import android.app.Application
import android.content.Context
import android.graphics.Typeface
import android.os.Bundle
import android.text.Spanned
import android.view.Gravity
import android.view.ViewGroup
import android.widget.TableLayout
import android.widget.TableRow
import android.widget.TextView
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.SafeParse
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.SafeParse
import javax.inject.Inject
import javax.inject.Singleton
@ -58,24 +64,47 @@ class ActivityMonitor @Inject constructor(
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
}
private fun toText(): String {
val keys: Map<String, *> = sp.getAll()
var result = ""
for ((key, value) in keys)
if (key.startsWith("Monitor") && key.endsWith("total")) {
val v = if (value is Long) value else SafeParse.stringToLong(value as String)
val activity = key.split("_")[1].replace("Activity", "")
val duration = dateUtil.niceTimeScalar(v, rh)
val start = sp.getLong(key.replace("total", "start"), 0)
val days = T.msecs(dateUtil.now() - start).days()
result += rh.gs(R.string.activitymonitorformat, activity, duration, days)
}
return result
}
fun stats(context: Context): TableLayout =
TableLayout(context).also { layout ->
layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
layout.addView(
TextView(context).apply {
text = rh.gs(R.string.activitymonitor)
setTypeface(typeface, Typeface.BOLD)
gravity = Gravity.CENTER_HORIZONTAL
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
})
layout.addView(
TableRow(context).also { row ->
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT).apply { weight = 1f }
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
row.gravity = Gravity.CENTER_HORIZONTAL
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 0 }; text = rh.gs(R.string.activity) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 1 }; text = rh.gs(R.string.duration) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 2 } })
}
)
fun stats(): Spanned {
return HtmlHelper.fromHtml("<br><b>" + rh.gs(R.string.activitymonitor) + ":</b><br>" + toText())
}
val keys: Map<String, *> = sp.getAll()
for ((key, value) in keys)
if (key.startsWith("Monitor") && key.endsWith("total")) {
val v = if (value is Long) value else SafeParse.stringToLong(value as String)
val activity = key.split("_")[1].replace("Activity", "")
val duration = dateUtil.niceTimeScalar(v, rh)
val start = sp.getLong(key.replace("total", "start"), 0)
val days = T.msecs(dateUtil.now() - start).days()
layout.addView(
TableRow(context).also { row ->
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT).apply { weight = 1f }
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
row.gravity = Gravity.CENTER_HORIZONTAL
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 0 }; text = activity })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 1 }; text = duration })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 2 }; text = rh.gs(R.string.in_days, days.toDouble()) })
}
)
}
}
fun reset() {
val keys: Map<String, *> = sp.getAll()

View file

@ -1,11 +1,16 @@
package info.nightscout.androidaps.utils.stats
import android.annotation.SuppressLint
import android.content.Context
import android.view.Gravity
import android.widget.TableRow
import android.widget.TextView
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlin.math.roundToInt
class TIR(val date: Long, val lowThreshold: Double, val highThreshold: Double) {
internal var below = 0
internal var inRange = 0
internal var above = 0
@ -17,11 +22,44 @@ class TIR(val date: Long, val lowThreshold: Double, val highThreshold: Double) {
fun inRange() = run { inRange++; count++ }
fun above() = run { above++; count++ }
private fun belowPct() = if (count > 0) (below.toDouble() / count * 100.0).roundToInt() else 0
private fun belowPct() = if (count > 0) below.toDouble() / count * 100.0 else 0.0
private fun inRangePct() = if (count > 0) 100 - belowPct() - abovePct() else 0
private fun abovePct() = if (count > 0) (above.toDouble() / count * 100.0).roundToInt() else 0
private fun abovePct() = if (count > 0) above.toDouble() / count * 100.0 else 0.0
fun toText(rh: ResourceHelper, dateUtil: DateUtil): String = rh.gs(R.string.tirformat, dateUtil.dateStringShort(date), belowPct(), inRangePct(), abovePct())
companion object {
fun toText(rh: ResourceHelper, days: Int): String = rh.gs(R.string.tirformat, "%02d".format(days) + " " + rh.gs(R.string.days), belowPct(), inRangePct(), abovePct())
fun toTableRowHeader(context: Context, rh: ResourceHelper): TableRow =
TableRow(context).also { header ->
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)
header.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
header.gravity = Gravity.CENTER_HORIZONTAL
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 0; weight = 1f }; text = rh.gs(R.string.date) })
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 1; weight = 1f }; text = rh.gs(R.string.below) })
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 2; weight = 1f }; text = rh.gs(R.string.in_range) })
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 3; weight = 1f }; text = rh.gs(R.string.above) })
}
}
fun toTableRow(context: Context, rh: ResourceHelper, dateUtil: DateUtil): TableRow =
TableRow(context).also { row ->
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT).apply { weight = 1f }
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
row.gravity = Gravity.CENTER_HORIZONTAL
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 0 }; text = dateUtil.dateStringShort(date) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 1 }; text = rh.gs(R.string.formatPercent, belowPct()) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 2 }; text = rh.gs(R.string.formatPercent, inRangePct()) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 3 }; text = rh.gs(R.string.formatPercent, abovePct()) })
}
@SuppressLint("SetTextI18n")
fun toTableRow(context: Context, rh: ResourceHelper, days: Int): TableRow =
TableRow(context).also { row ->
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT).apply { weight = 1f }
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
row.gravity = Gravity.CENTER_HORIZONTAL
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 0 }; text = "%02d".format(days) + " " + rh.gs(R.string.days) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 1 }; text = rh.gs(R.string.formatPercent, belowPct()) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 2 }; text = rh.gs(R.string.formatPercent, inRangePct()) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 3 }; text = rh.gs(R.string.formatPercent, abovePct()) })
}
}

View file

@ -1,18 +1,25 @@
package info.nightscout.androidaps.utils.stats
import android.text.Spanned
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Typeface
import android.util.LongSparseArray
import android.view.Gravity
import android.view.ViewGroup
import android.widget.TableLayout
import android.widget.TableRow
import android.widget.TextView
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.toText
import info.nightscout.androidaps.extensions.toTableRow
import info.nightscout.androidaps.extensions.toTableRowHeader
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -186,24 +193,31 @@ class TddCalculator @Inject constructor(
return totalTdd
}
fun stats(): Spanned {
@SuppressLint("SetTextI18n")
fun stats(context: Context): TableLayout {
val tdds = calculate(7)
val averageTdd = averageTDD(tdds)
return HtmlHelper.fromHtml(
if (averageTdd != null) "<b>" + rh.gs(R.string.tdd) + ":</b><br>" +
toText(tdds, true) +
"<b>" + rh.gs(R.string.average) + ":</b><br>" +
averageTdd.toText(rh, tdds.size(), true)
else ""
)
}
@Suppress("SameParameterValue")
private fun toText(tdds: LongSparseArray<TotalDailyDose>, includeCarbs: Boolean): String {
var t = ""
for (i in 0 until tdds.size()) {
t += "${tdds.valueAt(i).toText(rh, dateUtil, includeCarbs)}<br>"
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)
return TableLayout(context).also { layout ->
layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
layout.addView(TextView(context).apply {
text = rh.gs(R.string.tdd)
setTypeface(typeface, Typeface.BOLD)
gravity = Gravity.CENTER_HORIZONTAL
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
})
layout.addView(TotalDailyDose.toTableRowHeader(context, rh, includeCarbs = true))
for (i in 0 until tdds.size()) layout.addView(tdds.valueAt(i).toTableRow(context, rh, dateUtil, includeCarbs = true))
averageTdd?.let { averageTdd ->
layout.addView(TextView(context).apply {
layoutParams = lp
text = rh.gs(R.string.average)
setTypeface(typeface, Typeface.BOLD)
gravity = Gravity.CENTER_HORIZONTAL
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
})
layout.addView(averageTdd.toTableRow(context, rh, tdds.size(), includeCarbs = true))
}
}
return t
}
}

View file

@ -1,14 +1,19 @@
package info.nightscout.androidaps.utils.stats
import android.text.Spanned
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Typeface
import android.util.LongSparseArray
import android.view.Gravity
import android.view.ViewGroup
import android.widget.TableLayout
import android.widget.TextView
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -63,38 +68,49 @@ class TirCalculator @Inject constructor(
return totalTir
}
fun stats(): Spanned {
val lowTirMgdl = Constants.STATS_RANGE_LOW_MMOL * Constants.MMOLL_TO_MGDL
val highTirMgdl = Constants.STATS_RANGE_HIGH_MMOL * Constants.MMOLL_TO_MGDL
val lowTitMgdl = Constants.STATS_TARGET_LOW_MMOL * Constants.MMOLL_TO_MGDL
val highTitMgdl = Constants.STATS_TARGET_HIGH_MMOL * Constants.MMOLL_TO_MGDL
@SuppressLint("SetTextI18n")
fun stats(context: Context): TableLayout =
TableLayout(context).also { layout ->
val lowTirMgdl = Constants.STATS_RANGE_LOW_MMOL * Constants.MMOLL_TO_MGDL
val highTirMgdl = Constants.STATS_RANGE_HIGH_MMOL * Constants.MMOLL_TO_MGDL
val lowTitMgdl = Constants.STATS_TARGET_LOW_MMOL * Constants.MMOLL_TO_MGDL
val highTitMgdl = Constants.STATS_TARGET_HIGH_MMOL * 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>" + rh.gs(R.string.tir) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTirMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTirMgdl) + "):</b><br>" +
toText(rh, tir7) +
"<br><b>" + rh.gs(R.string.average) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTirMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTirMgdl) + "):</b><br>" +
averageTir7.toText(rh, tir7.size()) + "<br>" +
averageTir30.toText(rh, tir30.size()) +
"<br><b>" + rh.gs(R.string.average) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTitMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTitMgdl) + "):</b><br>" +
averageTit7.toText(rh, tit7.size()) + "<br>" +
averageTit30.toText(rh, tit30.size())
)
}
fun toText(rh: ResourceHelper, tirs: LongSparseArray<TIR>): String {
var t = ""
for (i in 0 until tirs.size()) {
t += "${tirs.valueAt(i).toText(rh, dateUtil)}<br>"
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)
layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
layout.addView(
TextView(context).apply {
text = rh.gs(R.string.tir) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTirMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTirMgdl) + ")"
setTypeface(typeface, Typeface.BOLD)
gravity = Gravity.CENTER_HORIZONTAL
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
})
layout.addView(TIR.toTableRowHeader(context, rh))
for (i in 0 until tir7.size()) layout.addView(tir7.valueAt(i).toTableRow(context, rh, dateUtil))
layout.addView(
TextView(context).apply {
text = rh.gs(R.string.average) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTirMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTirMgdl) + ")"
setTypeface(typeface, Typeface.BOLD)
gravity = Gravity.CENTER_HORIZONTAL
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
})
layout.addView(averageTir7.toTableRow(context, rh, tir7.size()))
layout.addView(averageTir30.toTableRow(context, rh, tir30.size()))
layout.addView(
TextView(context).apply {
text = rh.gs(R.string.average) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTitMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTitMgdl) + ")"
setTypeface(typeface, Typeface.BOLD)
gravity = Gravity.CENTER_HORIZONTAL
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
})
layout.addView(averageTit7.toTableRow(context, rh, tit7.size()))
layout.addView(averageTit30.toTableRow(context, rh, tit30.size()))
}
return t
}
}

View file

@ -16,7 +16,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/defaultbackground"
android:orientation="horizontal">
android:orientation="horizontal"
android:paddingBottom="10dp">
<TextView
android:id="@+id/menu1"
@ -26,7 +27,8 @@
android:gravity="center"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:text="1" />
android:text="1"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/menu2"
@ -36,12 +38,13 @@
android:gravity="center"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:text="2" />
android:text="2"
tools:ignore="HardcodedText" />
</LinearLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/profiletype_title"
android:id="@+id/profile_type_title"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -51,7 +54,7 @@
app:boxStrokeColor="?attr/tabBgColorSelected">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/profiletype"
android:id="@+id/profile_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
@ -145,13 +148,13 @@
</TableRow>
<TableRow
android:id="@+id/basalpctfromtdd_row"
android:id="@+id/basal_pct_from_tdd_row"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical">
<TextView
android:id="@+id/basalpctfromtdd_label"
android:id="@+id/basal_pct_from_tdd_label"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
@ -159,7 +162,7 @@
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/basalpctfromtdd"
android:id="@+id/basal_pct_from_tdd"
android:layout_width="130dp"
android:layout_height="40dp"
app:customContentDescription="@string/basalpctfromtdd_label" />
@ -168,15 +171,15 @@
</TableLayout>
<TextView
<LinearLayout
android:id="@+id/tdds"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
android:orientation="vertical" />
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/copytolocalprofile"
android:id="@+id/copy_to_local_profile"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -257,7 +260,7 @@
</LinearLayout>
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/compareprofile"
android:id="@+id/compare_profiles"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -47,51 +47,53 @@
android:orientation="horizontal"
android:padding="5dp" />
<TextView
<LinearLayout
android:id="@+id/tdds"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
android:orientation="vertical" />
<TextView
<LinearLayout
android:id="@+id/tir"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
android:layout_marginTop="20dp"
android:orientation="vertical" />
<TextView
<LinearLayout
android:id="@+id/activity"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
android:layout_marginTop="20dp"
android:orientation="vertical" />
<LinearLayout
android:id="@+id/done_background"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:background="@android:color/transparent"
android:gravity="end"
android:layout_gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="8dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/reset"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginEnd="8dp"
style="@style/OkCancelButton.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/reset" />
<com.google.android.material.button.MaterialButton
android:id="@+id/ok"
style="@style/OkCancelButton.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
style="@style/OkCancelButton.Text"
android:text="@string/ok" />
</LinearLayout>

View file

@ -163,7 +163,6 @@
<string name="overview_calculator_label">Calculator</string>
<string name="constraintapllied">Constraint applied!</string>
<string name="sms_bolus">Bolus:</string>
<string name="basal">Basal</string>
<string name="sms_basal">Basal:</string>
<string name="changeyourinput">Change your input!</string>
<string name="configbuilder_bgsource">BG Source</string>
@ -967,7 +966,6 @@
<string name="invalidage">Invalid age entry</string>
<string name="invalidweight">Invalid weight entry</string>
<string name="invalidpct">Invalid % entry</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="tir">TIR</string>
<string name="activitymonitor">Activity monitor</string>
@ -1235,4 +1233,7 @@
<string name="count_selected">%1$d selected</string>
<string name="sort_label">Sort</string>
<string name="dialog_cancled">Dialog canceled</string>
<string name="below">Below</string>
<string name="in_range">In range</string>
<string name="above">Above</string>
</resources>

View file

@ -1,5 +1,10 @@
package info.nightscout.androidaps.extensions
import android.annotation.SuppressLint
import android.content.Context
import android.view.Gravity
import android.widget.TableRow
import android.widget.TextView
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.utils.DateUtil
@ -11,12 +16,49 @@ val TotalDailyDose.total
val TotalDailyDose.basalPct: Double
get() = if (total > 0) basalAmount / total * 100 else 0.0
fun TotalDailyDose.toText(rh: ResourceHelper, dateUtil: DateUtil, includeCarbs: Boolean): String =
if (total.isNaN() || bolusAmount.isNaN() || basalAmount.isNaN() || carbs.isNaN()) ""
else if (includeCarbs) rh.gs(R.string.tddwithcarbsformat, dateUtil.dateStringShort(timestamp), total, bolusAmount, basalAmount, basalPct, carbs)
else rh.gs(R.string.tddformat, dateUtil.dateStringShort(timestamp), total, bolusAmount, basalAmount, basalPct)
fun TotalDailyDose.Companion.toTableRowHeader(context: Context, rh: ResourceHelper, includeCarbs: Boolean): TableRow =
TableRow(context).also { header ->
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)
header.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
header.gravity = Gravity.CENTER_HORIZONTAL
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 0; weight = 1f }; text = rh.gs(R.string.date) })
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 1; weight = 1f }; text = "" })
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 2; weight = 1f }; text = rh.gs(R.string.bolus) })
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 3; weight = 1f }; text = rh.gs(R.string.basal) })
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 4; weight = 1f }; text = rh.gs(R.string.basalpct) })
if (includeCarbs)
header.addView(TextView(context).apply { layoutParams = lp.apply { column = 5; weight = 1f }; text = rh.gs(R.string.carbs) })
}
fun TotalDailyDose.toText(rh: ResourceHelper, days: Int, includeCarbs: Boolean): String =
if (total.isNaN() || bolusAmount.isNaN() || basalAmount.isNaN() || carbs.isNaN()) ""
else if (includeCarbs) rh.gs(R.string.tddwithcarbsformat, days.toString() + rh.gs(R.string.days), total, bolusAmount, basalAmount, basalAmount / total * 100, carbs)
else rh.gs(R.string.tddformat, days.toString() + rh.gs(R.string.days), total, bolusAmount, basalAmount, basalAmount / total * 100)
fun TotalDailyDose.toTableRow(context: Context, rh: ResourceHelper, dateUtil: DateUtil, includeCarbs: Boolean): TableRow =
TableRow(context).also { row ->
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT).apply { weight = 1f }
if ((total.isNaN() || bolusAmount.isNaN() || basalAmount.isNaN() || carbs.isNaN()).not()) {
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
row.gravity = Gravity.CENTER_HORIZONTAL
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 0 }; text = dateUtil.dateStringShort(timestamp) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 1 }; text = rh.gs(R.string.formatinsulinunits1, total) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 2 }; text = rh.gs(R.string.formatinsulinunits1, bolusAmount) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 3 }; text = rh.gs(R.string.formatinsulinunits1, basalAmount) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 4 }; text = rh.gs(R.string.formatPercent, basalPct) })
if (includeCarbs)
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 5 }; text = rh.gs(R.string.formatinsulinunits1, carbs) })
}
}
@SuppressLint("SetTextI18n")
fun TotalDailyDose.toTableRow(context: Context, rh: ResourceHelper, days: Int, includeCarbs: Boolean): TableRow =
TableRow(context).also { row ->
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT).apply { weight = 1f }
if ((total.isNaN() || bolusAmount.isNaN() || basalAmount.isNaN() || carbs.isNaN()).not()) {
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
row.gravity = Gravity.CENTER_HORIZONTAL
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 0 }; text = "%02d".format(days) + " " + rh.gs(R.string.days) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 1 }; text = rh.gs(R.string.formatinsulinunits1, total) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 2 }; text = rh.gs(R.string.formatinsulinunits1, bolusAmount) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 3 }; text = rh.gs(R.string.formatinsulinunits1, basalAmount) })
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 4 }; text = rh.gs(R.string.formatPercent, basalPct) })
if (includeCarbs)
row.addView(TextView(context).apply { layoutParams = lp.apply { column = 5 }; text = rh.gs(R.string.formatinsulinunits1, carbs) })
}
}

View file

@ -263,11 +263,6 @@
<!-- Temptarget-->
<string name="mins">%1$d min</string>
<!-- TDD-->
<string name="tddformat"><![CDATA[<b>%1$s:</b> ∑: <b>%2$.2f U</b> Bol: <b>%3$.2f U</b> Bas: <b>%4$.2f U(%5$.0f%%)</b>]]></string>
<string name="tddwithcarbsformat"><![CDATA[<b>%1$s:</b> ∑: <b>%2$.2f U</b> Bol: <b>%3$.2f U</b> Bas: <b>%4$.2f U(%5$.0f%%)</b> Carbs: <b>%6$.0f g</b>]]></string>
<string name="activitymonitorformat"><![CDATA[<b><span style=\"color:yellow\">%1$s:</span></b> <b>%2$s</b> in <b>%3$d</b> days<br>]]></string>
<!-- Translator-->
<string name="careportal">Careportal</string>
<string name="careportal_bgcheck">BG Check</string>
@ -558,6 +553,9 @@
<string name="insight_refresh_button" comment="26 characters max for translation">Insight Refresh Button</string>
<string name="a11y_min_button_description">decrement %1$s by %2$s</string>
<string name="a11y_plus_button_description">increment %1$s by %2$s</string>
<string name="formatPercent">%1$.0f%%</string>
<string name="basal">Basal</string>
<string name="basalpct">Basal %</string>
<plurals name="days">
<item quantity="one">%1$d day</item>

View file

@ -40,4 +40,6 @@ data class TotalDailyDose(
var bolusAmount: Double = 0.0,
var totalAmount: Double = 0.0, // if zero it's calculated as basalAmount + bolusAmount
var carbs: Double = 0.0
) : TraceableDBEntry, DBEntryWithTime
) : TraceableDBEntry, DBEntryWithTime {
companion object
}