Skip to content

Commit

Permalink
Announcements: add current heartrate.
Browse files Browse the repository at this point in the history
Fixes #1635.
  • Loading branch information
dennisguse committed Dec 29, 2024
1 parent 43e1cbc commit 0e0958c
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

import java.time.Duration;
import java.time.Instant;
Expand All @@ -29,6 +30,7 @@
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.settings.UnitSystem;
import de.dennisguse.opentracks.stats.SensorStatistics;
Expand All @@ -48,6 +50,7 @@ public class VoiceAnnouncementUtilsTest {
public void setUp() {
contentProviderUtils = new ContentProviderUtils(context);

PreferencesUtils.setVoiceAnnounceHeartRateCurrent(false);
PreferencesUtils.setVoiceAnnounceLapHeartRate(false);
PreferencesUtils.setVoiceAnnounceAverageHeartRate(false);
PreferencesUtils.setVoiceAnnounceTotalDistance(true);
Expand All @@ -74,8 +77,11 @@ public void getAnnouncement_metric_speed() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, true, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 20.0 kilometers. 1 hour 5 minutes 10 seconds. Average moving speed 18.4 kilometers per hour.", announcement);
Expand All @@ -94,8 +100,11 @@ public void getAnnouncement_metric_speed_rounding_check() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, true, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 20.0 kilometers. 1 hour 1 second. Average moving speed 20.0 kilometers per hour.", announcement);
Expand All @@ -114,8 +123,11 @@ public void getAnnouncement_metric_distance_rounding_check() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, true, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 20.0 kilometers. 1 hour. Average moving speed 20.0 kilometers per hour.", announcement);
Expand All @@ -134,8 +146,11 @@ public void getAnnouncement_metric_distance_rounding_check_two() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, true, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 19.9 kilometers. 1 hour. Average moving speed 19.9 kilometers per hour.", announcement);
Expand All @@ -156,11 +171,14 @@ public void getAnnouncement_withInterval_metric_speed() {
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
}

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

Track track = new Track();
track.setTrackStatistics(stats);

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, true, lastInterval, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, lastInterval, null).toString();

// then
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Average moving speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour.", announcement);
Expand All @@ -179,8 +197,11 @@ public void getAnnouncement_metric_pace() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, false, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, false, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 20.0 kilometers. 1 hour 5 minutes 10 seconds. Pace 3 minutes 15 seconds per kilometer.", announcement);
Expand All @@ -204,8 +225,11 @@ public void getAnnouncement_withInterval_metric_pace() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, false, lastInterval, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, false, lastInterval, null).toString();

// then
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Pace 1 minute 10 seconds per kilometer. Lap time 1 minute 10 seconds per kilometer.", announcement);
Expand All @@ -224,8 +248,11 @@ public void getAnnouncement_imperial_speed() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.IMPERIAL_FEET, true, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, true, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Average moving speed 11.4 miles per hour.", announcement);
Expand All @@ -242,8 +269,11 @@ public void getAnnouncement_imperial_speed_1() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.IMPERIAL_FEET, true, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, true, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 1.1 miles. 1 hour. Average moving speed 1.1 miles per hour.", announcement);
Expand All @@ -260,8 +290,11 @@ public void getAnnouncement_imperial_meter_speed_1() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.IMPERIAL_METER, true, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_METER, true, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 1.1 miles. 1 hour. Average moving speed 1.1 miles per hour.", announcement);
Expand All @@ -278,8 +311,11 @@ public void getAnnouncement_metric_speed_1() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, true, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 1.1 kilometers. 1 hour. Average moving speed 1.1 kilometers per hour.", announcement);
Expand All @@ -303,8 +339,11 @@ public void getAnnouncement_withInterval_imperial_speed() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.IMPERIAL_FEET, true, lastInterval, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, true, lastInterval, null).toString();

// then
assertEquals("12:16 AM. Total distance 8.8 miles. 16 minutes 39 seconds. Average moving speed 31.8 miles per hour. Lap speed 31.8 miles per hour.", announcement);
Expand All @@ -323,8 +362,11 @@ public void getAnnouncement_imperial_pace() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.IMPERIAL_FEET, false, null, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, false, null, null).toString();

// then
assertEquals("12:00 AM. Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Pace 5 minutes 15 seconds per mile.", announcement);
Expand All @@ -348,8 +390,11 @@ public void getAnnouncement_withInterval_imperial_pace() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.IMPERIAL_FEET, false, lastInterval, null).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, false, lastInterval, null).toString();

