Use the activity type of current track to calculate calorie.

This commit is contained in:
youtaol
2013-09-05 14:33:37 +08:00
parent e0375050d2
commit 7233137e93
14 changed files with 124 additions and 48 deletions
+6
View File
@@ -2146,6 +2146,12 @@ limitations under the License.
Character limit: ~23 (1 line)"> Character limit: ~23 (1 line)">
Calories Calories
</string> </string>
<string name="stats_calorie_invalid_type"
translation_description="In the 'Stats' page, the calorie value label while pending.
Character limit: ~23 (1 line)">
Calories(Invalid type)
</string>
<string name="stats_fastest_pace" <string name="stats_fastest_pace"
translation_description="In the 'Stats' page, the fastest pace."> translation_description="In the 'Stats' page, the fastest pace.">
Fastest pace Fastest pace
@@ -19,6 +19,7 @@ package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.apps.mytracks.util.StatsUtils; import com.google.android.apps.mytracks.util.StatsUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -36,7 +37,8 @@ public class AggregatedStatsActivity extends AbstractMyTracksActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
StatsUtils.setTripStatisticsValues(this, getTripStatistics()); StatsUtils.setTripStatisticsValues(this, getTripStatistics(),
PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
StatsUtils.setLocationValues(this, null, false); StatsUtils.setLocationValues(this, null, false);
} }
@@ -579,8 +579,7 @@ public class TrackDataHub implements DataSourceListener {
* *
* @return the selectedTrackId * @return the selectedTrackId
*/ */
@VisibleForTesting public long getSelectedTrackId() {
long getSelectedTrackId() {
return selectedTrackId; return selectedTrackId;
} }
@@ -451,8 +451,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
double power = Double.NaN; double power = Double.NaN;
if (tripStatisticsUpdater != null) { if (tripStatisticsUpdater != null) {
tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, PreferencesUtils tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, getActivity());
.getInt(getActivity(), R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT));
TripStatistics tripStatistics = tripStatisticsUpdater.getTripStatistics(); TripStatistics tripStatistics = tripStatisticsUpdater.getTripStatistics();
if (chartByDistance) { if (chartByDistance) {
double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM; double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM;
@@ -192,7 +192,8 @@ public class MarkerDetailFragment extends Fragment {
TextView name = (TextView) getView().findViewById(R.id.marker_detail_statistics_name); TextView name = (TextView) getView().findViewById(R.id.marker_detail_statistics_name);
name.setText(getString(R.string.generic_name_line, waypoint.getName())); name.setText(getString(R.string.generic_name_line, waypoint.getName()));
StatsUtils.setTripStatisticsValues(getActivity(), waypoint.getTripStatistics()); StatsUtils.setTripStatisticsValues(getActivity(), waypoint.getTripStatistics(),
waypoint.getTrackId());
StatsUtils.setLocationValues(getActivity(), waypoint.getLocation(), false); StatsUtils.setLocationValues(getActivity(), waypoint.getLocation(), false);
} }
} }
@@ -259,7 +259,11 @@ public class StatsFragment extends Fragment implements TrackDataListener {
* Updates the UI. * Updates the UI.
*/ */
private void updateUi(FragmentActivity activity) { private void updateUi(FragmentActivity activity) {
StatsUtils.setTripStatisticsValues(activity, lastTripStatistics); StatsUtils.setTripStatisticsValues(
activity,
lastTripStatistics,
trackDataHub == null ? PreferencesUtils.RECORDING_TRACK_ID_DEFAULT : trackDataHub
.getSelectedTrackId());
StatsUtils.setLocationValues(activity, lastLocation, isSelectedTrackRecording()); StatsUtils.setLocationValues(activity, lastLocation, isSelectedTrackRecording());
} }
} }
@@ -243,11 +243,8 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
return; return;
} }
trackTripStatisticstrackUpdater.addLocation(trackPoint, recordingDistanceInterval, trackTripStatisticstrackUpdater.addLocation(trackPoint, recordingDistanceInterval,
PreferencesUtils.getInt(context, R.string.stats_weight_key, context);
PreferencesUtils.STATS_WEIGHT_DEFAULT)); markerTripStatisticsUpdater.addLocation(trackPoint, recordingDistanceInterval, context);
markerTripStatisticsUpdater.addLocation(trackPoint, recordingDistanceInterval,
PreferencesUtils.getInt(context, R.string.stats_weight_key,
PreferencesUtils.STATS_WEIGHT_DEFAULT));
} }
if (waypoint.getLocation().getTime() > trackPoint.getTime()) { if (waypoint.getLocation().getTime() > trackPoint.getTime()) {
trackPoint = null; trackPoint = null;
@@ -537,9 +534,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
trackData.tripStatisticsUpdater = new TripStatisticsUpdater( trackData.tripStatisticsUpdater = new TripStatisticsUpdater(
location.getTime() != -1L ? location.getTime() : trackData.importTime); location.getTime() != -1L ? location.getTime() : trackData.importTime);
} }
trackData.tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, trackData.tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
PreferencesUtils.getInt(context, R.string.stats_weight_key,
PreferencesUtils.STATS_WEIGHT_DEFAULT));
trackData.bufferedLocations[trackData.numBufferedLocations] = location; trackData.bufferedLocations[trackData.numBufferedLocations] = location;
trackData.numBufferedLocations++; trackData.numBufferedLocations++;
@@ -277,8 +277,7 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
sentStartMarker = true; sentStartMarker = true;
} }
tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, PreferencesUtils tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
.getInt(context, R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT));
if (i % elevationSamplingFrequency == 0) { if (i % elevationSamplingFrequency == 0) {
distances.add(tripStatisticsUpdater.getTripStatistics().getTotalDistance()); distances.add(tripStatisticsUpdater.getTripStatistics().getTotalDistance());
elevations.add(tripStatisticsUpdater.getSmoothedElevation()); elevations.add(tripStatisticsUpdater.getSmoothedElevation());
@@ -659,13 +659,9 @@ public class TrackRecordingService extends Service {
if (cursor.moveToLast()) { if (cursor.moveToLast()) {
do { do {
Location location = myTracksProviderUtils.createTrackPoint(cursor); Location location = myTracksProviderUtils.createTrackPoint(cursor);
trackTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, trackTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
PreferencesUtils.getInt(context, R.string.stats_weight_key,
PreferencesUtils.STATS_WEIGHT_DEFAULT));
if (location.getTime() > markerStartTime) { if (location.getTime() > markerStartTime) {
markerTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, markerTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
PreferencesUtils.getInt(context, R.string.stats_weight_key,
PreferencesUtils.STATS_WEIGHT_DEFAULT));
} }
} while (cursor.moveToPrevious()); } while (cursor.moveToPrevious());
} }
@@ -1005,10 +1001,8 @@ public class TrackRecordingService extends Service {
try { try {
Uri uri = myTracksProviderUtils.insertTrackPoint(location, track.getId()); Uri uri = myTracksProviderUtils.insertTrackPoint(location, track.getId());
long trackPointId = Long.parseLong(uri.getLastPathSegment()); long trackPointId = Long.parseLong(uri.getLastPathSegment());
trackTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, PreferencesUtils trackTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
.getInt(context, R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT)); markerTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
markerTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, PreferencesUtils
.getInt(context, R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT));
updateRecordingTrack(track, trackPointId, LocationUtils.isValidLocation(location)); updateRecordingTrack(track, trackPointId, LocationUtils.isValidLocation(location));
} catch (SQLiteException e) { } catch (SQLiteException e) {
/* /*
@@ -23,8 +23,11 @@ import static com.google.android.apps.mytracks.services.TrackRecordingService.PA
import com.google.android.apps.mytracks.util.CalorieUtils; import com.google.android.apps.mytracks.util.CalorieUtils;
import com.google.android.apps.mytracks.util.CalorieUtils.ActivityType; import com.google.android.apps.mytracks.util.CalorieUtils.ActivityType;
import com.google.android.apps.mytracks.util.LocationUtils; import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import android.content.Context;
import android.location.Location; import android.location.Location;
import android.util.Log; import android.util.Log;
@@ -118,14 +121,35 @@ public class TripStatisticsUpdater {
stats.merge(currentSegment); stats.merge(currentSegment);
return stats; return stats;
} }
/**
* Adds a location.
*
* @param location the location
* @param minRecordingDistance the min recording distance
* @param context the context to get the weight and track category
*/
public void addLocation(Location location, int minRecordingDistance, Context context) {
int weight = PreferencesUtils.getInt(context, R.string.stats_weight_key,
PreferencesUtils.STATS_WEIGHT_DEFAULT);
addLocation(
location,
minRecordingDistance,
CalorieUtils.getActivityType(context,
PreferencesUtils.getLong(context, R.string.recording_track_id_key)), weight);
}
/** /**
* Adds a location. TODO: This assume location has a valid time. * Adds a location. TODO: This assume location has a valid time.
* *
* @param location the location * @param location the location
* @param minRecordingDistance the min recording distance * @param minRecordingDistance the min recording distance
* @param activityType the activity type of current track
* @param weight the weight to calculate calorie
*/ */
public void addLocation(Location location, int minRecordingDistance, int weight) { @VisibleForTesting
void addLocation(Location location, int minRecordingDistance, ActivityType activityType,
int weight) {
// Always update time // Always update time
updateTime(location.getTime()); updateTime(location.getTime());
@@ -189,13 +213,10 @@ public class TripStatisticsUpdater {
updateSpeed( updateSpeed(
location.getTime(), location.getSpeed(), lastLocation.getTime(), lastLocation.getSpeed()); location.getTime(), location.getSpeed(), lastLocation.getTime(), lastLocation.getSpeed());
} }
// TODO 1: How to get the value of weight.
// TODO 2: How to get the value of ActivityType.
// Update calorie // Update calorie
double calorie = CalorieUtils.getCalorie(lastMovingLocation, location, double calorie = CalorieUtils.getCalorie(lastMovingLocation, location,
gradeBuffer.getAverage(), weight, ActivityType.FOOT); gradeBuffer.getAverage(), weight, activityType);
currentSegment.addCalorie(calorie); currentSegment.addCalorie(calorie);
lastLocation = location; lastLocation = location;
@@ -15,8 +15,13 @@
*/ */
package com.google.android.apps.mytracks.util; package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.mytracks.R;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import android.content.Context;
import android.location.Location; import android.location.Location;
/** /**
@@ -64,7 +69,7 @@ public class CalorieUtils {
* UnitConversions.KM_TO_M / UnitConversions.HR_TO_MIN; * UnitConversions.KM_TO_M / UnitConversions.HR_TO_MIN;
public enum ActivityType { public enum ActivityType {
CYCLING, FOOT CYCLING, FOOT, INVALID
} }
/** /**
@@ -213,7 +218,36 @@ public class CalorieUtils {
*/ */
public static double getCalorie(Location start, Location stop, double grade, int weight, public static double getCalorie(Location start, Location stop, double grade, int weight,
ActivityType activityType) { ActivityType activityType) {
if (activityType == ActivityType.INVALID) {
return TripStatistics.INVALID_CALORIE;
}
return ActivityType.CYCLING == activityType ? calculateCalorieCycling(start, stop, grade, return ActivityType.CYCLING == activityType ? calculateCalorieCycling(start, stop, grade,
weight) : calculateCalorieFoot(start, stop, grade, weight); weight) : calculateCalorieFoot(start, stop, grade, weight);
} }
}
/**
* Gets the activity type for calculating calorie by the category of track.
*
* @param context current context
* @param trackId the id of track
* @return activityType the activity type of track.
*/
public static ActivityType getActivityType(Context context, long trackId) {
ActivityType activityType = ActivityType.INVALID;
Track track = MyTracksProviderUtils.Factory.get(context).getTrack(trackId);
if (track != null) {
String category = track.getCategory();
if (category.equals(context.getString(R.string.activity_type_walking))
|| category.equals(context.getString(R.string.activity_type_running))) {
activityType = ActivityType.FOOT;
} else if (category.equals(context.getString(R.string.activity_type_cycling))
|| category.equals(context.getString(R.string.activity_type_biking))) {
activityType = ActivityType.CYCLING;
}
}
return activityType;
}
}
@@ -17,6 +17,7 @@
package com.google.android.apps.mytracks.util; package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.CalorieUtils.ActivityType;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -108,8 +109,10 @@ public class StatsUtils {
* *
* @param activity the activity * @param activity the activity
* @param tripStatistics the trip statistics * @param tripStatistics the trip statistics
* @param trackId the id of track
*/ */
public static void setTripStatisticsValues(Activity activity, TripStatistics tripStatistics) { public static void setTripStatisticsValues(Activity activity, TripStatistics tripStatistics,
long trackId) {
boolean metricUnits = PreferencesUtils.isMetricUnits(activity); boolean metricUnits = PreferencesUtils.isMetricUnits(activity);
boolean reportSpeed = PreferencesUtils.isReportSpeed(activity); boolean reportSpeed = PreferencesUtils.isReportSpeed(activity);
@@ -183,12 +186,15 @@ public class StatsUtils {
if (showCalorie) { if (showCalorie) {
calorieHorizontalLine.setVisibility(View.VISIBLE); calorieHorizontalLine.setVisibility(View.VISIBLE);
calorieContainer.setVisibility(View.VISIBLE); calorieContainer.setVisibility(View.VISIBLE);
double calories = tripStatistics == null ? Double.NaN : tripStatistics.getCalorie(); double calories = Double.NaN;
setCalorie(activity, R.id.stats_calorie, R.string.stats_calorie, calories); if (tripStatistics != null) {
calories = tripStatistics.getCalorie();
}
setCalorie(activity, R.id.stats_calorie, calories, trackId);
} else { } else {
calorieHorizontalLine.setVisibility(View.GONE); calorieHorizontalLine.setVisibility(View.GONE);
calorieContainer.setVisibility(View.GONE); calorieContainer.setVisibility(View.GONE);
} }
} }
/** /**
@@ -336,11 +342,18 @@ public class StatsUtils {
* *
* @param activity the activity * @param activity the activity
* @param itemId the item id * @param itemId the item id
* @param labelId the calorie label id
* @param calorie the value of calorie * @param calorie the value of calorie
* @param trackId the id of track
*/ */
private static void setCalorie(Activity activity, int itemId, int labelId, double calorie) { private static void setCalorie(Activity activity, int itemId, double calorie, long trackId) {
int labelId = R.string.stats_calorie;
// Current activity type is not supported.
if (trackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT
&& CalorieUtils.getActivityType(activity, trackId) == ActivityType.INVALID) {
labelId = R.string.stats_calorie_invalid_type;
}
setItem(activity, itemId, labelId, setItem(activity, itemId, labelId,
String.format(Locale.getDefault(), CALORIES_FORMAT, calorie), activity.getString(R.string.unit_calorie)); String.format(Locale.getDefault(), CALORIES_FORMAT, calorie),
activity.getString(R.string.unit_calorie));
} }
} }
@@ -65,6 +65,13 @@ public class TripStatistics implements Parcelable {
// The calorie of current track. // The calorie of current track.
private double calorie; private double calorie;
/**
* This value means the calorie value is invalid due to activity type is not
* supported.
*/
public static final double INVALID_CALORIE = -1;
/** /**
* Default constructor. * Default constructor.
*/ */
@@ -532,7 +539,6 @@ public class TripStatistics implements Parcelable {
data.gradeExtremities.set(minGrade, maxGrade); data.gradeExtremities.set(minGrade, maxGrade);
data.calorie = source.readDouble(); data.calorie = source.readDouble();
return data; return data;
} }
@@ -578,7 +584,9 @@ public class TripStatistics implements Parcelable {
* @param calorieAdded add the value to the total calorie * @param calorieAdded add the value to the total calorie
*/ */
public void addCalorie(double calorieAdded) { public void addCalorie(double calorieAdded) {
this.calorie += calorieAdded; if (calorieAdded != INVALID_CALORIE) {
this.calorie += calorieAdded;
}
} }
/** /**
@@ -591,7 +599,7 @@ public class TripStatistics implements Parcelable {
} }
/** /**
* Gets calories value. * Gets calorie value.
*/ */
public double getCalorie() { public double getCalorie() {
return calorie; return calorie;
@@ -2,6 +2,7 @@
package com.google.android.apps.mytracks.stats; package com.google.android.apps.mytracks.stats;
import com.google.android.apps.mytracks.util.CalorieUtils.ActivityType;
import com.google.android.apps.mytracks.util.PreferencesUtils; import com.google.android.apps.mytracks.util.PreferencesUtils;
import android.location.Location; import android.location.Location;
@@ -224,7 +225,7 @@ public class TripStatisticsUpdaterTest extends TestCase {
Location location = getLocation(i + locationOffset, (i + locationOffset) * .001, MOVING_SPEED, Location location = getLocation(i + locationOffset, (i + locationOffset) * .001, MOVING_SPEED,
startTime + (timeOffset + i) * TEN_SECONDS); startTime + (timeOffset + i) * TEN_SECONDS);
tripStatisticsUpdater.addLocation(location, tripStatisticsUpdater.addLocation(location,
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, ActivityType.FOOT,
PreferencesUtils.STATS_WEIGHT_DEFAULT); PreferencesUtils.STATS_WEIGHT_DEFAULT);
tripStatistics = tripStatisticsUpdater.getTripStatistics(); tripStatistics = tripStatisticsUpdater.getTripStatistics();
@@ -271,7 +272,7 @@ public class TripStatisticsUpdaterTest extends TestCase {
Location location = getLocation( Location location = getLocation(
locationOffset, locationOffset * .001, 0, startTime + (i + timeOffset) * TEN_SECONDS); locationOffset, locationOffset * .001, 0, startTime + (i + timeOffset) * TEN_SECONDS);
tripStatisticsUpdater.addLocation(location, tripStatisticsUpdater.addLocation(location,
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, ActivityType.FOOT,
PreferencesUtils.STATS_WEIGHT_DEFAULT); PreferencesUtils.STATS_WEIGHT_DEFAULT);
tripStatistics = tripStatisticsUpdater.getTripStatistics(); tripStatistics = tripStatisticsUpdater.getTripStatistics();
@@ -309,7 +310,7 @@ public class TripStatisticsUpdaterTest extends TestCase {
Location location = getLocation(i + locationOffset, (i + locationOffset) * .001, 99999, Location location = getLocation(i + locationOffset, (i + locationOffset) * .001, 99999,
startTime + (timeOffset + i) * TEN_SECONDS); startTime + (timeOffset + i) * TEN_SECONDS);
tripStatisticsUpdater.addLocation(location, tripStatisticsUpdater.addLocation(location,
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, ActivityType.FOOT,
PreferencesUtils.STATS_WEIGHT_DEFAULT); PreferencesUtils.STATS_WEIGHT_DEFAULT);
tripStatistics = tripStatisticsUpdater.getTripStatistics(); tripStatistics = tripStatisticsUpdater.getTripStatistics();