From aea505e54339ab7de84d0924d7fc68c25af9b16a Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 20 Jun 2016 12:03:05 +0200 Subject: [PATCH 1/5] some rouding to make nicer on screen --- .idea/misc.xml | 2 +- .../nightscout/androidaps/db/DatabaseHelper.java | 9 +++++++++ .../plugins/OpenAPSMA/DetermineBasalAdapterJS.java | 2 +- .../plugins/OpenAPSMA/DetermineBasalResult.java | 2 +- .../androidaps/plugins/OpenAPSMA/IobTotal.java | 11 +++++++++++ .../plugins/OpenAPSMA/OpenAPSMAFragment.java | 5 ++++- .../Overview/Dialogs/WizardDialogFragment.java | 9 +-------- app/src/main/java/info/nightscout/utils/Round.java | 13 +++++++++++++ 8 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/info/nightscout/utils/Round.java diff --git a/.idea/misc.xml b/.idea/misc.xml index 5d19981032..fbb68289f4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index a5ef1bef47..47d230bb02 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -29,6 +29,7 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; +import info.nightscout.utils.Round; public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class); @@ -227,6 +228,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { this.delta = delta; this.avgdelta = avgdelta; } + + public GlucoseStatus round() { + this.glucose = Round.roundTo(this.glucose, 0.1); + this.delta = Round.roundTo(this.delta, 0.01); + this.avgdelta = Round.roundTo(this.avgdelta, 0.01); + return this; + } } @Nullable @@ -284,6 +292,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { e.printStackTrace(); return null; } + result.round(); return result; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterJS.java index de09782ddd..c25200ceb5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterJS.java @@ -132,8 +132,8 @@ public class DetermineBasalAdapterJS implements Parcelable { mV8rt.add(PARAM_iobData, mIobData); // Glucose status mGlucoseStatus = new V8Object(mV8rt); - mGlucoseStatus.add("delta", 0); mGlucoseStatus.add("glucose", 0); + mGlucoseStatus.add("delta", 0); mGlucoseStatus.add("avgdelta", 0); mV8rt.add(PARAM_glucoseStatus, mGlucoseStatus); // Meal data diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResult.java index c023bad6b5..cd955d32ca 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResult.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResult.java @@ -32,7 +32,7 @@ public class DetermineBasalResult extends APSResult { } if (result.contains("duration")) { duration = result.getInteger("duration"); - changeRequested = changeRequested & true; + changeRequested = changeRequested; } else { duration = -1; changeRequested = false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/IobTotal.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/IobTotal.java index 0b167b8a94..77e3786313 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/IobTotal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/IobTotal.java @@ -6,6 +6,7 @@ import org.json.JSONObject; import java.util.Date; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.Round; public class IobTotal { public Double iob; @@ -50,6 +51,16 @@ public class IobTotal { return result; } + public IobTotal round() { + this.iob = Round.roundTo(this.iob, 0.001); + this.activity = Round.roundTo(this.activity, 0.0001); + this.bolussnooze = Round.roundTo(this.bolussnooze, 0.0001); + this.basaliob = Round.roundTo(this.basaliob, 0.001); + this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001); + this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001); + return this; + } + public JSONObject json() { JSONObject json = new JSONObject(); try { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java index bdae0f057c..3fb86d4ee7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java @@ -36,6 +36,7 @@ import info.nightscout.androidaps.plugins.ScriptReader; import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.Round; public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, PluginBase, APSInterface { private static Logger log = LoggerFactory.getLogger(OpenAPSMAFragment.class); @@ -262,6 +263,8 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, double maxBasal = Double.parseDouble(SP.getString("openapsma_max_basal", "1").replace(",", ".")); double minBg = NSProfile.toMgdl(Double.parseDouble(SP.getString("openapsma_min_bg", minBgDefault).replace(",", ".")), units); double maxBg = NSProfile.toMgdl(Double.parseDouble(SP.getString("openapsma_max_bg", maxBgDefault).replace(",", ".")), units); + minBg = Round.roundTo(minBg, 1d); + maxBg = Round.roundTo(maxBg, 1d); TreatmentsInterface treatments = MainActivity.getConfigBuilder().getActiveTreatments(); TempBasalsInterface tempBasals = MainActivity.getConfigBuilder().getActiveTempBasals(); @@ -270,7 +273,7 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, IobTotal bolusIob = treatments.getLastCalculation(); IobTotal basalIob = tempBasals.getLastCalculation(); - IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob); + IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round(); TreatmentsFragment.MealData mealData = treatments.getMealData(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java index 6188808545..25df14a849 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java @@ -244,7 +244,7 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe calculatedTotalInsulin = 0d; totalInsulin.setText(""); } else { - calculatedTotalInsulin = roundTo(calculatedTotalInsulin, 0.05d); + calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, 0.05d); total.setText(""); totalInsulin.setText(numberFormat.format(calculatedTotalInsulin) + "U"); } @@ -260,11 +260,4 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe wizardDialogDeliverButton.setVisibility(Button.GONE); } } - - private Double roundTo(Double x, Double step) { - if (x != 0d) { - return Math.round(x / step) * step; - } - return 0d; - } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/utils/Round.java b/app/src/main/java/info/nightscout/utils/Round.java new file mode 100644 index 0000000000..de4392b094 --- /dev/null +++ b/app/src/main/java/info/nightscout/utils/Round.java @@ -0,0 +1,13 @@ +package info.nightscout.utils; + +/** + * Created by mike on 20.06.2016. + */ +public class Round { + public static Double roundTo(Double x, Double step) { + if (x != 0d) { + return Math.round(x / step) * step; + } + return 0d; + } +} From cc45f74c25c6a6175b107428ccd569bc108ce0da Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 20 Jun 2016 13:36:55 +0200 Subject: [PATCH 2/5] fix remaining duration --- .../nightscout/androidaps/db/TempBasal.java | 48 ++----------------- .../VirtualPump/VirtualPumpFragment.java | 8 +--- 2 files changed, 5 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java b/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java index fd1426149a..852d74bf0a 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java @@ -110,49 +110,6 @@ public class TempBasal { return result; } - /* - public Iob calcIob() { - Iob iob = new Iob(); - - long msAgo = getMillisecondsFromStart(); - Calendar startAdjusted = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - startAdjusted.setTime(this.timeStart); - int minutes = startAdjusted.get(Calendar.MINUTE); - minutes = minutes % 4; - if (startAdjusted.get(Calendar.SECOND) > 0 && minutes == 0) { - minutes += 4; - } - startAdjusted.add(Calendar.MINUTE, minutes); - startAdjusted.set(Calendar.SECOND, 0); - - IobCalc iobCalc = new IobCalc(); - iobCalc.setTime(new Date()); - iobCalc.setAmount(-1.0d * (baseRatio - tempRatio) / 15.0d / 100.0d); - - long timeStartTime = startAdjusted.getTimeInMillis(); - Date currentTimeEnd = timeEnd; - if (currentTimeEnd == null) { - currentTimeEnd = new Date(); - if (getPlannedTimeEnd().getTime() < currentTimeEnd.getTime()) { - currentTimeEnd = getPlannedTimeEnd(); - } - } - for (long time = timeStartTime; time < currentTimeEnd.getTime(); time += 4 * 60_000) { - Date start = new Date(time); - - iobCalc.setTimeStart(start); - iob.plus(iobCalc.invoke()); - } - - if (Settings.logTempIOBCalculation) { - log.debug("TempIOB start: " + this.timeStart + " end: " + this.timeEnd + " Percent: " + this.percent + " Duration: " + this.duration + " CalcDurat: " + (int) ((currentTimeEnd.getTime() - this.timeStart.getTime()) / 1000 / 60) - + "min minAgo: " + (int) (msAgo / 1000 / 60) + " IOB: " + iob.iobContrib + " Activity: " + iob.activityContrib + " Impact: " + (-0.01d * (baseRatio - tempRatio) * ((currentTimeEnd.getTime() - this.timeStart.getTime()) / 1000 / 60) / 60) - ); - } - - return iob; - } - */ // Determine end of basal public Date getTimeEnd() { Date tempBasalTimePlannedEnd = getPlannedTimeEnd(); @@ -181,8 +138,9 @@ public class TempBasal { return new Date().getTime() - timeStart.getTime(); } - public int getRemainingMinutes() { - long remainingMin = (getTimeEnd().getTime() - new Date().getTime()) / 1000 / 60; + public int getPlannedRemainingMinutes() { + if (timeEnd != null) return 0; + long remainingMin = (getPlannedTimeEnd().getTime() - new Date().getTime()) / 1000 / 60; return (remainingMin < 0) ? 0 : (int) remainingMin; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java index 04e8dc0dc8..4f652662ab 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java @@ -17,9 +17,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.SQLException; -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.SimpleDateFormat; import java.util.Date; import info.nightscout.androidaps.Config; @@ -30,7 +27,6 @@ import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.data.Result; import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.APSResult; import info.nightscout.client.data.NSProfile; @@ -220,7 +216,7 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt public double getTempBasalRemainingMinutes() { if (!isTempBasalInProgress()) return 0; - return tempBasal.getRemainingMinutes(); + return tempBasal.getPlannedRemainingMinutes(); } @Override @@ -410,7 +406,7 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt if (isTempBasalInProgress()) { status.put("tempbasalpct", tempBasal.percent); status.put("tempbasalstart", DateUtil.toISOString(tempBasal.timeStart)); - status.put("tempbasalremainmin", tempBasal.getRemainingMinutes()); + status.put("tempbasalremainmin", tempBasal.getPlannedRemainingMinutes()); } status.put("timestamp", DateUtil.toISOString(new Date())); From 7cb0e0e5883626eba1609e6bf764e10bbb814fa3 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 20 Jun 2016 20:45:55 +0200 Subject: [PATCH 3/5] manual tempbasal dialog --- .idea/inspectionProfiles/Project_Default.xml | 6 + .../inspectionProfiles/profiles_settings.xml | 7 + .idea/misc.xml | 2 +- .../info/nightscout/androidaps/Config.java | 2 +- .../nightscout/androidaps/data/Result.java | 25 ++- ...terface.java => ConstraintsInterface.java} | 6 +- .../androidaps/interfaces/PluginBase.java | 2 +- .../ConfigBuilder/ConfigBuilderFragment.java | 182 +++++++++++++----- .../androidaps/plugins/Loop/LoopFragment.java | 40 ++-- .../Objectives/ObjectivesFragment.java | 20 +- .../Overview/Dialogs/NewTempBasalDialog.java | 112 +++++++++++ ...gFragment.java => NewTreatmentDialog.java} | 47 +++-- ...dDialogFragment.java => WizardDialog.java} | 5 +- .../plugins/Overview/OverviewFragment.java | 50 ++++- .../SafetyFragment/SafetyFragment.java | 101 +++++++--- .../VirtualPump/VirtualPumpFragment.java | 5 + .../java/info/nightscout/utils/Round.java | 12 ++ .../res/layout/configbuilder_fragment.xml | 4 +- app/src/main/res/layout/loop_fragment.xml | 4 +- app/src/main/res/layout/overview_fragment.xml | 96 +++++---- .../layout/overview_newtempbasal_fragment.xml | 108 +++++++++++ ...xml => overview_newtreatment_fragment.xml} | 0 ...gment.xml => overview_wizard_fragment.xml} | 0 app/src/main/res/values/colors.xml | 2 + app/src/main/res/values/strings.xml | 15 +- 25 files changed, 660 insertions(+), 193 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml rename app/src/main/java/info/nightscout/androidaps/interfaces/{ConstrainsInterface.java => ConstraintsInterface.java} (52%) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTempBasalDialog.java rename app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/{NewTreatmentDialogFragment.java => NewTreatmentDialog.java} (55%) rename app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/{WizardDialogFragment.java => WizardDialog.java} (98%) create mode 100644 app/src/main/res/layout/overview_newtempbasal_fragment.xml rename app/src/main/res/layout/{treatments_newtreatment_fragment.xml => overview_newtreatment_fragment.xml} (100%) rename app/src/main/res/layout/{treatments_wizard_fragment.xml => overview_wizard_fragment.xml} (100%) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000..f7b3a44868 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000000..3b312839bf --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index fbb68289f4..5d19981032 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index 20dd4a77bf..f6b6b259bd 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -19,7 +19,7 @@ public class Config { public static final boolean logPumpComm = true; public static final boolean logPrefsChange = true; public static final boolean logConfigBuilder = true; - public static final boolean logConstrainsChnages = true; + public static final boolean logConstraintsChanges = true; // Developing mode only - never turn on public static final boolean fakeGlucoseData = true; diff --git a/app/src/main/java/info/nightscout/androidaps/data/Result.java b/app/src/main/java/info/nightscout/androidaps/data/Result.java index 28661890fa..8593d4eefa 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Result.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Result.java @@ -4,23 +4,30 @@ import android.os.Parcel; import android.os.Parcelable; public class Result extends Object implements Parcelable{ - public boolean success = false; - public boolean enacted = false; + public boolean success = false; // request was processed successfully (but possible no change was needed) + public boolean enacted = false; // request was processed successfully and change has been made public String comment = ""; - public Integer duration = -1; - public Double absolute = -1d; - public Integer percent = -1; - public Double bolusDelivered = 0d; + // Result of basal change + public Integer duration = -1; // duration set [minutes] + public Double absolute = -1d; // absolute rate [U/h] , isPercent = false + public Integer percent = -1; // percent of current basal [%] (100% = current basal), isPercent = true + public boolean isPercent = false; // if true percent is used, otherwise absolute + // Result of bolus delivery + public Double bolusDelivered = 0d; // real value of delivered insulin public String log() { - return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent; + return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent + " IsPercent: " + isPercent; } public String toString() { String ret = "Success: " + success; if (enacted) { - ret += "\nEnacted: " + enacted + "\nComment: " + comment + "\nDuration: " + duration + " min\nAbsolute: " + absolute + " U/h"; + if (isPercent) { + ret += "\nEnacted: " + enacted + "\nComment: " + comment + "\nDuration: " + duration + " min\nPercent: " + percent + "%"; + } else { + ret += "\nEnacted: " + enacted + "\nComment: " + comment + "\nDuration: " + duration + " min\nAbsolute: " + absolute + " U/h"; + } } else { ret += "\nComment: " + comment; } @@ -36,6 +43,7 @@ public class Result extends Object implements Parcelable{ public void writeToParcel(Parcel dest, int flags) { dest.writeInt(success ? 1 : 0); dest.writeInt(enacted ? 1 : 0); + dest.writeInt(isPercent ? 1 : 0); dest.writeString(comment); dest.writeInt(duration); dest.writeDouble(absolute); @@ -55,6 +63,7 @@ public class Result extends Object implements Parcelable{ protected Result(Parcel in) { success = in.readInt() == 1 ? true : false; enacted = in.readInt() == 1 ? true : false; + isPercent = in.readInt() == 1 ? true : false; duration = in.readInt(); comment = in.readString(); absolute = in.readDouble(); diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java similarity index 52% rename from app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java rename to app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java index 5e429a7872..43851a1bdd 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java @@ -5,9 +5,11 @@ import info.nightscout.androidaps.plugins.APSResult; /** * Created by mike on 15.06.2016. */ -public interface ConstrainsInterface { +public interface ConstraintsInterface { boolean isAutomaticProcessingEnabled(); boolean manualConfirmationNeeded(); - APSResult applyBasalConstrains(APSResult result); + APSResult applyBasalConstraints(APSResult request); + Double applyBasalConstraints(Double absoluteRate); + Integer applyBasalConstraints(Integer percentRate); } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java index e4f3b10dcc..b4233df298 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -12,7 +12,7 @@ public interface PluginBase { int PROFILE = 4; int APS = 5; int PUMP = 6; - int CONSTRAINS = 7; + int CONSTRAINTS = 7; int LOOP = 8; public int getType(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java index f3de63c552..b55ee2e637 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java @@ -12,13 +12,11 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; -import android.widget.Toast; import org.json.JSONException; import org.json.JSONObject; @@ -39,21 +37,19 @@ import info.nightscout.androidaps.data.Result; import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; -import info.nightscout.androidaps.interfaces.APSInterface; -import info.nightscout.androidaps.interfaces.ConstrainsInterface; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.APSResult; -import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.DateUtil; -public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpInterface, ConstrainsInterface { +public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpInterface, ConstraintsInterface { private static Logger log = LoggerFactory.getLogger(ConfigBuilderFragment.class); private static final String PREFS_NAME = "Settings"; @@ -64,7 +60,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI ListView tempsListView; ListView profileListView; ListView apsListView; - ListView constrainsListView; + ListView constraintsListView; ListView generalListView; PluginCustomAdapter pumpDataAdapter = null; @@ -73,7 +69,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI PluginCustomAdapter tempsDataAdapter = null; PluginCustomAdapter profileDataAdapter = null; PluginCustomAdapter apsDataAdapter = null; - PluginCustomAdapter constrainsDataAdapter = null; + PluginCustomAdapter constraintsDataAdapter = null; PluginCustomAdapter generalDataAdapter = null; @@ -118,7 +114,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI tempsListView = (ListView) view.findViewById(R.id.configbuilder_tempslistview); profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview); apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview); - constrainsListView = (ListView) view.findViewById(R.id.configbuilder_constrainslistview); + constraintsListView = (ListView) view.findViewById(R.id.configbuilder_constraintslistview); generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview); setViews(); @@ -144,9 +140,9 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.APS)); apsListView.setAdapter(apsDataAdapter); setListViewHeightBasedOnChildren(apsListView); - constrainsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINS)); - constrainsListView.setAdapter(constrainsDataAdapter); - setListViewHeightBasedOnChildren(constrainsListView); + constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS)); + constraintsListView.setAdapter(constraintsDataAdapter); + setListViewHeightBasedOnChildren(constraintsListView); generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.GENERAL)); generalListView.setAdapter(generalDataAdapter); setListViewHeightBasedOnChildren(generalListView); @@ -200,7 +196,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI /* * Pump interface * - * Config builder return itself as a pump and check constrains before it passes command to pump driver + * Config builder return itself as a pump and check constraints before it passes command to pump driver */ @Nullable public PumpInterface getActivePump() { @@ -261,7 +257,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI if (insulin > maxbolus || carbs > maxcarbs) { Result failResult = new Result(); failResult.success = false; - failResult.comment = MainApp.instance().getString(R.string.constrains_violation); + failResult.comment = MainApp.instance().getString(R.string.constraints_violation); return failResult; } Result result = activePump.deliverTreatment(insulin, carbs); @@ -283,29 +279,55 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI return result; } + /** + * apply constraints, set temp based on absolute valus and expecting absolute result + * + * @param absoluteRate + * @param durationInMinutes + * @return + */ @Override public Result setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { - // TODO: constrains here - return activePump.setTempBasalAbsolute(absoluteRate, durationInMinutes); + Double rateAfterConstraints = applyBasalConstraints(absoluteRate); + Result result = activePump.setTempBasalAbsolute(rateAfterConstraints, durationInMinutes); + if (result.enacted) { + uploadTempBasalStartAbsolute(result.absolute, result.duration); + MainApp.bus().post(new EventTempBasalChange()); + } + return result; } + /** + * apply constraints, set temp based on percent and expecting result in percent + * + * @param percent 0 ... 100 ... + * @param durationInMinutes + * @return result + */ @Override public Result setTempBasalPercent(Integer percent, Integer durationInMinutes) { - // TODO: constrains here - return activePump.setTempBasalPercent(percent, durationInMinutes); + Integer percentAfterConstraints = applyBasalConstraints(percent); + Result result = activePump.setTempBasalPercent(percentAfterConstraints, durationInMinutes); + if (result.enacted) { + uploadTempBasalStartPercent(result.percent, result.duration); + MainApp.bus().post(new EventTempBasalChange()); + } + return result; } @Override public Result setExtendedBolus(Double insulin, Integer durationInMinutes) { - // TODO: constrains here + // TODO: constraints here return activePump.setExtendedBolus(insulin, durationInMinutes); } @Override public Result cancelTempBasal() { Result result = activePump.cancelTempBasal(); - if (result.enacted) + if (result.enacted) { uploadTempBasalEnd(); + MainApp.bus().post(new EventTempBasalChange()); + } return result; } @@ -314,11 +336,32 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI return activePump.cancelExtendedBolus(); } + /** + * expect absolute request and allow both absolute and percent response based on pump capabilities + * @param request + * @return + */ @Override public Result applyAPSRequest(APSResult request) { - Result result = activePump.applyAPSRequest(request); - if (result.enacted) - uploadTempBasalStart(result.absolute, result.duration); + Double rateAfterConstraints = applyBasalConstraints(request.rate); + request.rate = rateAfterConstraints; + Result result = activePump.applyAPSRequest(request); + if (result.enacted) { + if (result.isPercent) { + if (result.percent == 0) { + uploadTempBasalEnd(); + } else { + uploadTempBasalStartPercent(result.percent, result.duration); + } + } else { + if (result.absolute == 0d) { + uploadTempBasalEnd(); + } else { + uploadTempBasalStartAbsolute(result.absolute, result.duration); + } + } + MainApp.bus().post(new EventTempBasalChange()); + } return result; } @@ -405,8 +448,8 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI if (pluginList.size() < 2) holder.checkboxEnabled.setEnabled(false); - // Constrains cannot be disabled - if (type == PluginBase.CONSTRAINS) + // Constraints cannot be disabled + if (type == PluginBase.CONSTRAINTS) holder.checkboxEnabled.setEnabled(false); // Hide disabled profiles by default @@ -446,7 +489,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI // Multiple selection allowed case PluginBase.APS: case PluginBase.GENERAL: - case PluginBase.CONSTRAINS: + case PluginBase.CONSTRAINTS: break; // Single selection allowed case PluginBase.PROFILE: @@ -478,7 +521,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI // Multiple selection allowed case PluginBase.APS: case PluginBase.GENERAL: - case PluginBase.CONSTRAINS: + case PluginBase.CONSTRAINTS: break; // Single selection allowed case PluginBase.PROFILE: @@ -607,15 +650,15 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI } /** - * Constrains interface + * Constraints interface **/ @Override public boolean isAutomaticProcessingEnabled() { boolean result = true; - ArrayList constrainsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINS); - for (PluginBase p : constrainsPlugins) { - ConstrainsInterface constrain = (ConstrainsInterface) p; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled()) continue; result = result && constrain.isAutomaticProcessingEnabled(); } @@ -626,9 +669,9 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI public boolean manualConfirmationNeeded() { boolean result = false; - ArrayList constrainsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINS); - for (PluginBase p : constrainsPlugins) { - ConstrainsInterface constrain = (ConstrainsInterface) p; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled()) continue; result = result || constrain.manualConfirmationNeeded(); } @@ -636,29 +679,72 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI } @Override - public APSResult applyBasalConstrains(APSResult result) { - ArrayList constrainsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINS); - for (PluginBase p : constrainsPlugins) { - ConstrainsInterface constrain = (ConstrainsInterface) p; + public APSResult applyBasalConstraints(APSResult result) { + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled()) continue; - constrain.applyBasalConstrains(result); + constrain.applyBasalConstraints(result); } return result; } - public static void uploadTempBasalStart(Double absolute, double durationInMinutes) { - try { - //SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - //boolean useAbsoluteForUpload = sp.getBoolean("ns_sync_use_absolute", false); + @Override + public Double applyBasalConstraints(Double absoluteRate) { + Double rateAfterConstrain = absoluteRate; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled()) continue; + rateAfterConstrain = constrain.applyBasalConstraints(rateAfterConstrain); + } + return rateAfterConstrain; + } + @Override + public Integer applyBasalConstraints(Integer percentRate) { + Integer rateAfterConstrain = percentRate; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled()) continue; + rateAfterConstrain = constrain.applyBasalConstraints(rateAfterConstrain); + } + return rateAfterConstrain; + } + + public static void uploadTempBasalStartAbsolute(Double absolute, double durationInMinutes) { + try { Context context = MainApp.instance().getApplicationContext(); JSONObject data = new JSONObject(); data.put("eventType", "Temp Basal"); data.put("duration", durationInMinutes); - //if (useAbsoluteForUpload && absolute != null) - data.put("absolute", absolute); - //else - // data.put("percent", percent - 100); + data.put("absolute", absolute); + data.put("created_at", DateUtil.toISOString(new Date())); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + List q = context.getPackageManager().queryBroadcastReceivers(intent, 0); + if (q.size() < 1) { + log.error("DBADD No receivers"); + } else log.debug("DBADD dbAdd " + q.size() + " receivers " + data.toString()); + } catch (JSONException e) { + } + } + + public static void uploadTempBasalStartPercent(Integer percent, double durationInMinutes) { + try { + Context context = MainApp.instance().getApplicationContext(); + JSONObject data = new JSONObject(); + data.put("eventType", "Temp Basal"); + data.put("duration", durationInMinutes); + data.put("percent", percent - 100); data.put("created_at", DateUtil.toISOString(new Date())); data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); Bundle bundle = new Bundle(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java index 5ab9eb5501..4774884322 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java @@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.Loop; import android.app.Activity; -import android.content.DialogInterface; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -10,7 +9,6 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; @@ -29,7 +27,7 @@ import info.nightscout.androidaps.data.Result; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.APSInterface; -import info.nightscout.androidaps.interfaces.ConstrainsInterface; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.APSResult; @@ -42,14 +40,14 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug TextView lastEnactView; TextView sourceView; TextView requestView; - TextView constrainsProcessedView; + TextView constraintsProcessedView; TextView setByPumpView; boolean confirmed; class LastRun implements Parcelable { public APSResult request = null; - public APSResult constrainsProcessed = null; + public APSResult constraintsProcessed = null; public Result setByPump = null; public String source = null; public Date lastAPSRun = null; @@ -63,11 +61,11 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug @Override public void writeToParcel(Parcel dest, int flags) { dest.writeParcelable(request, 0); - dest.writeParcelable(constrainsProcessed, 0); + dest.writeParcelable(constraintsProcessed, 0); dest.writeParcelable(setByPump, 0); dest.writeString(source); dest.writeLong(lastAPSRun.getTime()); - dest.writeLong(lastEnact.getTime()); + dest.writeLong(lastEnact!= null ? lastEnact.getTime(): 0l); } public final Parcelable.Creator CREATOR = new Parcelable.Creator() { @@ -82,7 +80,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug private LastRun(Parcel in) { request = in.readParcelable(APSResult.class.getClassLoader()); - constrainsProcessed = in.readParcelable(APSResult.class.getClassLoader()); + constraintsProcessed = in.readParcelable(APSResult.class.getClassLoader()); setByPump = in.readParcelable(Result.class.getClassLoader()); source = in.readString(); lastAPSRun = new Date(in.readLong()); @@ -157,7 +155,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug lastEnactView = (TextView) view.findViewById(R.id.loop_lastenact); sourceView = (TextView) view.findViewById(R.id.loop_source); requestView = (TextView) view.findViewById(R.id.loop_request); - constrainsProcessedView = (TextView) view.findViewById(R.id.loop_constrainsprocessed); + constraintsProcessedView = (TextView) view.findViewById(R.id.loop_constraintsprocessed); setByPumpView = (TextView) view.findViewById(R.id.loop_setbypump); runNowButton = (Button) view.findViewById(R.id.loop_run); runNowButton.setOnClickListener(this); @@ -210,19 +208,19 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug @Subscribe public void onStatusEvent(final EventNewBG ev) { - ConstrainsInterface constrainsInterface = MainActivity.getConfigBuilder(); - if (constrainsInterface.isAutomaticProcessingEnabled()) { + ConstraintsInterface constraintsInterface = MainActivity.getConfigBuilder(); + if (constraintsInterface.isAutomaticProcessingEnabled()) { invoke(); updateGUI(); } } private void invoke() { - ConstrainsInterface constrainsInterface = MainActivity.getConfigBuilder(); + ConstraintsInterface constraintsInterface = MainActivity.getConfigBuilder(); PumpInterface pumpInterface = MainActivity.getConfigBuilder().getActivePump(); APSResult result = null; - if (constrainsInterface == null || pumpInterface == null || !isEnabled()) + if (constraintsInterface == null || pumpInterface == null || !isEnabled()) return; APSInterface usedAPS = null; @@ -255,7 +253,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug } confirmed = false; - if (constrainsInterface.manualConfirmationNeeded()) { + if (constraintsInterface.manualConfirmationNeeded()) { // TODO: user notification here confirmed = true; } else { @@ -263,15 +261,15 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug } // check rate for constrais - APSResult resultAfterConstrains = result.clone(); + APSResult resultAfterConstraints = result.clone(); if (result.changeRequested) { - constrainsInterface.applyBasalConstrains(resultAfterConstrains); - Result applyResult = pumpInterface.applyAPSRequest(resultAfterConstrains); + constraintsInterface.applyBasalConstraints(resultAfterConstraints); + Result applyResult = pumpInterface.applyAPSRequest(resultAfterConstraints); Date lastEnact = lastRun != null ? lastRun.lastEnact : new Date(0, 0, 0); lastRun = new LastRun(); lastRun.request = result; - lastRun.constrainsProcessed = resultAfterConstrains; + lastRun.constraintsProcessed = resultAfterConstraints; lastRun.setByPump = applyResult; lastRun.source = ((PluginBase) usedAPS).getName(); lastRun.lastAPSRun = new Date(); @@ -282,7 +280,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug } else { if (lastRun == null) lastRun = new LastRun(); lastRun.request = result; - lastRun.constrainsProcessed = resultAfterConstrains; + lastRun.constraintsProcessed = resultAfterConstraints; lastRun.setByPump = null; lastRun.source = null; lastRun.lastAPSRun = new Date(); @@ -298,7 +296,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug public void run() { if (lastRun != null) { requestView.setText(lastRun.request != null ? lastRun.request.toString() : ""); - constrainsProcessedView.setText(lastRun.constrainsProcessed != null ? lastRun.constrainsProcessed.toString() : ""); + constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toString() : ""); setByPumpView.setText(lastRun.setByPump != null ? lastRun.setByPump.toString() : ""); sourceView.setText(lastRun.source != null ? lastRun.source.toString() : ""); lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : ""); @@ -315,7 +313,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug @Override public void run() { requestView.setText(""); - constrainsProcessedView.setText(""); + constraintsProcessedView.setText(""); setByPumpView.setText(""); sourceView.setText(""); lastRunView.setText(""); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java index bfc301dab8..583e0bc927 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java @@ -25,11 +25,11 @@ import java.util.List; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.ConstrainsInterface; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.APSResult; -public class ObjectivesFragment extends Fragment implements View.OnClickListener, PluginBase, ConstrainsInterface { +public class ObjectivesFragment extends Fragment implements View.OnClickListener, PluginBase, ConstraintsInterface { private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class); RecyclerView recyclerView; @@ -42,7 +42,7 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener @Override public int getType() { - return PluginBase.CONSTRAINS; + return PluginBase.CONSTRAINTS; } @Override @@ -314,7 +314,7 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener } /** - * Constrains interface + * Constraints interface **/ @Override public boolean isAutomaticProcessingEnabled() { @@ -327,8 +327,18 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener } @Override - public APSResult applyBasalConstrains(APSResult result) { + public APSResult applyBasalConstraints(APSResult result) { return result; } + @Override + public Double applyBasalConstraints(Double absoluteRate) { + return absoluteRate; + } + + @Override + public Integer applyBasalConstraints(Integer percentRate) { + return percentRate; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTempBasalDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTempBasalDialog.java new file mode 100644 index 0000000000..615a174317 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTempBasalDialog.java @@ -0,0 +1,112 @@ +package info.nightscout.androidaps.plugins.Overview.Dialogs; + +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RadioButton; + +import info.nightscout.androidaps.MainActivity; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Result; +import info.nightscout.androidaps.interfaces.PumpInterface; + +public class NewTempBasalDialog extends DialogFragment implements View.OnClickListener { + + Button okButton; + EditText basalEdit; + RadioButton percentRadio; + RadioButton absoluteRadio; + RadioButton h05Radio; + RadioButton h10Radio; + RadioButton h20Radio; + RadioButton h30Radio; + RadioButton h40Radio; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.overview_newtempbasal_fragment, container, false); + okButton = (Button) view.findViewById(R.id.overview_newtempbasal_okbutton); + basalEdit = (EditText) view.findViewById(R.id.overview_newtempbasal_basal); + percentRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_percent); + absoluteRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_absolute); + h05Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_05h); + h10Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_1h); + h20Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_2h); + h30Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_3h); + h40Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_4h); + + okButton.setOnClickListener(this); + return view; + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.overview_newtempbasal_okbutton: + try { + int basalPercent = 100; + String basalText = basalEdit.getText().toString().replace(",", "."); + Double basal = Double.parseDouble(!basalText.equals("") ? basalText : "0"); + final boolean setAsPercent = percentRadio.isChecked(); + int durationInMinutes = 30; + if (h10Radio.isChecked()) durationInMinutes = 60; + if (h20Radio.isChecked()) durationInMinutes = 120; + if (h30Radio.isChecked()) durationInMinutes = 180; + if (h40Radio.isChecked()) durationInMinutes = 240; + + String confirmMessage = getString(R.string.setbasalquestion); + if (setAsPercent) { + basalPercent = MainActivity.getConfigBuilder().applyBasalConstraints(basal.intValue()); + confirmMessage += " " + basalPercent + "% ?"; + if (basalPercent != basal.intValue()) + confirmMessage += "\n" + getString(R.string.constraintapllied); + } else { + Double basalAfterConstraint = MainActivity.getConfigBuilder().applyBasalConstraints(basal); + confirmMessage += " " + basalAfterConstraint + " U/h ?"; + if (basalAfterConstraint != basal) + confirmMessage += "\n" + getString(R.string.constraintapllied); + basal = basalAfterConstraint; + } + + final int finalBasalPercent = basalPercent; + final Double finalBasal = basal; + final int finalDurationInMinutes = durationInMinutes; + + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.confirmation)); + builder.setMessage(confirmMessage); + builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + PumpInterface pump = MainActivity.getConfigBuilder().getActivePump(); + Result result; + if (setAsPercent) { + result = pump.setTempBasalPercent(finalBasalPercent, finalDurationInMinutes); + } else { + result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes); + } + if (!result.success) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(getContext().getString(R.string.treatmentdeliveryerror)); + builder.setMessage(result.comment); + builder.setPositiveButton(getContext().getString(R.string.ok), null); + builder.show(); + } + } + }); + builder.setNegativeButton(getString(R.string.cancel), null); + builder.show(); + dismiss(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialogFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java similarity index 55% rename from app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialogFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java index 23439b4c42..9950f4949c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialogFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java @@ -1,7 +1,5 @@ package info.nightscout.androidaps.plugins.Overview.Dialogs; -import android.content.DialogInterface; -import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; @@ -15,10 +13,9 @@ import android.widget.TextView; import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.Services.Intents; import info.nightscout.androidaps.data.Result; -public class NewTreatmentDialogFragment extends DialogFragment implements OnClickListener { +public class NewTreatmentDialog extends DialogFragment implements OnClickListener { Button deliverButton; TextView insulin; @@ -27,7 +24,7 @@ public class NewTreatmentDialogFragment extends DialogFragment implements OnClic @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.treatments_newtreatment_fragment, null, false); + View view = inflater.inflate(R.layout.overview_newtreatment_fragment, null, false); deliverButton = (Button) view.findViewById(R.id.treatments_newtreatment_deliverbutton); @@ -48,26 +45,28 @@ public class NewTreatmentDialogFragment extends DialogFragment implements OnClic Double maxbolus = Double.parseDouble(SP.getString("treatmentssafety_maxbolus", "3")); Double maxcarbs = Double.parseDouble(SP.getString("treatmentssafety_maxcarbs", "48")); - - String insulinText = this.insulin.getText().toString().replace(",", "."); - String carbsText = this.carbs.getText().toString().replace(",", "."); - Double insulin = Double.parseDouble(!insulinText.equals("") ? this.insulin.getText().toString() : "0"); - Double carbs = Double.parseDouble(!carbsText.equals("") ? this.carbs.getText().toString() : "0"); - if (insulin > maxbolus) { - this.insulin.setText(""); - } else if (carbs > maxcarbs) { - this.carbs.setText(""); - } else if (insulin > 0d || carbs > 0d) { - dismiss(); - Result result = MainActivity.getConfigBuilder().getActivePump().deliverTreatment(insulin, carbs); - if (!result.success) { - AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); - builder.setTitle(this.getContext().getString(R.string.bolusdeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(this.getContext().getString(R.string.ok), null); - builder.show(); - + try { + String insulinText = this.insulin.getText().toString().replace(",", "."); + String carbsText = this.carbs.getText().toString().replace(",", "."); + Double insulin = Double.parseDouble(!insulinText.equals("") ? insulinText : "0"); + Double carbs = Double.parseDouble(!carbsText.equals("") ? carbsText : "0"); + if (insulin > maxbolus) { + this.insulin.setText(""); + } else if (carbs > maxcarbs) { + this.carbs.setText(""); + } else if (insulin > 0d || carbs > 0d) { + dismiss(); + Result result = MainActivity.getConfigBuilder().getActivePump().deliverTreatment(insulin, carbs); + if (!result.success) { + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.treatmentdeliveryerror)); + builder.setMessage(result.comment); + builder.setPositiveButton(this.getContext().getString(R.string.ok), null); + builder.show(); + } } + } catch (Exception e) { + e.printStackTrace(); } break; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index 25df14a849..efc2c03081 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -15,7 +15,6 @@ import android.widget.TextView; import java.text.DecimalFormat; -import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -26,7 +25,7 @@ import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.*; -public class WizardDialogFragment extends DialogFragment implements OnClickListener { +public class WizardDialog extends DialogFragment implements OnClickListener { Button wizardDialogDeliverButton; TextView correctionInput; @@ -69,7 +68,7 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.treatments_wizard_fragment, null, false); + View view = inflater.inflate(R.layout.overview_wizard_fragment, null, false); wizardDialogDeliverButton = (Button) view.findViewById(R.id.treatments_wizard_deliverButton); wizardDialogDeliverButton.setOnClickListener(this); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index b090788f0d..0e76e82461 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -38,10 +38,12 @@ import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialogFragment; -import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialogFragment; +import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTempBasalDialog; +import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog; +import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; import info.nightscout.client.data.NSProfile; @@ -53,9 +55,13 @@ public class OverviewFragment extends Fragment implements PluginBase { TextView deltaView; GraphView bgGraph; + LinearLayout cancelTempLayout; + LinearLayout setTempLayout; Button cancelTempButton; Button treatmentButton; Button wizardButton; + Button setTempButton; + Button setExtenedButton; boolean visibleNow = false; Handler loopHandler = new Handler(); @@ -141,12 +147,16 @@ public class OverviewFragment extends Fragment implements PluginBase { cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp); treatmentButton = (Button) view.findViewById(R.id.overview_treatment); wizardButton = (Button) view.findViewById(R.id.overview_wizard); + setTempButton = (Button) view.findViewById(R.id.overview_settempbasal); + cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp); + setTempLayout = (LinearLayout) view.findViewById(R.id.overview_settemplayout); + cancelTempLayout = (LinearLayout) view.findViewById(R.id.overview_canceltemplayout); treatmentButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { FragmentManager manager = getFragmentManager(); - NewTreatmentDialogFragment treatmentDialogFragment = new NewTreatmentDialogFragment(); + NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog(); treatmentDialogFragment.show(manager, "TreatmentDialog"); } }); @@ -155,8 +165,8 @@ public class OverviewFragment extends Fragment implements PluginBase { @Override public void onClick(View view) { FragmentManager manager = getFragmentManager(); - WizardDialogFragment wizardDialogFragment = new WizardDialogFragment(); - wizardDialogFragment.show(manager, "WizardDialog"); + WizardDialog wizardDialog = new WizardDialog(); + wizardDialog.show(manager, "WizardDialog"); } }); @@ -170,6 +180,16 @@ public class OverviewFragment extends Fragment implements PluginBase { } } }); + + setTempButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + FragmentManager manager = getFragmentManager(); + NewTempBasalDialog newTempDialog = new NewTempBasalDialog(); + newTempDialog.show(manager, "NewTempDialog"); + } + }); + updateGUI(); return view; } @@ -183,6 +203,20 @@ public class OverviewFragment extends Fragment implements PluginBase { MainApp.bus().register(this); } + @Subscribe + public void onStatusEvent(final EventTreatmentChange ev) { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + updateGUI(); + } + }); + else + log.debug("EventTreatmentChange: Activity is null"); + } + @Subscribe public void onStatusEvent(final EventTempBasalChange ev) { Activity activity = getActivity(); @@ -243,10 +277,12 @@ public class OverviewFragment extends Fragment implements PluginBase { if (pump.isTempBasalInProgress()) { TempBasal activeTemp = pump.getTempBasal(); - cancelTempButton.setVisibility(View.VISIBLE); + cancelTempLayout.setVisibility(View.VISIBLE); + setTempLayout.setVisibility(View.GONE); cancelTempButton.setText(MainApp.instance().getString(R.string.cancel) + ": " + activeTemp.toString()); } else { - cancelTempButton.setVisibility(View.INVISIBLE); + cancelTempLayout.setVisibility(View.GONE); + setTempLayout.setVisibility(View.VISIBLE); } // **** BG value **** diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java index 70ec045682..0a11cbdd41 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java @@ -2,17 +2,8 @@ package info.nightscout.androidaps.plugins.SafetyFragment; import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.EditText; -import android.widget.TextView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,19 +12,19 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.ConstrainsInterface; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.plugins.APSResult; import info.nightscout.client.data.NSProfile; +import info.nightscout.utils.Round; -public class SafetyFragment extends Fragment implements PluginBase, ConstrainsInterface { +public class SafetyFragment extends Fragment implements PluginBase, ConstraintsInterface { private static Logger log = LoggerFactory.getLogger(SafetyFragment.class); @Override public int getType() { - return PluginBase.CONSTRAINS; + return PluginBase.CONSTRAINTS; } @Override @@ -71,7 +62,7 @@ public class SafetyFragment extends Fragment implements PluginBase, ConstrainsIn } /** - * Constrains interface + * Constraints interface **/ @Override public boolean isAutomaticProcessingEnabled() { @@ -84,33 +75,83 @@ public class SafetyFragment extends Fragment implements PluginBase, ConstrainsIn } @Override - public APSResult applyBasalConstrains(APSResult result) { + public APSResult applyBasalConstraints(APSResult result) { + result.rate = applyBasalConstraints(result.rate); + return result; + } + + @Override + public Double applyBasalConstraints(Double absoluteRate) { SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); Double maxBasal = Double.parseDouble(SP.getString("openapsma_max_basal", "1").replace(",", ".")); NSProfile profile = MainActivity.getConfigBuilder().getActiveProfile().getProfile(); - if (result.rate < 0) result.rate = 0; + if (absoluteRate < 0) absoluteRate = 0d; Integer maxBasalMult = 4; Integer maxBasalFromDaily = 3; // Check percentRate but absolute rate too, because we know real current basal in pump - Double origRate = result.rate; - if (result.rate > maxBasal) { - result.rate = maxBasal; - if (Config.logConstrainsChnages) - log.debug("Limiting rate " + origRate + " by maxBasal preference to " + result.rate + "U/h"); + Double origRate = absoluteRate; + if (absoluteRate > maxBasal) { + absoluteRate = maxBasal; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h"); } - if (result.rate > maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight())) { - result.rate = Math.floor(maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight()) * 100) / 100; - if (Config.logConstrainsChnages) - log.debug("Limiting rate " + origRate + " by maxBasalMult to " + result.rate + "U/h"); + if (absoluteRate > maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight())) { + absoluteRate = Math.floor(maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight()) * 100) / 100; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h"); } - if (result.rate > profile.getMaxDailyBasal() * maxBasalFromDaily) { - result.rate = profile.getMaxDailyBasal() * maxBasalFromDaily; - if (Config.logConstrainsChnages) - log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + result.rate + "U/h"); + if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) { + absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h"); } - return result; + return absoluteRate; + } + + @Override + public Integer applyBasalConstraints(Integer percentRate) { + SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); + Double maxBasal = Double.parseDouble(SP.getString("openapsma_max_basal", "1").replace(",", ".")); + + NSProfile profile = MainActivity.getConfigBuilder().getActiveProfile().getProfile(); + Double currentBasal = profile.getBasal(profile.secondsFromMidnight()); + + Double absoluteRate = currentBasal * ((double) percentRate / 100); + + if (Config.logConstraintsChanges) + log.debug("Percent rate " + percentRate + "% recalculated to " + absoluteRate + "U/h with current basal " + currentBasal + "U/h"); + + if (absoluteRate < 0) absoluteRate = 0d; + + Integer maxBasalMult = 4; + Integer maxBasalFromDaily = 3; + // Check percentRate but absolute rate too, because we know real current basal in pump + Double origRate = absoluteRate; + if (absoluteRate > maxBasal) { + absoluteRate = maxBasal; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h"); + } + if (absoluteRate > maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight())) { + absoluteRate = Math.floor(maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight()) * 100) / 100; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h"); + } + if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) { + absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h"); + } + + Integer percentRateAfterConst = new Double(absoluteRate / currentBasal * 100).intValue(); + if (percentRateAfterConst < 100) Round.ceilTo(absoluteRate, 10d).intValue(); + else Round.floorTo(absoluteRate, 10d).intValue(); + + if (Config.logConstraintsChanges) + log.debug("Recalculated percent rate " + percentRate + "% to " + percentRateAfterConst + "%"); + return percentRateAfterConst; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java index 4f652662ab..1e43f5b0ba 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java @@ -278,6 +278,7 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt result.success = true; result.enacted = true; result.percent = percent; + result.isPercent = true; result.duration = durationInMinutes; result.comment = getString(R.string.virtualpump_resultok); try { @@ -374,6 +375,8 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt if (isTempBasalInProgress()) { if (request.rate == getTempBasalAbsoluteRate()) { Result noChange = new Result(); + noChange.absolute = request.rate; + noChange.duration = tempBasal.getPlannedRemainingMinutes(); noChange.enacted = false; noChange.comment = "Temp basal set correctly"; noChange.success = true; @@ -384,6 +387,8 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt } if (request.rate == getBaseBasalRate()) { Result noChange = new Result(); + noChange.absolute = request.rate; + noChange.duration = 0; noChange.enacted = false; noChange.comment = "Basal set correctly"; noChange.success = true; diff --git a/app/src/main/java/info/nightscout/utils/Round.java b/app/src/main/java/info/nightscout/utils/Round.java index de4392b094..f1fe3e0df6 100644 --- a/app/src/main/java/info/nightscout/utils/Round.java +++ b/app/src/main/java/info/nightscout/utils/Round.java @@ -10,4 +10,16 @@ public class Round { } return 0d; } + public static Double floorTo(Double x, Double step) { + if (x != 0d) { + return Math.floor(x / step) * step; + } + return 0d; + } + public static Double ceilTo(Double x, Double step) { + if (x != 0d) { + return Math.ceil(x / step) * step; + } + return 0d; + } } diff --git a/app/src/main/res/layout/configbuilder_fragment.xml b/app/src/main/res/layout/configbuilder_fragment.xml index e40cd070e0..4c3140ddf3 100644 --- a/app/src/main/res/layout/configbuilder_fragment.xml +++ b/app/src/main/res/layout/configbuilder_fragment.xml @@ -116,12 +116,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" - android:text="@string/configbuilder_constrains" + android:text="@string/configbuilder_constraints" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> + android:layout_height="match_parent" + android:orientation="vertical"> + android:layout_height="wrap_content" + android:orientation="horizontal"> + android:textSize="60dp" /> + android:layout_marginTop="10dp" + android:orientation="vertical"> - - + + + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="10dp" + android:textAppearance="?android:attr/textAppearanceMedium" /> @@ -52,44 +52,72 @@ android:layout_height="200dip" /> + android:layout_height="wrap_content" + android:orientation="horizontal">