From a4cb4cbbd506606b27b40ff7ebe64742ca5ac413 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 26 Mar 2018 19:46:18 +0200 Subject: [PATCH] OverlapingIntervalsTest --- .../nightscout/androidaps/data/Intervals.java | 5 ++ .../data/NonOverlappingIntervals.java | 4 -- .../androidaps/data/OverlappingIntervals.java | 18 ++++-- .../nightscout/androidaps/db/TempTarget.java | 20 +++++++ .../plugins/Treatments/TreatmentsPlugin.java | 2 +- .../main/java/info/nightscout/utils/T.java | 59 +++++++++++++++++++ .../androidaps/data/GlucoseStatusTest.java | 3 +- .../data/OverapingIntervalsTest.java | 49 +++++++++++++++ .../java/info/nightscout/utils/TTest.java | 24 ++++++++ 9 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/info/nightscout/utils/T.java create mode 100644 app/src/test/java/info/nightscout/androidaps/data/OverapingIntervalsTest.java create mode 100644 app/src/test/java/info/nightscout/utils/TTest.java diff --git a/app/src/main/java/info/nightscout/androidaps/data/Intervals.java b/app/src/main/java/info/nightscout/androidaps/data/Intervals.java index 7213290aa5..b87d2687cb 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Intervals.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Intervals.java @@ -43,6 +43,11 @@ public abstract class Intervals { merge(); } + public synchronized void add(T interval) { + rawData.put(interval.start(), interval); + merge(); + } + public synchronized List getList() { List list = new ArrayList<>(); diff --git a/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java index d54aa252c4..8e0c286e7e 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java +++ b/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java @@ -17,10 +17,6 @@ public class NonOverlappingIntervals extends Intervals { super(); } - public NonOverlappingIntervals(LongSparseArray data) { - super(data); - } - public NonOverlappingIntervals (Intervals other) { rawData = other.rawData.clone(); } diff --git a/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java index 070426cca0..76c2ff3615 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java +++ b/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java @@ -11,18 +11,26 @@ import info.nightscout.androidaps.interfaces.Interval; public class OverlappingIntervals extends Intervals { + public OverlappingIntervals() { + super(); + } + + public OverlappingIntervals(Intervals other) { + rawData = other.rawData.clone(); + } + protected synchronized void merge() { boolean needToCut = false; long cutTime = 0; - for (int index = rawData.size()-1; index >= 0; index--) { //begin with newest + for (int index = rawData.size() - 1; index >= 0; index--) { //begin with newest Interval cur = rawData.valueAt(index); - if (cur.isEndingEvent()){ + if (cur.isEndingEvent()) { needToCut = true; cutTime = cur.start(); } else { //event that is no EndingEvent might need to be stopped by an ending event - if(needToCut&&cur.end() > cutTime){ + if (needToCut && cur.end() > cutTime) { cur.cutEndTo(cutTime); } } @@ -31,9 +39,9 @@ public class OverlappingIntervals extends Intervals { @Nullable public synchronized T getValueByInterval(long time) { - for (int index = rawData.size()-1; index >= 0; index--) { //begin with newest + for (int index = rawData.size() - 1; index >= 0; index--) { //begin with newest T cur = rawData.valueAt(index); - if (cur.match(time)){ + if (cur.match(time)) { return cur; } } diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java index 980ce1c03c..0725bf5d6f 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java @@ -71,6 +71,26 @@ public class TempTarget implements Interval { reason = t.reason; } + public TempTarget date(long date) { + this.date = date; + return this; + } + + public TempTarget low(double low) { + this.low = low; + return this; + } + + public TempTarget high(double high) { + this.high = high; + return this; + } + + public TempTarget duration(int duration) { + this.durationInMinutes = duration; + return this; + } + // -------- Interval interface --------- Long cuttedEnd = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java index 9f62e1a7d8..829ded4c46 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java @@ -526,7 +526,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { @Override public Intervals getTempTargetsFromHistory() { synchronized (tempTargets) { - return new NonOverlappingIntervals<>(tempTargets); + return new OverlappingIntervals<>(tempTargets); } } diff --git a/app/src/main/java/info/nightscout/utils/T.java b/app/src/main/java/info/nightscout/utils/T.java new file mode 100644 index 0000000000..ce8541dd8c --- /dev/null +++ b/app/src/main/java/info/nightscout/utils/T.java @@ -0,0 +1,59 @@ +package info.nightscout.utils; + +/** + * Created by mike on 26.03.2018. + */ + +public class T { + private long time; // in msec + + public static T msecs(long msec) { + T t = new T(); + t.time = msec; + return t; + } + + public static T secs(long sec) { + T t = new T(); + t.time = sec * 1000L; + return t; + } + + public static T mins(long min) { + T t = new T(); + t.time = min * 60 * 1000L; + return t; + } + + public static T hours(long hour) { + T t = new T(); + t.time = hour * 60 * 60 * 1000L; + return t; + } + + public static T days(long day) { + T t = new T(); + t.time = day * 24 * 60 * 60 * 1000L; + return t; + } + + public long msecs() { + return time; + } + + public long secs() { + return time / 1000L; + } + + public long mins() { + return time / 60 / 1000L; + } + + public long hours() { + return time / 60 / 60 / 1000L; + } + + public long days() { + return time / 24 / 60 / 60 / 1000L; + } +} diff --git a/app/src/test/java/info/nightscout/androidaps/data/GlucoseStatusTest.java b/app/src/test/java/info/nightscout/androidaps/data/GlucoseStatusTest.java index a2591040ed..346475dc01 100644 --- a/app/src/test/java/info/nightscout/androidaps/data/GlucoseStatusTest.java +++ b/app/src/test/java/info/nightscout/androidaps/data/GlucoseStatusTest.java @@ -19,6 +19,7 @@ import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.T; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyLong; @@ -123,7 +124,7 @@ public class GlucoseStatusTest { AAPSMocker.mockDatabaseHelper(); PowerMockito.mockStatic(DateUtil.class); - when(DateUtil.now()).thenReturn(1514766900000L + 60000L); + when(DateUtil.now()).thenReturn(1514766900000L + T.mins(1).msecs()); } // [{"mgdl":214,"mills":1521895773113,"device":"xDrip-DexcomG5","direction":"Flat","filtered":191040,"unfiltered":205024,"noise":1,"rssi":100},{"mgdl":219,"mills":1521896073352,"device":"xDrip-DexcomG5","direction":"Flat","filtered":200160,"unfiltered":209760,"noise":1,"rssi":100},{"mgdl":222,"mills":1521896372890,"device":"xDrip-DexcomG5","direction":"Flat","filtered":207360,"unfiltered":212512,"noise":1,"rssi":100},{"mgdl":220,"mills":1521896673062,"device":"xDrip-DexcomG5","direction":"Flat","filtered":211488,"unfiltered":210688,"noise":1,"rssi":100},{"mgdl":193,"mills":1521896972933,"device":"xDrip-DexcomG5","direction":"Flat","filtered":212384,"unfiltered":208960,"noise":1,"rssi":100},{"mgdl":181,"mills":1521897273336,"device":"xDrip-DexcomG5","direction":"SingleDown","filtered":210592,"unfiltered":204320,"noise":1,"rssi":100},{"mgdl":176,"mills":1521897572875,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":206720,"unfiltered":197440,"noise":1,"rssi":100},{"mgdl":168,"mills":1521897872929,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":201024,"unfiltered":187904,"noise":1,"rssi":100},{"mgdl":161,"mills":1521898172814,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":193376,"unfiltered":178144,"noise":1,"rssi":100},{"mgdl":148,"mills":1521898472879,"device":"xDrip-DexcomG5","direction":"SingleDown","filtered":183264,"unfiltered":161216,"noise":1,"rssi":100},{"mgdl":139,"mills":1521898772862,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":170784,"unfiltered":148928,"noise":1,"rssi":100},{"mgdl":132,"mills":1521899072896,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":157248,"unfiltered":139552,"noise":1,"rssi":100},{"mgdl":125,"mills":1521899372834,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":144416,"unfiltered":129616.00000000001,"noise":1,"rssi":100},{"mgdl":128,"mills":1521899973456,"device":"xDrip-DexcomG5","direction":"Flat","filtered":130240.00000000001,"unfiltered":133536,"noise":1,"rssi":100},{"mgdl":132,"mills":1521900573287,"device":"xDrip-DexcomG5","direction":"Flat","filtered":133504,"unfiltered":138720,"noise":1,"rssi":100},{"mgdl":127,"mills":1521900873711,"device":"xDrip-DexcomG5","direction":"Flat","filtered":136480,"unfiltered":132992,"noise":1,"rssi":100},{"mgdl":127,"mills":1521901180151,"device":"xDrip-DexcomG5","direction":"Flat","filtered":136896,"unfiltered":132128,"noise":1,"rssi":100},{"mgdl":125,"mills":1521901473582,"device":"xDrip-DexcomG5","direction":"Flat","filtered":134624,"unfiltered":129696,"noise":1,"rssi":100},{"mgdl":120,"mills":1521901773597,"device":"xDrip-DexcomG5","direction":"Flat","filtered":130704.00000000001,"unfiltered":123376,"noise":1,"rssi":100},{"mgdl":116,"mills":1521902075855,"device":"xDrip-DexcomG5","direction":"Flat","filtered":126272,"unfiltered":118448,"noise":1,"rssi":100}] diff --git a/app/src/test/java/info/nightscout/androidaps/data/OverapingIntervalsTest.java b/app/src/test/java/info/nightscout/androidaps/data/OverapingIntervalsTest.java new file mode 100644 index 0000000000..e66ac10a00 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/data/OverapingIntervalsTest.java @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.data; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.T; + +/** + * Created by mike on 26.03.2018. + */ + +@RunWith(PowerMockRunner.class) +public class OverapingIntervalsTest { + + private final long startDate = DateUtil.now(); + OverlappingIntervals list = new OverlappingIntervals<>(); + + @Test + public void doTests() { + // create one 10h interval and test value in and out + list.add(new TempTarget().date(startDate).duration((int) T.hours(10).mins()).low(100).high(100)); + Assert.assertEquals(null, list.getValueByInterval(startDate - T.secs(1).msecs())); + Assert.assertEquals(100d, list.getValueByInterval(startDate).target(), 0.01d); + Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(10).msecs() + 1)); + + // stop temp target after 5h + list.add(new TempTarget().date(startDate + T.hours(5).msecs()).duration(0)); + Assert.assertEquals(null, list.getValueByInterval(startDate - T.secs(1).msecs())); + Assert.assertEquals(100d, list.getValueByInterval(startDate).target(), 0.01d); + Assert.assertEquals(100d, list.getValueByInterval(startDate + T.hours(5).msecs() - 1).target(), 0.01d); + Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(5).msecs() + 1)); + Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(10).msecs() + 1)); + + // insert 1h interval inside + list.add(new TempTarget().date(startDate + T.hours(3).msecs()).duration((int) T.hours(1).mins()).low(200).high(200)); + Assert.assertEquals(null, list.getValueByInterval(startDate - T.secs(1).msecs())); + Assert.assertEquals(100d, list.getValueByInterval(startDate).target(), 0.01d); + Assert.assertEquals(100d, list.getValueByInterval(startDate + T.hours(5).msecs() - 1).target(), 0.01d); + Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(5).msecs() + 1)); + Assert.assertEquals(200d, list.getValueByInterval(startDate + T.hours(3).msecs()).target(), 0.01d); + Assert.assertEquals(100d, list.getValueByInterval(startDate + T.hours(4).msecs() + 1).target(), 0.01d); + Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(10).msecs() + 1)); + } + +} diff --git a/app/src/test/java/info/nightscout/utils/TTest.java b/app/src/test/java/info/nightscout/utils/TTest.java new file mode 100644 index 0000000000..ca7bb7cdaf --- /dev/null +++ b/app/src/test/java/info/nightscout/utils/TTest.java @@ -0,0 +1,24 @@ +package info.nightscout.utils; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; + +/** + * Created by mike on 26.03.2018. + */ + +@RunWith(PowerMockRunner.class) +public class TTest { + + @Test + public void doTests() { + Assert.assertEquals(1, T.msecs(1000).secs()); + Assert.assertEquals(1, T.secs(60).mins()); + Assert.assertEquals(1, T.mins(60).hours()); + Assert.assertEquals(1, T.hours(24).days()); + Assert.assertEquals(24, T.days(1).hours()); + Assert.assertEquals(60000, T.mins(1).msecs()); + } +}