Merging heads

This commit is contained in:
Rodrigo Damazio
2012-02-06 10:38:38 -02:00
10 changed files with 652 additions and 75 deletions
@@ -17,6 +17,7 @@ package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.ChartView.Mode;
import com.google.android.maps.mytracks.R;
import com.google.common.annotations.VisibleForTesting;
import android.app.Dialog;
import android.content.Context;
@@ -118,4 +119,9 @@ public class ChartSettingsDialog extends Dialog {
public void setOnClickListener(OnClickListener clickListener) {
this.clickListener = clickListener;
}
}
@VisibleForTesting
CheckBox[] getSeries() {
return series;
}
}
@@ -9,6 +9,7 @@ import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.StringUtils;
@@ -216,10 +217,10 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
Location lastLocation = null;
// Limit the number of elevation readings. Ideally we would want around
// 250.
// For chart server, limit the number of elevation readings to 250.
int elevationSamplingFrequency = Math.max(1, (int) (locationsCount / 250.0));
double totalDistance = 0;
TripStatisticsBuilder tripStatisticsBuilder = new TripStatisticsBuilder(
track.getStatistics().getStartTime());
DoubleBuffer elevationBuffer = new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
Vector<Double> distances = new Vector<Double>();
Vector<Double> elevations = new Vector<Double>();
@@ -230,9 +231,7 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
Location location = myTracksProviderUtils.createLocation(locationsCursor);
locations.add(location);
int readCount = i + 1;
if (readCount == 1) {
if (i == 0) {
// Create a start marker
String name = context.getString(R.string.marker_label_start, track.getName());
if (!createNewPoint(name, "", location, MARKER_TYPE_START)) {
@@ -243,19 +242,19 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
// Add to the distances and elevations vectors
if (LocationUtils.isValidLocation(location)) {
tripStatisticsBuilder.addLocation(location, location.getTime());
// All points go into the smoothing buffer
elevationBuffer.setNext(metricUnits ? location.getAltitude()
: location.getAltitude() * UnitConversions.M_TO_FT);
if (lastLocation != null) {
totalDistance += (double) lastLocation.distanceTo(location);
}
if (readCount % elevationSamplingFrequency == 0) {
distances.add(totalDistance);
if (i % elevationSamplingFrequency == 0) {
distances.add(tripStatisticsBuilder.getStatistics().getTotalDistance());
elevations.add(elevationBuffer.getAverage());
}
lastLocation = location;
}
// Upload periodically
int readCount = i + 1;
if (readCount % MAX_POINTS_PER_UPLOAD == 0) {
if (!prepareAndUploadPoints(track, locations, false)) {
Log.d(TAG, "Unable to upload points");
@@ -264,7 +263,6 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
updateProgress(readCount, locationsCount);
locations.clear();
}
lastLocation = location;
}
// Do a final upload with the remaining locations
@@ -275,6 +273,8 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
// Create an end marker
if (lastLocation != null) {
distances.add(tripStatisticsBuilder.getStatistics().getTotalDistance());
elevations.add(elevationBuffer.getAverage());
StringUtils stringUtils = new StringUtils(context);
track.setDescription("<p>" + track.getDescription() + "</p><p>"
+ stringUtils.generateTrackDescription(track, distances, elevations) + "</p>");
@@ -27,6 +27,7 @@ import com.google.android.apps.mytracks.io.gdata.maps.XmlMapsGDataParserFactory;
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
@@ -253,9 +254,10 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
Location lastLocation = null;
// Limit the number of elevation readings to 250.
// For chart server, limit the number of elevation readings to 250.
int elevationSamplingFrequency = Math.max(1, (int) (locationsCount / 250.0));
double totalDistance = 0;
TripStatisticsBuilder tripStatisticsBuilder = new TripStatisticsBuilder(
track.getStatistics().getStartTime());
DoubleBuffer elevationBuffer = new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
Vector<Double> distances = new Vector<Double>();
Vector<Double> elevations = new Vector<Double>();
@@ -266,9 +268,7 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
Location location = myTracksProviderUtils.createLocation(locationsCursor);
locations.add(location);
int readCount = i + 1;
if (readCount == 1) {
if (i == 0) {
// Create a start marker
if (!uploadMarker(context.getString(R.string.marker_label_start, track.getName()), "",
START_ICON_URL, location)) {
@@ -279,19 +279,19 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
// Add to the distances and elevations vectors
if (LocationUtils.isValidLocation(location)) {
tripStatisticsBuilder.addLocation(location, location.getTime());
// All points go into the smoothing buffer
elevationBuffer.setNext(metricUnits ? location.getAltitude()
: location.getAltitude() * UnitConversions.M_TO_FT);
if (lastLocation != null) {
totalDistance += (double) lastLocation.distanceTo(location);
}
if (readCount % elevationSamplingFrequency == 0) {
distances.add(totalDistance);
if (i % elevationSamplingFrequency == 0) {
distances.add(tripStatisticsBuilder.getStatistics().getTotalDistance());
elevations.add(elevationBuffer.getAverage());
}
lastLocation = location;
}
// Upload periodically
int readCount = i + 1;
if (readCount % MAX_POINTS_PER_UPLOAD == 0) {
if (!prepareAndUploadPoints(track, locations, false)) {
Log.d(TAG, "Unable to upload points");
@@ -300,7 +300,6 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
updateProgress(readCount, locationsCount);
locations.clear();
}
lastLocation = location;
}
// Do a final upload with the remaining locations
@@ -311,6 +310,8 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
// Create an end marker
if (lastLocation != null) {
distances.add(tripStatisticsBuilder.getStatistics().getTotalDistance());
elevations.add(elevationBuffer.getAverage());
StringUtils stringUtils = new StringUtils(context);
track.setDescription("<p>" + track.getDescription() + "</p><p>"
+ stringUtils.generateTrackDescription(track, distances, elevations) + "</p>");
@@ -22,34 +22,36 @@ 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 android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.util.Log;
/**
* A dynamic speed path descriptor.
*
*
* @author Vangelis S.
*/
public class DynamicSpeedTrackPathDescriptor
implements TrackPathDescriptor, OnSharedPreferenceChangeListener {
public class DynamicSpeedTrackPathDescriptor implements TrackPathDescriptor,
OnSharedPreferenceChangeListener {
private int slowSpeed;
private int normalSpeed;
private int speedMargin;
private final int speedMarginDefault;
private double averageMovingSpeed;
private final Context context;
public DynamicSpeedTrackPathDescriptor(Context context){
@VisibleForTesting
static final int CRITICAL_DIFFERENCE_PERCENTAGE = 20;
public DynamicSpeedTrackPathDescriptor(Context context) {
this.context = context;
speedMarginDefault = Integer.parseInt(
context.getString(R.string.color_mode_dynamic_percentage_default));
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
speedMarginDefault = Integer.parseInt(context
.getString(R.string.color_mode_dynamic_percentage_default));
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME,
Context.MODE_PRIVATE);
if (prefs == null) {
speedMargin = speedMarginDefault;
@@ -60,7 +62,8 @@ public class DynamicSpeedTrackPathDescriptor
speedMargin = getSpeedMargin(prefs);
}
private int getSpeedMargin(SharedPreferences sharedPreferences) {
@VisibleForTesting
int getSpeedMargin(SharedPreferences sharedPreferences) {
try {
return Integer.parseInt(sharedPreferences.getString(
context.getString(R.string.track_color_mode_dynamic_speed_variation_key),
@@ -72,34 +75,32 @@ public class DynamicSpeedTrackPathDescriptor
/**
* Get the slow speed calculated based on the % below the average speed.
*
* @return The speed limit considered as slow.
*/
public int getSlowSpeed()
{
slowSpeed = (int) (averageMovingSpeed - (averageMovingSpeed * speedMargin / 100));
public int getSlowSpeed() {
slowSpeed = (int) (averageMovingSpeed - (averageMovingSpeed * speedMargin / 100));
return slowSpeed;
}
/**
* Get the medium speed calculated based on the % above the average speed.
* Gets the medium speed calculated based on the % above the average speed.
*
* @return The speed limit considered as normal.
*/
public int getNormalSpeed()
{
normalSpeed = (int) (averageMovingSpeed + (averageMovingSpeed * speedMargin / 100));
public int getNormalSpeed() {
normalSpeed = (int) (averageMovingSpeed + (averageMovingSpeed * speedMargin / 100));
return normalSpeed;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d(TAG, "DynamicSpeedTrackPathDescriptor: onSharedPreferences changed " + key);
if (key == null
|| !key.equals(context.getString(R.string.track_color_mode_dynamic_speed_variation_key))) {
return;
}
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (key == null
|| !key.equals(context.getString(R.string.track_color_mode_dynamic_speed_variation_key))) { return; }
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME,
Context.MODE_PRIVATE);
if (prefs == null) {
speedMargin = speedMarginDefault;
return;
@@ -110,33 +111,69 @@ public class DynamicSpeedTrackPathDescriptor
@Override
public boolean needsRedraw() {
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME,
Context.MODE_PRIVATE);
long currentTrackId = prefs.getLong(context.getString(R.string.selected_track_key), -1);
if(currentTrackId == -1) {
// Could not find track.
return false;
if (currentTrackId == -1) {
// Could not find track.
return false;
}
Track track = MyTracksProviderUtils.Factory.get(context).getTrack(currentTrackId);
TripStatistics stats = track.getStatistics();
double newaverageSpeed = (int) Math.floor(stats.getAverageMovingSpeed() * 3.6);
if(averageMovingSpeed == 0) {
averageMovingSpeed = newaverageSpeed;
return true;
}
double difference = Math.max(averageMovingSpeed, newaverageSpeed);
double newAverageMovingSpeed = (int) Math.floor(stats.getAverageMovingSpeed() * 3.6);
if (difference == 0.0) {
difference = 0.0;
} else {
difference = Math.abs(averageMovingSpeed - newaverageSpeed) / difference * 100;
return isDifferenceSignificant(averageMovingSpeed, newAverageMovingSpeed);
}
/**
* Checks whether the old speed and the new speed differ significantly or not.
*/
public boolean isDifferenceSignificant(double oldAverageMovingSpeed, double newAverageMovingSpeed) {
if (oldAverageMovingSpeed == 0) {
if (newAverageMovingSpeed == 0) {
return false;
} else {
averageMovingSpeed = newAverageMovingSpeed;
return true;
}
}
if(difference >= 20) {
averageMovingSpeed = newaverageSpeed;
// Here, both oldAverageMovingSpeed and newAverageMovingSpeed are not zero.
double maxValue = Math.max(oldAverageMovingSpeed, newAverageMovingSpeed);
double differencePercentage = Math.abs(oldAverageMovingSpeed - newAverageMovingSpeed)
/ maxValue * 100;
if (differencePercentage >= CRITICAL_DIFFERENCE_PERCENTAGE) {
averageMovingSpeed = newAverageMovingSpeed;
return true;
}
return false;
}
/**
* Gets the value of variable speedMargin to check the result of test.
* @return the value of speedMargin.
*/
@VisibleForTesting
int getSpeedMargin() {
return speedMargin;
}
/**
* Sets the value of newAverageMovingSpeed to test the method isDifferenceSignificant.
* @param newAverageMovingSpeed the value to set.
*/
@VisibleForTesting
void setAverageMovingSpeed(double newAverageMovingSpeed) {
averageMovingSpeed = newAverageMovingSpeed;
}
/**
* Gets the value of averageMovingSpeed to check the result of test.
*
* @return the value of averageMovingSpeed
*/
@VisibleForTesting
double getAverageMovingSpeed() {
return averageMovingSpeed;
}
}
@@ -97,8 +97,9 @@ public abstract class AntSensorManager extends SensorManager {
if (DEBUGGING) {
Log.d(TAG, "Received RX message " + messageToString(antMessage));
}
handleMessage(antMessage);
if (getAntReceiver() != null) {
handleMessage(antMessage);
}
}
}
};