diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 4271ce29e86..ffaa3d65702 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -11,7 +11,7 @@ ext { mapboxMapSdk : '7.0.1', mapboxSdkServices : '4.3.0', mapboxEvents : '4.2.0', - mapboxNavigator : '3.4.12', + mapboxNavigator : '4.0.0', searchSdk : '0.1.0-SNAPSHOT', autoValue : '1.5.4', autoValueParcel : '0.2.5', diff --git a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/milestone/BannerInstructionMilestone.java b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/milestone/BannerInstructionMilestone.java index 63a4f4a6d98..aaef8e6287f 100644 --- a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/milestone/BannerInstructionMilestone.java +++ b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/milestone/BannerInstructionMilestone.java @@ -1,10 +1,15 @@ package com.mapbox.services.android.navigation.v5.milestone; +import com.mapbox.api.directions.v5.models.BannerComponents; import com.mapbox.api.directions.v5.models.BannerInstructions; -import com.mapbox.api.directions.v5.models.LegStep; -import com.mapbox.services.android.navigation.v5.routeprogress.RouteLegProgress; +import com.mapbox.api.directions.v5.models.BannerText; +import com.mapbox.navigator.BannerComponent; +import com.mapbox.navigator.BannerInstruction; +import com.mapbox.navigator.BannerSection; import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress; -import com.mapbox.services.android.navigation.v5.utils.RouteUtils; + +import java.util.ArrayList; +import java.util.List; /** * A default milestone that is added to {@link com.mapbox.services.android.navigation.v5.navigation.MapboxNavigation} @@ -16,26 +21,74 @@ public class BannerInstructionMilestone extends Milestone { private BannerInstructions instructions; - private RouteUtils routeUtils; - BannerInstructionMilestone(Builder builder) { + private BannerInstructionMilestone(Builder builder) { super(builder); - routeUtils = new RouteUtils(); } @Override public boolean isOccurring(RouteProgress previousRouteProgress, RouteProgress routeProgress) { - RouteLegProgress legProgress = routeProgress.currentLegProgress(); - LegStep currentStep = legProgress.currentStep(); - double stepDistanceRemaining = legProgress.currentStepProgress().distanceRemaining(); - BannerInstructions instructions = routeUtils.findCurrentBannerInstructions(currentStep, stepDistanceRemaining); - if (shouldBeShown(instructions, stepDistanceRemaining)) { - this.instructions = instructions; + return updateCurrentBanner(routeProgress); + } + + private boolean updateCurrentBanner(RouteProgress routeProgress) { + BannerInstruction currentBannerInstruction = routeProgress.bannerInstruction(); + if (currentBannerInstruction != null) { + BannerSection currentPrimary = currentBannerInstruction.getPrimary(); + BannerText primary = retrieveBannerFrom(currentPrimary); + BannerSection currentSecondary = currentBannerInstruction.getSecondary(); + BannerText secondary = retrieveBannerFrom(currentSecondary); + BannerSection currentSub = currentBannerInstruction.getSub(); + BannerText sub = retrieveBannerFrom(currentSub); + + this.instructions = BannerInstructions.builder() + .primary(primary) + .secondary(secondary) + .sub(sub) + .distanceAlongGeometry(currentBannerInstruction.getRemainingStepDistance()) + .build(); return true; } return false; } + private BannerText retrieveBannerFrom(BannerSection bannerSection) { + BannerText banner = null; + if (bannerSection == null) { + return banner; + } + List currentComponents = bannerSection.getComponents(); + if (currentComponents != null) { + List primaryComponents = new ArrayList<>(); + for (BannerComponent bannerComponent : currentComponents) { + BannerComponents bannerComponents = BannerComponents.builder() + .text(bannerComponent.getText()) + .type(bannerComponent.getType()) + .abbreviation(bannerComponent.getAbbr()) + .abbreviationPriority(bannerComponent.getAbbrPriority()) + .imageBaseUrl(bannerComponent.getImageBaseurl()) + .directions(bannerComponent.getDirections()) + .active(bannerComponent.getActive()) + .build(); + primaryComponents.add(bannerComponents); + } + Integer bannerSectionDegrees = bannerSection.getDegrees(); + Double degrees = null; + if (bannerSectionDegrees != null) { + degrees = Double.valueOf(bannerSectionDegrees); + } + banner = BannerText.builder() + .text(bannerSection.getText()) + .type(bannerSection.getType()) + .modifier(bannerSection.getModifier()) + .degrees(degrees) + .drivingSide(bannerSection.getDrivingSide()) + .components(primaryComponents) + .build(); + } + return banner; + } + /** * Returns the given {@link BannerInstructions} for the time that the milestone is triggered. * @@ -46,22 +99,6 @@ public BannerInstructions getBannerInstructions() { return instructions; } - /** - * Uses the current step distance remaining to check against banner instructions distance. - * - * @param instructions given banner instructions from the list of step instructions - * @param stepDistanceRemaining distance remaining along the current step - * @return true if time to show the instructions, false if not - */ - private boolean shouldBeShown(BannerInstructions instructions, double stepDistanceRemaining) { - boolean isNewInstruction = this.instructions == null || !this.instructions.equals(instructions); - boolean isValidNewInstruction = instructions != null && isNewInstruction; - boolean withinDistanceAlongGeometry = isValidNewInstruction - && instructions.distanceAlongGeometry() >= stepDistanceRemaining; - boolean isFirstInstruction = this.instructions == null && instructions != null; - return isFirstInstruction || withinDistanceAlongGeometry; - } - public static final class Builder extends Milestone.Builder { private Trigger.Statement trigger; diff --git a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/MapboxNavigator.java b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/MapboxNavigator.java index 1b16d98995b..a851164bdca 100644 --- a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/MapboxNavigator.java +++ b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/MapboxNavigator.java @@ -3,6 +3,7 @@ import android.location.Location; import com.mapbox.geojson.Point; +import com.mapbox.navigator.BannerInstruction; import com.mapbox.navigator.FixLocation; import com.mapbox.navigator.NavigationStatus; import com.mapbox.navigator.Navigator; @@ -71,6 +72,10 @@ synchronized VoiceInstruction retrieveVoiceInstruction(int index) { return navigator.getVoiceInstruction(index); } + synchronized BannerInstruction retrieveBannerInstruction(int index) { + return navigator.getBannerInstruction(index); + } + FixLocation buildFixLocationFromLocation(Location location) { Date time = new Date(); Point rawPoint = Point.fromLngLat(location.getLongitude(), location.getLatitude()); diff --git a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/NavigationRouteProcessor.java b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/NavigationRouteProcessor.java index 44468e59bf3..d8bcc31144f 100644 --- a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/NavigationRouteProcessor.java +++ b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/NavigationRouteProcessor.java @@ -8,6 +8,7 @@ import com.mapbox.api.directions.v5.models.RouteLeg; import com.mapbox.api.directions.v5.models.StepIntersection; import com.mapbox.geojson.Point; +import com.mapbox.navigator.BannerInstruction; import com.mapbox.navigator.NavigationStatus; import com.mapbox.navigator.RouteState; import com.mapbox.navigator.VoiceInstruction; @@ -30,6 +31,7 @@ class NavigationRouteProcessor { private static final int ONE_INDEX = 1; private static final double ONE_SECOND_IN_MILLISECONDS = 1000.0; + private static final int FIRST_BANNER_INSTRUCTION = 0; private final RouteProgressStateMap progressStateMap = new RouteProgressStateMap(); private RouteProgress previousRouteProgress; private DirectionsRoute route; @@ -42,9 +44,9 @@ class NavigationRouteProcessor { private List> currentIntersectionDistances; private CurrentLegAnnotation currentLegAnnotation; - RouteProgress buildNewRouteProgress(NavigationStatus status, DirectionsRoute route) { + RouteProgress buildNewRouteProgress(MapboxNavigator navigator, NavigationStatus status, DirectionsRoute route) { updateRoute(route); - return buildRouteProgressFrom(status); + return buildRouteProgressFrom(status, navigator); } void updatePreviousRouteProgress(RouteProgress routeProgress) { @@ -62,7 +64,7 @@ private void updateRoute(DirectionsRoute route) { } } - private RouteProgress buildRouteProgressFrom(NavigationStatus status) { + private RouteProgress buildRouteProgressFrom(NavigationStatus status, MapboxNavigator navigator) { int legIndex = status.getLegIndex(); int stepIndex = status.getStepIndex(); int upcomingStepIndex = stepIndex + ONE_INDEX; @@ -104,8 +106,8 @@ private RouteProgress buildRouteProgressFrom(NavigationStatus status) { .inTunnel(status.getInTunnel()) .currentState(currentRouteState); - // TODO build banner instructions from status here addVoiceInstructions(status, progressBuilder); + addBannerInstructions(status, navigator, progressBuilder); addUpcomingStepPoints(progressBuilder); return progressBuilder.build(); } @@ -142,4 +144,13 @@ private void addVoiceInstructions(NavigationStatus status, RouteProgress.Builder VoiceInstruction voiceInstruction = status.getVoiceInstruction(); progressBuilder.voiceInstruction(voiceInstruction); } + + private void addBannerInstructions(NavigationStatus status, MapboxNavigator navigator, + RouteProgress.Builder progressBuilder) { + BannerInstruction bannerInstruction = status.getBannerInstruction(); + if (status.getRouteState() == RouteState.INITIALIZED) { + bannerInstruction = navigator.retrieveBannerInstruction(FIRST_BANNER_INSTRUCTION); + } + progressBuilder.bannerInstruction(bannerInstruction); + } } diff --git a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/RouteProcessorRunnable.java b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/RouteProcessorRunnable.java index 4e00a580a6a..2a14ff0caeb 100644 --- a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/RouteProcessorRunnable.java +++ b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/RouteProcessorRunnable.java @@ -58,7 +58,7 @@ private void process() { NavigationStatus status = mapboxNavigator.retrieveStatus(new Date(), options.navigationLocationEngineIntervalLagInMilliseconds()); status = checkForNewLegIndex(mapboxNavigator, route, status, options.enableAutoIncrementLegIndex()); - RouteProgress routeProgress = routeProcessor.buildNewRouteProgress(status, route); + RouteProgress routeProgress = routeProcessor.buildNewRouteProgress(mapboxNavigator, status, route); NavigationEngineFactory engineFactory = navigation.retrieveEngineFactory(); final boolean userOffRoute = isUserOffRoute(options, status, rawLocation, routeProgress, engineFactory); diff --git a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/routeprogress/RouteProgress.java b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/routeprogress/RouteProgress.java index bf8790b9886..0a3a3da4129 100644 --- a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/routeprogress/RouteProgress.java +++ b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/routeprogress/RouteProgress.java @@ -9,6 +9,7 @@ import com.mapbox.api.directions.v5.models.RouteLeg; import com.mapbox.api.directions.v5.models.StepIntersection; import com.mapbox.geojson.Point; +import com.mapbox.navigator.BannerInstruction; import com.mapbox.navigator.VoiceInstruction; import java.util.List; @@ -168,6 +169,15 @@ public int remainingWaypoints() { @Nullable public abstract VoiceInstruction voiceInstruction(); + /** + * Current banner instruction. + * + * @return current banner instruction + * @since 0.25.0 + */ + @Nullable + public abstract BannerInstruction bannerInstruction(); + /** * Returns the current state of progress along the route. Provides route and location tracking * information. @@ -264,6 +274,8 @@ public abstract Builder intersectionDistancesAlongStep( public abstract Builder voiceInstruction(@Nullable VoiceInstruction voiceInstruction); + public abstract Builder bannerInstruction(@Nullable BannerInstruction bannerInstruction); + public abstract Builder currentState(@Nullable RouteProgressState currentState); abstract RouteProgress autoBuild(); // not public diff --git a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/snap/SnapToRoute.java b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/snap/SnapToRoute.java index 406dca73cde..472143b7b2a 100644 --- a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/snap/SnapToRoute.java +++ b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/snap/SnapToRoute.java @@ -3,6 +3,8 @@ import android.location.Location; import android.support.annotation.NonNull; +import com.mapbox.geojson.Point; +import com.mapbox.navigator.FixLocation; import com.mapbox.navigator.NavigationStatus; import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress; @@ -21,10 +23,14 @@ public Location getSnappedLocationWith(NavigationStatus status, Location rawLoca @NonNull private Location buildSnappedLocation(NavigationStatus status, Location rawLocation) { Location snappedLocation = new Location(rawLocation); - snappedLocation.setLatitude(status.getLocation().latitude()); - snappedLocation.setLongitude(status.getLocation().longitude()); - snappedLocation.setBearing(status.getBearing()); - snappedLocation.setTime(status.getTime().getTime()); + FixLocation fixLocation = status.getLocation(); + Point coordinate = fixLocation.getCoordinate(); + snappedLocation.setLatitude(coordinate.latitude()); + snappedLocation.setLongitude(coordinate.longitude()); + if (fixLocation.getBearing() != null) { + snappedLocation.setBearing(fixLocation.getBearing()); + } + snappedLocation.setTime(fixLocation.getTime().getTime()); return snappedLocation; } } \ No newline at end of file diff --git a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/utils/RouteUtils.java b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/utils/RouteUtils.java index 1b87a93b0ca..ff5087978c3 100644 --- a/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/utils/RouteUtils.java +++ b/libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/utils/RouteUtils.java @@ -1,17 +1,12 @@ package com.mapbox.services.android.navigation.v5.utils; -import android.location.Location; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import com.mapbox.api.directions.v5.DirectionsCriteria; import com.mapbox.api.directions.v5.models.BannerInstructions; -import com.mapbox.api.directions.v5.models.BannerText; -import com.mapbox.api.directions.v5.models.DirectionsRoute; import com.mapbox.api.directions.v5.models.LegStep; import com.mapbox.api.directions.v5.models.RouteLeg; import com.mapbox.api.directions.v5.models.RouteOptions; -import com.mapbox.api.directions.v5.models.VoiceInstructions; import com.mapbox.core.utils.TextUtils; import com.mapbox.geojson.Point; import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress; @@ -21,59 +16,15 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.HashSet; import java.util.List; -import java.util.Set; - -import static com.mapbox.services.android.navigation.v5.navigation.NavigationConstants.STEP_MANEUVER_TYPE_ARRIVE; public class RouteUtils { - - private static final String FORCED_LOCATION = "Forced Location"; - private static final int FIRST_COORDINATE = 0; private static final int FIRST_INSTRUCTION = 0; private static final int ORIGIN_WAYPOINT_NAME_THRESHOLD = 1; private static final int ORIGIN_WAYPOINT_NAME = 0; private static final int FIRST_POSITION = 0; private static final int SECOND_POSITION = 1; private static final String SEMICOLON = ";"; - private static final Set VALID_PROFILES = new HashSet() { - { - add(DirectionsCriteria.PROFILE_DRIVING_TRAFFIC); - add(DirectionsCriteria.PROFILE_DRIVING); - add(DirectionsCriteria.PROFILE_CYCLING); - add(DirectionsCriteria.PROFILE_WALKING); - } - }; - - /** - * Compares a new routeProgress geometry to a previousRouteProgress geometry to determine if the - * user is traversing along a new route. If the route geometries do not match, this returns true. - * - * @param previousRouteProgress the past route progress with the directions route included - * @param routeProgress the route progress with the directions route included - * @return true if the direction route geometries do not match up, otherwise, false - * @since 0.7.0 - */ - public boolean isNewRoute(@Nullable RouteProgress previousRouteProgress, - @NonNull RouteProgress routeProgress) { - return isNewRoute(previousRouteProgress, routeProgress.directionsRoute()); - } - - /** - * Compares a new routeProgress geometry to a previousRouteProgress geometry to determine if the - * user is traversing along a new route. If the route geometries do not match, this returns true. - * - * @param previousRouteProgress the past route progress with the directions route included - * @param directionsRoute the current directions route - * @return true if the direction route geometries do not match up, otherwise, false - * @since 0.7.0 - */ - public boolean isNewRoute(@Nullable RouteProgress previousRouteProgress, - @NonNull DirectionsRoute directionsRoute) { - return previousRouteProgress == null || !previousRouteProgress.directionsRoute().geometry() - .equals(directionsRoute.geometry()); - } /** * Looks at the current {@link RouteProgressState} and returns if @@ -155,38 +106,6 @@ public String[] calculateRemainingWaypointNames(RouteProgress routeProgress) { return waypointNames; } - /** - * If navigation begins, a location update is sometimes needed to force a - * progress change update as soon as navigation is started. - *

- * This method creates a location update from the first coordinate (origin) that created - * the route. - * - * @param route with list of coordinates - * @return {@link Location} from first coordinate - * @since 0.10.0 - */ - public Location createFirstLocationFromRoute(DirectionsRoute route) { - List coordinates = route.routeOptions().coordinates(); - Point origin = coordinates.get(FIRST_COORDINATE); - Location forcedLocation = new Location(FORCED_LOCATION); - forcedLocation.setLatitude(origin.latitude()); - forcedLocation.setLongitude(origin.longitude()); - return forcedLocation; - } - - /** - * Checks if the {@link String} route profile provided is a valid profile - * that can be used with the directions API. - * - * @param routeProfile being validated - * @return true if valid, false if not - * @since 0.13.0 - */ - public boolean isValidRouteProfile(String routeProfile) { - return !TextUtils.isEmpty(routeProfile) && VALID_PROFILES.contains(routeProfile); - } - /** * Given the current step / current step distance remaining, this function will * find the current instructions to be shown. @@ -226,76 +145,6 @@ public int compare(BannerInstructions instructions, BannerInstructions nextInstr return sortedInstructions; } - /** - * This method returns the current {@link BannerText} based on the currentStep distance - * remaining. - *

- * When called, this is the banner text that should be shown at the given point along the route. - * - * @param currentStep holding the current banner instructions - * @param stepDistanceRemaining to determine progress along the currentStep - * @param findPrimary if the primary or secondary BannerText should be retrieved - * @return current BannerText based on currentStep distance remaining - * @since 0.13.0 - */ - @Nullable - public BannerText findCurrentBannerText(LegStep currentStep, double stepDistanceRemaining, - boolean findPrimary) { - BannerInstructions instructions = findCurrentBannerInstructions(currentStep, stepDistanceRemaining); - if (instructions != null) { - return retrievePrimaryOrSecondaryBannerText(findPrimary, instructions); - } - return null; - } - - /** - * This method returns the current {@link VoiceInstructions} based on the step distance - * remaining. - * - * @param currentStep holding the current banner instructions - * @param stepDistanceRemaining to determine progress along the step - * @return current voice instructions based on step distance remaining - * @since 0.13.0 - */ - @Nullable - public VoiceInstructions findCurrentVoiceInstructions(LegStep currentStep, double stepDistanceRemaining) { - if (isValidVoiceInstructions(currentStep)) { - List instructions = sortVoiceInstructions(currentStep.voiceInstructions()); - for (VoiceInstructions instruction : instructions) { - double distanceAlongGeometry = instruction.distanceAlongGeometry(); - if (distanceAlongGeometry >= stepDistanceRemaining) { - return instruction; - } - } - return instructions.get(FIRST_INSTRUCTION); - } - return null; - } - - private boolean isValidVoiceInstructions(LegStep currentStep) { - return isValidStep(currentStep) && hasInstructions(currentStep.voiceInstructions()); - } - - private List sortVoiceInstructions(List instructions) { - List sortedInstructions = new ArrayList<>(instructions); - Collections.sort(sortedInstructions, new Comparator() { - @Override - public int compare(VoiceInstructions instructions, VoiceInstructions nextInstructions) { - return Double.compare(instructions.distanceAlongGeometry(), nextInstructions.distanceAlongGeometry()); - } - }); - return sortedInstructions; - } - - private boolean upcomingStepIsArrivalManeuverType(@NonNull RouteProgress routeProgress) { - return routeProgress.currentLegProgress().upComingStep() != null - && routeProgress.currentLegProgress().upComingStep().maneuver().type().contains(STEP_MANEUVER_TYPE_ARRIVE); - } - - private boolean currentStepIsArrivalManeuverType(@NonNull RouteProgress routeProgress) { - return routeProgress.currentLegProgress().currentStep().maneuver().type().contains(STEP_MANEUVER_TYPE_ARRIVE); - } - private boolean isValidStep(LegStep step) { return step != null; } @@ -303,21 +152,4 @@ private boolean isValidStep(LegStep step) { private boolean hasInstructions(List instructions) { return instructions != null && !instructions.isEmpty(); } - - private int checkValidIndex(List instructions) { - int instructionIndex = instructions.size() - 1; - if (instructionIndex < 0) { - instructionIndex = 0; - } - return instructionIndex; - } - - private boolean hasValidInstructions(List bannerInstructions, - BannerInstructions currentInstructions) { - return bannerInstructions != null && !bannerInstructions.isEmpty() && currentInstructions != null; - } - - private BannerText retrievePrimaryOrSecondaryBannerText(boolean findPrimary, BannerInstructions instruction) { - return findPrimary ? instruction.primary() : instruction.secondary(); - } } diff --git a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/milestone/BannerInstructionMilestoneTest.java b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/milestone/BannerInstructionMilestoneTest.java index b108a11405e..bb09ea843fd 100644 --- a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/milestone/BannerInstructionMilestoneTest.java +++ b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/milestone/BannerInstructionMilestoneTest.java @@ -1,107 +1,76 @@ package com.mapbox.services.android.navigation.v5.milestone; -import com.mapbox.api.directions.v5.models.BannerInstructions; -import com.mapbox.api.directions.v5.models.LegStep; +import com.mapbox.navigator.BannerComponent; +import com.mapbox.navigator.BannerInstruction; +import com.mapbox.navigator.BannerSection; import com.mapbox.services.android.navigation.v5.BaseTest; import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress; import org.junit.Test; -import java.util.List; +import java.util.ArrayList; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class BannerInstructionMilestoneTest extends BaseTest { @Test - public void sanity() { - BannerInstructionMilestone milestone = buildBannerInstructionMilestone(); - - assertNotNull(milestone); - } - - @Test - public void onBeginningOfStep_bannerInstructionsShouldTrigger() throws Exception { + public void checksNotBannerShownIfBannerInstructionIsNull() throws Exception { RouteProgress routeProgress = buildDefaultTestRouteProgress(); - routeProgress = createBeginningOfStepRouteProgress(routeProgress); + BannerInstruction nullBannerInstruction = null; + routeProgress = add(nullBannerInstruction, routeProgress); BannerInstructionMilestone milestone = buildBannerInstructionMilestone(); boolean isOccurring = milestone.isOccurring(routeProgress, routeProgress); - assertTrue(isOccurring); - } - - @Test - public void onSameInstructionOccurring_milestoneDoesNotTriggerTwice() throws Exception { - RouteProgress routeProgress = buildDefaultTestRouteProgress(); - RouteProgress firstProgress = createBeginningOfStepRouteProgress(routeProgress); - double fortyMetersIntoStep = routeProgress.currentLegProgress().currentStep().distance() - 40; - RouteProgress secondProgress = routeProgress.toBuilder() - .stepDistanceRemaining(fortyMetersIntoStep) - .stepIndex(0) - .build(); - BannerInstructionMilestone milestone = buildBannerInstructionMilestone(); - - milestone.isOccurring(firstProgress, firstProgress); - boolean shouldNotBeOccurring = milestone.isOccurring(firstProgress, secondProgress); - - assertFalse(shouldNotBeOccurring); + assertFalse(isOccurring); } @Test - public void nullInstructions_MilestoneDoesNotGetTriggered() throws Exception { + public void checksBannerShownIfBannerInstructionIsNotNull() throws Exception { RouteProgress routeProgress = buildDefaultTestRouteProgress(); - LegStep currentStep = routeProgress.currentLegProgress().currentStep(); - List instructions = currentStep.bannerInstructions(); - instructions.clear(); - routeProgress = createBeginningOfStepRouteProgress(routeProgress); + BannerInstruction emptyBannerInstruction = buildEmptyBannerInstructionWithPrimary(null); + routeProgress = add(emptyBannerInstruction, routeProgress); BannerInstructionMilestone milestone = buildBannerInstructionMilestone(); boolean isOccurring = milestone.isOccurring(routeProgress, routeProgress); - assertFalse(isOccurring); + assertTrue(isOccurring); } @Test - public void onOccurringMilestone_beginningOfStep_bannerInstructionsAreReturned() throws Exception { + public void checksBannerMappingIfBannerSectionHasComponents() throws Exception { RouteProgress routeProgress = buildDefaultTestRouteProgress(); - routeProgress = routeProgress.toBuilder() - .stepDistanceRemaining(routeProgress.currentLegProgress().currentStep().distance()) - .stepIndex(1) - .build(); - BannerInstructions instructions = routeProgress.currentLegProgress().currentStep().bannerInstructions().get(0); + int anAbbrPriority = 0; + boolean isActive = true; + ArrayList anyDirections = new ArrayList<>(); + anyDirections.add("a direction"); + BannerComponent aComponent = new BannerComponent("a type", "a text", "an abbr", anAbbrPriority, + "an image base url", isActive, anyDirections); + ArrayList components = new ArrayList<>(); + components.add(aComponent); + BannerSection sectionWithComponents = new BannerSection("a text", "a type", "a modifier", 60, "a driving side", + components); + BannerInstruction emptyBannerInstruction = buildEmptyBannerInstructionWithPrimary(sectionWithComponents); + routeProgress = add(emptyBannerInstruction, routeProgress); BannerInstructionMilestone milestone = buildBannerInstructionMilestone(); - milestone.isOccurring(routeProgress, routeProgress); + boolean isOccurring = milestone.isOccurring(routeProgress, routeProgress); - assertEquals(instructions, milestone.getBannerInstructions()); + assertTrue(isOccurring); + assertEquals(1, routeProgress.bannerInstruction().getPrimary().getComponents().size()); } - @Test - public void onOccurringMilestone_endOfStep_bannerInstructionsAreReturned() throws Exception { - RouteProgress routeProgress = buildDefaultTestRouteProgress(); - int tenMetersRemainingInStep = 10; - routeProgress = routeProgress.toBuilder() - .stepDistanceRemaining(tenMetersRemainingInStep) - .stepIndex(1) + private RouteProgress add(BannerInstruction bannerInstruction, RouteProgress routeProgress) { + return routeProgress.toBuilder() + .bannerInstruction(bannerInstruction) .build(); - List bannerInstructions = routeProgress.currentLegProgress().currentStep().bannerInstructions(); - BannerInstructions instructions = bannerInstructions.get(bannerInstructions.size() - 1); - BannerInstructionMilestone milestone = buildBannerInstructionMilestone(); - - milestone.isOccurring(routeProgress, routeProgress); - - assertEquals(instructions, milestone.getBannerInstructions()); } - private RouteProgress createBeginningOfStepRouteProgress(RouteProgress routeProgress) { - return routeProgress.toBuilder() - .stepDistanceRemaining(routeProgress.currentLegProgress().currentStep().distance()) - .stepIndex(0) - .build(); + private BannerInstruction buildEmptyBannerInstructionWithPrimary(BannerSection section) { + return new BannerInstruction(section, null, null, -1, -1); } private BannerInstructionMilestone buildBannerInstructionMilestone() { diff --git a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/navigation/NavigationRouteProcessorTest.java b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/navigation/NavigationRouteProcessorTest.java index c14852f1966..b779dd60092 100644 --- a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/navigation/NavigationRouteProcessorTest.java +++ b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/navigation/NavigationRouteProcessorTest.java @@ -20,7 +20,7 @@ public void buildNewRouteProgress_routeProgressReturned() throws IOException { NavigationRouteProcessor processor = new NavigationRouteProcessor(); // TODO mock final status - RouteProgress progress = processor.buildNewRouteProgress(mock(NavigationStatus.class), buildTestDirectionsRoute()); + RouteProgress progress = processor.buildNewRouteProgress(mock(MapboxNavigator.class), mock(NavigationStatus.class), buildTestDirectionsRoute()); assertNotNull(progress); } diff --git a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/navigation/RouteProcessorRunnableTest.java b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/navigation/RouteProcessorRunnableTest.java index 180645ab9b7..e7c24c59354 100644 --- a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/navigation/RouteProcessorRunnableTest.java +++ b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/navigation/RouteProcessorRunnableTest.java @@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -36,24 +37,26 @@ public class RouteProcessorRunnableTest { @Test public void onRun_buildNewRouteProgressReceivesStatusAndRoute() { NavigationRouteProcessor processor = mock(NavigationRouteProcessor.class); + MapboxNavigator navigator = mock(MapboxNavigator.class); NavigationStatus status = buildMockStatus(); DirectionsRoute route = mock(DirectionsRoute.class); - RouteProcessorRunnable runnable = buildRouteProcessorRunnableWith(processor, status, route); + RouteProcessorRunnable runnable = buildRouteProcessorRunnableWith(navigator,processor, status, route); runnable.updateRawLocation(mock(Location.class)); runnable.run(); - verify(processor).buildNewRouteProgress(status, route); + verify(processor).buildNewRouteProgress(navigator, status, route); } @Test public void onRun_previousRouteProgressIsUpdated() { NavigationRouteProcessor processor = mock(NavigationRouteProcessor.class); + MapboxNavigator navigator = mock(MapboxNavigator.class); NavigationStatus status = buildMockStatus(); DirectionsRoute route = mock(DirectionsRoute.class); RouteProgress progress = mock(RouteProgress.class); - when(processor.buildNewRouteProgress(status, route)).thenReturn(progress); - RouteProcessorRunnable runnable = buildRouteProcessorRunnableWith(processor, status, route); + when(processor.buildNewRouteProgress(navigator, status, route)).thenReturn(progress); + RouteProcessorRunnable runnable = buildRouteProcessorRunnableWith(navigator, processor, status, route); runnable.updateRawLocation(mock(Location.class)); runnable.run(); @@ -174,10 +177,9 @@ public void onRun_legIndexDoesNotIncrementOnLegCompletionWithAutoIncrementDisabl verify(navigator, times(0)).updateLegIndex(anyInt()); } - private RouteProcessorRunnable buildRouteProcessorRunnableWith(NavigationRouteProcessor processor, + private RouteProcessorRunnable buildRouteProcessorRunnableWith(MapboxNavigator navigator, NavigationRouteProcessor processor, NavigationStatus status, DirectionsRoute route) { MapboxNavigationOptions options = MapboxNavigationOptions.builder().build(); - MapboxNavigator navigator = mock(MapboxNavigator.class); when(navigator.retrieveStatus(any(Date.class), any(Long.class))).thenReturn(status); MapboxNavigation navigation = mock(MapboxNavigation.class); when(navigation.options()).thenReturn(options); @@ -255,11 +257,11 @@ private NavigationEngineFactory buildMockFactory(OffRouteDetector detector) { } private NavigationStatus buildMockStatus() { - NavigationStatus status = mock(NavigationStatus.class); + NavigationStatus status = mock(NavigationStatus.class, RETURNS_DEEP_STUBS); Point location = Point.fromLngLat(0.0, 0.0); - when(status.getLocation()).thenReturn(location); - when(status.getTime()).thenReturn(new Date()); - when(status.getBearing()).thenReturn(0.0f); + when(status.getLocation().getCoordinate()).thenReturn(location); + when(status.getLocation().getTime()).thenReturn(new Date()); + when(status.getLocation().getBearing()).thenReturn(0.0f); return status; } diff --git a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/snap/SnapToRouteTest.java b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/snap/SnapToRouteTest.java index 5afdaf2b2a7..2788b12f9c3 100644 --- a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/snap/SnapToRouteTest.java +++ b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/snap/SnapToRouteTest.java @@ -13,6 +13,7 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -78,11 +79,11 @@ public void getSnappedLocationWith_returnsRawLocationAccuracy() { } private NavigationStatus buildMockStatus() { - NavigationStatus status = mock(NavigationStatus.class); + NavigationStatus status = mock(NavigationStatus.class, RETURNS_DEEP_STUBS); Point location = Point.fromLngLat(0.0, 0.0); - when(status.getLocation()).thenReturn(location); - when(status.getTime()).thenReturn(new Date()); - when(status.getBearing()).thenReturn(0.0f); + when(status.getLocation().getCoordinate()).thenReturn(location); + when(status.getLocation().getTime()).thenReturn(new Date()); + when(status.getLocation().getBearing()).thenReturn(0.0f); return status; } } diff --git a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/utils/RouteUtilsTest.java b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/utils/RouteUtilsTest.java index 054a0eb0a79..bcba1dfd86f 100644 --- a/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/utils/RouteUtilsTest.java +++ b/libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/utils/RouteUtilsTest.java @@ -1,18 +1,11 @@ package com.mapbox.services.android.navigation.v5.utils; -import android.support.annotation.NonNull; - -import com.mapbox.api.directions.v5.DirectionsCriteria; import com.mapbox.api.directions.v5.models.BannerInstructions; -import com.mapbox.api.directions.v5.models.BannerText; import com.mapbox.api.directions.v5.models.DirectionsRoute; import com.mapbox.api.directions.v5.models.LegStep; import com.mapbox.api.directions.v5.models.RouteOptions; -import com.mapbox.api.directions.v5.models.VoiceInstructions; import com.mapbox.geojson.Point; import com.mapbox.services.android.navigation.v5.BaseTest; -import com.mapbox.services.android.navigation.v5.milestone.BannerInstructionMilestone; -import com.mapbox.services.android.navigation.v5.routeprogress.RouteLegProgress; import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress; import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgressState; @@ -30,40 +23,6 @@ public class RouteUtilsTest extends BaseTest { - @Test - public void isNewRoute_returnsTrueWhenPreviousGeometriesNull() throws Exception { - RouteProgress defaultRouteProgress = buildDefaultTestRouteProgress(); - RouteUtils routeUtils = new RouteUtils(); - - boolean isNewRoute = routeUtils.isNewRoute(null, defaultRouteProgress); - - assertTrue(isNewRoute); - } - - @Test - public void isNewRoute_returnsFalseWhenGeometriesEqualEachOther() throws Exception { - RouteProgress previousRouteProgress = buildDefaultTestRouteProgress(); - RouteUtils routeUtils = new RouteUtils(); - - boolean isNewRoute = routeUtils.isNewRoute(previousRouteProgress, previousRouteProgress); - - assertFalse(isNewRoute); - } - - @Test - public void isNewRoute_returnsTrueWhenGeometriesDoNotEqual() throws Exception { - DirectionsRoute aRoute = buildTestDirectionsRoute(); - RouteProgress defaultRouteProgress = buildDefaultTestRouteProgress(); - RouteProgress previousRouteProgress = defaultRouteProgress.toBuilder() - .directionsRoute(aRoute.toBuilder().geometry("vfejnqiv").build()) - .build(); - RouteUtils routeUtils = new RouteUtils(); - - boolean isNewRoute = routeUtils.isNewRoute(previousRouteProgress, defaultRouteProgress); - - assertTrue(isNewRoute); - } - @Test public void isArrivalEvent_returnsTrueWhenRouteProgressStateIsArrived() { RouteProgress routeProgress = mock(RouteProgress.class); @@ -86,66 +45,6 @@ public void isArrivalEvent_returnsFalseWhenRouteProgressStateIsNotArrived() { assertFalse(isArrivalEvent); } - @Test - public void isValidRouteProfile_returnsTrueWithDrivingTrafficProfile() throws Exception { - String routeProfileDrivingTraffic = DirectionsCriteria.PROFILE_DRIVING_TRAFFIC; - RouteUtils routeUtils = new RouteUtils(); - - boolean isValidProfile = routeUtils.isValidRouteProfile(routeProfileDrivingTraffic); - - assertTrue(isValidProfile); - } - - @Test - public void isValidRouteProfile_returnsTrueWithDrivingProfile() throws Exception { - String routeProfileDriving = DirectionsCriteria.PROFILE_DRIVING; - RouteUtils routeUtils = new RouteUtils(); - - boolean isValidProfile = routeUtils.isValidRouteProfile(routeProfileDriving); - - assertTrue(isValidProfile); - } - - @Test - public void isValidRouteProfile_returnsTrueWithCyclingProfile() throws Exception { - String routeProfileCycling = DirectionsCriteria.PROFILE_CYCLING; - RouteUtils routeUtils = new RouteUtils(); - - boolean isValidProfile = routeUtils.isValidRouteProfile(routeProfileCycling); - - assertTrue(isValidProfile); - } - - @Test - public void isValidRouteProfile_returnsTrueWithWalkingProfile() throws Exception { - String routeProfileWalking = DirectionsCriteria.PROFILE_WALKING; - RouteUtils routeUtils = new RouteUtils(); - - boolean isValidProfile = routeUtils.isValidRouteProfile(routeProfileWalking); - - assertTrue(isValidProfile); - } - - @Test - public void isValidRouteProfile_returnsFalseWithInvalidProfile() throws Exception { - String invalidProfile = "invalid_profile"; - RouteUtils routeUtils = new RouteUtils(); - - boolean isValidProfile = routeUtils.isValidRouteProfile(invalidProfile); - - assertFalse(isValidProfile); - } - - @Test - public void isValidRouteProfile_returnsFalseWithNullProfile() throws Exception { - String nullProfile = null; - RouteUtils routeUtils = new RouteUtils(); - - boolean isValidProfile = routeUtils.isValidRouteProfile(nullProfile); - - assertFalse(isValidProfile); - } - @Test public void findCurrentBannerInstructions_returnsNullWithNullCurrentStep() throws Exception { LegStep currentStep = null; @@ -225,139 +124,6 @@ public void findCurrentBannerInstructions_adjustedDistanceRemainingRemovesCorrec assertEquals(currentStep.bannerInstructions().get(0), currentBannerInstructions); } - @Test - public void findCurrentBannerText_returnsCorrectPrimaryBannerText() throws Exception { - RouteProgress routeProgress = buildDefaultTestRouteProgress(); - routeProgress = routeProgress.toBuilder() - .stepIndex(1) - .stepDistanceRemaining(50) - .build(); - LegStep currentStep = routeProgress.currentLegProgress().currentStep(); - double stepDistanceRemaining = routeProgress.currentLegProgress().currentStepProgress().distanceRemaining(); - RouteUtils routeUtils = new RouteUtils(); - - BannerText currentBannerText = routeUtils.findCurrentBannerText( - currentStep, stepDistanceRemaining, true - ); - - assertEquals(currentStep.bannerInstructions().get(1).primary(), currentBannerText); - } - - @Test - public void findCurrentBannerText_returnsCorrectSecondaryBannerText() throws Exception { - RouteProgress routeProgress = buildDefaultTestRouteProgress(); - routeProgress = routeProgress.toBuilder() - .stepIndex(1) - .stepDistanceRemaining(50) - .build(); - LegStep currentStep = routeProgress.currentLegProgress().currentStep(); - double stepDistanceRemaining = routeProgress.currentLegProgress().currentStepProgress().distanceRemaining(); - RouteUtils routeUtils = new RouteUtils(); - - BannerText currentBannerText = routeUtils.findCurrentBannerText( - currentStep, stepDistanceRemaining, false - ); - - assertEquals(currentStep.bannerInstructions().get(1).secondary(), currentBannerText); - } - - @Test - public void findCurrentBannerText_returnsNullWithNullCurrentStep() throws Exception { - LegStep currentStep = null; - double stepDistanceRemaining = 0; - RouteUtils routeUtils = new RouteUtils(); - - BannerText currentBannerText = routeUtils.findCurrentBannerText( - currentStep, stepDistanceRemaining, false - ); - - assertNull(currentBannerText); - } - - @Test - public void findCurrentVoiceInstructions_returnsNullWithNullCurrentStep() throws Exception { - LegStep currentStep = null; - double stepDistanceRemaining = 0; - RouteUtils routeUtils = new RouteUtils(); - - VoiceInstructions currentVoiceInstructions = routeUtils.findCurrentVoiceInstructions( - currentStep, stepDistanceRemaining - ); - - assertNull(currentVoiceInstructions); - } - - @Test - public void findCurrentVoiceInstructions_returnsNullWithCurrentStepEmptyInstructions() throws Exception { - RouteProgress routeProgress = buildDefaultTestRouteProgress(); - LegStep currentStep = routeProgress.currentLegProgress().currentStep(); - double stepDistanceRemaining = routeProgress.currentLegProgress().currentStepProgress().distanceRemaining(); - List currentInstructions = currentStep.voiceInstructions(); - currentInstructions.clear(); - RouteUtils routeUtils = new RouteUtils(); - - VoiceInstructions voiceInstructions = routeUtils.findCurrentVoiceInstructions( - currentStep, stepDistanceRemaining - ); - - assertNull(voiceInstructions); - } - - @Test - public void findCurrentVoiceInstructions_returnsCorrectInstructionsBeginningOfStepDistanceRemaining() throws - Exception { - RouteProgress routeProgress = buildDefaultTestRouteProgress(); - routeProgress = routeProgress.toBuilder() - .stepIndex(1) - .stepDistanceRemaining(300) - .build(); - LegStep currentStep = routeProgress.currentLegProgress().currentStep(); - double stepDistanceRemaining = routeProgress.currentLegProgress().currentStepProgress().distanceRemaining(); - RouteUtils routeUtils = new RouteUtils(); - - VoiceInstructions currentVoiceInstructions = routeUtils.findCurrentVoiceInstructions( - currentStep, stepDistanceRemaining - ); - - assertEquals(currentStep.voiceInstructions().get(1), currentVoiceInstructions); - } - - @Test - public void findCurrentVoiceInstructions_returnsCorrectInstructionsNoDistanceTraveled() throws Exception { - RouteProgress routeProgress = buildDefaultTestRouteProgress(); - routeProgress = routeProgress.toBuilder() - .stepDistanceRemaining(routeProgress.currentLegProgress().currentStep().distance()) - .stepIndex(0) - .build(); - LegStep currentStep = routeProgress.currentLegProgress().currentStep(); - double stepDistanceRemaining = routeProgress.currentLegProgress().currentStepProgress().distanceRemaining(); - RouteUtils routeUtils = new RouteUtils(); - - VoiceInstructions currentVoiceInstructions = routeUtils.findCurrentVoiceInstructions( - currentStep, stepDistanceRemaining - ); - - assertEquals(currentStep.voiceInstructions().get(0), currentVoiceInstructions); - } - - @Test - public void findCurrentVoiceInstructions_returnsCorrectInstructionsEndOfStepDistanceRemaining() throws Exception { - RouteProgress routeProgress = buildDefaultTestRouteProgress(); - routeProgress = routeProgress.toBuilder() - .stepIndex(1) - .stepDistanceRemaining(50) - .build(); - LegStep currentStep = routeProgress.currentLegProgress().currentStep(); - double stepDistanceRemaining = routeProgress.currentLegProgress().currentStepProgress().distanceRemaining(); - RouteUtils routeUtils = new RouteUtils(); - - VoiceInstructions currentVoiceInstructions = routeUtils.findCurrentVoiceInstructions( - currentStep, stepDistanceRemaining - ); - - assertEquals(currentStep.voiceInstructions().get(2), currentVoiceInstructions); - } - @Test public void calculateRemainingWaypoints() { DirectionsRoute route = mock(DirectionsRoute.class); @@ -424,25 +190,6 @@ public void calculateRemainingWaypointNames_handlesNullOptions() { assertNull(remainingWaypointNames); } - @NonNull - private RouteProgress buildRouteProgress(int first, DirectionsRoute route, LegStep currentStep, - LegStep upcomingStep) { - RouteProgress routeProgress = mock(RouteProgress.class); - RouteLegProgress legProgress = mock(RouteLegProgress.class); - when(legProgress.currentStep()).thenReturn(currentStep); - when(legProgress.upComingStep()).thenReturn(upcomingStep); - when(routeProgress.currentLegProgress()).thenReturn(legProgress); - when(routeProgress.directionsRoute()).thenReturn(route); - when(routeProgress.currentLeg()).thenReturn(route.legs().get(first)); - return routeProgress; - } - - private void buildBannerInstruction(int first, BannerInstructionMilestone bannerInstructionMilestone, - List currentStepBannerInstructions) { - BannerInstructions bannerInstructions = currentStepBannerInstructions.get(first); - when(bannerInstructionMilestone.getBannerInstructions()).thenReturn(bannerInstructions); - } - private List buildCoordinateList() { List coordinates = new ArrayList<>(); coordinates.add(Point.fromLngLat(1.234, 5.678));