From 09e41061828895824a7687b371645987ef2b6195 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 16 Jun 2019 09:00:47 +0200 Subject: [PATCH 1/4] BolusWizard -> kt, code consolidation --- .../androidaps/data/QuickWizardEntry.java | 20 +- .../general/overview/OverviewFragment.java | 144 +------- .../overview/dialogs/WizardDialog.java | 238 ++---------- .../general/wear/ActionStringHandler.java | 43 +-- .../androidaps/utils/BolusWizard.java | 183 ---------- .../androidaps/utils/BolusWizard.kt | 342 ++++++++++++++++++ .../androidaps/utils/StringUtils.java | 7 + app/src/main/res/values/strings.xml | 2 + app/src/test/java/info/AAPSMocker.java | 7 +- .../androidaps/utils/BolusWizardTest.java | 39 +- 10 files changed, 456 insertions(+), 569 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.java create mode 100644 app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java index 0bfcbb1002..c3c367aee8 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java @@ -50,7 +50,7 @@ public class QuickWizardEntry { useTemptarget: 0 } */ - public QuickWizardEntry() { + QuickWizardEntry() { String emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}"; try { storage = new JSONObject(emptyData); @@ -60,18 +60,17 @@ public class QuickWizardEntry { position = -1; } - public QuickWizardEntry(JSONObject entry, int position) { + QuickWizardEntry(JSONObject entry, int position) { storage = entry; this.position = position; } - public Boolean isActive() { + Boolean isActive() { return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo(); } - public BolusWizard doCalc(Profile profile, TempTarget tempTarget, BgReading lastBG, boolean _synchronized) { - BolusWizard wizard = new BolusWizard(); - + public BolusWizard doCalc(Profile profile, String profileName, BgReading lastBG, boolean _synchronized) { + final TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(); //BG double bg = 0; if (lastBG != null && useBG() == YES) { @@ -86,11 +85,6 @@ public class QuickWizardEntry { cob = cobInfo.displayCob; } - // Temp target - if (useTempTarget() == NO) { - tempTarget = null; - } - // Bolus IOB boolean bolusIOB = false; if (useBolusIOB() == YES) { @@ -130,7 +124,9 @@ public class QuickWizardEntry { trend = true; } - wizard.doCalc(profile, tempTarget, carbs(), cob, bg, 0d, bolusIOB, basalIOB, superBolus, trend); + BolusWizard wizard = new BolusWizard(profile, profileName, tempTarget, carbs(), cob, bg, 0d, 100, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend); + wizard.doCalc(); + wizard.setNotes("QuickWizard"); return wizard; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java index ee19d09f99..01e6eec299 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java @@ -37,12 +37,9 @@ import android.widget.TextView; import com.jjoe64.graphview.GraphView; import com.squareup.otto.Subscribe; -import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.text.DecimalFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; @@ -55,7 +52,6 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.QuickWizardEntry; @@ -95,7 +91,6 @@ import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity; import info.nightscout.androidaps.plugins.general.overview.dialogs.CalibrationDialog; -import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity; import info.nightscout.androidaps.plugins.general.overview.dialogs.NewCarbsDialog; import info.nightscout.androidaps.plugins.general.overview.dialogs.NewInsulinDialog; import info.nightscout.androidaps.plugins.general.overview.dialogs.NewTreatmentDialog; @@ -781,141 +776,25 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, void onClickQuickwizard() { final BgReading actualBg = DatabaseHelper.actualBg(); final Profile profile = ProfileFunctions.getInstance().getProfile(); - final TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(); + final String profileName = ProfileFunctions.getInstance().getProfileName(); + final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); final QuickWizardEntry quickWizardEntry = OverviewPlugin.getPlugin().quickWizard.getActive(); - if (quickWizardEntry != null && actualBg != null && profile != null) { + if (quickWizardEntry != null && actualBg != null && profile != null && pump != null) { quickWizardButton.setVisibility(View.VISIBLE); - final BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, actualBg, true); + final BolusWizard wizard = quickWizardEntry.doCalc(profile, profileName, actualBg, true); - final JSONObject boluscalcJSON = new JSONObject(); - try { - boluscalcJSON.put("eventTime", DateUtil.toISOString(new Date())); - boluscalcJSON.put("targetBGLow", wizard.targetBGLow); - boluscalcJSON.put("targetBGHigh", wizard.targetBGHigh); - boluscalcJSON.put("isf", wizard.sens); - boluscalcJSON.put("ic", wizard.ic); - boluscalcJSON.put("iob", -(wizard.insulingFromBolusIOB + wizard.insulingFromBasalsIOB)); - boluscalcJSON.put("bolusiobused", true); - boluscalcJSON.put("basaliobused", true); - boluscalcJSON.put("bg", actualBg.valueToUnits(profile.getUnits())); - boluscalcJSON.put("insulinbg", wizard.insulinFromBG); - boluscalcJSON.put("insulinbgused", true); - boluscalcJSON.put("bgdiff", wizard.bgDiff); - boluscalcJSON.put("insulincarbs", wizard.insulinFromCarbs); - boluscalcJSON.put("carbs", quickWizardEntry.carbs()); - boluscalcJSON.put("othercorrection", 0d); - boluscalcJSON.put("insulintrend", wizard.insulinFromTrend); - boluscalcJSON.put("insulin", wizard.calculatedTotalInsulin); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - if (wizard.calculatedTotalInsulin > 0d && quickWizardEntry.carbs() > 0d) { - DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); - String confirmMessage = MainApp.gs(R.string.entertreatmentquestion); - - Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(wizard.calculatedTotalInsulin)).value(); + if (wizard.getCalculatedTotalInsulin() > 0d && quickWizardEntry.carbs() > 0d) { Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(quickWizardEntry.carbs())).value(); - confirmMessage += "\n" + MainApp.gs(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U"; - confirmMessage += "\n" + MainApp.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"; - - if (Math.abs(insulinAfterConstraints - wizard.calculatedTotalInsulin) >= 0.01 || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) { - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - builder.setTitle(MainApp.gs(R.string.treatmentdeliveryerror)); - builder.setMessage(MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput)); - builder.setPositiveButton(MainApp.gs(R.string.ok), null); - builder.show(); + if (Math.abs(wizard.getInsulinAfterConstraints() - wizard.getCalculatedTotalInsulin()) >= pump.getPumpDescription().pumpType.determineCorrectBolusSize(wizard.getInsulinAfterConstraints()) || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) { + OKDialog.show(getContext(), MainApp.gs(R.string.treatmentdeliveryerror), MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput), null); return; } - final Double finalInsulinAfterConstraints = insulinAfterConstraints; - final Integer finalCarbsAfterConstraints = carbsAfterConstraints; - final Context context = getContext(); - final AlertDialog.Builder builder = new AlertDialog.Builder(context); - accepted = false; - builder.setTitle(MainApp.gs(R.string.confirmation)); - builder.setMessage(confirmMessage); - builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> { - synchronized (builder) { - if (accepted) { - if (L.isEnabled(L.OVERVIEW)) - log.debug("guarding: already accepted"); - return; - } - accepted = true; - if (Math.abs(insulinAfterConstraints - wizard.calculatedTotalInsulin) >= 0.01 || finalCarbsAfterConstraints > 0) { - if (wizard.superBolus) { - final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); - if (loopPlugin.isEnabled(PluginType.LOOP)) { - loopPlugin.superBolusTo(System.currentTimeMillis() + T.hours(2).msecs()); - MainApp.bus().post(new EventRefreshOverview("WizardDialog")); - } - - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - - if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(0.0d, 120, true, profile, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); - } else { - ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); - } - } - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; - detailedBolusInfo.insulin = finalInsulinAfterConstraints; - detailedBolusInfo.carbs = finalCarbsAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.boluscalc = boluscalcJSON; - detailedBolusInfo.source = Source.USER; - if (finalInsulinAfterConstraints > 0 || ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().storesCarbInfo) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); - } else { - TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false); - } - } - } - }); - builder.setNegativeButton(MainApp.gs(R.string.cancel), null); - builder.show(); + wizard.confirmAndExecute(getContext()); } } - } @Override @@ -1100,6 +979,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); final Profile profile = ProfileFunctions.getInstance().getProfile(); + final String profileName = ProfileFunctions.getInstance().getProfileName(); final String units = profile.getUnits(); final double lowLine = OverviewPlugin.getPlugin().determineLowLine(units); @@ -1297,10 +1177,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (quickWizardEntry != null && lastBG != null && pump.isInitialized() && !pump.isSuspended()) { quickWizardButton.setVisibility(View.VISIBLE); String text = quickWizardEntry.buttonText() + "\n" + DecimalFormatter.to0Decimal(quickWizardEntry.carbs()) + "g"; - BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, lastBG, false); - text += " " + DecimalFormatter.toPumpSupportedBolus(wizard.calculatedTotalInsulin) + "U"; + BolusWizard wizard = quickWizardEntry.doCalc(profile, profileName, lastBG, false); + text += " " + DecimalFormatter.toPumpSupportedBolus(wizard.getCalculatedTotalInsulin()) + "U"; quickWizardButton.setText(text); - if (wizard.calculatedTotalInsulin <= 0) + if (wizard.getCalculatedTotalInsulin() <= 0) quickWizardButton.setVisibility(View.GONE); } else quickWizardButton.setVisibility(View.GONE); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java index 608be5b29f..ed1471a4e9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java @@ -2,13 +2,9 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs; import android.app.Activity; import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; import android.os.Bundle; import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; import android.text.Editable; -import android.text.Html; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; @@ -28,47 +24,35 @@ import android.widget.TextView; import com.squareup.otto.Subscribe; -import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.DecimalFormat; import java.util.ArrayList; -import java.util.Date; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.events.EventFeatureRunning; -import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.PumpDescription; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.utils.BolusWizard; -import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.NumberPicker; import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.SafeParse; +import info.nightscout.androidaps.utils.StringUtils; import info.nightscout.androidaps.utils.ToastUtils; public class WizardDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener, Spinner.OnItemSelectedListener { @@ -109,8 +93,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com EditText notesEdit; Integer calculatedCarbs = 0; - Double calculatedTotalInsulin = 0d; - JSONObject boluscalcJSON; + BolusWizard wizard; Context context; @@ -312,119 +295,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com return; } okClicked = true; - final Profile profile = ProfileFunctions.getInstance().getProfile(); - final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - - if (pump != null && profile != null && (calculatedTotalInsulin > 0d || calculatedCarbs > 0d)) { - String confirmMessage = MainApp.gs(R.string.entertreatmentquestion); - - Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(calculatedTotalInsulin)).value(); - Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(calculatedCarbs)).value(); - - if (insulinAfterConstraints > 0) - confirmMessage += "
" + MainApp.gs(R.string.bolus) + ": " + "" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + ""; - if (carbsAfterConstraints > 0) - confirmMessage += "
" + MainApp.gs(R.string.carbs) + ": " + "" + carbsAfterConstraints + "g" + ""; - - if (Math.abs(insulinAfterConstraints - calculatedTotalInsulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints) || !carbsAfterConstraints.equals(calculatedCarbs)) { - confirmMessage += "
" + MainApp.gs(R.string.bolusconstraintapplied) + ""; - } - - final Double finalInsulinAfterConstraints = insulinAfterConstraints; - final Integer finalCarbsAfterConstraints = carbsAfterConstraints; - final Double bg = SafeParse.stringToDouble(editBg.getText()); - final int carbTime = SafeParse.stringToInt(editCarbTime.getText()); - final boolean useSuperBolus = superbolusCheckbox.isChecked(); - final String finalNotes = notesEdit.getText().toString(); - - final AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.gs(R.string.confirmation)); - builder.setMessage(Html.fromHtml(confirmMessage)); - builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - synchronized (builder) { - if (accepted) { - log.debug("guarding: already accepted"); - return; - } - accepted = true; - if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { - if (useSuperBolus) { - final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); - if (loopPlugin.isEnabled(PluginType.LOOP)) { - loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); - MainApp.bus().post(new EventRefreshOverview("WizardDialog")); - } - - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - - if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(0.0d, 120, true, profile, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); - } else { - - ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); - } - } - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; - detailedBolusInfo.insulin = finalInsulinAfterConstraints; - detailedBolusInfo.carbs = finalCarbsAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.glucose = bg; - detailedBolusInfo.glucoseType = "Manual"; - detailedBolusInfo.carbTime = carbTime; - detailedBolusInfo.boluscalc = boluscalcJSON; - detailedBolusInfo.source = Source.USER; - detailedBolusInfo.notes = finalNotes; - if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().storesCarbInfo) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); - } else { - TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false); - } - } - } - } - }); - builder.setNegativeButton(MainApp.gs(R.string.cancel), null); - builder.show(); - dismiss(); - } + wizard.confirmAndExecute(context); + dismiss(); break; case R.id.cancel: dismiss(); @@ -471,8 +343,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals(); IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round(); - bolusIobInsulin.setText(DecimalFormatter.to2Decimal(-bolusIob.iob) + "U"); - basalIobInsulin.setText(DecimalFormatter.to2Decimal(-basalIob.basaliob) + "U"); + bolusIobInsulin.setText(StringUtils.formatInsulin(-bolusIob.iob)); + basalIobInsulin.setText(StringUtils.formatInsulin(-basalIob.basaliob)); calculateInsulin(); } @@ -481,13 +353,13 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile(); if (profileSpinner == null || profileSpinner.getSelectedItem() == null || profileStore == null) return; // not initialized yet - String selectedAlternativeProfile = profileSpinner.getSelectedItem().toString(); + String profileName = profileSpinner.getSelectedItem().toString(); Profile specificProfile; - if (selectedAlternativeProfile.equals(MainApp.gs(R.string.active))) { + if (profileName.equals(MainApp.gs(R.string.active))) { specificProfile = ProfileFunctions.getInstance().getProfile(); - selectedAlternativeProfile = ProfileFunctions.getInstance().getProfileName(); + profileName = ProfileFunctions.getInstance().getProfileName(); } else - specificProfile = profileStore.getSpecificProfile(selectedAlternativeProfile); + specificProfile = profileStore.getSpecificProfile(profileName); // Entered values Double c_bg = SafeParse.stringToDouble(editBg.getText()); @@ -515,104 +387,64 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com Double c_cob = 0d; if (cobCheckbox.isChecked()) { CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard COB"); - if (cobInfo != null && cobInfo.displayCob != null) + if (cobInfo.displayCob != null) c_cob = cobInfo.displayCob; } - BolusWizard wizard = new BolusWizard(); - wizard.doCalc(specificProfile, tempTarget, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked(), superbolusCheckbox.isChecked(), bgtrendCheckbox.isChecked()); + wizard = new BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, 100d, bgCheckbox.isChecked(), cobCheckbox.isChecked(), bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked(), superbolusCheckbox.isChecked(), ttCheckbox.isChecked(), bgtrendCheckbox.isChecked()); + wizard.doCalc(); + wizard.setNotes(notesEdit.getText().toString()); + wizard.setCarbTime(SafeParse.stringToInt(editCarbTime.getText())); - bg.setText(c_bg + " ISF: " + DecimalFormatter.to1Decimal(wizard.sens)); - bgInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromBG) + "U"); + bg.setText(c_bg + " ISF: " + DecimalFormatter.to1Decimal(wizard.getSens())); + bgInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBG())); - carbs.setText(DecimalFormatter.to0Decimal(c_carbs) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic)); - carbsInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCarbs) + "U"); + carbs.setText(DecimalFormatter.to0Decimal(c_carbs) + "g IC: " + DecimalFormatter.to1Decimal(wizard.getIc())); + carbsInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCarbs())); - bolusIobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulingFromBolusIOB) + "U"); - basalIobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulingFromBasalsIOB) + "U"); + bolusIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulingFromBolusIOB())); + basalIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulingFromBasalsIOB())); - correctionInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCorrection) + "U"); - calculatedTotalInsulin = wizard.calculatedTotalInsulin; + correctionInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCorrection())); calculatedCarbs = carbsAfterConstraint; // Superbolus - if (superbolusCheckbox.isChecked()) { - superbolus.setText("2h"); - } else { - superbolus.setText(""); - } - superbolusInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromSuperBolus) + "U"); + superbolus.setText(superbolusCheckbox.isChecked() ? MainApp.gs(R.string.twohours) : ""); + superbolusInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromSuperBolus())); // Trend - if (bgtrendCheckbox.isChecked()) { - if (wizard.glucoseStatus != null) { - bgTrend.setText((wizard.glucoseStatus.avgdelta > 0 ? "+" : "") + Profile.toUnitsString(wizard.glucoseStatus.avgdelta * 3, wizard.glucoseStatus.avgdelta * 3 / 18, specificProfile.getUnits()) + " " + specificProfile.getUnits()); - } else { - bgTrend.setText(""); - } + if (bgtrendCheckbox.isChecked() && wizard.getGlucoseStatus() != null) { + bgTrend.setText( + (wizard.getTrend() > 0 ? "+" : "") + + Profile.toUnitsString(wizard.getTrend() * 3, wizard.getTrend() * 3 / Constants.MMOLL_TO_MGDL, specificProfile.getUnits()) + + " " + specificProfile.getUnits()); } else { bgTrend.setText(""); } - bgTrendInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromTrend) + "U"); + bgTrendInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromTrend())); // COB if (cobCheckbox.isChecked()) { - cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic)); - cobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCOB) + "U"); + cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.getIc())); + cobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCOB())); } else { cob.setText(""); cobInsulin.setText(""); } - if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { - String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.toPumpSupportedBolus(calculatedTotalInsulin) + "U") : ""; + if (wizard.getCalculatedTotalInsulin() > 0d || calculatedCarbs > 0d) { + String insulinText = wizard.getCalculatedTotalInsulin() > 0d ? (DecimalFormatter.toPumpSupportedBolus(wizard.getCalculatedTotalInsulin()) + "U") : ""; String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : ""; total.setText(MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText); okButton.setVisibility(View.VISIBLE); } else { // TODO this should also be run when loading the dialog as the OK button is initially visible // but does nothing if neither carbs nor insulin is > 0 - total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g"); + total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.getCarbsEquivalent()) + "g"); okButton.setVisibility(View.INVISIBLE); } - boluscalcJSON = new JSONObject(); - try { - boluscalcJSON.put("profile", selectedAlternativeProfile); - boluscalcJSON.put("notes", notesEdit.getText()); - boluscalcJSON.put("eventTime", DateUtil.toISOString(new Date())); - boluscalcJSON.put("targetBGLow", wizard.targetBGLow); - boluscalcJSON.put("targetBGHigh", wizard.targetBGHigh); - boluscalcJSON.put("isf", wizard.sens); - boluscalcJSON.put("ic", wizard.ic); - boluscalcJSON.put("iob", -(wizard.insulingFromBolusIOB + wizard.insulingFromBasalsIOB)); - boluscalcJSON.put("bolusiob", wizard.insulingFromBolusIOB); - boluscalcJSON.put("basaliob", wizard.insulingFromBasalsIOB); - boluscalcJSON.put("bolusiobused", bolusIobCheckbox.isChecked()); - boluscalcJSON.put("basaliobused", basalIobCheckbox.isChecked()); - boluscalcJSON.put("bg", c_bg); - boluscalcJSON.put("insulinbg", wizard.insulinFromBG); - boluscalcJSON.put("insulinbgused", bgCheckbox.isChecked()); - boluscalcJSON.put("bgdiff", wizard.bgDiff); - boluscalcJSON.put("insulincarbs", wizard.insulinFromCarbs); - boluscalcJSON.put("carbs", c_carbs); - boluscalcJSON.put("cob", c_cob); - boluscalcJSON.put("cobused", cobCheckbox.isChecked()); - boluscalcJSON.put("insulincob", wizard.insulinFromCOB); - boluscalcJSON.put("othercorrection", corrAfterConstraint); - boluscalcJSON.put("insulinsuperbolus", wizard.insulinFromSuperBolus); - boluscalcJSON.put("insulintrend", wizard.insulinFromTrend); - boluscalcJSON.put("insulin", calculatedTotalInsulin); - boluscalcJSON.put("superbolusused", superbolusCheckbox.isChecked()); - boluscalcJSON.put("insulinsuperbolus", wizard.insulinFromSuperBolus); - boluscalcJSON.put("trendused", bgtrendCheckbox.isChecked()); - boluscalcJSON.put("insulintrend", wizard.insulinFromTrend); - boluscalcJSON.put("trend", bgTrend.getText()); - boluscalcJSON.put("ttused", ttCheckbox.isChecked()); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java index 1a01a783cd..d7edb1dcc0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java @@ -207,6 +207,7 @@ public class ActionStringHandler { int percentage = Integer.parseInt(act[2]); Profile profile = ProfileFunctions.getInstance().getProfile(); + String profileName = ProfileFunctions.getInstance().getProfileName(); if (profile == null) { sendError("No profile found!"); return; @@ -226,45 +227,45 @@ public class ActionStringHandler { DecimalFormat format = new DecimalFormat("0.00"); DecimalFormat formatInt = new DecimalFormat("0"); - BolusWizard bolusWizard = new BolusWizard(); - bolusWizard.doCalc(profile, useTT ? TreatmentsPlugin.getPlugin().getTempTargetFromHistory() : null, - carbsAfterConstraints, useCOB?cobInfo.displayCob:0d, useBG ? bgReading.valueToUnits(profile.getUnits()) : 0d, - 0d, percentage, useBolusIOB, useBasalIOB, false, useTrend); + BolusWizard bolusWizard = new BolusWizard(profile, profileName, TreatmentsPlugin.getPlugin().getTempTargetFromHistory(), + carbsAfterConstraints, cobInfo.displayCob, bgReading.valueToUnits(profile.getUnits()), + 0d, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend); + bolusWizard.doCalc(); - Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(bolusWizard.calculatedTotalInsulin)).value(); - if (Math.abs(insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) { + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(bolusWizard.getCalculatedTotalInsulin())).value(); + if (Math.abs(insulinAfterConstraints - bolusWizard.getCalculatedTotalInsulin()) >= 0.01) { sendError("Insulin constraint violation!" + - "\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!"); + "\nCannot deliver " + format.format(bolusWizard.getCalculatedTotalInsulin()) + "!"); return; } - if (bolusWizard.calculatedTotalInsulin < 0) { - bolusWizard.calculatedTotalInsulin = 0d; + if (bolusWizard.getCalculatedTotalInsulin() < 0) { + bolusWizard.setCalculatedTotalInsulin(0d); } - if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) { + if (bolusWizard.getCalculatedTotalInsulin() <= 0 && bolusWizard.getCarbs() <= 0) { rAction = "info"; rTitle = "INFO"; } else { rAction = actionstring; } - rMessage += "Carbs: " + bolusWizard.carbs + "g"; - rMessage += "\nBolus: " + format.format(bolusWizard.calculatedTotalInsulin) + "U"; + rMessage += "Carbs: " + bolusWizard.getCarbs() + "g"; + rMessage += "\nBolus: " + format.format(bolusWizard.getCalculatedTotalInsulin()) + "U"; rMessage += "\n_____________"; - rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): "; - rMessage += "\nFrom Carbs: " + format.format(bolusWizard.insulinFromCarbs) + "U"; + rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.getIc()) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.getSens()) + "): "; + rMessage += "\nFrom Carbs: " + format.format(bolusWizard.getInsulinFromCarbs()) + "U"; if (useCOB) - rMessage += "\nFrom" + formatInt.format(cobInfo.displayCob) + "g COB : " + format.format(bolusWizard.insulinFromCOB) + "U"; - if (useBG) rMessage += "\nFrom BG: " + format.format(bolusWizard.insulinFromBG) + "U"; + rMessage += "\nFrom" + formatInt.format(cobInfo.displayCob) + "g COB : " + format.format(bolusWizard.getInsulinFromCOB()) + "U"; + if (useBG) rMessage += "\nFrom BG: " + format.format(bolusWizard.getInsulinFromBG()) + "U"; if (useBolusIOB) - rMessage += "\nBolus IOB: " + format.format(bolusWizard.insulingFromBolusIOB) + "U"; + rMessage += "\nBolus IOB: " + format.format(bolusWizard.getInsulingFromBolusIOB()) + "U"; if (useBasalIOB) - rMessage += "\nBasal IOB: " + format.format(bolusWizard.insulingFromBasalsIOB) + "U"; + rMessage += "\nBasal IOB: " + format.format(bolusWizard.getInsulingFromBasalsIOB()) + "U"; if (useTrend) - rMessage += "\nFrom 15' trend: " + format.format(bolusWizard.insulinFromTrend) + "U"; + rMessage += "\nFrom 15' trend: " + format.format(bolusWizard.getInsulinFromTrend()) + "U"; if (percentage != 100) { - rMessage += "\nPercentage: " + format.format(bolusWizard.totalBeforePercentageAdjustment) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.calculatedTotalInsulin) + "U"; + rMessage += "\nPercentage: " + format.format(bolusWizard.getTotalBeforePercentageAdjustment()) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.getCalculatedTotalInsulin()) + "U"; } lastBolusWizard = bolusWizard; @@ -628,7 +629,7 @@ public class ActionStringHandler { if (lastBolusWizard != null) { //use last calculation as confirmed string matches - doBolus(lastBolusWizard.calculatedTotalInsulin, lastBolusWizard.carbs); + doBolus(lastBolusWizard.getCalculatedTotalInsulin(), lastBolusWizard.getCarbs()); lastBolusWizard = null; } } else if ("bolus".equals(act[0])) { diff --git a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.java b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.java deleted file mode 100644 index cd789ee225..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.java +++ /dev/null @@ -1,183 +0,0 @@ -package info.nightscout.androidaps.utils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; - -/** - * Created by mike on 11.10.2016. - */ - -public class BolusWizard { - private Logger log = LoggerFactory.getLogger(L.CORE); - // Inputs - private Profile specificProfile = null; - private TempTarget tempTarget; - public Integer carbs = 0; - private Double bg = 0d; - private Double cob = 0d; - private Double correction; - private Double percentageCorrection; - private Boolean includeBolusIOB = true; - private Boolean includeBasalIOB = true; - public Boolean superBolus = false; - private Boolean trend = false; - - // Intermediate - public double sens = 0d; - public double ic = 0d; - - public GlucoseStatus glucoseStatus; - - public double targetBGLow = 0d; - public double targetBGHigh = 0d; - public double bgDiff = 0d; - - public double insulinFromBG = 0d; - public double insulinFromCarbs = 0d; - public double insulingFromBolusIOB = 0d; - public double insulingFromBasalsIOB = 0d; - public double insulinFromCorrection = 0d; - public double insulinFromSuperBolus = 0d; - public double insulinFromCOB = 0d; - public double insulinFromTrend = 0d; - - // Result - public Double calculatedTotalInsulin = 0d; - public Double totalBeforePercentageAdjustment = 0d; - public Double carbsEquivalent = 0d; - - public Double doCalc(Profile specificProfile, TempTarget tempTarget, Integer carbs, Double cob, Double bg, Double correction, Boolean includeBolusIOB, Boolean includeBasalIOB, Boolean superBolus, Boolean trend) { - return doCalc(specificProfile, tempTarget, carbs, cob, bg, correction, 100d, includeBolusIOB, includeBasalIOB, superBolus, trend); - } - - public Double doCalc(Profile specificProfile, TempTarget tempTarget, Integer carbs, Double cob, Double bg, Double correction, double percentageCorrection, Boolean includeBolusIOB, Boolean includeBasalIOB, Boolean superBolus, Boolean trend) { - this.specificProfile = specificProfile; - this.tempTarget = tempTarget; - this.carbs = carbs; - this.bg = bg; - this.cob = cob; - this.correction = correction; - this.percentageCorrection = percentageCorrection; - this.includeBolusIOB = includeBolusIOB; - this.includeBasalIOB = includeBasalIOB; - this.superBolus = superBolus; - this.trend = trend; - - // Insulin from BG - sens = specificProfile.getIsf(); - targetBGLow = specificProfile.getTargetLow(); - targetBGHigh = specificProfile.getTargetHigh(); - if (tempTarget != null) { - targetBGLow = Profile.fromMgdlToUnits(tempTarget.low, specificProfile.getUnits()); - targetBGHigh = Profile.fromMgdlToUnits(tempTarget.high, specificProfile.getUnits()); - } - if (bg >= targetBGLow && bg <= targetBGHigh) { - bgDiff = 0d; - } else if (bg <= targetBGLow) { - bgDiff = bg - targetBGLow; - } else { - bgDiff = bg - targetBGHigh; - } - insulinFromBG = bg != 0d ? bgDiff / sens : 0d; - - // Insulin from 15 min trend - glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - if (glucoseStatus != null && trend) { - insulinFromTrend = (Profile.fromMgdlToUnits(glucoseStatus.short_avgdelta, specificProfile.getUnits()) * 3) / sens; - } - - // Insuling from carbs - ic = specificProfile.getIc(); - insulinFromCarbs = carbs / ic; - insulinFromCOB = cob / ic; - - // Insulin from IOB - // IOB calculation - TreatmentsInterface treatments = TreatmentsPlugin.getPlugin(); - treatments.updateTotalIOBTreatments(); - IobTotal bolusIob = treatments.getLastCalculationTreatments().round(); - treatments.updateTotalIOBTempBasals(); - IobTotal basalIob = treatments.getLastCalculationTempBasals().round(); - - insulingFromBolusIOB = includeBolusIOB ? -bolusIob.iob : 0d; - insulingFromBasalsIOB = includeBasalIOB ? -basalIob.basaliob : 0d; - - // Insulin from correction - insulinFromCorrection = correction; - - // Insulin from superbolus for 2h. Get basal rate now and after 1h - if (superBolus) { - insulinFromSuperBolus = specificProfile.getBasal(); - long timeAfter1h = System.currentTimeMillis(); - timeAfter1h += T.hours(1).msecs(); - insulinFromSuperBolus += specificProfile.getBasal(timeAfter1h); - } - - // Total - calculatedTotalInsulin = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulingFromBolusIOB + insulingFromBasalsIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB; - - // Percentage adjustment - totalBeforePercentageAdjustment = calculatedTotalInsulin; - if (calculatedTotalInsulin > 0) { - calculatedTotalInsulin = calculatedTotalInsulin * percentageCorrection / 100d; - } - - if (calculatedTotalInsulin < 0) { - carbsEquivalent = -calculatedTotalInsulin * ic; - calculatedTotalInsulin = 0d; - } - - double bolusStep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep; - calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, bolusStep); - - log.debug(log()); - - return calculatedTotalInsulin; - } - - public String log() { - StringBuilder sb = new StringBuilder(); - - sb.append("TempTarget=").append(tempTarget != null ? tempTarget.toString() : "null").append("; "); - sb.append("Carbs=").append(carbs != null ? carbs : null).append("; "); - sb.append("Bg=").append(bg).append("; "); - sb.append("Cob=").append(cob).append("; "); - sb.append("Correction=").append(correction).append("; "); - sb.append("PercentageCorrection=").append(percentageCorrection).append("; "); - sb.append("IncludeBolusIOB=").append(includeBolusIOB).append("; "); - sb.append("IncludeBasalIOB=").append(includeBasalIOB).append("; "); - sb.append("Superbolus=").append(superBolus).append("; "); - sb.append("Trend=").append(trend).append("; "); - sb.append("Profile=").append(specificProfile != null && specificProfile.getData() != null ? specificProfile.getData().toString() : "null").append("; "); - sb.append("\n"); - - sb.append("targetBGLow=").append(targetBGLow).append("; "); - sb.append("targetBGHigh=").append(targetBGHigh).append("; "); - sb.append("bgDiff=").append(bgDiff).append("; "); - sb.append("insulinFromBG=").append(insulinFromBG).append("; "); - sb.append("insulinFromCarbs=").append(insulinFromCarbs).append("; "); - sb.append("insulingFromBolusIOB=").append(insulingFromBolusIOB).append("; "); - sb.append("insulingFromBasalsIOB=").append(insulingFromBasalsIOB).append("; "); - sb.append("insulinFromCorrection=").append(insulinFromCorrection).append("; "); - sb.append("insulinFromSuperBolus=").append(insulinFromSuperBolus).append("; "); - sb.append("insulinFromCOB=").append(insulinFromCOB).append("; "); - sb.append("insulinFromTrend=").append(insulinFromTrend).append("; "); - sb.append("\n"); - - - sb.append("calculatedTotalInsulin=").append(calculatedTotalInsulin).append("; "); - sb.append("totalBeforePercentageAdjustment=").append(totalBeforePercentageAdjustment).append("; "); - sb.append("carbsEquivalent=").append(carbsEquivalent).append("; "); - - return sb.toString(); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt new file mode 100644 index 0000000000..e42f417d40 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt @@ -0,0 +1,342 @@ +package info.nightscout.androidaps.utils + +import android.content.Context +import android.content.Intent +import android.support.v7.app.AlertDialog +import android.text.Html +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.db.CareportalEvent +import info.nightscout.androidaps.db.Source +import info.nightscout.androidaps.db.TempTarget +import info.nightscout.androidaps.events.EventRefreshOverview +import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.interfaces.PumpDescription +import info.nightscout.androidaps.interfaces.PumpInterface +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions +import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.queue.Callback +import org.json.JSONException +import org.json.JSONObject +import org.slf4j.LoggerFactory +import java.util.* + +class BolusWizard(val profile: Profile, + val profileName: String, + val tempTarget: TempTarget?, + val carbs: Int, + val cob: Double, + val bg: Double, + val correction: Double, + val percentageCorrection: Double = 100.0, + val useBg: Boolean, + val useCob: Boolean, + val includeBolusIOB: Boolean, + val includeBasalIOB: Boolean, + val useSuperBolus: Boolean, + val useTT: Boolean, + val useTrend: Boolean) { + + private val log = LoggerFactory.getLogger(L.CORE) + + // Intermediate + var sens = 0.0 + var ic = 0.0 + + var glucoseStatus: GlucoseStatus? = null + + var targetBGLow = 0.0 + var targetBGHigh = 0.0 + var bgDiff = 0.0 + + var insulinFromBG = 0.0 + var insulinFromCarbs = 0.0 + var insulingFromBolusIOB = 0.0 + var insulingFromBasalsIOB = 0.0 + var insulinFromCorrection = 0.0 + var insulinFromSuperBolus = 0.0 + var insulinFromCOB = 0.0 + var insulinFromTrend = 0.0 + + var trend = 0.0 + var carbTime = 0; + + var notes = "" + var accepted = false + + // Result + var calculatedTotalInsulin: Double = 0.0 + var totalBeforePercentageAdjustment: Double = 0.0 + var carbsEquivalent: Double = 0.0 + + var insulinAfterConstraints: Double = 0.0 + + fun doCalc(): Double { + + // Insulin from BG + sens = profile.isf + targetBGLow = profile.targetLow + targetBGHigh = profile.targetHigh + if (useTT && tempTarget != null) { + targetBGLow = Profile.fromMgdlToUnits(tempTarget.low, profile.units) + targetBGHigh = Profile.fromMgdlToUnits(tempTarget.high, profile.units) + } + if (useBg && bg > 0) { + if (bg >= targetBGLow && bg <= targetBGHigh) { + bgDiff = 0.0 + } else if (bg <= targetBGLow) { + bgDiff = bg - targetBGLow + } else { + bgDiff = bg - targetBGHigh + } + insulinFromBG = bgDiff / sens + } + + // Insulin from 15 min trend + glucoseStatus = GlucoseStatus.getGlucoseStatusData() + if (glucoseStatus != null && useTrend) { + trend = glucoseStatus!!.short_avgdelta + insulinFromTrend = Profile.fromMgdlToUnits(trend, profile.units) * 3 / sens + } + + // Insuling from carbs + ic = profile.ic + insulinFromCarbs = carbs / ic + insulinFromCOB = if (useCob) (cob / ic) else 0.0 + + // Insulin from IOB + // IOB calculation + val treatments = TreatmentsPlugin.getPlugin() + treatments.updateTotalIOBTreatments() + val bolusIob = treatments.lastCalculationTreatments.round() + treatments.updateTotalIOBTempBasals() + val basalIob = treatments.lastCalculationTempBasals.round() + + insulingFromBolusIOB = if (includeBolusIOB) -bolusIob.iob else 0.0 + insulingFromBasalsIOB = if (includeBasalIOB) -basalIob.basaliob else 0.0 + + // Insulin from correction + insulinFromCorrection = correction + + // Insulin from superbolus for 2h. Get basal rate now and after 1h + if (useSuperBolus) { + insulinFromSuperBolus = profile.basal + var timeAfter1h = System.currentTimeMillis() + timeAfter1h += T.hours(1).msecs() + insulinFromSuperBolus += profile.getBasal(timeAfter1h) + } + + // Total + calculatedTotalInsulin = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulingFromBolusIOB + insulingFromBasalsIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB + + // Percentage adjustment + totalBeforePercentageAdjustment = calculatedTotalInsulin + if (calculatedTotalInsulin > 0) { + calculatedTotalInsulin = calculatedTotalInsulin * percentageCorrection / 100.0 + } + + if (calculatedTotalInsulin < 0) { + carbsEquivalent = (-calculatedTotalInsulin) * ic + calculatedTotalInsulin = 0.0 + } + + val bolusStep = ConfigBuilderPlugin.getPlugin().activePump.pumpDescription.bolusStep + calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, bolusStep) + + insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(calculatedTotalInsulin)).value() + + log.debug(this.toString()) + + return calculatedTotalInsulin + } +/* + fun log(): String { + val sb = StringBuilder() + + sb.append("TempTarget=").append(tempTarget?.toString() ?: "null").append("; ") + sb.append("Carbs=").append(carbs).append("; ") + sb.append("Bg=").append(bg).append("; ") + sb.append("Cob=").append(cob).append("; ") + sb.append("Correction=").append(correction).append("; ") + sb.append("PercentageCorrection=").append(percentageCorrection).append("; ") + sb.append("IncludeBolusIOB=").append(includeBolusIOB).append("; ") + sb.append("IncludeBasalIOB=").append(includeBasalIOB).append("; ") + sb.append("Superbolus=").append(useSuperBolus).append("; ") + sb.append("Trend=").append(useTrend).append("; ") + sb.append("Profile=").append(profile.data?.toString()).append("; ") + sb.append("\n") + + sb.append("targetBGLow=").append(targetBGLow).append("; ") + sb.append("targetBGHigh=").append(targetBGHigh).append("; ") + sb.append("bgDiff=").append(bgDiff).append("; ") + sb.append("insulinFromBG=").append(insulinFromBG).append("; ") + sb.append("insulinFromCarbs=").append(insulinFromCarbs).append("; ") + sb.append("insulingFromBolusIOB=").append(insulingFromBolusIOB).append("; ") + sb.append("insulingFromBasalsIOB=").append(insulingFromBasalsIOB).append("; ") + sb.append("insulinFromCorrection=").append(insulinFromCorrection).append("; ") + sb.append("insulinFromSuperBolus=").append(insulinFromSuperBolus).append("; ") + sb.append("insulinFromCOB=").append(insulinFromCOB).append("; ") + sb.append("insulinFromTrend=").append(insulinFromTrend).append("; ") + sb.append("\n") + + sb.append("calculatedTotalInsulin=").append(calculatedTotalInsulin).append("; ") + sb.append("totalBeforePercentageAdjustment=").append(totalBeforePercentageAdjustment).append("; ") + sb.append("carbsEquivalent=").append(carbsEquivalent).append("; ") + + return sb.toString() + } +*/ + fun nsJSON(): JSONObject { + val boluscalcJSON = JSONObject() + try { + boluscalcJSON.put("profile", profileName) + boluscalcJSON.put("notes", notes) + boluscalcJSON.put("eventTime", DateUtil.toISOString(Date())) + boluscalcJSON.put("targetBGLow", targetBGLow) + boluscalcJSON.put("targetBGHigh", targetBGHigh) + boluscalcJSON.put("isf", sens) + boluscalcJSON.put("ic", ic) + boluscalcJSON.put("iob", -(insulingFromBolusIOB + insulingFromBasalsIOB)) + boluscalcJSON.put("bolusiob", insulingFromBolusIOB) + boluscalcJSON.put("basaliob", insulingFromBasalsIOB) + boluscalcJSON.put("bolusiobused", includeBolusIOB) + boluscalcJSON.put("basaliobused", includeBasalIOB) + boluscalcJSON.put("bg", bg) + boluscalcJSON.put("insulinbg", insulinFromBG) + boluscalcJSON.put("insulinbgused", useBg) + boluscalcJSON.put("bgdiff", bgDiff) + boluscalcJSON.put("insulincarbs", insulinFromCarbs) + boluscalcJSON.put("carbs", carbs) + boluscalcJSON.put("cob", cob) + boluscalcJSON.put("cobused", useCob) + boluscalcJSON.put("insulincob", insulinFromCOB) + boluscalcJSON.put("othercorrection", correction) + boluscalcJSON.put("insulinsuperbolus", insulinFromSuperBolus) + boluscalcJSON.put("insulintrend", insulinFromTrend) + boluscalcJSON.put("insulin", calculatedTotalInsulin) + boluscalcJSON.put("superbolusused", useSuperBolus) + boluscalcJSON.put("insulinsuperbolus", insulinFromSuperBolus) + boluscalcJSON.put("trendused", useTrend) + boluscalcJSON.put("insulintrend", insulinFromTrend) + boluscalcJSON.put("trend", trend) + boluscalcJSON.put("ttused", useTT) + } catch (e: JSONException) { + log.error("Unhandled exception", e) + } + return boluscalcJSON + } + + fun confirmMessageAfterConstraints(pump: PumpInterface): String { + + var confirmMessage = MainApp.gs(R.string.entertreatmentquestion) + if (insulinAfterConstraints > 0) + confirmMessage += "
" + MainApp.gs(R.string.bolus) + ": " + "" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + "" + if (carbs > 0) + confirmMessage += "
" + MainApp.gs(R.string.carbs) + ": " + "" + carbs + "g" + "" + + if (Math.abs(insulinAfterConstraints - calculatedTotalInsulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints)) { + confirmMessage += "
" + MainApp.gs(R.string.bolusconstraintapplied) + "" + } + + return confirmMessage + } + + fun confirmAndExecute(context: Context) { + val profile = ProfileFunctions.getInstance().profile + val pump = ConfigBuilderPlugin.getPlugin().activePump + + if (pump != null && profile != null && (calculatedTotalInsulin > 0.0 || carbs > 0.0)) { + val confirmMessage = confirmMessageAfterConstraints(pump) + + val builder = AlertDialog.Builder(context) + builder.setTitle(MainApp.gs(R.string.confirmation)) + builder.setMessage(Html.fromHtml(confirmMessage)) + builder.setPositiveButton(MainApp.gs(R.string.ok)) { dialog, id -> + synchronized(builder) { + if (accepted) { + log.debug("guarding: already accepted") + return@setPositiveButton + } + accepted = true + if (insulinAfterConstraints > 0 || carbs > 0) { + if (useSuperBolus) { + val loopPlugin = LoopPlugin.getPlugin() + if (loopPlugin.isEnabled(PluginType.LOOP)) { + loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000) + MainApp.bus().post(EventRefreshOverview("WizardDialog")) + } + + val pump1 = ConfigBuilderPlugin.getPlugin().activePump + + if (pump1.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { + ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalAbsolute(0.0, 120, true, profile, object : Callback() { + override fun run() { + if (!result.success) { + val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", result.comment) + i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + MainApp.instance().startActivity(i) + } + } + }) + } else { + + ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalPercent(0, 120, true, profile, object : Callback() { + override fun run() { + if (!result.success) { + val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", result.comment) + i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + MainApp.instance().startActivity(i) + } + } + }) + } + } + val detailedBolusInfo = DetailedBolusInfo() + detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD + detailedBolusInfo.insulin = insulinAfterConstraints + detailedBolusInfo.carbs = carbs.toDouble() + detailedBolusInfo.context = context + detailedBolusInfo.glucose = bg + detailedBolusInfo.glucoseType = "Manual" + detailedBolusInfo.carbTime = carbTime + detailedBolusInfo.boluscalc = nsJSON() + detailedBolusInfo.source = Source.USER + detailedBolusInfo.notes = notes + if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getPlugin().activePump.pumpDescription.storesCarbInfo) { + ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() { + override fun run() { + if (!result.success) { + val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", result.comment) + i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + MainApp.instance().startActivity(i) + } + } + }) + } else { + TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false) + } + } + } + } + builder.setNegativeButton(MainApp.gs(R.string.cancel), null) + builder.show() + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java b/app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java index cad2b76291..d089d213d4 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java @@ -1,5 +1,8 @@ package info.nightscout.androidaps.utils; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; + /** * class contains useful String functions */ @@ -17,4 +20,8 @@ public class StringUtils { return string; } + + public static String formatInsulin(double insulin) { + return String.format(MainApp.gs(R.string.formatinsulinunits), insulin); + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9620b64a50..f807d67cab 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1334,6 +1334,8 @@ old version very old version New version for at least %1$d days available! Fallback to LGS after 60 days, loop will be disabled after 90 days + 2h + %1$.2fU %1$d day diff --git a/app/src/test/java/info/AAPSMocker.java b/app/src/test/java/info/AAPSMocker.java index 79e0f89996..b757840b2e 100644 --- a/app/src/test/java/info/AAPSMocker.java +++ b/app/src/test/java/info/AAPSMocker.java @@ -10,7 +10,6 @@ import com.squareup.otto.Bus; import org.json.JSONException; import org.json.JSONObject; import org.junit.Assert; -import org.mockito.stubbing.Answer; import org.powermock.api.mockito.PowerMockito; import java.util.Locale; @@ -27,14 +26,12 @@ import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; import info.nightscout.androidaps.plugins.treatments.TreatmentService; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.CommandQueue; import info.nightscout.androidaps.utils.SP; @@ -42,7 +39,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -59,6 +55,7 @@ public class AAPSMocker { public static Intent intentSent = null; public static CommandQueue queue; + public static ConstraintChecker constraintChecker; public static void mockStrings() { Locale.setDefault(new Locale("en", "US")); @@ -168,7 +165,7 @@ public class AAPSMocker { } public static ConstraintChecker mockConstraintsChecker() { - ConstraintChecker constraintChecker = mock(ConstraintChecker.class); + constraintChecker = mock(ConstraintChecker.class); when(MainApp.getConstraintChecker()).thenReturn(constraintChecker); return constraintChecker; } diff --git a/app/src/test/java/info/nightscout/androidaps/utils/BolusWizardTest.java b/app/src/test/java/info/nightscout/androidaps/utils/BolusWizardTest.java index 2143a7101c..7007bb8245 100644 --- a/app/src/test/java/info/nightscout/androidaps/utils/BolusWizardTest.java +++ b/app/src/test/java/info/nightscout/androidaps/utils/BolusWizardTest.java @@ -3,12 +3,15 @@ package info.nightscout.androidaps.utils; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import info.AAPSMocker; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.ConstraintChecker; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; @@ -17,6 +20,7 @@ import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -24,38 +28,41 @@ import static org.mockito.Mockito.when; * Created by kuchjir on 12/12/2017. */ @RunWith(PowerMockRunner.class) -@PrepareForTest({MainApp.class, GlucoseStatus.class, ConfigBuilderPlugin.class, TreatmentsPlugin.class}) +@PrepareForTest({MainApp.class, GlucoseStatus.class, ConfigBuilderPlugin.class, TreatmentsPlugin.class, ConstraintChecker.class}) public class BolusWizardTest { private static final double PUMP_BOLUS_STEP = 0.1; @Test /** Should calculate the same bolus when different blood glucose but both in target range */ - public void shuldCalculateTheSameBolusWhenBGsInRange() throws Exception { - BolusWizard bw = new BolusWizard(); + public void shouldCalculateTheSameBolusWhenBGsInRange() throws Exception { Profile profile = setupProfile(4d, 8d, 20d, 12d); - Double bolusForBg42 = bw.doCalc(profile, null, 20, 0.0, 4.2, 0d, 100d, true, true, false, false); - Double bolusForBg54 = bw.doCalc(profile, null, 20, 0.0, 5.4, 0d, 100d, true, true, false, false); + BolusWizard bw = new BolusWizard(profile, "", null, 20, 0.0, 4.2, 0d, 100d, true, true, true, true, false, false, false); + Double bolusForBg42 = bw.doCalc(); + bw = new BolusWizard(profile, "", null, 20, 0.0, 5.4, 0d, 100d, true, true, true, true, false, false, false); + Double bolusForBg54 = bw.doCalc(); Assert.assertEquals(bolusForBg42, bolusForBg54); } @Test - public void shuldCalculateHigherBolusWhenHighBG() throws Exception { - BolusWizard bw = new BolusWizard(); + public void shouldCalculateHigherBolusWhenHighBG() throws Exception { Profile profile = setupProfile(4d, 8d, 20d, 12d); - Double bolusForHighBg = bw.doCalc(profile, null, 20, 0d, 9.8, 0d, 100d, true, true, false, false); - Double bolusForBgInRange = bw.doCalc(profile, null, 20, 0.0, 5.4, 0d, 100d, true, true, false, false); + BolusWizard bw = new BolusWizard(profile, "", null, 20, 0.0, 9.8, 0d, 100d, true, true, true, true, false, false, false); + Double bolusForHighBg = bw.doCalc(); + bw = new BolusWizard(profile, "", null, 20, 0.0, 5.4, 0d, 100d, true, true, true, true, false, false, false); + Double bolusForBgInRange = bw.doCalc(); Assert.assertTrue(bolusForHighBg > bolusForBgInRange); } @Test - public void shuldCalculateLowerBolusWhenLowBG() throws Exception { - BolusWizard bw = new BolusWizard(); + public void shouldCalculateLowerBolusWhenLowBG() throws Exception { Profile profile = setupProfile(4d, 8d, 20d, 12d); - Double bolusForLowBg = bw.doCalc(profile, null, 20, 0d, 3.6, 0d, 100d, true, true, false, false); - Double bolusForBgInRange = bw.doCalc(profile, null, 20, 0.0, 5.4, 0d, 100d, true, true, false, false); + BolusWizard bw = new BolusWizard(profile, "", null, 20, 0.0, 3.6, 0d, 100d, true, true, true, true, false, false, false); + Double bolusForLowBg = bw.doCalc(); + bw = new BolusWizard(profile, "", null, 20, 0.0, 5.4, 0d, 100d, true, true, true, true, false, false, false); + Double bolusForBgInRange = bw.doCalc(); Assert.assertTrue(bolusForLowBg < bolusForBgInRange); } @@ -82,6 +89,12 @@ public class BolusWizardTest { pump.getPumpDescription().bolusStep = PUMP_BOLUS_STEP; when(ConfigBuilderPlugin.getPlugin().getActivePump()).thenReturn(pump); + AAPSMocker.mockConstraintsChecker(); + Mockito.doAnswer(invocation -> { + Constraint constraint = invocation.getArgument(0); + return constraint; + }).when(AAPSMocker.constraintChecker).applyBolusConstraints(any(Constraint.class)); + return profile; } } \ No newline at end of file From af0d4f23b13691a8798801582a0f39e8b6892576 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 16 Jun 2019 09:11:11 +0200 Subject: [PATCH 2/4] kotlin lint --- .../main/java/info/nightscout/androidaps/utils/BolusWizard.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt index e42f417d40..e4bf845c72 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt @@ -67,7 +67,7 @@ class BolusWizard(val profile: Profile, var insulinFromTrend = 0.0 var trend = 0.0 - var carbTime = 0; + var carbTime = 0 var notes = "" var accepted = false @@ -259,7 +259,7 @@ class BolusWizard(val profile: Profile, val builder = AlertDialog.Builder(context) builder.setTitle(MainApp.gs(R.string.confirmation)) builder.setMessage(Html.fromHtml(confirmMessage)) - builder.setPositiveButton(MainApp.gs(R.string.ok)) { dialog, id -> + builder.setPositiveButton(MainApp.gs(R.string.ok)) { _, _ -> synchronized(builder) { if (accepted) { log.debug("guarding: already accepted") From 7b15cfb395eec787ad08c33303d7b9eada157221 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 21 Jun 2019 11:41:50 +0200 Subject: [PATCH 3/4] fix comparing bolus size granularity --- .../constraints/safety/SafetyPlugin.java | 6 +- .../general/overview/OverviewFragment.java | 2 +- .../overview/dialogs/NewInsulinDialog.java | 2 +- .../overview/dialogs/NewTreatmentDialog.java | 2 +- .../plugins/pump/common/defs/PumpType.java | 145 ++++++++---------- .../androidaps/utils/BolusWizard.kt | 38 +---- 6 files changed, 74 insertions(+), 121 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java index 65dc119c6a..127752d8dc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java @@ -13,10 +13,10 @@ import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin; import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin; @@ -196,7 +196,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface { PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (pump != null) { - double rounded = Round.roundTo(insulin.value(), pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value())); + double rounded = pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value()); insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this); } return insulin; @@ -213,7 +213,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface { PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (pump != null) { - double rounded = Round.roundTo(insulin.value(), pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value())); + double rounded = pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value()); insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this); } return insulin; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java index 01e6eec299..23440c2491 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java @@ -787,7 +787,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (wizard.getCalculatedTotalInsulin() > 0d && quickWizardEntry.carbs() > 0d) { Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(quickWizardEntry.carbs())).value(); - if (Math.abs(wizard.getInsulinAfterConstraints() - wizard.getCalculatedTotalInsulin()) >= pump.getPumpDescription().pumpType.determineCorrectBolusSize(wizard.getInsulinAfterConstraints()) || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) { + if (Math.abs(wizard.getInsulinAfterConstraints() - wizard.getCalculatedTotalInsulin()) >= pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(wizard.getInsulinAfterConstraints()) || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) { OKDialog.show(getContext(), MainApp.gs(R.string.treatmentdeliveryerror), MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput), null); return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java index 27e2e33ba7..ae29e98a3b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java @@ -225,7 +225,7 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener } } - if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints)) + if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)) actions.add("" + MainApp.gs(R.string.bolusconstraintapplied) + ""); int eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java index 837d206fb3..495cef0db5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java @@ -141,7 +141,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene if (recordOnlyCheckbox.isChecked()) { confirmMessage += "
" + MainApp.gs(R.string.bolusrecordedonly) + ""; } - if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints) || !Objects.equals(carbsAfterConstraints, carbs)) + if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints) || !Objects.equals(carbsAfterConstraints, carbs)) confirmMessage += "
" + MainApp.gs(R.string.bolusconstraintapplied) + ""; } if (carbsAfterConstraints > 0) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java index 9a7e351bf1..df92114ea4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java @@ -7,83 +7,83 @@ import java.util.Map; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.pump.common.data.DoseSettings; - +import info.nightscout.androidaps.utils.Round; /** * Created by andy on 02/05/2018. - * + *

* Most of this defintions is intended for VirtualPump only, but they can be used by other plugins. */ public enum PumpType { GenericAAPS("Generic AAPS", 0.1d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10,30, 24*60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10, 30, 24 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.01d, 0.01d, null, PumpCapability.VirtualPumpCapabilities), // // Cellnovo Cellnovo1("Cellnovo", 0.05d, null, // - new DoseSettings(0.05d, 30, 24*60, 1d, null), + new DoseSettings(0.05d, 30, 24 * 60, 1d, null), PumpTempBasalType.Percent, - new DoseSettings(5,30, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration30minAllowed, // + new DoseSettings(5, 30, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration30minAllowed, // 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // // Accu-Chek AccuChekCombo("Accu-Chek Combo", 0.1d, null, // - new DoseSettings(0.1d, 15, 12*60, 0.1d), // + new DoseSettings(0.1d, 15, 12 * 60, 0.1d), // PumpTempBasalType.Percent, - new DoseSettings(10, 15, 12*60,0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.01d, 0.01d, DoseStepSize.ComboBasal, PumpCapability.ComboCapabilities), // AccuChekSpirit("Accu-Chek Spirit", 0.1d, null, // - new DoseSettings(0.1d, 15, 12*60, 0.1d), // + new DoseSettings(0.1d, 15, 12 * 60, 0.1d), // PumpTempBasalType.Percent, - new DoseSettings(10, 15, 12*60,0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.01d, 0.1d, null, PumpCapability.VirtualPumpCapabilities), // AccuChekInsight("Accu-Chek Insight", 0.05d, DoseStepSize.InsightBolus, // - new DoseSettings(0.05d, 15, 24*60, 0.05d), // + new DoseSettings(0.05d, 15, 24 * 60, 0.05d), // PumpTempBasalType.Percent, - new DoseSettings(10, 15, 24*60,0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.02d, 0.01d, null, PumpCapability.InsightCapabilities), // AccuChekInsightBluetooth("Accu-Chek Insight", 0.01d, null, // - new DoseSettings(0.01d, 15, 24*60, 0.05d), // + new DoseSettings(0.01d, 15, 24 * 60, 0.05d), // PumpTempBasalType.Percent, - new DoseSettings(10, 15, 24*60,0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.02d, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities), // // Animas AnimasVibe("Animas Vibe", 0.05d, null, // AnimasBolus? - new DoseSettings(0.05d, 30, 12*60, 0.05d), // + new DoseSettings(0.05d, 30, 12 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10, 30, 24*60, 0d, 300d), PumpCapability.BasalRate_Duration30minAllowed, // + new DoseSettings(10, 30, 24 * 60, 0d, 300d), PumpCapability.BasalRate_Duration30minAllowed, // 0.025d, 5d, 0d, null, PumpCapability.VirtualPumpCapabilities), // AnimasPing("Animas Ping", AnimasVibe), // Dana DanaR("DanaR", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10d, 60, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // + new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // 0.04d, 0.01d, null, PumpCapability.DanaCapabilities), DanaRKorean("DanaR Korean", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10d, 60, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // + new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // 0.1d, 0.01d, null, PumpCapability.DanaCapabilities), DanaRS("DanaRS", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10d, 60, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.04d, 0.01d, null, PumpCapability.DanaWithHistoryCapabilities), DanaRv2("DanaRv2", DanaRS), @@ -91,40 +91,40 @@ public enum PumpType { // Insulet Insulet_Omnipod("Insulet Omnipod", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // - new DoseSettings(0.05d, 30, 12*60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, // cannot exceed max basal rate 30u/hr + new DoseSettings(0.05d, 30, 12 * 60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, // cannot exceed max basal rate 30u/hr 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // Medtronic Medtronic_512_712("Medtronic 512/712", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // - new DoseSettings(0.05d, 30, 24*60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // + new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // TODO Medtronic_515_715("Medtronic 515/715", Medtronic_512_712), Medtronic_522_722("Medtronic 522/722", Medtronic_512_712), Medtronic_523_723_Revel("Medtronic 523/723 (Revel)", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // - new DoseSettings(0.05d, 30, 24*60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // + new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), // Medtronic_554_754_Veo("Medtronic 554/754 (Veo)", Medtronic_523_723_Revel), // TODO Medtronic_640G("Medtronic 640G", 0.025d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // - new DoseSettings(0.05d, 30, 24*60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // + new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), // // Tandem TandemTSlim("Tandem t:slim", 0.01d, null, // - new DoseSettings(0.01d,15, 8*60, 0.4d), + new DoseSettings(0.01d, 15, 8 * 60, 0.4d), PumpTempBasalType.Percent, - new DoseSettings(1,15, 8*60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(1, 15, 8 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.1d, 0.001d, null, PumpCapability.VirtualPumpCapabilities), TandemTFlex("Tandem t:flex", TandemTSlim), // @@ -146,10 +146,9 @@ public enum PumpType { private PumpCapability pumpCapability; private PumpType parent; - private static Map mapByDescription; + private static Map mapByDescription; - static - { + static { mapByDescription = new HashMap<>(); for (PumpType pumpType : values()) { @@ -158,14 +157,12 @@ public enum PumpType { } - PumpType(String description, PumpType parent) - { + PumpType(String description, PumpType parent) { this.description = description; this.parent = parent; } - PumpType(String description, PumpType parent, PumpCapability pumpCapability) - { + PumpType(String description, PumpType parent, PumpCapability pumpCapability) { this.description = description; this.parent = parent; this.pumpCapability = pumpCapability; @@ -173,17 +170,15 @@ public enum PumpType { PumpType(String description, double bolusSize, DoseStepSize specialBolusSize, // DoseSettings extendedBolusSettings, // - PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // - double baseBasalMinValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) - { + PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // + double baseBasalMinValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) { this(description, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType, tbrSettings, specialBasalDurations, baseBasalMinValue, null, baseBasalStep, baseBasalSpecialSteps, pumpCapability); } PumpType(String description, double bolusSize, DoseStepSize specialBolusSize, // DoseSettings extendedBolusSettings, // PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // - double baseBasalMinValue, Double baseBasalMaxValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) - { + double baseBasalMinValue, Double baseBasalMaxValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) { this.description = description; this.bolusSize = bolusSize; this.specialBolusSize = specialBolusSize; @@ -261,20 +256,15 @@ public enum PumpType { } - private boolean isParentSet() - { - return this.parent!=null; + private boolean isParentSet() { + return this.parent != null; } - public static PumpType getByDescription(String desc) - { - if (mapByDescription.containsKey(desc)) - { + public static PumpType getByDescription(String desc) { + if (mapByDescription.containsKey(desc)) { return mapByDescription.get(desc); - } - else - { + } else { return PumpType.GenericAAPS; } } @@ -282,7 +272,7 @@ public enum PumpType { public String getFullDescription(String i18nTemplate, boolean hasExtendedBasals) { - String unit = getPumpTempBasalType()==PumpTempBasalType.Percent ? "%" : ""; + String unit = getPumpTempBasalType() == PumpTempBasalType.Percent ? "%" : ""; DoseSettings eb = getExtendedBolusSettings(); DoseSettings tbr = getTbrSettings(); @@ -291,24 +281,22 @@ public enum PumpType { return String.format(i18nTemplate, // getStep("" + getBolusSize(), getSpecialBolusSize()), // - eb.getStep(), eb.getDurationStep(), eb.getMaxDuration()/60, // + eb.getStep(), eb.getDurationStep(), eb.getMaxDuration() / 60, // getStep(getBaseBasalRange(), getBaseBasalSpecialSteps()), // tbr.getMinDose() + unit + "-" + tbr.getMaxDose() + unit, tbr.getStep() + unit, - tbr.getDurationStep(), tbr.getMaxDuration()/60, extendedNote); + tbr.getDurationStep(), tbr.getMaxDuration() / 60, extendedNote); } - private String getBaseBasalRange() - { + private String getBaseBasalRange() { Double maxValue = getBaseBasalMaxValue(); - return maxValue==null ? "" + getBaseBasalMinValue() : getBaseBasalMinValue() + "-" + maxValue; + return maxValue == null ? "" + getBaseBasalMinValue() : getBaseBasalMinValue() + "-" + maxValue; } - private String getStep(String step, DoseStepSize stepSize) - { - if (stepSize!=null) + private String getStep(String step, DoseStepSize stepSize) { + if (stepSize != null) return step + " [" + stepSize.getDescription() + "] *"; else return "" + step; @@ -316,18 +304,15 @@ public enum PumpType { public boolean hasExtendedBasals() { - return ((getBaseBasalSpecialSteps() !=null) || (getSpecialBolusSize() != null)); + return ((getBaseBasalSpecialSteps() != null) || (getSpecialBolusSize() != null)); } public PumpCapability getSpecialBasalDurations() { - if (isParentSet()) - { + if (isParentSet()) { return parent.getSpecialBasalDurations(); - } - else - { + } else { return specialBasalDurations == null ? // PumpCapability.BasalRate_Duration15and30minNotAllowed : specialBasalDurations; } @@ -338,20 +323,24 @@ public enum PumpType { return bolusAmount; } - double bolusStepSize; + double bolusStepSize = getBolusSize(); - if (getSpecialBolusSize() == null) { - bolusStepSize = getBolusSize(); - } else { + if (getSpecialBolusSize() != null) { DoseStepSize specialBolusSize = getSpecialBolusSize(); - - bolusStepSize = specialBolusSize.getStepSizeForAmount((double)bolusAmount); + bolusStepSize = specialBolusSize.getStepSizeForAmount(bolusAmount); } - return Math.round(bolusAmount / bolusStepSize) * bolusStepSize; + return Round.roundTo(bolusAmount, bolusStepSize); } + public double determineCorrectBolusStepSize(double bolusAmount) { + DoseStepSize specialBolusSize = getSpecialBolusSize(); + if (specialBolusSize != null) + return specialBolusSize.getStepSizeForAmount(bolusAmount); + return getBolusSize(); + } + public double determineCorrectExtendedBolusSize(double bolusAmount) { if (bolusAmount == 0.0d) { return bolusAmount; @@ -371,7 +360,7 @@ public enum PumpType { bolusAmount = extendedBolusSettings.getMaxDose(); } - return Math.round(bolusAmount / bolusStepSize) * bolusStepSize; + return Round.roundTo(bolusAmount, bolusStepSize); } @@ -393,7 +382,7 @@ public enum PumpType { if (basalAmount > getTbrSettings().getMaxDose()) basalAmount = getTbrSettings().getMaxDose().doubleValue(); - return Math.round(basalAmount / basalStepSize) * basalStepSize; + return Round.roundTo(basalAmount, basalStepSize); } } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt index e4bf845c72..2050557756 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt @@ -157,43 +157,7 @@ class BolusWizard(val profile: Profile, return calculatedTotalInsulin } -/* - fun log(): String { - val sb = StringBuilder() - sb.append("TempTarget=").append(tempTarget?.toString() ?: "null").append("; ") - sb.append("Carbs=").append(carbs).append("; ") - sb.append("Bg=").append(bg).append("; ") - sb.append("Cob=").append(cob).append("; ") - sb.append("Correction=").append(correction).append("; ") - sb.append("PercentageCorrection=").append(percentageCorrection).append("; ") - sb.append("IncludeBolusIOB=").append(includeBolusIOB).append("; ") - sb.append("IncludeBasalIOB=").append(includeBasalIOB).append("; ") - sb.append("Superbolus=").append(useSuperBolus).append("; ") - sb.append("Trend=").append(useTrend).append("; ") - sb.append("Profile=").append(profile.data?.toString()).append("; ") - sb.append("\n") - - sb.append("targetBGLow=").append(targetBGLow).append("; ") - sb.append("targetBGHigh=").append(targetBGHigh).append("; ") - sb.append("bgDiff=").append(bgDiff).append("; ") - sb.append("insulinFromBG=").append(insulinFromBG).append("; ") - sb.append("insulinFromCarbs=").append(insulinFromCarbs).append("; ") - sb.append("insulingFromBolusIOB=").append(insulingFromBolusIOB).append("; ") - sb.append("insulingFromBasalsIOB=").append(insulingFromBasalsIOB).append("; ") - sb.append("insulinFromCorrection=").append(insulinFromCorrection).append("; ") - sb.append("insulinFromSuperBolus=").append(insulinFromSuperBolus).append("; ") - sb.append("insulinFromCOB=").append(insulinFromCOB).append("; ") - sb.append("insulinFromTrend=").append(insulinFromTrend).append("; ") - sb.append("\n") - - sb.append("calculatedTotalInsulin=").append(calculatedTotalInsulin).append("; ") - sb.append("totalBeforePercentageAdjustment=").append(totalBeforePercentageAdjustment).append("; ") - sb.append("carbsEquivalent=").append(carbsEquivalent).append("; ") - - return sb.toString() - } -*/ fun nsJSON(): JSONObject { val boluscalcJSON = JSONObject() try { @@ -242,7 +206,7 @@ class BolusWizard(val profile: Profile, if (carbs > 0) confirmMessage += "
" + MainApp.gs(R.string.carbs) + ": " + "" + carbs + "g" + "" - if (Math.abs(insulinAfterConstraints - calculatedTotalInsulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints)) { + if (Math.abs(insulinAfterConstraints - calculatedTotalInsulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)) { confirmMessage += "
" + MainApp.gs(R.string.bolusconstraintapplied) + "" } From 45805ed41055c19a56807a48217bae72c877ee88 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Fri, 21 Jun 2019 13:23:37 +0200 Subject: [PATCH 4/4] BolusWizard privacy --- .../androidaps/data/QuickWizardEntry.java | 5 +- .../overview/dialogs/WizardDialog.java | 9 +- .../general/wear/ActionStringHandler.java | 13 +-- .../androidaps/utils/BolusWizard.kt | 102 ++++++++++++------ .../androidaps/utils/BolusWizardTest.java | 12 +-- 5 files changed, 83 insertions(+), 58 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java index c3c367aee8..062f6ae391 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java @@ -124,10 +124,7 @@ public class QuickWizardEntry { trend = true; } - BolusWizard wizard = new BolusWizard(profile, profileName, tempTarget, carbs(), cob, bg, 0d, 100, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend); - wizard.doCalc(); - wizard.setNotes("QuickWizard"); - return wizard; + return new BolusWizard(profile, profileName, tempTarget, carbs(), cob, bg, 0d, 100, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, "QuickWizard"); } public String buttonText() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java index ed1471a4e9..0f7bbaf1f2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java @@ -391,10 +391,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com c_cob = cobInfo.displayCob; } - wizard = new BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, 100d, bgCheckbox.isChecked(), cobCheckbox.isChecked(), bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked(), superbolusCheckbox.isChecked(), ttCheckbox.isChecked(), bgtrendCheckbox.isChecked()); - wizard.doCalc(); - wizard.setNotes(notesEdit.getText().toString()); - wizard.setCarbTime(SafeParse.stringToInt(editCarbTime.getText())); + wizard = new BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, 100d, bgCheckbox.isChecked(), cobCheckbox.isChecked(), bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked(), superbolusCheckbox.isChecked(), ttCheckbox.isChecked(), bgtrendCheckbox.isChecked(), notesEdit.getText().toString(), SafeParse.stringToInt(editCarbTime.getText())); bg.setText(c_bg + " ISF: " + DecimalFormatter.to1Decimal(wizard.getSens())); bgInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBG())); @@ -402,8 +399,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com carbs.setText(DecimalFormatter.to0Decimal(c_carbs) + "g IC: " + DecimalFormatter.to1Decimal(wizard.getIc())); carbsInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCarbs())); - bolusIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulingFromBolusIOB())); - basalIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulingFromBasalsIOB())); + bolusIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBolusIOB())); + basalIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBasalsIOB())); correctionInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCorrection())); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java index d7edb1dcc0..6cc681fa23 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java @@ -230,20 +230,13 @@ public class ActionStringHandler { BolusWizard bolusWizard = new BolusWizard(profile, profileName, TreatmentsPlugin.getPlugin().getTempTargetFromHistory(), carbsAfterConstraints, cobInfo.displayCob, bgReading.valueToUnits(profile.getUnits()), 0d, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend); - bolusWizard.doCalc(); - Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(bolusWizard.getCalculatedTotalInsulin())).value(); - if (Math.abs(insulinAfterConstraints - bolusWizard.getCalculatedTotalInsulin()) >= 0.01) { + if (Math.abs(bolusWizard.getInsulinAfterConstraints() - bolusWizard.getCalculatedTotalInsulin()) >= 0.01) { sendError("Insulin constraint violation!" + "\nCannot deliver " + format.format(bolusWizard.getCalculatedTotalInsulin()) + "!"); return; } - - if (bolusWizard.getCalculatedTotalInsulin() < 0) { - bolusWizard.setCalculatedTotalInsulin(0d); - } - if (bolusWizard.getCalculatedTotalInsulin() <= 0 && bolusWizard.getCarbs() <= 0) { rAction = "info"; rTitle = "INFO"; @@ -259,9 +252,9 @@ public class ActionStringHandler { rMessage += "\nFrom" + formatInt.format(cobInfo.displayCob) + "g COB : " + format.format(bolusWizard.getInsulinFromCOB()) + "U"; if (useBG) rMessage += "\nFrom BG: " + format.format(bolusWizard.getInsulinFromBG()) + "U"; if (useBolusIOB) - rMessage += "\nBolus IOB: " + format.format(bolusWizard.getInsulingFromBolusIOB()) + "U"; + rMessage += "\nBolus IOB: " + format.format(bolusWizard.getInsulinFromBolusIOB()) + "U"; if (useBasalIOB) - rMessage += "\nBasal IOB: " + format.format(bolusWizard.getInsulingFromBasalsIOB()) + "U"; + rMessage += "\nBasal IOB: " + format.format(bolusWizard.getInsulinFromBasalsIOB()) + "U"; if (useTrend) rMessage += "\nFrom 15' trend: " + format.format(bolusWizard.getInsulinFromTrend()) + "U"; if (percentage != 100) { diff --git a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt index 2050557756..bb74c833f2 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt @@ -29,57 +29,94 @@ import org.json.JSONObject import org.slf4j.LoggerFactory import java.util.* -class BolusWizard(val profile: Profile, - val profileName: String, - val tempTarget: TempTarget?, - val carbs: Int, - val cob: Double, - val bg: Double, - val correction: Double, - val percentageCorrection: Double = 100.0, - val useBg: Boolean, - val useCob: Boolean, - val includeBolusIOB: Boolean, - val includeBasalIOB: Boolean, - val useSuperBolus: Boolean, - val useTT: Boolean, - val useTrend: Boolean) { +class BolusWizard @JvmOverloads constructor(val profile: Profile, + val profileName: String, + val tempTarget: TempTarget?, + val carbs: Int, + val cob: Double, + val bg: Double, + val correction: Double, + private val percentageCorrection: Double = 100.0, + private val useBg: Boolean, + private val useCob: Boolean, + private val includeBolusIOB: Boolean, + private val includeBasalIOB: Boolean, + private val useSuperBolus: Boolean, + private val useTT: Boolean, + private val useTrend: Boolean, + val notes: String = "", + private val carbTime: Int = 0 +) { private val log = LoggerFactory.getLogger(L.CORE) // Intermediate var sens = 0.0 + private set + var ic = 0.0 + private set var glucoseStatus: GlucoseStatus? = null + private set var targetBGLow = 0.0 + private set + var targetBGHigh = 0.0 + private set + var bgDiff = 0.0 + private set var insulinFromBG = 0.0 + private set + var insulinFromCarbs = 0.0 - var insulingFromBolusIOB = 0.0 - var insulingFromBasalsIOB = 0.0 + private set + + var insulinFromBolusIOB = 0.0 + private set + + var insulinFromBasalsIOB = 0.0 + private set + var insulinFromCorrection = 0.0 + private set + var insulinFromSuperBolus = 0.0 + private set + var insulinFromCOB = 0.0 + private set + var insulinFromTrend = 0.0 + private set var trend = 0.0 - var carbTime = 0 + private set - var notes = "" var accepted = false + private set // Result var calculatedTotalInsulin: Double = 0.0 + private set + var totalBeforePercentageAdjustment: Double = 0.0 + private set + var carbsEquivalent: Double = 0.0 + private set var insulinAfterConstraints: Double = 0.0 + private set - fun doCalc(): Double { + init { + doCalc() + } + + private fun doCalc() { // Insulin from BG sens = profile.isf @@ -102,11 +139,14 @@ class BolusWizard(val profile: Profile, // Insulin from 15 min trend glucoseStatus = GlucoseStatus.getGlucoseStatusData() - if (glucoseStatus != null && useTrend) { - trend = glucoseStatus!!.short_avgdelta - insulinFromTrend = Profile.fromMgdlToUnits(trend, profile.units) * 3 / sens + glucoseStatus?.let { + if (useTrend) { + trend = it.short_avgdelta + insulinFromTrend = Profile.fromMgdlToUnits(trend, profile.units) * 3 / sens + } } + // Insuling from carbs ic = profile.ic insulinFromCarbs = carbs / ic @@ -120,8 +160,8 @@ class BolusWizard(val profile: Profile, treatments.updateTotalIOBTempBasals() val basalIob = treatments.lastCalculationTempBasals.round() - insulingFromBolusIOB = if (includeBolusIOB) -bolusIob.iob else 0.0 - insulingFromBasalsIOB = if (includeBasalIOB) -basalIob.basaliob else 0.0 + insulinFromBolusIOB = if (includeBolusIOB) -bolusIob.iob else 0.0 + insulinFromBasalsIOB = if (includeBasalIOB) -basalIob.basaliob else 0.0 // Insulin from correction insulinFromCorrection = correction @@ -135,7 +175,7 @@ class BolusWizard(val profile: Profile, } // Total - calculatedTotalInsulin = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulingFromBolusIOB + insulingFromBasalsIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB + calculatedTotalInsulin = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulinFromBolusIOB + insulinFromBasalsIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB // Percentage adjustment totalBeforePercentageAdjustment = calculatedTotalInsulin @@ -154,8 +194,6 @@ class BolusWizard(val profile: Profile, insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(calculatedTotalInsulin)).value() log.debug(this.toString()) - - return calculatedTotalInsulin } fun nsJSON(): JSONObject { @@ -168,9 +206,9 @@ class BolusWizard(val profile: Profile, boluscalcJSON.put("targetBGHigh", targetBGHigh) boluscalcJSON.put("isf", sens) boluscalcJSON.put("ic", ic) - boluscalcJSON.put("iob", -(insulingFromBolusIOB + insulingFromBasalsIOB)) - boluscalcJSON.put("bolusiob", insulingFromBolusIOB) - boluscalcJSON.put("basaliob", insulingFromBasalsIOB) + boluscalcJSON.put("iob", -(insulinFromBolusIOB + insulinFromBasalsIOB)) + boluscalcJSON.put("bolusiob", insulinFromBolusIOB) + boluscalcJSON.put("basaliob", insulinFromBasalsIOB) boluscalcJSON.put("bolusiobused", includeBolusIOB) boluscalcJSON.put("basaliobused", includeBasalIOB) boluscalcJSON.put("bg", bg) @@ -198,7 +236,7 @@ class BolusWizard(val profile: Profile, return boluscalcJSON } - fun confirmMessageAfterConstraints(pump: PumpInterface): String { + private fun confirmMessageAfterConstraints(pump: PumpInterface): String { var confirmMessage = MainApp.gs(R.string.entertreatmentquestion) if (insulinAfterConstraints > 0) diff --git a/app/src/test/java/info/nightscout/androidaps/utils/BolusWizardTest.java b/app/src/test/java/info/nightscout/androidaps/utils/BolusWizardTest.java index 7007bb8245..e56970182b 100644 --- a/app/src/test/java/info/nightscout/androidaps/utils/BolusWizardTest.java +++ b/app/src/test/java/info/nightscout/androidaps/utils/BolusWizardTest.java @@ -38,9 +38,9 @@ public class BolusWizardTest { Profile profile = setupProfile(4d, 8d, 20d, 12d); BolusWizard bw = new BolusWizard(profile, "", null, 20, 0.0, 4.2, 0d, 100d, true, true, true, true, false, false, false); - Double bolusForBg42 = bw.doCalc(); + Double bolusForBg42 = bw.getCalculatedTotalInsulin(); bw = new BolusWizard(profile, "", null, 20, 0.0, 5.4, 0d, 100d, true, true, true, true, false, false, false); - Double bolusForBg54 = bw.doCalc(); + Double bolusForBg54 = bw.getCalculatedTotalInsulin(); Assert.assertEquals(bolusForBg42, bolusForBg54); } @@ -49,9 +49,9 @@ public class BolusWizardTest { Profile profile = setupProfile(4d, 8d, 20d, 12d); BolusWizard bw = new BolusWizard(profile, "", null, 20, 0.0, 9.8, 0d, 100d, true, true, true, true, false, false, false); - Double bolusForHighBg = bw.doCalc(); + Double bolusForHighBg = bw.getCalculatedTotalInsulin(); bw = new BolusWizard(profile, "", null, 20, 0.0, 5.4, 0d, 100d, true, true, true, true, false, false, false); - Double bolusForBgInRange = bw.doCalc(); + Double bolusForBgInRange = bw.getCalculatedTotalInsulin(); Assert.assertTrue(bolusForHighBg > bolusForBgInRange); } @@ -60,9 +60,9 @@ public class BolusWizardTest { Profile profile = setupProfile(4d, 8d, 20d, 12d); BolusWizard bw = new BolusWizard(profile, "", null, 20, 0.0, 3.6, 0d, 100d, true, true, true, true, false, false, false); - Double bolusForLowBg = bw.doCalc(); + Double bolusForLowBg = bw.getCalculatedTotalInsulin(); bw = new BolusWizard(profile, "", null, 20, 0.0, 5.4, 0d, 100d, true, true, true, true, false, false, false); - Double bolusForBgInRange = bw.doCalc(); + Double bolusForBgInRange = bw.getCalculatedTotalInsulin(); Assert.assertTrue(bolusForLowBg < bolusForBgInRange); }