Added elevation loss via barometer (like elevation gain). Fixes #547.

This commit is contained in:
Román Martínez
2020-12-24 16:47:48 +01:00
parent 4bff376442
commit 4714171e21
29 changed files with 420 additions and 130 deletions
@@ -64,6 +64,7 @@ public class DescriptionGeneratorTest {
stats.setMaxElevation(550);
stats.setMinElevation(-500);
stats.setTotalElevationGain(6000);
stats.setTotalElevationLoss(6000);
stats.setStartTime_ms(START_TIME);
track.setTrackStatistics(stats);
track.setCategory("hiking");
@@ -84,6 +85,7 @@ public class DescriptionGeneratorTest {
+ "Max elevation: 550 m (1804 ft)<br>"
+ "Min elevation: -500 m (-1640 ft)<br>"
+ "Elevation gain: 6000 m (19685 ft)<br>"
+ "Elevation loss: 6000 m (19685 ft)<br>"
+ "Recorded: " + StringUtils.formatDateTime(context, START_TIME) + "<br>";
assertEquals(expected, descriptionGenerator.generateTrackDescription(track, true));
@@ -100,6 +102,7 @@ public class DescriptionGeneratorTest {
stats.setMaxElevation(Double.POSITIVE_INFINITY);
stats.setMinElevation(Double.NEGATIVE_INFINITY);
stats.setTotalElevationGain(6000);
stats.setTotalElevationLoss(6000);
stats.setStartTime_ms(START_TIME);
track.setTrackStatistics(stats);
track.setCategory("hiking");
@@ -118,6 +121,7 @@ public class DescriptionGeneratorTest {
+ "Average moving pace: 0:15 min/km (0:24 min/mi)<br>"
+ "Fastest pace: 0:10 min/km (0:16 min/mi)<br>"
+ "Elevation gain: 6000 m (19685 ft)<br>"
+ "Elevation loss: 6000 m (19685 ft)<br>"
+ "Recorded: " + StringUtils.formatDateTime(context, START_TIME) + "<br>";
assertEquals(expected, descriptionGenerator.generateTrackDescription(track, true));
@@ -32,7 +32,7 @@ public class ElevationSumManagerTest {
// then
Assert.assertEquals(0f, elevationSumManager.getElevationGain_m(), 0.01);
Assert.assertEquals(-48.0, elevationSumManager.getElevationLoss_m(), 0.01);
Assert.assertEquals(48.0, elevationSumManager.getElevationLoss_m(), 0.01);
}
@Test
@@ -43,7 +43,7 @@ public class PressureSensorUtilsTest {
// then
assertEquals(0f, elevationGain_m, 0.01);
assertEquals(-15.0f, elevationLoss_m, 0.01);
assertEquals(15.0f, elevationLoss_m, 0.01);
assertEquals(1016.80f, lastUsedPressureValue_hPa, 0.01); //Expect exponential smoothing
}
}
@@ -45,6 +45,7 @@ public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.I
viewHolder.distance = intervalView.findViewById(R.id.interval_item_distance);
viewHolder.rate = intervalView.findViewById(R.id.interval_item_rate);
viewHolder.gain = intervalView.findViewById(R.id.interval_item_gain);
viewHolder.loss = intervalView.findViewById(R.id.interval_item_loss);
intervalView.setTag(viewHolder);
} else {
@@ -66,6 +67,7 @@ public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.I
}
viewHolder.gain.setText(StringUtils.formatDistance(getContext(), interval.getGain_m(), metricUnits));
viewHolder.loss.setText(StringUtils.formatDistance(getContext(), interval.getLoss_m(), metricUnits));
return intervalView;
}
@@ -82,5 +84,6 @@ public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.I
private TextView distance;
private TextView rate;
private TextView gain;
private TextView loss;
}
}
@@ -140,6 +140,11 @@ public class DescriptionGenerator {
writeElevation(stats.getTotalElevationGain(), builder, R.string.description_elevation_gain, lineBreak);
}
// Elevation loss
if (stats.hasTotalElevationLoss()) {
writeElevation(stats.getTotalElevationLoss(), builder, R.string.description_elevation_loss, lineBreak);
}
// Recorded time
builder.append(context.getString(R.string.description_recorded_time, StringUtils.formatDateTime(context, stats.getStartTime_ms())));
builder.append(lineBreak);
@@ -33,6 +33,7 @@ public class TrackPoint {
private Float cyclingCadence_rpm = null;
private Float power = null;
private Float elevationGain = null;
private Float elevationLoss = null;
public TrackPoint() {
this.location = new Location("");
@@ -50,6 +51,7 @@ public class TrackPoint {
this.power = trackPoint.getPower();
this.elevationGain = trackPoint.getElevationGain();
this.elevationLoss = trackPoint.getElevationLoss();
}
public TrackPoint(double latitude, double longitude, Double altitude, long time) {
@@ -107,6 +109,18 @@ public class TrackPoint {
this.elevationGain = elevationGain;
}
public boolean hasElevationLoss() {
return elevationLoss != null;
}
public float getElevationLoss() {
return elevationLoss;
}
public void setElevationLoss(Float elevationLoss) {
this.elevationLoss = elevationLoss;
}
public double getLatitude() {
return location.getLatitude();
}
@@ -54,6 +54,7 @@ public interface TrackPointsColumns extends BaseColumns {
String SENSOR_CADENCE = "sensor_cadence";
String SENSOR_POWER = "sensor_power";
String ELEVATION_GAIN = "elevation_gain";
String ELEVATION_LOSS = "elevation_loss";
String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " ("
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
@@ -69,6 +70,7 @@ public interface TrackPointsColumns extends BaseColumns {
+ SENSOR_CADENCE + " FLOAT, "
+ SENSOR_POWER + " FLOAT, "
+ ELEVATION_GAIN + " FLOAT, "
+ ELEVATION_LOSS + " FLOAT, "
+ "FOREIGN KEY (" + TRACKID + ") REFERENCES " + TracksColumns.TABLE_NAME + "(" + TracksColumns._ID + ") ON UPDATE CASCADE ON DELETE CASCADE"
+ ")";
@@ -54,6 +54,7 @@ public interface TracksColumns extends BaseColumns {
String MINELEVATION = "minelevation"; // minimum elevation
String MAXELEVATION = "maxelevation"; // maximum elevation
String ELEVATIONGAIN = "elevationgain"; // elevation gain
String ELEVATIONLOSS = "elevationloss"; // elevation loss
String ICON = "icon"; // track activity type icon
String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " ("
@@ -74,7 +75,8 @@ public interface TracksColumns extends BaseColumns {
+ MAXELEVATION + " FLOAT, "
+ ELEVATIONGAIN + " FLOAT, "
+ ICON + " TEXT, "
+ UUID + " BLOB)";
+ UUID + " BLOB, "
+ ELEVATIONLOSS + " FLOAT)";
String CREATE_TABLE_INDEX = "CREATE UNIQUE INDEX " + TABLE_NAME + "_" + UUID + "_index ON " + TABLE_NAME + "(" + UUID + ")";
@@ -20,6 +20,7 @@ class CachedTrackPointsIndexes {
final int sensorCadenceIndex;
final int sensorPowerIndex;
final int elevationGainIndex;
final int elevationLossIndex;
CachedTrackPointsIndexes(Cursor cursor) {
idIndex = cursor.getColumnIndex(TrackPointsColumns._ID);
@@ -34,5 +35,6 @@ class CachedTrackPointsIndexes {
sensorCadenceIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_CADENCE);
sensorPowerIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_POWER);
elevationGainIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.ELEVATION_GAIN);
elevationLossIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.ELEVATION_LOSS);
}
}
@@ -114,6 +114,7 @@ public class ContentProviderUtils {
int minElevationIndex = cursor.getColumnIndexOrThrow(TracksColumns.MINELEVATION);
int maxElevationIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAXELEVATION);
int elevationGainIndex = cursor.getColumnIndexOrThrow(TracksColumns.ELEVATIONGAIN);
int elevationLossIndex = cursor.getColumnIndexOrThrow(TracksColumns.ELEVATIONLOSS);
int iconIndex = cursor.getColumnIndexOrThrow(TracksColumns.ICON);
Track track = new Track();
@@ -160,6 +161,9 @@ public class ContentProviderUtils {
if (!cursor.isNull(elevationGainIndex)) {
trackStatistics.setTotalElevationGain(cursor.getFloat(elevationGainIndex));
}
if (!cursor.isNull(elevationLossIndex)) {
trackStatistics.setTotalElevationLoss(cursor.getFloat(elevationLossIndex));
}
if (!cursor.isNull(iconIndex)) {
track.setIcon(cursor.getString(iconIndex));
}
@@ -300,6 +304,7 @@ public class ContentProviderUtils {
values.put(TracksColumns.MINELEVATION, trackStatistics.getMinElevation());
values.put(TracksColumns.MAXELEVATION, trackStatistics.getMaxElevation());
values.put(TracksColumns.ELEVATIONGAIN, trackStatistics.getTotalElevationGain());
values.put(TracksColumns.ELEVATIONLOSS, trackStatistics.getTotalElevationLoss());
values.put(TracksColumns.ICON, track.getIcon());
return values;
@@ -591,6 +596,9 @@ public class ContentProviderUtils {
if (!cursor.isNull(indexes.elevationGainIndex)) {
trackPoint.setElevationGain(cursor.getFloat(indexes.elevationGainIndex));
}
if (!cursor.isNull(indexes.elevationLossIndex)) {
trackPoint.setElevationLoss(cursor.getFloat(indexes.elevationLossIndex));
}
return trackPoint;
}
@@ -793,6 +801,9 @@ public class ContentProviderUtils {
if (trackPoint.hasElevationGain()) {
values.put(TrackPointsColumns.ELEVATION_GAIN, trackPoint.getElevationGain());
}
if (trackPoint.hasElevationLoss()) {
values.put(TrackPointsColumns.ELEVATION_LOSS, trackPoint.getElevationLoss());
}
return values;
}
@@ -25,7 +25,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
private static final String TAG = CustomSQLiteOpenHelper.class.getSimpleName();
private static final int DATABASE_VERSION = 28;
private static final int DATABASE_VERSION = 29;
@VisibleForTesting
public static final String DATABASE_NAME = "database.db";
@@ -76,6 +76,9 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
case 28:
upgradeFrom27to28(db);
break;
case 29:
upgradeFrom28to29(db);
break;
default:
throw new RuntimeException("Not implemented: upgrade to " + toVersion);
@@ -103,6 +106,9 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
case 27:
downgradeFrom28to27(db);
break;
case 28:
downgradeFrom29to28(db);
break;
default:
throw new RuntimeException("Not implemented: downgrade to " + toVersion);
@@ -284,4 +290,44 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
db.setTransactionSuccessful();
db.endTransaction();
}
/**
* Add elevation loss.
*/
private void upgradeFrom28to29(SQLiteDatabase db) {
db.beginTransaction();
db.execSQL("ALTER TABLE tracks ADD COLUMN elevationloss FLOAT");
db.execSQL("ALTER TABLE trackpoints ADD COLUMN elevation_loss FLOAT");
db.setTransactionSuccessful();
db.endTransaction();
}
private void downgradeFrom29to28(SQLiteDatabase db) {
db.beginTransaction();
// Tracks
db.execSQL("DROP INDEX tracks_uuid_index");
db.execSQL("ALTER TABLE tracks RENAME TO tracks_old");
db.execSQL("CREATE TABLE tracks (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, category TEXT, starttime INTEGER, stoptime INTEGER, numpoints INTEGER, totaldistance FLOAT, totaltime INTEGER, movingtime INTEGER, avgspeed FLOAT, avgmovingspeed FLOAT, maxspeed FLOAT, minelevation FLOAT, maxelevation FLOAT, elevationgain FLOAT, icon TEXT, uuid BLOB)");
db.execSQL("INSERT INTO tracks SELECT _id, name, description, category, starttime, stoptime, numpoints, totaldistance, totaltime, movingtime, avgspeed, avgmovingspeed, maxspeed, minelevation, maxelevation, elevationgain, icon, uuid FROM tracks_old");
db.execSQL("DROP TABLE tracks_old");
db.execSQL("CREATE UNIQUE INDEX tracks_uuid_index ON tracks(uuid)");
// TrackPoints
db.execSQL("DROP INDEX trackpoints_trackid_index");
db.execSQL("ALTER TABLE trackpoints RENAME TO trackpoints_old");
db.execSQL("CREATE TABLE trackpoints (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackid INTEGER NOT NULL, longitude INTEGER, latitude INTEGER, time INTEGER, elevation FLOAT, accuracy FLOAT, speed FLOAT, bearing FLOAT, sensor_heartrate FLOAT, sensor_cadence FLOAT, sensor_power FLOAT, elevation_gain FLOAT, FOREIGN KEY (trackid) REFERENCES tracks(_id) ON UPDATE CASCADE ON DELETE CASCADE)");
db.execSQL("INSERT INTO trackpoints SELECT _id, trackid, longitude, latitude, time, elevation, accuracy, speed, bearing, sensor_heartrate, sensor_cadence, sensor_power, elevation_gain FROM trackpoints_old");
db.execSQL("DROP TABLE trackpoints_old");
db.execSQL("CREATE INDEX trackpoints_trackid_index ON trackpoints(trackid)");
db.setTransactionSuccessful();
db.endTransaction();
}
}
@@ -176,17 +176,24 @@ public class StatisticsRecordedFragment extends Fragment {
viewBinding.statsMovingSpeedUnit.setText(parts.second);
}
// Set elevation gain
// Set elevation gain and loss
{
// Make elevation visible?
boolean showElevation = PreferencesUtils.isShowStatsElevation(getContext());
viewBinding.statsElevationGroup.setVisibility(showElevation ? View.VISIBLE : View.GONE);
Float elevationGain_m = trackStatistics != null ? trackStatistics.getTotalElevationGain() : null;
Float elevationLoss_m = trackStatistics != null ? trackStatistics.getTotalElevationLoss() : null;
Pair<String, String> parts = StringUtils.formatElevation(getContext(), elevationGain_m, metricUnits);
Pair<String, String> parts;
parts = StringUtils.formatElevation(getContext(), elevationGain_m, metricUnits);
viewBinding.statsElevationGainValue.setText(parts.first);
viewBinding.statsElevationGainUnit.setText(parts.second);
parts = StringUtils.formatElevation(getContext(), elevationLoss_m, metricUnits);
viewBinding.statsElevationLossValue.setText(parts.first);
viewBinding.statsElevationLossUnit.setText(parts.second);
}
}
}
@@ -261,7 +261,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
/**
* Tries to fetch most recent {@link SensorDataSet} from {@link de.dennisguse.opentracks.services.TrackRecordingService}.
* Also sets elevation gain.
* Also sets elevation gain and loss.
*/
private void updateSensorDataUI() {
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
@@ -284,13 +284,14 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
sensorsAdapter.swapData(sensorDataList);
setSpeedSensorData(sensorDataSet);
}
//TODO Check if we can distribute the total elevation gain and loss via trackStatistics instead of doing some computation in the UI layer.
setTotalElevationGain(trackRecordingService.getElevationGain_m());
setTotalElevationLoss(trackRecordingService.getElevationLoss_m());
}
}
// Set elevation gain
private void setTotalElevationGain(Float elevationGain_m) {
//TODO Check if we can distribute the total elevation gain via trackStatistics instead of doing some computation in the UI layer.
boolean metricUnits = PreferencesUtils.isMetricUnits(getContext());
Float totalElevationGain = elevationGain_m;
@@ -308,6 +309,25 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
viewBinding.statsElevationGainUnit.setText(parts.second);
}
// Set elevation loss
private void setTotalElevationLoss(Float elevationLoss_m) {
boolean metricUnits = PreferencesUtils.isMetricUnits(getContext());
Float totalElevationLoss = elevationLoss_m;
if (lastTrackStatistics != null && lastTrackStatistics.hasTotalElevationLoss()) {
if (elevationLoss_m == null) {
totalElevationLoss = lastTrackStatistics.getTotalElevationLoss();
} else {
totalElevationLoss += lastTrackStatistics.getTotalElevationLoss();
}
}
Pair<String, String> parts = StringUtils.formatElevation(getContext(), totalElevationLoss, metricUnits);
viewBinding.statsElevationLossValue.setText(parts.first);
viewBinding.statsElevationLossUnit.setText(parts.second);
}
private void setSpeedSensorData(SensorDataSet sensorDataSet) {
if (sensorDataSet != null && sensorDataSet.getCyclingSpeed() != null) {
SensorDataCycling.Speed data = sensorDataSet.getCyclingSpeed();
@@ -378,7 +398,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
viewBinding.statsMovingSpeedUnit.setText(parts.second);
}
// Set elevation (gain)
// Set elevation gain and loss
{
// Make elevation visible?
boolean showElevation = PreferencesUtils.isShowStatsElevation(getContext());
@@ -51,6 +51,7 @@ public class KmlTrackWriter implements TrackWriter {
public static final String EXTENDED_DATA_TYPE_HEART_RATE = "heart_rate";
public static final String EXTENDED_DATA_TYPE_POWER = "power";
public static final String EXTENDED_DATA_TYPE_ELEVATION_GAIN = "elevation_gain";
public static final String EXTENDED_DATA_TYPE_ELEVATION_LOSS = "elevation_loss";
private static final String MARKER_ICON = "http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png";
private static final String START_ICON = "http://maps.google.com/mapfiles/kml/paddle/grn-circle.png";
@@ -70,6 +71,7 @@ public class KmlTrackWriter implements TrackWriter {
private final List<Float> cadenceList = new ArrayList<>();
private final List<Float> heartRateList = new ArrayList<>();
private final List<Float> elevationGainList = new ArrayList<>();
private final List<Float> elevationLossList = new ArrayList<>();
private TrackPoint startTrackPoint;
@@ -262,6 +264,9 @@ public class KmlTrackWriter implements TrackWriter {
if (elevationGainList.size() > 0) {
writeSimpleArrayData(elevationGainList, EXTENDED_DATA_TYPE_ELEVATION_GAIN);
}
if (elevationLossList.size() > 0) {
writeSimpleArrayData(elevationLossList, EXTENDED_DATA_TYPE_ELEVATION_LOSS);
}
}
printWriter.println("</SchemaData>");
printWriter.println("</ExtendedData>");
@@ -295,6 +300,9 @@ public class KmlTrackWriter implements TrackWriter {
if (trackPoint.hasElevationGain()) {
elevationGainList.add(trackPoint.getElevationGain());
}
if (trackPoint.hasElevationLoss()) {
elevationLossList.add(trackPoint.getElevationLoss());
}
}
}
}
@@ -69,6 +69,7 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
private final ArrayList<Float> heartRateList = new ArrayList<>();
private final ArrayList<Float> powerList = new ArrayList<>();
private final ArrayList<Float> elevationGainList = new ArrayList<>();
private final ArrayList<Float> elevationLossList = new ArrayList<>();
public KmlFileTrackImporter(Context context) {
this(context, new ContentProviderUtils(context));
@@ -217,6 +218,7 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
cadenceList.clear();
powerList.clear();
elevationGainList.clear();
elevationLossList.clear();
}
/**
@@ -242,6 +244,9 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
if (i < elevationGainList.size()) {
trackPoint.setElevationGain(elevationGainList.get(i));
}
if (i < elevationLossList.size()) {
trackPoint.setElevationLoss(elevationLossList.get(i));
}
insertTrackPoint(trackPoint);
}
@@ -311,6 +316,9 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
case KmlTrackWriter.EXTENDED_DATA_TYPE_ELEVATION_GAIN:
elevationGainList.add(value);
break;
case KmlTrackWriter.EXTENDED_DATA_TYPE_ELEVATION_LOSS:
elevationLossList.add(value);
break;
default:
Log.w(TAG, "Data from extended data " + extendedDataType + " is not (yet) supported.");
}
@@ -665,6 +665,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
try {
if (elevationSumManager != null) {
trackPoint.setElevationGain(elevationSumManager.getElevationGain_m());
trackPoint.setElevationLoss(elevationSumManager.getElevationLoss_m());
elevationSumManager.reset();
}
contentProviderUtils.insertTrackPoint(trackPoint, track.getId());
@@ -680,7 +681,6 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
voiceExecutor.update();
}
/**
* Updates the recording track time.
*
@@ -718,6 +718,17 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
return elevationSumManager.getElevationGain_m();
}
/**
* Returns the relative elevation loss (since last trackpoint).
*/
Float getElevationLoss_m() {
if (elevationSumManager == null || !elevationSumManager.isConnected()) {
return null;
}
return elevationSumManager.getElevationLoss_m();
}
private void showNotification(boolean isGpsStarted) {
if (isRecording()) {
Intent intent = IntentUtils.newIntent(this, TrackRecordingActivity.class)
@@ -104,6 +104,11 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco
return trackRecordingService.getElevationGain_m();
}
@Override
public Float getElevationLoss_m() {
return trackRecordingService.getElevationLoss_m();
}
@VisibleForTesting
@Override
public void setRemoteSensorManager(BluetoothRemoteSensorManager remoteSensorManager) {
@@ -78,6 +78,13 @@ public interface TrackRecordingServiceInterface {
*/
Float getElevationGain_m();
/**
* Gets the current elevation loss.
*
* @return elevation loss in m or null.
*/
Float getElevationLoss_m();
@VisibleForTesting
void setRemoteSensorManager(BluetoothRemoteSensorManager remoteSensorManager);
@@ -112,6 +112,6 @@ public class ElevationSumManager implements SensorEventListener {
lastSeenSensorValue_hPa = value_hPa;
Log.v(TAG, "elevation gain: " + elevationGain_m);
Log.v(TAG, "elevation gain: " + elevationGain_m + ", elevation loss: " + elevationLoss_m);
}
}
@@ -45,6 +45,8 @@ public class TrackStatistics {
private double maxSpeed_mps;
// The total elevation gained (meters).
private Float totalElevationGain_m = null;
// The total elevation lost (meters).
private Float totalElevationLoss_m = null;
public TrackStatistics() {
}
@@ -63,6 +65,7 @@ public class TrackStatistics {
maxSpeed_mps = other.maxSpeed_mps;
elevationExtremities.set(other.elevationExtremities.getMin(), other.elevationExtremities.getMax());
totalElevationGain_m = other.totalElevationGain_m;
totalElevationLoss_m = other.totalElevationLoss_m;
}
/**
@@ -91,6 +94,15 @@ public class TrackStatistics {
totalElevationGain_m += other.totalElevationGain_m;
}
}
if (totalElevationLoss_m == null) {
if (other.totalElevationLoss_m != null) {
totalElevationLoss_m = other.totalElevationLoss_m;
}
} else {
if (other.totalElevationLoss_m != null) {
totalElevationLoss_m += other.totalElevationLoss_m;
}
}
}
/**
@@ -257,6 +269,26 @@ public class TrackStatistics {
totalElevationGain_m += gain_m;
}
public boolean hasTotalElevationLoss() {
return totalElevationLoss_m != null;
}
public @Nullable
Float getTotalElevationLoss() {
return totalElevationLoss_m;
}
public void setTotalElevationLoss(float totalElevationLoss_m) {
this.totalElevationLoss_m = totalElevationLoss_m;
}
public void addTotalElevationLoss(float loss_m) {
if (totalElevationLoss_m == null) {
totalElevationLoss_m = 0f;
}
totalElevationLoss_m += loss_m;
}
@NonNull
@Override
public String toString() {
@@ -264,6 +296,7 @@ public class TrackStatistics {
+ "; Total Distance: " + getTotalDistance() + "; Total Time: " + getTotalTime()
+ "; Moving Time: " + getMovingTime() + "; Max Speed: " + getMaxSpeed()
+ "; Min Elevation: " + getMinElevation() + "; Max Elevation: " + getMaxElevation()
+ "; Elevation Gain: " + getTotalElevationGain() + "}";
+ "; Elevation Gain: " + getTotalElevationGain()
+ "; Elevation Loss: " + getTotalElevationLoss() + "}";
}
}
@@ -145,6 +145,12 @@ public class TrackStatisticsUpdater {
Log.d(TAG, "elevation gain: " + trackPoint.getElevationGain());
}
//Get elevation loss
if (trackPoint.hasElevationLoss()) {
currentSegment.addTotalElevationLoss(trackPoint.getElevationLoss());
Log.d(TAG, "elevation loss: " + trackPoint.getElevationLoss());
}
if (lastTrackPoint == null || lastMovingTrackPoint == null) {
lastTrackPoint = trackPoint;
lastMovingTrackPoint = trackPoint;
@@ -36,7 +36,7 @@ public class PressureSensorUtils {
}
public float getElevationLoss_m() {
return elevationChange_m < 0 ? elevationChange_m : 0;
return elevationChange_m < 0 ? -1 * elevationChange_m : 0;
}
}
@@ -65,7 +65,7 @@ public class PressureSensorUtils {
// Limit elevation change by ELEVATION_CHANGE_DIFF and computes pressure value accordingly.
ElevationChange elevationChange = new ElevationChange(currentSensorValue_hPa, elevationChange_m);
if (elevationChange.getElevationGain_m() > 0) {
if (elevationChange.getElevationChange_m() > 0) {
return new ElevationChange(getBarometricPressure(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, lastSensorValue_m + ELEVATION_CHANGE_DIFF_M), ELEVATION_CHANGE_DIFF_M);
} else {
return new ElevationChange(getBarometricPressure(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, lastSensorValue_m - ELEVATION_CHANGE_DIFF_M), -1 * ELEVATION_CHANGE_DIFF_M);
@@ -25,6 +25,7 @@ public class IntervalStatistics {
Interval interval = new Interval();
interval.gain_m += trackPoints.get(0).hasElevationGain() ? trackPoints.get(0).getElevationGain() : 0;
interval.loss_m += trackPoints.get(0).hasElevationLoss() ? trackPoints.get(0).getElevationLoss() : 0;
for (int i = 1; i < trackPoints.size(); i++) {
TrackPoint prevTrackPoint = trackPoints.get(i - 1);
TrackPoint trackPoint = trackPoints.get(i);
@@ -33,6 +34,7 @@ public class IntervalStatistics {
interval.distance_m += prevTrackPoint.distanceTo(trackPoint);
interval.time_ms += trackPoint.getTime() - prevTrackPoint.getTime();
interval.gain_m += trackPoint.hasElevationGain() ? trackPoint.getElevationGain() : 0;
interval.loss_m += trackPoint.hasElevationLoss() ? trackPoint.getElevationLoss() : 0;
if (interval.distance_m >= distanceInterval_m) {
float adjustFactor = distanceInterval_m / interval.distance_m;
@@ -80,6 +82,7 @@ public class IntervalStatistics {
private float distance_m = 0f;
private float time_ms = 0f;
private float gain_m = 0f;
private float loss_m = 0f;
public Interval() {}
@@ -87,12 +90,14 @@ public class IntervalStatistics {
this.distance_m = distance_m;
this.time_ms = time_ms;
this.gain_m = 0f;
this.loss_m = 0f;
}
public Interval(Interval i) {
distance_m = i.distance_m;
time_ms = i.time_ms;
gain_m = i.gain_m;
loss_m = i.loss_m;
}
public float getDistance_m() {
@@ -117,5 +122,9 @@ public class IntervalStatistics {
public float getGain_m() {
return gain_m;
}
public float getLoss_m() {
return loss_m;
}
}
}
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M7,10l5,5 5,-5z"/>
</vector>
+1 -1
View File
@@ -46,7 +46,7 @@
<TextView
android:id="@+id/interval_elevation"
style="@style/IntervalLabel"
android:text="@string/stats_gain" />
android:text="@string/stats_elevation" />
</LinearLayout>
@@ -4,28 +4,48 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:orientation="horizontal">
<TextView
android:id="@+id/interval_item_distance"
style="@style/TextMedium"
style="@style/TextMediumPrimary"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_gravity="center_vertical"
tools:text="1 km" />
<TextView
android:id="@+id/interval_item_rate"
style="@style/TextMedium"
style="@style/TextMediumPrimary"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_gravity="center_vertical"
tools:text="15 km/h" />
<TextView
android:id="@+id/interval_item_gain"
style="@style/TextMedium"
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:drawableStartCompat="@drawable/ic_arrow_drop_up_24"
tools:text="100 m" />
android:orientation="vertical">
<TextView
android:id="@+id/interval_item_gain"
style="@style/TextSmall"
android:layout_width="match_parent"
android:layout_weight="1"
app:drawableStartCompat="@drawable/ic_arrow_drop_up_24"
tools:text="100 m" />
<TextView
android:id="@+id/interval_item_loss"
style="@style/TextSmall"
android:layout_width="match_parent"
android:layout_weight="1"
app:drawableStartCompat="@drawable/ic_arrow_drop_down_24"
tools:text="100 m" />
</LinearLayout>
</LinearLayout>
+33 -6
View File
@@ -234,20 +234,20 @@
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintTop_toBottomOf="@+id/stats_speed_barrier" />
<!-- Elevation gain -->
<!-- Elevation gain and loss -->
<androidx.constraintlayout.widget.Group
android:id="@+id/stats_elevation_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="stats_elevation_horizontal_line,stats_elevation_gain_label,stats_elevation_gain_value,stats_elevation_gain_unit" />
app:constraint_referenced_ids="stats_elevation_horizontal_line,stats_elevation_gain_label,stats_elevation_gain_value,stats_elevation_gain_unit,stats_elevation_loss_label,stats_elevation_loss_value,stats_elevation_loss_unit" />
<TextView
android:id="@+id/stats_elevation_gain_label"
style="@style/StatsSmallLabel"
android:text="@string/stats_gain"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintTop_toBottomOf="@id/stats_elevation_horizontal_line" />
<TextView
@@ -255,7 +255,7 @@
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/stats_elevation_gain_unit"
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_gain_label"
tools:text="100" />
@@ -265,6 +265,33 @@
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@+id/stats_elevation_gain_value"
app:layout_constraintStart_toEndOf="@+id/stats_elevation_gain_value"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
tools:text="m" />
<TextView
android:id="@+id/stats_elevation_loss_label"
style="@style/StatsSmallLabel"
android:text="@string/stats_loss"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_elevation_horizontal_line" />
<TextView
android:id="@+id/stats_elevation_loss_value"
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/stats_elevation_loss_unit"
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_loss_label"
tools:text="100" />
<TextView
android:id="@+id/stats_elevation_loss_unit"
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@+id/stats_elevation_loss_value"
app:layout_constraintStart_toEndOf="@+id/stats_elevation_loss_value"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
tools:text="m" />
@@ -274,7 +301,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="stats_elevation_gain_value" />
app:constraint_referenced_ids="stats_elevation_gain_value,stats_elevation_loss_value" />
<!-- Horizontal line -->
<View
+130 -102
View File
@@ -36,8 +36,8 @@
style="@style/StatsLargeLabel"
android:text="@string/stats_distance"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline2"
app:layout_constraintTop_toTopOf="parent" />
<TextView
@@ -45,17 +45,17 @@
style="@style/StatsLargeValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/stats_distance_unit"
app:layout_constraintTop_toBottomOf="@+id/stats_distance_label"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/stats_distance_unit"
app:layout_constraintTop_toBottomOf="@id/stats_distance_label"
tools:text="100" />
<TextView
android:id="@+id/stats_distance_unit"
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@+id/stats_distance_value"
app:layout_constraintStart_toEndOf="@+id/stats_distance_value"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintBottom_toBottomOf="@id/stats_distance_value"
app:layout_constraintStart_toEndOf="@id/stats_distance_value"
app:layout_constraintEnd_toStartOf="@id/guideline2"
tools:text="km" />
<!-- Activity Type -->
@@ -64,8 +64,8 @@
style="@style/StatsLargeLabel"
android:text="@string/track_edit_activity_type_hint"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
@@ -73,10 +73,10 @@
style="@style/StatsLargeValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintBottom_toBottomOf="@+id/stats_distance_value"
app:layout_constraintTop_toTopOf="@+id/stats_distance_value"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintBottom_toBottomOf="@id/stats_distance_value"
app:layout_constraintTop_toTopOf="@id/stats_distance_value"
app:tint="?android:textColorPrimary" />
<!-- Total time -->
@@ -85,16 +85,16 @@
style="@style/StatsLargeLabel"
android:text="@string/stats_total_time"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintTop_toBottomOf="@+id/stats_distance_value" />
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline2"
app:layout_constraintTop_toBottomOf="@id/stats_distance_value" />
<TextView
android:id="@+id/stats_total_time_value"
style="@style/StatsLargeValue"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintTop_toBottomOf="@+id/stats_total_time_label"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline2"
app:layout_constraintTop_toBottomOf="@id/stats_total_time_label"
tools:text="00:00:00" />
<!-- Moving time -->
@@ -103,18 +103,18 @@
style="@style/StatsLargeLabel"
android:text="@string/stats_moving_time"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintTop_toTopOf="@+id/stats_total_time_label"
app:layout_constraintBottom_toBottomOf="@+id/stats_total_time_label" />
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toTopOf="@id/stats_total_time_label"
app:layout_constraintBottom_toBottomOf="@id/stats_total_time_label" />
<TextView
android:id="@+id/stats_moving_time_value"
style="@style/StatsLargeValue"
android:value="@string/value_unknown"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintTop_toBottomOf="@+id/stats_moving_time_label"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_moving_time_label"
tools:text="00:00:00" />
<!-- Barrier -->
@@ -130,17 +130,17 @@
android:id="@+id/stats_speed_horizontal_line"
style="@style/StatsHorizontalLine"
android:layout_marginBottom="8dp"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintTop_toBottomOf="@+id/stats_time_barrier" />
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_time_barrier" />
<!-- Speed/pace -->
<TextView
android:id="@+id/stats_speed_label"
style="@style/StatsSmallLabel"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline2"
app:layout_constraintTop_toBottomOf="@id/stats_speed_horizontal_line"
tools:text="Speed" />
@@ -149,17 +149,17 @@
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/stats_speed_unit"
app:layout_constraintTop_toBottomOf="@+id/stats_speed_label"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/stats_speed_unit"
app:layout_constraintTop_toBottomOf="@id/stats_speed_label"
tools:text="30.00" />
<TextView
android:id="@+id/stats_speed_unit"
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@+id/stats_speed_value"
app:layout_constraintStart_toEndOf="@+id/stats_speed_value"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintBottom_toBottomOf="@id/stats_speed_value"
app:layout_constraintStart_toEndOf="@id/stats_speed_value"
app:layout_constraintEnd_toStartOf="@id/guideline2"
tools:text="km/h" />
<!-- Average speed/pace -->
@@ -167,8 +167,8 @@
android:id="@+id/stats_average_speed_label"
style="@style/StatsSmallLabel"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_speed_horizontal_line"
tools:text="Avg. Speed" />
@@ -177,17 +177,17 @@
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/stats_average_speed_unit"
app:layout_constraintTop_toBottomOf="@+id/stats_average_speed_label"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/stats_average_speed_unit"
app:layout_constraintTop_toBottomOf="@id/stats_average_speed_label"
tools:text="30.00" />
<TextView
android:id="@+id/stats_average_speed_unit"
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@+id/stats_average_speed_value"
app:layout_constraintStart_toEndOf="@+id/stats_average_speed_value"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintBottom_toBottomOf="@id/stats_average_speed_value"
app:layout_constraintStart_toEndOf="@id/stats_average_speed_value"
app:layout_constraintEnd_toStartOf="@id/guideline3"
tools:text="km/h" />
<!-- Speed max -->
@@ -195,8 +195,8 @@
android:id="@+id/stats_max_speed_label"
style="@style/StatsSmallLabel"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline2"
app:layout_constraintTop_toBottomOf="@id/stats_average_speed_value"
tools:text="Max. Speed" />
@@ -205,17 +205,17 @@
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/stats_max_speed_unit"
app:layout_constraintTop_toBottomOf="@+id/stats_max_speed_label"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/stats_max_speed_unit"
app:layout_constraintTop_toBottomOf="@id/stats_max_speed_label"
tools:text="30.00" />
<TextView
android:id="@+id/stats_max_speed_unit"
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@+id/stats_max_speed_value"
app:layout_constraintStart_toEndOf="@+id/stats_max_speed_value"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintBottom_toBottomOf="@id/stats_max_speed_value"
app:layout_constraintStart_toEndOf="@id/stats_max_speed_value"
app:layout_constraintEnd_toStartOf="@id/guideline2"
tools:text="km/h" />
<!-- Moving speed max -->
@@ -223,8 +223,8 @@
android:id="@+id/stats_moving_speed_label"
style="@style/StatsSmallLabel"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_average_speed_value"
tools:text="Max. Moving Speed" />
@@ -233,17 +233,17 @@
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/stats_moving_speed_unit"
app:layout_constraintTop_toBottomOf="@+id/stats_moving_speed_label"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/stats_moving_speed_unit"
app:layout_constraintTop_toBottomOf="@id/stats_moving_speed_label"
tools:text="30.00" />
<TextView
android:id="@+id/stats_moving_speed_unit"
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@+id/stats_moving_speed_value"
app:layout_constraintStart_toEndOf="@+id/stats_moving_speed_value"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintBottom_toBottomOf="@id/stats_moving_speed_value"
app:layout_constraintStart_toEndOf="@id/stats_moving_speed_value"
app:layout_constraintEnd_toStartOf="@id/guideline3"
tools:text="km/h" />
<!-- Barrier -->
@@ -259,16 +259,16 @@
android:id="@+id/stats_elevation_horizontal_line"
style="@style/StatsHorizontalLine"
android:layout_marginBottom="8dp"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintTop_toBottomOf="@+id/stats_speed_barrier" />
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_speed_barrier" />
<!-- Elevation -->
<androidx.constraintlayout.widget.Group
android:id="@+id/stats_elevation_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="stats_elevation_horizontal_line,stats_elevation_current_label,stats_elevation_current_value,stats_elevation_current_unit,stats_elevation_gain_label,stats_elevation_gain_value,stats_elevation_gain_unit" />
app:constraint_referenced_ids="stats_elevation_horizontal_line,stats_elevation_current_label,stats_elevation_current_value,stats_elevation_current_unit,stats_elevation_gain_label,stats_elevation_gain_value,stats_elevation_gain_unit,stats_elevation_loss_label,stats_elevation_loss_value,stats_elevation_loss_unit" />
<!-- Elevation -->
<TextView
@@ -276,8 +276,8 @@
style="@style/StatsSmallLabel"
android:text="@string/stats_elevation"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline2"
app:layout_constraintTop_toBottomOf="@id/stats_elevation_horizontal_line" />
<TextView
@@ -285,27 +285,27 @@
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/stats_elevation_current_unit"
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_current_label"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/stats_elevation_current_unit"
app:layout_constraintTop_toBottomOf="@id/stats_elevation_current_label"
tools:text="100" />
<TextView
android:id="@+id/stats_elevation_current_unit"
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@+id/stats_elevation_current_value"
app:layout_constraintStart_toEndOf="@+id/stats_elevation_current_value"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintBottom_toBottomOf="@id/stats_elevation_current_value"
app:layout_constraintStart_toEndOf="@id/stats_elevation_current_value"
app:layout_constraintEnd_toStartOf="@id/guideline2"
tools:text="m" />
<!-- Current elevation -->
<!-- Elevation gain -->
<TextView
android:id="@+id/stats_elevation_gain_label"
style="@style/StatsSmallLabel"
android:text="@string/stats_gain"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_elevation_horizontal_line" />
<TextView
@@ -313,17 +313,45 @@
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/stats_elevation_gain_unit"
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_gain_label"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/stats_elevation_gain_unit"
app:layout_constraintTop_toBottomOf="@id/stats_elevation_gain_label"
tools:text="100" />
<TextView
android:id="@+id/stats_elevation_gain_unit"
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@+id/stats_elevation_gain_value"
app:layout_constraintStart_toEndOf="@+id/stats_elevation_gain_value"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintBottom_toBottomOf="@id/stats_elevation_gain_value"
app:layout_constraintStart_toEndOf="@id/stats_elevation_gain_value"
app:layout_constraintEnd_toStartOf="@id/guideline3"
tools:text="m" />
<!-- Elevation loss -->
<TextView
android:id="@+id/stats_elevation_loss_label"
style="@style/StatsSmallLabel"
android:text="@string/stats_loss"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_elevation_gain_value" />
<TextView
android:id="@+id/stats_elevation_loss_value"
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/stats_elevation_loss_unit"
app:layout_constraintTop_toBottomOf="@id/stats_elevation_loss_label"
tools:text="100" />
<TextView
android:id="@+id/stats_elevation_loss_unit"
style="@style/StatsUnit"
app:layout_constraintBottom_toBottomOf="@id/stats_elevation_loss_value"
app:layout_constraintStart_toEndOf="@id/stats_elevation_loss_value"
app:layout_constraintEnd_toStartOf="@id/guideline3"
tools:text="m" />
<!-- Coordinate group -->
@@ -339,16 +367,16 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="stats_elevation_current_value,stats_elevation_gain_value" />
app:constraint_referenced_ids="stats_elevation_current_value,stats_elevation_gain_value,stats_elevation_loss_value" />
<!-- Horizontal line -->
<View
android:id="@+id/stats_coordinate_horizontal_line"
style="@style/StatsHorizontalLine"
android:layout_marginBottom="8dp"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_barrier" />
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_elevation_barrier" />
<!-- Latitude -->
<TextView
@@ -356,16 +384,16 @@
style="@style/StatsSmallLabel"
android:text="@string/stats_latitude"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline2"
app:layout_constraintTop_toBottomOf="@id/stats_coordinate_horizontal_line" />
<TextView
android:id="@+id/stats_latitude_value"
style="@style/StatsSmallValue"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintTop_toBottomOf="@+id/stats_latitude_label"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline2"
app:layout_constraintTop_toBottomOf="@id/stats_latitude_label"
tools:text="0.834937848" />
<!-- Longitude -->
@@ -374,17 +402,17 @@
style="@style/StatsSmallLabel"
android:text="@string/stats_longitude"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_coordinate_horizontal_line" />
<TextView
android:id="@+id/stats_longitude_value"
style="@style/StatsSmallValue"
android:value="@string/value_unknown"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintTop_toBottomOf="@+id/stats_longitude_label"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_longitude_label"
tools:text="0.834937848" />
<!-- Barrier -->
@@ -400,17 +428,17 @@
android:id="@+id/stats_sensor_horizontal_line"
style="@style/StatsHorizontalLine"
android:layout_marginBottom="8dp"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintTop_toBottomOf="@+id/stats_location_barrier" />
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_location_barrier" />
<!-- Sensors data -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/stats_sensors_recycler_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@id/guideline3"
app:layout_constraintTop_toBottomOf="@id/stats_sensor_horizontal_line" />
</androidx.constraintlayout.widget.ConstraintLayout>
+2
View File
@@ -176,6 +176,7 @@ limitations under the License.
<string name="description_average_pace_in_minute">Average pace: %1$s min/km (%2$s min/mi)</string>
<string name="description_average_speed">Average speed: %1$.2f km/h (%2$.1f mi/h)</string>
<string name="description_elevation_gain">Elevation gain: %1$d m (%2$d ft)</string>
<string name="description_elevation_loss">Elevation loss: %1$d m (%2$d ft)</string>
<string name="description_elevation_imperial">Elevation (ft)</string>
<string name="description_elevation_metric">Elevation (m)</string>
<string name="description_fastest_pace_in_minute">Fastest pace: %1$s min/km (%2$s min/mi)</string>
@@ -447,6 +448,7 @@ limitations under the License.
<string name="stats_elevation">Elevation</string>
<string name="stats_fastest_pace">Fastest pace</string>
<string name="stats_gain">Gain</string>
<string name="stats_loss">Loss</string>
<string name="stats_grade">Grade</string>
<string name="stats_latitude">Latitude</string>
<string name="stats_longitude">Longitude</string>