otbeta/com.iamthefij.otbeta/src/main/java/com/iamthefij/otbeta/WorkoutDetailFragment.java

231 lines
8.5 KiB
Java

package com.iamthefij.otbeta;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.support.design.widget.CollapsingToolbarLayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.goebl.david.Response;
import com.goebl.david.WebbException;
import com.jjoe64.graphview.DefaultLabelFormatter;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.GridLabelRenderer;
import com.jjoe64.graphview.ValueDependentColor;
import com.jjoe64.graphview.series.BarGraphSeries;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.LineGraphSeries;
import com.iamthefij.otbeta.api.Client;
import com.iamthefij.otbeta.api.Exerciser;
import com.iamthefij.otbeta.api.Interval;
import com.iamthefij.otbeta.api.Workout;
import java.util.List;
/**
* A fragment representing a single Workout detail screen.
* This fragment is either contained in a {@link WorkoutListActivity}
* in two-pane mode (on tablets) or a {@link WorkoutDetailActivity}
* on handsets.
*/
public class WorkoutDetailFragment extends Fragment {
/**
* The fragment argument representing the item ID that this fragment
* represents.
*/
public static final String ARG_EXERCISER_UUID = "exerciser_uuid";
public static final String ARG_WORKOUT_ID = "workout_id";
public static final String ARG_WORKOUT_TITLE = "workout_TITLE";
private Client mClient;
private Exerciser mExerciser;
private Interval mInterval;
private Workout mWorkout;
private View mRootView;
private String mWorkoutTitle;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public WorkoutDetailFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mClient = new Client(this.getContext());
if (getArguments().containsKey(ARG_EXERCISER_UUID)) {
// TODO: In a real-world scenario, use a Loader
// to load content from a content provider.
mExerciser = new Exerciser(getArguments().getString(ARG_EXERCISER_UUID));
mInterval = new Interval(getArguments().getInt(ARG_WORKOUT_ID));
mWorkoutTitle = getArguments().getString(ARG_WORKOUT_TITLE);
}
new WorkoutDetailGetter().execute();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.workout_detail, container, false);
maybeSetRootView();
setTitle(mWorkoutTitle);
return mRootView;
}
private void setTitle(String workoutTitle) {
Activity activity = this.getActivity();
CollapsingToolbarLayout appBarLayout = (CollapsingToolbarLayout) activity.findViewById(R.id.toolbar_layout);
if (appBarLayout != null) {
appBarLayout.setTitle(workoutTitle);
}
}
private void maybeSetRootView() {
if (mRootView != null && mWorkout != null) {
fillHeartRateZoneGraph((GraphView) mRootView.findViewById(R.id.workout_hr_zone_graph));
fillHeartRateGraph((GraphView) mRootView.findViewById(R.id.workout_hrm_graph));
fillStats(mRootView.findViewById(R.id.workout_detail_insert));
}
}
private void fillStats(View view) {
TextView splatPointsView = (TextView) view.findViewById(R.id.workout_detail_splat_points);
splatPointsView.setText(String.valueOf(mWorkout.getPoints()));
TextView caloriesView = (TextView) view.findViewById(R.id.workout_detail_calories);
caloriesView.setText(String.valueOf(mWorkout.getCalories()));
TextView avgHrView = (TextView) view.findViewById(R.id.workout_detail_avg_hr);
avgHrView.setText(String.valueOf(mWorkout.getHeartRate().getAverage()));
TextView durationView = (TextView) view.findViewById(R.id.workout_detail_duration);
durationView.setText(String.valueOf(mWorkout.getDuration()/60));
}
private void fillHeartRateZoneGraph(GraphView graphView) {
Workout.HeartRateZones zones = mWorkout.getHrm();
BarGraphSeries<DataPoint> series = new BarGraphSeries<>(
new DataPoint[] {
new DataPoint(0, zones.getGreyZoneSeconds()/60),
new DataPoint(1, zones.getBlueZoneSeconds()/60),
new DataPoint(2, zones.getGreenZoneSeconds()/60),
new DataPoint(3, zones.getOrangeZoneSeconds()/60),
new DataPoint(4, zones.getRedZoneSeconds()/60)
}
);
series.setAnimated(true);
series.setDrawValuesOnTop(true);
series.setValuesOnTopColor(R.color.colorPrimary);
series.setValueDependentColor(new ValueDependentColor<DataPoint>() {
@Override
public int get(DataPoint data) {
switch ((int) data.getX()) {
case 0:
return Color.GRAY;
case 1:
return Color.BLUE;
case 2:
return Color.GREEN;
case 3:
return Color.rgb(255, 165, 0);
case 4:
return Color.RED;
}
return Color.DKGRAY;
}
});
graphView.getGridLabelRenderer().setHorizontalLabelsVisible(false);
graphView.getGridLabelRenderer().setGridStyle(GridLabelRenderer.GridStyle.HORIZONTAL);
graphView.getViewport().setXAxisBoundsManual(true);
graphView.getViewport().setMinX(-0.5);
graphView.getViewport().setMaxX(4.5);
graphView.addSeries(series);
}
private void fillHeartRateGraph(GraphView graphView) {
Workout.Metric heartRate = mWorkout.getHeartRate();
List<Double> values = heartRate.getValues();
double time = 0.0;
int numIntervals = values.size();
int intervalLength = heartRate.getInterval();
int targetHeartRate = mWorkout.getHrm().getTargetHeartRate();
double percentOfTarget;
DataPoint[] dataPoints = new DataPoint[numIntervals];
for (int i = 0; i < numIntervals; i++) {
percentOfTarget = (values.get(i) / targetHeartRate) * 100;
dataPoints[i] = new DataPoint(time, percentOfTarget);
time += intervalLength;
}
graphView.getGridLabelRenderer().setVerticalAxisTitle("Heart Rate");
graphView.getGridLabelRenderer().setHorizontalAxisTitle("Minutes");
graphView.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter() {
@Override
public String formatLabel(double value, boolean isValueX) {
if (isValueX) {
// Convert to minutes
value = value / 60;
}
return super.formatLabel(value, isValueX);
}
});
graphView.addSeries(new LineGraphSeries<>(dataPoints));
}
/**
* Represents an asynchronous task to retrieve workouts from the api and populate
* the recycle view adapter
*/
private class WorkoutDetailGetter extends AsyncTask<Void, Void, Boolean> {
private Workout mWorkoutTemp;
private boolean mInvalidSession = false;
@Override
protected Boolean doInBackground(Void... params) {
try {
mWorkoutTemp = mClient.getWorkout(mExerciser, mInterval);
} catch (WebbException ex) {
Response response = ex.getResponse();
if (response.getStatusCode() == 403) {
mInvalidSession = true;
return false;
} else {
throw ex;
}
}
return true;
}
@Override
protected void onPostExecute(Boolean success) {
super.onPostExecute(success);
if (success) {
mWorkout = mWorkoutTemp;
maybeSetRootView();
} else if (mInvalidSession) {
Intent loginActivity = new Intent(getActivity(), LoginActivity.class);
startActivity(loginActivity);
}
}
}
}