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 ;
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
2016-02-27 15:29:47 +01:00
private CombinedChart mWeekStepsChart ;
2015-07-29 16:30:19 +02:00
private PieChart mTodayStepsChart ;
2015-08-03 01:17:02 +02:00
@Override
2015-08-25 00:33:37 +02:00
protected void refreshInBackground ( DBHandler db , GBDevice device ) {
2015-09-04 21:55:29 +02:00
ChartsHost chartsHost = getChartsHost ( ) ;
if ( chartsHost ! = null ) {
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
refreshDaySteps ( db , mTodayStepsChart , day , device ) ;
refreshWeekBeforeSteps ( db , mWeekStepsChart , day , device ) ;
}
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-02-27 15:29:47 +01:00
private void 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 < > ( ) ;
List < String > labels = new ArrayList < > ( ) ;
for ( int counter = 0 ; counter < 7 ; counter + + ) {
2015-08-25 00:33:37 +02:00
entries . add ( new BarEntry ( analysis . calculateTotalSteps ( getSamplesOfDay ( db , day , device ) ) , counter ) ) ;
2015-07-29 16:30:19 +02:00
labels . add ( day . getDisplayName ( Calendar . DAY_OF_WEEK , Calendar . SHORT , mLocale ) ) ;
day . add ( Calendar . DATE , 1 ) ;
}
BarDataSet set = new BarDataSet ( entries , " " ) ;
set . setColor ( akActivity . color ) ;
2016-02-27 15:29:47 +01:00
BarData barData = new BarData ( labels , 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);
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-02-27 15:29:47 +01:00
CombinedData combinedData = new CombinedData ( labels ) ;
combinedData . setData ( barData ) ;
setupLegend ( combinedChart ) ;
combinedChart . setData ( combinedData ) ;
combinedChart . getLegend ( ) . setEnabled ( false ) ;
2015-07-29 16:30:19 +02:00
}
2015-08-25 00:33:37 +02:00
private void refreshDaySteps ( DBHandler db , PieChart pieChart , 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
pieChart . setCenterText ( NumberFormat . getNumberInstance ( mLocale ) . format ( totalSteps ) ) ;
PieData data = new PieData ( ) ;
List < Entry > entries = new ArrayList < > ( ) ;
List < Integer > colors = new ArrayList < > ( ) ;
entries . add ( new Entry ( totalSteps , 0 ) ) ;
colors . add ( akActivity . color ) ;
2015-07-29 18:07:35 +02:00
//we don't want labels on the pie chart
2015-07-29 16:30:19 +02:00
data . addXValue ( " " ) ;
2015-07-29 18:07:35 +02:00
if ( totalSteps < mTargetSteps ) {
entries . add ( new Entry ( ( mTargetSteps - totalSteps ) , 1 ) ) ;
colors . add ( Color . GRAY ) ;
//we don't want labels on the pie chart
data . addXValue ( " " ) ;
}
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 ) ;
pieChart . setData ( data ) ;
pieChart . getLegend ( ) . setEnabled ( false ) ;
}
@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 ) ;
mTodayStepsChart . setDescriptionColor ( DESCRIPTION_COLOR ) ;
2015-09-01 23:56:14 +02:00
mTodayStepsChart . setDescription ( getContext ( ) . getString ( R . string . weeksteps_today_steps_description , mTargetSteps ) ) ;
2015-07-29 16:30:19 +02:00
mTodayStepsChart . setNoDataTextDescription ( " " ) ;
mTodayStepsChart . setNoDataText ( " " ) ;
}
private void setupWeekStepsChart ( ) {
mWeekStepsChart . setBackgroundColor ( BACKGROUND_COLOR ) ;
mWeekStepsChart . setDescriptionColor ( DESCRIPTION_COLOR ) ;
mWeekStepsChart . setDescription ( " " ) ;
configureBarLineChartDefaults ( mWeekStepsChart ) ;
XAxis x = mWeekStepsChart . getXAxis ( ) ;
x . setDrawLabels ( true ) ;
x . setDrawGridLines ( false ) ;
x . setEnabled ( true ) ;
x . setTextColor ( CHART_TEXT_COLOR ) ;
x . setDrawLimitLinesBehindData ( true ) ;
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 ) ;
}
protected void setupLegend ( Chart chart ) {
List < Integer > legendColors = new ArrayList < > ( 1 ) ;
List < String > legendLabels = new ArrayList < > ( 1 ) ;
legendColors . add ( akActivity . color ) ;
2015-09-01 22:30:02 +02:00
legendLabels . add ( getContext ( ) . getString ( R . string . chart_steps ) ) ;
2015-09-24 00:02:58 +02:00
chart . getLegend ( ) . setCustom ( legendColors , legendLabels ) ;
2015-07-29 16:30:19 +02:00
chart . getLegend ( ) . setTextColor ( LEGEND_TEXT_COLOR ) ;
}
2015-08-25 00:33:37 +02:00
private List < 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
2015-08-03 01:17:02 +02:00
protected List < ActivitySample > getSamples ( DBHandler db , GBDevice device , int tsFrom , int tsTo ) {
return super . getAllSamples ( db , device , tsFrom , tsTo ) ;
2015-07-29 16:30:19 +02:00
}
}