Elevation now visible in statistics sheet - works for new tracks only (see #28)
This commit is contained in:
		
							parent
							
								
									ed0d53e336
								
							
						
					
					
						commit
						03d5513df6
					
				
					 13 changed files with 514 additions and 50 deletions
				
			
		|  | @ -27,6 +27,7 @@ import android.os.Bundle; | |||
| import android.support.annotation.NonNull; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.support.constraint.ConstraintLayout; | ||||
| import android.support.constraint.Group; | ||||
| import android.support.design.widget.BottomSheetBehavior; | ||||
| import android.support.v4.app.DialogFragment; | ||||
| import android.support.v4.app.Fragment; | ||||
|  | @ -41,6 +42,7 @@ import android.widget.ImageButton; | |||
| import android.widget.LinearLayout; | ||||
| import android.widget.Spinner; | ||||
| import android.widget.TextView; | ||||
| import android.widget.Toast; | ||||
| 
 | ||||
| import org.osmdroid.api.IMapController; | ||||
| import org.osmdroid.tileprovider.tilesource.TileSourceFactory; | ||||
|  | @ -89,6 +91,11 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O | |||
|     private TextView mDurationView; | ||||
|     private TextView mRecordingStartView; | ||||
|     private TextView mRecordingStopView; | ||||
|     private TextView mMaxAltitudeView; | ||||
|     private TextView mMinAltitudeView; | ||||
|     private TextView mPositiveElevationView; | ||||
|     private TextView mNegativeElevationView; | ||||
|     private Group mElevationDataViews; | ||||
|     private BottomSheetBehavior mStatisticsSheetBehavior; | ||||
|     private int mCurrentTrack; | ||||
|     private Track mTrack; | ||||
|  | @ -204,6 +211,14 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O | |||
|         mDurationView = (TextView) mRootView.findViewById(R.id.statistics_data_duration); | ||||
|         mRecordingStartView = (TextView) mRootView.findViewById(R.id.statistics_data_recording_start); | ||||
|         mRecordingStopView = (TextView) mRootView.findViewById(R.id.statistics_data_recording_stop); | ||||
|         mMaxAltitudeView = (TextView) mRootView.findViewById(R.id.statistics_data_max_altitude); | ||||
|         mMinAltitudeView = (TextView) mRootView.findViewById(R.id.statistics_data_min_altitude); | ||||
|         mPositiveElevationView = (TextView) mRootView.findViewById(R.id.statistics_data_positive_elevation); | ||||
|         mNegativeElevationView = (TextView) mRootView.findViewById(R.id.statistics_data_negative_elevation); | ||||
|         mElevationDataViews = (Group) mRootView.findViewById(R.id.elevation_data); | ||||
| 
 | ||||
|         // attach listners for taps on elevation views | ||||
|         attachTapListeners(); | ||||
| 
 | ||||
|         // display map and statistics | ||||
|         if (savedInstanceState != null) { | ||||
|  | @ -359,9 +374,23 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O | |||
|             mDurationView.setText(mTrack.getTrackDurationString()); | ||||
|             mRecordingStartView.setText(recordingStart); | ||||
|             mRecordingStopView.setText(recordingStop); | ||||
|             mPositiveElevationView.setText(mTrack.getPositiveElevationString()); | ||||
|             mNegativeElevationView.setText(mTrack.getNegativeElevationString()); | ||||
|             mMaxAltitudeView.setText(mTrack.getMaxAltitudeString()); | ||||
|             mMinAltitudeView.setText(mTrack.getMinAltitudeString()); | ||||
| 
 | ||||
|             // show/hide elevation views depending on file format version | ||||
|             if (mTrack.getTrackFormatVersion() > 1 || mTrack.getMinAltitude() > 0) { | ||||
|                 // show elevation views | ||||
|                 mElevationDataViews.setVisibility(View.VISIBLE); | ||||
|             } else { | ||||
|                 // hide elevation views | ||||
|                 mElevationDataViews.setVisibility(View.GONE); | ||||
|             } | ||||
| 
 | ||||
|             // draw track on map | ||||
|             drawTrackOverlay(mTrack); | ||||
| 
 | ||||
|         } else { | ||||
|             position = new GeoPoint(DEFAULT_LATITUDE, DEFAULT_LONGITUDE); | ||||
|         } | ||||
|  | @ -531,6 +560,21 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Add tap listners to elevation data views */ | ||||
|     private void attachTapListeners() { | ||||
|         int referencedIds[] = mElevationDataViews.getReferencedIds(); | ||||
|         for (int id : referencedIds) { | ||||
|             mRootView.findViewById(id).setOnClickListener(new View.OnClickListener() { | ||||
|                 @Override | ||||
|                 public void onClick(View view) { | ||||
|                     // inform user about possible issues with altitude measurements | ||||
|                     Toast.makeText(mActivity, R.string.toast_message_elevation_info, Toast.LENGTH_LONG).show(); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Inner class: Loads track from external storage using AsyncTask | ||||
|      */ | ||||
|  | @ -559,10 +603,6 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O | |||
|         protected void onPostExecute(Void aVoid) { | ||||
|             super.onPostExecute(aVoid); | ||||
| 
 | ||||
|             // todo remove | ||||
|             StorageHelper storageHelper = new StorageHelper(mActivity); | ||||
|             storageHelper.calculateTrackElevation(mTrack); | ||||
| 
 | ||||
|             // display track on map | ||||
|             displayTrack(); | ||||
|         } | ||||
|  |  | |||
|  | @ -49,6 +49,32 @@ public class Track implements TrackbookKeys, Parcelable { | |||
|     private float mStepCount; | ||||
|     private final Date mRecordingStart; | ||||
|     private Date mRecordingStop; | ||||
|     private double mMaxAltitude; | ||||
|     private double mMinAltitude; | ||||
|     private double mPositiveElevation; | ||||
|     private double mNegativeElevation; | ||||
| 
 | ||||
| 
 | ||||
|     /* Generic Constructor */ | ||||
|     public Track(int trackFormatVersion, List<WayPoint> wayPoints, float trackLength, long duration, float stepCount, Date recordingStart, Date recordingStop, double maxAltitude, double minAltitude, double positiveElevation, double negativeElevation) { | ||||
|         mTrackFormatVersion = trackFormatVersion; | ||||
|         mWayPoints = wayPoints; | ||||
|         mTrackLength = trackLength; | ||||
|         mDuration = duration; | ||||
|         mStepCount = stepCount; | ||||
|         mRecordingStart = recordingStart; | ||||
|         mRecordingStop = recordingStop; | ||||
|         mMaxAltitude = maxAltitude; | ||||
|         mMinAltitude = minAltitude; | ||||
|         mPositiveElevation = positiveElevation; | ||||
|         mNegativeElevation = negativeElevation; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Copy Constructor */ | ||||
|     public Track(Track track) { | ||||
|         this(track.getTrackFormatVersion(), track.getWayPoints(), track.getTrackLength(), track.getTrackDuration(), track.getStepCount(), track.getRecordingStart(), track.getRecordingStop(), track.getMaxAltitude(), track.getMinAltitude(), track.getPositiveElevation(), track.getNegativeElevation()); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Constructor */ | ||||
|  | @ -60,6 +86,10 @@ public class Track implements TrackbookKeys, Parcelable { | |||
|         mStepCount = 0f; | ||||
|         mRecordingStart = GregorianCalendar.getInstance().getTime(); | ||||
|         mRecordingStop = mRecordingStart; | ||||
|         mMaxAltitude = 0f; | ||||
|         mMinAltitude = 0f; | ||||
|         mPositiveElevation = 0f; | ||||
|         mNegativeElevation = 0f; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -72,6 +102,10 @@ public class Track implements TrackbookKeys, Parcelable { | |||
|         mStepCount = in.readFloat(); | ||||
|         mRecordingStart = new Date(in.readLong()); | ||||
|         mRecordingStop = new Date(in.readLong()); | ||||
|         mMaxAltitude = in.readDouble(); | ||||
|         mMinAltitude = in.readDouble(); | ||||
|         mPositiveElevation = in.readDouble(); | ||||
|         mNegativeElevation = in.readDouble(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -136,6 +170,36 @@ public class Track implements TrackbookKeys, Parcelable { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Setter for maximum altitude of recording */ | ||||
|     public void setMaxAltitude(double maxAltitude) { | ||||
|         mMaxAltitude = maxAltitude; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Setter for lowest altitude of recording */ | ||||
|     public void setMinAltitude(double minAltitude) { | ||||
|         mMinAltitude = minAltitude; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Setter for positive elevation of recording (cumulative altitude difference) */ | ||||
|     public void setPositiveElevation(double positiveElevation) { | ||||
|         mPositiveElevation = positiveElevation; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Setter for negative elevation of recording (cumulative altitude difference) */ | ||||
|     public void setNegativeElevation(double megativeElevation) { | ||||
|         mNegativeElevation = megativeElevation; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for file/track fornat version */ | ||||
|     public int getTrackFormatVersion() { | ||||
|         return mTrackFormatVersion; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for mWayPoints */ | ||||
|     public List<WayPoint> getWayPoints() { | ||||
|         return mWayPoints; | ||||
|  | @ -148,6 +212,12 @@ public class Track implements TrackbookKeys, Parcelable { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for track length */ | ||||
|     public float getTrackLength() { | ||||
|         return mTrackLength; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for duration of track */ | ||||
|     public long getTrackDuration() { | ||||
|         return mDuration; | ||||
|  | @ -171,26 +241,64 @@ public class Track implements TrackbookKeys, Parcelable { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for maximum altitude of recording */ | ||||
|     public double getMaxAltitude() { | ||||
|         return mMaxAltitude; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for lowest altitude of recording */ | ||||
|     public double getMinAltitude() { | ||||
|         return mMinAltitude; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for positive elevation of recording (cumulative altitude difference) */ | ||||
|     public double getPositiveElevation() { | ||||
|         return mPositiveElevation; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for negative elevation of recording (cumulative altitude difference) */ | ||||
|     public double getNegativeElevation() { | ||||
|         return mNegativeElevation; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for string representation of maximum altitude of recording */ | ||||
|     public String getMaxAltitudeString() { | ||||
|         return convertDistanceToString(mMaxAltitude); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for string representation of lowest altitude of recording */ | ||||
|     public String getMinAltitudeString() { | ||||
|         return convertDistanceToString(mMinAltitude); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for string representation of positive elevation of recording (cumulative altitude difference) */ | ||||
|     public String getPositiveElevationString() { | ||||
|         return convertDistanceToString(mPositiveElevation); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for string representation of negative elevation of recording (cumulative altitude difference) */ | ||||
|     public String getNegativeElevationString() { | ||||
|         return convertDistanceToString(mNegativeElevation); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for string representation of track duration */ | ||||
|     public String getTrackDurationString() { | ||||
|         return LocationHelper.convertToReadableTime(mDuration, true); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Getter for string representation of track distance */ | ||||
|     public String getTrackDistanceString() { | ||||
|         float trackDistance; | ||||
|         String unit; | ||||
| 
 | ||||
|         if (getUnitSystem(Locale.getDefault()) == IMPERIAL) { | ||||
|             // get track distance and convert to feet | ||||
|             trackDistance = mWayPoints.get(mWayPoints.size()-1).getDistanceToStartingPoint() * 3.28084f; | ||||
|             unit = "ft"; | ||||
|         } else { | ||||
|             // get track distance | ||||
|             trackDistance = mWayPoints.get(mWayPoints.size()-1).getDistanceToStartingPoint(); | ||||
|             unit = "m"; | ||||
|         } | ||||
|         return String.format (Locale.ENGLISH, "%.0f", trackDistance) + unit; | ||||
|         double trackDistance = (double) mWayPoints.get(mWayPoints.size()-1).getDistanceToStartingPoint(); | ||||
|         return convertDistanceToString(trackDistance); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -216,6 +324,23 @@ public class Track implements TrackbookKeys, Parcelable { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Converts a given distance value to a readable string */ | ||||
|     private String convertDistanceToString(double distance) { | ||||
|         // check for locale and set unit system accordingly | ||||
|         String unit; | ||||
|         if (getUnitSystem(Locale.getDefault()) == IMPERIAL) { | ||||
|             // convert distance to feet | ||||
|             distance = distance * 3.28084f; | ||||
|             // set measurement unit | ||||
|             unit = "ft"; | ||||
|         } else { | ||||
|             // set measurement unit | ||||
|             unit = "m"; | ||||
|         } | ||||
|         return String.format (Locale.ENGLISH, "%.0f", distance) + unit; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Determines which unit system the device is using (metric or imperial) */ | ||||
|     private int getUnitSystem(Locale locale) { | ||||
|         // America (US), Liberia (LR), Myanmar(MM) use the imperial system | ||||
|  | @ -245,8 +370,11 @@ public class Track implements TrackbookKeys, Parcelable { | |||
|         parcel.writeFloat(mStepCount); | ||||
|         parcel.writeLong(mRecordingStart.getTime()); | ||||
|         parcel.writeLong(mRecordingStop.getTime()); | ||||
|         parcel.writeDouble(mMaxAltitude); | ||||
|         parcel.writeDouble(mMinAltitude); | ||||
|         parcel.writeDouble(mPositiveElevation); | ||||
|         parcel.writeDouble(mNegativeElevation); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
							
								
								
									
										80
									
								
								app/src/main/java/org/y20k/trackbook/core/TrackBuilder.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								app/src/main/java/org/y20k/trackbook/core/TrackBuilder.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,80 @@ | |||
| /** | ||||
|  * TrackBuilder.java | ||||
|  * Implements a builder for the Track class | ||||
|  * A TrackBuilder can build a track object depending on the version of its file format | ||||
|  * | ||||
|  * This file is part of | ||||
|  * TRACKBOOK - Movement Recorder for Android | ||||
|  * | ||||
|  * Copyright (c) 2016-18 - Y20K.org | ||||
|  * Licensed under the MIT-License | ||||
|  * http://opensource.org/licenses/MIT | ||||
|  * | ||||
|  * Trackbook uses osmdroid - OpenStreetMap-Tools for Android | ||||
|  * https://github.com/osmdroid/osmdroid | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| package org.y20k.trackbook.core; | ||||
| 
 | ||||
| import org.y20k.trackbook.helpers.LogHelper; | ||||
| 
 | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * TrackBuilder class | ||||
|  */ | ||||
| public class TrackBuilder { | ||||
| 
 | ||||
|     /* Define log tag */ | ||||
|     private static final String LOG_TAG = TrackBuilder.class.getSimpleName(); | ||||
| 
 | ||||
| 
 | ||||
|     /* Main class variables */ | ||||
|     private final int mTrackFormatVersion; | ||||
|     private final List<WayPoint> mWayPoints; | ||||
|     private float mTrackLength; | ||||
|     private long mDuration; | ||||
|     private float mStepCount; | ||||
|     private final Date mRecordingStart; | ||||
|     private Date mRecordingStop; | ||||
|     private double mMaxAltitude; | ||||
|     private double mMinAltitude; | ||||
|     private double mPositiveElevation; | ||||
|     private double mNegativeElevation; | ||||
| 
 | ||||
| 
 | ||||
|     /* Generic Constructor */ | ||||
|     public TrackBuilder(int trackFormatVersion, List<WayPoint> wayPoints, float trackLength, long duration, float stepCount, Date recordingStart, Date recordingStop, double maxAltitude, double minAltitude, double positiveElevation, double negativeElevation) { | ||||
|         mTrackFormatVersion = trackFormatVersion; | ||||
|         mWayPoints = wayPoints; | ||||
|         mTrackLength = trackLength; | ||||
|         mDuration = duration; | ||||
|         mStepCount = stepCount; | ||||
|         mRecordingStart = recordingStart; | ||||
|         mRecordingStop = recordingStop; | ||||
|         mMaxAltitude = maxAltitude; | ||||
|         mMinAltitude = minAltitude; | ||||
|         mPositiveElevation = positiveElevation; | ||||
|         mNegativeElevation = negativeElevation; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Builds and return a Track object */ | ||||
|     public Track toTrack() { | ||||
|         switch (mTrackFormatVersion) { | ||||
|             case 1: | ||||
|                 // file format version 1 - does not have elevation data stored | ||||
|                 return new Track(mTrackFormatVersion, mWayPoints, mTrackLength, mDuration, mStepCount, mRecordingStart, mRecordingStop, 0f, 0f, 0f, 0f); | ||||
|             case 2: | ||||
|                 // file format version 2 (current version) | ||||
|                 return new Track(mTrackFormatVersion, mWayPoints, mTrackLength, mDuration, mStepCount, mRecordingStart, mRecordingStop, mMaxAltitude, mMinAltitude, mPositiveElevation, mNegativeElevation); | ||||
|             default: | ||||
|                 LogHelper.e(LOG_TAG, "Unknown file format version: " + mTrackFormatVersion); | ||||
|                 return null; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -17,7 +17,6 @@ | |||
| package org.y20k.trackbook.helpers; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.location.Location; | ||||
| import android.os.Environment; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.support.v4.os.EnvironmentCompat; | ||||
|  | @ -28,6 +27,7 @@ import com.google.gson.GsonBuilder; | |||
| 
 | ||||
| import org.y20k.trackbook.R; | ||||
| import org.y20k.trackbook.core.Track; | ||||
| import org.y20k.trackbook.core.TrackBuilder; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.BufferedWriter; | ||||
|  | @ -101,6 +101,9 @@ public class StorageHelper implements TrackbookKeys { | |||
|         } | ||||
| 
 | ||||
|         if (mFolder != null && mFolder.exists() && mFolder.isDirectory() && mFolder.canWrite() && recordingStart != null && track != null) { | ||||
|             // calculate elevation and store it in track | ||||
|             track = calculateElevation(track); | ||||
| 
 | ||||
|             // create file object | ||||
|             String fileName; | ||||
|             if (fileType == FILE_TEMP_TRACK) { | ||||
|  | @ -221,22 +224,19 @@ public class StorageHelper implements TrackbookKeys { | |||
|         try (BufferedReader br = new BufferedReader(new FileReader(file))) { | ||||
|             LogHelper.v(LOG_TAG, "Loading track from external storage: " + file.toString()); | ||||
| 
 | ||||
|             // read until last line reached | ||||
|             String line; | ||||
|             StringBuilder sb = new StringBuilder(""); | ||||
| 
 | ||||
|             // read until last line reached | ||||
|             while ((line = br.readLine()) != null) { | ||||
|                 sb.append(line); | ||||
|                 sb.append("\n"); | ||||
|             } | ||||
| 
 | ||||
|             // TODO implement a format version check before handing the file to GSON | ||||
| 
 | ||||
|             // get track from JSON | ||||
|             // prepare GsonBuilder and return Track object | ||||
|             GsonBuilder gsonBuilder = new GsonBuilder(); | ||||
|             gsonBuilder.setDateFormat("M/d/yy hh:mm a"); | ||||
|             Gson gson = gsonBuilder.create(); | ||||
|             return gson.fromJson(sb.toString(), Track.class); | ||||
|             return gson.fromJson(sb.toString(), TrackBuilder.class).toTrack(); | ||||
| 
 | ||||
|         } catch (IOException e) { | ||||
|             LogHelper.e(LOG_TAG, "Unable to read file from external storage: " + file.toString()); | ||||
|  | @ -360,38 +360,105 @@ public class StorageHelper implements TrackbookKeys { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* Calculates positive and negative elevation of track */ // todo make private | ||||
|     public Track calculateTrackElevation(@Nullable Track track) { | ||||
|     /* Calculates positive and negative elevation of track */ | ||||
|     private Track calculateElevation(@Nullable Track track) { | ||||
|         double maxAltitude = 0; | ||||
|         double minAltitude = 0; | ||||
|         double positiveElevation = 0; | ||||
|         double negativeElevation = 0; | ||||
|         double LIKELY_MEASUREMENT_ERROR = 25; // move to TrackbookKeys | ||||
| 
 | ||||
|         if (track != null && track.getWayPoints().size() > 0 && track.getWayPointLocation(0).getAltitude() != 0) { | ||||
|             Location previousLocation; | ||||
|             Location nextLocation; | ||||
|             double previousLocationHeight; | ||||
|             double currentLocationHeight; | ||||
|             long previousTimeStamp; | ||||
|             long currentTimeStamp; | ||||
| 
 | ||||
|             // initial values for max height and min height - first waypoint | ||||
|             maxAltitude = track.getWayPointLocation(0).getAltitude(); | ||||
|             minAltitude = maxAltitude; | ||||
| 
 | ||||
|             // apply filter & smooth data | ||||
| //            track = lowPass(track, 15f, 35f); | ||||
| 
 | ||||
|             // iterate over track | ||||
|             for (int i = 0; i < track.getWayPoints().size() - 1; i++ ) { | ||||
|                 // calculate elevation difference | ||||
|                 previousLocation = track.getWayPointLocation(i); | ||||
|                 nextLocation = track.getWayPointLocation(i + 1); | ||||
|                 double difference = nextLocation.getAltitude() - previousLocation.getAltitude(); | ||||
|                 LogHelper.i(LOG_TAG, "next:" + nextLocation.getAltitude() + " | prev:" + previousLocation.getAltitude() + " | diff:" + difference); // todo remove | ||||
|             for (int i = 1; i < track.getWayPoints().size(); i++ ) { | ||||
| 
 | ||||
|                 // add difference to elevation | ||||
|                 if (difference > 0 && difference < LIKELY_MEASUREMENT_ERROR) { | ||||
|                     positiveElevation = positiveElevation + difference; | ||||
|                 } else if (difference < 0 && difference > -LIKELY_MEASUREMENT_ERROR) { | ||||
|                     negativeElevation = negativeElevation + difference; | ||||
|                 // get time difference | ||||
|                 previousTimeStamp = track.getWayPointLocation(i -1).getTime(); | ||||
|                 currentTimeStamp = track.getWayPointLocation(i).getTime(); | ||||
|                 double timeDiff = (currentTimeStamp - previousTimeStamp); | ||||
| 
 | ||||
|                 // factor is bigger than 1 if the time stamp difference is larger than the movement recording interval (usually 15 seconds) | ||||
|                 double timeDiffFactor = timeDiff / FIFTEEN_SECONDS_IN_MILLISECONDS; | ||||
| 
 | ||||
|                 // height of previous and current waypoints | ||||
|                 previousLocationHeight = track.getWayPointLocation(i -1).getAltitude(); | ||||
|                 currentLocationHeight = track.getWayPointLocation(i).getAltitude(); | ||||
| 
 | ||||
|                 // check for new min and max heights | ||||
|                 if (currentLocationHeight > maxAltitude) { | ||||
|                     maxAltitude = currentLocationHeight; | ||||
|                 } else if (minAltitude == 0 || currentLocationHeight < minAltitude) { | ||||
|                     minAltitude = currentLocationHeight; | ||||
|                 } | ||||
| 
 | ||||
|                 // get elevation difference and sum it up | ||||
|                 double altitudeDiff = currentLocationHeight - previousLocationHeight; | ||||
|                 if (altitudeDiff > 0 && altitudeDiff < MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationHeight != 0) { | ||||
|                     positiveElevation = positiveElevation + altitudeDiff; | ||||
|                 } else if (altitudeDiff < 0 && altitudeDiff > -MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationHeight != 0) { | ||||
|                     negativeElevation = negativeElevation + altitudeDiff; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             String toastString = "Calculated elevation: +" +  positiveElevation + " / " + negativeElevation + " meters"; // todo remove | ||||
|             Toast.makeText(mContext, toastString, Toast.LENGTH_LONG).show(); // todo remove | ||||
|             LogHelper.i(LOG_TAG, toastString); // todo remove | ||||
|             // store elevation data in track | ||||
|             track.setMaxAltitude(maxAltitude); | ||||
|             track.setMinAltitude(minAltitude); | ||||
|             track.setPositiveElevation(positiveElevation); | ||||
|             track.setNegativeElevation(negativeElevation); | ||||
|         } | ||||
|         return track; | ||||
|     } | ||||
| 
 | ||||
|     /* Tries to smooth the elevation data using a low pass filter */ | ||||
|     private Track lowPass(Track input, float dt, float rc) { | ||||
|         /* The following code is adapted from https://en.wikipedia.org/wiki/Low-pass_filter | ||||
|           * | ||||
|           * // Return RC low-pass filter output samples, given input samples, | ||||
|           * // time interval dt, and time constant RC | ||||
|           * function lowpass(real[0..n] x, real dt, real RC) | ||||
|           *     var real[0..n] y | ||||
|           *     var real α := dt / (RC + dt) | ||||
|           *     y[0] := α * x[0] | ||||
|           *     for i from 1 to n | ||||
|           *         y[i] := α * x[i] + (1-α) * y[i-1] | ||||
|           *     return y | ||||
|           */ | ||||
| 
 | ||||
|         // copy input track | ||||
|         Track output = new Track(input); | ||||
| 
 | ||||
|         // calculate alpha | ||||
|         float alpha = dt / (rc + dt); | ||||
| 
 | ||||
|         // set initial value for first waypoint | ||||
|         double outputInitialAltituteValue = alpha * input.getWayPoints().get(0).getLocation().getAltitude(); | ||||
|         output.getWayPoints().get(0).getLocation().setAltitude(outputInitialAltituteValue); | ||||
| 
 | ||||
|         double inputCurrentAltitudeValue; | ||||
|         double outputPreviousAltitudeValue; | ||||
|         double outputCurrentAltitudeValue; | ||||
|         for (int i = 1; i < input.getSize(); i++) { | ||||
|             inputCurrentAltitudeValue = input.getWayPoints().get(i).getLocation().getAltitude(); | ||||
|             outputPreviousAltitudeValue = output.getWayPoints().get(i-1).getLocation().getAltitude(); | ||||
| 
 | ||||
|             outputCurrentAltitudeValue = alpha * inputCurrentAltitudeValue + (1 - alpha) * outputPreviousAltitudeValue; | ||||
| 
 | ||||
|             output.getWayPoints().get(i).getLocation().setAltitude(outputCurrentAltitudeValue); | ||||
|         } | ||||
| 
 | ||||
|         return output; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -111,10 +111,10 @@ public interface TrackbookKeys { | |||
|     String NOTIFICATION_CHANEL_ID_RECORDING_CHANNEL ="notificationChannelIdRecordingChannel"; | ||||
| 
 | ||||
|     /* MISC */ | ||||
|     int CURRENT_TRACK_FORMAT_VERSION = 2; // incremental version number to prevent issues in case the Track format evolves | ||||
|     double DEFAULT_LATITUDE = 49.41667; // latitude Nordkapp, Norway | ||||
|     double DEFAULT_LONGITUDE = 8.67201; // longitude Nordkapp, Norway | ||||
|     int CURRENT_TRACK_FORMAT_VERSION = 1; // incremental version number to prevent issues in case the Track format evolves | ||||
|     int MEASUREMENT_ERROR_THRESHOLD = 10; // altitude changes of 10 meter or more (per 15 seconds) are being discarded | ||||
|     int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124; | ||||
|     int INFOSHEET_CONTENT_ABOUT = 1; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -5,6 +5,12 @@ | |||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content"> | ||||
| 
 | ||||
|     <android.support.constraint.Group | ||||
|         android:id="@+id/elevation_data" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:constraint_referenced_ids="statistics_p_positive_elevation, statistics_data_positive_elevation, statistics_p_negative_elevation, statistics_data_negative_elevation, statistics_p_max_altitude, statistics_data_max_altitude, statistics_p_min_altitude, statistics_data_min_altitude" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/statistics_headline" | ||||
|         android:layout_width="0dp" | ||||
|  | @ -148,11 +154,9 @@ | |||
|         android:id="@+id/statistics_p_recording_stop" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="16dp" | ||||
|         android:layout_marginTop="16dp" | ||||
|         android:contentDescription="@string/descr_statistics_sheet_p_recording_end" | ||||
|         android:text="@string/statistics_sheet_p_recording_stop" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="@+id/statistics_p_recording_start" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/statistics_p_recording_start" /> | ||||
| 
 | ||||
|  | @ -168,4 +172,90 @@ | |||
|         app:layout_constraintStart_toEndOf="@+id/statistics_p_recording_stop" | ||||
|         app:layout_constraintTop_toTopOf="@+id/statistics_p_recording_stop" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/statistics_p_positive_elevation" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginTop="16dp" | ||||
|         android:contentDescription="@string/descr_statistics_sheet_p_positive_elevation" | ||||
|         android:text="@string/statistics_sheet_p_positive_elevation" | ||||
|         app:layout_constraintStart_toStartOf="@+id/statistics_p_recording_stop" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/statistics_p_recording_stop" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/statistics_data_positive_elevation" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="16dp" | ||||
|         android:text="@string/statistics_sheet_p_default_data" | ||||
|         android:textAppearance="@android:style/TextAppearance.Material.Medium" | ||||
|         app:layout_constraintBottom_toBottomOf="@+id/statistics_p_positive_elevation" | ||||
|         app:layout_constraintStart_toEndOf="@+id/statistics_p_positive_elevation" | ||||
|         app:layout_constraintTop_toTopOf="@+id/statistics_p_positive_elevation" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/statistics_p_negative_elevation" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginTop="16dp" | ||||
|         android:contentDescription="@string/descr_statistics_sheet_p_negative_elevation" | ||||
|         android:text="@string/statistics_sheet_p_negative_elevation" | ||||
|         app:layout_constraintStart_toStartOf="@+id/statistics_p_positive_elevation" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/statistics_p_positive_elevation" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/statistics_data_negative_elevation" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="16dp" | ||||
|         android:text="@string/statistics_sheet_p_default_data" | ||||
|         android:textAppearance="@android:style/TextAppearance.Material.Medium" | ||||
|         app:layout_constraintBottom_toBottomOf="@+id/statistics_p_negative_elevation" | ||||
|         app:layout_constraintStart_toEndOf="@+id/statistics_p_negative_elevation" | ||||
|         app:layout_constraintTop_toTopOf="@+id/statistics_p_negative_elevation" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/statistics_p_max_altitude" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginTop="16dp" | ||||
|         android:contentDescription="@string/descr_statistics_sheet_p_max_altitude" | ||||
|         android:text="@string/statistics_sheet_p_max_altitude" | ||||
|         app:layout_constraintStart_toStartOf="@+id/statistics_p_negative_elevation" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/statistics_p_negative_elevation" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/statistics_data_max_altitude" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="16dp" | ||||
|         android:text="@string/statistics_sheet_p_default_data" | ||||
|         android:textAppearance="@android:style/TextAppearance.Material.Medium" | ||||
|         app:layout_constraintBottom_toBottomOf="@+id/statistics_p_max_altitude" | ||||
|         app:layout_constraintStart_toEndOf="@+id/statistics_p_max_altitude" | ||||
|         app:layout_constraintTop_toTopOf="@+id/statistics_p_max_altitude" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/statistics_p_min_altitude" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="16dp" | ||||
|         android:layout_marginTop="16dp" | ||||
|         android:contentDescription="@string/descr_statistics_sheet_p_min_altitude" | ||||
|         android:text="@string/statistics_sheet_p_min_altitude" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="@+id/statistics_p_max_altitude" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/statistics_p_max_altitude" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/statistics_data_min_altitude" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="16dp" | ||||
|         android:text="@string/statistics_sheet_p_default_data" | ||||
|         android:textAppearance="@android:style/TextAppearance.Material.Medium" | ||||
|         app:layout_constraintBottom_toBottomOf="@+id/statistics_p_min_altitude" | ||||
|         app:layout_constraintStart_toEndOf="@+id/statistics_p_min_altitude" | ||||
|         app:layout_constraintTop_toTopOf="@+id/statistics_p_min_altitude" /> | ||||
| 
 | ||||
| </android.support.constraint.ConstraintLayout> | ||||
|  | @ -56,8 +56,9 @@ | |||
|     <string name="toast_message_save_track">Aufzeichnung wird gespeichert.</string> | ||||
|     <string name="toast_message_last_location_age_one_hour">über eine Stunde</string> | ||||
|     <string name="toast_message_track_clear">Aufzeichnung zurückgesetzt.</string> | ||||
|     <string name="toast_message_export_success">GPX export successful:</string> | ||||
|     <string name="toast_message_export_fail">GPX export failed:</string> | ||||
|     <string name="toast_message_export_success">GPX-Export erfolgreich:</string> | ||||
|     <string name="toast_message_export_fail">GPX-Export fehlgeschlagen:</string> | ||||
|     <string name="toast_message_elevation_info">Hinweis: Die Genauogkeit der Höhenmeter-Werte ist geräteabhängig. Gemessen werden die Steigungen und Gefälle der Gesamtstrecke.</string> | ||||
| 
 | ||||
|     <!-- map markers --> | ||||
|     <string name="marker_description_source">Quelle</string> | ||||
|  | @ -74,6 +75,10 @@ | |||
|     <string name="statistics_sheet_p_duration">Dauer (gesamt):</string> | ||||
|     <string name="statistics_sheet_p_recording_start">Start der Aufzeichnung:</string> | ||||
|     <string name="statistics_sheet_p_recording_stop">Ende der Aufzeichnung:</string> | ||||
|     <string name="statistics_sheet_p_max_altitude">Höchster Wegpunkt:</string> | ||||
|     <string name="statistics_sheet_p_min_altitude">Tiefster Wegpunkt:</string> | ||||
|     <string name="statistics_sheet_p_positive_elevation">Höhenmeter (bergauf):</string> | ||||
|     <string name="statistics_sheet_p_negative_elevation">Höhenmeter (bergab):</string> | ||||
| 
 | ||||
|     <!-- onboarding layout --> | ||||
|     <string name="layout_onboarding_h1_welcome">Hallo</string> | ||||
|  | @ -114,6 +119,10 @@ | |||
|     <string name="descr_statistics_sheet_p_duration_value">Wert: Dauer</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_start_value">Wert: Start der Aufzeichnung</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_end_value">Wert: Ende der Aufzeichnung</string> | ||||
|     <string name="descr_statistics_sheet_p_max_altitude">Wert: Höchster Wegpunkt</string> | ||||
|     <string name="descr_statistics_sheet_p_min_altitude">Wert: Tiefster Wegpunkt:</string> | ||||
|     <string name="descr_statistics_sheet_p_positive_elevation">Wert: Höhenmeter (bergauf)</string> | ||||
|     <string name="descr_statistics_sheet_p_negative_elevation">Wert Höhenmeter (bergab)</string> | ||||
|     <string name="descr_track_selector">Auswahl-Menü für weitere Aufzeichnungen</string> | ||||
|     <string name="descr_export_button">Button Track Exportierem</string> | ||||
|     <string name="descr_delete_button">Button Track Löschen</string> | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ | |||
|     <string name="toast_message_track_clear">Current track data removed.</string> | ||||
|     <string name="toast_message_export_success">GPX export successful:</string> | ||||
|     <string name="toast_message_export_fail">GPX export failed:</string> | ||||
|     <string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string> | ||||
| 
 | ||||
|     <!-- map markers --> | ||||
|     <string name="marker_description_source">Source</string> | ||||
|  | @ -74,6 +75,10 @@ | |||
|     <string name="statistics_sheet_p_duration">Total duration:</string> | ||||
|     <string name="statistics_sheet_p_recording_start">Recording started:</string> | ||||
|     <string name="statistics_sheet_p_recording_stop">Recording stopped:</string> | ||||
|     <string name="statistics_sheet_p_max_altitude">Highest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string> | ||||
|     <string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string> | ||||
| 
 | ||||
|     <!-- onboarding layout --> | ||||
|     <string name="layout_onboarding_h1_welcome">Hello</string> | ||||
|  | @ -114,6 +119,10 @@ | |||
|     <string name="descr_statistics_sheet_p_duration_value">Value: Duration</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_start_value">Value: Start of recording</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_end_value">Value: End of recording</string> | ||||
|     <string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string> | ||||
|     <string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string> | ||||
|     <string name="descr_track_selector">Dropdown menu for further tracks</string> | ||||
|     <string name="descr_export_button">Track export button</string> | ||||
|     <string name="descr_delete_button">Track delete button</string> | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ | |||
|     <string name="toast_message_track_clear">Dati della traccia corrente rimossi.</string> | ||||
|     <string name="toast_message_export_success">L\'esportazione GPX è riuscita:</string> | ||||
|     <string name="toast_message_export_fail">L\'esportazione GPX non è riuscita:</string> | ||||
|     <string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string> | ||||
| 
 | ||||
|     <!-- map markers --> | ||||
|     <string name="marker_description_source">Fonte</string> | ||||
|  | @ -74,6 +75,10 @@ | |||
|     <string name="statistics_sheet_p_duration">Durata totale:</string> | ||||
|     <string name="statistics_sheet_p_recording_start">Registrazione avviata il:</string> | ||||
|     <string name="statistics_sheet_p_recording_stop">Registrazione interrotta il:</string> | ||||
|     <string name="statistics_sheet_p_max_altitude">Highest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string> | ||||
|     <string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string> | ||||
| 
 | ||||
|     <!-- onboarding layout --> | ||||
|     <string name="layout_onboarding_h1_welcome">Ciao</string> | ||||
|  | @ -114,6 +119,10 @@ | |||
|     <string name="descr_statistics_sheet_p_duration_value">Valore: Durata</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_start_value">Valore: Inizio della registrazione</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_end_value">Valore: Fine della registrazione</string> | ||||
|     <string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string> | ||||
|     <string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string> | ||||
|     <string name="descr_track_selector">Elenco registrazioni</string> | ||||
|     <string name="descr_export_button">Pulsante di esportazione della traccia</string> | ||||
|     <string name="descr_delete_button">Pulsante di eliminazione della traccia</string> | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ | |||
|     <string name="toast_message_track_clear">現在のトレース データを削除しました。</string> | ||||
|     <string name="toast_message_export_success">GPX export successful:</string> | ||||
|     <string name="toast_message_export_fail">GPX export failed:</string> | ||||
|     <string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string> | ||||
| 
 | ||||
|     <!-- map markers --> | ||||
|     <string name="marker_description_source">ソース</string> | ||||
|  | @ -74,6 +75,10 @@ | |||
|     <string name="statistics_sheet_p_duration">合計時間:</string> | ||||
|     <string name="statistics_sheet_p_recording_start">記録の開始:</string> | ||||
|     <string name="statistics_sheet_p_recording_stop">記録の停止:</string> | ||||
|     <string name="statistics_sheet_p_max_altitude">Highest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string> | ||||
|     <string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string> | ||||
| 
 | ||||
|     <!-- onboarding layout --> | ||||
|     <string name="layout_onboarding_h1_welcome">こんにちは</string> | ||||
|  | @ -114,6 +119,10 @@ | |||
|     <string name="descr_statistics_sheet_p_duration_value">値: 期間</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_start_value">値: 記録の開始</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_end_value">値: 記録の終了</string> | ||||
|     <string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string> | ||||
|     <string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string> | ||||
|     <string name="descr_track_selector">ドロップダウン メニューでさらにトレース</string> | ||||
|     <string name="descr_export_button">Track export button</string> | ||||
|     <string name="descr_delete_button">トレース削除ボタン</string> | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ | |||
|     <string name="toast_message_track_clear">Nåværende turdata fjernet.</string> | ||||
|     <string name="toast_message_export_success">GPX-eksportering vellykket:</string> | ||||
|     <string name="toast_message_export_fail">GPX-eksportering mislyktes:</string> | ||||
|     <string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string> | ||||
| 
 | ||||
|     <!-- map markers --> | ||||
|     <string name="marker_description_source">Kilde</string> | ||||
|  | @ -74,6 +75,10 @@ | |||
|     <string name="statistics_sheet_p_duration">Total varighet:</string> | ||||
|     <string name="statistics_sheet_p_recording_start">Opptak startet:</string> | ||||
|     <string name="statistics_sheet_p_recording_stop">Opptak stoppet:</string> | ||||
|     <string name="statistics_sheet_p_max_altitude">Highest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string> | ||||
|     <string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string> | ||||
| 
 | ||||
|     <!-- onboarding layout --> | ||||
|     <string name="layout_onboarding_h1_welcome">Hallo</string> | ||||
|  | @ -114,6 +119,10 @@ | |||
|     <string name="descr_statistics_sheet_p_duration_value">Verdi: Varighet</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_start_value">Verdi: Opptaksstart</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_end_value">Verdi: Opptaksslutt</string> | ||||
|     <string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string> | ||||
|     <string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string> | ||||
|     <string name="descr_track_selector">Nedtrekksmeny for ytterligere turer</string> | ||||
|     <string name="descr_export_button">Tureksportknapp</string> | ||||
|     <string name="descr_delete_button">Turslettingsknapp</string> | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ | |||
|     <string name="toast_message_track_clear">Huidige baangegevens verwijderd.</string> | ||||
|     <string name="toast_message_export_success">GPX export successful:</string> | ||||
|     <string name="toast_message_export_fail">GPX export failed:</string> | ||||
|     <string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string> | ||||
| 
 | ||||
|     <!-- map markers --> | ||||
|     <string name="marker_description_source">Bron</string> | ||||
|  | @ -74,6 +75,10 @@ | |||
|     <string name="statistics_sheet_p_duration">Totale duur:</string> | ||||
|     <string name="statistics_sheet_p_recording_start">Bijhouden gestart:</string> | ||||
|     <string name="statistics_sheet_p_recording_stop">Bijhouden gestopt:</string> | ||||
|     <string name="statistics_sheet_p_max_altitude">Highest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string> | ||||
|     <string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string> | ||||
| 
 | ||||
|     <!-- onboarding layout --> | ||||
|     <string name="layout_onboarding_h1_welcome">Hallo</string> | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ | |||
|     <string name="toast_message_track_clear">Current track data removed.</string> | ||||
|     <string name="toast_message_export_success">GPX export successful:</string> | ||||
|     <string name="toast_message_export_fail">GPX export failed:</string> | ||||
|     <string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string> | ||||
| 
 | ||||
|     <!-- map markers --> | ||||
|     <string name="marker_description_source">Source</string> | ||||
|  | @ -74,6 +75,10 @@ | |||
|     <string name="statistics_sheet_p_duration">Total duration:</string> | ||||
|     <string name="statistics_sheet_p_recording_start">Recording started:</string> | ||||
|     <string name="statistics_sheet_p_recording_stop">Recording stopped:</string> | ||||
|     <string name="statistics_sheet_p_max_altitude">Highest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string> | ||||
|     <string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string> | ||||
|     <string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string> | ||||
| 
 | ||||
|     <!-- onboarding layout --> | ||||
|     <string name="layout_onboarding_h1_welcome">Hello</string> | ||||
|  | @ -114,6 +119,10 @@ | |||
|     <string name="descr_statistics_sheet_p_duration_value">Value: Duration</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_start_value">Value: Start of recording</string> | ||||
|     <string name="descr_statistics_sheet_p_recording_end_value">Value: End of recording</string> | ||||
|     <string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string> | ||||
|     <string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string> | ||||
|     <string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string> | ||||
|     <string name="descr_track_selector">Dropdown menu for further tracks</string> | ||||
|     <string name="descr_export_button">Track export button</string> | ||||
|     <string name="descr_delete_button">Track delete button</string> | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 y20k
						y20k