From 6a88e43ac6b09c0129721b79b60b7acd60860df7 Mon Sep 17 00:00:00 2001 From: trentsuzuki Date: Mon, 12 May 2025 17:53:30 -0400 Subject: [PATCH] Refactor sleep chart fragments --- .../charts/CaloriesPeriodFragment.java | 5 + .../charts/HeartRatePeriodFragment.java | 5 + .../charts/RespiratoryRatePeriodFragment.java | 5 + ...tFragment.java => SleepDailyFragment.java} | 59 +--- .../activities/charts/SleepFragment.java | 82 +++++ ...Fragment.java => SleepPeriodFragment.java} | 322 +++++++++++++++--- .../charts/StepsPeriodFragment.java | 5 + .../adapter/HeartRateFragmentAdapter.java | 3 - .../adapter/SleepFragmentAdapter.java | 12 +- 9 files changed, 391 insertions(+), 107 deletions(-) rename app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/{DaySleepChartFragment.java => SleepDailyFragment.java} (91%) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepFragment.java rename app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/{WeekSleepChartFragment.java => SleepPeriodFragment.java} (61%) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/CaloriesPeriodFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/CaloriesPeriodFragment.java index 38989e9475..1feac094c8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/CaloriesPeriodFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/CaloriesPeriodFragment.java @@ -55,6 +55,11 @@ public class CaloriesPeriodFragment extends CaloriesFragment { - protected static final Logger LOG = LoggerFactory.getLogger(DaySleepChartFragment.class); +public class SleepDailyFragment extends SleepFragment { + protected static final Logger LOG = LoggerFactory.getLogger(SleepDailyFragment.class); private LineChart mActivityChart; private ImageView sleepStagesGauge; @@ -134,8 +141,6 @@ public class DaySleepChartFragment extends AbstractActivityChartFragment samples, List sleepScoreSamples) { SleepAnalysis sleepAnalysis = new SleepAnalysis(); List sleepSessions = sleepAnalysis.calculateSleepSessions(samples); @@ -364,15 +369,7 @@ public class DaySleepChartFragment extends AbstractActivityChartFragment chart) { - List legendEntries = new ArrayList<>(4); - LegendEntry lightSleepEntry = new LegendEntry(); - lightSleepEntry.label = getActivity().getString(R.string.sleep_colored_stats_light); - lightSleepEntry.formColor = akLightSleep.color; - legendEntries.add(lightSleepEntry); - - LegendEntry deepSleepEntry = new LegendEntry(); - deepSleepEntry.label = getActivity().getString(R.string.sleep_colored_stats_deep); - deepSleepEntry.formColor = akDeepSleep.color; - legendEntries.add(deepSleepEntry); - - if (supportsRemSleep(getChartsHost().getDevice())) { - LegendEntry remSleepEntry = new LegendEntry(); - remSleepEntry.label = getActivity().getString(R.string.sleep_colored_stats_rem); - remSleepEntry.formColor = akRemSleep.color; - legendEntries.add(remSleepEntry); - } - - if (supportsAwakeSleep(getChartsHost().getDevice())) { - LegendEntry awakeSleepEntry = new LegendEntry(); - awakeSleepEntry.label = getActivity().getString(R.string.abstract_chart_fragment_kind_awake_sleep); - awakeSleepEntry.formColor = akAwakeSleep.color; - legendEntries.add(awakeSleepEntry); - } + List legendEntries = super.createLegendEntries(chart); if (supportsHeartrate(getChartsHost().getDevice())) { LegendEntry hrEntry = new LegendEntry(); @@ -498,17 +472,6 @@ public class DaySleepChartFragment extends AbstractActivityChartFragment getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) { - // Temporary fix for totally wrong sleep amounts. - return super.getAllSamples(db, device, tsFrom, tsTo); - } - - protected List getSleepScoreSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) { - TimeSampleProvider provider = device.getDeviceCoordinator().getSleepScoreProvider(device, db.getDaoSession()); - return (List) provider.getAllSamples(tsFrom * 1000L, tsTo * 1000L); - } - @Override protected void renderCharts() { mActivityChart.animateX(ANIM_TIME, Easing.EaseInOutQuart); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepFragment.java new file mode 100644 index 0000000000..5f657e7c04 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepFragment.java @@ -0,0 +1,82 @@ +package nodomain.freeyourgadget.gadgetbridge.activities.charts; + +import com.github.mikephil.charting.charts.Chart; +import com.github.mikephil.charting.components.LegendEntry; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; +import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.SleepScoreSample; + +abstract class SleepFragment extends AbstractActivityChartFragment { + @Override + public String getTitle() { + return getString(R.string.sleepchart_your_sleep); + } + + @Override + protected List getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) { + return super.getAllSamples(db, device, tsFrom, tsTo); + } + + public boolean supportsSleepScore() { + final GBDevice device = getChartsHost().getDevice(); + return device.getDeviceCoordinator().supportsSleepScore(device); + } + + protected List getSleepScoreSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) { + TimeSampleProvider provider = device.getDeviceCoordinator().getSleepScoreProvider(device, db.getDaoSession()); + return (List) provider.getAllSamples(tsFrom * 1000L, tsTo * 1000L); + } + + protected List getSleepScoreSamples(DBHandler db, GBDevice device, Calendar day) { + int startTs; + int endTs; + + day = (Calendar) day.clone(); // do not modify the caller's argument + day.set(Calendar.HOUR_OF_DAY, 0); + day.set(Calendar.MINUTE, 0); + day.set(Calendar.SECOND, 0); + day.add(Calendar.HOUR, 0); + startTs = (int) (day.getTimeInMillis() / 1000); + endTs = startTs + 24 * 60 * 60 - 1; + + TimeSampleProvider provider = device.getDeviceCoordinator().getSleepScoreProvider(device, db.getDaoSession()); + return (List) provider.getAllSamples(startTs * 1000L, endTs * 1000L); + } + + protected List createLegendEntries(Chart chart) { + List legendEntries = new ArrayList<>(4); + LegendEntry lightSleepEntry = new LegendEntry(); + lightSleepEntry.label = getActivity().getString(R.string.sleep_colored_stats_light); + lightSleepEntry.formColor = akLightSleep.color; + legendEntries.add(lightSleepEntry); + + LegendEntry deepSleepEntry = new LegendEntry(); + deepSleepEntry.label = getActivity().getString(R.string.sleep_colored_stats_deep); + deepSleepEntry.formColor = akDeepSleep.color; + legendEntries.add(deepSleepEntry); + + if (supportsRemSleep(getChartsHost().getDevice())) { + LegendEntry remSleepEntry = new LegendEntry(); + remSleepEntry.label = getActivity().getString(R.string.sleep_colored_stats_rem); + remSleepEntry.formColor = akRemSleep.color; + legendEntries.add(remSleepEntry); + } + + if (supportsAwakeSleep(getChartsHost().getDevice())) { + LegendEntry awakeSleepEntry = new LegendEntry(); + awakeSleepEntry.label = getActivity().getString(R.string.abstract_chart_fragment_kind_awake_sleep); + awakeSleepEntry.formColor = akAwakeSleep.color; + legendEntries.add(awakeSleepEntry); + } + + return legendEntries; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepPeriodFragment.java similarity index 61% rename from app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java rename to app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepPeriodFragment.java index c5e32f447e..5c6ec98ed2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/SleepPeriodFragment.java @@ -17,6 +17,8 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.activities.charts; +import android.app.Activity; +import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.view.LayoutInflater; @@ -25,24 +27,35 @@ import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; +import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.LegendEntry; +import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; +import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import org.apache.commons.lang3.ArrayUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; -import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.concurrent.TimeUnit; import nodomain.freeyourgadget.gadgetbridge.GBApplication; @@ -50,11 +63,17 @@ import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmount; import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmounts; import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; +import nodomain.freeyourgadget.gadgetbridge.model.SleepScoreSample; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; +import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue; -public class WeekSleepChartFragment extends AbstractWeekChartFragment { +public class SleepPeriodFragment extends SleepFragment { + protected static final Logger LOG = LoggerFactory.getLogger(SleepPeriodFragment.class); + protected int TOTAL_DAYS = getRangeDays(); + protected int TOTAL_DAYS_FOR_AVERAGE = 0; private TextView awakeSleepTimeText; private LinearLayout awakeSleepTimeTextWrapper; private TextView remSleepTimeText; @@ -67,11 +86,16 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { private LineChart sleepScoreChart; private TextView mBalanceView; + protected Locale mLocale; + protected int mTargetValue = 0; + + protected BarChart mWeekChart; + private final int mOffsetHours = getOffsetHours(); protected boolean SHOW_BALANCE; - public static WeekSleepChartFragment newInstance ( int totalDays ) { - WeekSleepChartFragment fragmentFirst = new WeekSleepChartFragment(); + public static SleepPeriodFragment newInstance(int totalDays) { + SleepPeriodFragment fragmentFirst = new SleepPeriodFragment(); Bundle args = new Bundle(); args.putInt("totalDays", totalDays); fragmentFirst.setArguments(args); @@ -167,7 +191,38 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { } protected void setupWeekChart() { - super.setupWeekChart(); + mWeekChart.setBackgroundColor(BACKGROUND_COLOR); + mWeekChart.getDescription().setTextColor(DESCRIPTION_COLOR); + mWeekChart.getDescription().setText(""); + mWeekChart.setFitBars(true); + + configureBarLineChartDefaults(mWeekChart); + + XAxis x = mWeekChart.getXAxis(); + x.setDrawLabels(true); + x.setDrawGridLines(false); + x.setEnabled(true); + x.setTextColor(CHART_TEXT_COLOR); + x.setDrawLimitLinesBehindData(true); + x.setPosition(XAxis.XAxisPosition.BOTTOM); + + YAxis y = mWeekChart.getAxisLeft(); + y.setDrawGridLines(false); + y.setDrawTopYLabelEntry(false); + y.setTextColor(CHART_TEXT_COLOR); + y.setDrawZeroLine(true); + y.setSpaceBottom(0); + y.setAxisMinimum(0); + y.setValueFormatter(getYAxisFormatter()); + y.setEnabled(true); + + YAxis yAxisRight = mWeekChart.getAxisRight(); + yAxisRight.setDrawGridLines(false); + yAxisRight.setEnabled(false); + yAxisRight.setDrawLabels(false); + yAxisRight.setDrawTopYLabelEntry(false); + yAxisRight.setTextColor(CHART_TEXT_COLOR); + if (TOTAL_DAYS > 7) { mWeekChart.setRenderer(new AngledLabelsChartRenderer(mWeekChart, mWeekChart.getAnimator(), mWeekChart.getViewPortHandler())); } else { @@ -236,6 +291,129 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { return new MyChartsData(weekBeforeData); } + protected WeekChartsData refreshWeekBeforeData(DBHandler db, BarChart barChart, Calendar day, GBDevice device) { + day = (Calendar) day.clone(); // do not modify the caller's argument + day.add(Calendar.DATE, -TOTAL_DAYS + 1); + List entries = new ArrayList<>(); + ArrayList labels = new ArrayList(); + + long balance = 0; + long daily_balance = 0; + TOTAL_DAYS_FOR_AVERAGE=0; + List sleepScoreEntities = new ArrayList<>(); + final List sleepScoreDataSets = new ArrayList<>(); + for (int counter = 0; counter < TOTAL_DAYS; counter++) { + // Sleep stages + ActivityAmounts amounts = getActivityAmountsForDay(db, day, device); + daily_balance=calculateBalance(amounts); + if (daily_balance > 0) { + TOTAL_DAYS_FOR_AVERAGE++; + } + balance += daily_balance; + entries.add(new BarEntry(counter, getTotalsForActivityAmounts(amounts))); + labels.add(getWeeksChartsLabel(day)); + // Sleep score + if (supportsSleepScore()) { + List sleepScoreSamples = getSleepScoreSamples(db, device, day); + if (!sleepScoreSamples.isEmpty() && sleepScoreSamples.get(0).getSleepScore() > 0) { + sleepScoreEntities.add(new Entry(counter, sleepScoreSamples.get(0).getSleepScore())); + } else { + if (!sleepScoreEntities.isEmpty()) { + List clone = new ArrayList<>(sleepScoreEntities.size()); + clone.addAll(sleepScoreEntities); + sleepScoreDataSets.add(createSleepScoreDataSet(clone)); + sleepScoreEntities.clear(); + } + } + } + day.add(Calendar.DATE, 1); + } + if (!sleepScoreEntities.isEmpty()) { + sleepScoreDataSets.add(createSleepScoreDataSet(sleepScoreEntities)); + } + final LineData sleepScoreLineData = new LineData(sleepScoreDataSets); + sleepScoreLineData.setHighlightEnabled(false); + + BarDataSet set = new BarDataSet(entries, ""); + set.setColors(getColors()); + set.setValueFormatter(getBarValueFormatter()); + + BarData barData = new BarData(set); + barData.setValueTextColor(Color.GRAY); //prevent tearing other graph elements with the black text. Another approach would be to hide the values cmpletely with data.setDrawValues(false); + barData.setValueTextSize(10f); + + barChart.getAxisLeft().setAxisMaximum(Math.max(set.getYMax(), mTargetValue) + 60); + + LimitLine target = new LimitLine(mTargetValue); + target.setLineWidth(1.5f); + target.enableDashedLine(15f, 10f, 0f); + target.setLineColor(getResources().getColor(R.color.chart_deep_sleep_dark)); + barChart.getAxisLeft().removeAllLimitLines(); + barChart.getAxisLeft().addLimitLine(target); + + float average = 0; + if (TOTAL_DAYS_FOR_AVERAGE > 0) { + average = Math.abs(balance / TOTAL_DAYS_FOR_AVERAGE); + } + LimitLine average_line = new LimitLine(average); + average_line.setLineWidth(1.5f); + average_line.enableDashedLine(15f, 10f, 0f); + average_line.setLabel(getString(R.string.average, getAverage(average))); + + if (average > (mTargetValue)) { + average_line.setLineColor(Color.GREEN); + average_line.setTextColor(Color.GREEN); + } + else { + average_line.setLineColor(Color.RED); + average_line.setTextColor(Color.RED); + } + if (average > 0) { + if (GBApplication.getPrefs().getBoolean("charts_show_average", true)) { + barChart.getAxisLeft().addLimitLine(average_line); + } + } + + if (supportsSleepScore()) { + return new WeekChartsData(barData, new PreformattedXIndexLabelFormatter(labels), getBalanceMessage(balance, mTargetValue), sleepScoreLineData); + } + return new WeekChartsData(barData, new PreformattedXIndexLabelFormatter(labels), getBalanceMessage(balance, mTargetValue)); + } + + protected String getWeeksChartsLabel(Calendar day){ + if (TOTAL_DAYS > 7) { + //month, show day date + return String.valueOf(day.get(Calendar.DAY_OF_MONTH)); + } + else{ + //week, show short day name + return day.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, mLocale); + } + } + + protected LineDataSet createSleepScoreDataSet(final List values) { + final LineDataSet lineDataSet = new LineDataSet(values, getString(R.string.sleep_score)); + lineDataSet.setColor(getResources().getColor(R.color.chart_light_sleep_light)); + lineDataSet.setDrawCircles(false); + lineDataSet.setLineWidth(2f); + lineDataSet.setFillAlpha(255); + lineDataSet.setCircleRadius(5f); + lineDataSet.setDrawCircles(true); + lineDataSet.setDrawCircleHole(true); + lineDataSet.setCircleColor(getResources().getColor(R.color.chart_light_sleep_light)); + lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT); + lineDataSet.setDrawValues(true); + lineDataSet.setValueTextSize(10f); + lineDataSet.setValueTextColor(CHART_TEXT_COLOR); + lineDataSet.setValueFormatter(new ValueFormatter() { + @Override + public String getFormattedValue(float value) { + return String.format(Locale.ROOT, "%d", (int) value); + } + }); + return lineDataSet; + }; + private void setupSleepScoreChart() { final XAxis xAxisBottom = sleepScoreChart.getXAxis(); xAxisBottom.setPosition(XAxis.XAxisPosition.BOTTOM); @@ -287,23 +465,19 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { } } - @Override String getPieDescription(int targetValue) { return getString(R.string.weeksleepchart_today_sleep_description, DateTimeUtils.formatDurationHoursMinutes(targetValue, TimeUnit.MINUTES)); } - @Override int getGoal() { return GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_SLEEP_DURATION, 8) * 60; } - @Override int getOffsetHours() { return -12; } - @Override protected long calculateBalance(ActivityAmounts activityAmounts) { long balance = 0; @@ -317,7 +491,6 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { return (int) (balance / 60); } - @Override protected String getBalanceMessage(long balance, int targetValue) { if (balance > 0) { final long totalBalance = balance - ((long)targetValue * TOTAL_DAYS_FOR_AVERAGE); @@ -329,7 +502,6 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { return getString(R.string.no_data); } - @Override float[] getTotalsForActivityAmounts(ActivityAmounts activityAmounts) { long totalSecondsDeepSleep = 0; long totalSecondsLightSleep = 0; @@ -362,12 +534,10 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { return activityAmountsTotals; } - @Override protected String formatPieValue(long value) { return DateTimeUtils.formatDurationHoursMinutes(value, TimeUnit.MINUTES); } - @Override String[] getPieLabels() { String[] labels = { getString(R.string.abstract_chart_fragment_kind_deep_sleep), @@ -382,7 +552,6 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { return labels; } - @Override ValueFormatter getPieValueFormatter() { return new ValueFormatter() { @Override @@ -392,7 +561,6 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { }; } - @Override ValueFormatter getBarValueFormatter() { return new ValueFormatter() { @Override @@ -402,7 +570,6 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { }; } - @Override ValueFormatter getYAxisFormatter() { return new ValueFormatter() { @Override @@ -412,7 +579,6 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { }; } - @Override int[] getColors() { int[] colors = {akDeepSleep.color, akLightSleep.color}; if (supportsRemSleep(getChartsHost().getDevice())) { @@ -426,33 +592,9 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { @Override protected void setupLegend(Chart chart) { - List legendEntries = new ArrayList<>(2); - - LegendEntry lightSleepEntry = new LegendEntry(); - lightSleepEntry.label = getActivity().getString(R.string.sleep_colored_stats_light); - lightSleepEntry.formColor = akLightSleep.color; - legendEntries.add(lightSleepEntry); - - LegendEntry deepSleepEntry = new LegendEntry(); - deepSleepEntry.label = getActivity().getString(R.string.sleep_colored_stats_deep); - deepSleepEntry.formColor = akDeepSleep.color; - legendEntries.add(deepSleepEntry); - - if (supportsRemSleep(getChartsHost().getDevice())) { - LegendEntry remSleepEntry = new LegendEntry(); - remSleepEntry.label = getActivity().getString(R.string.sleep_colored_stats_rem); - remSleepEntry.formColor = akRemSleep.color; - legendEntries.add(remSleepEntry); - } - - if (supportsAwakeSleep(getChartsHost().getDevice())) { - LegendEntry awakeSleepEntry = new LegendEntry(); - awakeSleepEntry.label = getActivity().getString(R.string.abstract_chart_fragment_kind_awake_sleep); - awakeSleepEntry.formColor = akAwakeSleep.color; - legendEntries.add(awakeSleepEntry); - } - + List legendEntries = super.createLegendEntries(chart); chart.getLegend().setCustom(legendEntries); + chart.getLegend().setTextColor(LEGEND_TEXT_COLOR); chart.getLegend().setWordWrapEnabled(true); chart.getLegend().setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); @@ -462,17 +604,97 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { return DateTimeUtils.formatDurationHoursMinutes(value, TimeUnit.MINUTES); } - @Override String getAverage(float value) { return getHM((long)value); } + protected static class MyChartsData extends ChartsData { + private final WeekChartsData weekBeforeData; + + MyChartsData(WeekChartsData weekBeforeData) { + this.weekBeforeData = weekBeforeData; + } + + WeekChartsData getWeekBeforeData() { + return weekBeforeData; + } + } + + protected ActivityAmounts getActivityAmountsForDay(DBHandler db, Calendar day, GBDevice device) { + + LimitedQueue activityAmountCache = null; + ActivityAmounts amounts = null; + + Activity activity = getActivity(); + int key = (int) (day.getTimeInMillis() / 1000) + (mOffsetHours * 3600); + if (activity != null) { + activityAmountCache = ((ActivityChartsActivity) activity).mActivityAmountCache; + amounts = activityAmountCache.lookup(key); + } + + if (amounts == null) { + ActivityAnalysis analysis = new ActivityAnalysis(); + amounts = analysis.calculateActivityAmounts(getSamplesOfDay(db, day, mOffsetHours, device)); + if (activityAmountCache != null) { + activityAmountCache.add(key, amounts); + } + } + + return amounts; + } + + private List getSamplesOfDay(DBHandler db, Calendar day, int offsetHours, GBDevice device) { + int startTs; + int endTs; + + day = (Calendar) day.clone(); // do not modify the caller's argument + day.set(Calendar.HOUR_OF_DAY, 0); + day.set(Calendar.MINUTE, 0); + day.set(Calendar.SECOND, 0); + day.add(Calendar.HOUR, offsetHours); + + startTs = (int) (day.getTimeInMillis() / 1000); + endTs = startTs + 24 * 60 * 60 - 1; + + return getSamples(db, device, startTs, endTs); + } + + private int getRangeDays(){ + if (GBApplication.getPrefs().getBoolean("charts_range", true)) { + return 30;} + else{ + return 7; + } + } + + protected class WeekChartsData> extends DefaultChartsData { + private final String balanceMessage; + private LineData sleepScoresLineData; + + public WeekChartsData(T data, PreformattedXIndexLabelFormatter xIndexLabelFormatter, String balanceMessage) { + super(data, xIndexLabelFormatter); + this.balanceMessage = balanceMessage; + } + + public WeekChartsData(T data, PreformattedXIndexLabelFormatter xIndexLabelFormatter, String balanceMessage, LineData sleepScores) { + super(data, xIndexLabelFormatter); + this.balanceMessage = balanceMessage; + this.sleepScoresLineData = sleepScores; + } + + public String getBalanceMessage() { + return balanceMessage; + } + + public LineData getSleepScoreData() { return sleepScoresLineData; } + } + private static class MySleepWeeklyData { - private long totalAwake; - private long totalRem; - private long totalDeep; - private long totalLight; - private int totalDaysForAverage; + private final long totalAwake; + private final long totalRem; + private final long totalDeep; + private final long totalLight; + private final int totalDaysForAverage; public MySleepWeeklyData(long totalAwake, long totalRem, long totalDeep, long totalLight) { this.totalDeep = totalDeep; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/StepsPeriodFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/StepsPeriodFragment.java index ddec67e216..4049e323de 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/StepsPeriodFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/StepsPeriodFragment.java @@ -57,6 +57,11 @@ public class StepsPeriodFragment extends StepsFragment