diff --git a/app/src/main/java/info/nightscout/androidaps/activities/SurveyActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/SurveyActivity.kt
index ff3e361a9b..86c90e1657 100644
--- a/app/src/main/java/info/nightscout/androidaps/activities/SurveyActivity.kt
+++ b/app/src/main/java/info/nightscout/androidaps/activities/SurveyActivity.kt
@@ -8,9 +8,9 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.defaultProfile.DefaultProfile
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.interfaces.ActivePluginProvider
+import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
-import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.InstanceId
@@ -62,16 +62,19 @@ class SurveyActivity : NoSplashAppCompatActivity() {
ToastUtils.showToastInUiThread(this, R.string.invalidweight)
return@setOnClickListener
}
- val profile = defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())
- val args = Bundle()
- args.putLong("time", DateUtil.now())
- args.putInt("mode", ProfileViewerDialog.Mode.CUSTOM_PROFILE.ordinal)
- args.putString("customProfile", profile.data.toString())
- args.putString("customProfileUnits", profile.units)
- args.putString("customProfileName", "Age: $age TDD: $tdd Weight: $weight")
- val pvd = ProfileViewerDialog()
- pvd.arguments = args
- pvd.show(supportFragmentManager, "ProfileViewDialog")
+ profileFunction.getProfile()?.let { runningProfile ->
+ val profile = defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())
+ ProfileViewerDialog().also { pvd ->
+ pvd.arguments = Bundle().also {
+ it.putLong("time", DateUtil.now())
+ it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal)
+ it.putString("customProfile", runningProfile.data.toString())
+ it.putString("customProfile2", profile.data.toString())
+ it.putString("customProfileUnits", profile.units)
+ it.putString("customProfileName", "Age: $age TDD: $tdd Weight: $weight")
+ }
+ }.show(supportFragmentManager, "ProfileViewDialog")
+ }
}
survey_submit.setOnClickListener {
diff --git a/core/src/main/java/info/nightscout/androidaps/data/Profile.java b/core/src/main/java/info/nightscout/androidaps/data/Profile.java
index 7f583663bb..9fe8c7846e 100644
--- a/core/src/main/java/info/nightscout/androidaps/data/Profile.java
+++ b/core/src/main/java/info/nightscout/androidaps/data/Profile.java
@@ -370,7 +370,7 @@ public class Profile {
return lastValue;
}
- protected String format_HH_MM(Integer timeAsSeconds) {
+ public static String format_HH_MM(Integer timeAsSeconds) {
String time;
int hour = timeAsSeconds / 60 / 60;
int minutes = (timeAsSeconds - hour * 60 * 60) / 60;
diff --git a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt
index 56e48bd894..75708b76ae 100644
--- a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt
+++ b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt
@@ -1,6 +1,7 @@
package info.nightscout.androidaps.dialogs
import android.os.Bundle
+import android.text.Spanned
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -14,10 +15,12 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.close.*
import kotlinx.android.synthetic.main.dialog_profileviewer.*
import org.json.JSONObject
+import java.text.DecimalFormat
import javax.inject.Inject
class ProfileViewerDialog : DaggerDialogFragment() {
@@ -32,11 +35,13 @@ class ProfileViewerDialog : DaggerDialogFragment() {
enum class Mode(val i: Int) {
RUNNING_PROFILE(1),
CUSTOM_PROFILE(2),
- DB_PROFILE(3)
+ DB_PROFILE(3),
+ PROFILE_COMPARE(4)
}
private var mode: Mode = Mode.RUNNING_PROFILE
private var customProfileJson: String = ""
+ private var customProfileJson2: String = ""
private var customProfileName: String = ""
private var customProfileUnits: String = Constants.MGDL
@@ -49,6 +54,8 @@ class ProfileViewerDialog : DaggerDialogFragment() {
customProfileJson = bundle.getString("customProfile", "")
customProfileUnits = bundle.getString("customProfileUnits", Constants.MGDL)
customProfileName = bundle.getString("customProfileName", "")
+ if (mode == Mode.PROFILE_COMPARE)
+ customProfileJson2 = bundle.getString("customProfile2", "")
}
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
@@ -65,11 +72,13 @@ class ProfileViewerDialog : DaggerDialogFragment() {
close.setOnClickListener { dismiss() }
val profile: Profile?
+ val profile2: Profile?
val profileName: String?
val date: String?
when (mode) {
Mode.RUNNING_PROFILE -> {
profile = activePlugin.activeTreatments.getProfileSwitchFromHistory(time)?.profileObject
+ profile2 = null
profileName = activePlugin.activeTreatments.getProfileSwitchFromHistory(time)?.customizedName
date = dateUtil.dateAndTimeString(activePlugin.activeTreatments.getProfileSwitchFromHistory(time)?.date
?: 0)
@@ -78,6 +87,15 @@ class ProfileViewerDialog : DaggerDialogFragment() {
Mode.CUSTOM_PROFILE -> {
profile = Profile(injector, JSONObject(customProfileJson), customProfileUnits)
+ profile2 = null
+ profileName = customProfileName
+ date = ""
+ profileview_datelayout.visibility = View.GONE
+ }
+
+ Mode.PROFILE_COMPARE -> {
+ profile = Profile(injector, JSONObject(customProfileJson), customProfileUnits)
+ profile2 = Profile(injector, JSONObject(customProfileJson2), customProfileUnits)
profileName = customProfileName
date = ""
profileview_datelayout.visibility = View.GONE
@@ -86,6 +104,7 @@ class ProfileViewerDialog : DaggerDialogFragment() {
Mode.DB_PROFILE -> {
val profileList = databaseHelper.getProfileSwitchData(time, true)
profile = if (profileList.isNotEmpty()) profileList[0].profileObject else null
+ profile2 = null
profileName = if (profileList.isNotEmpty()) profileList[0].customizedName else null
date = if (profileList.isNotEmpty()) dateUtil.dateAndTimeString(profileList[0].date) else null
profileview_datelayout.visibility = View.VISIBLE
@@ -93,20 +112,38 @@ class ProfileViewerDialog : DaggerDialogFragment() {
}
profileview_noprofile.visibility = View.VISIBLE
- profile?.let {
- profileview_units.text = it.units
- profileview_dia.text = resourceHelper.gs(R.string.format_hours, it.dia)
- profileview_activeprofile.text = profileName
- profileview_date.text = date
- profileview_ic.text = it.icList
- profileview_isf.text = it.isfList
- profileview_basal.text = it.basalList
- profileview_target.text = it.targetList
- basal_graph.show(it)
+ if (mode == Mode.PROFILE_COMPARE)
+ profile?.let { profile1 ->
+ profile2?.let { profile2 ->
+ profileview_units.text = profile1.units
+ profileview_dia.text = HtmlHelper.fromHtml(formatColors("", profile1.dia, profile1.dia, DecimalFormat("0.00"), resourceHelper.gs(R.string.shorthour)))
+ profileview_activeprofile.text = profileName
+ profileview_date.text = date
+ profileview_ic.text = ics(profile1, profile2)
+ profileview_isf.text = isfs(profile1, profile2)
+ profileview_basal.text = basals(profile1, profile2)
+ profileview_target.text = HtmlHelper.fromHtml(formatColors("", profile1.targetList + "
", profile2.targetList, ""))
+ basal_graph.show(profile1, profile2)
+ }
- profileview_noprofile.visibility = View.GONE
- profileview_invalidprofile.visibility = if (it.isValid("ProfileViewDialog")) View.GONE else View.VISIBLE
- }
+ profileview_noprofile.visibility = View.GONE
+ profileview_invalidprofile.visibility = if (profile1.isValid("ProfileViewDialog")) View.GONE else View.VISIBLE
+ }
+ else
+ profile?.let {
+ profileview_units.text = it.units
+ profileview_dia.text = resourceHelper.gs(R.string.format_hours, it.dia)
+ profileview_activeprofile.text = profileName
+ profileview_date.text = date
+ profileview_ic.text = it.icList
+ profileview_isf.text = it.isfList
+ profileview_basal.text = it.basalList
+ profileview_target.text = it.targetList
+ basal_graph.show(it)
+
+ profileview_noprofile.visibility = View.GONE
+ profileview_invalidprofile.visibility = if (it.isValid("ProfileViewDialog")) View.GONE else View.VISIBLE
+ }
}
override fun onStart() {
@@ -121,6 +158,79 @@ class ProfileViewerDialog : DaggerDialogFragment() {
bundle.putString("customProfile", customProfileJson)
bundle.putString("customProfileName", customProfileName)
bundle.putString("customProfileUnits", customProfileUnits)
+ if (mode == Mode.PROFILE_COMPARE)
+ bundle.putString("customProfile2", customProfileJson2)
}
+ private fun formatColors(label: String, value1: Double, value2: Double, format: DecimalFormat, units: String): String {
+ return formatColors(label, format.format(value1), format.format(value2), units)
+ }
+
+ private fun formatColors(label: String, text1: String, text2: String, units: String): String {
+ var s = "$label"
+ s += " "
+ s += "$text1"
+ s += " "
+ s += "$text2"
+ s += " "
+ s += "$units"
+ return s
+ }
+
+ private fun basals(profile1: Profile, profile2: Profile): Spanned {
+ var prev1 = 0.0
+ var prev2 = 0.0
+ val s = StringBuilder()
+ for (hour in 0..23) {
+ val val1 = profile1.getBasalTimeFromMidnight(hour * 60 * 60)
+ val val2 = profile2.getBasalTimeFromMidnight(hour * 60 * 60)
+ if (val1 != prev1 || val2 != prev2) {
+ s.append(formatColors(Profile.format_HH_MM(hour * 60 * 60), val1, val2, DecimalFormat("0.00"), resourceHelper.gs(R.string.profile_ins_units_per_hour)))
+ s.append("
")
+ }
+ prev1 = val1
+ prev2 = val2
+ }
+ s.append(formatColors(
+ " ∑ ",
+ profile1.baseBasalSum(),
+ profile2.baseBasalSum(),
+ DecimalFormat("0.00"),
+ resourceHelper.gs(R.string.insulin_unit_shortname)))
+ return HtmlHelper.fromHtml(s.toString())
+ }
+
+ private fun ics(profile1: Profile, profile2: Profile): Spanned {
+ var prev1 = 0.0
+ var prev2 = 0.0
+ val s = StringBuilder()
+ for (hour in 0..23) {
+ val val1 = profile1.getIcTimeFromMidnight(hour * 60 * 60)
+ val val2 = profile2.getIcTimeFromMidnight(hour * 60 * 60)
+ if (val1 != prev1 || val2 != prev2) {
+ s.append(formatColors(Profile.format_HH_MM(hour * 60 * 60), val1, val2, DecimalFormat("0.0"), resourceHelper.gs(R.string.profile_carbs_per_unit)))
+ s.append("
")
+ }
+ prev1 = val1
+ prev2 = val2
+ }
+ return HtmlHelper.fromHtml(s.toString())
+ }
+
+ private fun isfs(profile1: Profile, profile2: Profile): Spanned {
+ var prev1 = 0.0
+ var prev2 = 0.0
+ val s = StringBuilder()
+ for (hour in 0..23) {
+ val val1 = Profile.fromMgdlToUnits(profile1.getIsfMgdlTimeFromMidnight(hour * 60 * 60), profile1.units)
+ val val2 = Profile.fromMgdlToUnits(profile2.getIsfMgdlTimeFromMidnight(hour * 60 * 60), profile1.units)
+ if (val1 != prev1 || val2 != prev2) {
+ s.append(formatColors(Profile.format_HH_MM(hour * 60 * 60), val1, val2, DecimalFormat("0.0"), resourceHelper.gs(R.string.profile_carbs_per_unit)))
+ s.append("
")
+ }
+ prev1 = val1
+ prev2 = val2
+ }
+ return HtmlHelper.fromHtml(s.toString())
+ }
}
diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileGraph.kt b/core/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileGraph.kt
index a48f5e4118..8dd922ca60 100644
--- a/core/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileGraph.kt
+++ b/core/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileGraph.kt
@@ -1,13 +1,16 @@
package info.nightscout.androidaps.plugins.treatments.fragments
import android.content.Context
+import android.graphics.Color
import android.util.AttributeSet
import com.jjoe64.graphview.GraphView
import com.jjoe64.graphview.series.DataPoint
import com.jjoe64.graphview.series.LineGraphSeries
+import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.utils.Round
import java.util.*
+import kotlin.math.max
class ProfileGraph : GraphView {
@@ -21,7 +24,7 @@ class ProfileGraph : GraphView {
basalArray.add(DataPoint(hour.toDouble(), profile.getBasalTimeFromMidnight(hour * 60 * 60)))
basalArray.add(DataPoint((hour + 1).toDouble(), profile.getBasalTimeFromMidnight(hour * 60 * 60)))
}
- val basalDataPoints: Array = Array(basalArray.size){ i-> basalArray[i]}
+ val basalDataPoints: Array = Array(basalArray.size) { i -> basalArray[i] }
val basalSeries: LineGraphSeries = LineGraphSeries(basalDataPoints)
addSeries(basalSeries)
basalSeries.thickness = 8
@@ -35,4 +38,40 @@ class ProfileGraph : GraphView {
gridLabelRenderer.numHorizontalLabels = 13
gridLabelRenderer.verticalLabelsColor = basalSeries.color
}
+
+ fun show(profile1: Profile, profile2: Profile) {
+ removeAllSeries()
+
+ // profile 1
+ val basalArray1: MutableList = ArrayList()
+ for (hour in 0..23) {
+ basalArray1.add(DataPoint(hour.toDouble(), profile1.getBasalTimeFromMidnight(hour * 60 * 60)))
+ basalArray1.add(DataPoint((hour + 1).toDouble(), profile1.getBasalTimeFromMidnight(hour * 60 * 60)))
+ }
+ val basalSeries1: LineGraphSeries = LineGraphSeries(Array(basalArray1.size) { i -> basalArray1[i] })
+ addSeries(basalSeries1)
+ basalSeries1.thickness = 8
+ basalSeries1.isDrawBackground = true
+
+ // profile 2
+ val basalArray2: MutableList = ArrayList()
+ for (hour in 0..23) {
+ basalArray2.add(DataPoint(hour.toDouble(), profile2.getBasalTimeFromMidnight(hour * 60 * 60)))
+ basalArray2.add(DataPoint((hour + 1).toDouble(), profile2.getBasalTimeFromMidnight(hour * 60 * 60)))
+ }
+ val basalSeries2: LineGraphSeries = LineGraphSeries(Array(basalArray2.size) { i -> basalArray2[i] })
+ addSeries(basalSeries2)
+ basalSeries2.thickness = 8
+ basalSeries2.isDrawBackground = false
+ basalSeries2.color = context.getColor(R.color.examinedProfile)
+ basalSeries2.backgroundColor = context.getColor(R.color.examinedProfile)
+
+ viewport.isXAxisBoundsManual = true
+ viewport.setMinX(0.0)
+ viewport.setMaxX(24.0)
+ viewport.isYAxisBoundsManual = true
+ viewport.setMinY(0.0)
+ viewport.setMaxY(Round.ceilTo(max(profile1.maxDailyBasal, profile2.maxDailyBasal) * 1.1, 0.5))
+ gridLabelRenderer.numHorizontalLabels = 13
+ }
}
\ No newline at end of file
diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml
index 27e0e33010..d6def91fd7 100644
--- a/core/src/main/res/values/colors.xml
+++ b/core/src/main/res/values/colors.xml
@@ -23,6 +23,7 @@
#FF000000
#FFFF5555
#FF000000
+ #FFFF5555
#C803A9F4