From a2a387ed012e1ba5887ec3dde8a7d421056cc6d4 Mon Sep 17 00:00:00 2001 From: Cameron Mace Date: Tue, 27 Jun 2017 10:29:08 -0400 Subject: [PATCH 01/10] initial instruction setup --- .../navigation/v5/instruction/DefaultInstruction.java | 10 ++++++++++ .../navigation/v5/instruction/Instruction.java | 11 +++++++++++ .../navigation/v5/instruction/package-info.java | 4 ++++ 3 files changed, 25 insertions(+) create mode 100644 navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java create mode 100644 navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java create mode 100644 navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/package-info.java diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java new file mode 100644 index 00000000000..b6b44dee11d --- /dev/null +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java @@ -0,0 +1,10 @@ +package com.mapbox.services.android.navigation.v5.instruction; + +import com.mapbox.services.android.navigation.v5.RouteProgress; + +public class DefaultInstruction extends Instruction { + + DefaultInstruction(RouteProgress routeProgress) { + super(routeProgress); + } +} diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java new file mode 100644 index 00000000000..1eaac0bd506 --- /dev/null +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java @@ -0,0 +1,11 @@ +package com.mapbox.services.android.navigation.v5.instruction; + +import com.mapbox.services.android.navigation.v5.RouteProgress; + +public abstract class Instruction { + + Instruction(RouteProgress routeProgress) { + + } + +} diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/package-info.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/package-info.java new file mode 100644 index 00000000000..f3904b84ed8 --- /dev/null +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains instruction logic for providing turn by turn navigation instructions. + */ +package com.mapbox.services.android.navigation.v5.instruction; \ No newline at end of file From 082006b0dd2e3d0fdd809d7f15c49fdbb9b3d3ce Mon Sep 17 00:00:00 2001 From: danesfeder Date: Tue, 27 Jun 2017 11:49:43 -0400 Subject: [PATCH 02/10] Setup for DefaultInstruction class and String instruction creation - passing to MilestoneEventListeners for possible voicing on client side --- .../navigation/v5/NavigationEngine.java | 7 +- .../v5/instruction/DefaultInstruction.java | 16 ++- .../v5/instruction/Instruction.java | 1 + .../v5/instruction/InstructionEngine.java | 112 ++++++++++++++++++ .../navigation/v5/instruction/LengthUnit.java | 97 +++++++++++++++ 5 files changed, 229 insertions(+), 4 deletions(-) create mode 100644 navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/InstructionEngine.java create mode 100644 navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/LengthUnit.java diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/NavigationEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/NavigationEngine.java index db709a28fd0..97e57657e67 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/NavigationEngine.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/NavigationEngine.java @@ -6,6 +6,7 @@ import android.text.TextUtils; import com.mapbox.services.Constants; +import com.mapbox.services.android.navigation.v5.instruction.DefaultInstruction; import com.mapbox.services.android.navigation.v5.listeners.OffRouteListener; import com.mapbox.services.android.navigation.v5.listeners.ProgressChangeListener; import com.mapbox.services.android.navigation.v5.milestone.Milestone; @@ -31,8 +32,6 @@ */ class NavigationEngine { - private static final String INSTRUCTION_STRING = "instruction"; - // Listeners private CopyOnWriteArrayList progressChangeListeners; private CopyOnWriteArrayList offRouteListeners; @@ -105,7 +104,9 @@ && calculateSnappedDistanceToNextStep(location, previousRouteProgress) < options for (Milestone milestone : milestones) { if (milestone.isOccurring(previousRouteProgress, routeProgress)) { for (MilestoneEventListener listener : milestoneEventListeners) { - listener.onMilestoneEvent(routeProgress, INSTRUCTION_STRING, milestone.getIdentifier()); + // Create a new DefaultInstruction based on the current RouteProgress and Milestone identifier + DefaultInstruction instruction = new DefaultInstruction(routeProgress, milestone.getIdentifier()); + listener.onMilestoneEvent(routeProgress, instruction.getInstruction(), milestone.getIdentifier()); } } } diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java index b6b44dee11d..d6702cb848d 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java @@ -4,7 +4,21 @@ public class DefaultInstruction extends Instruction { - DefaultInstruction(RouteProgress routeProgress) { + private InstructionEngine instructionEngine; + private String instruction; + + public DefaultInstruction(RouteProgress routeProgress, int identifier) { super(routeProgress); + instructionEngine = new InstructionEngine(); + instruction = createInstruction(routeProgress, identifier); + } + + @Override + public String getInstruction() { + return instruction; + } + + private String createInstruction(RouteProgress routeProgress, int identifier) { + return instructionEngine.get(identifier).build(routeProgress); } } diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java index 1eaac0bd506..5a560768b32 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java @@ -8,4 +8,5 @@ public abstract class Instruction { } + public abstract String getInstruction(); } diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/InstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/InstructionEngine.java new file mode 100644 index 00000000000..79fedbdf60d --- /dev/null +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/InstructionEngine.java @@ -0,0 +1,112 @@ +package com.mapbox.services.android.navigation.v5.instruction; + +import android.text.TextUtils; + +import com.mapbox.services.android.navigation.v5.NavigationConstants; +import com.mapbox.services.android.navigation.v5.RouteProgress; + +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.Locale; + +import timber.log.Timber; + +class InstructionEngine extends HashMap { + + private static final String DECIMAL_FORMAT = "###.#"; + private static final String MILES_STRING_FORMAT = "%s Miles"; + private static final String FEET_STRING_FORMAT = "%s Feet"; + private static final String IN_STRING_FORMAT = "In %s %s"; + + InstructionEngine() { + this.put(NavigationConstants.DEPARTURE_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + getDepartureInstruction(); + return null; + } + }); + this.put(NavigationConstants.NEW_STEP_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + getNewStepInstruction(); + return null; + } + }); + this.put(NavigationConstants.IMMINENT_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + getImminentInstruction(); + return null; + } + }); + this.put(NavigationConstants.URGENT_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + getUrgentInstruction(); + return null; + } + }); + this.put(NavigationConstants.ARRIVAL_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + getArrivalInstruction(routeProgress); + return null; + } + }); + } + + private void getDepartureInstruction() { + Timber.d("Departing"); + } + + private void getNewStepInstruction() { + Timber.d("New Step"); + } + + private void getImminentInstruction() { + Timber.d("Imminent"); + } + + private void getUrgentInstruction() { + Timber.d("Urgent"); + } + + private String getArrivalInstruction(RouteProgress progress) { + String instruction = progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); + if (!TextUtils.isEmpty(instruction)) { + return instruction; + } else { + return getDefaultInstruction(progress); + } + } + + private String getDefaultInstruction(RouteProgress progress) { + double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); + return String.format( + Locale.US, + IN_STRING_FORMAT, + distanceFormatter(userDistance), + progress.getCurrentLegProgress().getCurrentStep().getManeuver().getInstruction() + ); + } + + private static String distanceFormatter(double distance) { + String formattedString; + if (LengthUnit.convert(LengthUnit.Unit.METERS, LengthUnit.Unit.FEET, distance) > 1999) { + distance = LengthUnit.convert(LengthUnit.Unit.METERS, LengthUnit.Unit.MILES, distance); + DecimalFormat df = new DecimalFormat(DECIMAL_FORMAT); + double roundedNumber = (distance / 100 * 100); + formattedString = String.format(Locale.US, MILES_STRING_FORMAT, df.format(roundedNumber)); + } else { + distance = LengthUnit.convert(LengthUnit.Unit.METERS, LengthUnit.Unit.FEET, distance); + int roundedNumber = ((int) Math.round(distance)) / 100 * 100; + formattedString = String.format(Locale.US, FEET_STRING_FORMAT, roundedNumber); + } + return formattedString; + } + + interface InstructionBuilder { + String build(RouteProgress routeProgress); + } +} diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/LengthUnit.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/LengthUnit.java new file mode 100644 index 00000000000..099ecda6163 --- /dev/null +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/LengthUnit.java @@ -0,0 +1,97 @@ +package com.mapbox.services.android.navigation.v5.instruction; + +public class LengthUnit { + + public static double convert(String originalUnit, String newUnit, double input) { + double output = 0.0d; + + originalUnit = originalUnit.toLowerCase(); + newUnit = newUnit.toLowerCase(); + + switch (originalUnit) { + case "feet": + switch (newUnit) { + case "feet": + output = input; + break; + case "miles": + output = input / 5280.0d; + break; + case "meters": + output = input * 0.3048d; + break; + case "kilometers": + output = input * 0.0003048d; + break; + default: + break; + } + break; + case "miles": + switch (newUnit) { + case "feet": + output = input * 5280.0d; + break; + case "miles": + output = input; + break; + case "meters": + output = input * 1609.34d; + break; + case "kilometers": + output = input * 1.60934d; + break; + default: + break; + } + break; + case "meters": + switch (newUnit) { + case "feet": + output = input * 3.28084d; + break; + case "miles": + output = input / 1609.34d; + break; + case "meters": + output = input; + break; + case "kilometers": + // TODO + break; + default: + break; + } + break; + case "kilometers": + switch (newUnit) { + case "feet": + output = input * 3280.84d; + break; + case "miles": + output = input / 1.60934d; + break; + case "meters": + //TODO + break; + case "kilometers": + output = input; + break; + default: + break; + } + break; + default: + break; + } + + return output; + } + + public static class Unit { + public static final String METERS = "meters"; + public static final String KILOMETERS = "kilometers"; + public static final String FEET = "feet"; + public static final String MILES = "miles"; + } +} From 2f10359aae544fe3d15e457dd454658583008b89 Mon Sep 17 00:00:00 2001 From: danesfeder Date: Tue, 27 Jun 2017 13:21:11 -0400 Subject: [PATCH 03/10] Add instruction builders for each default milestone - Fix issues per Cam code review --- .../navigation/v5/NavigationEngine.java | 3 +- .../v5/instruction/DefaultInstruction.java | 8 +- .../instruction/DefaultInstructionEngine.java | 144 ++++++++++++++++++ .../v5/instruction/Instruction.java | 3 +- .../v5/instruction/InstructionEngine.java | 112 -------------- .../navigation/v5/instruction/LengthUnit.java | 97 ------------ 6 files changed, 151 insertions(+), 216 deletions(-) create mode 100644 navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java delete mode 100644 navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/InstructionEngine.java delete mode 100644 navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/LengthUnit.java diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/NavigationEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/NavigationEngine.java index 97e57657e67..3b020cc47af 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/NavigationEngine.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/NavigationEngine.java @@ -7,6 +7,7 @@ import com.mapbox.services.Constants; import com.mapbox.services.android.navigation.v5.instruction.DefaultInstruction; +import com.mapbox.services.android.navigation.v5.instruction.Instruction; import com.mapbox.services.android.navigation.v5.listeners.OffRouteListener; import com.mapbox.services.android.navigation.v5.listeners.ProgressChangeListener; import com.mapbox.services.android.navigation.v5.milestone.Milestone; @@ -105,7 +106,7 @@ && calculateSnappedDistanceToNextStep(location, previousRouteProgress) < options if (milestone.isOccurring(previousRouteProgress, routeProgress)) { for (MilestoneEventListener listener : milestoneEventListeners) { // Create a new DefaultInstruction based on the current RouteProgress and Milestone identifier - DefaultInstruction instruction = new DefaultInstruction(routeProgress, milestone.getIdentifier()); + Instruction instruction = new DefaultInstruction(routeProgress, milestone.getIdentifier()); listener.onMilestoneEvent(routeProgress, instruction.getInstruction(), milestone.getIdentifier()); } } diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java index d6702cb848d..f6688394bfd 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java @@ -4,12 +4,12 @@ public class DefaultInstruction extends Instruction { - private InstructionEngine instructionEngine; + private DefaultInstructionEngine defaultInstructionEngine; private String instruction; public DefaultInstruction(RouteProgress routeProgress, int identifier) { - super(routeProgress); - instructionEngine = new InstructionEngine(); + super(routeProgress, identifier); + defaultInstructionEngine = new DefaultInstructionEngine(); instruction = createInstruction(routeProgress, identifier); } @@ -19,6 +19,6 @@ public String getInstruction() { } private String createInstruction(RouteProgress routeProgress, int identifier) { - return instructionEngine.get(identifier).build(routeProgress); + return defaultInstructionEngine.get(identifier).build(routeProgress); } } diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java new file mode 100644 index 00000000000..b47a6e203c6 --- /dev/null +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java @@ -0,0 +1,144 @@ +package com.mapbox.services.android.navigation.v5.instruction; + +import android.text.TextUtils; +import android.util.SparseArray; + +import com.mapbox.services.android.navigation.v5.NavigationConstants; +import com.mapbox.services.android.navigation.v5.RouteProgress; +import com.mapbox.services.api.utils.turf.TurfConstants; +import com.mapbox.services.api.utils.turf.TurfHelpers; + +import java.text.DecimalFormat; +import java.util.Locale; + +class DefaultInstructionEngine extends SparseArray { + + private static final String DECIMAL_FORMAT = "###.#"; + private static final String MILES_STRING_FORMAT = "%s Miles"; + private static final String FEET_STRING_FORMAT = "%s Feet"; + private static final String IN_STRING_FORMAT = "In %s %s"; + private static final String THEN_STRING_FORMAT = "%s then %s"; + private static final String CONTINUE_STRING_FORMAT = "Continue on %s for %s"; + + DefaultInstructionEngine() { + initDefaultBuilders(); + } + + private void initDefaultBuilders() { + this.put(NavigationConstants.DEPARTURE_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + buildDepartureInstruction(routeProgress); + return null; + } + }); + this.put(NavigationConstants.NEW_STEP_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + buildNewStepInstruction(routeProgress); + return null; + } + }); + this.put(NavigationConstants.IMMINENT_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + buildImminentInstruction(routeProgress); + return null; + } + }); + this.put(NavigationConstants.URGENT_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + buildUrgentInstruction(routeProgress); + return null; + } + }); + this.put(NavigationConstants.ARRIVAL_MILESTONE, new InstructionBuilder() { + @Override + public String build(RouteProgress routeProgress) { + return buildArrivalInstruction(routeProgress); + } + }); + } + + private String buildDepartureInstruction(RouteProgress progress) { + return buildContinueFormatInstruction(progress); + } + + private String buildNewStepInstruction(RouteProgress progress) { + return buildDefaultFormatInstruction(progress); + } + + private String buildImminentInstruction(RouteProgress progress) { + return buildContinueFormatInstruction(progress); + } + + private String buildUrgentInstruction(RouteProgress progress) { + String urgentInstruction = buildThenFormatInstruction(progress); + + if (!TextUtils.isEmpty(urgentInstruction)) { + return urgentInstruction; + } else { + return buildDefaultFormatInstruction(progress); + } + } + + private String buildArrivalInstruction(RouteProgress progress) { + String instruction = progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); + if (!TextUtils.isEmpty(instruction)) { + return instruction; + } else { + return buildDefaultFormatInstruction(progress); + } + } + + private String buildContinueFormatInstruction(RouteProgress progress) { + double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); + return String.format( + Locale.US, + CONTINUE_STRING_FORMAT, + progress.getCurrentLegProgress().getCurrentStep().getName(), + distanceFormatter(userDistance)); + } + + private String buildDefaultFormatInstruction(RouteProgress progress) { + double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); + return String.format( + Locale.US, + IN_STRING_FORMAT, + distanceFormatter(userDistance), + progress.getCurrentLegProgress().getCurrentStep().getManeuver().getInstruction() + ); + } + + private String buildThenFormatInstruction(RouteProgress progress) { + int legIndex = progress.getLegIndex(); + int followUpStepIndex = progress.getCurrentLegProgress().getStepIndex() + 2; + + return String.format( + Locale.US, + THEN_STRING_FORMAT, + progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(), + progress.getRoute().getLegs().get(legIndex).getSteps().get(followUpStepIndex).getManeuver().getInstruction() + ); + } + + private static String distanceFormatter(double distance) { + String formattedString; + if (TurfHelpers.convertDistance(distance, TurfConstants.UNIT_METERS, TurfConstants.UNIT_FEET) > 1999) { + distance = TurfHelpers.convertDistance(distance, TurfConstants.UNIT_METERS, TurfConstants.UNIT_MILES); + DecimalFormat df = new DecimalFormat(DECIMAL_FORMAT); + double roundedNumber = (distance / 100 * 100); + formattedString = String.format(Locale.US, MILES_STRING_FORMAT, df.format(roundedNumber)); + } else { + distance = TurfHelpers.convertDistance(distance, TurfConstants.UNIT_METERS, TurfConstants.UNIT_FEET); + int roundedNumber = ((int) Math.round(distance)) / 100 * 100; + formattedString = String.format(Locale.US, FEET_STRING_FORMAT, roundedNumber); + } + return formattedString; + } + + interface InstructionBuilder { + String build(RouteProgress routeProgress); + } +} diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java index 5a560768b32..bd9cb367ac0 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java @@ -4,8 +4,7 @@ public abstract class Instruction { - Instruction(RouteProgress routeProgress) { - + Instruction(RouteProgress routeProgress, int identifier) { } public abstract String getInstruction(); diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/InstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/InstructionEngine.java deleted file mode 100644 index 79fedbdf60d..00000000000 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/InstructionEngine.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.mapbox.services.android.navigation.v5.instruction; - -import android.text.TextUtils; - -import com.mapbox.services.android.navigation.v5.NavigationConstants; -import com.mapbox.services.android.navigation.v5.RouteProgress; - -import java.text.DecimalFormat; -import java.util.HashMap; -import java.util.Locale; - -import timber.log.Timber; - -class InstructionEngine extends HashMap { - - private static final String DECIMAL_FORMAT = "###.#"; - private static final String MILES_STRING_FORMAT = "%s Miles"; - private static final String FEET_STRING_FORMAT = "%s Feet"; - private static final String IN_STRING_FORMAT = "In %s %s"; - - InstructionEngine() { - this.put(NavigationConstants.DEPARTURE_MILESTONE, new InstructionBuilder() { - @Override - public String build(RouteProgress routeProgress) { - getDepartureInstruction(); - return null; - } - }); - this.put(NavigationConstants.NEW_STEP_MILESTONE, new InstructionBuilder() { - @Override - public String build(RouteProgress routeProgress) { - getNewStepInstruction(); - return null; - } - }); - this.put(NavigationConstants.IMMINENT_MILESTONE, new InstructionBuilder() { - @Override - public String build(RouteProgress routeProgress) { - getImminentInstruction(); - return null; - } - }); - this.put(NavigationConstants.URGENT_MILESTONE, new InstructionBuilder() { - @Override - public String build(RouteProgress routeProgress) { - getUrgentInstruction(); - return null; - } - }); - this.put(NavigationConstants.ARRIVAL_MILESTONE, new InstructionBuilder() { - @Override - public String build(RouteProgress routeProgress) { - getArrivalInstruction(routeProgress); - return null; - } - }); - } - - private void getDepartureInstruction() { - Timber.d("Departing"); - } - - private void getNewStepInstruction() { - Timber.d("New Step"); - } - - private void getImminentInstruction() { - Timber.d("Imminent"); - } - - private void getUrgentInstruction() { - Timber.d("Urgent"); - } - - private String getArrivalInstruction(RouteProgress progress) { - String instruction = progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); - if (!TextUtils.isEmpty(instruction)) { - return instruction; - } else { - return getDefaultInstruction(progress); - } - } - - private String getDefaultInstruction(RouteProgress progress) { - double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); - return String.format( - Locale.US, - IN_STRING_FORMAT, - distanceFormatter(userDistance), - progress.getCurrentLegProgress().getCurrentStep().getManeuver().getInstruction() - ); - } - - private static String distanceFormatter(double distance) { - String formattedString; - if (LengthUnit.convert(LengthUnit.Unit.METERS, LengthUnit.Unit.FEET, distance) > 1999) { - distance = LengthUnit.convert(LengthUnit.Unit.METERS, LengthUnit.Unit.MILES, distance); - DecimalFormat df = new DecimalFormat(DECIMAL_FORMAT); - double roundedNumber = (distance / 100 * 100); - formattedString = String.format(Locale.US, MILES_STRING_FORMAT, df.format(roundedNumber)); - } else { - distance = LengthUnit.convert(LengthUnit.Unit.METERS, LengthUnit.Unit.FEET, distance); - int roundedNumber = ((int) Math.round(distance)) / 100 * 100; - formattedString = String.format(Locale.US, FEET_STRING_FORMAT, roundedNumber); - } - return formattedString; - } - - interface InstructionBuilder { - String build(RouteProgress routeProgress); - } -} diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/LengthUnit.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/LengthUnit.java deleted file mode 100644 index 099ecda6163..00000000000 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/LengthUnit.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.mapbox.services.android.navigation.v5.instruction; - -public class LengthUnit { - - public static double convert(String originalUnit, String newUnit, double input) { - double output = 0.0d; - - originalUnit = originalUnit.toLowerCase(); - newUnit = newUnit.toLowerCase(); - - switch (originalUnit) { - case "feet": - switch (newUnit) { - case "feet": - output = input; - break; - case "miles": - output = input / 5280.0d; - break; - case "meters": - output = input * 0.3048d; - break; - case "kilometers": - output = input * 0.0003048d; - break; - default: - break; - } - break; - case "miles": - switch (newUnit) { - case "feet": - output = input * 5280.0d; - break; - case "miles": - output = input; - break; - case "meters": - output = input * 1609.34d; - break; - case "kilometers": - output = input * 1.60934d; - break; - default: - break; - } - break; - case "meters": - switch (newUnit) { - case "feet": - output = input * 3.28084d; - break; - case "miles": - output = input / 1609.34d; - break; - case "meters": - output = input; - break; - case "kilometers": - // TODO - break; - default: - break; - } - break; - case "kilometers": - switch (newUnit) { - case "feet": - output = input * 3280.84d; - break; - case "miles": - output = input / 1.60934d; - break; - case "meters": - //TODO - break; - case "kilometers": - output = input; - break; - default: - break; - } - break; - default: - break; - } - - return output; - } - - public static class Unit { - public static final String METERS = "meters"; - public static final String KILOMETERS = "kilometers"; - public static final String FEET = "feet"; - public static final String MILES = "miles"; - } -} From 30f63a29a836b49268971019ae34a31b8df3b28f Mon Sep 17 00:00:00 2001 From: danesfeder Date: Tue, 27 Jun 2017 14:12:59 -0400 Subject: [PATCH 04/10] Check upcoming step distance when building departure instruction --- .../instruction/DefaultInstructionEngine.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java index b47a6e203c6..ea712b01e5b 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java @@ -5,6 +5,7 @@ import com.mapbox.services.android.navigation.v5.NavigationConstants; import com.mapbox.services.android.navigation.v5.RouteProgress; +import com.mapbox.services.api.directions.v5.models.StepManeuver; import com.mapbox.services.api.utils.turf.TurfConstants; import com.mapbox.services.api.utils.turf.TurfHelpers; @@ -13,11 +14,13 @@ class DefaultInstructionEngine extends SparseArray { + private static final double MINIMUM_UPCOMING_STEP_DISTANCE = 15d; private static final String DECIMAL_FORMAT = "###.#"; private static final String MILES_STRING_FORMAT = "%s Miles"; private static final String FEET_STRING_FORMAT = "%s Feet"; private static final String IN_STRING_FORMAT = "In %s %s"; private static final String THEN_STRING_FORMAT = "%s then %s"; + private static final String THEN_IN_STRING_FORMAT = "%s then in %s %s"; private static final String CONTINUE_STRING_FORMAT = "Continue on %s for %s"; DefaultInstructionEngine() { @@ -62,7 +65,11 @@ public String build(RouteProgress routeProgress) { } private String buildDepartureInstruction(RouteProgress progress) { - return buildContinueFormatInstruction(progress); + if (progress.getCurrentLegProgress().getUpComingStep().getDistance() > MINIMUM_UPCOMING_STEP_DISTANCE) { + return buildContinueFormatInstruction(progress); + } else { + return buildThenInFormatInstruction(progress); + } } private String buildNewStepInstruction(RouteProgress progress) { @@ -111,6 +118,18 @@ private String buildDefaultFormatInstruction(RouteProgress progress) { ); } + private String buildThenInFormatInstruction(RouteProgress progress) { + double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); + StepManeuver currentStepManeuver = progress.getCurrentLegProgress().getCurrentStep().getManeuver(); + return String.format( + Locale.US, + THEN_IN_STRING_FORMAT, + currentStepManeuver.getInstruction(), + distanceFormatter(userDistance), + progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction() + ); + } + private String buildThenFormatInstruction(RouteProgress progress) { int legIndex = progress.getLegIndex(); int followUpStepIndex = progress.getCurrentLegProgress().getStepIndex() + 2; From 1dd077428d8f1511678d0bf22179c58e802fc10f Mon Sep 17 00:00:00 2001 From: danesfeder Date: Tue, 27 Jun 2017 15:56:33 -0400 Subject: [PATCH 05/10] Improve logic for return strings based on current step --- .../v5/instruction/DefaultInstruction.java | 8 ++- .../instruction/DefaultInstructionEngine.java | 51 ++++++++++--------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java index f6688394bfd..9800728dde3 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java @@ -4,6 +4,8 @@ public class DefaultInstruction extends Instruction { + private static final String EMPTY_STRING = ""; + private DefaultInstructionEngine defaultInstructionEngine; private String instruction; @@ -19,6 +21,10 @@ public String getInstruction() { } private String createInstruction(RouteProgress routeProgress, int identifier) { - return defaultInstructionEngine.get(identifier).build(routeProgress); + if (defaultInstructionEngine.get(identifier) != null) { + return defaultInstructionEngine.get(identifier).build(routeProgress); + } else { + return EMPTY_STRING; + } } } diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java index ea712b01e5b..238955b0f25 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java @@ -16,8 +16,8 @@ class DefaultInstructionEngine extends SparseArray MINIMUM_UPCOMING_STEP_DISTANCE) { + return buildThenFormatInstruction(progress); } else { - return buildDefaultFormatInstruction(progress); + return progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); } } private String buildArrivalInstruction(RouteProgress progress) { - String instruction = progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); - if (!TextUtils.isEmpty(instruction)) { - return instruction; + if (progress.getCurrentLegProgress().getUpComingStep() != null) { + String instruction = progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); + if (!TextUtils.isEmpty(instruction)) { + return instruction; + } } else { - return buildDefaultFormatInstruction(progress); + return progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); } + return ""; } private String buildContinueFormatInstruction(RouteProgress progress) { @@ -114,7 +111,8 @@ private String buildDefaultFormatInstruction(RouteProgress progress) { Locale.US, IN_STRING_FORMAT, distanceFormatter(userDistance), - progress.getCurrentLegProgress().getCurrentStep().getManeuver().getInstruction() + convertFirstCharLowercase(progress.getCurrentLegProgress() + .getCurrentStep().getManeuver().getInstruction()) ); } @@ -126,25 +124,30 @@ private String buildThenInFormatInstruction(RouteProgress progress) { THEN_IN_STRING_FORMAT, currentStepManeuver.getInstruction(), distanceFormatter(userDistance), - progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction() + convertFirstCharLowercase(progress.getCurrentLegProgress() + .getUpComingStep().getManeuver().getInstruction()) ); } private String buildThenFormatInstruction(RouteProgress progress) { int legIndex = progress.getLegIndex(); int followUpStepIndex = progress.getCurrentLegProgress().getStepIndex() + 2; - return String.format( Locale.US, THEN_STRING_FORMAT, progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(), - progress.getRoute().getLegs().get(legIndex).getSteps().get(followUpStepIndex).getManeuver().getInstruction() + convertFirstCharLowercase(progress.getRoute().getLegs().get(legIndex) + .getSteps().get(followUpStepIndex).getManeuver().getInstruction()) ); } + private static String convertFirstCharLowercase(String instruction) { + return instruction.substring(0,1).toLowerCase() + instruction.substring(1); + } + private static String distanceFormatter(double distance) { String formattedString; - if (TurfHelpers.convertDistance(distance, TurfConstants.UNIT_METERS, TurfConstants.UNIT_FEET) > 1999) { + if (TurfHelpers.convertDistance(distance, TurfConstants.UNIT_METERS, TurfConstants.UNIT_FEET) > 1099) { distance = TurfHelpers.convertDistance(distance, TurfConstants.UNIT_METERS, TurfConstants.UNIT_MILES); DecimalFormat df = new DecimalFormat(DECIMAL_FORMAT); double roundedNumber = (distance / 100 * 100); From 888da4cf550150e9c855fdc634f26eab5deee4f9 Mon Sep 17 00:00:00 2001 From: danesfeder Date: Tue, 27 Jun 2017 16:01:19 -0400 Subject: [PATCH 06/10] Use current step for fallback on arrival if upcoming step is null and use upcoming step for default instruction --- .../navigation/v5/instruction/DefaultInstructionEngine.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java index 238955b0f25..b235f641be6 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java @@ -91,7 +91,7 @@ private String buildArrivalInstruction(RouteProgress progress) { return instruction; } } else { - return progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); + return progress.getCurrentLegProgress().getCurrentStep().getManeuver().getInstruction(); } return ""; } @@ -112,7 +112,7 @@ private String buildDefaultFormatInstruction(RouteProgress progress) { IN_STRING_FORMAT, distanceFormatter(userDistance), convertFirstCharLowercase(progress.getCurrentLegProgress() - .getCurrentStep().getManeuver().getInstruction()) + .getUpComingStep().getManeuver().getInstruction()) ); } From 611d73915deb6cf270bfb973382a58379c0fee13 Mon Sep 17 00:00:00 2001 From: danesfeder Date: Tue, 27 Jun 2017 17:04:46 -0400 Subject: [PATCH 07/10] Add javadoc comments --- .../instruction/DefaultInstructionEngine.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java index b235f641be6..156a5cd3ef4 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java @@ -60,6 +60,12 @@ public String build(RouteProgress routeProgress) { }); } + /** + * If the next step is greater than 15 meters long, use continue format instruction. + * Otherwise, use then in format for instruction + * @param progress {@link RouteProgress} created by the location change + * @return {@link String} to be announced on departure milestone + */ private String buildDepartureInstruction(RouteProgress progress) { if (progress.getCurrentLegProgress().getUpComingStep().getDistance() > MINIMUM_UPCOMING_STEP_DISTANCE) { return buildContinueFormatInstruction(progress); @@ -68,14 +74,29 @@ private String buildDepartureInstruction(RouteProgress progress) { } } + /** + * Create default format instruction for new step milestone + * @param progress {@link RouteProgress} created by the location change + * @return {@link String} to be announced on new step milestone + */ private String buildNewStepInstruction(RouteProgress progress) { return buildDefaultFormatInstruction(progress); } + /** + * @param progress {@link RouteProgress} created by the location change + * @return {@link String} to be announced on imminent milestone + */ private String buildImminentInstruction(RouteProgress progress) { return buildContinueFormatInstruction(progress); } + /** + * If the next step is greater than 15 meters long, use then format instruction. + * Otherwise, just use the upcoming step instruction + * @param progress {@link RouteProgress} created by the location change + * @return {@link String} to be announced on urgent milestone + */ private String buildUrgentInstruction(RouteProgress progress) { if (progress.getCurrentLegProgress().getUpComingStep().getDistance() > MINIMUM_UPCOMING_STEP_DISTANCE) { return buildThenFormatInstruction(progress); @@ -84,6 +105,12 @@ private String buildUrgentInstruction(RouteProgress progress) { } } + /** + * On arrival, use the upcoming step instruction. + * If empty, use the current step instruction as a fallback + * @param progress {@link RouteProgress} created by the location change + * @return {@link String} to be announced on departure milestone + */ private String buildArrivalInstruction(RouteProgress progress) { if (progress.getCurrentLegProgress().getUpComingStep() != null) { String instruction = progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); @@ -96,6 +123,12 @@ private String buildArrivalInstruction(RouteProgress progress) { return ""; } + /** + * Creates a {@link String} with the current step name and distance remaining + * Example: "Continue on Main St. for 3.2 miles" + * @param progress {@link RouteProgress} created by the location change + * @return {@link String} with format "Continue on %s for %s" + */ private String buildContinueFormatInstruction(RouteProgress progress) { double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); return String.format( @@ -105,6 +138,12 @@ private String buildContinueFormatInstruction(RouteProgress progress) { distanceFormatter(userDistance)); } + /** + * Creates a {@link String} with the current step distance remaining upcoming step instruction + * Example: "In 3.2 miles turn left onto Main St." + * @param progress {@link RouteProgress} created by the location change + * @return {@link String} with format "In %s %s" + */ private String buildDefaultFormatInstruction(RouteProgress progress) { double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); return String.format( @@ -116,6 +155,13 @@ private String buildDefaultFormatInstruction(RouteProgress progress) { ); } + /** + * Creates a {@link String} with the current step maneuver instruction, current step distance remaining, + * and upcoming step instruction + * Example: "Turn left onto Main St. then in 3.2 miles turn right onto Second St." + * @param progress {@link RouteProgress} created by the location change + * @return {@link String} with format "%s then in %s %s" + */ private String buildThenInFormatInstruction(RouteProgress progress) { double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); StepManeuver currentStepManeuver = progress.getCurrentLegProgress().getCurrentStep().getManeuver(); @@ -129,6 +175,12 @@ private String buildThenInFormatInstruction(RouteProgress progress) { ); } + /** + * Creates a {@link String} with the upcoming step instruction and follow up step instruction + * Example: "Turn right onto Main St. then turn left onto Second St." + * @param progress {@link RouteProgress} created by the location change + * @return {@link String} with format "%s then %s" + */ private String buildThenFormatInstruction(RouteProgress progress) { int legIndex = progress.getLegIndex(); int followUpStepIndex = progress.getCurrentLegProgress().getStepIndex() + 2; @@ -145,6 +197,11 @@ private static String convertFirstCharLowercase(String instruction) { return instruction.substring(0,1).toLowerCase() + instruction.substring(1); } + /** + * If over 1099 feet, use miles format. If less, use feet in intervals of 100 + * @param distance given distance extracted from {@link RouteProgress} + * @return {@link String} in either feet (int) or miles (decimal) format + */ private static String distanceFormatter(double distance) { String formattedString; if (TurfHelpers.convertDistance(distance, TurfConstants.UNIT_METERS, TurfConstants.UNIT_FEET) > 1099) { From bbe852d0825f1e24d9fc45b3f40033049d8b7eee Mon Sep 17 00:00:00 2001 From: danesfeder Date: Tue, 27 Jun 2017 17:30:47 -0400 Subject: [PATCH 08/10] Urgent instructions use then string format when upcoming step is less than 15 meters long --- .../navigation/v5/instruction/DefaultInstructionEngine.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java index 156a5cd3ef4..5ee61e18449 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java @@ -75,7 +75,7 @@ private String buildDepartureInstruction(RouteProgress progress) { } /** - * Create default format instruction for new step milestone + * Create default string format instruction for new step milestone * @param progress {@link RouteProgress} created by the location change * @return {@link String} to be announced on new step milestone */ @@ -92,13 +92,13 @@ private String buildImminentInstruction(RouteProgress progress) { } /** - * If the next step is greater than 15 meters long, use then format instruction. + * If the next step is less than 15 meters long, use then string format instruction. * Otherwise, just use the upcoming step instruction * @param progress {@link RouteProgress} created by the location change * @return {@link String} to be announced on urgent milestone */ private String buildUrgentInstruction(RouteProgress progress) { - if (progress.getCurrentLegProgress().getUpComingStep().getDistance() > MINIMUM_UPCOMING_STEP_DISTANCE) { + if (progress.getCurrentLegProgress().getUpComingStep().getDistance() < MINIMUM_UPCOMING_STEP_DISTANCE) { return buildThenFormatInstruction(progress); } else { return progress.getCurrentLegProgress().getUpComingStep().getManeuver().getInstruction(); From 882b4c39410effece26c372ac37b8af957306faa Mon Sep 17 00:00:00 2001 From: danesfeder Date: Wed, 28 Jun 2017 09:35:03 -0400 Subject: [PATCH 09/10] Add javadoc tags and changes per review requests --- .../v5/instruction/DefaultInstruction.java | 17 ++++++++++- .../instruction/DefaultInstructionEngine.java | 28 ++++++++++++++++--- .../v5/instruction/Instruction.java | 15 ++++++---- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java index 9800728dde3..8d2be14d990 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java @@ -9,8 +9,14 @@ public class DefaultInstruction extends Instruction { private DefaultInstructionEngine defaultInstructionEngine; private String instruction; + /** + * Uses the {@link DefaultInstructionEngine} to create an instruction based on the + * passed {@link RouteProgress} and milestone identifier + * @param routeProgress for current route data / distance + * @param identifier for what type of instruction we want to build + * @since 0.4.0 + */ public DefaultInstruction(RouteProgress routeProgress, int identifier) { - super(routeProgress, identifier); defaultInstructionEngine = new DefaultInstructionEngine(); instruction = createInstruction(routeProgress, identifier); } @@ -20,6 +26,15 @@ public String getInstruction() { return instruction; } + /** + * Provides the {@link RouteProgress} and milestone identifier to the {@link DefaultInstructionEngine} + * which returns the appropriate instruction. Will return an empty {@link String} if the + * milestone identifier provided is not one of the default identifiers + * @param routeProgress for current route data / distance + * @param identifier for what type of instruction we want to build + * @return {@link String} instruction that has been created by the engine + * @since 0.4.0 + */ private String createInstruction(RouteProgress routeProgress, int identifier) { if (defaultInstructionEngine.get(identifier) != null) { return defaultInstructionEngine.get(identifier).build(routeProgress); diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java index 5ee61e18449..25803bb1929 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java @@ -5,13 +5,18 @@ import com.mapbox.services.android.navigation.v5.NavigationConstants; import com.mapbox.services.android.navigation.v5.RouteProgress; -import com.mapbox.services.api.directions.v5.models.StepManeuver; import com.mapbox.services.api.utils.turf.TurfConstants; import com.mapbox.services.api.utils.turf.TurfHelpers; import java.text.DecimalFormat; import java.util.Locale; +/** + * Creates voice instructions based on the default milestones + * provided by {@link com.mapbox.services.android.navigation.v5.MapboxNavigation} + * + * @since 0.4.0 + */ class DefaultInstructionEngine extends SparseArray { private static final double MINIMUM_UPCOMING_STEP_DISTANCE = 15d; @@ -24,6 +29,7 @@ class DefaultInstructionEngine extends SparseArray MINIMUM_UPCOMING_STEP_DISTANCE) { @@ -78,6 +85,7 @@ private String buildDepartureInstruction(RouteProgress progress) { * Create default string format instruction for new step milestone * @param progress {@link RouteProgress} created by the location change * @return {@link String} to be announced on new step milestone + * @since 0.4.0 */ private String buildNewStepInstruction(RouteProgress progress) { return buildDefaultFormatInstruction(progress); @@ -96,6 +104,7 @@ private String buildImminentInstruction(RouteProgress progress) { * Otherwise, just use the upcoming step instruction * @param progress {@link RouteProgress} created by the location change * @return {@link String} to be announced on urgent milestone + * @since 0.4.0 */ private String buildUrgentInstruction(RouteProgress progress) { if (progress.getCurrentLegProgress().getUpComingStep().getDistance() < MINIMUM_UPCOMING_STEP_DISTANCE) { @@ -110,6 +119,7 @@ private String buildUrgentInstruction(RouteProgress progress) { * If empty, use the current step instruction as a fallback * @param progress {@link RouteProgress} created by the location change * @return {@link String} to be announced on departure milestone + * @since 0.4.0 */ private String buildArrivalInstruction(RouteProgress progress) { if (progress.getCurrentLegProgress().getUpComingStep() != null) { @@ -128,6 +138,7 @@ private String buildArrivalInstruction(RouteProgress progress) { * Example: "Continue on Main St. for 3.2 miles" * @param progress {@link RouteProgress} created by the location change * @return {@link String} with format "Continue on %s for %s" + * @since 0.4.0 */ private String buildContinueFormatInstruction(RouteProgress progress) { double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); @@ -143,6 +154,7 @@ private String buildContinueFormatInstruction(RouteProgress progress) { * Example: "In 3.2 miles turn left onto Main St." * @param progress {@link RouteProgress} created by the location change * @return {@link String} with format "In %s %s" + * @since 0.4.0 */ private String buildDefaultFormatInstruction(RouteProgress progress) { double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); @@ -161,14 +173,16 @@ private String buildDefaultFormatInstruction(RouteProgress progress) { * Example: "Turn left onto Main St. then in 3.2 miles turn right onto Second St." * @param progress {@link RouteProgress} created by the location change * @return {@link String} with format "%s then in %s %s" + * @since 0.4.0 */ private String buildThenInFormatInstruction(RouteProgress progress) { double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); - StepManeuver currentStepManeuver = progress.getCurrentLegProgress().getCurrentStep().getManeuver(); + String currentStepInstruction = progress.getCurrentLegProgress().getCurrentStep() + .getManeuver().getInstruction(); return String.format( Locale.US, THEN_IN_STRING_FORMAT, - currentStepManeuver.getInstruction(), + currentStepInstruction, distanceFormatter(userDistance), convertFirstCharLowercase(progress.getCurrentLegProgress() .getUpComingStep().getManeuver().getInstruction()) @@ -180,6 +194,7 @@ private String buildThenInFormatInstruction(RouteProgress progress) { * Example: "Turn right onto Main St. then turn left onto Second St." * @param progress {@link RouteProgress} created by the location change * @return {@link String} with format "%s then %s" + * @since 0.4.0 */ private String buildThenFormatInstruction(RouteProgress progress) { int legIndex = progress.getLegIndex(); @@ -194,13 +209,18 @@ private String buildThenFormatInstruction(RouteProgress progress) { } private static String convertFirstCharLowercase(String instruction) { - return instruction.substring(0,1).toLowerCase() + instruction.substring(1); + if (TextUtils.isEmpty(instruction)) { + return instruction; + } else { + return instruction.substring(0,1).toLowerCase() + instruction.substring(1); + } } /** * If over 1099 feet, use miles format. If less, use feet in intervals of 100 * @param distance given distance extracted from {@link RouteProgress} * @return {@link String} in either feet (int) or miles (decimal) format + * @since 0.4.0 */ private static String distanceFormatter(double distance) { String formattedString; diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java index bd9cb367ac0..2502db06d54 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java @@ -1,11 +1,16 @@ package com.mapbox.services.android.navigation.v5.instruction; -import com.mapbox.services.android.navigation.v5.RouteProgress; - +/** + * Base Instruction. Subclassed to provide concrete instructions. + * + * @since 0.4.0 + */ public abstract class Instruction { - Instruction(RouteProgress routeProgress, int identifier) { - } - + /** + * Will provide an instruction based on your specifications + * @return {@link String} instruction that will be voiced on the client + * @since 0.4.0 + */ public abstract String getInstruction(); } From 0aed2d535bf81f2fc1b5f5bd436ea26d45cff3e8 Mon Sep 17 00:00:00 2001 From: danesfeder Date: Wed, 28 Jun 2017 11:39:38 -0400 Subject: [PATCH 10/10] Clean up code / javadoc - Also include check for empty step name or rounded user distance to 0 (occurring sometimes on departure) --- .../v5/instruction/DefaultInstruction.java | 15 ++++++++--- .../instruction/DefaultInstructionEngine.java | 25 ++++++++++++++----- .../v5/instruction/Instruction.java | 1 + 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java index 8d2be14d990..3661da4bd16 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstruction.java @@ -1,7 +1,14 @@ package com.mapbox.services.android.navigation.v5.instruction; import com.mapbox.services.android.navigation.v5.RouteProgress; +import com.mapbox.services.android.navigation.v5.milestone.MilestoneEventListener; +/** + * Used to provide the {@link String} instruction in + * {@link MilestoneEventListener#onMilestoneEvent(RouteProgress, String, int)} + * + * @since 0.4.0 + */ public class DefaultInstruction extends Instruction { private static final String EMPTY_STRING = ""; @@ -10,10 +17,11 @@ public class DefaultInstruction extends Instruction { private String instruction; /** - * Uses the {@link DefaultInstructionEngine} to create an instruction based on the + * Creates a {@link DefaultInstructionEngine} to generate an instruction based on the * passed {@link RouteProgress} and milestone identifier + * * @param routeProgress for current route data / distance - * @param identifier for what type of instruction we want to build + * @param identifier for what type of instruction we want to build * @since 0.4.0 */ public DefaultInstruction(RouteProgress routeProgress, int identifier) { @@ -30,8 +38,9 @@ public String getInstruction() { * Provides the {@link RouteProgress} and milestone identifier to the {@link DefaultInstructionEngine} * which returns the appropriate instruction. Will return an empty {@link String} if the * milestone identifier provided is not one of the default identifiers + * * @param routeProgress for current route data / distance - * @param identifier for what type of instruction we want to build + * @param identifier for what type of instruction we want to build * @return {@link String} instruction that has been created by the engine * @since 0.4.0 */ diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java index 25803bb1929..b87291c3f81 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/DefaultInstructionEngine.java @@ -69,6 +69,7 @@ public String build(RouteProgress routeProgress) { /** * If the next step is greater than 15 meters long, use continue format instruction. * Otherwise, use then in format for instruction + * * @param progress {@link RouteProgress} created by the location change * @return {@link String} to be announced on departure milestone * @since 0.4.0 @@ -83,6 +84,7 @@ private String buildDepartureInstruction(RouteProgress progress) { /** * Create default string format instruction for new step milestone + * * @param progress {@link RouteProgress} created by the location change * @return {@link String} to be announced on new step milestone * @since 0.4.0 @@ -102,6 +104,7 @@ private String buildImminentInstruction(RouteProgress progress) { /** * If the next step is less than 15 meters long, use then string format instruction. * Otherwise, just use the upcoming step instruction + * * @param progress {@link RouteProgress} created by the location change * @return {@link String} to be announced on urgent milestone * @since 0.4.0 @@ -117,6 +120,7 @@ private String buildUrgentInstruction(RouteProgress progress) { /** * On arrival, use the upcoming step instruction. * If empty, use the current step instruction as a fallback + * * @param progress {@link RouteProgress} created by the location change * @return {@link String} to be announced on departure milestone * @since 0.4.0 @@ -136,22 +140,28 @@ private String buildArrivalInstruction(RouteProgress progress) { /** * Creates a {@link String} with the current step name and distance remaining * Example: "Continue on Main St. for 3.2 miles" + * * @param progress {@link RouteProgress} created by the location change * @return {@link String} with format "Continue on %s for %s" * @since 0.4.0 */ private String buildContinueFormatInstruction(RouteProgress progress) { double userDistance = progress.getCurrentLegProgress().getCurrentStepProgress().getDistanceRemaining(); - return String.format( - Locale.US, - CONTINUE_STRING_FORMAT, - progress.getCurrentLegProgress().getCurrentStep().getName(), - distanceFormatter(userDistance)); + if (TextUtils.isEmpty(progress.getCurrentLegProgress().getCurrentStep().getName()) || userDistance == 0) { + return ""; + } else { + return String.format( + Locale.US, + CONTINUE_STRING_FORMAT, + progress.getCurrentLegProgress().getCurrentStep().getName(), + distanceFormatter(userDistance)); + } } /** * Creates a {@link String} with the current step distance remaining upcoming step instruction * Example: "In 3.2 miles turn left onto Main St." + * * @param progress {@link RouteProgress} created by the location change * @return {@link String} with format "In %s %s" * @since 0.4.0 @@ -171,6 +181,7 @@ private String buildDefaultFormatInstruction(RouteProgress progress) { * Creates a {@link String} with the current step maneuver instruction, current step distance remaining, * and upcoming step instruction * Example: "Turn left onto Main St. then in 3.2 miles turn right onto Second St." + * * @param progress {@link RouteProgress} created by the location change * @return {@link String} with format "%s then in %s %s" * @since 0.4.0 @@ -192,6 +203,7 @@ private String buildThenInFormatInstruction(RouteProgress progress) { /** * Creates a {@link String} with the upcoming step instruction and follow up step instruction * Example: "Turn right onto Main St. then turn left onto Second St." + * * @param progress {@link RouteProgress} created by the location change * @return {@link String} with format "%s then %s" * @since 0.4.0 @@ -212,12 +224,13 @@ private static String convertFirstCharLowercase(String instruction) { if (TextUtils.isEmpty(instruction)) { return instruction; } else { - return instruction.substring(0,1).toLowerCase() + instruction.substring(1); + return instruction.substring(0, 1).toLowerCase() + instruction.substring(1); } } /** * If over 1099 feet, use miles format. If less, use feet in intervals of 100 + * * @param distance given distance extracted from {@link RouteProgress} * @return {@link String} in either feet (int) or miles (decimal) format * @since 0.4.0 diff --git a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java index 2502db06d54..b2905e97413 100644 --- a/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java +++ b/navigation/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/instruction/Instruction.java @@ -9,6 +9,7 @@ public abstract class Instruction { /** * Will provide an instruction based on your specifications + * * @return {@link String} instruction that will be voiced on the client * @since 0.4.0 */