// then
assertEquals("12:16 AM. Total distance 8.8 miles. 16 minutes 39 seconds. Pace 1 minute 53 seconds per mile. Lap time 1 minute 53 seconds per mile.", announcement);
Expand Down Expand Up @@ -377,17 +422,22 @@ public void getAnnouncement_heart_rate_and_sensor_statistics() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();

// then
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Average moving speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour. Average heart rate 180 bpm. Current heart rate 133 bpm.", announcement);
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Average moving speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour. Average heart rate 180 bpm. Lap heart rate 133 bpm.", announcement);
}

@Test
public void getAnnouncement_only_lap_heart_rate() {
public void getAnnouncement_heart_rate() {
PreferencesUtils.setVoiceAnnounceHeartRateCurrent(true);
PreferencesUtils.setVoiceAnnounceLapHeartRate(true);
PreferencesUtils.setVoiceAnnounceAverageHeartRate(false);
PreferencesUtils.setVoiceAnnounceAverageHeartRate(true);

PreferencesUtils.setVoiceAnnounceTotalDistance(false);
PreferencesUtils.setVoiceAnnounceMovingTime(false);
PreferencesUtils.setVoiceAnnounceAverageSpeedPace(false);
Expand All @@ -410,11 +460,14 @@ public void getAnnouncement_only_lap_heart_rate() {
Track track = new Track();
track.setTrackStatistics(stats);

SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));

// when
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();

// then
assertEquals("12:16 AM. Current heart rate 133 bpm.", announcement);
assertEquals("12:16 AM. Current heart rate 60 bpm. Average heart rate 180 bpm. Lap heart rate 133 bpm.", announcement);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
import de.dennisguse.opentracks.settings.PreferencesUtils;

public final class SensorDataSet {
public class SensorDataSet {

private static final String TAG = SensorDataSet.class.getSimpleName();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ private void updateRecordingDataWhileRecording() {
// Compute temporary track statistics using sensorData and update time.
Pair<Track, Pair<TrackPoint, SensorDataSet>> data = trackRecordingManager.getDataForUI();

voiceAnnouncementManager.announceStatisticsIfNeeded(data.first);
voiceAnnouncementManager.announceStatisticsIfNeeded(data.first, data.second.second);

recordingDataObservable.postValue(new RecordingData(data.first, data.second.first, data.second.second));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.stats.SensorStatistics;
import de.dennisguse.opentracks.stats.TrackStatistics;
Expand Down Expand Up @@ -118,7 +119,7 @@ public void announceIdle() {
voiceAnnouncement.speak(VoiceAnnouncementUtils.createIdle(context));
}

public void announceStatisticsIfNeeded(@NonNull Track track) {
public void announceStatisticsIfNeeded(@NonNull Track track, @NonNull SensorDataSet sensorDataSet) {
if (shouldNotAnnounce()) {
return;
}
Expand All @@ -135,11 +136,11 @@ public void announceStatisticsIfNeeded(@NonNull Track track) {
}

if (announce) {
voiceAnnouncement.speak(createAnnouncement(track));
voiceAnnouncement.speak(createAnnouncement(track, sensorDataSet));
}
}

private Spannable createAnnouncement(Track track) {
private Spannable createAnnouncement(Track track, SensorDataSet sensorDataSet) {
Distance currentIntervalDistance = PreferencesUtils.getVoiceAnnouncementDistance();
if (currentIntervalDistance != intervalDistance) {
intervalStatistics = new IntervalStatistics(currentIntervalDistance);
Expand All @@ -155,7 +156,7 @@ private Spannable createAnnouncement(Track track) {
sensorStatistics = contentProviderUtils.getSensorStats(track.getId());
}

return VoiceAnnouncementUtils.createStatistics(context, track, PreferencesUtils.getUnitSystem(), PreferencesUtils.isReportSpeed(track), lastInterval, sensorStatistics);
return VoiceAnnouncementUtils.createStatistics(context, track, sensorDataSet, PreferencesUtils.getUnitSystem(), PreferencesUtils.isReportSpeed(track), lastInterval, sensorStatistics);
}

public void stop() {
Expand Down
Loading

0 comments on commit 0e0958c

Please sign in to comment.