Merge pull request #286 from AdrianLxM/temp-target-logic

Temp target logic
This commit is contained in:
AdrianLxM 2017-07-19 19:33:17 +02:00 committed by GitHub
commit f220bb034e
10 changed files with 193 additions and 123 deletions

View file

@ -0,0 +1,90 @@
package info.nightscout.androidaps.data;
import android.support.annotation.Nullable;
import android.support.v4.util.LongSparseArray;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.interfaces.Interval;
/**
* Created by mike on 09.05.2017.
*/
// Zero duration means end of interval
public abstract class Intervals<T extends Interval> {
LongSparseArray<T> rawData = new LongSparseArray<T>(); // oldest at index 0
public synchronized Intervals reset() {
rawData = new LongSparseArray<T>();
return this;
}
protected abstract void merge();
/**
* The List must be sorted by `T.start()` in ascending order
*
* */
public synchronized void add(List<T> list) {
for (T interval : list) {
rawData.put(interval.start(), interval);
}
merge();
}
public synchronized List<T> getList() {
List<T> list = new ArrayList<>();
for (int i = 0; i < rawData.size(); i++)
list.add(rawData.valueAt(i));
return list;
}
public synchronized List<T> getReversedList() {
List<T> list = new ArrayList<>();
for (int i = rawData.size() -1; i>=0; i--)
list.add(rawData.valueAt(i));
return list;
}
protected synchronized int binarySearch(long value) {
int lo = 0;
int hi = rawData.size() - 1;
while (lo <= hi) {
final int mid = (lo + hi) >>> 1;
final Interval midVal = rawData.valueAt(mid);
if (midVal.before(value)) {
lo = mid + 1;
} else if (midVal.after(value)) {
hi = mid - 1;
} else if (midVal.match(value)) {
return mid; // value found
}
}
return ~lo; // value not present
}
public abstract T getValueByInterval(long time);
public synchronized int size() {
return rawData.size();
}
public synchronized T get(int index) {
return rawData.valueAt(index);
}
public synchronized T getReversed(int index) {
return rawData.valueAt(size() - 1 - index);
}
}

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.data;
import android.support.annotation.Nullable;
import info.nightscout.androidaps.interfaces.Interval;
/**
* Created by adrian on 15/07/17.
*/
public class NonOverlappingIntervals<T extends Interval> extends Intervals<T> {
protected synchronized void merge() {
for (int index = 0; index < rawData.size() - 1; index++) {
Interval i = rawData.valueAt(index);
long startOfNewer = rawData.valueAt(index + 1).start();
if (i.originalEnd() > startOfNewer) {
i.cutEndTo(startOfNewer);
}
}
}
@Nullable
public synchronized T getValueByInterval(long time) {
int index = binarySearch(time);
if (index >= 0) return rawData.valueAt(index);
return null;
}
}

View file

@ -1,99 +1,43 @@
package info.nightscout.androidaps.data; package info.nightscout.androidaps.data;
import android.support.annotation.Nullable;
import android.support.v4.util.LongSparseArray;
import java.util.ArrayList; import android.support.annotation.Nullable;
import java.util.List;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
/** /**
* Created by mike on 09.05.2017. * Created by adrian on 15/07/17.
*/ */
// Zero duration means end of interval public class OverlappingIntervals<T extends Interval> extends Intervals<T> {
public class OverlappingIntervals<T extends Interval> { protected synchronized void merge() {
boolean needToCut = false;
long cutTime = 0;
private LongSparseArray<T> rawData = new LongSparseArray<>(); // oldest at index 0 for (int index = rawData.size()-1; index > 0; index--) { //begin with newest
Interval cur = rawData.valueAt(index);
public OverlappingIntervals reset() { if (cur.isEndingEvent()){
rawData = new LongSparseArray<>(); needToCut = true;
return this; cutTime = cur.start();
} } else {
//event that is no EndingEvent might need to be stopped by an ending event
public void add(T newInterval) { if(needToCut&&cur.end() > cutTime){
rawData.put(newInterval.start(), newInterval); cur.cutEndTo(cutTime);
merge(); }
}
public void add(List<T> list) {
for (T interval : list) {
rawData.put(interval.start(), interval);
}
merge();
}
private void merge() {
for (int index = 0; index < rawData.size() - 1; index++) {
Interval i = rawData.valueAt(index);
long startOfNewer = rawData.valueAt(index + 1).start();
if (i.originalEnd() > startOfNewer) {
i.cutEndTo(startOfNewer);
} }
} }
} }
@Nullable @Nullable
public Interval getValueByInterval(long time) { public synchronized T getValueByInterval(long time) {
int index = binarySearch(time); for (int index = rawData.size()-1; index > 0; index--) { //begin with newest
if (index >= 0) return rawData.valueAt(index); T cur = rawData.valueAt(index);
if (cur.match(time)){
return cur;
}
}
return null; return null;
} }
public List<T> getList() { }
List<T> list = new ArrayList<>();
for (int i = 0; i < rawData.size(); i++)
list.add(rawData.valueAt(i));
return list;
}
public List<T> getReversedList() {
List<T> list = new ArrayList<>();
for (int i = rawData.size() -1; i>=0; i--)
list.add(rawData.valueAt(i));
return list;
}
private int binarySearch(long value) {
int lo = 0;
int hi = rawData.size() - 1;
while (lo <= hi) {
final int mid = (lo + hi) >>> 1;
final Interval midVal = rawData.valueAt(mid);
if (midVal.before(value)) {
lo = mid + 1;
} else if (midVal.after(value)) {
hi = mid - 1;
} else if (midVal.match(value)) {
return mid; // value found
}
}
return ~lo; // value not present
}
public int size() {
return rawData.size();
}
public T get(int index) {
return rawData.valueAt(index);
}
public T getReversed(int index) {
return rawData.valueAt(size() - 1 - index);
}
}

