profiles visualisation
This commit is contained in:
parent
f267c85377
commit
6ca4811e8e
16 changed files with 429 additions and 39 deletions
|
@ -1,7 +1,5 @@
|
||||||
package info.nightscout.utils;
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.util.LongSparseArray;
|
import android.support.v4.util.LongSparseArray;
|
||||||
|
|
|
@ -291,7 +291,7 @@ public class Profile {
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int secondsFromMidnight() {
|
public static Integer secondsFromMidnight() {
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
long now = c.getTimeInMillis();
|
long now = c.getTimeInMillis();
|
||||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
@ -302,7 +302,7 @@ public class Profile {
|
||||||
return (int) (passed / 1000);
|
return (int) (passed / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int secondsFromMidnight(Date date) {
|
public static Integer secondsFromMidnight(Date date) {
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
long now = date.getTime();
|
long now = date.getTime();
|
||||||
c.setTime(date);
|
c.setTime(date);
|
||||||
|
@ -314,7 +314,7 @@ public class Profile {
|
||||||
return (int) (passed / 1000);
|
return (int) (passed / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int secondsFromMidnight(long date) {
|
public static Integer secondsFromMidnight(long date) {
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
c.setTimeInMillis(date);
|
c.setTimeInMillis(date);
|
||||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.utils;
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.util.LongSparseArray;
|
import android.support.v4.util.LongSparseArray;
|
||||||
|
@ -68,6 +68,8 @@ public class ProfileIntervals<T extends Interval> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int binarySearch(long value) {
|
private int binarySearch(long value) {
|
||||||
|
if (rawData.size() == 0)
|
||||||
|
return -1;
|
||||||
int lo = 0;
|
int lo = 0;
|
||||||
int hi = rawData.size() - 1;
|
int hi = rawData.size() - 1;
|
||||||
|
|
||||||
|
@ -84,7 +86,7 @@ public class ProfileIntervals<T extends Interval> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// not found, try nearest older with duration 0
|
// not found, try nearest older with duration 0
|
||||||
while (lo >= 0) {
|
while (lo >= 0 && lo < rawData.size()) {
|
||||||
if (rawData.valueAt(lo).isEndingEvent())
|
if (rawData.valueAt(lo).isEndingEvent())
|
||||||
return lo;
|
return lo;
|
||||||
lo--;
|
lo--;
|
|
@ -31,10 +31,11 @@ import java.util.concurrent.TimeUnit;
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.events.EventCareportalEventChange;
|
import info.nightscout.androidaps.events.EventCareportalEventChange;
|
||||||
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
||||||
import info.nightscout.androidaps.events.EventNewBG;
|
import info.nightscout.androidaps.events.EventNewBG;
|
||||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
import info.nightscout.androidaps.events.EventProfileSwitchChange;
|
||||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||||
import info.nightscout.androidaps.events.EventReloadTempBasalData;
|
import info.nightscout.androidaps.events.EventReloadTempBasalData;
|
||||||
import info.nightscout.androidaps.events.EventReloadTreatmentData;
|
import info.nightscout.androidaps.events.EventReloadTreatmentData;
|
||||||
|
@ -42,7 +43,6 @@ import info.nightscout.androidaps.events.EventTempBasalChange;
|
||||||
import info.nightscout.androidaps.events.EventTempTargetChange;
|
import info.nightscout.androidaps.events.EventTempTargetChange;
|
||||||
import info.nightscout.androidaps.events.EventTreatmentChange;
|
import info.nightscout.androidaps.events.EventTreatmentChange;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync;
|
import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync;
|
||||||
|
|
||||||
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
|
@ -272,7 +272,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
scheduleCareportalEventChange();
|
scheduleCareportalEventChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetProfileSwitch() {
|
public void resetProfileSwitch() {
|
||||||
try {
|
try {
|
||||||
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
|
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
|
||||||
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
|
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
|
||||||
|
@ -1342,14 +1342,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
|
|
||||||
// ---------------- ProfileSwitch handling ---------------
|
// ---------------- ProfileSwitch handling ---------------
|
||||||
|
|
||||||
public List<ProfileSwitch> getProfileSwitchDataFromTime(long mills, boolean ascending) {
|
public List<ProfileSwitch> getProfileSwitchData(boolean ascending) {
|
||||||
try {
|
try {
|
||||||
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
|
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
|
||||||
List<ProfileSwitch> profileSwitches;
|
List<ProfileSwitch> profileSwitches;
|
||||||
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
|
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
|
||||||
queryBuilder.orderBy("date", ascending);
|
queryBuilder.orderBy("date", ascending);
|
||||||
Where where = queryBuilder.where();
|
queryBuilder.limit(20L);
|
||||||
where.ge("date", mills);
|
|
||||||
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
|
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
|
||||||
profileSwitches = daoProfileSwitch.query(preparedQuery);
|
profileSwitches = daoProfileSwitch.query(preparedQuery);
|
||||||
return profileSwitches;
|
return profileSwitches;
|
||||||
|
@ -1381,8 +1380,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
private static void scheduleProfileSwitchChange() {
|
private static void scheduleProfileSwitchChange() {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
log.debug("Firing EventNewBasalProfileChange");
|
log.debug("Firing EventProfileSwitchChange");
|
||||||
MainApp.bus().post(new EventNewBasalProfile());
|
MainApp.bus().post(new EventProfileSwitchChange());
|
||||||
scheduledProfileSwitchEventPost = null;
|
scheduledProfileSwitchEventPost = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1438,11 +1437,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
if (trJson.has("timeshift"))
|
if (trJson.has("timeshift"))
|
||||||
profileSwitch.timeshift = trJson.getInt("timeshift");
|
profileSwitch.timeshift = trJson.getInt("timeshift");
|
||||||
if (trJson.has("percentage"))
|
if (trJson.has("percentage"))
|
||||||
profileSwitch.percentage = trJson.getInt("percentage");
|
profileSwitch.percentage = trJson.getInt("percentage");
|
||||||
if (trJson.has("profileJson"))
|
if (trJson.has("profileJson"))
|
||||||
profileSwitch.profileJson = trJson.getString("profileJson");
|
profileSwitch.profileJson = trJson.getString("profileJson");
|
||||||
if (trJson.has("profilePlugin"))
|
if (trJson.has("profilePlugin"))
|
||||||
profileSwitch.profilePlugin = trJson.getString("profilePlugin");
|
profileSwitch.profilePlugin = trJson.getString("profilePlugin");
|
||||||
createOrUpdate(profileSwitch);
|
createOrUpdate(profileSwitch);
|
||||||
} catch (SQLException | JSONException e) {
|
} catch (SQLException | JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -8,14 +8,12 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.interfaces.Interval;
|
import info.nightscout.androidaps.interfaces.Interval;
|
||||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||||
import info.nightscout.utils.DateUtil;
|
import info.nightscout.utils.DateUtil;
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
|
||||||
|
|
||||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES)
|
@DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES)
|
||||||
public class ProfileSwitch implements Interval {
|
public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
|
||||||
private static Logger log = LoggerFactory.getLogger(ProfileSwitch.class);
|
private static Logger log = LoggerFactory.getLogger(ProfileSwitch.class);
|
||||||
|
|
||||||
@DatabaseField(id = true)
|
@DatabaseField(id = true)
|
||||||
|
@ -106,6 +104,25 @@ public class ProfileSwitch implements Interval {
|
||||||
|
|
||||||
// -------- Interval interface end ---------
|
// -------- Interval interface end ---------
|
||||||
|
|
||||||
|
// ----------------- DataPointInterface --------------------
|
||||||
|
@Override
|
||||||
|
public double getX() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
// default when no sgv around available
|
||||||
|
private double yValue = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getY() {
|
||||||
|
return yValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLabel() {
|
||||||
|
return profileName;
|
||||||
|
}
|
||||||
|
|
||||||
public String log() {
|
public String log() {
|
||||||
return "ProfileSwitch{" +
|
return "ProfileSwitch{" +
|
||||||
"date=" + date +
|
"date=" + date +
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 02.06.2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class EventProfileSwitchChange {
|
||||||
|
}
|
|
@ -10,8 +10,8 @@ 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.utils.OverlappingIntervals;
|
import info.nightscout.androidaps.data.OverlappingIntervals;
|
||||||
import info.nightscout.utils.ProfileIntervals;
|
import info.nightscout.androidaps.data.ProfileIntervals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 14.06.2016.
|
* Created by mike on 14.06.2016.
|
||||||
|
|
|
@ -47,8 +47,8 @@ import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogr
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||||
import info.nightscout.utils.NSUpload;
|
import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.OverlappingIntervals;
|
import info.nightscout.androidaps.data.OverlappingIntervals;
|
||||||
import info.nightscout.utils.ProfileIntervals;
|
import info.nightscout.androidaps.data.ProfileIntervals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 05.08.2016.
|
* Created by mike on 05.08.2016.
|
||||||
|
|
|
@ -227,6 +227,8 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void calculateSensitivityData() {
|
public void calculateSensitivityData() {
|
||||||
|
if (MainApp.getConfigBuilder() == null)
|
||||||
|
return; // app still initializing
|
||||||
//log.debug("Locking calculateSensitivityData");
|
//log.debug("Locking calculateSensitivityData");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
|
@ -514,6 +516,8 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onNewProfile(EventNewBasalProfile ev) {
|
public void onNewProfile(EventNewBasalProfile ev) {
|
||||||
|
if (MainApp.getConfigBuilder() == null)
|
||||||
|
return; // app still initializing
|
||||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
dia = profile.getDia();
|
dia = profile.getDia();
|
||||||
if (ev == null) { // on init no need of reset
|
if (ev == null) { // on init no need of reset
|
||||||
|
|
|
@ -70,6 +70,7 @@ import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.db.CareportalEvent;
|
import info.nightscout.androidaps.db.CareportalEvent;
|
||||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||||
|
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;
|
||||||
|
@ -107,6 +108,7 @@ import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoi
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.VerticalTextsGraphSeries;
|
||||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||||
import info.nightscout.utils.BolusWizard;
|
import info.nightscout.utils.BolusWizard;
|
||||||
import info.nightscout.utils.DateUtil;
|
import info.nightscout.utils.DateUtil;
|
||||||
|
@ -1112,6 +1114,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
PointsGraphSeries<BgReading> seriesHigh;
|
PointsGraphSeries<BgReading> seriesHigh;
|
||||||
PointsGraphSeries<BgReading> predSeries;
|
PointsGraphSeries<BgReading> predSeries;
|
||||||
PointsWithLabelGraphSeries<Treatment> seriesTreatments;
|
PointsWithLabelGraphSeries<Treatment> seriesTreatments;
|
||||||
|
VerticalTextsGraphSeries<ProfileSwitch> seriesProfileSwitch;
|
||||||
|
|
||||||
// **** TEMP BASALS graph ****
|
// **** TEMP BASALS graph ****
|
||||||
Double maxBasalValueFound = 0d;
|
Double maxBasalValueFound = 0d;
|
||||||
|
@ -1419,7 +1422,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
|
|
||||||
for (int tx = 0; tx < treatments.size(); tx++) {
|
for (int tx = 0; tx < treatments.size(); tx++) {
|
||||||
Treatment t = treatments.get(tx);
|
Treatment t = treatments.get(tx);
|
||||||
if (t.date < fromTime || t.date > now) continue;
|
if (t.date < fromTime || t.date > endTime) continue;
|
||||||
t.setYValue(bgReadingsArray);
|
t.setYValue(bgReadingsArray);
|
||||||
filteredTreatments.add(t);
|
filteredTreatments.add(t);
|
||||||
}
|
}
|
||||||
|
@ -1432,6 +1435,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
seriesTreatments.setColor(Color.CYAN);
|
seriesTreatments.setColor(Color.CYAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProfileSwitch
|
||||||
|
List<ProfileSwitch> profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList();
|
||||||
|
List<ProfileSwitch> filteredProfileSwitches = new ArrayList<ProfileSwitch>();
|
||||||
|
|
||||||
|
for (int tx = 0; tx < profileSwitches.size(); tx++) {
|
||||||
|
ProfileSwitch t = profileSwitches.get(tx);
|
||||||
|
if (t.date < fromTime || t.date > now) continue;
|
||||||
|
filteredProfileSwitches.add(t);
|
||||||
|
}
|
||||||
|
ProfileSwitch[] profileSwitchArray = new ProfileSwitch[filteredProfileSwitches.size()];
|
||||||
|
profileSwitchArray = filteredProfileSwitches.toArray(profileSwitchArray);
|
||||||
|
if (profileSwitchArray.length > 0) {
|
||||||
|
bgGraph.addSeries(seriesProfileSwitch = new VerticalTextsGraphSeries<ProfileSwitch>(profileSwitchArray));
|
||||||
|
//seriesProfileSwitch.setShape(PointsWithLabelGraphSeries.Shape.TRIANGLE);
|
||||||
|
seriesProfileSwitch.setSize(10);
|
||||||
|
seriesProfileSwitch.setColor(Color.CYAN);
|
||||||
|
}
|
||||||
|
|
||||||
// set manual y bounds to have nice steps
|
// set manual y bounds to have nice steps
|
||||||
bgGraph.getViewport().setMaxY(maxBgValue);
|
bgGraph.getViewport().setMaxY(maxBgValue);
|
||||||
bgGraph.getViewport().setMinY(0);
|
bgGraph.getViewport().setMinY(0);
|
||||||
|
|
|
@ -0,0 +1,326 @@
|
||||||
|
package info.nightscout.androidaps.plugins.Overview.graphExtensions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GraphView
|
||||||
|
* Copyright (C) 2014 Jonas Gehring
|
||||||
|
* <p>
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License,
|
||||||
|
* with the "Linking Exception", which can be found at the license.txt
|
||||||
|
* file in this program.
|
||||||
|
* <p>
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* <p>
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* with the "Linking Exception" along with this program; if not,
|
||||||
|
* write to the author Jonas Gehring <g.jjoe64@gmail.com>.
|
||||||
|
* <p>
|
||||||
|
* Added by mike
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Added by mike
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
|
||||||
|
import com.jjoe64.graphview.GraphView;
|
||||||
|
import com.jjoe64.graphview.series.BaseSeries;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Series that plots the data as points.
|
||||||
|
* The points can be different shapes or a
|
||||||
|
* complete custom drawing.
|
||||||
|
*
|
||||||
|
* @author jjoe64
|
||||||
|
*/
|
||||||
|
public class VerticalTextsGraphSeries<E extends DataPointWithLabelInterface> extends BaseSeries<E> {
|
||||||
|
/**
|
||||||
|
* interface to implement a custom
|
||||||
|
* drawing for the data points.
|
||||||
|
*/
|
||||||
|
public static interface CustomShape {
|
||||||
|
/**
|
||||||
|
* called when drawing a single data point.
|
||||||
|
* use the x and y coordinates to render your
|
||||||
|
* drawing at this point.
|
||||||
|
*
|
||||||
|
* @param canvas canvas to draw on
|
||||||
|
* @param paint internal paint object. this has the correct color.
|
||||||
|
* But you can use your own paint.
|
||||||
|
* @param x x-coordinate the point has to be drawn to
|
||||||
|
* @param y y-coordinate the point has to be drawn to
|
||||||
|
* @param dataPoint the related data point
|
||||||
|
*/
|
||||||
|
void draw(Canvas canvas, Paint paint, float x, float y, DataPointWithLabelInterface dataPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* choose a predefined shape to render for
|
||||||
|
* each data point.
|
||||||
|
* You can also render a custom drawing via {@link com.jjoe64.graphview.series.PointsGraphSeries.CustomShape}
|
||||||
|
*/
|
||||||
|
public enum Shape {
|
||||||
|
/**
|
||||||
|
* draws a point / circle
|
||||||
|
*/
|
||||||
|
POINT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* draws a triangle
|
||||||
|
*/
|
||||||
|
TRIANGLE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* draws a rectangle
|
||||||
|
*/
|
||||||
|
RECTANGLE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wrapped styles for this series
|
||||||
|
*/
|
||||||
|
private final class Styles {
|
||||||
|
/**
|
||||||
|
* this is used for the size of the shape that
|
||||||
|
* will be drawn.
|
||||||
|
* This is useless if you are using a custom shape.
|
||||||
|
*/
|
||||||
|
float size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the shape that will be drawn for each point.
|
||||||
|
*/
|
||||||
|
Shape shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wrapped styles
|
||||||
|
*/
|
||||||
|
private Styles mStyles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* internal paint object
|
||||||
|
*/
|
||||||
|
private Paint mPaint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handler to use a custom drawing
|
||||||
|
*/
|
||||||
|
private CustomShape mCustomShape;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates the series without data
|
||||||
|
*/
|
||||||
|
public VerticalTextsGraphSeries() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates the series with data
|
||||||
|
*
|
||||||
|
* @param data datapoints
|
||||||
|
*/
|
||||||
|
public VerticalTextsGraphSeries(E[] data) {
|
||||||
|
super(data);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inits the internal objects
|
||||||
|
* set the defaults
|
||||||
|
*/
|
||||||
|
protected void init() {
|
||||||
|
mStyles = new Styles();
|
||||||
|
mStyles.size = 20f;
|
||||||
|
mPaint = new Paint();
|
||||||
|
mPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
setShape(Shape.POINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* plot the data to the viewport
|
||||||
|
*
|
||||||
|
* @param graphView graphview
|
||||||
|
* @param canvas canvas to draw on
|
||||||
|
* @param isSecondScale whether it is the second scale
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) {
|
||||||
|
resetDataPoints();
|
||||||
|
|
||||||
|
// get data
|
||||||
|
double maxX = graphView.getViewport().getMaxX(false);
|
||||||
|
double minX = graphView.getViewport().getMinX(false);
|
||||||
|
|
||||||
|
double maxY;
|
||||||
|
double minY;
|
||||||
|
if (isSecondScale) {
|
||||||
|
maxY = graphView.getSecondScale().getMaxY();
|
||||||
|
minY = graphView.getSecondScale().getMinY();
|
||||||
|
} else {
|
||||||
|
maxY = graphView.getViewport().getMaxY(false);
|
||||||
|
minY = graphView.getViewport().getMinY(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<E> values = getValues(minX, maxX);
|
||||||
|
|
||||||
|
// draw background
|
||||||
|
double lastEndY = 0;
|
||||||
|
double lastEndX = 0;
|
||||||
|
|
||||||
|
// draw data
|
||||||
|
mPaint.setColor(getColor());
|
||||||
|
|
||||||
|
double diffY = maxY - minY;
|
||||||
|
double diffX = maxX - minX;
|
||||||
|
|
||||||
|
float graphHeight = graphView.getGraphContentHeight();
|
||||||
|
float graphWidth = graphView.getGraphContentWidth();
|
||||||
|
float graphLeft = graphView.getGraphContentLeft();
|
||||||
|
float graphTop = graphView.getGraphContentTop();
|
||||||
|
|
||||||
|
lastEndY = 0;
|
||||||
|
lastEndX = 0;
|
||||||
|
float firstX = 0;
|
||||||
|
int i = 0;
|
||||||
|
while (values.hasNext()) {
|
||||||
|
E value = values.next();
|
||||||
|
|
||||||
|
double valY = value.getY() - minY;
|
||||||
|
double ratY = valY / diffY;
|
||||||
|
double y = graphHeight * ratY;
|
||||||
|
|
||||||
|
double valX = value.getX() - minX;
|
||||||
|
double ratX = valX / diffX;
|
||||||
|
double x = graphWidth * ratX;
|
||||||
|
|
||||||
|
double orgX = x;
|
||||||
|
double orgY = y;
|
||||||
|
|
||||||
|
// overdraw
|
||||||
|
boolean overdraw = false;
|
||||||
|
if (x > graphWidth) { // end right
|
||||||
|
overdraw = true;
|
||||||
|
}
|
||||||
|
if (y < 0) { // end bottom
|
||||||
|
overdraw = true;
|
||||||
|
}
|
||||||
|
if (y > graphHeight) { // end top
|
||||||
|
overdraw = true;
|
||||||
|
}
|
||||||
|
/* Fix a bug that continue to show the DOT after Y axis */
|
||||||
|
if (x < 0) {
|
||||||
|
overdraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float endX = (float) x + (graphLeft + 1);
|
||||||
|
float endY = (float) (graphTop - y) + graphHeight;
|
||||||
|
registerDataPoint(endX, endY, value);
|
||||||
|
|
||||||
|
// draw data point
|
||||||
|
if (!overdraw) {
|
||||||
|
if (value.getLabel() != null) {
|
||||||
|
mPaint.setTextSize((int) (getSize() * 3));
|
||||||
|
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
|
||||||
|
Rect bounds = new Rect();
|
||||||
|
mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
|
||||||
|
mPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
float px = endX;
|
||||||
|
float py = (float) (graphHeight * ratY + bounds.height() + 80);
|
||||||
|
canvas.save();
|
||||||
|
canvas.rotate(-90, px, py);
|
||||||
|
canvas.drawText(value.getLabel(), px, py, mPaint);
|
||||||
|
canvas.drawRect(bounds.left + px - 3, bounds.top + py - 3, bounds.right + px + 3, bounds.bottom + py + 3, mPaint);
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper to render triangle
|
||||||
|
*
|
||||||
|
* @param point array with 3 coordinates
|
||||||
|
* @param canvas canvas to draw on
|
||||||
|
* @param paint paint object
|
||||||
|
*/
|
||||||
|
private void drawArrows(Point[] point, Canvas canvas, Paint paint) {
|
||||||
|
float[] points = new float[8];
|
||||||
|
points[0] = point[0].x;
|
||||||
|
points[1] = point[0].y;
|
||||||
|
points[2] = point[1].x;
|
||||||
|
points[3] = point[1].y;
|
||||||
|
points[4] = point[2].x;
|
||||||
|
points[5] = point[2].y;
|
||||||
|
points[6] = point[0].x;
|
||||||
|
points[7] = point[0].y;
|
||||||
|
|
||||||
|
canvas.drawVertices(Canvas.VertexMode.TRIANGLES, 8, points, 0, null, 0, null, 0, null, 0, 0, paint);
|
||||||
|
Path path = new Path();
|
||||||
|
path.moveTo(point[0].x, point[0].y);
|
||||||
|
path.lineTo(point[1].x, point[1].y);
|
||||||
|
path.lineTo(point[2].x, point[2].y);
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used for the size of the shape that
|
||||||
|
* will be drawn.
|
||||||
|
* This is useless if you are using a custom shape.
|
||||||
|
*
|
||||||
|
* @return the size of the shape
|
||||||
|
*/
|
||||||
|
public float getSize() {
|
||||||
|
return mStyles.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used for the size of the shape that
|
||||||
|
* will be drawn.
|
||||||
|
* This is useless if you are using a custom shape.
|
||||||
|
*
|
||||||
|
* @param radius the size of the shape
|
||||||
|
*/
|
||||||
|
public void setSize(float radius) {
|
||||||
|
mStyles.size = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the shape that will be drawn for each point
|
||||||
|
*/
|
||||||
|
public Shape getShape() {
|
||||||
|
return mStyles.shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param s the shape that will be drawn for each point
|
||||||
|
*/
|
||||||
|
public void setShape(Shape s) {
|
||||||
|
mStyles.shape = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a custom handler to render your own
|
||||||
|
* drawing for each data point.
|
||||||
|
*
|
||||||
|
* @param shape handler to use a custom drawing
|
||||||
|
*/
|
||||||
|
public void setCustomShape(CustomShape shape) {
|
||||||
|
mCustomShape = shape;
|
||||||
|
}
|
||||||
|
}
|
|
@ -102,7 +102,7 @@ public class PersistentNotificationPlugin implements PluginBase {
|
||||||
if (getType() == type) {
|
if (getType() == type) {
|
||||||
this.fragmentEnabled = fragmentEnabled;
|
this.fragmentEnabled = fragmentEnabled;
|
||||||
checkBusRegistration();
|
checkBusRegistration();
|
||||||
updateNotification();
|
//updateNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
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.DetailedBolusInfo;
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||||
|
@ -22,6 +23,8 @@ 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.events.EventNewBasalProfile;
|
||||||
|
import info.nightscout.androidaps.events.EventProfileSwitchChange;
|
||||||
import info.nightscout.androidaps.events.EventReloadTempBasalData;
|
import info.nightscout.androidaps.events.EventReloadTempBasalData;
|
||||||
import info.nightscout.androidaps.events.EventReloadTreatmentData;
|
import info.nightscout.androidaps.events.EventReloadTreatmentData;
|
||||||
import info.nightscout.androidaps.events.EventTempTargetChange;
|
import info.nightscout.androidaps.events.EventTempTargetChange;
|
||||||
|
@ -31,8 +34,8 @@ import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.utils.OverlappingIntervals;
|
import info.nightscout.androidaps.data.OverlappingIntervals;
|
||||||
import info.nightscout.utils.ProfileIntervals;
|
import info.nightscout.androidaps.data.ProfileIntervals;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,6 +51,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
private static OverlappingIntervals<TemporaryBasal> tempBasals = new OverlappingIntervals<>();
|
private static OverlappingIntervals<TemporaryBasal> tempBasals = new OverlappingIntervals<>();
|
||||||
private static OverlappingIntervals<ExtendedBolus> extendedBoluses = new OverlappingIntervals<>();
|
private static OverlappingIntervals<ExtendedBolus> extendedBoluses = new OverlappingIntervals<>();
|
||||||
private static OverlappingIntervals<TempTarget> tempTargets = new OverlappingIntervals<>();
|
private static OverlappingIntervals<TempTarget> tempTargets = new OverlappingIntervals<>();
|
||||||
|
private static ProfileIntervals<ProfileSwitch> profiles = new ProfileIntervals<>();
|
||||||
|
|
||||||
private static boolean fragmentEnabled = true;
|
private static boolean fragmentEnabled = true;
|
||||||
private static boolean fragmentVisible = true;
|
private static boolean fragmentVisible = true;
|
||||||
|
@ -119,11 +123,12 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
initializeTreatmentData();
|
initializeTreatmentData();
|
||||||
initializeExtendedBolusData();
|
initializeExtendedBolusData();
|
||||||
initializeTempTargetData();
|
initializeTempTargetData();
|
||||||
|
initializeProfileSwitchData();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initializeTreatmentData() {
|
public static void initializeTreatmentData() {
|
||||||
// Treatments
|
// Treatments
|
||||||
double dia = MainApp.getConfigBuilder().getProfile().getDia();
|
double dia = MainApp.getConfigBuilder() == null ? Constants.defaultDIA : MainApp.getConfigBuilder().getProfile().getDia();
|
||||||
long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia));
|
long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia));
|
||||||
|
|
||||||
treatments = MainApp.getDbHelper().getTreatmentDataFromTime(fromMills, false);
|
treatments = MainApp.getDbHelper().getTreatmentDataFromTime(fromMills, false);
|
||||||
|
@ -131,7 +136,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
|
|
||||||
public static void initializeTempBasalData() {
|
public static void initializeTempBasalData() {
|
||||||
// Treatments
|
// Treatments
|
||||||
double dia = MainApp.getConfigBuilder().getProfile().getDia();
|
double dia = MainApp.getConfigBuilder() == null ? Constants.defaultDIA : MainApp.getConfigBuilder().getProfile().getDia();
|
||||||
long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia));
|
long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia));
|
||||||
|
|
||||||
tempBasals.reset().add(MainApp.getDbHelper().getTemporaryBasalsDataFromTime(fromMills, false));
|
tempBasals.reset().add(MainApp.getDbHelper().getTemporaryBasalsDataFromTime(fromMills, false));
|
||||||
|
@ -140,7 +145,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
|
|
||||||
public static void initializeExtendedBolusData() {
|
public static void initializeExtendedBolusData() {
|
||||||
// Treatments
|
// Treatments
|
||||||
double dia = MainApp.getConfigBuilder().getProfile().getDia();
|
double dia = MainApp.getConfigBuilder() == null ? Constants.defaultDIA : MainApp.getConfigBuilder().getProfile().getDia();
|
||||||
long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia));
|
long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia));
|
||||||
|
|
||||||
extendedBoluses.reset().add(MainApp.getDbHelper().getExtendedBolusDataFromTime(fromMills, false));
|
extendedBoluses.reset().add(MainApp.getDbHelper().getExtendedBolusDataFromTime(fromMills, false));
|
||||||
|
@ -152,6 +157,10 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
tempTargets.reset().add(MainApp.getDbHelper().getTemptargetsDataFromTime(fromMills, false));
|
tempTargets.reset().add(MainApp.getDbHelper().getTemptargetsDataFromTime(fromMills, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initializeProfileSwitchData() {
|
||||||
|
profiles.reset().add(MainApp.getDbHelper().getProfileSwitchData(false));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IobTotal getLastCalculationTreatments() {
|
public IobTotal getLastCalculationTreatments() {
|
||||||
return lastTreatmentCalculation;
|
return lastTreatmentCalculation;
|
||||||
|
@ -446,14 +455,20 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
return tempTargets;
|
return tempTargets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Profile Switch
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventProfileSwitchChange ev) {
|
||||||
|
initializeProfileSwitchData();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProfileSwitch getProfileSwitchFromHistory(long time) {
|
public ProfileSwitch getProfileSwitchFromHistory(long time) {
|
||||||
return null;
|
return (ProfileSwitch) profiles.getValueToTime(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory() {
|
public ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory() {
|
||||||
return null;
|
return profiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,7 +34,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.utils.OverlappingIntervals;
|
import info.nightscout.androidaps.data.OverlappingIntervals;
|
||||||
|
|
||||||
|
|
||||||
public class TreatmentsExtendedBolusesFragment extends Fragment {
|
public class TreatmentsExtendedBolusesFragment extends Fragment {
|
||||||
|
|
|
@ -29,7 +29,7 @@ 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.utils.OverlappingIntervals;
|
import info.nightscout.androidaps.data.OverlappingIntervals;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -34,7 +34,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.utils.OverlappingIntervals;
|
import info.nightscout.androidaps.data.OverlappingIntervals;
|
||||||
|
|
||||||
|
|
||||||
public class TreatmentsTemporaryBasalsFragment extends Fragment {
|
public class TreatmentsTemporaryBasalsFragment extends Fragment {
|
||||||
|
|
Loading…
Reference in a new issue