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

View file

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

View file

@ -43,9 +43,9 @@ class SurveyActivity : NoSplashAppCompatActivity() {
val profileList = profileStore?.getProfileList() ?: return val profileList = profileStore?.getProfileList() ?: return
binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList) binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
binding.tdds.text = tddCalculator.stats() //binding.tdds.text = tddCalculator.stats()
binding.tir.text = tirCalculator.stats() //binding.tir.text = tirCalculator.stats()
binding.activity.text = activityMonitor.stats() //binding.activity.text = activityMonitor.stats()
binding.profile.setOnClickListener { binding.profile.setOnClickListener {
val age = SafeParse.stringToDouble(binding.age.text.toString()) 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.Activity
import android.app.Application import android.app.Application
import android.content.Context
import android.graphics.Typeface
import android.os.Bundle 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.R
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.SafeParse
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.SafeParse
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -58,24 +64,47 @@ class ActivityMonitor @Inject constructor(
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
} }
private fun toText(): String { fun stats(context: Context): TableLayout =
val keys: Map<String, *> = sp.getAll() TableLayout(context).also { layout ->
var result = "" layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
for ((key, value) in keys) layout.addView(
if (key.startsWith("Monitor") && key.endsWith("total")) { TextView(context).apply {
val v = if (value is Long) value else SafeParse.stringToLong(value as String) text = rh.gs(R.string.activitymonitor)
val activity = key.split("_")[1].replace("Activity", "") setTypeface(typeface, Typeface.BOLD)
val duration = dateUtil.niceTimeScalar(v, rh) gravity = Gravity.CENTER_HORIZONTAL
val start = sp.getLong(key.replace("total", "start"), 0) setTextAppearance(android.R.style.TextAppearance_Material_Medium)
val days = T.msecs(dateUtil.now() - start).days() })
result += rh.gs(R.string.activitymonitorformat, activity, duration, days) layout.addView(
} TableRow(context).also { row ->
return result 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 { val keys: Map<String, *> = sp.getAll()
return HtmlHelper.fromHtml("<br><b>" + rh.gs(R.string.activitymonitor) + ":</b><br>" + toText()) 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() { fun reset() {
val keys: Map<String, *> = sp.getAll() val keys: Map<String, *> = sp.getAll()

View file

@ -1,11 +1,16 @@
package info.nightscout.androidaps.utils.stats 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.R
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlin.math.roundToInt
class TIR(val date: Long, val lowThreshold: Double, val highThreshold: Double) { class TIR(val date: Long, val lowThreshold: Double, val highThreshold: Double) {
internal var below = 0 internal var below = 0
internal var inRange = 0 internal var inRange = 0
internal var above = 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 inRange() = run { inRange++; count++ }
fun above() = run { above++; 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 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 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.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.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.TotalDailyDose import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.extensions.convertedToAbsolute 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.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.MidnightTime import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -186,24 +193,31 @@ class TddCalculator @Inject constructor(
return totalTdd return totalTdd
} }
fun stats(): Spanned { @SuppressLint("SetTextI18n")
fun stats(context: Context): TableLayout {
val tdds = calculate(7) val tdds = calculate(7)
val averageTdd = averageTDD(tdds) val averageTdd = averageTDD(tdds)
return HtmlHelper.fromHtml( val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)
if (averageTdd != null) "<b>" + rh.gs(R.string.tdd) + ":</b><br>" + return TableLayout(context).also { layout ->
toText(tdds, true) + layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
"<b>" + rh.gs(R.string.average) + ":</b><br>" + layout.addView(TextView(context).apply {
averageTdd.toText(rh, tdds.size(), true) text = rh.gs(R.string.tdd)
else "" setTypeface(typeface, Typeface.BOLD)
) gravity = Gravity.CENTER_HORIZONTAL
} setTextAppearance(android.R.style.TextAppearance_Material_Medium)
})
@Suppress("SameParameterValue") layout.addView(TotalDailyDose.toTableRowHeader(context, rh, includeCarbs = true))
private fun toText(tdds: LongSparseArray<TotalDailyDose>, includeCarbs: Boolean): String { for (i in 0 until tdds.size()) layout.addView(tdds.valueAt(i).toTableRow(context, rh, dateUtil, includeCarbs = true))
var t = "" averageTdd?.let { averageTdd ->
for (i in 0 until tdds.size()) { layout.addView(TextView(context).apply {
t += "${tdds.valueAt(i).toText(rh, dateUtil, includeCarbs)}<br>" 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 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.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.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.MidnightTime import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -63,38 +68,49 @@ class TirCalculator @Inject constructor(
return totalTir return totalTir
} }
fun stats(): Spanned { @SuppressLint("SetTextI18n")
val lowTirMgdl = Constants.STATS_RANGE_LOW_MMOL * Constants.MMOLL_TO_MGDL fun stats(context: Context): TableLayout =
val highTirMgdl = Constants.STATS_RANGE_HIGH_MMOL * Constants.MMOLL_TO_MGDL TableLayout(context).also { layout ->
val lowTitMgdl = Constants.STATS_TARGET_LOW_MMOL * Constants.MMOLL_TO_MGDL val lowTirMgdl = Constants.STATS_RANGE_LOW_MMOL * Constants.MMOLL_TO_MGDL
val highTitMgdl = Constants.STATS_TARGET_HIGH_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 tir7 = calculate(7, lowTirMgdl, highTirMgdl)
val averageTir7 = averageTIR(tir7) val averageTir7 = averageTIR(tir7)
val tir30 = calculate(30, lowTirMgdl, highTirMgdl) val tir30 = calculate(30, lowTirMgdl, highTirMgdl)
val averageTir30 = averageTIR(tir30) val averageTir30 = averageTIR(tir30)
val tit7 = calculate(7, lowTitMgdl, highTitMgdl) val tit7 = calculate(7, lowTitMgdl, highTitMgdl)
val averageTit7 = averageTIR(tit7) val averageTit7 = averageTIR(tit7)
val tit30 = calculate(30, lowTitMgdl, highTitMgdl) val tit30 = calculate(30, lowTitMgdl, highTitMgdl)
val averageTit30 = averageTIR(tit30) val averageTit30 = averageTIR(tit30)
return HtmlHelper.fromHtml( layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
"<br><b>" + rh.gs(R.string.tir) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTirMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTirMgdl) + "):</b><br>" + layout.addView(
toText(rh, tir7) + TextView(context).apply {
"<br><b>" + rh.gs(R.string.average) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTirMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTirMgdl) + "):</b><br>" + text = rh.gs(R.string.tir) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTirMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTirMgdl) + ")"
averageTir7.toText(rh, tir7.size()) + "<br>" + setTypeface(typeface, Typeface.BOLD)
averageTir30.toText(rh, tir30.size()) + gravity = Gravity.CENTER_HORIZONTAL
"<br><b>" + rh.gs(R.string.average) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTitMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTitMgdl) + "):</b><br>" + setTextAppearance(android.R.style.TextAppearance_Material_Medium)
averageTit7.toText(rh, tit7.size()) + "<br>" + })
averageTit30.toText(rh, tit30.size()) 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 {
fun toText(rh: ResourceHelper, tirs: LongSparseArray<TIR>): String { text = rh.gs(R.string.average) + " (" + Profile.toCurrentUnitsString(profileFunction, lowTirMgdl) + "-" + Profile.toCurrentUnitsString(profileFunction, highTirMgdl) + ")"
var t = "" setTypeface(typeface, Typeface.BOLD)
for (i in 0 until tirs.size()) { gravity = Gravity.CENTER_HORIZONTAL
t += "${tirs.valueAt(i).toText(rh, dateUtil)}<br>" 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_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/defaultbackground" android:background="?attr/defaultbackground"
android:orientation="horizontal"> android:orientation="horizontal"
android:paddingBottom="10dp">
<TextView <TextView
android:id="@+id/menu1" android:id="@+id/menu1"
@ -26,7 +27,8 @@
android:gravity="center" android:gravity="center"
android:paddingLeft="5dp" android:paddingLeft="5dp"
android:paddingRight="5dp" android:paddingRight="5dp"
android:text="1" /> android:text="1"
tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/menu2" android:id="@+id/menu2"
@ -36,12 +38,13 @@
android:gravity="center" android:gravity="center"
android:paddingLeft="5dp" android:paddingLeft="5dp"
android:paddingRight="5dp" android:paddingRight="5dp"
android:text="2" /> android:text="2"
tools:ignore="HardcodedText" />
</LinearLayout> </LinearLayout>
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/profiletype_title" android:id="@+id/profile_type_title"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -51,7 +54,7 @@
app:boxStrokeColor="?attr/tabBgColorSelected"> app:boxStrokeColor="?attr/tabBgColorSelected">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/profiletype" android:id="@+id/profile_type"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:clickable="true"
@ -145,13 +148,13 @@
</TableRow> </TableRow>
<TableRow <TableRow
android:id="@+id/basalpctfromtdd_row" android:id="@+id/basal_pct_from_tdd_row"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical"> android:gravity="center_vertical">
<TextView <TextView
android:id="@+id/basalpctfromtdd_label" android:id="@+id/basal_pct_from_tdd_label"
android:layout_width="150dp" android:layout_width="150dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
@ -159,7 +162,7 @@
android:textAppearance="@style/TextAppearance.AppCompat.Medium" /> android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/basalpctfromtdd" android:id="@+id/basal_pct_from_tdd"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" android:layout_height="40dp"
app:customContentDescription="@string/basalpctfromtdd_label" /> app:customContentDescription="@string/basalpctfromtdd_label" />
@ -168,15 +171,15 @@
</TableLayout> </TableLayout>
<TextView <LinearLayout
android:id="@+id/tdds" android:id="@+id/tdds"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:textAppearance="@style/TextAppearance.AppCompat.Small" /> android:orientation="vertical" />
<info.nightscout.androidaps.utils.ui.SingleClickButton <info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/copytolocalprofile" android:id="@+id/copy_to_local_profile"
style="?android:attr/buttonStyle" style="?android:attr/buttonStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -257,7 +260,7 @@
</LinearLayout> </LinearLayout>
<info.nightscout.androidaps.utils.ui.SingleClickButton <info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/compareprofile" android:id="@+id/compare_profiles"
style="?android:attr/buttonStyle" style="?android:attr/buttonStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

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

View file

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

View file

@ -1,5 +1,10 @@
package info.nightscout.androidaps.extensions 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.core.R
import info.nightscout.androidaps.database.entities.TotalDailyDose import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
@ -11,12 +16,49 @@ val TotalDailyDose.total
val TotalDailyDose.basalPct: Double val TotalDailyDose.basalPct: Double
get() = if (total > 0) basalAmount / total * 100 else 0.0 get() = if (total > 0) basalAmount / total * 100 else 0.0
fun TotalDailyDose.toText(rh: ResourceHelper, dateUtil: DateUtil, includeCarbs: Boolean): String = fun TotalDailyDose.Companion.toTableRowHeader(context: Context, rh: ResourceHelper, includeCarbs: Boolean): TableRow =
if (total.isNaN() || bolusAmount.isNaN() || basalAmount.isNaN() || carbs.isNaN()) "" TableRow(context).also { header ->
else if (includeCarbs) rh.gs(R.string.tddwithcarbsformat, dateUtil.dateStringShort(timestamp), total, bolusAmount, basalAmount, basalPct, carbs) val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)
else rh.gs(R.string.tddformat, dateUtil.dateStringShort(timestamp), total, bolusAmount, basalAmount, basalPct) 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 = fun TotalDailyDose.toTableRow(context: Context, rh: ResourceHelper, dateUtil: DateUtil, includeCarbs: Boolean): TableRow =
if (total.isNaN() || bolusAmount.isNaN() || basalAmount.isNaN() || carbs.isNaN()) "" TableRow(context).also { row ->
else if (includeCarbs) rh.gs(R.string.tddwithcarbsformat, days.toString() + rh.gs(R.string.days), total, bolusAmount, basalAmount, basalAmount / total * 100, carbs) val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT).apply { weight = 1f }
else rh.gs(R.string.tddformat, days.toString() + rh.gs(R.string.days), total, bolusAmount, basalAmount, basalAmount / total * 100) 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--> <!-- Temptarget-->
<string name="mins">%1$d min</string> <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--> <!-- Translator-->
<string name="careportal">Careportal</string> <string name="careportal">Careportal</string>
<string name="careportal_bgcheck">BG Check</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="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_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="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"> <plurals name="days">
<item quantity="one">%1$d day</item> <item quantity="one">%1$d day</item>

View file

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