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 class OverlappingIntervals { private LongSparseArray rawData = new LongSparseArray<>(); // oldest at index 0 public OverlappingIntervals reset() { rawData = new LongSparseArray<>(); return this; } public void add(T newInterval) { rawData.put(newInterval.start(), newInterval); merge(); } public void add(List 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 public Interval getValueByInterval(long time) { int index = binarySearch(time); if (index >= 0) return rawData.valueAt(index); return null; } public List getList() { List list = new ArrayList<>(); for (int i = 0; i < rawData.size(); i++) list.add(rawData.valueAt(i)); return list; } public List getReversedList() { List 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); } }