This commit is contained in:
Dennis Guse
2020-04-03 20:43:02 +02:00
parent 46f8753746
commit 38a15a96b3
5 changed files with 119 additions and 142 deletions
@@ -49,7 +49,7 @@ public class TrackStubUtils {
public static Track createTrack(int numberOfLocations) { public static Track createTrack(int numberOfLocations) {
Track track = new Track(); Track track = new Track();
for (int i = 0; i < numberOfLocations; i++) { for (int i = 0; i < numberOfLocations; i++) {
track.addTrackPoint(createSensorDataSetLocation(INITIAL_LATITUDE + i * DIFFERENCE, INITIAL_LONGITUDE + i * DIFFERENCE, INITIAL_ALTITUDE + i * DIFFERENCE)); track.addTrackPoint(createDefaultTrackPoint(INITIAL_LATITUDE + i * DIFFERENCE, INITIAL_LONGITUDE + i * DIFFERENCE, INITIAL_ALTITUDE + i * DIFFERENCE));
} }
return track; return track;
@@ -60,8 +60,8 @@ public class TrackStubUtils {
* *
* @return a track stub. * @return a track stub.
*/ */
public static TrackPoint createSensorDataSetLocation() { public static TrackPoint createDefaultTrackPoint() {
return createSensorDataSetLocation(INITIAL_LATITUDE, INITIAL_LONGITUDE, INITIAL_ALTITUDE); return createDefaultTrackPoint(INITIAL_LATITUDE, INITIAL_LONGITUDE, INITIAL_ALTITUDE);
} }
/** /**
@@ -69,7 +69,7 @@ public class TrackStubUtils {
* *
* @return a SensorDataSetLocation stub. * @return a SensorDataSetLocation stub.
*/ */
private static TrackPoint createSensorDataSetLocation(double latitude, double longitude, double altitude) { private static TrackPoint createDefaultTrackPoint(double latitude, double longitude, double altitude) {
Location location = new Location(LOCATION_PROVIDER); Location location = new Location(LOCATION_PROVIDER);
location.setLatitude(latitude); location.setLatitude(latitude);
location.setLongitude(longitude); location.setLongitude(longitude);
@@ -67,14 +67,14 @@ public class ChartFragmentTest {
} }
/** /**
* Tests the logic to get the incorrect values of sensor in {@link ChartFragment#fillDataPoint(TrackPoint, double[])}. * Tests the logic to get the incorrect values of sensor in {@link ChartFragment#createPendingPoint(TrackPoint)}.
*/ */
@Test @Test
public void testFillDataPoint_sensorIncorrect() { public void testCreatePendingPoint_sensorIncorrect() {
TrackPoint sensorDataSetLocation = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
// No input. // No input.
double[] point = fillDataPointTestHelper(sensorDataSetLocation); double[] point = chartFragment.createPendingPoint(trackPoint);
Assert.assertEquals(Float.NaN, point[ChartView.HEART_RATE_SERIES + 1], 0.01); Assert.assertEquals(Float.NaN, point[ChartView.HEART_RATE_SERIES + 1], 0.01);
Assert.assertEquals(Float.NaN, point[ChartView.CADENCE_SERIES + 1], 0.01); Assert.assertEquals(Float.NaN, point[ChartView.CADENCE_SERIES + 1], 0.01);
Assert.assertEquals(Float.NaN, point[ChartView.POWER_SERIES + 1], 0.01); Assert.assertEquals(Float.NaN, point[ChartView.POWER_SERIES + 1], 0.01);
@@ -82,22 +82,22 @@ public class ChartFragmentTest {
// Input incorrect state. // Input incorrect state.
// Creates SensorData. // Creates SensorData.
SensorDataSet sensorDataSet = new SensorDataSet(SensorDataSet.DATA_UNAVAILABLE, SensorDataSet.DATA_UNAVAILABLE); SensorDataSet sensorDataSet = new SensorDataSet(SensorDataSet.DATA_UNAVAILABLE, SensorDataSet.DATA_UNAVAILABLE);
sensorDataSetLocation.setSensorDataSet(sensorDataSet); trackPoint.setSensorDataSet(sensorDataSet);
// Test. // Test.
point = fillDataPointTestHelper(sensorDataSetLocation); point = chartFragment.createPendingPoint(trackPoint);
Assert.assertEquals(Float.NaN, point[ChartView.HEART_RATE_SERIES + 1], 0.01); Assert.assertEquals(Float.NaN, point[ChartView.HEART_RATE_SERIES + 1], 0.01);
Assert.assertEquals(Float.NaN, point[ChartView.CADENCE_SERIES + 1], 0.01); Assert.assertEquals(Float.NaN, point[ChartView.CADENCE_SERIES + 1], 0.01);
Assert.assertEquals(Float.NaN, point[ChartView.POWER_SERIES + 1], 0.01); Assert.assertEquals(Float.NaN, point[ChartView.POWER_SERIES + 1], 0.01);
} }
/** /**
* Tests the logic to get the correct values of sensor in {@link ChartFragment#fillDataPoint(TrackPoint, double[])}. * Tests the logic to get the correct values of sensor in {@link ChartFragment#createPendingPoint(TrackPoint)}.
*/ */
@Test @Test
public void testFillDataPoint_sensorCorrect() { public void testCreatePendingPoint_sensorCorrect() {
TrackPoint sensorDataSetLocation = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
// No input. // No input.
double[] point = fillDataPointTestHelper(sensorDataSetLocation); double[] point = chartFragment.createPendingPoint(trackPoint);
Assert.assertEquals(Float.NaN, point[ChartView.HEART_RATE_SERIES + 1], 0.01); Assert.assertEquals(Float.NaN, point[ChartView.HEART_RATE_SERIES + 1], 0.01);
Assert.assertEquals(Float.NaN, point[ChartView.CADENCE_SERIES + 1], 0.01); Assert.assertEquals(Float.NaN, point[ChartView.CADENCE_SERIES + 1], 0.01);
Assert.assertEquals(Float.NaN, point[ChartView.POWER_SERIES + 1], 0.01); Assert.assertEquals(Float.NaN, point[ChartView.POWER_SERIES + 1], 0.01);
@@ -106,167 +106,164 @@ public class ChartFragmentTest {
SensorDataSet sensorDataSet = new SensorDataSet(100, 101, 102); SensorDataSet sensorDataSet = new SensorDataSet(100, 101, 102);
// Creates SensorDataSet. // Creates SensorDataSet.
sensorDataSetLocation.setSensorDataSet(sensorDataSet); trackPoint.setSensorDataSet(sensorDataSet);
// Test. // Test.
point = fillDataPointTestHelper(sensorDataSetLocation); point = chartFragment.createPendingPoint(trackPoint);
Assert.assertEquals(100.0, point[ChartView.HEART_RATE_SERIES + 1], 0.01); Assert.assertEquals(100.0, point[ChartView.HEART_RATE_SERIES + 1], 0.01);
Assert.assertEquals(101.0, point[ChartView.CADENCE_SERIES + 1], 0.01); Assert.assertEquals(101.0, point[ChartView.CADENCE_SERIES + 1], 0.01);
Assert.assertEquals(102.0, point[ChartView.POWER_SERIES + 1], 0.01); Assert.assertEquals(102.0, point[ChartView.POWER_SERIES + 1], 0.01);
} }
/** /**
* Tests the logic to get the value of metric Distance in {@link ChartFragment#fillDataPoint(TrackPoint, double[])}. * Tests the logic to get the value of metric Distance in {@link ChartFragment#createPendingPoint(TrackPoint)}.
*/ */
@Test @Test
public void testFillDataPoint_distanceMetric() { public void testCreatePendingPoint_distanceMetric() {
// By distance.
chartFragment.setChartByDistance(true); chartFragment.setChartByDistance(true);
// Resets last location and writes first location. // Resets last location and writes first location.
TrackPoint sensorDataSetLocation1 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
double[] point = fillDataPointTestHelper(sensorDataSetLocation1); double[] point = chartFragment.createPendingPoint(trackPoint1);
Assert.assertEquals(0.0, point[0], 0.01); Assert.assertEquals(0.0, point[0], 0.01);
// The second is a same location, just different time. // The second is a same location, just different time.
TrackPoint sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
point = fillDataPointTestHelper(sensorDataSetLocation2); point = chartFragment.createPendingPoint(trackPoint2);
Assert.assertEquals(0.0, point[0], 0.01); Assert.assertEquals(0.0, point[0], 0.01);
// The third location is a new location, and use metric. // The third location is a new location, and use metric.
TrackPoint sensorDataSetLocation3 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint3 = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation3.setLatitude(23); trackPoint3.setLatitude(23);
point = fillDataPointTestHelper(sensorDataSetLocation3); point = chartFragment.createPendingPoint(trackPoint3);
// Computes the distance between Latitude 22 and 23. // Computes the distance between Latitude 22 and 23.
float[] results = new float[4]; float[] results = new float[4];
Location.distanceBetween(sensorDataSetLocation2.getLatitude(), sensorDataSetLocation2.getLongitude(), Location.distanceBetween(trackPoint2.getLatitude(), trackPoint2.getLongitude(),
sensorDataSetLocation3.getLatitude(), sensorDataSetLocation3.getLongitude(), results); trackPoint3.getLatitude(), trackPoint3.getLongitude(), results);
double distance1 = results[0] * UnitConversions.M_TO_KM; double distance1 = results[0] * UnitConversions.M_TO_KM;
Assert.assertEquals(distance1, point[0], 0.01); Assert.assertEquals(distance1, point[0], 0.01);
// The fourth location is a new location, and use metric. // The fourth location is a new location, and use metric.
TrackPoint sensorDataSetLocation4 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint4 = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation4.setLatitude(24); trackPoint4.setLatitude(24);
point = fillDataPointTestHelper(sensorDataSetLocation4); point = chartFragment.createPendingPoint(trackPoint4);
// Computes the distance between Latitude 23 and 24. // Computes the distance between Latitude 23 and 24.
Location.distanceBetween(sensorDataSetLocation3.getLatitude(), sensorDataSetLocation3.getLongitude(), Location.distanceBetween(trackPoint3.getLatitude(), trackPoint3.getLongitude(),
sensorDataSetLocation4.getLatitude(), sensorDataSetLocation4.getLongitude(), results); trackPoint4.getLatitude(), trackPoint4.getLongitude(), results);
double distance2 = results[0] * UnitConversions.M_TO_KM; double distance2 = results[0] * UnitConversions.M_TO_KM;
Assert.assertEquals((distance1 + distance2), point[0], 0.01); Assert.assertEquals((distance1 + distance2), point[0], 0.01);
} }
/** /**
* Tests the logic to get the value of imperial Distance in {@link ChartFragment#fillDataPoint(TrackPoint, double[])}. * Tests the logic to get the value of imperial Distance in {@link ChartFragment#createPendingPoint(TrackPoint)}.
*/ */
@Test @Test
public void testFillDataPoint_distanceImperial() { public void testCreatePendingPoint_distanceImperial() {
// By distance. // By distance.
chartFragment.setChartByDistance(true); chartFragment.setChartByDistance(true);
// Setups to use imperial. // Setups to use imperial.
chartFragment.setMetricUnits(false); chartFragment.setMetricUnits(false);
// The first is a same location, just different time. // The first is a same location, just different time.
TrackPoint sensorDataSetLocation1 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
double[] point = fillDataPointTestHelper(sensorDataSetLocation1); double[] point = chartFragment.createPendingPoint(trackPoint1);
Assert.assertEquals(0.0, point[0], 0.01); Assert.assertEquals(0.0, point[0], 0.01);
// The second location is a new location, and use imperial. // The second location is a new location, and use imperial.
TrackPoint sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation2.setLatitude(23); trackPoint2.setLatitude(23);
point = fillDataPointTestHelper(sensorDataSetLocation2); point = chartFragment.createPendingPoint(trackPoint2);
/* /*
* Computes the distance between Latitude 22 and 23. * Computes the distance between Latitude 22 and 23.
* And for we set using * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI. * And for we set using * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI.
*/ */
float[] results = new float[4]; float[] results = new float[4];
Location.distanceBetween(sensorDataSetLocation1.getLatitude(), sensorDataSetLocation1.getLongitude(), sensorDataSetLocation2.getLatitude(), sensorDataSetLocation2.getLongitude(), results); Location.distanceBetween(trackPoint1.getLatitude(), trackPoint1.getLongitude(), trackPoint2.getLatitude(), trackPoint2.getLongitude(), results);
double distance1 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI; double distance1 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
Assert.assertEquals(distance1, point[0], 0.01); Assert.assertEquals(distance1, point[0], 0.01);
// The third location is a new location, and use imperial. // The third location is a new location, and use imperial.
TrackPoint sensorDataSetLocation3 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint3 = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation3.setLatitude(24); trackPoint3.setLatitude(24);
point = fillDataPointTestHelper(sensorDataSetLocation3); point = chartFragment.createPendingPoint(trackPoint3);
/* /*
* Computes the distance between Latitude 23 and 24. * Computes the distance between Latitude 23 and 24.
* And for we set using * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI. * And for we set using * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI.
*/ */
Location.distanceBetween(sensorDataSetLocation2.getLatitude(), sensorDataSetLocation2.getLongitude(), sensorDataSetLocation3.getLatitude(), sensorDataSetLocation3.getLongitude(), results); Location.distanceBetween(trackPoint2.getLatitude(), trackPoint2.getLongitude(), trackPoint3.getLatitude(), trackPoint3.getLongitude(), results);
double distance2 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI; double distance2 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
Assert.assertEquals(distance1 + distance2, point[0], 0.01); Assert.assertEquals(distance1 + distance2, point[0], 0.01);
} }
/** /**
* Tests the logic to get the values of time in {@link ChartFragment#fillDataPoint(TrackPoint, double[])}. * Tests the logic to get the values of time in {@link ChartFragment#createPendingPoint(TrackPoint)}.
*/ */
@Test @Test
public void testFillDataPoint_time() { public void testCreatePendingPoint_time() {
// By time
chartFragment.setChartByDistance(false); chartFragment.setChartByDistance(false);
TrackPoint sensorDataSetLocation1 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
double[] point = fillDataPointTestHelper(sensorDataSetLocation1); double[] point = chartFragment.createPendingPoint(trackPoint1);
Assert.assertEquals(0.0, point[0], 0.01); Assert.assertEquals(0.0, point[0], 0.01);
long timeSpan = 222; long timeSpan = 222;
TrackPoint sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation2.setTime(sensorDataSetLocation1.getTime() + timeSpan); trackPoint2.setTime(trackPoint1.getTime() + timeSpan);
point = fillDataPointTestHelper(sensorDataSetLocation2); point = chartFragment.createPendingPoint(trackPoint2);
Assert.assertEquals((double) timeSpan, point[0], 0.01); Assert.assertEquals((double) timeSpan, point[0], 0.01);
} }
/** /**
* Tests the logic to get the value of elevation in {@link ChartFragment#fillDataPoint(TrackPoint, double[])} by one and two points. * Tests the logic to get the value of elevation in {@link ChartFragment#createPendingPoint(TrackPoint)} by one and two points.
*/ */
@Test @Test
public void testFillDataPoint_elevation() { public void testCreatePendingPoint_elevation() {
TrackPoint sensorDataSetLocation1 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
/* /*
* At first, clear old points of elevation, so give true to the second parameter. * At first, clear old points of elevation, so give true to the second parameter.
* Then only one value INITIAL_ALTITUDE in buffer. * Then only one value INITIAL_ALTITUDE in buffer.
*/ */
double[] point = fillDataPointTestHelper(sensorDataSetLocation1); double[] point = chartFragment.createPendingPoint(trackPoint1);
Assert.assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[ChartView.ELEVATION_SERIES + 1], 0.01); Assert.assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[ChartView.ELEVATION_SERIES + 1], 0.01);
/* /*
* Send another value to buffer, now there are two values, INITIAL_ALTITUDE and INITIAL_ALTITUDE * 2. * Send another value to buffer, now there are two values, INITIAL_ALTITUDE and INITIAL_ALTITUDE * 2.
*/ */
TrackPoint sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2); trackPoint2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2);
point = fillDataPointTestHelper(sensorDataSetLocation2); point = chartFragment.createPendingPoint(trackPoint2);
Assert.assertEquals((TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0, Assert.assertEquals((TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0, point[ChartView.ELEVATION_SERIES + 1], 0.01);
point[ChartView.ELEVATION_SERIES + 1], 0.01);
} }
/** /**
* Tests the logic to get the value of speed in {@link ChartFragment#fillDataPoint(TrackPoint, double[])}. * Tests the logic to get the value of speed in {@link ChartFragment#createPendingPoint(TrackPoint)}.
* In this test, firstly remove all points in memory, and then fill in two points one by one. * In this test, firstly remove all points in memory, and then fill in two points one by one.
* The speed values of these points are 129, 130. * The speed values of these points are 129, 130.
*/ */
@Test @Test
public void testFillDataPoint_speed() { public void testCreatePendingPoint_speed() {
/* /*
* At first, clear old points of speed, so give true to the second parameter. * At first, clear old points of speed, so give true to the second parameter.
* It will not be filled in to the speed buffer. * It will not be filled in to the speed buffer.
*/ */
TrackPoint sensorDataSetLocation1 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation1.setSpeed(128.5f); trackPoint1.setSpeed(128.5f);
double[] point = fillDataPointTestHelper(sensorDataSetLocation1); double[] point = chartFragment.createPendingPoint(trackPoint1);
Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01); Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01);
/* /*
* Tests the logic when both metricUnits and reportSpeed are true. * Tests the logic when both metricUnits and reportSpeed are true.
* This location will be filled into speed buffer. * This location will be filled into speed buffer.
*/ */
TrackPoint sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
/* /*
* Add a time span here to make sure the second point is valid, the value 222 here is doesn't matter. * Add a time span here to make sure the second point is valid, the value 222 here is doesn't matter.
*/ */
sensorDataSetLocation2.setTime(sensorDataSetLocation1.getTime() + 222); trackPoint2.setTime(trackPoint1.getTime() + 222);
sensorDataSetLocation2.setSpeed(130); trackPoint2.setSpeed(130);
point = fillDataPointTestHelper(sensorDataSetLocation2); point = chartFragment.createPendingPoint(trackPoint2);
Assert.assertEquals(130.0 * UnitConversions.MS_TO_KMH, point[ChartView.SPEED_SERIES + 1], 0.01); Assert.assertEquals(130.0 * UnitConversions.MS_TO_KMH, point[ChartView.SPEED_SERIES + 1], 0.01);
} }
@@ -274,25 +271,24 @@ public class ChartFragmentTest {
* Tests the logic to compute speed when use Imperial. * Tests the logic to compute speed when use Imperial.
*/ */
@Test @Test
public void testFillDataPoint_speedImperial() { public void testCreatePendingPoint_speedImperial() {
// Setups to use imperial.
chartFragment.setMetricUnits(false); chartFragment.setMetricUnits(false);
// First data point is not added to the speed buffer // First data point is not added to the speed buffer
TrackPoint sensorDataSetLocation1 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation1.setSpeed(100.0f); trackPoint1.setSpeed(100.0f);
double[] point = fillDataPointTestHelper(sensorDataSetLocation1); double[] point = chartFragment.createPendingPoint(trackPoint1);
Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01); Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01);
TrackPoint sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
/* /*
* Add a time span here to make sure the second point and the speed is valid. * Add a time span here to make sure the second point and the speed is valid.
* Speed is valid if: speedDifference > Constants.MAX_ACCELERATION * timeDifference speedDifference = 102 -100 timeDifference = 222 * Speed is valid if: speedDifference > Constants.MAX_ACCELERATION * timeDifference speedDifference = 102 -100 timeDifference = 222
*/ */
sensorDataSetLocation2.setTime(sensorDataSetLocation2.getTime() + 222); trackPoint2.setTime(trackPoint2.getTime() + 222);
sensorDataSetLocation2.setSpeed(102); trackPoint2.setSpeed(102);
point = fillDataPointTestHelper(sensorDataSetLocation2); point = chartFragment.createPendingPoint(trackPoint2);
Assert.assertEquals(102.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI, point[ChartView.SPEED_SERIES + 1], 0.01); Assert.assertEquals(102.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI, point[ChartView.SPEED_SERIES + 1], 0.01);
} }
@@ -300,25 +296,24 @@ public class ChartFragmentTest {
* Tests the logic to get pace value when reportSpeed is false. * Tests the logic to get pace value when reportSpeed is false.
*/ */
@Test @Test
public void testFillDataPoint_pace_nonZeroSpeed() { public void testCreatePendingPoint_pace_nonZeroSpeed() {
// Setups reportSpeed to false.
chartFragment.setReportSpeed(false); chartFragment.setReportSpeed(false);
// First data point is not added to the speed buffer // First data point is not added to the speed buffer
TrackPoint sensorDataSetLocation1 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation1.setSpeed(100.0f); trackPoint1.setSpeed(100.0f);
double[] point = fillDataPointTestHelper(sensorDataSetLocation1); double[] point = chartFragment.createPendingPoint(trackPoint1);
Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01); Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01);
TrackPoint sensorDataSetLocation2 = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
/* /*
* Add a time span here to make sure the second point and the speed is valid. * Add a time span here to make sure the second point and the speed is valid.
* Speed is valid if: speedDifference > Constants.MAX_ACCELERATION * timeDifference speedDifference = 102 -100 timeDifference = 222 * Speed is valid if: speedDifference > Constants.MAX_ACCELERATION * timeDifference speedDifference = 102 -100 timeDifference = 222
*/ */
sensorDataSetLocation2.setTime(sensorDataSetLocation2.getTime() + 222); trackPoint2.setTime(trackPoint2.getTime() + 222);
sensorDataSetLocation2.setSpeed(102); trackPoint2.setSpeed(102);
point = fillDataPointTestHelper(sensorDataSetLocation2); point = chartFragment.createPendingPoint(trackPoint2);
Assert.assertEquals(HOURS_PER_UNIT / (102.0 * UnitConversions.MS_TO_KMH), point[ChartView.PACE_SERIES + 1], 0.01); Assert.assertEquals(HOURS_PER_UNIT / (102.0 * UnitConversions.MS_TO_KMH), point[ChartView.PACE_SERIES + 1], 0.01);
} }
@@ -326,24 +321,11 @@ public class ChartFragmentTest {
* Tests the logic to get pace value when reportSpeed is false and average speed is zero. * Tests the logic to get pace value when reportSpeed is false and average speed is zero.
*/ */
@Test @Test
public void testFillDataPoint_pace_zeroSpeed() { public void testCreatePendingPoint_pace_zeroSpeed() {
// Setups reportSpeed to false.
chartFragment.setReportSpeed(false); chartFragment.setReportSpeed(false);
TrackPoint sensorDataSetLocation = TrackStubUtils.createSensorDataSetLocation(); TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
sensorDataSetLocation.setSpeed(0); trackPoint.setSpeed(0);
double[] point = fillDataPointTestHelper(sensorDataSetLocation); double[] point = chartFragment.createPendingPoint(trackPoint);
Assert.assertEquals(0.0, point[ChartView.PACE_SERIES + 1], 0.01); Assert.assertEquals(0.0, point[ChartView.PACE_SERIES + 1], 0.01);
} }
/**
* Helper method to test fillDataPoint.
*
* @param trackPoint trackPoint to fill
* @return data of this trackPoint
*/
private double[] fillDataPointTestHelper(TrackPoint trackPoint) {
double[] point = new double[ChartView.NUM_SERIES + 1];
chartFragment.fillDataPoint(trackPoint, point);
return point;
}
} }
@@ -335,7 +335,7 @@ public class ChartView extends View {
* *
* @param dataPoints an array of data points to be added * @param dataPoints an array of data points to be added
*/ */
public void addDataPoints(List<double[]> dataPoints) { public void addPendingPoints(List<double[]> dataPoints) {
synchronized (chartData) { synchronized (chartData) {
chartData.addAll(dataPoints); chartData.addAll(dataPoints);
for (double[] dataPoint : dataPoints) { for (double[] dataPoint : dataPoints) {
@@ -43,7 +43,10 @@ import de.dennisguse.opentracks.util.LocationUtils;
import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.PreferencesUtils;
/** /**
* Track data hub. Receives data from {@link de.dennisguse.opentracks.content.provider.CustomContentProvider} and distributes it to {@link TrackDataListener} after some processing. * Track data hub.
* Receives data from {@link de.dennisguse.opentracks.content.provider.CustomContentProvider} and distributes it to {@link TrackDataListener} after some processing.
*
* {@link TrackPoint}s are filtered/downsampled with a dynamic sampling frequency.
* *
* @author Rodrigo Damazio * @author Rodrigo Damazio
*/ */
@@ -377,32 +380,32 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
} }
} }
int localNumLoadedPoints = updateSamplingState ? numLoadedPoints : 0; int localNumLoadedTrackPoints = updateSamplingState ? numLoadedPoints : 0;
long localFirstSeenLocationId = updateSamplingState ? firstSeenTrackPointId : -1L; long localFirstSeenTrackPointId = updateSamplingState ? firstSeenTrackPointId : -1L;
long localLastSeenLocationId = updateSamplingState ? lastSeenTrackPointId : -1L; long localLastSeenTrackPointIdId = updateSamplingState ? lastSeenTrackPointId : -1L;
long maxPointId = updateSamplingState ? -1L : lastSeenTrackPointId; long maxPointId = updateSamplingState ? -1L : lastSeenTrackPointId;
long lastTrackPointId = contentProviderUtils.getLastTrackPointId(selectedTrackId); long lastTrackPointId = contentProviderUtils.getLastTrackPointId(selectedTrackId);
int samplingFrequency = -1; int samplingFrequency = -1;
boolean includeNextPoint = false; boolean includeNextPoint = false;
try (TrackPointIterator locationIterator = contentProviderUtils.getTrackPointLocationIterator(selectedTrackId, localLastSeenLocationId + 1, false)) { try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(selectedTrackId, localLastSeenTrackPointIdId + 1, false)) {
while (locationIterator.hasNext()) { while (trackPointIterator.hasNext()) {
TrackPoint trackPoint = locationIterator.next(); TrackPoint trackPoint = trackPointIterator.next();
long locationId = locationIterator.getTrackPointId(); long trackPointId = trackPointIterator.getTrackPointId();
// Stop if past the last wanted point // Stop if past the last wanted point
if (maxPointId != -1L && locationId > maxPointId) { if (maxPointId != -1L && trackPointId > maxPointId) {
break; break;
} }
if (localFirstSeenLocationId == -1) { if (localFirstSeenTrackPointId == -1) {
localFirstSeenLocationId = locationId; localFirstSeenTrackPointId = trackPointId;
} }
if (samplingFrequency == -1) { if (samplingFrequency == -1) {
long numTotalPoints = Math.max(0L, lastTrackPointId - localFirstSeenLocationId); long numTotalPoints = Math.max(0L, lastTrackPointId - localFirstSeenTrackPointId);
samplingFrequency = 1 + (int) (numTotalPoints / targetNumPoints); samplingFrequency = 1 + (int) (numTotalPoints / targetNumPoints);
} }
@@ -410,7 +413,7 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
includeNextPoint = true; includeNextPoint = true;
} else { } else {
// Also include the last point if the selected track is not recording. // Also include the last point if the selected track is not recording.
if (includeNextPoint || (localNumLoadedPoints % samplingFrequency == 0) || (locationId == lastTrackPointId && !isSelectedTrackRecording())) { if (includeNextPoint || (localNumLoadedTrackPoints % samplingFrequency == 0) || (trackPointId == lastTrackPointId && !isSelectedTrackRecording())) {
includeNextPoint = false; includeNextPoint = false;
for (TrackDataListener trackDataListener : sampledInListeners) { for (TrackDataListener trackDataListener : sampledInListeners) {
trackDataListener.onSampledInTrackPoint(trackPoint); trackDataListener.onSampledInTrackPoint(trackPoint);
@@ -422,15 +425,15 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
} }
} }
localNumLoadedPoints++; localNumLoadedTrackPoints++;
localLastSeenLocationId = locationId; localLastSeenTrackPointIdId = trackPointId;
} }
} }
if (updateSamplingState) { if (updateSamplingState) {
numLoadedPoints = localNumLoadedPoints; numLoadedPoints = localNumLoadedTrackPoints;
firstSeenTrackPointId = localFirstSeenLocationId; firstSeenTrackPointId = localFirstSeenTrackPointId;
lastSeenTrackPointId = localLastSeenLocationId; lastSeenTrackPointId = localLastSeenTrackPointIdId;
} }
for (TrackDataListener listener : sampledInListeners) { for (TrackDataListener listener : sampledInListeners) {
@@ -48,6 +48,7 @@ import de.dennisguse.opentracks.util.UnitConversions;
/** /**
* A fragment to display track chart to the user. * A fragment to display track chart to the user.
* ChartFragment uses a {@link TrackStatisticsUpdater} internally and recomputes the {@link TrackStatistics} from the beginning.
* *
* @author Sandor Dornbush * @author Sandor Dornbush
* @author Rodrigo Damazio * @author Rodrigo Damazio
@@ -219,23 +220,23 @@ public class ChartFragment extends Fragment implements TrackDataListener {
@Override @Override
public void onSampledInTrackPoint(TrackPoint trackPoint) { public void onSampledInTrackPoint(TrackPoint trackPoint) {
if (isResumed()) { if (isResumed()) {
double[] data = new double[ChartView.NUM_SERIES + 1]; pendingPoints.add(createPendingPoint(trackPoint));
fillDataPoint(trackPoint, data);
pendingPoints.add(data);
} }
} }
@Override @Override
public void onSampledOutTrackPoint(TrackPoint trackPoint) { public void onSampledOutTrackPoint(TrackPoint trackPoint) {
if (isResumed()) { if (isResumed()) {
fillDataPoint(trackPoint, null); if (trackStatisticsUpdater != null) {
trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
}
} }
} }
@Override @Override
public void onNewTrackPointsDone() { public void onNewTrackPointsDone() {
if (isResumed()) { if (isResumed()) {
chartView.addDataPoints(pendingPoints); chartView.addPendingPoints(pendingPoints);
pendingPoints.clear(); pendingPoints.clear();
runOnUiThread(updateChart); runOnUiThread(updateChart);
} }
@@ -346,7 +347,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
} }
/** /**
* Given a trackPoint, fill in a data point, an array of double[]. <br> * Given a {@link TrackPoint}, fill in a data point. <br>
* data[0] = time/distance <br> * data[0] = time/distance <br>
* data[1] = elevation <br> * data[1] = elevation <br>
* data[2] = speed <br> * data[2] = speed <br>
@@ -356,10 +357,9 @@ public class ChartFragment extends Fragment implements TrackDataListener {
* data[6] = power <br> * data[6] = power <br>
* *
* @param trackPoint the trackPoint * @param trackPoint the trackPoint
* @param data the data point to fill in, can be null
*/ */
@VisibleForTesting @VisibleForTesting
void fillDataPoint(@NonNull TrackPoint trackPoint, double[] data) { double[] createPendingPoint(@NonNull TrackPoint trackPoint) {
double timeOrDistance = Double.NaN; double timeOrDistance = Double.NaN;
double elevation = Double.NaN; double elevation = Double.NaN;
double speed = Double.NaN; double speed = Double.NaN;
@@ -407,15 +407,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
} }
//TODO: Is related to ChartView.ELEVATION_SERIES etc. //TODO: Is related to ChartView.ELEVATION_SERIES etc.
if (data != null) { return new double[]{timeOrDistance, elevation, speed, pace, heartRate, cadence, power};
data[0] = timeOrDistance;
data[1] = elevation;
data[2] = speed;
data[3] = pace;
data[4] = heartRate;
data[5] = cadence;
data[6] = power;
}
} }
@VisibleForTesting @VisibleForTesting