2015-08-03 23:09:49 +02:00
package nodomain.freeyourgadget.gadgetbridge.activities.charts ;
2015-07-29 16:30:19 +02:00
import android.graphics.Color ;
import android.os.Bundle ;
import android.view.LayoutInflater ;
import android.view.View ;
import android.view.ViewGroup ;
import com.github.mikephil.charting.charts.Chart ;
2016-02-27 15:29:47 +01:00
import com.github.mikephil.charting.charts.CombinedChart ;
2015-07-29 16:30:19 +02:00
import com.github.mikephil.charting.charts.PieChart ;
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 ;
2016-02-27 15:29:47 +01:00
import com.github.mikephil.charting.data.CombinedData ;
2015-07-29 16:30:19 +02:00
import com.github.mikephil.charting.data.Entry ;
import com.github.mikephil.charting.data.PieData ;
import com.github.mikephil.charting.data.PieDataSet ;
2016-09-18 23:37:41 +02:00
import com.github.mikephil.charting.data.PieEntry ;
import com.github.mikephil.charting.formatter.IValueFormatter ;
import com.github.mikephil.charting.utils.ViewPortHandler ;
2015-07-29 16:30:19 +02:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import java.text.NumberFormat ;
import java.util.ArrayList ;
import java.util.Calendar ;
import java.util.List ;
import java.util.Locale ;
import nodomain.freeyourgadget.gadgetbridge.R ;
2015-08-03 01:17:02 +02:00
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler ;
2015-08-03 23:09:49 +02:00
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator ;
2015-08-17 02:22:16 +02:00
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice ;
2015-07-29 16:30:19 +02:00
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample ;
public class WeekStepsChartFragment extends AbstractChartFragment {
protected static final Logger LOG = LoggerFactory . getLogger ( WeekStepsChartFragment . class ) ;
private Locale mLocale ;
2015-07-29 18:49:16 +02:00
private int mTargetSteps = 10000 ;
2015-07-29 16:30:19 +02:00
private PieChart mTodayStepsChart ;
2016-04-11 23:18:12 +02:00
private CombinedChart mWeekStepsChart ;
2016-10-03 22:41:40 +02:00
private XIndexLabelFormatter xIndexLabelFormatter = new XIndexLabelFormatter ( ) ;
2015-07-29 16:30:19 +02:00
2015-08-03 01:17:02 +02:00
@Override
2016-04-11 23:18:12 +02:00
protected ChartsData refreshInBackground ( ChartsHost chartsHost , DBHandler db , GBDevice device ) {
Calendar day = Calendar . getInstance ( ) ;
day . setTime ( chartsHost . getEndDate ( ) ) ;
//NB: we could have omitted the day, but this way we can move things to the past easily
DaySteps daySteps = refreshDaySteps ( db , day , device ) ;
DefaultChartsData weekBeforeStepsData = refreshWeekBeforeSteps ( db , mWeekStepsChart , day , device ) ;
return new MyChartsData ( daySteps , weekBeforeStepsData ) ;
}
@Override
protected void updateChartsnUIThread ( ChartsData chartsData ) {
MyChartsData mcd = ( MyChartsData ) chartsData ;
// setupLegend(mWeekStepsChart);
mTodayStepsChart . setCenterText ( NumberFormat . getNumberInstance ( mLocale ) . format ( mcd . getDaySteps ( ) . totalSteps ) ) ;
mTodayStepsChart . setData ( mcd . getDaySteps ( ) . data ) ;
2016-09-29 22:16:08 +02:00
mWeekStepsChart . setData ( null ) ; // workaround for https://github.com/PhilJay/MPAndroidChart/issues/2317
2016-04-11 23:18:12 +02:00
mWeekStepsChart . setData ( mcd . getWeekBeforeStepsData ( ) . getCombinedData ( ) ) ;
mWeekStepsChart . getLegend ( ) . setEnabled ( false ) ;
2016-10-03 23:34:05 +02:00
xIndexLabelFormatter . setxLabels ( mcd . getWeekBeforeStepsData ( ) . getXLabels ( ) ) ;
2015-08-03 01:17:02 +02:00
}
2015-07-29 16:30:19 +02:00
2015-08-03 01:17:02 +02:00
@Override
protected void renderCharts ( ) {
2015-07-29 16:30:19 +02:00
mWeekStepsChart . invalidate ( ) ;
mTodayStepsChart . invalidate ( ) ;
}
2016-04-11 23:18:12 +02:00
private DefaultChartsData refreshWeekBeforeSteps ( DBHandler db , CombinedChart combinedChart , Calendar day , GBDevice device ) {
2015-07-29 16:30:19 +02:00
ActivityAnalysis analysis = new ActivityAnalysis ( ) ;
2015-09-01 22:12:22 +02:00
day = ( Calendar ) day . clone ( ) ; // do not modify the caller's argument
2015-07-29 16:30:19 +02:00
day . add ( Calendar . DATE , - 7 ) ;
List < BarEntry > entries = new ArrayList < > ( ) ;
2016-10-03 22:41:40 +02:00
ArrayList < String > labels = new ArrayList < String > ( ) ;
2015-07-29 16:30:19 +02:00
for ( int counter = 0 ; counter < 7 ; counter + + ) {
2016-09-18 23:37:41 +02:00
entries . add ( new BarEntry ( counter , analysis . calculateTotalSteps ( getSamplesOfDay ( db , day , device ) ) ) ) ;
2016-10-03 22:41:40 +02:00
labels . add ( day . getDisplayName ( Calendar . DAY_OF_WEEK , Calendar . SHORT , mLocale ) ) ;
2015-07-29 16:30:19 +02:00
day . add ( Calendar . DATE , 1 ) ;
}
BarDataSet set = new BarDataSet ( entries , " " ) ;
set . setColor ( akActivity . color ) ;
2016-10-03 22:41:40 +02:00
BarData barData = new BarData ( set ) ;
2016-02-27 15:29:47 +01:00
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);
2015-07-29 16:30:19 +02:00
LimitLine target = new LimitLine ( mTargetSteps ) ;
2016-02-27 15:29:47 +01:00
combinedChart . getAxisLeft ( ) . removeAllLimitLines ( ) ;
combinedChart . getAxisLeft ( ) . addLimitLine ( target ) ;
2015-07-29 16:30:19 +02:00
2016-09-18 23:37:41 +02:00
CombinedData combinedData = new CombinedData ( ) ;
2016-02-27 15:29:47 +01:00
combinedData . setData ( barData ) ;
2016-10-03 23:34:05 +02:00
return new DefaultChartsData ( combinedData , labels ) ;
2015-07-29 16:30:19 +02:00
}
2016-04-11 23:18:12 +02:00
private DaySteps refreshDaySteps ( DBHandler db , Calendar day , GBDevice device ) {
2015-07-29 16:30:19 +02:00
ActivityAnalysis analysis = new ActivityAnalysis ( ) ;
2015-08-25 00:33:37 +02:00
int totalSteps = analysis . calculateTotalSteps ( getSamplesOfDay ( db , day , device ) ) ;
2015-07-29 16:30:19 +02:00
PieData data = new PieData ( ) ;
2016-09-18 23:37:41 +02:00
List < PieEntry > entries = new ArrayList < > ( ) ;
2015-07-29 16:30:19 +02:00
List < Integer > colors = new ArrayList < > ( ) ;
2016-09-18 23:37:41 +02:00
entries . add ( new PieEntry ( totalSteps , " " ) ) ; //we don't want labels on the pie chart
2015-07-29 16:30:19 +02:00
colors . add ( akActivity . color ) ;
2015-07-29 18:07:35 +02:00
if ( totalSteps < mTargetSteps ) {
2016-09-18 23:37:41 +02:00
entries . add ( new PieEntry ( ( mTargetSteps - totalSteps ) ) ) ; //we don't want labels on the pie chart
2015-07-29 18:07:35 +02:00
colors . add ( Color . GRAY ) ;
}
2015-07-29 16:30:19 +02:00
PieDataSet set = new PieDataSet ( entries , " " ) ;
set . setColors ( colors ) ;
data . setDataSet ( set ) ;
2015-07-29 18:07:35 +02:00
//this hides the values (numeric) added to the set. These would be shown aside the strings set with addXValue above
2015-07-29 16:30:19 +02:00
data . setDrawValues ( false ) ;
2016-04-11 23:18:12 +02:00
return new DaySteps ( data , totalSteps ) ;
2015-07-29 16:30:19 +02:00
}
@Override
public View onCreateView ( LayoutInflater inflater , ViewGroup container ,
Bundle savedInstanceState ) {
mLocale = getResources ( ) . getConfiguration ( ) . locale ;
View rootView = inflater . inflate ( R . layout . fragment_sleepchart , container , false ) ;
2015-09-04 21:55:29 +02:00
GBDevice device = getChartsHost ( ) . getDevice ( ) ;
2015-08-29 11:31:48 +02:00
if ( device ! = null ) {
2015-09-09 21:15:29 +02:00
// TODO: eek, this is device specific!
2015-08-25 00:33:37 +02:00
mTargetSteps = MiBandCoordinator . getFitnessGoal ( device . getAddress ( ) ) ;
2015-07-29 18:49:16 +02:00
}
2016-02-27 15:29:47 +01:00
mWeekStepsChart = ( CombinedChart ) rootView . findViewById ( R . id . sleepchart ) ;
2015-07-29 16:30:19 +02:00
mTodayStepsChart = ( PieChart ) rootView . findViewById ( R . id . sleepchart_pie_light_deep ) ;
setupWeekStepsChart ( ) ;
setupTodayStepsChart ( ) ;
2015-08-25 01:03:58 +02:00
// refresh immediately instead of use refreshIfVisible(), for perceived performance
2015-07-29 16:30:19 +02:00
refresh ( ) ;
return rootView ;
}
2015-08-25 00:33:37 +02:00
@Override
public String getTitle ( ) {
return getString ( R . string . weekstepschart_steps_a_week ) ;
}
2015-07-29 16:30:19 +02:00
private void setupTodayStepsChart ( ) {
mTodayStepsChart . setBackgroundColor ( BACKGROUND_COLOR ) ;
2016-09-18 23:37:41 +02:00
mTodayStepsChart . getDescription ( ) . setTextColor ( DESCRIPTION_COLOR ) ;
mTodayStepsChart . getDescription ( ) . setText ( getContext ( ) . getString ( R . string . weeksteps_today_steps_description , String . valueOf ( mTargetSteps ) ) ) ;
// mTodayStepsChart.setNoDataTextDescription("");
2015-07-29 16:30:19 +02:00
mTodayStepsChart . setNoDataText ( " " ) ;
2016-04-11 23:18:12 +02:00
mTodayStepsChart . getLegend ( ) . setEnabled ( false ) ;
// setupLegend(mTodayStepsChart);
2015-07-29 16:30:19 +02:00
}
private void setupWeekStepsChart ( ) {
mWeekStepsChart . setBackgroundColor ( BACKGROUND_COLOR ) ;
2016-09-18 23:37:41 +02:00
mWeekStepsChart . getDescription ( ) . setTextColor ( DESCRIPTION_COLOR ) ;
mWeekStepsChart . getDescription ( ) . setText ( " " ) ;
2015-07-29 16:30:19 +02:00
configureBarLineChartDefaults ( mWeekStepsChart ) ;
XAxis x = mWeekStepsChart . getXAxis ( ) ;
x . setDrawLabels ( true ) ;
x . setDrawGridLines ( false ) ;
x . setEnabled ( true ) ;
x . setTextColor ( CHART_TEXT_COLOR ) ;
x . setDrawLimitLinesBehindData ( true ) ;
2016-10-03 22:41:40 +02:00
x . setValueFormatter ( xIndexLabelFormatter ) ;
x . setPosition ( XAxis . XAxisPosition . BOTTOM ) ;
2015-07-29 16:30:19 +02:00
YAxis y = mWeekStepsChart . getAxisLeft ( ) ;
y . setDrawGridLines ( false ) ;
y . setDrawTopYLabelEntry ( false ) ;
y . setTextColor ( CHART_TEXT_COLOR ) ;
y . setEnabled ( true ) ;
YAxis yAxisRight = mWeekStepsChart . getAxisRight ( ) ;
yAxisRight . setDrawGridLines ( false ) ;
yAxisRight . setEnabled ( false ) ;
yAxisRight . setDrawLabels ( false ) ;
yAxisRight . setDrawTopYLabelEntry ( false ) ;
yAxisRight . setTextColor ( CHART_TEXT_COLOR ) ;
}
2016-09-18 23:37:41 +02:00
@Override
2015-07-29 16:30:19 +02:00
protected void setupLegend ( Chart chart ) {
2016-04-11 23:18:12 +02:00
// List<Integer> legendColors = new ArrayList<>(1);
// List<String> legendLabels = new ArrayList<>(1);
// legendColors.add(akActivity.color);
// legendLabels.add(getContext().getString(R.string.chart_steps));
// chart.getLegend().setCustom(legendColors, legendLabels);
// chart.getLegend().setTextColor(LEGEND_TEXT_COLOR);
2015-07-29 16:30:19 +02:00
}
2016-05-16 23:36:54 +02:00
private List < ? extends ActivitySample > getSamplesOfDay ( DBHandler db , Calendar day , GBDevice device ) {
2015-07-29 16:30:19 +02:00
int startTs ;
int endTs ;
2015-09-01 22:12:22 +02:00
day = ( Calendar ) day . clone ( ) ; // do not modify the caller's argument
2015-07-29 16:30:19 +02:00
day . set ( Calendar . HOUR_OF_DAY , 0 ) ;
day . set ( Calendar . MINUTE , 0 ) ;
day . set ( Calendar . SECOND , 0 ) ;
startTs = ( int ) ( day . getTimeInMillis ( ) / 1000 ) ;
day . set ( Calendar . HOUR_OF_DAY , 23 ) ;
day . set ( Calendar . MINUTE , 59 ) ;
day . set ( Calendar . SECOND , 59 ) ;
endTs = ( int ) ( day . getTimeInMillis ( ) / 1000 ) ;
2015-08-25 00:33:37 +02:00
return getSamples ( db , device , startTs , endTs ) ;
2015-07-29 16:30:19 +02:00
}
@Override
2016-05-16 23:36:54 +02:00
protected List < ? extends ActivitySample > getSamples ( DBHandler db , GBDevice device , int tsFrom , int tsTo ) {
2015-08-03 01:17:02 +02:00
return super . getAllSamples ( db , device , tsFrom , tsTo ) ;
2015-07-29 16:30:19 +02:00
}
2016-04-11 23:18:12 +02:00
private static class DaySteps {
private final PieData data ;
private final int totalSteps ;
public DaySteps ( PieData data , int totalSteps ) {
this . data = data ;
this . totalSteps = totalSteps ;
}
}
private static class MyChartsData extends ChartsData {
private final DefaultChartsData weekBeforeStepsData ;
private final DaySteps daySteps ;
public MyChartsData ( DaySteps daySteps , DefaultChartsData weekBeforeStepsData ) {
this . daySteps = daySteps ;
this . weekBeforeStepsData = weekBeforeStepsData ;
}
public DaySteps getDaySteps ( ) {
return daySteps ;
}
public DefaultChartsData getWeekBeforeStepsData ( ) {
return weekBeforeStepsData ;
}
}
2015-07-29 16:30:19 +02:00
}