2017-06-02 12:27:21 +02:00
|
|
|
package info.nightscout.androidaps.data;
|
2017-06-02 10:25:49 +02:00
|
|
|
|
|
|
|
import android.support.annotation.Nullable;
|
|
|
|
import android.support.v4.util.LongSparseArray;
|
|
|
|
|
2018-03-17 23:18:34 +01:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2017-06-02 10:25:49 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import info.nightscout.androidaps.interfaces.Interval;
|
2018-03-17 23:18:34 +01:00
|
|
|
import info.nightscout.utils.DateUtil;
|
2017-06-02 10:25:49 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Created by mike on 09.05.2017.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Zero duration means profile is valid until is chaged
|
|
|
|
// When no interval match the lastest record without duration is used
|
|
|
|
|
|
|
|
public class ProfileIntervals<T extends Interval> {
|
2018-03-17 23:18:34 +01:00
|
|
|
private static Logger log = LoggerFactory.getLogger(ProfileIntervals.class);
|
2017-06-02 10:25:49 +02:00
|
|
|
|
|
|
|
private LongSparseArray<T> rawData = new LongSparseArray<>(); // oldest at index 0
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
public synchronized ProfileIntervals reset() {
|
2017-06-02 10:25:49 +02:00
|
|
|
rawData = new LongSparseArray<>();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
public synchronized void add(T newInterval) {
|
2017-06-02 10:25:49 +02:00
|
|
|
rawData.put(newInterval.start(), newInterval);
|
|
|
|
merge();
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
public synchronized void add(List<T> list) {
|
2017-06-02 10:25:49 +02:00
|
|
|
for (T interval : list) {
|
2018-01-21 13:37:38 +01:00
|
|
|
if (interval.isValid())
|
|
|
|
rawData.put(interval.start(), interval);
|
2017-06-02 10:25:49 +02:00
|
|
|
}
|
|
|
|
merge();
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
private synchronized void merge() {
|
2017-06-02 10:25:49 +02:00
|
|
|
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
|
2017-07-19 17:38:20 +02:00
|
|
|
public synchronized Interval getValueToTime(long time) {
|
2017-06-02 10:25:49 +02:00
|
|
|
int index = binarySearch(time);
|
|
|
|
if (index >= 0) return rawData.valueAt(index);
|
2018-03-17 23:18:34 +01:00
|
|
|
// if we request data older than first record, use oldest instead
|
|
|
|
if (rawData.size() > 0) {
|
|
|
|
log.debug("Requested profile for time: " + DateUtil.dateAndTimeString(time) + ". Providing oldest record: " + rawData.valueAt(0).toString());
|
|
|
|
return rawData.valueAt(0);
|
|
|
|
}
|
2017-06-02 10:25:49 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
public synchronized List<T> getList() {
|
2017-06-02 10:25:49 +02:00
|
|
|
List<T> list = new ArrayList<>();
|
|
|
|
for (int i = 0; i < rawData.size(); i++)
|
|
|
|
list.add(rawData.valueAt(i));
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
public synchronized List<T> getReversedList() {
|
2017-06-02 10:25:49 +02:00
|
|
|
List<T> list = new ArrayList<>();
|
2018-01-21 13:37:38 +01:00
|
|
|
for (int i = rawData.size() - 1; i >= 0; i--)
|
2017-06-02 10:25:49 +02:00
|
|
|
list.add(rawData.valueAt(i));
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
private synchronized int binarySearch(long value) {
|
2017-06-02 12:27:21 +02:00
|
|
|
if (rawData.size() == 0)
|
|
|
|
return -1;
|
2017-06-02 10:25:49 +02:00
|
|
|
int lo = 0;
|
|
|
|
int hi = rawData.size() - 1;
|
|
|
|
|
|
|
|
while (lo <= hi) {
|
|
|
|
final int mid = (lo + hi) >>> 1;
|
|
|
|
final Interval midVal = rawData.valueAt(mid);
|
|
|
|
|
2017-06-02 23:25:11 +02:00
|
|
|
if (midVal.match(value)) {
|
|
|
|
return mid; // value found
|
|
|
|
} else if (midVal.before(value)) {
|
2017-06-02 10:25:49 +02:00
|
|
|
lo = mid + 1;
|
|
|
|
} else if (midVal.after(value)) {
|
|
|
|
hi = mid - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// not found, try nearest older with duration 0
|
2017-06-02 23:25:11 +02:00
|
|
|
lo = lo - 1;
|
2017-06-02 12:27:21 +02:00
|
|
|
while (lo >= 0 && lo < rawData.size()) {
|
2017-06-02 10:25:49 +02:00
|
|
|
if (rawData.valueAt(lo).isEndingEvent())
|
|
|
|
return lo;
|
|
|
|
lo--;
|
|
|
|
}
|
|
|
|
return -1; // value not present
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
public synchronized int size() {
|
2017-06-02 10:25:49 +02:00
|
|
|
return rawData.size();
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
public synchronized T get(int index) {
|
2017-06-02 10:25:49 +02:00
|
|
|
return rawData.valueAt(index);
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:38:20 +02:00
|
|
|
public synchronized T getReversed(int index) {
|
2017-06-02 10:25:49 +02:00
|
|
|
return rawData.valueAt(size() - 1 - index);
|
|
|
|
}
|
|
|
|
}
|