231 lines
8.5 KiB
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);
|
|
}
|
|
}
|
|
}
|
|
}
|