forked from upstream-mirrors/OpenTracks
merge heads
This commit is contained in:
@@ -142,5 +142,12 @@ limitations under the License.
|
||||
<include
|
||||
android:id="@+id/stats_calorie"
|
||||
layout="@layout/stats_small_item" />
|
||||
<!-- Setup activity type-->
|
||||
<Button
|
||||
android:id="@+id/stats_calorie_setup"
|
||||
android:layout_gravity="right"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/stats_calorie_setup" />
|
||||
</LinearLayout>
|
||||
</merge>
|
||||
@@ -2141,6 +2141,12 @@ limitations under the License.
|
||||
Character limit: ~23 (1 line)">
|
||||
Calories
|
||||
</string>
|
||||
<string name="stats_calorie_setup"
|
||||
translation_description="In the 'Stats' page, the button to setup calorie.
|
||||
|
||||
Character limit: ~23 (1 line)">
|
||||
Setup Activity Type
|
||||
</string>
|
||||
<string name="stats_fastest_pace"
|
||||
translation_description="In the 'Stats' page, the 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.Track;
|
||||
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.maps.mytracks.R;
|
||||
|
||||
@@ -36,7 +37,8 @@ public class AggregatedStatsActivity extends AbstractMyTracksActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
StatsUtils.setTripStatisticsValues(this, getTripStatistics());
|
||||
StatsUtils.setTripStatisticsValues(this, getTripStatistics(),
|
||||
PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
||||
StatsUtils.setLocationValues(this, null, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,12 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.fragments.ChooseActivityTypeDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
import com.google.android.apps.mytracks.util.CalorieUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackIconUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackNameUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
@@ -57,6 +60,7 @@ public class TrackEditActivity extends AbstractMyTracksActivity
|
||||
private static final String ICON_VALUE_KEY = "icon_value_key";
|
||||
|
||||
private Long trackId;
|
||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||
private MyTracksProviderUtils myTracksProviderUtils;
|
||||
private Track track;
|
||||
private String iconValue;
|
||||
@@ -70,6 +74,7 @@ public class TrackEditActivity extends AbstractMyTracksActivity
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, null);
|
||||
trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L);
|
||||
if (trackId == -1L) {
|
||||
Log.e(TAG, "invalid trackId");
|
||||
@@ -180,6 +185,15 @@ public class TrackEditActivity extends AbstractMyTracksActivity
|
||||
public void onClick(View v) {
|
||||
track.setName(name.getText().toString());
|
||||
String category = activityType.getText().toString();
|
||||
if (!category.equals(track.getCategory())) {
|
||||
// TODO Is there no race condition when setCalorie is called.
|
||||
double calorie = CalorieUtils.calculateTrackCalorie(getApplicationContext(), track,
|
||||
category);
|
||||
|
||||
track.getTripStatistics().setCalorie(calorie);
|
||||
TrackRecordingServiceConnectionUtils.updateCalorie(trackRecordingServiceConnection,
|
||||
calorie);
|
||||
}
|
||||
track.setCategory(category);
|
||||
track.setIcon(TrackIconUtils.getIconValue(TrackEditActivity.this, category));
|
||||
track.setDescription(description.getText().toString());
|
||||
@@ -209,6 +223,18 @@ public class TrackEditActivity extends AbstractMyTracksActivity
|
||||
cancel.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
TrackRecordingServiceConnectionUtils.startConnection(this, trackRecordingServiceConnection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
trackRecordingServiceConnection.unbind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
|
||||
@@ -587,8 +587,7 @@ public class TrackDataHub implements DataSourceListener {
|
||||
*
|
||||
* @return the selectedTrackId
|
||||
*/
|
||||
@VisibleForTesting
|
||||
long getSelectedTrackId() {
|
||||
public long getSelectedTrackId() {
|
||||
return selectedTrackId;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
@@ -189,7 +188,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
||||
public void onSampledInTrackPoint(Location location) {
|
||||
if (isResumed()) {
|
||||
double[] data = new double[ChartView.NUM_SERIES + 1];
|
||||
fillDataPoint(getActivity(), location, data);
|
||||
fillDataPoint(location, data);
|
||||
pendingPoints.add(data);
|
||||
}
|
||||
}
|
||||
@@ -197,14 +196,14 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
||||
@Override
|
||||
public void onSampledOutTrackPoint(Location location) {
|
||||
if (isResumed()) {
|
||||
fillDataPoint(getActivity(), location, null);
|
||||
fillDataPoint(location, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSegmentSplit(Location location) {
|
||||
if (isResumed()) {
|
||||
fillDataPoint(getActivity(), location, null);
|
||||
fillDataPoint(location, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,12 +437,11 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
||||
* data[5] = cadence <br>
|
||||
* data[6] = power <br>
|
||||
*
|
||||
* @param context the context
|
||||
* @param location the location
|
||||
* @param data the data point to fill in, can be null
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void fillDataPoint(Context context, Location location, double data[]) {
|
||||
void fillDataPoint(Location location, double data[]) {
|
||||
double timeOrDistance = Double.NaN;
|
||||
double elevation = Double.NaN;
|
||||
double speed = Double.NaN;
|
||||
@@ -453,9 +451,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
||||
double power = Double.NaN;
|
||||
|
||||
if (tripStatisticsUpdater != null) {
|
||||
int weight = PreferencesUtils.getInt(
|
||||
context, R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT);
|
||||
tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, weight);
|
||||
tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, getActivity());
|
||||
TripStatistics tripStatistics = tripStatisticsUpdater.getTripStatistics();
|
||||
if (chartByDistance) {
|
||||
double distance = tripStatistics.getTotalDistance() * UnitConversions.M_TO_KM;
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||
import com.google.android.apps.mytracks.util.PhotoUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.StatsUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
@@ -192,7 +193,8 @@ public class MarkerDetailFragment extends Fragment {
|
||||
TextView name = (TextView) getView().findViewById(R.id.marker_detail_statistics_name);
|
||||
name.setText(getString(R.string.generic_name_line, waypoint.getName()));
|
||||
|
||||
StatsUtils.setTripStatisticsValues(getActivity(), waypoint.getTripStatistics());
|
||||
StatsUtils.setTripStatisticsValues(getActivity(), waypoint.getTripStatistics(),
|
||||
PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
||||
StatsUtils.setLocationValues(getActivity(), waypoint.getLocation(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +259,11 @@ public class StatsFragment extends Fragment implements TrackDataListener {
|
||||
* Updates the UI.
|
||||
*/
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
+3
-8
@@ -242,11 +242,8 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
return;
|
||||
}
|
||||
trackTripStatisticstrackUpdater.addLocation(trackPoint, recordingDistanceInterval,
|
||||
PreferencesUtils.getInt(context, R.string.stats_weight_key,
|
||||
PreferencesUtils.STATS_WEIGHT_DEFAULT));
|
||||
markerTripStatisticsUpdater.addLocation(trackPoint, recordingDistanceInterval,
|
||||
PreferencesUtils.getInt(context, R.string.stats_weight_key,
|
||||
PreferencesUtils.STATS_WEIGHT_DEFAULT));
|
||||
context);
|
||||
markerTripStatisticsUpdater.addLocation(trackPoint, recordingDistanceInterval, context);
|
||||
}
|
||||
if (waypoint.getLocation().getTime() > trackPoint.getTime()) {
|
||||
trackPoint = null;
|
||||
@@ -549,9 +546,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
trackData.tripStatisticsUpdater = new TripStatisticsUpdater(
|
||||
location.getTime() != -1L ? location.getTime() : trackData.importTime);
|
||||
}
|
||||
trackData.tripStatisticsUpdater.addLocation(location, recordingDistanceInterval,
|
||||
PreferencesUtils.getInt(context, R.string.stats_weight_key,
|
||||
PreferencesUtils.STATS_WEIGHT_DEFAULT));
|
||||
trackData.tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
|
||||
|
||||
trackData.bufferedLocations[trackData.numBufferedLocations] = location;
|
||||
trackData.numBufferedLocations++;
|
||||
|
||||
@@ -277,8 +277,7 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
|
||||
sentStartMarker = true;
|
||||
}
|
||||
|
||||
tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, PreferencesUtils
|
||||
.getInt(context, R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT));
|
||||
tripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
|
||||
if (i % elevationSamplingFrequency == 0) {
|
||||
distances.add(tripStatisticsUpdater.getTripStatistics().getTotalDistance());
|
||||
elevations.add(tripStatisticsUpdater.getSmoothedElevation());
|
||||
|
||||
@@ -659,13 +659,9 @@ public class TrackRecordingService extends Service {
|
||||
if (cursor.moveToLast()) {
|
||||
do {
|
||||
Location location = myTracksProviderUtils.createTrackPoint(cursor);
|
||||
trackTripStatisticsUpdater.addLocation(location, recordingDistanceInterval,
|
||||
PreferencesUtils.getInt(context, R.string.stats_weight_key,
|
||||
PreferencesUtils.STATS_WEIGHT_DEFAULT));
|
||||
trackTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
|
||||
if (location.getTime() > markerStartTime) {
|
||||
markerTripStatisticsUpdater.addLocation(location, recordingDistanceInterval,
|
||||
PreferencesUtils.getInt(context, R.string.stats_weight_key,
|
||||
PreferencesUtils.STATS_WEIGHT_DEFAULT));
|
||||
markerTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
|
||||
}
|
||||
} while (cursor.moveToPrevious());
|
||||
}
|
||||
@@ -1005,10 +1001,8 @@ public class TrackRecordingService extends Service {
|
||||
try {
|
||||
Uri uri = myTracksProviderUtils.insertTrackPoint(location, track.getId());
|
||||
long trackPointId = Long.parseLong(uri.getLastPathSegment());
|
||||
trackTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, PreferencesUtils
|
||||
.getInt(context, R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT));
|
||||
markerTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, PreferencesUtils
|
||||
.getInt(context, R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT));
|
||||
trackTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
|
||||
markerTripStatisticsUpdater.addLocation(location, recordingDistanceInterval, context);
|
||||
updateRecordingTrack(track, trackPointId, LocationUtils.isValidLocation(location));
|
||||
} catch (SQLiteException e) {
|
||||
/*
|
||||
@@ -1339,5 +1333,34 @@ public class TrackRecordingService extends Service {
|
||||
deathRecipient.binderDied();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCalorie(double calorie) {
|
||||
if (!canAccess()) {
|
||||
return;
|
||||
}
|
||||
trackRecordingService.updateCalorie(calorie);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the calorie value.
|
||||
*
|
||||
* @param calorie new calorie value.
|
||||
*/
|
||||
public void updateCalorie(final double calorie) {
|
||||
if (myTracksLocationManager == null || executorService == null
|
||||
|| !myTracksLocationManager.isAllowed() || executorService.isShutdown()
|
||||
|| executorService.isTerminated()) {
|
||||
return;
|
||||
}
|
||||
executorService.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
trackTripStatisticsUpdater.updateCalorie(calorie);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ public class StatsSettingsActivity extends AbstractSettingsActivity {
|
||||
@SuppressWarnings("deprecation")
|
||||
ListPreference listPreference = (ListPreference) findPreference(getString(R.string.stats_units_key));
|
||||
OnPreferenceChangeListener listener = new OnPreferenceChangeListener() {
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference pref, Object newValue) {
|
||||
configRateListPreference(PreferencesUtils.STATS_UNITS_DEFAULT.equals((String) newValue));
|
||||
@@ -83,6 +84,10 @@ public class StatsSettingsActivity extends AbstractSettingsActivity {
|
||||
* activity.
|
||||
*/
|
||||
updateWeightSummary(PreferencesUtils.STATS_UNITS_DEFAULT.equals((String) newValue));
|
||||
// Recreate weight value dialog.
|
||||
removeDialog(WEIGHT_INPUT_DIALOG);
|
||||
onCreateDialog(WEIGHT_INPUT_DIALOG);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -134,7 +139,8 @@ public class StatsSettingsActivity extends AbstractSettingsActivity {
|
||||
case WEIGHT_INPUT_DIALOG:
|
||||
final EditText weightInput = new EditText(this);
|
||||
weightInput.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
||||
weightInput.setText(Integer.toString(PreferencesUtils.STATS_WEIGHT_DEFAULT));
|
||||
weightInput.setText(Integer.toString(getWeightDisplayValue(PreferencesUtils
|
||||
.isMetricUnits(getApplicationContext()))));
|
||||
weightInput.setSelectAllOnFocus(true);
|
||||
dialog = (new AlertDialog.Builder(this))
|
||||
.setMessage(R.string.settings_stats_calorie_weight_description)
|
||||
|
||||
@@ -22,8 +22,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.ActivityType;
|
||||
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 android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -119,14 +122,35 @@ public class TripStatisticsUpdater {
|
||||
stats.merge(currentSegment);
|
||||
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.
|
||||
*
|
||||
* @param location the location
|
||||
* @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
|
||||
updateTime(location.getTime());
|
||||
|
||||
@@ -190,18 +214,24 @@ public class TripStatisticsUpdater {
|
||||
updateSpeed(
|
||||
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
|
||||
double calorie = CalorieUtils.getCalorie(lastMovingLocation, location,
|
||||
gradeBuffer.getAverage(), weight, ActivityType.FOOT);
|
||||
gradeBuffer.getAverage(), weight, activityType);
|
||||
currentSegment.addCalorie(calorie);
|
||||
|
||||
lastLocation = location;
|
||||
lastMovingLocation = location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the calorie value.
|
||||
*
|
||||
* @param calorie new calorie value.
|
||||
*/
|
||||
public void updateCalorie(double calorie) {
|
||||
currentSegment.setCalorie(calorie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the smoothed elevation over several readings. The elevation readings
|
||||
|
||||
@@ -15,8 +15,13 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks.util;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
|
||||
/**
|
||||
@@ -64,7 +69,7 @@ public class CalorieUtils {
|
||||
* UnitConversions.KM_TO_M / UnitConversions.HR_TO_MIN;
|
||||
|
||||
public enum ActivityType {
|
||||
CYCLING, FOOT
|
||||
CYCLING, FOOT, INVALID
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,14 +133,14 @@ public class CalorieUtils {
|
||||
* @param grade the grade to calculate
|
||||
* @param weight of rider plus bike, in kilogram
|
||||
* @param timeUsed how many times used in second
|
||||
* @return the power value watts(Joule/second).
|
||||
* @return the calorie value in kcal.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static double calculateCyclingCalorie(double speed, double grade, int weight, double timeUsed) {
|
||||
// Get the Power, the unit is Watt (Joule/second)
|
||||
double power = earthGravity * weight * speed * (K1 + grade) + K2 * (speed * speed * speed);
|
||||
|
||||
// Get the calories
|
||||
// Get the calories in kcal
|
||||
return power * timeUsed / UnitConversions.KCAL_TO_J;
|
||||
}
|
||||
|
||||
@@ -213,7 +218,89 @@ public class CalorieUtils {
|
||||
*/
|
||||
public static double getCalorie(Location start, Location stop, double grade, int weight,
|
||||
ActivityType activityType) {
|
||||
if (activityType == ActivityType.INVALID) {
|
||||
return 0.0;
|
||||
}
|
||||
return ActivityType.CYCLING == activityType ? calculateCalorieCycling(start, stop, grade,
|
||||
weight) : calculateCalorieFoot(start, stop, grade, weight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the activity type for calculating calorie by the id 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the activity type for calculating calorie by the category of track.
|
||||
*
|
||||
* @param context current context
|
||||
* @param category the category of track
|
||||
* @return activityType the activity type of track.
|
||||
*/
|
||||
public static ActivityType getActivityType(Context context, String category) {
|
||||
ActivityType activityType = ActivityType.INVALID;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the calorie of track.
|
||||
*
|
||||
* @param context the context
|
||||
* @param track the track to calculate
|
||||
* @param category the category of track
|
||||
*/
|
||||
public static double calculateTrackCalorie(Context context, Track track, String category) {
|
||||
ActivityType activityType = getActivityType(context, category);
|
||||
if (activityType == ActivityType.INVALID) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double calorie = 0.0;
|
||||
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
long trackId = track.getId();
|
||||
LocationIterator points = providerUtils.getTrackPointLocationIterator(trackId, -1, false,
|
||||
MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
// TODO How get grade
|
||||
double grade = 0;
|
||||
if (points.hasNext()) {
|
||||
Location start = points.next();
|
||||
while (points.hasNext()) {
|
||||
Location stop = points.next();
|
||||
calorie += getCalorie(start, stop, grade, PreferencesUtils.getInt(context,
|
||||
R.string.stats_weight_key, PreferencesUtils.STATS_WEIGHT_DEFAULT), activityType);
|
||||
start = stop;
|
||||
}
|
||||
}
|
||||
return calorie;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package com.google.android.apps.mytracks.util;
|
||||
|
||||
import com.google.android.apps.mytracks.TrackEditActivity;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
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 android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.location.Location;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.Locale;
|
||||
@@ -108,8 +114,9 @@ public class StatsUtils {
|
||||
*
|
||||
* @param activity the activity
|
||||
* @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 reportSpeed = PreferencesUtils.isReportSpeed(activity);
|
||||
|
||||
@@ -181,14 +188,20 @@ public class StatsUtils {
|
||||
View calorieContainer = activity.findViewById(R.id.stats_calorie_container);
|
||||
|
||||
if (showCalorie) {
|
||||
if(trackId == PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
|
||||
return;
|
||||
}
|
||||
calorieHorizontalLine.setVisibility(View.VISIBLE);
|
||||
calorieContainer.setVisibility(View.VISIBLE);
|
||||
double calories = tripStatistics == null ? Double.NaN : tripStatistics.getCalorie();
|
||||
setCalorie(activity, R.id.stats_calorie, R.string.stats_calorie, calories);
|
||||
double calories = Double.NaN;
|
||||
if (tripStatistics != null) {
|
||||
calories = tripStatistics.getCalorie();
|
||||
}
|
||||
setCalorie(activity, R.id.stats_calorie, calories, trackId);
|
||||
} else {
|
||||
calorieHorizontalLine.setVisibility(View.GONE);
|
||||
calorieContainer.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,11 +349,45 @@ public class StatsUtils {
|
||||
*
|
||||
* @param activity the activity
|
||||
* @param itemId the item id
|
||||
* @param labelId the calorie label id
|
||||
* @param calorie the value of calorie
|
||||
* @param trackId the id of track which is used to start track edit activity
|
||||
* when user want to change the activity type
|
||||
*/
|
||||
private static void setCalorie(Activity activity, int itemId, int labelId, double calorie) {
|
||||
setItem(activity, itemId, labelId,
|
||||
String.format(Locale.getDefault(), CALORIES_FORMAT, calorie), activity.getString(R.string.unit_calorie));
|
||||
private static void setCalorie(final Activity activity, int itemId, double calorie,
|
||||
final long trackId) {
|
||||
String calorieString;
|
||||
View view = activity.findViewById(itemId);
|
||||
Button button = (Button) activity.findViewById(R.id.stats_calorie_setup);
|
||||
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(activity);
|
||||
ActivityType activityType = CalorieUtils.getActivityType(activity,
|
||||
providerUtils.getTrack(trackId).getCategory());
|
||||
// Current activity type is not supported.
|
||||
if (activityType == ActivityType.INVALID) {
|
||||
button.setVisibility(View.VISIBLE);
|
||||
view.setVisibility(View.GONE);
|
||||
|
||||
/*
|
||||
* Return when it is not a valid track, which may be aggregated stats or
|
||||
* marker.
|
||||
*/
|
||||
if (trackId == PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
|
||||
button.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
button.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = IntentUtils.newIntent(activity, TrackEditActivity.class).putExtra(
|
||||
TrackEditActivity.EXTRA_TRACK_ID, trackId);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
button.setVisibility(View.GONE);
|
||||
view.setVisibility(View.VISIBLE);
|
||||
calorieString = String.format(Locale.getDefault(), CALORIES_FORMAT, calorie);
|
||||
setItem(activity, itemId, R.string.stats_calorie, calorieString,
|
||||
activity.getString(R.string.unit_calorie));
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -193,4 +193,24 @@ public class TrackRecordingServiceConnectionUtils {
|
||||
Toast.makeText(context, R.string.marker_add_error, Toast.LENGTH_LONG).show();
|
||||
return -1L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the calorie of current recording track.
|
||||
*/
|
||||
public static void updateCalorie(TrackRecordingServiceConnection trackRecordingServiceConnection,
|
||||
double calorie) {
|
||||
ITrackRecordingService trackRecordingService = trackRecordingServiceConnection
|
||||
.getServiceIfBound();
|
||||
if (trackRecordingService == null) {
|
||||
Log.d(TAG, "Unable to update calorie, no track recording service");
|
||||
} else {
|
||||
try {
|
||||
trackRecordingService.updateCalorie(calorie);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to update calorie", e);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Unable to update calorie.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,5 +78,8 @@ public class UnitConversions {
|
||||
public static final double DEG_TO_RAD = Math.PI / 180.0;
|
||||
|
||||
// multiplication factor to convert Kcal to joules.
|
||||
public static final double KCAL_TO_J = 4.184;
|
||||
public static final double KCAL_TO_J = 4184;
|
||||
|
||||
// multiplication factor to convert joules to Kcal.
|
||||
public static final double J_TO_KCAL = 1 / KCAL_TO_J;
|
||||
}
|
||||
|
||||
@@ -106,4 +106,11 @@ interface ITrackRecordingService {
|
||||
* return a Sensor.SensorState enum value.
|
||||
*/
|
||||
int getSensorState();
|
||||
|
||||
/**
|
||||
* Updates the calorie value.
|
||||
*
|
||||
* @param calorie new calorie value.
|
||||
*/
|
||||
void updateCalorie(double calorie);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class TripStatistics implements Parcelable {
|
||||
private final ExtremityMonitor gradeExtremities = new ExtremityMonitor();
|
||||
|
||||
// The calorie of current track.
|
||||
private double calorie;
|
||||
private double calorie = 0.0;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
@@ -532,7 +532,6 @@ public class TripStatistics implements Parcelable {
|
||||
data.gradeExtremities.set(minGrade, maxGrade);
|
||||
|
||||
data.calorie = source.readDouble();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -578,7 +577,7 @@ public class TripStatistics implements Parcelable {
|
||||
* @param calorieAdded add the value to the total calorie
|
||||
*/
|
||||
public void addCalorie(double calorieAdded) {
|
||||
this.calorie += calorieAdded;
|
||||
calorie += calorieAdded;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -591,7 +590,7 @@ public class TripStatistics implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets calories value.
|
||||
* Gets calorie value.
|
||||
*/
|
||||
public double getCalorie() {
|
||||
return calorie;
|
||||
|
||||
@@ -359,7 +359,7 @@ public class ChartFragmentTest extends AndroidTestCase {
|
||||
*/
|
||||
private double[] fillDataPointTestHelper(Location location) {
|
||||
double[] point = new double[ChartView.NUM_SERIES + 1];
|
||||
chartFragment.fillDataPoint(getContext(), location, point);
|
||||
chartFragment.fillDataPoint(location, point);
|
||||
return point;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -2,6 +2,7 @@
|
||||
|
||||
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 android.location.Location;
|
||||
@@ -224,7 +225,7 @@ public class TripStatisticsUpdaterTest extends TestCase {
|
||||
Location location = getLocation(i + locationOffset, (i + locationOffset) * .001, MOVING_SPEED,
|
||||
startTime + (timeOffset + i) * TEN_SECONDS);
|
||||
tripStatisticsUpdater.addLocation(location,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, ActivityType.FOOT,
|
||||
PreferencesUtils.STATS_WEIGHT_DEFAULT);
|
||||
tripStatistics = tripStatisticsUpdater.getTripStatistics();
|
||||
|
||||
@@ -271,7 +272,7 @@ public class TripStatisticsUpdaterTest extends TestCase {
|
||||
Location location = getLocation(
|
||||
locationOffset, locationOffset * .001, 0, startTime + (i + timeOffset) * TEN_SECONDS);
|
||||
tripStatisticsUpdater.addLocation(location,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, ActivityType.FOOT,
|
||||
PreferencesUtils.STATS_WEIGHT_DEFAULT);
|
||||
|
||||
tripStatistics = tripStatisticsUpdater.getTripStatistics();
|
||||
@@ -309,7 +310,7 @@ public class TripStatisticsUpdaterTest extends TestCase {
|
||||
Location location = getLocation(i + locationOffset, (i + locationOffset) * .001, 99999,
|
||||
startTime + (timeOffset + i) * TEN_SECONDS);
|
||||
tripStatisticsUpdater.addLocation(location,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, ActivityType.FOOT,
|
||||
PreferencesUtils.STATS_WEIGHT_DEFAULT);
|
||||
tripStatistics = tripStatisticsUpdater.getTripStatistics();
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ public class CalorieUtilsTest extends TestCase {
|
||||
|
||||
Location start = new Location(LocationManager.GPS_PROVIDER);
|
||||
Location stop = new Location(LocationManager.GPS_PROVIDER);
|
||||
private double grade = 10.0;
|
||||
private int weight = 20;
|
||||
private double grade = 0.07;
|
||||
private int weight = 80;
|
||||
private final long TIME_INTERVAL = 1000l;
|
||||
|
||||
@Override
|
||||
@@ -94,4 +94,16 @@ public class CalorieUtilsTest extends TestCase {
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Checks calculating cycling calorie.
|
||||
*/
|
||||
public void testCalculateCalorieCycling() {
|
||||
grade = 0;
|
||||
weight = 90;
|
||||
start.setSpeed(9);
|
||||
stop.setSpeed(9);
|
||||
double expected = 175 / 1000 / UnitConversions.KCAL_TO_J;
|
||||
double actual = CalorieUtils.calculateCalorieCycling(start, stop, grade, weight);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user