View file

@ -19,24 +19,24 @@ public class ProfileIntervals<T extends Interval> {
private LongSparseArray<T> rawData = new LongSparseArray<>(); // oldest at index 0 private LongSparseArray<T> rawData = new LongSparseArray<>(); // oldest at index 0
public ProfileIntervals reset() { public synchronized ProfileIntervals reset() {
rawData = new LongSparseArray<>(); rawData = new LongSparseArray<>();
return this; return this;
} }
public void add(T newInterval) { public synchronized void add(T newInterval) {
rawData.put(newInterval.start(), newInterval); rawData.put(newInterval.start(), newInterval);
merge(); merge();
} }
public void add(List<T> list) { public synchronized void add(List<T> list) {
for (T interval : list) { for (T interval : list) {
rawData.put(interval.start(), interval); rawData.put(interval.start(), interval);
} }
merge(); merge();
} }
private void merge() { private synchronized void merge() {
for (int index = 0; index < rawData.size() - 1; index++) { for (int index = 0; index < rawData.size() - 1; index++) {
Interval i = rawData.valueAt(index); Interval i = rawData.valueAt(index);
long startOfNewer = rawData.valueAt(index + 1).start(); long startOfNewer = rawData.valueAt(index + 1).start();
@ -47,27 +47,27 @@ public class ProfileIntervals<T extends Interval> {
} }
@Nullable @Nullable
public Interval getValueToTime(long time) { public synchronized Interval getValueToTime(long time) {
int index = binarySearch(time); int index = binarySearch(time);
if (index >= 0) return rawData.valueAt(index); if (index >= 0) return rawData.valueAt(index);
return null; return null;
} }
public List<T> getList() { public synchronized List<T> getList() {
List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
for (int i = 0; i < rawData.size(); i++) for (int i = 0; i < rawData.size(); i++)
list.add(rawData.valueAt(i)); list.add(rawData.valueAt(i));
return list; return list;
} }
public List<T> getReversedList() { public synchronized List<T> getReversedList() {
List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
for (int i = rawData.size() -1; i>=0; i--) for (int i = rawData.size() -1; i>=0; i--)
list.add(rawData.valueAt(i)); list.add(rawData.valueAt(i));
return list; return list;
} }
private int binarySearch(long value) { private synchronized int binarySearch(long value) {
if (rawData.size() == 0) if (rawData.size() == 0)
return -1; return -1;
int lo = 0; int lo = 0;
@ -95,15 +95,15 @@ public class ProfileIntervals<T extends Interval> {
return -1; // value not present return -1; // value not present
} }
public int size() { public synchronized int size() {
return rawData.size(); return rawData.size();
} }
public T get(int index) { public synchronized T get(int index) {
return rawData.valueAt(index); return rawData.valueAt(index);
} }
public T getReversed(int index) { public synchronized T getReversed(int index) {
return rawData.valueAt(size() - 1 - index); return rawData.valueAt(size() - 1 - index);
} }
} }

View file

@ -10,7 +10,7 @@ import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.data.OverlappingIntervals; import info.nightscout.androidaps.data.Intervals;
import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.data.ProfileIntervals;
/** /**
@ -42,18 +42,18 @@ public interface TreatmentsInterface {
TemporaryBasal getTempBasalFromHistory(long time); TemporaryBasal getTempBasalFromHistory(long time);
double getTempBasalAbsoluteRateHistory(); double getTempBasalAbsoluteRateHistory();
double getTempBasalRemainingMinutesFromHistory(); double getTempBasalRemainingMinutesFromHistory();
OverlappingIntervals<TemporaryBasal> getTemporaryBasalsFromHistory(); Intervals<TemporaryBasal> getTemporaryBasalsFromHistory();
boolean isInHistoryExtendedBoluslInProgress(); boolean isInHistoryExtendedBoluslInProgress();
ExtendedBolus getExtendedBolusFromHistory(long time); ExtendedBolus getExtendedBolusFromHistory(long time);
OverlappingIntervals<ExtendedBolus> getExtendedBolusesFromHistory(); Intervals<ExtendedBolus> getExtendedBolusesFromHistory();
boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus); boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus);
boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo); boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo);
TempTarget getTempTargetFromHistory(long time); TempTarget getTempTargetFromHistory(long time);
OverlappingIntervals<TempTarget> getTempTargetsFromHistory(); Intervals<TempTarget> getTempTargetsFromHistory();
ProfileSwitch getProfileSwitchFromHistory(long time); ProfileSwitch getProfileSwitchFromHistory(long time);
ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory(); ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory();

View file

@ -23,7 +23,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.OverlappingIntervals; import info.nightscout.androidaps.data.Intervals;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.data.ProfileIntervals;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
@ -827,7 +827,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
} }
@Override @Override
public OverlappingIntervals<TemporaryBasal> getTemporaryBasalsFromHistory() { public Intervals<TemporaryBasal> getTemporaryBasalsFromHistory() {
return activeTreatments.getTemporaryBasalsFromHistory(); return activeTreatments.getTemporaryBasalsFromHistory();
} }
@ -874,7 +874,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
} }
@Override @Override
public OverlappingIntervals<ExtendedBolus> getExtendedBolusesFromHistory() { public Intervals<ExtendedBolus> getExtendedBolusesFromHistory() {
return activeTreatments.getExtendedBolusesFromHistory(); return activeTreatments.getExtendedBolusesFromHistory();
} }
@ -896,7 +896,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
} }
@Override @Override
public OverlappingIntervals<TempTarget> getTempTargetsFromHistory() { public Intervals<TempTarget> getTempTargetsFromHistory() {
return activeTreatments.getTempTargetsFromHistory(); return activeTreatments.getTempTargetsFromHistory();
} }

View file

@ -8,7 +8,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
@ -19,6 +18,8 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Intervals;
import info.nightscout.androidaps.data.NonOverlappingIntervals;
import info.nightscout.androidaps.data.OverlappingIntervals; import info.nightscout.androidaps.data.OverlappingIntervals;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.data.ProfileIntervals;
@ -48,9 +49,9 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
public static IobTotal lastTempBasalsCalculation; public static IobTotal lastTempBasalsCalculation;
public static List<Treatment> treatments; public static List<Treatment> treatments;
private static OverlappingIntervals<TemporaryBasal> tempBasals = new OverlappingIntervals<>(); private static Intervals<TemporaryBasal> tempBasals = new NonOverlappingIntervals<TemporaryBasal>();
private static OverlappingIntervals<ExtendedBolus> extendedBoluses = new OverlappingIntervals<>(); private static Intervals<ExtendedBolus> extendedBoluses = new NonOverlappingIntervals<ExtendedBolus>();
private static OverlappingIntervals<TempTarget> tempTargets = new OverlappingIntervals<>(); private static Intervals<TempTarget> tempTargets = new OverlappingIntervals<TempTarget>();
private static ProfileIntervals<ProfileSwitch> profiles = new ProfileIntervals<>(); private static ProfileIntervals<ProfileSwitch> profiles = new ProfileIntervals<>();
private static boolean fragmentEnabled = true; private static boolean fragmentEnabled = true;
@ -347,7 +348,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
} }
@Override @Override
public OverlappingIntervals<ExtendedBolus> getExtendedBolusesFromHistory() { public Intervals<ExtendedBolus> getExtendedBolusesFromHistory() {
return extendedBoluses; return extendedBoluses;
} }
@ -380,7 +381,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
} }
@Override @Override
public OverlappingIntervals<TemporaryBasal> getTemporaryBasalsFromHistory() { public Intervals<TemporaryBasal> getTemporaryBasalsFromHistory() {
return tempBasals; return tempBasals;
} }
@ -442,7 +443,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
} }
@Override @Override
public OverlappingIntervals<TempTarget> getTempTargetsFromHistory() { public Intervals<TempTarget> getTempTargetsFromHistory() {
return tempTargets; return tempTargets;
} }

View file

@ -23,8 +23,6 @@ import com.squareup.otto.Subscribe;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
@ -35,7 +33,7 @@ import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.androidaps.data.OverlappingIntervals; import info.nightscout.androidaps.data.Intervals;
public class TreatmentsExtendedBolusesFragment extends Fragment { public class TreatmentsExtendedBolusesFragment extends Fragment {
@ -48,9 +46,9 @@ public class TreatmentsExtendedBolusesFragment extends Fragment {
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ExtendedBolusesViewHolder> { public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ExtendedBolusesViewHolder> {
OverlappingIntervals<ExtendedBolus> extendedBolusList; Intervals<ExtendedBolus> extendedBolusList;
RecyclerViewAdapter(OverlappingIntervals<ExtendedBolus> extendedBolusList) { RecyclerViewAdapter(Intervals<ExtendedBolus> extendedBolusList) {
this.extendedBolusList = extendedBolusList; this.extendedBolusList = extendedBolusList;
} }

View file

@ -26,11 +26,10 @@ import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.events.EventTempTargetChange;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.androidaps.data.OverlappingIntervals; import info.nightscout.androidaps.data.Intervals;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**
@ -47,10 +46,12 @@ public class TreatmentsTempTargetFragment extends Fragment implements View.OnCli
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.TempTargetsViewHolder> { public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.TempTargetsViewHolder> {
OverlappingIntervals<TempTarget> tempTargetList; Intervals<TempTarget> tempTargetList;
TempTarget currentlyActiveTarget;
RecyclerViewAdapter(OverlappingIntervals<TempTarget> TempTargetList) { RecyclerViewAdapter(Intervals<TempTarget> TempTargetList) {
this.tempTargetList = TempTargetList; this.tempTargetList = TempTargetList;
currentlyActiveTarget = tempTargetList.getValueByInterval(System.currentTimeMillis());
} }
@Override @Override
@ -81,10 +82,18 @@ public class TreatmentsTempTargetFragment extends Fragment implements View.OnCli
holder.reasonLabel.setText(""); holder.reasonLabel.setText("");
holder.reasonColon.setText(""); holder.reasonColon.setText("");
} }
if (tempTarget.isInProgress()) if (tempTarget.isInProgress()) {
holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); if(tempTarget == currentlyActiveTarget){
else // active as newest
holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorInProgress));
} else {
// other's that might become active again after the latest (overlapping) is over
holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive));
}
}
else {
holder.date.setTextColor(holder.reasonColon.getCurrentTextColor()); holder.date.setTextColor(holder.reasonColon.getCurrentTextColor());
}
holder.remove.setTag(tempTarget); holder.remove.setTag(tempTarget);
} }

View file

@ -23,8 +23,6 @@ import com.squareup.otto.Subscribe;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
@ -35,7 +33,7 @@ import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.androidaps.data.OverlappingIntervals; import info.nightscout.androidaps.data.Intervals;
public class TreatmentsTemporaryBasalsFragment extends Fragment { public class TreatmentsTemporaryBasalsFragment extends Fragment {
@ -50,9 +48,9 @@ public class TreatmentsTemporaryBasalsFragment extends Fragment {
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.TempBasalsViewHolder> { public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.TempBasalsViewHolder> {
OverlappingIntervals<TemporaryBasal> tempBasalList; Intervals<TemporaryBasal> tempBasalList;
RecyclerViewAdapter(OverlappingIntervals<TemporaryBasal> tempBasalList) { RecyclerViewAdapter(Intervals<TemporaryBasal> tempBasalList) {
this.tempBasalList = tempBasalList; this.tempBasalList = tempBasalList;
} }