diff --git a/MyTracks/res/values/colors.xml b/MyTracks/res/values/colors.xml
index 936356e81..672ffeeba 100644
--- a/MyTracks/res/values/colors.xml
+++ b/MyTracks/res/values/colors.xml
@@ -33,6 +33,10 @@ limitations under the License.
#FF0066FF
#40C8E0FF
+
+ #FF0066FF
+ #40C8E0FF
+
#FFCC3300
#40E88A70
diff --git a/MyTracks/res/values/strings.xml b/MyTracks/res/values/strings.xml
index da27b7b8d..243620cee 100644
--- a/MyTracks/res/values/strings.xml
+++ b/MyTracks/res/values/strings.xml
@@ -451,6 +451,10 @@ limitations under the License.
%2$.1f speed in miles per hour">
Average speed: %1$.2f km/h (%2$.1f mi/h)
+
+ Elevation (ft)
+
Elevation gain: %1$d m (%2$d ft)
+
+ Elevation (m)
+
Moving time: %1$s
+
+ Pace (hr/mi)
+
+
+ Pace (hr/km)
+
Power (W)
+
+ Speed (mi/hr)
+
+
+ Speed (km/hr)
+
Point
@@ -1898,26 +1922,6 @@ limitations under the License.
of inclination to the horizontal, also known as slope or incline.">
Grade
-
- Pace (hr/mi)
-
-
- Pace (hr/km)
-
-
- Speed (mi/hr)
-
-
- Speed (km/hr)
-
diff --git a/MyTracks/src/com/google/android/apps/mytracks/ChartValueSeries.java b/MyTracks/src/com/google/android/apps/mytracks/ChartValueSeries.java
index 58650580d..8fcb2cd3a 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/ChartValueSeries.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/ChartValueSeries.java
@@ -22,195 +22,93 @@ import com.google.common.annotations.VisibleForTesting;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import java.text.NumberFormat;
/**
- * This class encapsulates the meta data for one series of chart values.
- *
+ * This class encapsulates the meta data for one series of the chart values.
+ *
* @author Sandor Dornbush
*/
public class ChartValueSeries {
private static final float STROKE_WIDTH = 2f;
+ private final int absoluteMin;
+ private final int absoluteMax;
+ private final int[] intervalValues;
+ private final int metricTitleId;
+ private final int imperialTitleId;
+ private final Paint fillPaint;
+ private final Paint strokePaint;
+ private final Paint titlePaint;
+ private final Paint markerPaint;
private final ExtremityMonitor extremityMonitor;
private final NumberFormat numberFormat;
private final Path path;
- private final Paint fillPaint;
- private final Paint strokePaint;
- private final Paint labelPaint;
- private final YAxisDimension markingInterval;
- private String title;
-
- private boolean enabled = true;
+
private int interval = 1;
- private int effectiveMin = 0;
- private int effectiveMax = 1;
+ private int minMarkerValue = 0;
+ private int maxMarkerValue = interval * ChartView.Y_AXIS_INTERVALS;
+ private boolean enabled = true;
/**
- * This class to calculates the y axis dimension, interval, effective min, and
- * effective max.
- */
- public static class YAxisDimension {
- private final int numberOfIntervals;
- private final int absoluteMin;
- private final int absoluteMax;
- private final int[] intervalValues;
-
- /**
- * Constructor.
- *
- * @param numberOfIntervals the number of intervals
- * @param absoluteMin the absolute minimum value
- * @param absoluteMax the absolute maximum value
- * @param intervalValues the list of interval values
- */
- public YAxisDimension(
- int numberOfIntervals, int absoluteMin, int absoluteMax, int[] intervalValues) {
- this.numberOfIntervals = numberOfIntervals;
- this.absoluteMin = absoluteMin;
- this.absoluteMax = absoluteMax;
- this.intervalValues = intervalValues;
- }
-
- /**
- * Gets the y axis dimension. Returns an array of int[3], containing interval, effectiveMin,
- * and effectiveMax.
- *
- * @param min the min value
- * @param max the max value
- */
- public int[] getYAxisDimension(double min, double max) {
- min = Math.max(min, absoluteMin);
- max = Math.min(max, absoluteMax);
- int interval = 0;
- int effectiveMin = 0;
- for (int i = 0; i < intervalValues.length; i++) {
- interval = intervalValues[i];
- effectiveMin = getEffetiveMin(min, interval);
- double targetInterval = (max - effectiveMin) / numberOfIntervals;
- if (interval >= targetInterval) {
- break;
- }
- }
- int effectiveMax = getEffectiveMax(max, interval);
- return new int[] { interval, effectiveMin, effectiveMax };
- }
-
- /**
- * Gets the effective min value.
- *
- * @param min the min value
- * @param interval the interval
- */
- private int getEffetiveMin(double min, int interval) {
- int value = (int) (min / interval) * interval;
- // value > min if min is negative
- if (value > min) {
- return value - interval;
- }
- return value;
- }
-
- /**
- * Gets the effective max value
- *
- * @param max the max value
- * @param interval the interval
- */
- private int getEffectiveMax(double max, int interval) {
- return ((int) (max / interval)) * interval + interval;
- }
- }
-
- /**
- * Constructs a new chart value series.
- *
+ * Constructor.
+ *
* @param context the context
+ * @param absoluteMin the absolute min value
+ * @param absoluteMax the absolute max value
+ * @param intervalValues the list of interval values
+ * @param metricTitleId the metric title id
+ * @param imperialTitleId the imperial title id
* @param fillColor the fill color
* @param strokeColor the stroke color
- * @param yAxisDimension the marking interval
- * @param titleId the title id
*/
- public ChartValueSeries(Context context, int fillColor, int strokeColor,
- YAxisDimension yAxisDimension, int titleId) {
- extremityMonitor = new ExtremityMonitor();
- numberFormat = NumberFormat.getIntegerInstance();
- path = new Path();
+ public ChartValueSeries(Context context, int absoluteMin, int absoluteMax, int[] intervalValues,
+ int metricTitleId, int imperialTitleId, int fillColor, int strokeColor) {
+ this.absoluteMin = absoluteMin;
+ this.absoluteMax = absoluteMax;
+ this.intervalValues = intervalValues;
+ this.metricTitleId = metricTitleId;
+ this.imperialTitleId = imperialTitleId;
+
fillPaint = new Paint();
fillPaint.setStyle(Style.FILL);
fillPaint.setColor(context.getResources().getColor(fillColor));
fillPaint.setAntiAlias(true);
- if (strokeColor != -1) {
- strokePaint = new Paint();
- strokePaint.setStyle(Style.STROKE);
- strokePaint.setColor(context.getResources().getColor(strokeColor));
- strokePaint.setAntiAlias(true);
- // Make a copy of the stroke paint with the default thickness
- labelPaint = new Paint(strokePaint);
- strokePaint.setStrokeWidth(STROKE_WIDTH);
- } else {
- strokePaint = null;
- labelPaint = fillPaint;
- }
- this.markingInterval = yAxisDimension;
- title = context.getString(titleId);
+
+ strokePaint = new Paint();
+ strokePaint.setStyle(Style.STROKE);
+ strokePaint.setColor(context.getResources().getColor(strokeColor));
+ strokePaint.setAntiAlias(true);
+
+ // Make copies of the stroke paint with the default thickness
+ titlePaint = new Paint(strokePaint);
+ titlePaint.setTextSize(ChartView.LARGE_TEXT_SIZE);
+ titlePaint.setTextAlign(Align.CENTER);
+
+ markerPaint = new Paint(strokePaint);
+ markerPaint.setTextSize(ChartView.MEDIUM_TEXT_SIZE);
+ markerPaint.setTextAlign(Align.RIGHT);
+
+ // Set stroke paint thickness
+ strokePaint.setStrokeWidth(STROKE_WIDTH);
+
+ extremityMonitor = new ExtremityMonitor();
+ numberFormat = NumberFormat.getIntegerInstance();
+ path = new Path();
}
/**
- * Returns true if the series has data.
+ * Sets the series enabled value.
+ *
+ * @param enabled true to enable
*/
- public boolean hasData() {
- return extremityMonitor.hasData();
- }
-
- /**
- * Updates the series with a new value.
- *
- * @param value the new value
- */
- public void update(double value) {
- extremityMonitor.update(value);
- }
-
- /**
- * Gets the number format for the series.
- */
- public NumberFormat getNumberFormat() {
- return numberFormat;
- }
-
- /**
- * Gets the path.
- */
- public Path getPath() {
- return path;
- }
-
- /**
- * Gets the label paint.
- */
- public Paint getLabelPaint() {
- return labelPaint;
- }
-
- /**
- * Gets the title.
- */
- public String getTitle() {
- return title;
- }
-
- /**
- * Sets the title.
- *
- * @param title the title
- */
- public void setTitle(String title) {
- this.title = title;
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
}
/**
@@ -221,65 +119,144 @@ public class ChartValueSeries {
}
/**
- * Sets the enabled value.
- *
- * @param enabled true to enable
+ * Returns true if the series has data.
*/
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
+ public boolean hasData() {
+ return extremityMonitor.hasData();
}
-
+
+ /**
+ * Updates the series with a new value.
+ *
+ * @param value the new value
+ */
+ public void update(double value) {
+ extremityMonitor.update(value);
+ }
+
+ /**
+ * Gets the path.
+ */
+ public Path getPath() {
+ return path;
+ }
+
/**
* Draws the path on canvas.
- *
+ *
* @param canvas the canvas
*/
public void drawPath(Canvas canvas) {
canvas.drawPath(path, fillPaint);
- if (strokePaint != null) {
- canvas.drawPath(path, strokePaint);
- }
+ canvas.drawPath(path, strokePaint);
}
/**
* Updates the y axis dimension.
*/
public void updateDimension() {
- boolean hasData = extremityMonitor.hasData();
- double min = hasData ? extremityMonitor.getMin() : 0.0;
- double max = hasData ? extremityMonitor.getMax() : 1.0;
- int[] dimension = markingInterval.getYAxisDimension(min, max);
- interval = dimension[0];
- effectiveMin = dimension[1];
- effectiveMax = dimension[2];
+ double min = hasData() ? extremityMonitor.getMin() : 0.0;
+ double max = hasData() ? extremityMonitor.getMax() : 1.0;
+ min = Math.max(min, absoluteMin);
+ max = Math.min(max, absoluteMax);
+ interval = getInterval(min, max);
+ minMarkerValue = getMinMarkerValue(min, interval);
+ maxMarkerValue = minMarkerValue + interval * ChartView.Y_AXIS_INTERVALS;
}
/**
- * Gets the y axis interval value.
+ * Gets the interval value.
+ *
+ * @param min the min value
+ * @param max the max value
+ */
+ private int getInterval(double min, double max) {
+ for (int i = 0; i < intervalValues.length; i++) {
+ int intervalValue = intervalValues[i];
+ int minValue = getMinMarkerValue(min, intervalValue);
+ double targetInterval = (max - minValue) / ChartView.Y_AXIS_INTERVALS;
+ if (intervalValue >= targetInterval) {
+ return intervalValue;
+ }
+ }
+ // Return the largest interval
+ return intervalValues[intervalValues.length - 1];
+ }
+
+ /**
+ * Gets the min marker value.
+ *
+ * @param min the min series value
+ * @param intervalValue the interval value
+ */
+ private int getMinMarkerValue(double min, int intervalValue) {
+ // Round down to the nearest intervalValue
+ int value = ((int) (min / intervalValue)) * intervalValue;
+ // value > min if min is negative
+ if (value > min) {
+ return value - intervalValue;
+ }
+ return value;
+ }
+
+ /**
+ * Gets the interval value.
*/
public int getInterval() {
return interval;
}
/**
- * Gets the minimum value.
+ * Gets the minimum marker value.
*/
- public int getMin() {
- return effectiveMin;
+ public int getMinMarkerValue() {
+ return minMarkerValue;
}
/**
- * Gets the maximum value.
+ * Gets the maximum marker value.
*/
@VisibleForTesting
- int getMax() {
- return effectiveMax;
+ int getMaxMarkerValue() {
+ return maxMarkerValue;
}
/**
- * Gets the maximum label length.
+ * Gets the title id.
*/
- public int getMaxLabelLength() {
- return Math.max(numberFormat.format(getMin()).length(), numberFormat.format(getMax()).length());
+ public int getTitleId(boolean metricUnits) {
+ return metricUnits ? metricTitleId : imperialTitleId;
+ }
+
+ /**
+ * Gets the title paint.
+ */
+ public Paint getTitlePaint() {
+ return titlePaint;
+ }
+
+ /**
+ * Gets the marker paint.
+ */
+ public Paint getMarkerPaint() {
+ return markerPaint;
+ }
+
+ /**
+ * Gets the largest marker.
+ */
+ public String getLargestMarker() {
+ String minMarker = numberFormat.format(getMinMarkerValue());
+ String maxMarker = numberFormat.format(getMaxMarkerValue());
+ return minMarker.length() >= maxMarker.length() ? minMarker : maxMarker;
+ }
+
+ /**
+ * Formats a marker value.
+ *
+ * @param value the value
+ */
+ public String formatMarker(int value) {
+ return numberFormat.format(value);
}
}
diff --git a/MyTracks/src/com/google/android/apps/mytracks/ChartView.java b/MyTracks/src/com/google/android/apps/mytracks/ChartView.java
index 330493387..802bd80f9 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/ChartView.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/ChartView.java
@@ -15,7 +15,6 @@
*/
package com.google.android.apps.mytracks;
-import com.google.android.apps.mytracks.ChartValueSeries.YAxisDimension;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.stats.ExtremityMonitor;
import com.google.android.apps.mytracks.util.IntentUtils;
@@ -30,7 +29,6 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
-import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.drawable.Drawable;
@@ -50,6 +48,21 @@ import java.util.ArrayList;
* @author Leif Hendrik Wilden
*/
public class ChartView extends View {
+
+ public static final float LARGE_TEXT_SIZE = 22f;
+ public static final float MEDIUM_TEXT_SIZE = 18f;
+ public static final float SMALL_TEXT_SIZE = 14f;
+
+ public static final int Y_AXIS_INTERVALS = 5;
+
+ public static final int NUM_SERIES = 6;
+ public static final int ELEVATION_SERIES = 0;
+ public static final int SPEED_SERIES = 1;
+ public static final int PACE_SERIES = 2;
+ public static final int HEART_RATE_SERIES = 3;
+ public static final int CADENCE_SERIES = 4;
+ public static final int POWER_SERIES = 5;
+
private static final int MIN_ZOOM_LEVEL = 1;
/*
@@ -66,8 +79,6 @@ public class ChartView extends View {
private int zoomLevel = 1;
private int maxZoomLevel = 10;
- private static final int MAX_INTERVALS = 5;
-
/*
* Borders, margins, dimensions (in pixels):
*/
@@ -109,15 +120,6 @@ public class ChartView extends View {
*/
private double maxX = 1;
- /**
- * The various series.
- */
- public static final int ELEVATION_SERIES = 0;
- public static final int SPEED_SERIES = 1;
- public static final int POWER_SERIES = 2;
- public static final int CADENCE_SERIES = 3;
- public static final int HEART_RATE_SERIES = 4;
- public static final int NUM_SERIES = 5;
private ChartValueSeries[] series;
private final ExtremityMonitor xMonitor = new ExtremityMonitor();
@@ -204,41 +206,54 @@ public class ChartView extends View {
series = new ChartValueSeries[NUM_SERIES];
// Create the value series.
- series[ELEVATION_SERIES] =
- new ChartValueSeries(context,
- R.color.elevation_fill,
- R.color.elevation_border,
- new YAxisDimension(MAX_INTERVALS, Integer.MIN_VALUE, Integer.MAX_VALUE,
- new int[] {5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000}),
- R.string.stats_elevation);
-
- series[SPEED_SERIES] =
- new ChartValueSeries(context,
- R.color.speed_fill,
- R.color.speed_border,
- new YAxisDimension(MAX_INTERVALS, 0, Integer.MAX_VALUE,
- new int[] {1, 5, 10, 20, 50}),
- R.string.stats_speed);
- series[POWER_SERIES] =
- new ChartValueSeries(context,
- R.color.power_fill,
- R.color.power_border,
- new YAxisDimension(MAX_INTERVALS, 0, 1000, new int[] {5, 50, 100, 200}),
- R.string.sensor_state_power);
- series[CADENCE_SERIES] =
- new ChartValueSeries(context,
- R.color.cadence_fill,
- R.color.cadence_border,
- new YAxisDimension(MAX_INTERVALS, 0, Integer.MAX_VALUE,
- new int[] {5, 10, 25, 50}),
- R.string.sensor_state_cadence);
- series[HEART_RATE_SERIES] =
- new ChartValueSeries(context,
- R.color.heartrate_fill,
- R.color.heartrate_border,
- new YAxisDimension(MAX_INTERVALS, 0, Integer.MAX_VALUE,
- new int[] {25, 50}),
- R.string.sensor_state_heart_rate);
+ series[ELEVATION_SERIES] = new ChartValueSeries(context,
+ Integer.MIN_VALUE,
+ Integer.MAX_VALUE,
+ new int[] {5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000},
+ R.string.description_elevation_metric,
+ R.string.description_elevation_imperial,
+ R.color.elevation_fill,
+ R.color.elevation_border);
+ series[SPEED_SERIES] = new ChartValueSeries(context,
+ 0,
+ Integer.MAX_VALUE,
+ new int[] {1, 5, 10, 20, 50},
+ R.string.description_speed_metric,
+ R.string.description_speed_imperial,
+ R.color.speed_fill,
+ R.color.speed_border);
+ series[PACE_SERIES] = new ChartValueSeries(context,
+ 0,
+ Integer.MAX_VALUE,
+ new int[] { 1, 2, 5, 10, 15, 20, 30, 60, 120 },
+ R.string.description_pace_metric,
+ R.string.description_pace_imperial,
+ R.color.pace_fill,
+ R.color.pace_border);
+ series[HEART_RATE_SERIES] = new ChartValueSeries(context,
+ 0,
+ Integer.MAX_VALUE,
+ new int[] {25, 50},
+ R.string.description_sensor_heart_rate,
+ R.string.description_sensor_heart_rate,
+ R.color.heartrate_fill,
+ R.color.heartrate_border);
+ series[CADENCE_SERIES] = new ChartValueSeries(context,
+ 0,
+ Integer.MAX_VALUE,
+ new int[] {5, 10, 25, 50},
+ R.string.description_sensor_cadence,
+ R.string.description_sensor_cadence,
+ R.color.cadence_fill,
+ R.color.cadence_border);
+ series[POWER_SERIES] = new ChartValueSeries(context,
+ 0,
+ 1000,
+ new int[] {5, 50, 100, 200},
+ R.string.description_sensor_power,
+ R.string.description_sensor_power,
+ R.color.power_fill,
+ R.color.power_border);
}
public void clearWaypoints() {
@@ -263,12 +278,6 @@ public class ChartView extends View {
this.metricUnits = metricUnits;
}
- public void setReportSpeed(boolean reportSpeed, Context c) {
- series[SPEED_SERIES].setTitle(c.getString(reportSpeed
- ? R.string.stats_speed
- : R.string.stats_pace));
- }
-
private void addDataPointInternal(double[] theData) {
xMonitor.update(theData[0]);
int min = Math.min(series.length, theData.length - 1);
@@ -622,7 +631,8 @@ public class ChartView extends View {
for (ChartValueSeries cvs : series) {
if (cvs.isEnabled() && cvs.hasData()) {
int x = (int) (w * (double) ++j / sections) + getScrollX();
- c.drawText(cvs.getTitle(), x, topBorder, cvs.getLabelPaint());
+ c.drawText(
+ getContext().getString(cvs.getTitleId(metricUnits)), x, topBorder, cvs.getTitlePaint());
}
}
}
@@ -719,7 +729,7 @@ public class ChartView extends View {
int maxLength = 0;
for (ChartValueSeries cvs : series) {
if (cvs.isEnabled() && cvs.hasData()) {
- maxLength += cvs.getMaxLabelLength();
+ maxLength += cvs.getLargestMarker().length();
}
}
float density = getContext().getResources().getDisplayMetrics().density;
@@ -758,9 +768,9 @@ public class ChartView extends View {
}
private int getY(ChartValueSeries cvs, double y) {
- int effectiveSpread = cvs.getInterval() * MAX_INTERVALS;
+ int effectiveSpread = cvs.getInterval() * Y_AXIS_INTERVALS;
return topBorder + effectiveHeight
- - (int) ((y - cvs.getMin()) * effectiveHeight / effectiveSpread);
+ - (int) ((y - cvs.getMinMarkerValue()) * effectiveHeight / effectiveSpread);
}
/** Draws the labels on the X axis into the given canvas. */
@@ -792,8 +802,8 @@ public class ChartView extends View {
private float drawYLabels(ChartValueSeries cvs, Canvas c, int x) {
int interval = cvs.getInterval();
float maxTextWidth = 0;
- for (int i = 0; i < MAX_INTERVALS; ++i) {
- maxTextWidth = Math.max(maxTextWidth, drawYLabel(cvs, c, x, i * interval + cvs.getMin()));
+ for (int i = 0; i < Y_AXIS_INTERVALS; ++i) {
+ maxTextWidth = Math.max(maxTextWidth, drawYLabel(cvs, c, x, i * interval + cvs.getMinMarkerValue()));
}
return maxTextWidth;
}
@@ -814,14 +824,13 @@ public class ChartView extends View {
/** Draws a single label on the Y axis. */
private float drawYLabel(ChartValueSeries cvs, Canvas c, int x, int y) {
- int desiredY = (int) ((y - cvs.getMin()) * effectiveHeight /
- (cvs.getInterval() * MAX_INTERVALS));
+ int desiredY = (int) ((y - cvs.getMinMarkerValue()) * effectiveHeight /
+ (cvs.getInterval() * Y_AXIS_INTERVALS));
desiredY = topBorder + effectiveHeight + FONT_HEIGHT / 2 - desiredY - 1;
- Paint p = new Paint(cvs.getLabelPaint());
- p.setTextAlign(Align.RIGHT);
- String text = cvs.getNumberFormat().format(y);
- c.drawText(text, x, desiredY, p);
- return p.measureText(text);
+ Paint markerPaint = cvs.getMarkerPaint();
+ String text = cvs.formatMarker(y);
+ c.drawText(text, x, desiredY, markerPaint);
+ return markerPaint.measureText(text);
}
/** Draws the actual X axis line and its label. */
@@ -844,8 +853,8 @@ public class ChartView extends View {
canvas.drawLine(leftBorder, UNIT_BORDER + topBorder,
leftBorder, effectiveHeight + topBorder,
borderPaint);
- for (int i = 1; i < MAX_INTERVALS; ++i) {
- int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
+ for (int i = 1; i < Y_AXIS_INTERVALS; ++i) {
+ int y = i * effectiveHeight / Y_AXIS_INTERVALS + topBorder;
canvas.drawLine(leftBorder - 5, y, leftBorder, y, gridPaint);
}
@@ -858,8 +867,8 @@ public class ChartView extends View {
/** Draws the grid for the graph. */
private void drawGrid(Canvas c) {
float rightEdge = getX(maxX);
- for (int i = 1; i < MAX_INTERVALS; ++i) {
- int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
+ for (int i = 1; i < Y_AXIS_INTERVALS; ++i) {
+ int y = i * effectiveHeight / Y_AXIS_INTERVALS + topBorder;
c.drawLine(leftBorder, y, rightEdge, y, gridBarPaint);
}
}
diff --git a/MyTracks/src/com/google/android/apps/mytracks/fragments/ChartFragment.java b/MyTracks/src/com/google/android/apps/mytracks/fragments/ChartFragment.java
index 9a7f87b8d..679129d3e 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/fragments/ChartFragment.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/fragments/ChartFragment.java
@@ -77,15 +77,15 @@ public class ChartFragment extends Fragment implements TrackDataListener {
private boolean reportSpeed = true;
private boolean chartByDistance = true;
- private boolean[] chartShow = new boolean[] {true, true, true, true, true};
+ private boolean[] chartShow = new boolean[] {true, true, true, true, true, true};
// UI elements
private ChartView chartView;
private ZoomControls zoomControls;
/**
- * A runnable that will remove the spinner (if any), enable/disable zoom
- * controls and orange pointer as appropriate and redraw.
+ * A runnable that will enable/disable zoom controls and orange pointer as
+ * appropriate and redraw.
*/
private final Runnable updateChart = new Runnable() {
@Override
@@ -215,7 +215,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
@Override
public void onNewTrackPoint(Location location) {
if (LocationUtils.isValidLocation(location)) {
- double[] data = new double[6];
+ double[] data = new double[ChartView.NUM_SERIES + 1];
fillDataPoint(location, data);
pendingPoints.add(data);
}
@@ -280,7 +280,8 @@ public class ChartFragment extends Fragment implements TrackDataListener {
return false;
}
reportSpeed = speed;
- chartView.setReportSpeed(speed, getActivity());
+ setSeriesEnabled(ChartView.SPEED_SERIES, reportSpeed);
+ setSeriesEnabled(ChartView.PACE_SERIES, !reportSpeed);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -310,6 +311,10 @@ public class ChartFragment extends Fragment implements TrackDataListener {
getActivity(), R.string.chart_show_speed_key, PreferencesUtils.CHART_SHOW_SPEED_DEFAULT))) {
needUpdate = true;
}
+ if (setSeriesEnabled(ChartView.PACE_SERIES, !PreferencesUtils.getBoolean(
+ getActivity(), R.string.chart_show_speed_key, PreferencesUtils.CHART_SHOW_SPEED_DEFAULT))) {
+ needUpdate = true;
+ }
if (setSeriesEnabled(ChartView.POWER_SERIES, PreferencesUtils.getBoolean(
getActivity(), R.string.chart_show_power_key, PreferencesUtils.CHART_SHOW_POWER_DEFAULT))) {
needUpdate = true;
@@ -405,13 +410,14 @@ public class ChartFragment extends Fragment implements TrackDataListener {
}
/**
- * Given a location, fill in a data point, an array of double[6].
+ * Given a location, fill in a data point, an array of double[].
* data[0] = time/distance
* data[1] = elevation
* data[2] = speed
- * data[3] = power
- * data[4] = cadence
- * data[5] = heart rate
+ * data[3] = pace
+ * data[4] = heart rate
+ * data[5] = cadence
+ * data[6] = power
*
* @param location the location
* @param data the data point to fill in, can be null
@@ -421,9 +427,10 @@ public class ChartFragment extends Fragment implements TrackDataListener {
double timeOrDistance = Double.NaN;
double elevation = Double.NaN;
double speed = Double.NaN;
- double power = Double.NaN;
+ double pace = Double.NaN;
+ double heartRate = Double.NaN;
double cadence = Double.NaN;
- double heartRate = Double.NaN;
+ double power = Double.NaN;
// TODO: Use TripStatisticsBuilder
if (chartByDistance) {
@@ -460,36 +467,36 @@ public class ChartFragment extends Fragment implements TrackDataListener {
if (!metricUnits) {
speed *= UnitConversions.KM_TO_MI;
}
- if (!reportSpeed) {
- speed = speed == 0 ? 0.0 : 60.0 / speed;
- }
-
+ pace = speed == 0 ? 0.0 : 60.0 / speed;
+
if (location instanceof MyTracksLocation
&& ((MyTracksLocation) location).getSensorDataSet() != null) {
SensorDataSet sensorDataSet = ((MyTracksLocation) location).getSensorDataSet();
- if (sensorDataSet.hasPower() && sensorDataSet.getPower().getState() == Sensor.SensorState.SENDING
- && sensorDataSet.getPower().hasValue()) {
- power = sensorDataSet.getPower().getValue();
+ if (sensorDataSet.hasHeartRate()
+ && sensorDataSet.getHeartRate().getState() == Sensor.SensorState.SENDING
+ && sensorDataSet.getHeartRate().hasValue()) {
+ heartRate = sensorDataSet.getHeartRate().getValue();
}
if (sensorDataSet.hasCadence()
&& sensorDataSet.getCadence().getState() == Sensor.SensorState.SENDING
&& sensorDataSet.getCadence().hasValue()) {
cadence = sensorDataSet.getCadence().getValue();
}
- if (sensorDataSet.hasHeartRate()
- && sensorDataSet.getHeartRate().getState() == Sensor.SensorState.SENDING
- && sensorDataSet.getHeartRate().hasValue()) {
- heartRate = sensorDataSet.getHeartRate().getValue();
+ if (sensorDataSet.hasPower()
+ && sensorDataSet.getPower().getState() == Sensor.SensorState.SENDING
+ && sensorDataSet.getPower().hasValue()) {
+ power = sensorDataSet.getPower().getValue();
}
}
-
+
if (data != null) {
data[0] = timeOrDistance;
data[1] = elevation;
data[2] = speed;
- data[3] = power;
- data[4] = cadence;
- data[5] = heartRate;
+ data[3] = pace;
+ data[4] = heartRate;
+ data[5] = cadence;
+ data[6] = power;
}
lastLocation = location;
}
diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivity.java
index 01369bb09..354a389f9 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivity.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivity.java
@@ -44,7 +44,8 @@ import android.widget.TextView;
public class UploadResultActivity extends FragmentActivity {
private static final String TAG = UploadResultActivity.class.getSimpleName();
- private static final int DIALOG_RESULT_ID = 0;
+ @VisibleForTesting
+ static final int DIALOG_RESULT_ID = 0;
private SendRequest sendRequest;
private String shareUrl;
diff --git a/MyTracks/src/com/google/android/apps/mytracks/settings/StatsSettingsActivity.java b/MyTracks/src/com/google/android/apps/mytracks/settings/StatsSettingsActivity.java
index 7b5781756..89e5214f7 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/settings/StatsSettingsActivity.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/settings/StatsSettingsActivity.java
@@ -71,11 +71,9 @@ public class StatsSettingsActivity extends AbstractSettingsActivity {
getString(R.string.report_speed_key));
boolean metric = PreferencesUtils.getBoolean(
this, R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT);
- reportSpeedCheckBoxPreference.setSummaryOn(
- metric ? getString(R.string.settings_stats_rate_speed_metric)
- : getString(R.string.settings_stats_rate_speed_imperial));
- reportSpeedCheckBoxPreference.setSummaryOff(
- metric ? getString(R.string.settings_stats_rate_pace_metric)
- : getString(R.string.settings_stats_rate_pace_imperial));
+ reportSpeedCheckBoxPreference.setSummaryOn(metric ? getString(R.string.description_speed_metric)
+ : getString(R.string.description_speed_imperial));
+ reportSpeedCheckBoxPreference.setSummaryOff(metric ? getString(R.string.description_pace_metric)
+ : getString(R.string.description_pace_imperial));
}
}
diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/ChartValueSeriesTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/ChartValueSeriesTest.java
index 3d0ad000c..39e69f67c 100644
--- a/MyTracksTest/src/com/google/android/apps/mytracks/ChartValueSeriesTest.java
+++ b/MyTracksTest/src/com/google/android/apps/mytracks/ChartValueSeriesTest.java
@@ -15,7 +15,6 @@
*/
package com.google.android.apps.mytracks;
-import com.google.android.apps.mytracks.ChartValueSeries.YAxisDimension;
import com.google.android.maps.mytracks.R;
import android.test.AndroidTestCase;
@@ -30,18 +29,20 @@ public class ChartValueSeriesTest extends AndroidTestCase {
@Override
protected void setUp() throws Exception {
- YAxisDimension yAxisDimension = new YAxisDimension(
- 5, Integer.MIN_VALUE, Integer.MAX_VALUE, new int[] { 100 });
- series = new ChartValueSeries(getContext(), R.color.elevation_fill, R.color.elevation_border,
- yAxisDimension, R.string.stats_elevation);
+ series = new ChartValueSeries(getContext(),
+ Integer.MIN_VALUE,
+ Integer.MAX_VALUE,
+ new int[] {100, 1000 },
+ R.string.description_elevation_metric,
+ R.string.description_elevation_imperial,
+ R.color.elevation_fill,
+ R.color.elevation_border);
}
public void testInitialConditions() {
assertEquals(1, series.getInterval());
- assertEquals(1, series.getMaxLabelLength());
- assertEquals(0, series.getMin());
- assertEquals(1, series.getMax());
- assertEquals(getContext().getString(R.string.stats_elevation), series.getTitle());
+ assertEquals(0, series.getMinMarkerValue());
+ assertEquals(5, series.getMaxMarkerValue());
assertTrue(series.isEnabled());
}
@@ -55,49 +56,25 @@ public class ChartValueSeriesTest extends AndroidTestCase {
series.update(10);
series.updateDimension();
assertEquals(100, series.getInterval());
- assertEquals(3, series.getMaxLabelLength());
- assertEquals(0, series.getMin());
- assertEquals(100, series.getMax());
+ assertEquals(0, series.getMinMarkerValue());
+ assertEquals(500, series.getMaxMarkerValue());
}
public void testBigUpdates() {
series.update(0);
series.update(901);
series.updateDimension();
- assertEquals(100, series.getInterval());
- assertEquals(5, series.getMaxLabelLength());
- assertEquals(0, series.getMin());
- assertEquals(1000, series.getMax());
+ assertEquals(1000, series.getInterval());
+ assertEquals(0, series.getMinMarkerValue());
+ assertEquals(5000, series.getMaxMarkerValue());
}
public void testNotZeroBasedUpdates() {
- series.update(500);
- series.update(1401);
+ series.update(220);
+ series.update(250);
series.updateDimension();
assertEquals(100, series.getInterval());
- assertEquals(5, series.getMaxLabelLength());
- assertEquals(500, series.getMin());
- assertEquals(1500, series.getMax());
- }
-
- public void testYAxisDimension_minAligned() {
- YAxisDimension yAxisDimension = new YAxisDimension(
- 5, Integer.MIN_VALUE, Integer.MAX_VALUE, new int[] { 10, 50, 100 });
- assertEquals(10, yAxisDimension.getYAxisDimension(0, 15)[0]);
- assertEquals(10, yAxisDimension.getYAxisDimension(0, 50)[0]);
- assertEquals(50, yAxisDimension.getYAxisDimension(0, 111)[0]);
- assertEquals(50, yAxisDimension.getYAxisDimension(0, 250)[0]);
- assertEquals(100, yAxisDimension.getYAxisDimension(0, 251)[0]);
- assertEquals(100, yAxisDimension.getYAxisDimension(0, 10000)[0]);
- }
-
- public void testYAxisDimension_minNotAligned() {
- YAxisDimension settings = new YAxisDimension(
- 5, Integer.MIN_VALUE, Integer.MAX_VALUE, new int[] { 10, 50, 100 });
- assertEquals(50, settings.getYAxisDimension(5, 55)[0]);
- assertEquals(10, settings.getYAxisDimension(10, 60)[0]);
- assertEquals(50, settings.getYAxisDimension(7, 250)[0]);
- assertEquals(100, settings.getYAxisDimension(7, 257)[0]);
- assertEquals(100, settings.getYAxisDimension(11, 10000)[0]);
+ assertEquals(200, series.getMinMarkerValue());
+ assertEquals(700, series.getMaxMarkerValue());
}
}
diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/fragments/ChartFragmentTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/fragments/ChartFragmentTest.java
index f171510a6..8ba25ceac 100644
--- a/MyTracksTest/src/com/google/android/apps/mytracks/fragments/ChartFragmentTest.java
+++ b/MyTracksTest/src/com/google/android/apps/mytracks/fragments/ChartFragmentTest.java
@@ -52,31 +52,32 @@ public class ChartFragmentTest extends AndroidTestCase {
// No input.
double[] point = fillDataPointTestHelper(myTracksLocation);
- assertEquals(Double.NaN, point[3]);
- assertEquals(Double.NaN, point[4]);
- assertEquals(Double.NaN, point[5]);
+ assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
+ assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
+ assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
// Input incorrect state.
// Creates SensorData.
- Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
- .setValue(20).setState(Sensor.SensorState.NONE);
- Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
- .setValue(20).setState(Sensor.SensorState.NONE);
Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder()
- .setValue(20).setState(Sensor.SensorState.NONE);
+ .setValue(100).setState(Sensor.SensorState.NONE);
+ Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
+ .setValue(101).setState(Sensor.SensorState.NONE);
+ Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
+ .setValue(102).setState(Sensor.SensorState.NONE);
+
// Creates SensorDataSet.
SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet();
sensorDataSet = sensorDataSet.toBuilder()
- .setPower(powerData)
- .setCadence(cadenceData)
.setHeartRate(heartRateData)
+ .setCadence(cadenceData)
+ .setPower(powerData)
.build();
myTracksLocation.setSensorData(sensorDataSet);
// Test.
point = fillDataPointTestHelper(myTracksLocation);
- assertEquals(Double.NaN, point[3]);
- assertEquals(Double.NaN, point[4]);
- assertEquals(Double.NaN, point[5]);
+ assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
+ assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
+ assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
}
/**
@@ -87,31 +88,31 @@ public class ChartFragmentTest extends AndroidTestCase {
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
// No input.
double[] point = fillDataPointTestHelper(myTracksLocation);
- assertEquals(Double.NaN, point[3]);
- assertEquals(Double.NaN, point[4]);
- assertEquals(Double.NaN, point[5]);
+ assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
+ assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
+ assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
// Creates SensorData.
- Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
- .setValue(20).setState(Sensor.SensorState.SENDING);
- Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
- .setValue(20).setState(Sensor.SensorState.SENDING);
Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder()
- .setValue(20).setState(Sensor.SensorState.SENDING);
+ .setValue(100).setState(Sensor.SensorState.SENDING);
+ Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
+ .setValue(101).setState(Sensor.SensorState.SENDING);
+ Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
+ .setValue(102).setState(Sensor.SensorState.SENDING);
// Creates SensorDataSet.
SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet();
sensorDataSet = sensorDataSet.toBuilder()
- .setPower(powerData)
- .setCadence(cadenceData)
.setHeartRate(heartRateData)
+ .setCadence(cadenceData)
+ .setPower(powerData)
.build();
myTracksLocation.setSensorData(sensorDataSet);
// Test.
point = fillDataPointTestHelper(myTracksLocation);
- assertEquals(20.0, point[3]);
- assertEquals(20.0, point[4]);
- assertEquals(20.0, point[5]);
+ assertEquals(100.0, point[ChartView.HEART_RATE_SERIES + 1]);
+ assertEquals(101.0, point[ChartView.CADENCE_SERIES + 1]);
+ assertEquals(102.0, point[ChartView.POWER_SERIES + 1]);
}
/**
@@ -230,7 +231,7 @@ public class ChartFragmentTest extends AndroidTestCase {
* parameter. Then only one value INITIALLONGTITUDE in buffer.
*/
double[] point = fillDataPointTestHelper(myTracksLocation1);
- assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[1]);
+ assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[ChartView.ELEVATION_SERIES + 1]);
/*
* Send another value to buffer, now there are two values, INITIALALTITUDE
@@ -239,8 +240,8 @@ public class ChartFragmentTest extends AndroidTestCase {
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
myTracksLocation2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2);
point = fillDataPointTestHelper(myTracksLocation2);
- assertEquals(
- (TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0, point[1]);
+ assertEquals((TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0,
+ point[ChartView.ELEVATION_SERIES + 1]);
}
/**
@@ -260,7 +261,7 @@ public class ChartFragmentTest extends AndroidTestCase {
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
myTracksLocation1.setSpeed(129);
double[] point = fillDataPointTestHelper(myTracksLocation1);
- assertEquals(0.0, point[2]);
+ assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
/*
* Tests the logic when both metricUnits and reportSpeed are true.This
@@ -275,7 +276,7 @@ public class ChartFragmentTest extends AndroidTestCase {
myTracksLocation2.setTime(myTracksLocation1.getTime() + 222);
myTracksLocation2.setSpeed(130);
point = fillDataPointTestHelper(myTracksLocation2);
- assertEquals(130.0 * UnitConversions.MS_TO_KMH, point[2]);
+ assertEquals(130.0 * UnitConversions.MS_TO_KMH, point[ChartView.SPEED_SERIES + 1]);
}
/**
@@ -287,7 +288,8 @@ public class ChartFragmentTest extends AndroidTestCase {
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
myTracksLocation.setSpeed(132);
double[] point = fillDataPointTestHelper(myTracksLocation);
- assertEquals(132.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI, point[2]);
+ assertEquals(132.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI,
+ point[ChartView.SPEED_SERIES + 1]);
}
/**
@@ -299,8 +301,8 @@ public class ChartFragmentTest extends AndroidTestCase {
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
myTracksLocation.setSpeed(134);
double[] point = fillDataPointTestHelper(myTracksLocation);
- assertEquals(HOURS_PER_UNIT / (134.0 * UnitConversions.MS_TO_KMH), point[2]);
-
+ assertEquals(
+ HOURS_PER_UNIT / (134.0 * UnitConversions.MS_TO_KMH), point[ChartView.PACE_SERIES + 1]);
}
/**
@@ -313,7 +315,7 @@ public class ChartFragmentTest extends AndroidTestCase {
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
myTracksLocation.setSpeed(0);
double[] point = fillDataPointTestHelper(myTracksLocation);
- assertEquals(0.0, point[2]);
+ assertEquals(0.0, point[ChartView.PACE_SERIES + 1]);
}
/**
@@ -323,7 +325,7 @@ public class ChartFragmentTest extends AndroidTestCase {
* @return data of this location
*/
private double[] fillDataPointTestHelper(Location location) {
- double[] point = new double[6];
+ double[] point = new double[ChartView.NUM_SERIES + 1];
chartFragment.fillDataPoint(location, point);
return point;
}
diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivityTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivityTest.java
index f56de3b42..6ec62b942 100644
--- a/MyTracksTest/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivityTest.java
+++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivityTest.java
@@ -46,6 +46,7 @@ public class UploadResultActivityTest
*/
public void testAllSuccess() {
initialActivity(true, true, true, true, true, true);
+ uploadResultActivity.showDialog(UploadResultActivity.DIALOG_RESULT_ID);
Dialog dialog = uploadResultActivity.getDialog();
TextView textView = (TextView) dialog.findViewById(R.id.upload_result_success_footer);
assertTrue(textView.isShown());
@@ -57,6 +58,7 @@ public class UploadResultActivityTest
public void testAllFailed() {
// Send all kinds but all failed.
initialActivity(true, true, true, false, false, false);
+ uploadResultActivity.showDialog(UploadResultActivity.DIALOG_RESULT_ID);
Dialog dialog = uploadResultActivity.getDialog();
TextView textView = (TextView) dialog.findViewById(R.id.upload_result_error_footer);
assertTrue(textView.isShown());
@@ -72,6 +74,7 @@ public class UploadResultActivityTest
*/
public void testPartialSuccess() {
initialActivity(true, false, true, true, false, false);
+ uploadResultActivity.showDialog(UploadResultActivity.DIALOG_RESULT_ID);
Dialog dialog = uploadResultActivity.getDialog();
TextView textView = (TextView) dialog.findViewById(R.id.upload_result_error_footer);
assertTrue(textView.isShown());