diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.java index 7f3560bb18..9e5c9e2cdd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.java @@ -19,6 +19,7 @@ import butterknife.Unbinder; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg; +import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerCOB; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerIob; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerLocation; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerProfilePercent; @@ -39,6 +40,7 @@ public class ChooseTriggerDialog extends DialogFragment { add(new TriggerRecurringTime()); add(new TriggerBg()); add(new TriggerIob()); + add(new TriggerCOB()); add(new TriggerProfilePercent()); add(new TriggerTempTarget()); add(new TriggerWifiSsid()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java new file mode 100644 index 0000000000..1ded6c4da9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java @@ -0,0 +1,152 @@ +package info.nightscout.androidaps.plugins.general.automation.triggers; + + +import android.support.v4.app.FragmentManager; +import android.widget.LinearLayout; + +import com.google.common.base.Optional; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DecimalFormat; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.general.automation.elements.Comparator; +import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble; +import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement; +import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder; +import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.JsonHelper; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; + +public class TriggerCOB extends Trigger { + private static Logger log = LoggerFactory.getLogger(L.AUTOMATION); + private final int minValue = 0; + private final int maxValue = (int) (SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48)); + private final double step = 1; + private DecimalFormat decimalFormat = new DecimalFormat("1"); + private InputDouble value = new InputDouble(0, (double) minValue, (double) maxValue, step, decimalFormat); + private Comparator comparator = new Comparator(); + + public TriggerCOB() { + super(); + } + + private TriggerCOB(TriggerCOB triggerCOB) { + super(); + value = new InputDouble(triggerCOB.value); + lastRun = triggerCOB.lastRun; + comparator = new Comparator(triggerCOB.comparator); + } + + public double getValue() { + return value.getValue(); + } + + public Comparator getComparator() { + return comparator; + } + + @Override + public synchronized boolean shouldRun() { + CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "AutomationTriggerCOB"); + if (cobInfo == null) + if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE) + return true; + else + return false; + + if (lastRun > DateUtil.now() - T.mins(5).msecs()) + return false; + + boolean doRun = comparator.getValue().check((cobInfo.displayCob), getValue()); + if (doRun) { + if (L.isEnabled(L.AUTOMATION)) + log.debug("Ready for execution: " + friendlyDescription()); + return true; + } + return false; + } + + @Override + public synchronized String toJSON() { + JSONObject o = new JSONObject(); + try { + o.put("type", TriggerCOB.class.getName()); + JSONObject data = new JSONObject(); + data.put("carbs", getValue()); + data.put("lastRun", lastRun); + data.put("comparator", comparator.getValue().toString()); + o.put("data", data); + } catch (JSONException e) { + e.printStackTrace(); + } + return o.toString(); + } + + @Override + Trigger fromJSON(String data) { + try { + JSONObject d = new JSONObject(data); + value.setValue(JsonHelper.safeGetDouble(d, "carbs")); + lastRun = JsonHelper.safeGetLong(d, "lastRun"); + comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator"))); + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + @Override + public int friendlyName() { + return R.string.triggercoblabel; + } + + @Override + public String friendlyDescription() { + return MainApp.gs(R.string.cobcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue()); + } + + @Override + public Optional icon() { + return Optional.of(R.drawable.icon_cp_bolus_carbs); + } + + @Override + public Trigger duplicate() { + return new TriggerCOB(this); + } + + TriggerCOB setValue(int requestedValue) { + this.value.setValue(requestedValue); + return this; + } + + TriggerCOB lastRun(long lastRun) { + this.lastRun = lastRun; + return this; + } + + TriggerCOB comparator(Comparator.Compare compare) { + this.comparator = new Comparator().setValue(compare); + return this; + } + + @Override + public void generateDialog(LinearLayout root, FragmentManager fragmentManager) { + new LayoutBuilder() + .add(new StaticLabel(R.string.triggercoblabel)) + .add(comparator) + .add(new LabelWithElement(MainApp.gs(R.string.triggercoblabel) + ": ", "", value)) + .build(root); + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1c243b09f7..461f126a5f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1409,6 +1409,8 @@ Dist [m]: Name: Location is %1$s + COB + COB %1$s %2$.0f %1$d day diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOBTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOBTest.java new file mode 100644 index 0000000000..69ec02f119 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOBTest.java @@ -0,0 +1,121 @@ +package info.nightscout.androidaps.plugins.general.automation.triggers; + +import com.google.common.base.Optional; +import com.squareup.otto.Bus; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +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.R; +import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.automation.elements.Comparator; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.powermock.api.mockito.PowerMockito.verifyNew; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, Bus.class, ProfileFunctions.class, DateUtil.class, IobCobCalculatorPlugin.class, SP.class}) +public class TriggerCOBTest { + + long now = 1514766900000L; + IobCobCalculatorPlugin iobCobCalculatorPlugin; + + @Test + public void shouldRunTest() { + // COB value is 6 + PowerMockito.when(IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "AutomationTriggerCOB")).thenReturn(new CobInfo(6d, 2d)); TriggerCOB t = new TriggerCOB().setValue(1).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertFalse(t.shouldRun()); + t = new TriggerCOB().setValue(6).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertTrue(t.shouldRun()); + t = new TriggerCOB().setValue(5).comparator(Comparator.Compare.IS_GREATER); + Assert.assertTrue(t.shouldRun()); + t = new TriggerCOB().setValue(5).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER); + Assert.assertTrue(t.shouldRun()); + t = new TriggerCOB().setValue(6).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + Assert.assertTrue(t.shouldRun()); + t = new TriggerCOB().setValue(1).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertFalse(t.shouldRun()); + t = new TriggerCOB().setValue(10).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + Assert.assertTrue(t.shouldRun()); + t = new TriggerCOB().setValue(5).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + Assert.assertFalse(t.shouldRun()); + + t = new TriggerCOB().setValue(1).comparator(Comparator.Compare.IS_EQUAL).lastRun(now - 1); + Assert.assertFalse(t.shouldRun()); + + } + + @Test + public void copyConstructorTest() { + TriggerCOB t = new TriggerCOB().setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + TriggerCOB t1 = (TriggerCOB) t.duplicate(); + Assert.assertEquals(213d, t.getValue(), 0.01d); + Assert.assertEquals(Comparator.Compare.IS_EQUAL_OR_LESSER, t.getComparator().getValue()); + } + + @Test + public void executeTest() { + TriggerCOB t = new TriggerCOB().setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + t.executed(1); + Assert.assertEquals(1l, t.getLastRun()); + } + + String bgJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"carbs\":4},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerCOB\"}"; + + @Test + public void toJSONTest() { + TriggerCOB t = new TriggerCOB().setValue(4).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertEquals(bgJson, t.toJSON()); + } + + @Test + public void fromJSONTest() throws JSONException { + TriggerCOB t = new TriggerCOB().setValue(4).comparator(Comparator.Compare.IS_EQUAL); + + TriggerCOB t2 = (TriggerCOB) Trigger.instantiate(new JSONObject(t.toJSON())); + Assert.assertEquals(Comparator.Compare.IS_EQUAL, t2.getComparator().getValue()); + Assert.assertEquals(4, t2.getValue(), 0.01d); + } + + @Test + public void iconTest() { + Assert.assertEquals(Optional.of(R.drawable.icon_cp_bolus_carbs), new TriggerCOB().icon()); + } + + + @Before + public void mock() { + AAPSMocker.mockMainApp(); + AAPSMocker.mockBus(); + iobCobCalculatorPlugin = AAPSMocker.mockIobCobCalculatorPlugin(); + AAPSMocker.mockProfileFunctions(); + AAPSMocker.mockSP(); + AAPSMocker.mockL(); + + PowerMockito.mockStatic(DateUtil.class); + when(DateUtil.now()).thenReturn(now); + when(SP.getInt(any(), any())).thenReturn(48); + } + + public CobInfo generateCobInfo(){ + return new CobInfo(6d, 0d); + } + +}