Intervals: added elevation gain and only shows speed or pace, depending on settings.

This commit is contained in:
Román
2020-09-20 17:46:51 +02:00
committed by Román Martínez
parent c508747203
commit 0036934fb3
9 changed files with 133 additions and 46 deletions
@@ -66,8 +66,8 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
// Preferences
private boolean recordingTrackPaused;
// Intervals recording fragment needs Track.Id when the activity creates it.
private OnTrackIdListener intervalsListener;
// Intervals recording fragment needs Track.Id when the activity creates it and knowing when category change.
private OnTrackRecordingListener intervalsListener;
private final Runnable bindChangedCallback = new Runnable() {
@Override
@@ -370,6 +370,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
Track track = contentProviderUtils.getTrack(trackId);
String category = getString(TrackIconUtils.getIconActivityType(iconValue));
TrackUtils.updateTrack(this, track, null, category, null, contentProviderUtils);
intervalsListener.onCategoryChanged(category);
}
private class CustomFragmentPagerAdapter extends FragmentPagerAdapter {
@@ -417,11 +418,12 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
}
}
public interface OnTrackIdListener {
public interface OnTrackRecordingListener {
void onTrackId(Track.Id trackId);
void onCategoryChanged(String category);
}
public void setTrackIdListener(OnTrackIdListener listener) {
public void setTrackIdListener(OnTrackRecordingListener listener) {
this.intervalsListener = listener;
if (trackId != null) {
listener.onTrackId(trackId);
@@ -23,10 +23,12 @@ public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.I
private StackMode stackMode;
private boolean metricUnits;
private float sumDistance_m;
private String category;
public IntervalStatisticsAdapter(Context context, List<IntervalStatistics.Interval> intervalList, StackMode stackMode) {
public IntervalStatisticsAdapter(Context context, List<IntervalStatistics.Interval> intervalList, String category, StackMode stackMode) {
super(context, R.layout.interval_stats_list_item, intervalList);
metricUnits = PreferencesUtils.isMetricUnits(context);
this.category = category;
this.stackMode = stackMode;
}
@@ -43,8 +45,8 @@ public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.I
intervalView = LayoutInflater.from(getContext()).inflate(R.layout.interval_stats_list_item, parent, false);
viewHolder.distance = intervalView.findViewById(R.id.interval_item_distance);
viewHolder.speed = intervalView.findViewById(R.id.interval_item_speed);
viewHolder.pace = intervalView.findViewById(R.id.interval_item_pace);
viewHolder.rate = intervalView.findViewById(R.id.interval_item_rate);
viewHolder.gain = intervalView.findViewById(R.id.interval_item_gain);
intervalView.setTag(viewHolder);
} else {
@@ -58,11 +60,16 @@ public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.I
}
viewHolder.distance.setText(StringUtils.formatDistance(getContext(), sumDistance_m, metricUnits));
Pair<String, String> speedParts = StringUtils.getSpeedParts(getContext(), interval.getSpeed_ms(), metricUnits, true);
viewHolder.speed.setText(speedParts.first + " " + speedParts.second);
if (PreferencesUtils.isReportSpeed(getContext(), category)) {
Pair<String, String> speedParts = StringUtils.getSpeedParts(getContext(), interval.getSpeed_ms(), metricUnits, true);
viewHolder.rate.setText(speedParts.first + " " + speedParts.second);
} else {
Pair<String, String> paceParts = StringUtils.getSpeedParts(getContext(), interval.getSpeed_ms(), metricUnits, false);
viewHolder.rate.setText(paceParts.first + " " + paceParts.second);
}
Pair<String, String> paceParts = StringUtils.getSpeedParts(getContext(), interval.getSpeed_ms(), metricUnits, false);
viewHolder.pace.setText(paceParts.first + " " + paceParts.second);
Pair<String, String> gainParts = StringUtils.formatElevation(getContext(), interval.getGain_m(), metricUnits);
viewHolder.gain.setText(gainParts.first + " " + gainParts.second);
return intervalView;
}
@@ -77,7 +84,7 @@ public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.I
private static class ViewHolder {
private TextView distance;
private TextView speed;
private TextView pace;
private TextView rate;
private TextView gain;
}
}
@@ -22,6 +22,7 @@ import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TrackRecordingActivity;
import de.dennisguse.opentracks.adapters.IntervalStatisticsAdapter;
import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.UnitConversions;
import de.dennisguse.opentracks.viewmodels.IntervalStatistics;
@@ -46,7 +47,10 @@ public class IntervalsFragment extends Fragment {
protected Spinner spinnerIntervals;
private ArrayAdapter<IntervalStatisticsModel.IntervalOption> spinnerAdapter;
private TextView rateLabel;
private Track.Id trackId;
private String category;
protected final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (preferences, key) -> {
if (PreferencesUtils.isKey(getContext(), R.string.stats_units_key, key) || PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key)) {
@@ -54,6 +58,7 @@ public class IntervalsFragment extends Fragment {
if (adapter != null) {
adapter.notifyDataSetChanged();
spinnerAdapter.notifyDataSetChanged();
setRateLabel();
intervalChanged();
}
}
@@ -81,11 +86,13 @@ public class IntervalsFragment extends Fragment {
intervalUnit = PreferencesUtils.isMetricUnits(getContext()) ? getContext().getString(R.string.unit_kilometer) : getContext().getString(R.string.unit_mile);
if (savedInstanceState != null) {
trackId = savedInstanceState.getParcelable(TRACK_ID_KEY);
setTrackId(savedInstanceState.getParcelable(TRACK_ID_KEY));
} else {
trackId = getArguments().getParcelable(TRACK_ID_KEY);
setTrackId(getArguments().getParcelable(TRACK_ID_KEY));
}
rateLabel = view.findViewById(R.id.interval_rate);
intervalListView = view.findViewById(R.id.interval_list);
intervalListView.setEmptyView(view.findViewById(R.id.interval_list_empty_view));
@@ -126,6 +133,7 @@ public class IntervalsFragment extends Fragment {
}
});
setRateLabel();
intervalChanged();
}
@@ -147,6 +155,12 @@ public class IntervalsFragment extends Fragment {
outState.putParcelable(TRACK_ID_KEY, trackId);
}
@Override
public void onResume() {
super.onResume();
setTrackId(trackId);
}
/**
* Update intervals through {@link IntervalStatisticsModel} view model.
*/
@@ -158,7 +172,7 @@ public class IntervalsFragment extends Fragment {
LiveData<IntervalStatistics> liveData = viewModel.getIntervalStats(trackId, selectedInterval);
liveData.observe(getActivity(), intervalStatistics -> {
if (intervalStatistics != null) {
adapter = new IntervalStatisticsAdapter(getContext(), intervalStatistics.getIntervalList(), stackModeListView);
adapter = new IntervalStatisticsAdapter(getContext(), intervalStatistics.getIntervalList(), category, stackModeListView);
intervalListView.setAdapter(adapter);
}
});
@@ -166,9 +180,29 @@ public class IntervalsFragment extends Fragment {
public void setTrackId(Track.Id trackId) {
this.trackId = trackId;
if (this.trackId != null) {
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(getContext());
Track track = contentProviderUtils.getTrack(this.trackId);
setCategory(track.getCategory());
}
}
public static class IntervalsRecordingFragment extends IntervalsFragment implements TrackRecordingActivity.OnTrackIdListener {
public void setCategory(String category) {
if (this.category == null || !this.category.equals(category)) {
this.category = category;
setRateLabel();
intervalChanged();
}
}
private void setRateLabel() {
if (rateLabel != null) {
boolean reportSpeed = PreferencesUtils.isReportSpeed(getContext(), category);
rateLabel.setText(reportSpeed ? R.string.stats_speed : R.string.stats_pace);
}
}
public static class IntervalsRecordingFragment extends IntervalsFragment implements TrackRecordingActivity.OnTrackRecordingListener {
// Refreshing intervals stats it's not so demanding so 5 seconds is enough to balance performance and user experience.
private static final long UI_UPDATE_INTERVAL = 5 * UnitConversions.ONE_SECOND_MS;
@@ -221,5 +255,10 @@ public class IntervalsFragment extends Fragment {
public void onTrackId(Track.Id trackId) {
setTrackId(trackId);
}
@Override
public void onCategoryChanged(String category) {
setCategory(category);
}
}
}
@@ -24,6 +24,7 @@ public class IntervalStatistics {
}
Interval interval = new Interval();
interval.gain_m += trackPointList.get(0).hasElevationGain() ? trackPointList.get(0).getElevationGain() : 0;
for (int i = 1; i < trackPointList.size(); i++) {
TrackPoint prevTrackPoint = trackPointList.get(i - 1);
TrackPoint trackPoint = trackPointList.get(i);
@@ -31,6 +32,7 @@ public class IntervalStatistics {
if (LocationUtils.isValidLocation(trackPoint.getLocation()) && LocationUtils.isValidLocation(prevTrackPoint.getLocation())) {
interval.distance_m += prevTrackPoint.distanceTo(trackPoint);
interval.time_ms += trackPoint.getTime() - prevTrackPoint.getTime();
interval.gain_m += trackPoint.hasElevationGain() ? trackPoint.getElevationGain() : 0;
if (interval.distance_m >= distanceInterval_m) {
float adjustFactor = distanceInterval_m / interval.distance_m;
@@ -80,17 +82,20 @@ public class IntervalStatistics {
public static class Interval {
private float distance_m = 0f;
private float time_ms = 0f;
private float gain_m = 0f;
public Interval() {}
public Interval(float distance_m, float time_ms) {
this.distance_m = distance_m;
this.time_ms = time_ms;
this.gain_m = 0f;
}
public Interval(Interval i) {
distance_m = i.distance_m;
time_ms = i.time_ms;
gain_m = i.gain_m;
}
public float getDistance_m() {
@@ -111,5 +116,9 @@ public class IntervalStatistics {
}
return distance_m / (float) (time_ms * UnitConversions.MS_TO_S);
}
public float getGain_m() {
return gain_m;
}
}
}