diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index ebd4a150..63651ef8 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -8,7 +8,7 @@ on: jobs: build: - runs-on: macos-14 + runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ github.ref }}-android-build cancel-in-progress: true @@ -52,8 +52,7 @@ jobs: working-directory: android test: - - runs-on: macos-14 + runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ github.ref }}-android-test cancel-in-progress: true @@ -99,7 +98,7 @@ jobs: verify-snapshots: - runs-on: macos-14 + runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ github.ref }}-android-snapshots cancel-in-progress: true diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml index e754a1f2..a299c1dd 100644 --- a/.github/workflows/typos.yml +++ b/.github/workflows/typos.yml @@ -16,4 +16,4 @@ jobs: uses: actions/checkout@v4 - name: Run typos - uses: crate-ci/typos@v1.26.0 + uses: crate-ci/typos@master diff --git a/.swiftformat b/.swiftformat index 09fd015e..945ffffe 100644 --- a/.swiftformat +++ b/.swiftformat @@ -2,6 +2,7 @@ --exclude apple/.build --exclude apple/DemoApp/.build +--exclude apple/Sources/UniFFI/ferrostar.swift # format options diff --git a/Package.swift b/Package.swift index 96e0af14..2928f9fd 100644 --- a/Package.swift +++ b/Package.swift @@ -16,8 +16,8 @@ if useLocalFramework { path: "./common/target/ios/libferrostar-rs.xcframework" ) } else { - let releaseTag = "0.20.0" - let releaseChecksum = "b3565c57b70ac72426e10e7d3c3020900c07548d0eede8200ef4d07edb617a22" + let releaseTag = "0.20.1" + let releaseChecksum = "a5d8ecc5b4d4b77e2e9fd237b3c6ffd62772606a996a0e34f0fc7ecadc19fb9c" binaryTarget = .binaryTarget( name: "FerrostarCoreRS", url: diff --git a/android/build.gradle b/android/build.gradle index 5d487cef..6b82729b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -17,5 +17,5 @@ ext { allprojects { group = "com.stadiamaps.ferrostar" - version = "0.20.0" + version = "0.20.1" } diff --git a/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/theme/InstructionRowTheme.kt b/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/theme/InstructionRowTheme.kt index c9b04263..43d0ca1d 100644 --- a/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/theme/InstructionRowTheme.kt +++ b/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/theme/InstructionRowTheme.kt @@ -33,5 +33,5 @@ object DefaultInstructionRowTheme : InstructionRowTheme { @Composable get() = MaterialTheme.colorScheme.onSurface override val backgroundColor: Color - @Composable get() = MaterialTheme.colorScheme.surface + @Composable get() = MaterialTheme.colorScheme.surfaceContainerLow } diff --git a/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/theme/RoadNameViewTheme.kt b/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/theme/RoadNameViewTheme.kt index 0c433472..cab42953 100644 --- a/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/theme/RoadNameViewTheme.kt +++ b/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/theme/RoadNameViewTheme.kt @@ -23,9 +23,7 @@ interface RoadNameViewTheme { */ object DefaultRoadNameViewTheme : RoadNameViewTheme { override val textStyle: TextStyle - @Composable - get() = - MaterialTheme.typography.labelSmall.copy(color = MaterialTheme.colorScheme.inverseOnSurface) + @Composable get() = MaterialTheme.typography.labelSmall.copy(color = Color.White) override val backgroundColor: Color @Composable get() = Color(0x35, 0x83, 0xdd) diff --git a/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/views/InstructionsView.kt b/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/views/InstructionsView.kt index a609f903..f57841d2 100644 --- a/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/views/InstructionsView.kt +++ b/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/views/InstructionsView.kt @@ -1,25 +1,47 @@ package com.stadiamaps.ferrostar.composeui.views import android.icu.util.ULocale +import androidx.compose.animation.animateContentSize +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.spring import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.shadow +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.stadiamaps.ferrostar.composeui.formatting.DistanceFormatter import com.stadiamaps.ferrostar.composeui.formatting.LocalizedDistanceFormatter import com.stadiamaps.ferrostar.composeui.theme.DefaultInstructionRowTheme import com.stadiamaps.ferrostar.composeui.theme.InstructionRowTheme +import com.stadiamaps.ferrostar.composeui.views.controls.PillDragHandle import com.stadiamaps.ferrostar.composeui.views.maneuver.ManeuverImage import com.stadiamaps.ferrostar.composeui.views.maneuver.ManeuverInstructionView import uniffi.ferrostar.ManeuverModifier import uniffi.ferrostar.ManeuverType +import uniffi.ferrostar.RouteStep import uniffi.ferrostar.VisualInstruction import uniffi.ferrostar.VisualInstructionContent @@ -36,23 +58,88 @@ fun InstructionsView( distanceToNextManeuver: Double?, distanceFormatter: DistanceFormatter = LocalizedDistanceFormatter(), theme: InstructionRowTheme = DefaultInstructionRowTheme, - content: @Composable () -> Unit = { - ManeuverImage(instructions.primaryContent, tint = MaterialTheme.colorScheme.primary) + remainingSteps: List? = null, + initExpanded: Boolean = false, + contentBuilder: @Composable (VisualInstruction) -> Unit = { + ManeuverImage(it.primaryContent, tint = MaterialTheme.colorScheme.primary) } ) { - Column( + var isExpanded by remember { mutableStateOf(initExpanded) } + val screenHeight = LocalConfiguration.current.screenHeightDp.dp + + Box( modifier = Modifier.fillMaxWidth() - .shadow(elevation = 5.dp, RoundedCornerShape(10.dp)) + .heightIn(max = screenHeight) + .animateContentSize(animationSpec = spring(stiffness = Spring.StiffnessHigh)) .background(theme.backgroundColor, RoundedCornerShape(10.dp)) - .padding(8.dp)) { - ManeuverInstructionView( - text = instructions.primaryContent.text, - distanceFormatter = distanceFormatter, - distanceToNextManeuver = distanceToNextManeuver, - theme = theme, - content = content) - // TODO: Secondary instructions + .clickable { isExpanded = true }) { + Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) { + // Primary content + ManeuverInstructionView( + text = instructions.primaryContent.text, + distanceFormatter = distanceFormatter, + distanceToNextManeuver = distanceToNextManeuver, + theme = theme) { + contentBuilder(instructions) + } + + // TODO: Secondary content + + // Expanded content + val showMultipleRows = isExpanded && remainingSteps != null && remainingSteps.count() > 1 + if (showMultipleRows) { + Spacer(modifier = Modifier.height(8.dp)) + HorizontalDivider(thickness = 1.dp) + Spacer(modifier = Modifier.height(8.dp)) + } + + if (isExpanded) { + Box(modifier = Modifier.weight(1f)) { + LazyColumn( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(8.dp)) { + if (remainingSteps != null) { + items(remainingSteps.drop(1)) { step -> + step.visualInstructions.firstOrNull()?.let { upcomingInstruction -> + ManeuverInstructionView( + text = upcomingInstruction.primaryContent.text, + distanceFormatter = distanceFormatter, + distanceToNextManeuver = step.distance, + theme = theme) { + contentBuilder(upcomingInstruction) + } + Spacer(modifier = Modifier.height(8.dp)) + HorizontalDivider(thickness = 1.dp) + } + } + } + } + } + } + + if (showMultipleRows) { + Spacer(modifier = Modifier.height(16.dp)) + } + } + + PillDragHandle( + isExpanded, + // The modifier here lets us keep the container as slim as possible + modifier = + Modifier.offset { + IntOffset( + 0, + if (isExpanded) { + (-4 * density).toInt() + } else { + (-8 * density).toInt() + }) + } + .align(Alignment.BottomCenter), + iconTintColor = theme.iconTintColor) { + isExpanded = !isExpanded + } } } diff --git a/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/views/controls/PillDragHandle.kt b/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/views/controls/PillDragHandle.kt new file mode 100644 index 00000000..1eb7af00 --- /dev/null +++ b/android/composeui/src/main/java/com/stadiamaps/ferrostar/composeui/views/controls/PillDragHandle.kt @@ -0,0 +1,68 @@ +package com.stadiamaps.ferrostar.composeui.views.controls + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.KeyboardArrowUp +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.onClick +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +@Composable +fun PillDragHandle( + isExpanded: Boolean, + modifier: Modifier = Modifier.fillMaxWidth(), + iconTintColor: Color = MaterialTheme.colorScheme.onSurface, + toggle: () -> Unit = {} +) { + val handleHeight = if (isExpanded) 36.dp else 4.dp + Box(modifier = modifier.height(handleHeight).clickable(onClick = toggle)) { + if (isExpanded) { + Icon( + Icons.Rounded.KeyboardArrowUp, + modifier = Modifier.align(Alignment.Center), + contentDescription = "Show upcoming maneuvers", + tint = iconTintColor) + } else { + Box( + modifier = + Modifier.align(Alignment.Center) + .height(handleHeight) + .width(24.dp) + .background(iconTintColor, RoundedCornerShape(6.dp)) + .semantics { + role = Role.Button + onClick(label = "Hide upcoming maneuvers") { + toggle() + true + } + }) + } + } +} + +@Preview +@Composable +fun PreviewPillDragHandleCollapsed() { + PillDragHandle(isExpanded = false, iconTintColor = Color.White) +} + +@Preview +@Composable +fun PreviewPillDragHandleExpanded() { + PillDragHandle(isExpanded = true, iconTintColor = Color.White) +} diff --git a/android/composeui/src/test/java/com/stadiamaps/ferrostar/views/InstructionViewTest.kt b/android/composeui/src/test/java/com/stadiamaps/ferrostar/views/InstructionViewTest.kt index 3850680d..4f356d16 100644 --- a/android/composeui/src/test/java/com/stadiamaps/ferrostar/views/InstructionViewTest.kt +++ b/android/composeui/src/test/java/com/stadiamaps/ferrostar/views/InstructionViewTest.kt @@ -1,6 +1,8 @@ package com.stadiamaps.ferrostar.views import com.stadiamaps.ferrostar.composeui.views.InstructionsView +import com.stadiamaps.ferrostar.core.NavigationUiState +import com.stadiamaps.ferrostar.core.mock.pedestrianExample import com.stadiamaps.ferrostar.support.paparazziDefault import com.stadiamaps.ferrostar.support.withSnapshotBackground import org.junit.Rule @@ -35,4 +37,19 @@ class InstructionViewTest { } } } + + @Test + fun testInstructionViewExpanded() { + val state = NavigationUiState.pedestrianExample() + + paparazzi.snapshot { + withSnapshotBackground { + InstructionsView( + instructions = state.visualInstruction!!, + remainingSteps = state.remainingSteps, + distanceToNextManeuver = 42.0, + initExpanded = true) + } + } + } } diff --git a/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_InstructionViewTest_testInstructionView.png b/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_InstructionViewTest_testInstructionView.png index 5ba73ea3..e427e067 100644 Binary files a/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_InstructionViewTest_testInstructionView.png and b/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_InstructionViewTest_testInstructionView.png differ diff --git a/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_InstructionViewTest_testInstructionViewExpanded.png b/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_InstructionViewTest_testInstructionViewExpanded.png new file mode 100644 index 00000000..a4e3b9f7 Binary files /dev/null and b/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_InstructionViewTest_testInstructionViewExpanded.png differ diff --git a/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_RTLInstructionViewTests_testRTLInstructionView.png b/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_RTLInstructionViewTests_testRTLInstructionView.png index 01b134a0..2546b01e 100644 Binary files a/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_RTLInstructionViewTests_testRTLInstructionView.png and b/android/composeui/src/test/snapshots/images/com.stadiamaps.ferrostar.views_RTLInstructionViewTests_testRTLInstructionView.png differ diff --git a/android/core/src/main/java/com/stadiamaps/ferrostar/core/Location.kt b/android/core/src/main/java/com/stadiamaps/ferrostar/core/Location.kt index 827eaa97..3e2ecb4c 100644 --- a/android/core/src/main/java/com/stadiamaps/ferrostar/core/Location.kt +++ b/android/core/src/main/java/com/stadiamaps/ferrostar/core/Location.kt @@ -20,6 +20,7 @@ import kotlinx.coroutines.launch import uniffi.ferrostar.CourseOverGround import uniffi.ferrostar.GeographicCoordinate import uniffi.ferrostar.Heading +import uniffi.ferrostar.LocationBias import uniffi.ferrostar.LocationSimulationState import uniffi.ferrostar.Route import uniffi.ferrostar.Speed @@ -155,7 +156,7 @@ class SimulatedLocationProvider : LocationProvider { override fun addListener(listener: LocationUpdateListener, executor: Executor) { listeners.add(listener to executor) - if (simulationJob == null) { + if (simulationJob?.isActive != true) { simulationJob = scope.launch { startSimulation() } } } @@ -168,11 +169,11 @@ class SimulatedLocationProvider : LocationProvider { } } - fun setSimulatedRoute(route: Route) { - simulationState = locationSimulationFromRoute(route, resampleDistance = 10.0) + fun setSimulatedRoute(route: Route, bias: LocationBias = LocationBias.None) { + simulationState = locationSimulationFromRoute(route, resampleDistance = 10.0, bias) lastLocation = simulationState?.currentLocation - if (listeners.isNotEmpty() && simulationJob == null) { + if (listeners.isNotEmpty() && simulationJob?.isActive != true) { simulationJob = scope.launch { startSimulation() } } } diff --git a/android/core/src/main/java/com/stadiamaps/ferrostar/core/NavigationViewModel.kt b/android/core/src/main/java/com/stadiamaps/ferrostar/core/NavigationViewModel.kt index 779d43b1..5bd011cd 100644 --- a/android/core/src/main/java/com/stadiamaps/ferrostar/core/NavigationViewModel.kt +++ b/android/core/src/main/java/com/stadiamaps/ferrostar/core/NavigationViewModel.kt @@ -8,13 +8,17 @@ import com.stadiamaps.ferrostar.core.annotation.NoOpAnnotationPublisher import com.stadiamaps.ferrostar.core.extensions.currentRoadName import com.stadiamaps.ferrostar.core.extensions.deviation import com.stadiamaps.ferrostar.core.extensions.progress +import com.stadiamaps.ferrostar.core.extensions.remainingSteps import com.stadiamaps.ferrostar.core.extensions.visualInstruction +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import uniffi.ferrostar.GeographicCoordinate import uniffi.ferrostar.RouteDeviation +import uniffi.ferrostar.RouteStep import uniffi.ferrostar.SpokenInstruction import uniffi.ferrostar.TripProgress import uniffi.ferrostar.TripState @@ -51,7 +55,9 @@ data class NavigationUiState( /** If true, spoken instructions will not be synthesized. */ val isMuted: Boolean?, /** The name of the road which the current route step is traversing. */ - val currentStepRoadName: String? + val currentStepRoadName: String?, + /** The remaining steps in the trip (including the current step). */ + val remainingSteps: List? ) { companion object { fun fromFerrostar( @@ -72,7 +78,8 @@ data class NavigationUiState( isCalculatingNewRoute = coreState.isCalculatingNewRoute, routeDeviation = coreState.tripState.deviation(), isMuted = isMuted, - currentStepRoadName = coreState.tripState.currentRoadName()) + currentStepRoadName = coreState.tripState.currentRoadName(), + remainingSteps = coreState.tripState.remainingSteps()) } } @@ -97,11 +104,13 @@ class DefaultNavigationViewModel( ) : ViewModel(), NavigationViewModel { private var userLocation: UserLocation? = locationProvider.lastLocation + private val muteState: StateFlow = + spokenInstructionObserver?.muteState ?: MutableStateFlow(null) override val uiState = - ferrostarCore.state - .map { annotationPublisher.map(it) } - .map { stateWrapper -> + combine(ferrostarCore.state, muteState) { a, b -> a to b } + .map { (coreState, muteState) -> annotationPublisher.map(coreState) to muteState } + .map { (stateWrapper, muteState) -> val coreState = stateWrapper.state val location = locationProvider.lastLocation userLocation = @@ -110,7 +119,7 @@ class DefaultNavigationViewModel( is TripState.Complete, TripState.Idle -> locationProvider.lastLocation } - uiState(coreState, spokenInstructionObserver?.isMuted, location, userLocation) + uiState(coreState, muteState, location, userLocation) // This awkward dance is required because Kotlin doesn't have a way to map over // StateFlows // without converting to a generic Flow in the process. @@ -134,7 +143,7 @@ class DefaultNavigationViewModel( Log.d("NavigationViewModel", "Spoken instruction observer is null, mute operation ignored.") return } - spokenInstructionObserver.isMuted = !spokenInstructionObserver.isMuted + spokenInstructionObserver.setMuted(!spokenInstructionObserver.isMuted) } // TODO: We can add a hook here to override the current road name. diff --git a/android/core/src/main/java/com/stadiamaps/ferrostar/core/Speech.kt b/android/core/src/main/java/com/stadiamaps/ferrostar/core/Speech.kt index 2a101247..d1d6713b 100644 --- a/android/core/src/main/java/com/stadiamaps/ferrostar/core/Speech.kt +++ b/android/core/src/main/java/com/stadiamaps/ferrostar/core/Speech.kt @@ -3,6 +3,10 @@ package com.stadiamaps.ferrostar.core import android.content.Context import android.speech.tts.TextToSpeech import android.speech.tts.TextToSpeech.OnInitListener +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update import uniffi.ferrostar.SpokenInstruction interface SpokenInstructionObserver { @@ -17,7 +21,12 @@ interface SpokenInstructionObserver { /** Stops speech and clears the queue of spoken utterances. */ fun stopAndClearQueue() - var isMuted: Boolean + fun setMuted(isMuted: Boolean) + + val muteState: StateFlow + + val isMuted: Boolean + get() = muteState.value } /** Observes the status of an [AndroidTtsObserver]. */ @@ -62,14 +71,18 @@ class AndroidTtsObserver( private const val TAG = "AndroidTtsObserver" } - override var isMuted: Boolean = false - set(value) { - field = value + private var _muteState: MutableStateFlow = MutableStateFlow(false) - if (value && tts?.isSpeaking == true) { + override fun setMuted(isMuted: Boolean) { + _muteState.update { _ -> + if (isMuted && tts?.isSpeaking == true) { tts?.stop() } + isMuted } + } + + override val muteState: StateFlow = _muteState.asStateFlow() var tts: TextToSpeech? private set diff --git a/android/core/src/main/java/com/stadiamaps/ferrostar/core/extensions/TripStateExtensions.kt b/android/core/src/main/java/com/stadiamaps/ferrostar/core/extensions/TripStateExtensions.kt index f045cb91..b5ca06a0 100644 --- a/android/core/src/main/java/com/stadiamaps/ferrostar/core/extensions/TripStateExtensions.kt +++ b/android/core/src/main/java/com/stadiamaps/ferrostar/core/extensions/TripStateExtensions.kt @@ -60,3 +60,15 @@ fun TripState.currentRoadName() = is TripState.Complete, TripState.Idle -> null } + +/** + * Get the remaining steps (including the current) in the current trip. + * + * @return The list of remaining steps (if any). + */ +fun TripState.remainingSteps() = + when (this) { + is TripState.Navigating -> this.remainingSteps + is TripState.Complete, + TripState.Idle -> null + } diff --git a/android/demo-app/src/main/java/com/stadiamaps/ferrostar/DemoNavigationViewModel.kt b/android/demo-app/src/main/java/com/stadiamaps/ferrostar/DemoNavigationViewModel.kt index 16c7c6cf..40d59d91 100644 --- a/android/demo-app/src/main/java/com/stadiamaps/ferrostar/DemoNavigationViewModel.kt +++ b/android/demo-app/src/main/java/com/stadiamaps/ferrostar/DemoNavigationViewModel.kt @@ -42,7 +42,7 @@ class DemoNavigationViewModel : ViewModel(), NavigationViewModel { .map { userLocation -> // TODO: Heading NavigationUiState( - userLocation, null, null, null, null, null, null, false, null, null, null) + userLocation, null, null, null, null, null, null, false, null, null, null, null) } .stateIn( scope = viewModelScope, @@ -50,7 +50,7 @@ class DemoNavigationViewModel : ViewModel(), NavigationViewModel { // TODO: Heading initialValue = NavigationUiState( - null, null, null, null, null, null, null, false, null, null, null)) + null, null, null, null, null, null, null, false, null, null, null, null)) override fun toggleMute() { // Do nothing diff --git a/android/gradle.properties b/android/gradle.properties index 3c5031eb..0b4df693 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -6,7 +6,7 @@ # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 2f5659aa..2deebe99 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -1,9 +1,9 @@ [versions] -agp = "8.7.1" +agp = "8.7.2" kotlin = "2.0.20" cargo-ndk = "0.3.4" ktfmt = "0.20.1" -androidx-lifecycle = "2.8.6" +androidx-lifecycle = "2.8.7" paparazzi = "1.3.4" desugar_jdk_libs = "2.1.2" ktx = "1.13.1" @@ -18,10 +18,10 @@ maplibre-compose = "0.2.3" playServicesLocation = "21.3.0" junit = "4.13.2" junitVersion = "1.2.1" -junitCompose = "1.7.4" +junitCompose = "1.7.5" espressoCore = "3.6.1" okhttp-mock = "2.0.0" -mavenPublish = "0.29.0" +mavenPublish = "0.30.0" material = "1.12.0" stadiaAutocompleteSearch = "1.0.0" diff --git a/android/maplibreui/src/main/java/com/stadiamaps/ferrostar/maplibreui/views/overlays/LandscapeNavigationOverlayView.kt b/android/maplibreui/src/main/java/com/stadiamaps/ferrostar/maplibreui/views/overlays/LandscapeNavigationOverlayView.kt index f3855f4a..790f144e 100644 --- a/android/maplibreui/src/main/java/com/stadiamaps/ferrostar/maplibreui/views/overlays/LandscapeNavigationOverlayView.kt +++ b/android/maplibreui/src/main/java/com/stadiamaps/ferrostar/maplibreui/views/overlays/LandscapeNavigationOverlayView.kt @@ -54,7 +54,9 @@ fun LandscapeNavigationOverlayView( Column(modifier = Modifier.fillMaxHeight().fillMaxWidth(0.5f)) { uiState.visualInstruction?.let { instructions -> InstructionsView( - instructions, distanceToNextManeuver = uiState.progress?.distanceToNextManeuver) + instructions, + remainingSteps = uiState.remainingSteps, + distanceToNextManeuver = uiState.progress?.distanceToNextManeuver) } Spacer(modifier = Modifier.weight(1f)) diff --git a/android/maplibreui/src/main/java/com/stadiamaps/ferrostar/maplibreui/views/overlays/PortraitNavigationOverlayView.kt b/android/maplibreui/src/main/java/com/stadiamaps/ferrostar/maplibreui/views/overlays/PortraitNavigationOverlayView.kt index f378a657..c2bf2fd8 100644 --- a/android/maplibreui/src/main/java/com/stadiamaps/ferrostar/maplibreui/views/overlays/PortraitNavigationOverlayView.kt +++ b/android/maplibreui/src/main/java/com/stadiamaps/ferrostar/maplibreui/views/overlays/PortraitNavigationOverlayView.kt @@ -57,7 +57,9 @@ fun PortraitNavigationOverlayView( Column(modifier) { uiState.visualInstruction?.let { instructions -> InstructionsView( - instructions, distanceToNextManeuver = uiState.progress?.distanceToNextManeuver) + instructions, + remainingSteps = uiState.remainingSteps, + distanceToNextManeuver = uiState.progress?.distanceToNextManeuver) } val cameraIsTrackingLocation = camera.value.state is CameraState.TrackingUserLocationWithBearing diff --git a/apple/DemoApp/Demo/DemoNavigationView.swift b/apple/DemoApp/Demo/DemoNavigationView.swift index c69f9913..2f8ecfb3 100644 --- a/apple/DemoApp/Demo/DemoNavigationView.swift +++ b/apple/DemoApp/Demo/DemoNavigationView.swift @@ -16,7 +16,7 @@ struct DemoNavigationView: View { private let navigationDelegate = NavigationDelegate() // NOTE: This is probably not ideal but works for demo purposes. // This causes a thread performance checker warning log. - private let spokenInstructionObserver = SpokenInstructionObserver.initAVSpeechSynthesizer(isMuted: false) + @State private var spokenInstructionObserver = SpokenInstructionObserver.initAVSpeechSynthesizer() private var locationProvider: LocationProviding @ObservedObject private var ferrostarCore: FerrostarCore @@ -143,7 +143,6 @@ struct DemoNavigationView: View { .font(.body.bold()) } .disabled(routes?.isEmpty == true) - .shadow(radius: 10) } } else { NavigationUIButton { diff --git a/apple/Sources/FerrostarCore/Location.swift b/apple/Sources/FerrostarCore/Location.swift index 23db3c26..2fa33b63 100644 --- a/apple/Sources/FerrostarCore/Location.swift +++ b/apple/Sources/FerrostarCore/Location.swift @@ -156,8 +156,16 @@ public class SimulatedLocationProvider: LocationProviding, ObservableObject { lastLocation = location } - public func setSimulatedRoute(_ route: Route, resampleDistance: Double = 10) throws { - simulationState = try locationSimulationFromRoute(route: route, resampleDistance: resampleDistance) + public func setSimulatedRoute( + _ route: Route, + resampleDistance: Double = 10, + bias: LocationBias = .none + ) throws { + simulationState = try locationSimulationFromRoute( + route: route, + resampleDistance: resampleDistance, + bias: bias + ) lastLocation = simulationState?.currentLocation } diff --git a/apple/Sources/FerrostarCore/Speech/SpokenInstructionObserver.swift b/apple/Sources/FerrostarCore/Speech/SpokenInstructionObserver.swift index a4e86755..f484a244 100644 --- a/apple/Sources/FerrostarCore/Speech/SpokenInstructionObserver.swift +++ b/apple/Sources/FerrostarCore/Speech/SpokenInstructionObserver.swift @@ -7,7 +7,7 @@ import Foundation public class SpokenInstructionObserver: ObservableObject { @Published public private(set) var isMuted: Bool - private let synthesizer: SpeechSynthesizer + let synthesizer: SpeechSynthesizer private let queue = DispatchQueue(label: "ferrostar-spoken-instruction-observer", qos: .default) /// Create a spoken instruction observer with any ``SpeechSynthesizer`` @@ -28,16 +28,16 @@ public class SpokenInstructionObserver: ObservableObject { return } - let utterance: AVSpeechUtterance = if #available(iOS 16.0, *), - let ssml = instruction.ssml, - let ssmlUtterance = AVSpeechUtterance(ssmlRepresentation: ssml) - { - ssmlUtterance - } else { - AVSpeechUtterance(string: instruction.text) - } - queue.async { + let utterance: AVSpeechUtterance = if #available(iOS 16.0, *), + let ssml = instruction.ssml, + let ssmlUtterance = AVSpeechUtterance(ssmlRepresentation: ssml) + { + ssmlUtterance + } else { + AVSpeechUtterance(string: instruction.text) + } + self.synthesizer.speak(utterance) } } diff --git a/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIButton.swift b/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIButton.swift index 33ae5dc9..c92015ee 100644 --- a/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIButton.swift +++ b/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIButton.swift @@ -11,6 +11,7 @@ public struct NavigationUIButtonStyle: ButtonStyle { .foregroundStyle(.primary) .clipShape(Capsule()) .frame(minWidth: 52, minHeight: 52) + .shadow(radius: 8) } } diff --git a/apple/Sources/FerrostarSwiftUI/Views/Controls/MuteUIButton.swift b/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIMuteButton.swift similarity index 61% rename from apple/Sources/FerrostarSwiftUI/Views/Controls/MuteUIButton.swift rename to apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIMuteButton.swift index a204e6c8..31881a03 100644 --- a/apple/Sources/FerrostarSwiftUI/Views/Controls/MuteUIButton.swift +++ b/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIMuteButton.swift @@ -1,8 +1,7 @@ import FerrostarCore -import FerrostarCoreFFI import SwiftUI -public struct MuteUIButton: View { +public struct NavigationUIMuteButton: View { let isMuted: Bool let action: () -> Void @@ -12,21 +11,19 @@ public struct MuteUIButton: View { } public var body: some View { - Button(action: action) { + NavigationUIButton(action: action) { Image(systemName: isMuted ? "speaker.slash.fill" : "speaker.2.fill") .resizable() .aspectRatio(contentMode: .fit) .frame(width: 18, height: 18) - .padding() } - .foregroundColor(.black) - .background(Color.white) - .clipShape(Circle()) } } #Preview { - MuteUIButton(isMuted: true, action: {}) + VStack { + NavigationUIMuteButton(isMuted: true, action: {}) - MuteUIButton(isMuted: false, action: {}) + NavigationUIMuteButton(isMuted: false, action: {}) + } } diff --git a/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIZoomButton.swift b/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIZoomButton.swift index 60c58351..af91836d 100644 --- a/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIZoomButton.swift +++ b/apple/Sources/FerrostarSwiftUI/Views/Controls/NavigationUIZoomButton.swift @@ -34,6 +34,7 @@ public struct NavigationUIZoomButton: View { .foregroundColor(.primary) .background(Color(.systemBackground)) .clipShape(Capsule()) + .shadow(radius: 8) } } diff --git a/apple/Sources/FerrostarSwiftUI/Views/GridViews/NavigatingInnerGridView.swift b/apple/Sources/FerrostarSwiftUI/Views/GridViews/NavigatingInnerGridView.swift index 28bbc01f..5f89237b 100644 --- a/apple/Sources/FerrostarSwiftUI/Views/GridViews/NavigatingInnerGridView.swift +++ b/apple/Sources/FerrostarSwiftUI/Views/GridViews/NavigatingInnerGridView.swift @@ -87,8 +87,7 @@ public struct NavigatingInnerGridView: View, CustomizableNavigatingInnerGridView topCenter: { topCenter?() }, topTrailing: { if showMute { - MuteUIButton(isMuted: isMuted, action: onMute) - .shadow(radius: 8) + NavigationUIMuteButton(isMuted: isMuted, action: onMute) } }, midLeading: { midLeading?() }, @@ -99,7 +98,6 @@ public struct NavigatingInnerGridView: View, CustomizableNavigatingInnerGridView midTrailing: { if showZoom { NavigationUIZoomButton(onZoomIn: onZoomIn, onZoomOut: onZoomOut) - .shadow(radius: 8) } else { Spacer() } @@ -112,7 +110,6 @@ public struct NavigatingInnerGridView: View, CustomizableNavigatingInnerGridView .aspectRatio(contentMode: .fit) .frame(width: 18, height: 18) } - .shadow(radius: 8) } else { Spacer() } diff --git a/apple/Sources/UniFFI/ferrostar.swift b/apple/Sources/UniFFI/ferrostar.swift index 00af66e6..cd157817 100644 --- a/apple/Sources/UniFFI/ferrostar.swift +++ b/apple/Sources/UniFFI/ferrostar.swift @@ -1,3 +1,6 @@ +// This file was autogenerated by some hot garbage in the `uniffi` crate. +// Trust me, you don't want to mess with it! + // swiftlint:disable all import Foundation @@ -5,10 +8,10 @@ import Foundation // might be in a separate module, or it might be compiled inline into // this module. This is a bit of light hackery to work with both. #if canImport(ferrostarFFI) - import ferrostarFFI +import ferrostarFFI #endif -private extension RustBuffer { +fileprivate extension RustBuffer { // Allocate a new buffer, copying the contents of a `UInt8` array. init(bytes: [UInt8]) { let rbuf = bytes.withUnsafeBufferPointer { ptr in @@ -18,7 +21,7 @@ private extension RustBuffer { } static func empty() -> RustBuffer { - RustBuffer(capacity: 0, len: 0, data: nil) + RustBuffer(capacity: 0, len:0, data: nil) } static func from(_ ptr: UnsafeBufferPointer) -> RustBuffer { @@ -32,7 +35,7 @@ private extension RustBuffer { } } -private extension ForeignBytes { +fileprivate extension ForeignBytes { init(bufferPointer: UnsafeBufferPointer) { self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress) } @@ -45,7 +48,7 @@ private extension ForeignBytes { // Helper classes/extensions that don't change. // Someday, this will be in a library of its own. -private extension Data { +fileprivate extension Data { init(rustBuffer: RustBuffer) { self.init( bytesNoCopy: rustBuffer.data!, @@ -69,15 +72,15 @@ private extension Data { // // Instead, the read() method and these helper functions input a tuple of data -private func createReader(data: Data) -> (data: Data, offset: Data.Index) { +fileprivate func createReader(data: Data) -> (data: Data, offset: Data.Index) { (data: data, offset: 0) } // Reads an integer at the current offset, in big-endian order, and advances // the offset on success. Throws if reading the integer would move the // offset past the end of the buffer. -private func readInt(_ reader: inout (data: Data, offset: Data.Index)) throws -> T { - let range = reader.offset ..< reader.offset + MemoryLayout.size +fileprivate func readInt(_ reader: inout (data: Data, offset: Data.Index)) throws -> T { + let range = reader.offset...size guard reader.data.count >= range.upperBound else { throw UniffiInternalError.bufferOverflow } @@ -87,50 +90,50 @@ private func readInt(_ reader: inout (data: Data, offset: return value as! T } var value: T = 0 - let _ = withUnsafeMutableBytes(of: &value) { reader.data.copyBytes(to: $0, from: range) } + let _ = withUnsafeMutableBytes(of: &value, { reader.data.copyBytes(to: $0, from: range)}) reader.offset = range.upperBound return value.bigEndian } // Reads an arbitrary number of bytes, to be used to read // raw bytes, this is useful when lifting strings -private func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> [UInt8] { - let range = reader.offset ..< (reader.offset + count) +fileprivate func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> Array { + let range = reader.offset..<(reader.offset+count) guard reader.data.count >= range.upperBound else { throw UniffiInternalError.bufferOverflow } var value = [UInt8](repeating: 0, count: count) - value.withUnsafeMutableBufferPointer { buffer in + value.withUnsafeMutableBufferPointer({ buffer in reader.data.copyBytes(to: buffer, from: range) - } + }) reader.offset = range.upperBound return value } // Reads a float at the current offset. -private func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float { - try Float(bitPattern: readInt(&reader)) +fileprivate func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float { + return Float(bitPattern: try readInt(&reader)) } // Reads a float at the current offset. -private func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double { - try Double(bitPattern: readInt(&reader)) +fileprivate func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double { + return Double(bitPattern: try readInt(&reader)) } // Indicates if the offset has reached the end of the buffer. -private func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool { - reader.offset < reader.data.count +fileprivate func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool { + return reader.offset < reader.data.count } // Define writer functionality. Normally this would be defined in a class or // struct, but we use standalone functions instead in order to make external // types work. See the above discussion on Readers for details. -private func createWriter() -> [UInt8] { - [] +fileprivate func createWriter() -> [UInt8] { + return [] } -private func writeBytes(_ writer: inout [UInt8], _ byteArr: some Sequence) { +fileprivate func writeBytes(_ writer: inout [UInt8], _ byteArr: S) where S: Sequence, S.Element == UInt8 { writer.append(contentsOf: byteArr) } @@ -138,22 +141,22 @@ private func writeBytes(_ writer: inout [UInt8], _ byteArr: some Sequence // // Warning: make sure what you are trying to write // is in the correct type! -private func writeInt(_ writer: inout [UInt8], _ value: some FixedWidthInteger) { +fileprivate func writeInt(_ writer: inout [UInt8], _ value: T) { var value = value.bigEndian withUnsafeBytes(of: &value) { writer.append(contentsOf: $0) } } -private func writeFloat(_ writer: inout [UInt8], _ value: Float) { +fileprivate func writeFloat(_ writer: inout [UInt8], _ value: Float) { writeInt(&writer, value.bitPattern) } -private func writeDouble(_ writer: inout [UInt8], _ value: Double) { +fileprivate func writeDouble(_ writer: inout [UInt8], _ value: Double) { writeInt(&writer, value.bitPattern) } // Protocol for types that transfer other types across the FFI. This is // analogous to the Rust trait of the same name. -private protocol FfiConverter { +fileprivate protocol FfiConverter { associatedtype FfiType associatedtype SwiftType @@ -164,23 +167,32 @@ private protocol FfiConverter { } // Types conforming to `Primitive` pass themselves directly over the FFI. -private protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType {} +fileprivate protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType { } extension FfiConverterPrimitive { +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public static func lift(_ value: FfiType) throws -> SwiftType { - value + return value } +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public static func lower(_ value: SwiftType) -> FfiType { - value + return value } } // Types conforming to `FfiConverterRustBuffer` lift and lower into a `RustBuffer`. // Used for complex types where it's hard to write a custom lift/lower. -private protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {} +fileprivate protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {} extension FfiConverterRustBuffer { +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public static func lift(_ buf: RustBuffer) throws -> SwiftType { var reader = createReader(data: Data(rustBuffer: buf)) let value = try read(from: &reader) @@ -191,16 +203,18 @@ extension FfiConverterRustBuffer { return value } +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public static func lower(_ value: SwiftType) -> RustBuffer { - var writer = createWriter() - write(value, into: &writer) - return RustBuffer(bytes: writer) + var writer = createWriter() + write(value, into: &writer) + return RustBuffer(bytes: writer) } } - // An error type for FFI errors. These errors occur at the UniFFI level, not // the library level. -private enum UniffiInternalError: LocalizedError { +fileprivate enum UniffiInternalError: LocalizedError { case bufferOverflow case incompleteData case unexpectedOptionalTag @@ -213,37 +227,37 @@ private enum UniffiInternalError: LocalizedError { public var errorDescription: String? { switch self { - case .bufferOverflow: "Reading the requested value would read past the end of the buffer" - case .incompleteData: "The buffer still has data after lifting its containing value" - case .unexpectedOptionalTag: "Unexpected optional tag; should be 0 or 1" - case .unexpectedEnumCase: "Raw enum value doesn't match any cases" - case .unexpectedNullPointer: "Raw pointer value was null" - case .unexpectedRustCallStatusCode: "Unexpected RustCallStatus code" - case .unexpectedRustCallError: "CALL_ERROR but no errorClass specified" - case .unexpectedStaleHandle: "The object in the handle map has been dropped already" - case let .rustPanic(message): message + case .bufferOverflow: return "Reading the requested value would read past the end of the buffer" + case .incompleteData: return "The buffer still has data after lifting its containing value" + case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1" + case .unexpectedEnumCase: return "Raw enum value doesn't match any cases" + case .unexpectedNullPointer: return "Raw pointer value was null" + case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code" + case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified" + case .unexpectedStaleHandle: return "The object in the handle map has been dropped already" + case let .rustPanic(message): return message } } } -private extension NSLock { +fileprivate extension NSLock { func withLock(f: () throws -> T) rethrows -> T { - lock() + self.lock() defer { self.unlock() } return try f() } } -private let CALL_SUCCESS: Int8 = 0 -private let CALL_ERROR: Int8 = 1 -private let CALL_UNEXPECTED_ERROR: Int8 = 2 -private let CALL_CANCELLED: Int8 = 3 +fileprivate let CALL_SUCCESS: Int8 = 0 +fileprivate let CALL_ERROR: Int8 = 1 +fileprivate let CALL_UNEXPECTED_ERROR: Int8 = 2 +fileprivate let CALL_CANCELLED: Int8 = 3 -private extension RustCallStatus { +fileprivate extension RustCallStatus { init() { self.init( code: CALL_SUCCESS, - errorBuf: RustBuffer( + errorBuf: RustBuffer.init( capacity: 0, len: 0, data: nil @@ -257,67 +271,66 @@ private func rustCall(_ callback: (UnsafeMutablePointer) -> T return try makeRustCall(callback, errorHandler: neverThrow) } -private func rustCallWithError( - _ errorHandler: @escaping (RustBuffer) throws -> some Swift.Error, - _ callback: (UnsafeMutablePointer) -> T -) throws -> T { +private func rustCallWithError( + _ errorHandler: @escaping (RustBuffer) throws -> E, + _ callback: (UnsafeMutablePointer) -> T) throws -> T { try makeRustCall(callback, errorHandler: errorHandler) } -private func makeRustCall( +private func makeRustCall( _ callback: (UnsafeMutablePointer) -> T, - errorHandler: ((RustBuffer) throws -> some Swift.Error)? + errorHandler: ((RustBuffer) throws -> E)? ) throws -> T { uniffiEnsureInitialized() - var callStatus = RustCallStatus() + var callStatus = RustCallStatus.init() let returnedVal = callback(&callStatus) try uniffiCheckCallStatus(callStatus: callStatus, errorHandler: errorHandler) return returnedVal } -private func uniffiCheckCallStatus( +private func uniffiCheckCallStatus( callStatus: RustCallStatus, - errorHandler: ((RustBuffer) throws -> some Swift.Error)? + errorHandler: ((RustBuffer) throws -> E)? ) throws { switch callStatus.code { - case CALL_SUCCESS: - return + case CALL_SUCCESS: + return - case CALL_ERROR: - if let errorHandler { - throw try errorHandler(callStatus.errorBuf) - } else { - callStatus.errorBuf.deallocate() - throw UniffiInternalError.unexpectedRustCallError - } + case CALL_ERROR: + if let errorHandler = errorHandler { + throw try errorHandler(callStatus.errorBuf) + } else { + callStatus.errorBuf.deallocate() + throw UniffiInternalError.unexpectedRustCallError + } - case CALL_UNEXPECTED_ERROR: - // When the rust code sees a panic, it tries to construct a RustBuffer - // with the message. But if that code panics, then it just sends back - // an empty buffer. - if callStatus.errorBuf.len > 0 { - throw try UniffiInternalError.rustPanic(FfiConverterString.lift(callStatus.errorBuf)) - } else { - callStatus.errorBuf.deallocate() - throw UniffiInternalError.rustPanic("Rust panic") - } + case CALL_UNEXPECTED_ERROR: + // When the rust code sees a panic, it tries to construct a RustBuffer + // with the message. But if that code panics, then it just sends back + // an empty buffer. + if callStatus.errorBuf.len > 0 { + throw UniffiInternalError.rustPanic(try FfiConverterString.lift(callStatus.errorBuf)) + } else { + callStatus.errorBuf.deallocate() + throw UniffiInternalError.rustPanic("Rust panic") + } - case CALL_CANCELLED: - fatalError("Cancellation not supported yet") + case CALL_CANCELLED: + fatalError("Cancellation not supported yet") - default: - throw UniffiInternalError.unexpectedRustCallStatusCode + default: + throw UniffiInternalError.unexpectedRustCallStatusCode } } private func uniffiTraitInterfaceCall( callStatus: UnsafeMutablePointer, makeCall: () throws -> T, - writeReturn: (T) -> Void + writeReturn: (T) -> () ) { do { try writeReturn(makeCall()) - } catch { + } catch let error { callStatus.pointee.code = CALL_UNEXPECTED_ERROR callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error)) } @@ -326,7 +339,7 @@ private func uniffiTraitInterfaceCall( private func uniffiTraitInterfaceCallWithError( callStatus: UnsafeMutablePointer, makeCall: () throws -> T, - writeReturn: (T) -> Void, + writeReturn: (T) -> (), lowerError: (E) -> RustBuffer ) { do { @@ -339,8 +352,7 @@ private func uniffiTraitInterfaceCallWithError( callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error)) } } - -private class UniffiHandleMap { +fileprivate class UniffiHandleMap { private var map: [UInt64: T] = [:] private let lock = NSLock() private var currentHandle: UInt64 = 1 @@ -354,7 +366,7 @@ private class UniffiHandleMap { } } - func get(handle: UInt64) throws -> T { + func get(handle: UInt64) throws -> T { try lock.withLock { guard let obj = map[handle] else { throw UniffiInternalError.unexpectedStaleHandle @@ -374,18 +386,25 @@ private class UniffiHandleMap { } var count: Int { - map.count + get { + map.count + } } } + // Public interface members begin here. -private struct FfiConverterUInt16: FfiConverterPrimitive { + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterUInt16: FfiConverterPrimitive { typealias FfiType = UInt16 typealias SwiftType = UInt16 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt16 { - try lift(readInt(&buf)) + return try lift(readInt(&buf)) } public static func write(_ value: SwiftType, into buf: inout [UInt8]) { @@ -393,12 +412,15 @@ private struct FfiConverterUInt16: FfiConverterPrimitive { } } -private struct FfiConverterUInt32: FfiConverterPrimitive { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterUInt32: FfiConverterPrimitive { typealias FfiType = UInt32 typealias SwiftType = UInt32 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt32 { - try lift(readInt(&buf)) + return try lift(readInt(&buf)) } public static func write(_ value: SwiftType, into buf: inout [UInt8]) { @@ -406,12 +428,15 @@ private struct FfiConverterUInt32: FfiConverterPrimitive { } } -private struct FfiConverterUInt64: FfiConverterPrimitive { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterUInt64: FfiConverterPrimitive { typealias FfiType = UInt64 typealias SwiftType = UInt64 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt64 { - try lift(readInt(&buf)) + return try lift(readInt(&buf)) } public static func write(_ value: SwiftType, into buf: inout [UInt8]) { @@ -419,12 +444,15 @@ private struct FfiConverterUInt64: FfiConverterPrimitive { } } -private struct FfiConverterDouble: FfiConverterPrimitive { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterDouble: FfiConverterPrimitive { typealias FfiType = Double typealias SwiftType = Double public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Double { - try lift(readDouble(&buf)) + return try lift(readDouble(&buf)) } public static func write(_ value: Double, into buf: inout [UInt8]) { @@ -432,20 +460,23 @@ private struct FfiConverterDouble: FfiConverterPrimitive { } } -private struct FfiConverterBool: FfiConverter { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterBool : FfiConverter { typealias FfiType = Int8 typealias SwiftType = Bool public static func lift(_ value: Int8) throws -> Bool { - value != 0 + return value != 0 } public static func lower(_ value: Bool) -> Int8 { - value ? 1 : 0 + return value ? 1 : 0 } public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Bool { - try lift(readInt(&buf)) + return try lift(readInt(&buf)) } public static func write(_ value: Bool, into buf: inout [UInt8]) { @@ -453,7 +484,10 @@ private struct FfiConverterBool: FfiConverter { } } -private struct FfiConverterString: FfiConverter { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterString: FfiConverter { typealias SwiftType = String typealias FfiType = RustBuffer @@ -469,7 +503,7 @@ private struct FfiConverterString: FfiConverter { } public static func lower(_ value: String) -> RustBuffer { - value.utf8CString.withUnsafeBufferPointer { ptr in + return value.utf8CString.withUnsafeBufferPointer { ptr in // The swift string gives us int8_t, we want uint8_t. ptr.withMemoryRebound(to: UInt8.self) { ptr in // The swift string gives us a trailing null byte, we don't want it. @@ -481,7 +515,7 @@ private struct FfiConverterString: FfiConverter { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> String { let len: Int32 = try readInt(&buf) - return try String(bytes: readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)! + return String(bytes: try readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)! } public static func write(_ value: String, into buf: inout [UInt8]) { @@ -491,12 +525,15 @@ private struct FfiConverterString: FfiConverter { } } -private struct FfiConverterData: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterData: FfiConverterRustBuffer { typealias SwiftType = Data public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Data { let len: Int32 = try readInt(&buf) - return try Data(readBytes(&buf, count: Int(len))) + return Data(try readBytes(&buf, count: Int(len))) } public static func write(_ value: Data, into buf: inout [UInt8]) { @@ -506,7 +543,10 @@ private struct FfiConverterData: FfiConverterRustBuffer { } } -private struct FfiConverterTimestamp: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterTimestamp: FfiConverterRustBuffer { typealias SwiftType = Date public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Date { @@ -514,10 +554,10 @@ private struct FfiConverterTimestamp: FfiConverterRustBuffer { let nanoseconds: UInt32 = try readInt(&buf) if seconds >= 0 { let delta = Double(seconds) + (Double(nanoseconds) / 1.0e9) - return Date(timeIntervalSince1970: delta) + return Date.init(timeIntervalSince1970: delta) } else { let delta = Double(seconds) - (Double(nanoseconds) / 1.0e9) - return Date(timeIntervalSince1970: delta) + return Date.init(timeIntervalSince1970: delta) } } @@ -541,6 +581,9 @@ private struct FfiConverterTimestamp: FfiConverterRustBuffer { } } + + + /** * Manages the navigation lifecycle through a route, * returning an updated state given inputs like user location. @@ -549,7 +592,8 @@ private struct FfiConverterTimestamp: FfiConverterRustBuffer { * - A controller is bound to a single route; if you want recalculation, create a new instance. * - This is a pure type (no interior mutability), so a core function of your platform code is responsibly managing mutable state. */ -public protocol NavigationControllerProtocol: AnyObject { +public protocol NavigationControllerProtocol : AnyObject { + /** * Advances navigation to the next step. * @@ -560,13 +604,13 @@ public protocol NavigationControllerProtocol: AnyObject { * This method is takes the intermediate state (e.g. from `update_user_location`) and advances if necessary. * As a result, you do not to re-calculate things like deviation or the snapped user location (search this file for usage of this function). */ - func advanceToNextStep(state: TripState) -> TripState - + func advanceToNextStep(state: TripState) -> TripState + /** * Returns initial trip state as if the user had just started the route with no progress. */ - func getInitialState(location: UserLocation) -> TripState - + func getInitialState(location: UserLocation) -> TripState + /** * Updates the user's current location and updates the navigation state accordingly. * @@ -575,7 +619,8 @@ public protocol NavigationControllerProtocol: AnyObject { * If there is no current step ([`TripState::Navigating`] has an empty `remainingSteps` value), * this function will panic. */ - func updateUserLocation(location: UserLocation, state: TripState) -> TripState + func updateUserLocation(location: UserLocation, state: TripState) -> TripState + } /** @@ -587,11 +632,13 @@ public protocol NavigationControllerProtocol: AnyObject { * - This is a pure type (no interior mutability), so a core function of your platform code is responsibly managing mutable state. */ open class NavigationController: - NavigationControllerProtocol -{ + NavigationControllerProtocol { fileprivate let pointer: UnsafeMutableRawPointer! /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public struct NoPointer { public init() {} } @@ -599,47 +646,53 @@ open class NavigationController: // TODO: We'd like this to be `private` but for Swifty reasons, // we can't implement `FfiConverter` without making this `required` and we can't // make it `required` without making it `public`. - public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + required public init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { self.pointer = pointer } - /// This constructor can be used to instantiate a fake object. - /// - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that - /// may be implemented for classes extending [FFIObject]. - /// - /// - Warning: - /// Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there - /// isn't a backing [Pointer] the FFI lower functions will crash. - public init(noPointer _: NoPointer) { - pointer = nil + // This constructor can be used to instantiate a fake object. + // - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + // + // - Warning: + // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif + public init(noPointer: NoPointer) { + self.pointer = nil } +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public func uniffiClonePointer() -> UnsafeMutableRawPointer { - try! rustCall { uniffi_ferrostar_fn_clone_navigationcontroller(self.pointer, $0) } + return try! rustCall { uniffi_ferrostar_fn_clone_navigationcontroller(self.pointer, $0) } } - /** * Create a navigation controller for a route and configuration. */ - public convenience init(route: Route, config: NavigationControllerConfig) { - let pointer = - try! rustCall { - uniffi_ferrostar_fn_constructor_navigationcontroller_new( - FfiConverterTypeRoute.lower(route), - FfiConverterTypeNavigationControllerConfig.lower(config), $0 - ) - } - self.init(unsafeFromRawPointer: pointer) - } +public convenience init(route: Route, config: NavigationControllerConfig) { + let pointer = + try! rustCall() { + uniffi_ferrostar_fn_constructor_navigationcontroller_new( + FfiConverterTypeRoute.lower(route), + FfiConverterTypeNavigationControllerConfig.lower(config),$0 + ) +} + self.init(unsafeFromRawPointer: pointer) +} deinit { - guard let pointer else { + guard let pointer = pointer else { return } try! rustCall { uniffi_ferrostar_fn_free_navigationcontroller(pointer, $0) } } + + + /** * Advances navigation to the next step. * @@ -650,25 +703,25 @@ open class NavigationController: * This method is takes the intermediate state (e.g. from `update_user_location`) and advances if necessary. * As a result, you do not to re-calculate things like deviation or the snapped user location (search this file for usage of this function). */ - open func advanceToNextStep(state: TripState) -> TripState { - try! FfiConverterTypeTripState.lift(try! rustCall { - uniffi_ferrostar_fn_method_navigationcontroller_advance_to_next_step(self.uniffiClonePointer(), - FfiConverterTypeTripState.lower(state), - $0) - }) - } - +open func advanceToNextStep(state: TripState) -> TripState { + return try! FfiConverterTypeTripState.lift(try! rustCall() { + uniffi_ferrostar_fn_method_navigationcontroller_advance_to_next_step(self.uniffiClonePointer(), + FfiConverterTypeTripState.lower(state),$0 + ) +}) +} + /** * Returns initial trip state as if the user had just started the route with no progress. */ - open func getInitialState(location: UserLocation) -> TripState { - try! FfiConverterTypeTripState.lift(try! rustCall { - uniffi_ferrostar_fn_method_navigationcontroller_get_initial_state(self.uniffiClonePointer(), - FfiConverterTypeUserLocation - .lower(location), $0) - }) - } - +open func getInitialState(location: UserLocation) -> TripState { + return try! FfiConverterTypeTripState.lift(try! rustCall() { + uniffi_ferrostar_fn_method_navigationcontroller_get_initial_state(self.uniffiClonePointer(), + FfiConverterTypeUserLocation.lower(location),$0 + ) +}) +} + /** * Updates the user's current location and updates the navigation state accordingly. * @@ -677,27 +730,32 @@ open class NavigationController: * If there is no current step ([`TripState::Navigating`] has an empty `remainingSteps` value), * this function will panic. */ - open func updateUserLocation(location: UserLocation, state: TripState) -> TripState { - try! FfiConverterTypeTripState.lift(try! rustCall { - uniffi_ferrostar_fn_method_navigationcontroller_update_user_location(self.uniffiClonePointer(), - FfiConverterTypeUserLocation - .lower(location), - FfiConverterTypeTripState.lower(state), - $0) - }) - } +open func updateUserLocation(location: UserLocation, state: TripState) -> TripState { + return try! FfiConverterTypeTripState.lift(try! rustCall() { + uniffi_ferrostar_fn_method_navigationcontroller_update_user_location(self.uniffiClonePointer(), + FfiConverterTypeUserLocation.lower(location), + FfiConverterTypeTripState.lower(state),$0 + ) +}) +} + + } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeNavigationController: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer typealias SwiftType = NavigationController public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> NavigationController { - NavigationController(unsafeFromRawPointer: pointer) + return NavigationController(unsafeFromRawPointer: pointer) } public static func lower(_ value: NavigationController) -> UnsafeMutableRawPointer { - value.uniffiClonePointer() + return value.uniffiClonePointer() } public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> NavigationController { @@ -705,7 +763,7 @@ public struct FfiConverterTypeNavigationController: FfiConverter { // The Rust code won't compile if a pointer won't fit in a UInt64. // We have to go via `UInt` because that's the thing that's the size of a pointer. let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) - if ptr == nil { + if (ptr == nil) { throw UniffiInternalError.unexpectedNullPointer } return try lift(ptr!) @@ -718,16 +776,26 @@ public struct FfiConverterTypeNavigationController: FfiConverter { } } -public func FfiConverterTypeNavigationController_lift(_ pointer: UnsafeMutableRawPointer) throws - -> NavigationController -{ - try FfiConverterTypeNavigationController.lift(pointer) + + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeNavigationController_lift(_ pointer: UnsafeMutableRawPointer) throws -> NavigationController { + return try FfiConverterTypeNavigationController.lift(pointer) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeNavigationController_lower(_ value: NavigationController) -> UnsafeMutableRawPointer { - FfiConverterTypeNavigationController.lower(value) + return FfiConverterTypeNavigationController.lower(value) } + + + /** * The route adapter bridges between the common core and a routing backend where interaction takes place * over a generic request/response flow (typically over a network; @@ -750,10 +818,12 @@ public func FfiConverterTypeNavigationController_lower(_ value: NavigationContro * is modularity, including the possibility of user-provided implementations, and these will not * always be of a "known" type to the Rust side. */ -public protocol RouteAdapterProtocol: AnyObject { - func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest - - func parseResponse(response: Data) throws -> [Route] +public protocol RouteAdapterProtocol : AnyObject { + + func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest + + func parseResponse(response: Data) throws -> [Route] + } /** @@ -779,11 +849,13 @@ public protocol RouteAdapterProtocol: AnyObject { * always be of a "known" type to the Rust side. */ open class RouteAdapter: - RouteAdapterProtocol -{ + RouteAdapterProtocol { fileprivate let pointer: UnsafeMutableRawPointer! /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public struct NoPointer { public init() {} } @@ -791,83 +863,94 @@ open class RouteAdapter: // TODO: We'd like this to be `private` but for Swifty reasons, // we can't implement `FfiConverter` without making this `required` and we can't // make it `required` without making it `public`. - public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + required public init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { self.pointer = pointer } - /// This constructor can be used to instantiate a fake object. - /// - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that - /// may be implemented for classes extending [FFIObject]. - /// - /// - Warning: - /// Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there - /// isn't a backing [Pointer] the FFI lower functions will crash. - public init(noPointer _: NoPointer) { - pointer = nil + // This constructor can be used to instantiate a fake object. + // - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + // + // - Warning: + // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif + public init(noPointer: NoPointer) { + self.pointer = nil } +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public func uniffiClonePointer() -> UnsafeMutableRawPointer { - try! rustCall { uniffi_ferrostar_fn_clone_routeadapter(self.pointer, $0) } - } - - public convenience init(requestGenerator: RouteRequestGenerator, responseParser: RouteResponseParser) { - let pointer = - try! rustCall { - uniffi_ferrostar_fn_constructor_routeadapter_new( - FfiConverterTypeRouteRequestGenerator.lower(requestGenerator), - FfiConverterTypeRouteResponseParser.lower(responseParser), $0 - ) - } - self.init(unsafeFromRawPointer: pointer) - } + return try! rustCall { uniffi_ferrostar_fn_clone_routeadapter(self.pointer, $0) } + } +public convenience init(requestGenerator: RouteRequestGenerator, responseParser: RouteResponseParser) { + let pointer = + try! rustCall() { + uniffi_ferrostar_fn_constructor_routeadapter_new( + FfiConverterTypeRouteRequestGenerator.lower(requestGenerator), + FfiConverterTypeRouteResponseParser.lower(responseParser),$0 + ) +} + self.init(unsafeFromRawPointer: pointer) +} deinit { - guard let pointer else { + guard let pointer = pointer else { return } try! rustCall { uniffi_ferrostar_fn_free_routeadapter(pointer, $0) } } - public static func newValhallaHttp(endpointUrl: String, profile: String, - optionsJson: String?) throws -> RouteAdapter - { - try FfiConverterTypeRouteAdapter.lift(rustCallWithError(FfiConverterTypeInstantiationError.lift) { - uniffi_ferrostar_fn_constructor_routeadapter_new_valhalla_http( - FfiConverterString.lower(endpointUrl), - FfiConverterString.lower(profile), - FfiConverterOptionString.lower(optionsJson), $0 - ) - }) - } + +public static func newValhallaHttp(endpointUrl: String, profile: String, optionsJson: String?)throws -> RouteAdapter { + return try FfiConverterTypeRouteAdapter.lift(try rustCallWithError(FfiConverterTypeInstantiationError.lift) { + uniffi_ferrostar_fn_constructor_routeadapter_new_valhalla_http( + FfiConverterString.lower(endpointUrl), + FfiConverterString.lower(profile), + FfiConverterOptionString.lower(optionsJson),$0 + ) +}) +} + - open func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest { - try FfiConverterTypeRouteRequest.lift(rustCallWithError(FfiConverterTypeRoutingRequestGenerationError.lift) { - uniffi_ferrostar_fn_method_routeadapter_generate_request(self.uniffiClonePointer(), - FfiConverterTypeUserLocation.lower(userLocation), - FfiConverterSequenceTypeWaypoint.lower(waypoints), - $0) - }) - } + +open func generateRequest(userLocation: UserLocation, waypoints: [Waypoint])throws -> RouteRequest { + return try FfiConverterTypeRouteRequest.lift(try rustCallWithError(FfiConverterTypeRoutingRequestGenerationError.lift) { + uniffi_ferrostar_fn_method_routeadapter_generate_request(self.uniffiClonePointer(), + FfiConverterTypeUserLocation.lower(userLocation), + FfiConverterSequenceTypeWaypoint.lower(waypoints),$0 + ) +}) +} + +open func parseResponse(response: Data)throws -> [Route] { + return try FfiConverterSequenceTypeRoute.lift(try rustCallWithError(FfiConverterTypeParsingError.lift) { + uniffi_ferrostar_fn_method_routeadapter_parse_response(self.uniffiClonePointer(), + FfiConverterData.lower(response),$0 + ) +}) +} + - open func parseResponse(response: Data) throws -> [Route] { - try FfiConverterSequenceTypeRoute.lift(rustCallWithError(FfiConverterTypeParsingError.lift) { - uniffi_ferrostar_fn_method_routeadapter_parse_response(self.uniffiClonePointer(), - FfiConverterData.lower(response), $0) - }) - } } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRouteAdapter: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer typealias SwiftType = RouteAdapter public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> RouteAdapter { - RouteAdapter(unsafeFromRawPointer: pointer) + return RouteAdapter(unsafeFromRawPointer: pointer) } public static func lower(_ value: RouteAdapter) -> UnsafeMutableRawPointer { - value.uniffiClonePointer() + return value.uniffiClonePointer() } public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> RouteAdapter { @@ -875,7 +958,7 @@ public struct FfiConverterTypeRouteAdapter: FfiConverter { // The Rust code won't compile if a pointer won't fit in a UInt64. // We have to go via `UInt` because that's the thing that's the size of a pointer. let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) - if ptr == nil { + if (ptr == nil) { throw UniffiInternalError.unexpectedNullPointer } return try lift(ptr!) @@ -888,14 +971,26 @@ public struct FfiConverterTypeRouteAdapter: FfiConverter { } } + + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteAdapter_lift(_ pointer: UnsafeMutableRawPointer) throws -> RouteAdapter { - try FfiConverterTypeRouteAdapter.lift(pointer) + return try FfiConverterTypeRouteAdapter.lift(pointer) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteAdapter_lower(_ value: RouteAdapter) -> UnsafeMutableRawPointer { - FfiConverterTypeRouteAdapter.lower(value) + return FfiConverterTypeRouteAdapter.lower(value) } + + + /** * A custom deviation detector (for extending the behavior of [`RouteDeviationTracking`]). * @@ -903,7 +998,8 @@ public func FfiConverterTypeRouteAdapter_lower(_ value: RouteAdapter) -> UnsafeM * For example, detecting that the user is proceeding the wrong direction by keeping a ring buffer * of recent locations, or perform local map matching. */ -public protocol RouteDeviationDetector: AnyObject { +public protocol RouteDeviationDetector : AnyObject { + /** * Determines whether the user is following the route correctly or not. * @@ -911,7 +1007,8 @@ public protocol RouteDeviationDetector: AnyObject { * Side-effects like whether to recalculate a route are left to higher levels, * and implementations should only be concerned with determining the facts. */ - func checkRouteDeviation(location: UserLocation, route: Route, currentRouteStep: RouteStep) -> RouteDeviation + func checkRouteDeviation(location: UserLocation, route: Route, currentRouteStep: RouteStep) -> RouteDeviation + } /** @@ -922,11 +1019,13 @@ public protocol RouteDeviationDetector: AnyObject { * of recent locations, or perform local map matching. */ open class RouteDeviationDetectorImpl: - RouteDeviationDetector -{ + RouteDeviationDetector { fileprivate let pointer: UnsafeMutableRawPointer! /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public struct NoPointer { public init() {} } @@ -934,35 +1033,41 @@ open class RouteDeviationDetectorImpl: // TODO: We'd like this to be `private` but for Swifty reasons, // we can't implement `FfiConverter` without making this `required` and we can't // make it `required` without making it `public`. - public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + required public init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { self.pointer = pointer } - /// This constructor can be used to instantiate a fake object. - /// - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that - /// may be implemented for classes extending [FFIObject]. - /// - /// - Warning: - /// Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there - /// isn't a backing [Pointer] the FFI lower functions will crash. - public init(noPointer _: NoPointer) { - pointer = nil + // This constructor can be used to instantiate a fake object. + // - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + // + // - Warning: + // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif + public init(noPointer: NoPointer) { + self.pointer = nil } +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public func uniffiClonePointer() -> UnsafeMutableRawPointer { - try! rustCall { uniffi_ferrostar_fn_clone_routedeviationdetector(self.pointer, $0) } + return try! rustCall { uniffi_ferrostar_fn_clone_routedeviationdetector(self.pointer, $0) } } - // No primary constructor declared for this class. deinit { - guard let pointer else { + guard let pointer = pointer else { return } try! rustCall { uniffi_ferrostar_fn_free_routedeviationdetector(pointer, $0) } } + + + /** * Determines whether the user is following the route correctly or not. * @@ -970,21 +1075,18 @@ open class RouteDeviationDetectorImpl: * Side-effects like whether to recalculate a route are left to higher levels, * and implementations should only be concerned with determining the facts. */ - open func checkRouteDeviation(location: UserLocation, route: Route, currentRouteStep: RouteStep) -> RouteDeviation { - try! FfiConverterTypeRouteDeviation.lift(try! rustCall { - uniffi_ferrostar_fn_method_routedeviationdetector_check_route_deviation(self.uniffiClonePointer(), - FfiConverterTypeUserLocation.lower( - location - ), - FfiConverterTypeRoute.lower(route), - FfiConverterTypeRouteStep.lower( - currentRouteStep - ), - $0) - }) - } +open func checkRouteDeviation(location: UserLocation, route: Route, currentRouteStep: RouteStep) -> RouteDeviation { + return try! FfiConverterTypeRouteDeviation.lift(try! rustCall() { + uniffi_ferrostar_fn_method_routedeviationdetector_check_route_deviation(self.uniffiClonePointer(), + FfiConverterTypeUserLocation.lower(location), + FfiConverterTypeRoute.lower(route), + FfiConverterTypeRouteStep.lower(currentRouteStep),$0 + ) +}) } + +} // Magic number for the Rust proxy to call using the same mechanism as every other method, // to free the callback once it's dropped by Rust. private let IDX_CALLBACK_FREE: Int32 = 0 @@ -994,10 +1096,11 @@ private let UNIFFI_CALLBACK_ERROR: Int32 = 1 private let UNIFFI_CALLBACK_UNEXPECTED_ERROR: Int32 = 2 // Put the implementation in a struct so we don't pollute the top-level namespace -private enum UniffiCallbackInterfaceRouteDeviationDetector { +fileprivate struct UniffiCallbackInterfaceRouteDeviationDetector { + // Create the VTable using a series of closures. // Swift automatically converts these into C callback functions. - static var vtable: UniffiVTableCallbackInterfaceRouteDeviationDetector = .init( + static var vtable: UniffiVTableCallbackInterfaceRouteDeviationDetector = UniffiVTableCallbackInterfaceRouteDeviationDetector( checkRouteDeviation: { ( uniffiHandle: UInt64, location: RustBuffer, @@ -1008,17 +1111,17 @@ private enum UniffiCallbackInterfaceRouteDeviationDetector { ) in let makeCall = { () throws -> RouteDeviation in - guard let uniffiObj = try? FfiConverterTypeRouteDeviationDetector.handleMap.get(handle: uniffiHandle) - else { + guard let uniffiObj = try? FfiConverterTypeRouteDeviationDetector.handleMap.get(handle: uniffiHandle) else { throw UniffiInternalError.unexpectedStaleHandle } - return try uniffiObj.checkRouteDeviation( - location: FfiConverterTypeUserLocation.lift(location), - route: FfiConverterTypeRoute.lift(route), - currentRouteStep: FfiConverterTypeRouteStep.lift(currentRouteStep) + return uniffiObj.checkRouteDeviation( + location: try FfiConverterTypeUserLocation.lift(location), + route: try FfiConverterTypeRoute.lift(route), + currentRouteStep: try FfiConverterTypeRouteStep.lift(currentRouteStep) ) } + let writeReturn = { uniffiOutReturn.pointee = FfiConverterTypeRouteDeviation.lower($0) } uniffiTraitInterfaceCall( callStatus: uniffiCallStatus, @@ -1026,7 +1129,7 @@ private enum UniffiCallbackInterfaceRouteDeviationDetector { writeReturn: writeReturn ) }, - uniffiFree: { (uniffiHandle: UInt64) in + uniffiFree: { (uniffiHandle: UInt64) -> () in let result = try? FfiConverterTypeRouteDeviationDetector.handleMap.remove(handle: uniffiHandle) if result == nil { print("Uniffi callback interface RouteDeviationDetector: handle missing in uniffiFree") @@ -1036,10 +1139,12 @@ private enum UniffiCallbackInterfaceRouteDeviationDetector { } private func uniffiCallbackInitRouteDeviationDetector() { - uniffi_ferrostar_fn_init_callback_vtable_routedeviationdetector(&UniffiCallbackInterfaceRouteDeviationDetector - .vtable) + uniffi_ferrostar_fn_init_callback_vtable_routedeviationdetector(&UniffiCallbackInterfaceRouteDeviationDetector.vtable) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRouteDeviationDetector: FfiConverter { fileprivate static var handleMap = UniffiHandleMap() @@ -1047,12 +1152,11 @@ public struct FfiConverterTypeRouteDeviationDetector: FfiConverter { typealias SwiftType = RouteDeviationDetector public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> RouteDeviationDetector { - RouteDeviationDetectorImpl(unsafeFromRawPointer: pointer) + return RouteDeviationDetectorImpl(unsafeFromRawPointer: pointer) } public static func lower(_ value: RouteDeviationDetector) -> UnsafeMutableRawPointer { - guard let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: handleMap.insert(obj: value))) - else { + guard let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: handleMap.insert(obj: value))) else { fatalError("Cast to UnsafeMutableRawPointer failed") } return ptr @@ -1063,7 +1167,7 @@ public struct FfiConverterTypeRouteDeviationDetector: FfiConverter { // The Rust code won't compile if a pointer won't fit in a UInt64. // We have to go via `UInt` because that's the thing that's the size of a pointer. let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) - if ptr == nil { + if (ptr == nil) { throw UniffiInternalError.unexpectedNullPointer } return try lift(ptr!) @@ -1076,16 +1180,26 @@ public struct FfiConverterTypeRouteDeviationDetector: FfiConverter { } } -public func FfiConverterTypeRouteDeviationDetector_lift(_ pointer: UnsafeMutableRawPointer) throws - -> RouteDeviationDetector -{ - try FfiConverterTypeRouteDeviationDetector.lift(pointer) + + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeRouteDeviationDetector_lift(_ pointer: UnsafeMutableRawPointer) throws -> RouteDeviationDetector { + return try FfiConverterTypeRouteDeviationDetector.lift(pointer) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteDeviationDetector_lower(_ value: RouteDeviationDetector) -> UnsafeMutableRawPointer { - FfiConverterTypeRouteDeviationDetector.lower(value) + return FfiConverterTypeRouteDeviationDetector.lower(value) } + + + /** * A trait describing any object capable of generating [`RouteRequest`]s. * @@ -1097,14 +1211,16 @@ public func FfiConverterTypeRouteDeviationDetector_lower(_ value: RouteDeviation * Implementations may be either in Rust (most popular engines should eventually have Rust * glue code) or foreign code. */ -public protocol RouteRequestGenerator: AnyObject { +public protocol RouteRequestGenerator : AnyObject { + /** * Generates a routing backend request given the set of locations. * * While most implementations will treat the locations as an ordered sequence, this is not * guaranteed (ex: an optimized router). */ - func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest + func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest + } /** @@ -1119,11 +1235,13 @@ public protocol RouteRequestGenerator: AnyObject { * glue code) or foreign code. */ open class RouteRequestGeneratorImpl: - RouteRequestGenerator -{ + RouteRequestGenerator { fileprivate let pointer: UnsafeMutableRawPointer! /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public struct NoPointer { public init() {} } @@ -1131,58 +1249,66 @@ open class RouteRequestGeneratorImpl: // TODO: We'd like this to be `private` but for Swifty reasons, // we can't implement `FfiConverter` without making this `required` and we can't // make it `required` without making it `public`. - public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + required public init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { self.pointer = pointer } - /// This constructor can be used to instantiate a fake object. - /// - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that - /// may be implemented for classes extending [FFIObject]. - /// - /// - Warning: - /// Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there - /// isn't a backing [Pointer] the FFI lower functions will crash. - public init(noPointer _: NoPointer) { - pointer = nil + // This constructor can be used to instantiate a fake object. + // - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + // + // - Warning: + // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif + public init(noPointer: NoPointer) { + self.pointer = nil } +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public func uniffiClonePointer() -> UnsafeMutableRawPointer { - try! rustCall { uniffi_ferrostar_fn_clone_routerequestgenerator(self.pointer, $0) } + return try! rustCall { uniffi_ferrostar_fn_clone_routerequestgenerator(self.pointer, $0) } } - // No primary constructor declared for this class. deinit { - guard let pointer else { + guard let pointer = pointer else { return } try! rustCall { uniffi_ferrostar_fn_free_routerequestgenerator(pointer, $0) } } + + + /** * Generates a routing backend request given the set of locations. * * While most implementations will treat the locations as an ordered sequence, this is not * guaranteed (ex: an optimized router). */ - open func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest { - try FfiConverterTypeRouteRequest.lift(rustCallWithError(FfiConverterTypeRoutingRequestGenerationError.lift) { - uniffi_ferrostar_fn_method_routerequestgenerator_generate_request(self.uniffiClonePointer(), - FfiConverterTypeUserLocation - .lower(userLocation), - FfiConverterSequenceTypeWaypoint - .lower(waypoints), - $0) - }) - } +open func generateRequest(userLocation: UserLocation, waypoints: [Waypoint])throws -> RouteRequest { + return try FfiConverterTypeRouteRequest.lift(try rustCallWithError(FfiConverterTypeRoutingRequestGenerationError.lift) { + uniffi_ferrostar_fn_method_routerequestgenerator_generate_request(self.uniffiClonePointer(), + FfiConverterTypeUserLocation.lower(userLocation), + FfiConverterSequenceTypeWaypoint.lower(waypoints),$0 + ) +}) +} + + } + // Put the implementation in a struct so we don't pollute the top-level namespace -private enum UniffiCallbackInterfaceRouteRequestGenerator { +fileprivate struct UniffiCallbackInterfaceRouteRequestGenerator { + // Create the VTable using a series of closures. // Swift automatically converts these into C callback functions. - static var vtable: UniffiVTableCallbackInterfaceRouteRequestGenerator = .init( + static var vtable: UniffiVTableCallbackInterfaceRouteRequestGenerator = UniffiVTableCallbackInterfaceRouteRequestGenerator( generateRequest: { ( uniffiHandle: UInt64, userLocation: RustBuffer, @@ -1192,16 +1318,16 @@ private enum UniffiCallbackInterfaceRouteRequestGenerator { ) in let makeCall = { () throws -> RouteRequest in - guard let uniffiObj = try? FfiConverterTypeRouteRequestGenerator.handleMap.get(handle: uniffiHandle) - else { + guard let uniffiObj = try? FfiConverterTypeRouteRequestGenerator.handleMap.get(handle: uniffiHandle) else { throw UniffiInternalError.unexpectedStaleHandle } return try uniffiObj.generateRequest( - userLocation: FfiConverterTypeUserLocation.lift(userLocation), - waypoints: FfiConverterSequenceTypeWaypoint.lift(waypoints) + userLocation: try FfiConverterTypeUserLocation.lift(userLocation), + waypoints: try FfiConverterSequenceTypeWaypoint.lift(waypoints) ) } + let writeReturn = { uniffiOutReturn.pointee = FfiConverterTypeRouteRequest.lower($0) } uniffiTraitInterfaceCallWithError( callStatus: uniffiCallStatus, @@ -1210,7 +1336,7 @@ private enum UniffiCallbackInterfaceRouteRequestGenerator { lowerError: FfiConverterTypeRoutingRequestGenerationError.lower ) }, - uniffiFree: { (uniffiHandle: UInt64) in + uniffiFree: { (uniffiHandle: UInt64) -> () in let result = try? FfiConverterTypeRouteRequestGenerator.handleMap.remove(handle: uniffiHandle) if result == nil { print("Uniffi callback interface RouteRequestGenerator: handle missing in uniffiFree") @@ -1223,6 +1349,9 @@ private func uniffiCallbackInitRouteRequestGenerator() { uniffi_ferrostar_fn_init_callback_vtable_routerequestgenerator(&UniffiCallbackInterfaceRouteRequestGenerator.vtable) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRouteRequestGenerator: FfiConverter { fileprivate static var handleMap = UniffiHandleMap() @@ -1230,12 +1359,11 @@ public struct FfiConverterTypeRouteRequestGenerator: FfiConverter { typealias SwiftType = RouteRequestGenerator public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> RouteRequestGenerator { - RouteRequestGeneratorImpl(unsafeFromRawPointer: pointer) + return RouteRequestGeneratorImpl(unsafeFromRawPointer: pointer) } public static func lower(_ value: RouteRequestGenerator) -> UnsafeMutableRawPointer { - guard let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: handleMap.insert(obj: value))) - else { + guard let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: handleMap.insert(obj: value))) else { fatalError("Cast to UnsafeMutableRawPointer failed") } return ptr @@ -1246,7 +1374,7 @@ public struct FfiConverterTypeRouteRequestGenerator: FfiConverter { // The Rust code won't compile if a pointer won't fit in a UInt64. // We have to go via `UInt` because that's the thing that's the size of a pointer. let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) - if ptr == nil { + if (ptr == nil) { throw UniffiInternalError.unexpectedNullPointer } return try lift(ptr!) @@ -1259,28 +1387,40 @@ public struct FfiConverterTypeRouteRequestGenerator: FfiConverter { } } -public func FfiConverterTypeRouteRequestGenerator_lift(_ pointer: UnsafeMutableRawPointer) throws - -> RouteRequestGenerator -{ - try FfiConverterTypeRouteRequestGenerator.lift(pointer) + + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeRouteRequestGenerator_lift(_ pointer: UnsafeMutableRawPointer) throws -> RouteRequestGenerator { + return try FfiConverterTypeRouteRequestGenerator.lift(pointer) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteRequestGenerator_lower(_ value: RouteRequestGenerator) -> UnsafeMutableRawPointer { - FfiConverterTypeRouteRequestGenerator.lower(value) + return FfiConverterTypeRouteRequestGenerator.lower(value) } + + + /** * A generic interface describing any object capable of parsing a response from a routing * backend into one or more [`Route`]s. */ -public protocol RouteResponseParser: AnyObject { +public protocol RouteResponseParser : AnyObject { + /** * Parses a raw response from the routing backend into a route. * * We use a sequence of octets as a common interchange format. * as this works for all currently conceivable formats (JSON, PBF, etc.). */ - func parseResponse(response: Data) throws -> [Route] + func parseResponse(response: Data) throws -> [Route] + } /** @@ -1288,11 +1428,13 @@ public protocol RouteResponseParser: AnyObject { * backend into one or more [`Route`]s. */ open class RouteResponseParserImpl: - RouteResponseParser -{ + RouteResponseParser { fileprivate let pointer: UnsafeMutableRawPointer! /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public struct NoPointer { public init() {} } @@ -1300,54 +1442,65 @@ open class RouteResponseParserImpl: // TODO: We'd like this to be `private` but for Swifty reasons, // we can't implement `FfiConverter` without making this `required` and we can't // make it `required` without making it `public`. - public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + required public init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { self.pointer = pointer } - /// This constructor can be used to instantiate a fake object. - /// - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that - /// may be implemented for classes extending [FFIObject]. - /// - /// - Warning: - /// Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there - /// isn't a backing [Pointer] the FFI lower functions will crash. - public init(noPointer _: NoPointer) { - pointer = nil + // This constructor can be used to instantiate a fake object. + // - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + // + // - Warning: + // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. +#if swift(>=5.8) + @_documentation(visibility: private) +#endif + public init(noPointer: NoPointer) { + self.pointer = nil } +#if swift(>=5.8) + @_documentation(visibility: private) +#endif public func uniffiClonePointer() -> UnsafeMutableRawPointer { - try! rustCall { uniffi_ferrostar_fn_clone_routeresponseparser(self.pointer, $0) } + return try! rustCall { uniffi_ferrostar_fn_clone_routeresponseparser(self.pointer, $0) } } - // No primary constructor declared for this class. deinit { - guard let pointer else { + guard let pointer = pointer else { return } try! rustCall { uniffi_ferrostar_fn_free_routeresponseparser(pointer, $0) } } + + + /** * Parses a raw response from the routing backend into a route. * * We use a sequence of octets as a common interchange format. * as this works for all currently conceivable formats (JSON, PBF, etc.). */ - open func parseResponse(response: Data) throws -> [Route] { - try FfiConverterSequenceTypeRoute.lift(rustCallWithError(FfiConverterTypeParsingError.lift) { - uniffi_ferrostar_fn_method_routeresponseparser_parse_response(self.uniffiClonePointer(), - FfiConverterData.lower(response), $0) - }) - } +open func parseResponse(response: Data)throws -> [Route] { + return try FfiConverterSequenceTypeRoute.lift(try rustCallWithError(FfiConverterTypeParsingError.lift) { + uniffi_ferrostar_fn_method_routeresponseparser_parse_response(self.uniffiClonePointer(), + FfiConverterData.lower(response),$0 + ) +}) +} + + } + // Put the implementation in a struct so we don't pollute the top-level namespace -private enum UniffiCallbackInterfaceRouteResponseParser { +fileprivate struct UniffiCallbackInterfaceRouteResponseParser { + // Create the VTable using a series of closures. // Swift automatically converts these into C callback functions. - static var vtable: UniffiVTableCallbackInterfaceRouteResponseParser = .init( + static var vtable: UniffiVTableCallbackInterfaceRouteResponseParser = UniffiVTableCallbackInterfaceRouteResponseParser( parseResponse: { ( uniffiHandle: UInt64, response: RustBuffer, @@ -1356,15 +1509,15 @@ private enum UniffiCallbackInterfaceRouteResponseParser { ) in let makeCall = { () throws -> [Route] in - guard let uniffiObj = try? FfiConverterTypeRouteResponseParser.handleMap.get(handle: uniffiHandle) - else { + guard let uniffiObj = try? FfiConverterTypeRouteResponseParser.handleMap.get(handle: uniffiHandle) else { throw UniffiInternalError.unexpectedStaleHandle } return try uniffiObj.parseResponse( - response: FfiConverterData.lift(response) + response: try FfiConverterData.lift(response) ) } + let writeReturn = { uniffiOutReturn.pointee = FfiConverterSequenceTypeRoute.lower($0) } uniffiTraitInterfaceCallWithError( callStatus: uniffiCallStatus, @@ -1373,7 +1526,7 @@ private enum UniffiCallbackInterfaceRouteResponseParser { lowerError: FfiConverterTypeParsingError.lower ) }, - uniffiFree: { (uniffiHandle: UInt64) in + uniffiFree: { (uniffiHandle: UInt64) -> () in let result = try? FfiConverterTypeRouteResponseParser.handleMap.remove(handle: uniffiHandle) if result == nil { print("Uniffi callback interface RouteResponseParser: handle missing in uniffiFree") @@ -1386,6 +1539,9 @@ private func uniffiCallbackInitRouteResponseParser() { uniffi_ferrostar_fn_init_callback_vtable_routeresponseparser(&UniffiCallbackInterfaceRouteResponseParser.vtable) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRouteResponseParser: FfiConverter { fileprivate static var handleMap = UniffiHandleMap() @@ -1393,12 +1549,11 @@ public struct FfiConverterTypeRouteResponseParser: FfiConverter { typealias SwiftType = RouteResponseParser public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> RouteResponseParser { - RouteResponseParserImpl(unsafeFromRawPointer: pointer) + return RouteResponseParserImpl(unsafeFromRawPointer: pointer) } public static func lower(_ value: RouteResponseParser) -> UnsafeMutableRawPointer { - guard let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: handleMap.insert(obj: value))) - else { + guard let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: handleMap.insert(obj: value))) else { fatalError("Cast to UnsafeMutableRawPointer failed") } return ptr @@ -1409,7 +1564,7 @@ public struct FfiConverterTypeRouteResponseParser: FfiConverter { // The Rust code won't compile if a pointer won't fit in a UInt64. // We have to go via `UInt` because that's the thing that's the size of a pointer. let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) - if ptr == nil { + if (ptr == nil) { throw UniffiInternalError.unexpectedNullPointer } return try lift(ptr!) @@ -1422,14 +1577,24 @@ public struct FfiConverterTypeRouteResponseParser: FfiConverter { } } + + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteResponseParser_lift(_ pointer: UnsafeMutableRawPointer) throws -> RouteResponseParser { - try FfiConverterTypeRouteResponseParser.lift(pointer) + return try FfiConverterTypeRouteResponseParser.lift(pointer) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteResponseParser_lower(_ value: RouteResponseParser) -> UnsafeMutableRawPointer { - FfiConverterTypeRouteResponseParser.lower(value) + return FfiConverterTypeRouteResponseParser.lower(value) } + /** * A geographic bounding box defined by its corners. */ @@ -1448,18 +1613,19 @@ public struct BoundingBox { public init( /** * The southwest corner of the bounding box. - */ sw: GeographicCoordinate, + */sw: GeographicCoordinate, /** - * The northeast corner of the bounding box. - */ ne: GeographicCoordinate - ) { + * The northeast corner of the bounding box. + */ne: GeographicCoordinate) { self.sw = sw self.ne = ne } } + + extension BoundingBox: Equatable, Hashable { - public static func == (lhs: BoundingBox, rhs: BoundingBox) -> Bool { + public static func ==(lhs: BoundingBox, rhs: BoundingBox) -> Bool { if lhs.sw != rhs.sw { return false } @@ -1475,11 +1641,16 @@ extension BoundingBox: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeBoundingBox: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> BoundingBox { - try BoundingBox( - sw: FfiConverterTypeGeographicCoordinate.read(from: &buf), - ne: FfiConverterTypeGeographicCoordinate.read(from: &buf) + return + try BoundingBox( + sw: FfiConverterTypeGeographicCoordinate.read(from: &buf), + ne: FfiConverterTypeGeographicCoordinate.read(from: &buf) ) } @@ -1489,14 +1660,22 @@ public struct FfiConverterTypeBoundingBox: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeBoundingBox_lift(_ buf: RustBuffer) throws -> BoundingBox { - try FfiConverterTypeBoundingBox.lift(buf) + return try FfiConverterTypeBoundingBox.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeBoundingBox_lower(_ value: BoundingBox) -> RustBuffer { - FfiConverterTypeBoundingBox.lower(value) + return FfiConverterTypeBoundingBox.lower(value) } + /** * The direction in which the user/device is observed to be traveling. */ @@ -1517,18 +1696,19 @@ public struct CourseOverGround { /** * The direction in which the user's device is traveling, measured in clockwise degrees from * true north (N = 0, E = 90, S = 180, W = 270). - */ degrees: UInt16, + */degrees: UInt16, /** - * The accuracy of the course value, measured in degrees. - */ accuracy: UInt16? - ) { + * The accuracy of the course value, measured in degrees. + */accuracy: UInt16?) { self.degrees = degrees self.accuracy = accuracy } } + + extension CourseOverGround: Equatable, Hashable { - public static func == (lhs: CourseOverGround, rhs: CourseOverGround) -> Bool { + public static func ==(lhs: CourseOverGround, rhs: CourseOverGround) -> Bool { if lhs.degrees != rhs.degrees { return false } @@ -1544,11 +1724,16 @@ extension CourseOverGround: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeCourseOverGround: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> CourseOverGround { - try CourseOverGround( - degrees: FfiConverterUInt16.read(from: &buf), - accuracy: FfiConverterOptionUInt16.read(from: &buf) + return + try CourseOverGround( + degrees: FfiConverterUInt16.read(from: &buf), + accuracy: FfiConverterOptionUInt16.read(from: &buf) ) } @@ -1558,14 +1743,22 @@ public struct FfiConverterTypeCourseOverGround: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeCourseOverGround_lift(_ buf: RustBuffer) throws -> CourseOverGround { - try FfiConverterTypeCourseOverGround.lift(buf) + return try FfiConverterTypeCourseOverGround.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeCourseOverGround_lower(_ value: CourseOverGround) -> RustBuffer { - FfiConverterTypeCourseOverGround.lower(value) + return FfiConverterTypeCourseOverGround.lower(value) } + /** * A geographic coordinate in WGS84. */ @@ -1584,18 +1777,19 @@ public struct GeographicCoordinate { public init( /** * The latitude (in degrees). - */ lat: Double, + */lat: Double, /** - * The Longitude (in degrees). - */ lng: Double - ) { + * The Longitude (in degrees). + */lng: Double) { self.lat = lat self.lng = lng } } + + extension GeographicCoordinate: Equatable, Hashable { - public static func == (lhs: GeographicCoordinate, rhs: GeographicCoordinate) -> Bool { + public static func ==(lhs: GeographicCoordinate, rhs: GeographicCoordinate) -> Bool { if lhs.lat != rhs.lat { return false } @@ -1611,11 +1805,16 @@ extension GeographicCoordinate: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeGeographicCoordinate: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> GeographicCoordinate { - try GeographicCoordinate( - lat: FfiConverterDouble.read(from: &buf), - lng: FfiConverterDouble.read(from: &buf) + return + try GeographicCoordinate( + lat: FfiConverterDouble.read(from: &buf), + lng: FfiConverterDouble.read(from: &buf) ) } @@ -1625,14 +1824,22 @@ public struct FfiConverterTypeGeographicCoordinate: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeGeographicCoordinate_lift(_ buf: RustBuffer) throws -> GeographicCoordinate { - try FfiConverterTypeGeographicCoordinate.lift(buf) + return try FfiConverterTypeGeographicCoordinate.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeGeographicCoordinate_lower(_ value: GeographicCoordinate) -> RustBuffer { - FfiConverterTypeGeographicCoordinate.lower(value) + return FfiConverterTypeGeographicCoordinate.lower(value) } + /** * The heading of the user/device. */ @@ -1655,22 +1862,23 @@ public struct Heading { public init( /** * The heading in degrees relative to true north. - */ trueHeading: UInt16, + */trueHeading: UInt16, /** - * The platform specific accuracy of the heading value. - */ accuracy: UInt16, + * The platform specific accuracy of the heading value. + */accuracy: UInt16, /** - * The time at which the heading was recorded. - */ timestamp: Date - ) { + * The time at which the heading was recorded. + */timestamp: Date) { self.trueHeading = trueHeading self.accuracy = accuracy self.timestamp = timestamp } } + + extension Heading: Equatable, Hashable { - public static func == (lhs: Heading, rhs: Heading) -> Bool { + public static func ==(lhs: Heading, rhs: Heading) -> Bool { if lhs.trueHeading != rhs.trueHeading { return false } @@ -1690,12 +1898,17 @@ extension Heading: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeHeading: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Heading { - try Heading( - trueHeading: FfiConverterUInt16.read(from: &buf), - accuracy: FfiConverterUInt16.read(from: &buf), - timestamp: FfiConverterTimestamp.read(from: &buf) + return + try Heading( + trueHeading: FfiConverterUInt16.read(from: &buf), + accuracy: FfiConverterUInt16.read(from: &buf), + timestamp: FfiConverterTimestamp.read(from: &buf) ) } @@ -1706,14 +1919,22 @@ public struct FfiConverterTypeHeading: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeHeading_lift(_ buf: RustBuffer) throws -> Heading { - try FfiConverterTypeHeading.lift(buf) + return try FfiConverterTypeHeading.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeHeading_lower(_ value: Heading) -> RustBuffer { - FfiConverterTypeHeading.lower(value) + return FfiConverterTypeHeading.lower(value) } + /** * The content of a visual instruction. */ @@ -1731,8 +1952,10 @@ public struct LaneInfo { } } + + extension LaneInfo: Equatable, Hashable { - public static func == (lhs: LaneInfo, rhs: LaneInfo) -> Bool { + public static func ==(lhs: LaneInfo, rhs: LaneInfo) -> Bool { if lhs.active != rhs.active { return false } @@ -1752,12 +1975,17 @@ extension LaneInfo: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeLaneInfo: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LaneInfo { - try LaneInfo( - active: FfiConverterBool.read(from: &buf), - directions: FfiConverterSequenceString.read(from: &buf), - activeDirection: FfiConverterOptionString.read(from: &buf) + return + try LaneInfo( + active: FfiConverterBool.read(from: &buf), + directions: FfiConverterSequenceString.read(from: &buf), + activeDirection: FfiConverterOptionString.read(from: &buf) ) } @@ -1768,68 +1996,99 @@ public struct FfiConverterTypeLaneInfo: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeLaneInfo_lift(_ buf: RustBuffer) throws -> LaneInfo { - try FfiConverterTypeLaneInfo.lift(buf) + return try FfiConverterTypeLaneInfo.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeLaneInfo_lower(_ value: LaneInfo) -> RustBuffer { - FfiConverterTypeLaneInfo.lower(value) + return FfiConverterTypeLaneInfo.lower(value) } + /** * The current state of the simulation. */ public struct LocationSimulationState { public var currentLocation: UserLocation public var remainingLocations: [GeographicCoordinate] + public var bias: LocationBias // Default memberwise initializers are never public by default, so we // declare one manually. - public init(currentLocation: UserLocation, remainingLocations: [GeographicCoordinate]) { + public init(currentLocation: UserLocation, remainingLocations: [GeographicCoordinate], bias: LocationBias) { self.currentLocation = currentLocation self.remainingLocations = remainingLocations + self.bias = bias } } + + extension LocationSimulationState: Equatable, Hashable { - public static func == (lhs: LocationSimulationState, rhs: LocationSimulationState) -> Bool { + public static func ==(lhs: LocationSimulationState, rhs: LocationSimulationState) -> Bool { if lhs.currentLocation != rhs.currentLocation { return false } if lhs.remainingLocations != rhs.remainingLocations { return false } + if lhs.bias != rhs.bias { + return false + } return true } public func hash(into hasher: inout Hasher) { hasher.combine(currentLocation) hasher.combine(remainingLocations) + hasher.combine(bias) } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeLocationSimulationState: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LocationSimulationState { - try LocationSimulationState( - currentLocation: FfiConverterTypeUserLocation.read(from: &buf), - remainingLocations: FfiConverterSequenceTypeGeographicCoordinate.read(from: &buf) + return + try LocationSimulationState( + currentLocation: FfiConverterTypeUserLocation.read(from: &buf), + remainingLocations: FfiConverterSequenceTypeGeographicCoordinate.read(from: &buf), + bias: FfiConverterTypeLocationBias.read(from: &buf) ) } public static func write(_ value: LocationSimulationState, into buf: inout [UInt8]) { FfiConverterTypeUserLocation.write(value.currentLocation, into: &buf) FfiConverterSequenceTypeGeographicCoordinate.write(value.remainingLocations, into: &buf) + FfiConverterTypeLocationBias.write(value.bias, into: &buf) } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeLocationSimulationState_lift(_ buf: RustBuffer) throws -> LocationSimulationState { - try FfiConverterTypeLocationSimulationState.lift(buf) + return try FfiConverterTypeLocationSimulationState.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeLocationSimulationState_lower(_ value: LocationSimulationState) -> RustBuffer { - FfiConverterTypeLocationSimulationState.lower(value) + return FfiConverterTypeLocationSimulationState.lower(value) } + public struct NavigationControllerConfig { /** * Configures when navigation advances to the next step in the route. @@ -1852,29 +2111,34 @@ public struct NavigationControllerConfig { public init( /** * Configures when navigation advances to the next step in the route. - */ stepAdvance: StepAdvanceMode, + */stepAdvance: StepAdvanceMode, /** - * Configures when the user is deemed to be off course. - * - * NOTE: This is distinct from the action that is taken. - * It is only the determination that the user has deviated from the expected route. - */ routeDeviationTracking: RouteDeviationTracking, + * Configures when the user is deemed to be off course. + * + * NOTE: This is distinct from the action that is taken. + * It is only the determination that the user has deviated from the expected route. + */routeDeviationTracking: RouteDeviationTracking, /** - * Configures how the heading component of the snapped location is reported in [`TripState`]. - */ snappedLocationCourseFiltering: CourseFiltering - ) { + * Configures how the heading component of the snapped location is reported in [`TripState`]. + */snappedLocationCourseFiltering: CourseFiltering) { self.stepAdvance = stepAdvance self.routeDeviationTracking = routeDeviationTracking self.snappedLocationCourseFiltering = snappedLocationCourseFiltering } } + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeNavigationControllerConfig: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> NavigationControllerConfig { - try NavigationControllerConfig( - stepAdvance: FfiConverterTypeStepAdvanceMode.read(from: &buf), - routeDeviationTracking: FfiConverterTypeRouteDeviationTracking.read(from: &buf), - snappedLocationCourseFiltering: FfiConverterTypeCourseFiltering.read(from: &buf) + return + try NavigationControllerConfig( + stepAdvance: FfiConverterTypeStepAdvanceMode.read(from: &buf), + routeDeviationTracking: FfiConverterTypeRouteDeviationTracking.read(from: &buf), + snappedLocationCourseFiltering: FfiConverterTypeCourseFiltering.read(from: &buf) ) } @@ -1885,14 +2149,22 @@ public struct FfiConverterTypeNavigationControllerConfig: FfiConverterRustBuffer } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeNavigationControllerConfig_lift(_ buf: RustBuffer) throws -> NavigationControllerConfig { - try FfiConverterTypeNavigationControllerConfig.lift(buf) + return try FfiConverterTypeNavigationControllerConfig.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeNavigationControllerConfig_lower(_ value: NavigationControllerConfig) -> RustBuffer { - FfiConverterTypeNavigationControllerConfig.lower(value) + return FfiConverterTypeNavigationControllerConfig.lower(value) } + /** * Information describing the series of steps needed to travel between two or more points. * @@ -1916,16 +2188,15 @@ public struct Route { // Default memberwise initializers are never public by default, so we // declare one manually. - public init(geometry: [GeographicCoordinate], bbox: BoundingBox, - /** - * The total route distance, in meters. - */ distance: Double, - /** - * The ordered list of waypoints to visit, including the starting point. - * Note that this is distinct from the *geometry* which includes all points visited. - * A waypoint represents a start/end point for a route leg. - */ waypoints: [Waypoint], steps: [RouteStep]) - { + public init(geometry: [GeographicCoordinate], bbox: BoundingBox, + /** + * The total route distance, in meters. + */distance: Double, + /** + * The ordered list of waypoints to visit, including the starting point. + * Note that this is distinct from the *geometry* which includes all points visited. + * A waypoint represents a start/end point for a route leg. + */waypoints: [Waypoint], steps: [RouteStep]) { self.geometry = geometry self.bbox = bbox self.distance = distance @@ -1934,8 +2205,10 @@ public struct Route { } } + + extension Route: Equatable, Hashable { - public static func == (lhs: Route, rhs: Route) -> Bool { + public static func ==(lhs: Route, rhs: Route) -> Bool { if lhs.geometry != rhs.geometry { return false } @@ -1963,14 +2236,19 @@ extension Route: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRoute: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Route { - try Route( - geometry: FfiConverterSequenceTypeGeographicCoordinate.read(from: &buf), - bbox: FfiConverterTypeBoundingBox.read(from: &buf), - distance: FfiConverterDouble.read(from: &buf), - waypoints: FfiConverterSequenceTypeWaypoint.read(from: &buf), - steps: FfiConverterSequenceTypeRouteStep.read(from: &buf) + return + try Route( + geometry: FfiConverterSequenceTypeGeographicCoordinate.read(from: &buf), + bbox: FfiConverterTypeBoundingBox.read(from: &buf), + distance: FfiConverterDouble.read(from: &buf), + waypoints: FfiConverterSequenceTypeWaypoint.read(from: &buf), + steps: FfiConverterSequenceTypeRouteStep.read(from: &buf) ) } @@ -1983,14 +2261,22 @@ public struct FfiConverterTypeRoute: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRoute_lift(_ buf: RustBuffer) throws -> Route { - try FfiConverterTypeRoute.lift(buf) + return try FfiConverterTypeRoute.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRoute_lower(_ value: Route) -> RustBuffer { - FfiConverterTypeRoute.lower(value) + return FfiConverterTypeRoute.lower(value) } + /** * A maneuver (such as a turn or merge) followed by travel of a certain distance until reaching * the next step. @@ -2038,33 +2324,32 @@ public struct RouteStep { public init( /** * The full route geometry for this step. - */ geometry: [GeographicCoordinate], + */geometry: [GeographicCoordinate], /** - * The distance, in meters, to travel along the route after the maneuver to reach the next step. - */ distance: Double, + * The distance, in meters, to travel along the route after the maneuver to reach the next step. + */distance: Double, /** - * The estimated duration, in seconds, that it will take to complete this step. - */ duration: Double, + * The estimated duration, in seconds, that it will take to complete this step. + */duration: Double, /** - * The name of the road being traveled on (useful for certain UI styles). - */ roadName: String?, + * The name of the road being traveled on (useful for certain UI styles). + */roadName: String?, /** - * A description of the maneuver (ex: "Turn wright onto main street"). - * - * Note for UI implementers: the context this appears in (or doesn't) - * depends somewhat on your use case and routing engine. - * For example, this field is useful as a written instruction in Valhalla. - */ instruction: String, + * A description of the maneuver (ex: "Turn wright onto main street"). + * + * Note for UI implementers: the context this appears in (or doesn't) + * depends somewhat on your use case and routing engine. + * For example, this field is useful as a written instruction in Valhalla. + */instruction: String, /** - * A list of instructions for visual display (usually as banners) at specific points along the step. - */ visualInstructions: [VisualInstruction], + * A list of instructions for visual display (usually as banners) at specific points along the step. + */visualInstructions: [VisualInstruction], /** - * A list of prompts to announce (via speech synthesis) at specific points along the step. - */ spokenInstructions: [SpokenInstruction], + * A list of prompts to announce (via speech synthesis) at specific points along the step. + */spokenInstructions: [SpokenInstruction], /** - * A list of json encoded strings representing annotations between each coordinate along the step. - */ annotations: [String]? - ) { + * A list of json encoded strings representing annotations between each coordinate along the step. + */annotations: [String]?) { self.geometry = geometry self.distance = distance self.duration = duration @@ -2076,8 +2361,10 @@ public struct RouteStep { } } + + extension RouteStep: Equatable, Hashable { - public static func == (lhs: RouteStep, rhs: RouteStep) -> Bool { + public static func ==(lhs: RouteStep, rhs: RouteStep) -> Bool { if lhs.geometry != rhs.geometry { return false } @@ -2117,17 +2404,22 @@ extension RouteStep: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRouteStep: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> RouteStep { - try RouteStep( - geometry: FfiConverterSequenceTypeGeographicCoordinate.read(from: &buf), - distance: FfiConverterDouble.read(from: &buf), - duration: FfiConverterDouble.read(from: &buf), - roadName: FfiConverterOptionString.read(from: &buf), - instruction: FfiConverterString.read(from: &buf), - visualInstructions: FfiConverterSequenceTypeVisualInstruction.read(from: &buf), - spokenInstructions: FfiConverterSequenceTypeSpokenInstruction.read(from: &buf), - annotations: FfiConverterOptionSequenceString.read(from: &buf) + return + try RouteStep( + geometry: FfiConverterSequenceTypeGeographicCoordinate.read(from: &buf), + distance: FfiConverterDouble.read(from: &buf), + duration: FfiConverterDouble.read(from: &buf), + roadName: FfiConverterOptionString.read(from: &buf), + instruction: FfiConverterString.read(from: &buf), + visualInstructions: FfiConverterSequenceTypeVisualInstruction.read(from: &buf), + spokenInstructions: FfiConverterSequenceTypeSpokenInstruction.read(from: &buf), + annotations: FfiConverterOptionSequenceString.read(from: &buf) ) } @@ -2143,14 +2435,22 @@ public struct FfiConverterTypeRouteStep: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteStep_lift(_ buf: RustBuffer) throws -> RouteStep { - try FfiConverterTypeRouteStep.lift(buf) + return try FfiConverterTypeRouteStep.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteStep_lower(_ value: RouteStep) -> RustBuffer { - FfiConverterTypeRouteStep.lower(value) + return FfiConverterTypeRouteStep.lower(value) } + /** * The speed of the user from the location provider. */ @@ -2169,18 +2469,19 @@ public struct Speed { public init( /** * The user's speed in meters per second. - */ value: Double, + */value: Double, /** - * The accuracy of the speed value, measured in meters per second. - */ accuracy: Double? - ) { + * The accuracy of the speed value, measured in meters per second. + */accuracy: Double?) { self.value = value self.accuracy = accuracy } } + + extension Speed: Equatable, Hashable { - public static func == (lhs: Speed, rhs: Speed) -> Bool { + public static func ==(lhs: Speed, rhs: Speed) -> Bool { if lhs.value != rhs.value { return false } @@ -2196,11 +2497,16 @@ extension Speed: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeSpeed: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Speed { - try Speed( - value: FfiConverterDouble.read(from: &buf), - accuracy: FfiConverterOptionDouble.read(from: &buf) + return + try Speed( + value: FfiConverterDouble.read(from: &buf), + accuracy: FfiConverterOptionDouble.read(from: &buf) ) } @@ -2210,14 +2516,22 @@ public struct FfiConverterTypeSpeed: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeSpeed_lift(_ buf: RustBuffer) throws -> Speed { - try FfiConverterTypeSpeed.lift(buf) + return try FfiConverterTypeSpeed.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeSpeed_lower(_ value: Speed) -> RustBuffer { - FfiConverterTypeSpeed.lower(value) + return FfiConverterTypeSpeed.lower(value) } + /** * An instruction that can be synthesized using a TTS engine to announce an upcoming maneuver. * @@ -2253,24 +2567,23 @@ public struct SpokenInstruction { public init( /** * Plain-text instruction which can be synthesized with a TTS engine. - */ text: String, + */text: String, /** - * Speech Synthesis Markup Language, which should be preferred by clients capable of understanding it. - */ ssml: String?, + * Speech Synthesis Markup Language, which should be preferred by clients capable of understanding it. + */ssml: String?, /** - * How far (in meters) from the upcoming maneuver the instruction should start being displayed - */ triggerDistanceBeforeManeuver: Double, + * How far (in meters) from the upcoming maneuver the instruction should start being displayed + */triggerDistanceBeforeManeuver: Double, /** - * A unique identifier for this instruction. - * - * This is provided so that platform-layer integrations can easily disambiguate between distinct utterances, - * which may have the same textual content. - * UUIDs conveniently fill this purpose. - * - * NOTE: While it is possible to deterministically create UUIDs, we do not do so at this time. - * This should be theoretically possible though if someone cares to write up a proposal and a PR. - */ utteranceId: Uuid - ) { + * A unique identifier for this instruction. + * + * This is provided so that platform-layer integrations can easily disambiguate between distinct utterances, + * which may have the same textual content. + * UUIDs conveniently fill this purpose. + * + * NOTE: While it is possible to deterministically create UUIDs, we do not do so at this time. + * This should be theoretically possible though if someone cares to write up a proposal and a PR. + */utteranceId: Uuid) { self.text = text self.ssml = ssml self.triggerDistanceBeforeManeuver = triggerDistanceBeforeManeuver @@ -2278,8 +2591,10 @@ public struct SpokenInstruction { } } -extension SpokenInstruction: Equatable, Hashable { - public static func == (lhs: SpokenInstruction, rhs: SpokenInstruction) -> Bool { + + +extension SpokenInstruction: Equatable, Hashable { + public static func ==(lhs: SpokenInstruction, rhs: SpokenInstruction) -> Bool { if lhs.text != rhs.text { return false } @@ -2303,13 +2618,18 @@ extension SpokenInstruction: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeSpokenInstruction: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SpokenInstruction { - try SpokenInstruction( - text: FfiConverterString.read(from: &buf), - ssml: FfiConverterOptionString.read(from: &buf), - triggerDistanceBeforeManeuver: FfiConverterDouble.read(from: &buf), - utteranceId: FfiConverterTypeUuid.read(from: &buf) + return + try SpokenInstruction( + text: FfiConverterString.read(from: &buf), + ssml: FfiConverterOptionString.read(from: &buf), + triggerDistanceBeforeManeuver: FfiConverterDouble.read(from: &buf), + utteranceId: FfiConverterTypeUuid.read(from: &buf) ) } @@ -2321,14 +2641,22 @@ public struct FfiConverterTypeSpokenInstruction: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeSpokenInstruction_lift(_ buf: RustBuffer) throws -> SpokenInstruction { - try FfiConverterTypeSpokenInstruction.lift(buf) + return try FfiConverterTypeSpokenInstruction.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeSpokenInstruction_lower(_ value: SpokenInstruction) -> RustBuffer { - FfiConverterTypeSpokenInstruction.lower(value) + return FfiConverterTypeSpokenInstruction.lower(value) } + /** * High-level state describing progress through a route. */ @@ -2353,24 +2681,25 @@ public struct TripProgress { public init( /** * The distance to the next maneuver, in meters. - */ distanceToNextManeuver: Double, + */distanceToNextManeuver: Double, /** - * The total distance remaining in the trip, in meters. - * - * This is the sum of the distance remaining in the current step and the distance remaining in all subsequent steps. - */ distanceRemaining: Double, + * The total distance remaining in the trip, in meters. + * + * This is the sum of the distance remaining in the current step and the distance remaining in all subsequent steps. + */distanceRemaining: Double, /** - * The total duration remaining in the trip, in seconds. - */ durationRemaining: Double - ) { + * The total duration remaining in the trip, in seconds. + */durationRemaining: Double) { self.distanceToNextManeuver = distanceToNextManeuver self.distanceRemaining = distanceRemaining self.durationRemaining = durationRemaining } } + + extension TripProgress: Equatable, Hashable { - public static func == (lhs: TripProgress, rhs: TripProgress) -> Bool { + public static func ==(lhs: TripProgress, rhs: TripProgress) -> Bool { if lhs.distanceToNextManeuver != rhs.distanceToNextManeuver { return false } @@ -2390,12 +2719,17 @@ extension TripProgress: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeTripProgress: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TripProgress { - try TripProgress( - distanceToNextManeuver: FfiConverterDouble.read(from: &buf), - distanceRemaining: FfiConverterDouble.read(from: &buf), - durationRemaining: FfiConverterDouble.read(from: &buf) + return + try TripProgress( + distanceToNextManeuver: FfiConverterDouble.read(from: &buf), + distanceRemaining: FfiConverterDouble.read(from: &buf), + durationRemaining: FfiConverterDouble.read(from: &buf) ) } @@ -2406,14 +2740,22 @@ public struct FfiConverterTypeTripProgress: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeTripProgress_lift(_ buf: RustBuffer) throws -> TripProgress { - try FfiConverterTypeTripProgress.lift(buf) + return try FfiConverterTypeTripProgress.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeTripProgress_lower(_ value: TripProgress) -> RustBuffer { - FfiConverterTypeTripProgress.lower(value) + return FfiConverterTypeTripProgress.lower(value) } + /** * The location of the user that is navigating. * @@ -2435,11 +2777,10 @@ public struct UserLocation { // Default memberwise initializers are never public by default, so we // declare one manually. - public init(coordinates: GeographicCoordinate, - /** - * The estimated accuracy of the coordinate (in meters) - */ horizontalAccuracy: Double, courseOverGround: CourseOverGround?, timestamp: Date, speed: Speed?) - { + public init(coordinates: GeographicCoordinate, + /** + * The estimated accuracy of the coordinate (in meters) + */horizontalAccuracy: Double, courseOverGround: CourseOverGround?, timestamp: Date, speed: Speed?) { self.coordinates = coordinates self.horizontalAccuracy = horizontalAccuracy self.courseOverGround = courseOverGround @@ -2448,8 +2789,10 @@ public struct UserLocation { } } + + extension UserLocation: Equatable, Hashable { - public static func == (lhs: UserLocation, rhs: UserLocation) -> Bool { + public static func ==(lhs: UserLocation, rhs: UserLocation) -> Bool { if lhs.coordinates != rhs.coordinates { return false } @@ -2477,14 +2820,19 @@ extension UserLocation: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeUserLocation: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UserLocation { - try UserLocation( - coordinates: FfiConverterTypeGeographicCoordinate.read(from: &buf), - horizontalAccuracy: FfiConverterDouble.read(from: &buf), - courseOverGround: FfiConverterOptionTypeCourseOverGround.read(from: &buf), - timestamp: FfiConverterTimestamp.read(from: &buf), - speed: FfiConverterOptionTypeSpeed.read(from: &buf) + return + try UserLocation( + coordinates: FfiConverterTypeGeographicCoordinate.read(from: &buf), + horizontalAccuracy: FfiConverterDouble.read(from: &buf), + courseOverGround: FfiConverterOptionTypeCourseOverGround.read(from: &buf), + timestamp: FfiConverterTimestamp.read(from: &buf), + speed: FfiConverterOptionTypeSpeed.read(from: &buf) ) } @@ -2497,14 +2845,22 @@ public struct FfiConverterTypeUserLocation: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeUserLocation_lift(_ buf: RustBuffer) throws -> UserLocation { - try FfiConverterTypeUserLocation.lift(buf) + return try FfiConverterTypeUserLocation.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeUserLocation_lower(_ value: UserLocation) -> RustBuffer { - FfiConverterTypeUserLocation.lower(value) + return FfiConverterTypeUserLocation.lower(value) } + /** * An instruction for visual display (usually as banners) at a specific point along a [`RouteStep`]. */ @@ -2535,17 +2891,16 @@ public struct VisualInstruction { * The primary instruction content. * * This is usually given more visual weight. - */ primaryContent: VisualInstructionContent, + */primaryContent: VisualInstructionContent, /** - * Optional secondary instruction content. - */ secondaryContent: VisualInstructionContent?, + * Optional secondary instruction content. + */secondaryContent: VisualInstructionContent?, /** - * Optional sub-maneuver instruction content. - */ subContent: VisualInstructionContent?, + * Optional sub-maneuver instruction content. + */subContent: VisualInstructionContent?, /** - * How far (in meters) from the upcoming maneuver the instruction should start being displayed - */ triggerDistanceBeforeManeuver: Double - ) { + * How far (in meters) from the upcoming maneuver the instruction should start being displayed + */triggerDistanceBeforeManeuver: Double) { self.primaryContent = primaryContent self.secondaryContent = secondaryContent self.subContent = subContent @@ -2553,8 +2908,10 @@ public struct VisualInstruction { } } + + extension VisualInstruction: Equatable, Hashable { - public static func == (lhs: VisualInstruction, rhs: VisualInstruction) -> Bool { + public static func ==(lhs: VisualInstruction, rhs: VisualInstruction) -> Bool { if lhs.primaryContent != rhs.primaryContent { return false } @@ -2578,13 +2935,18 @@ extension VisualInstruction: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeVisualInstruction: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> VisualInstruction { - try VisualInstruction( - primaryContent: FfiConverterTypeVisualInstructionContent.read(from: &buf), - secondaryContent: FfiConverterOptionTypeVisualInstructionContent.read(from: &buf), - subContent: FfiConverterOptionTypeVisualInstructionContent.read(from: &buf), - triggerDistanceBeforeManeuver: FfiConverterDouble.read(from: &buf) + return + try VisualInstruction( + primaryContent: FfiConverterTypeVisualInstructionContent.read(from: &buf), + secondaryContent: FfiConverterOptionTypeVisualInstructionContent.read(from: &buf), + subContent: FfiConverterOptionTypeVisualInstructionContent.read(from: &buf), + triggerDistanceBeforeManeuver: FfiConverterDouble.read(from: &buf) ) } @@ -2596,14 +2958,22 @@ public struct FfiConverterTypeVisualInstruction: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeVisualInstruction_lift(_ buf: RustBuffer) throws -> VisualInstruction { - try FfiConverterTypeVisualInstruction.lift(buf) + return try FfiConverterTypeVisualInstruction.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeVisualInstruction_lower(_ value: VisualInstruction) -> RustBuffer { - FfiConverterTypeVisualInstruction.lower(value) + return FfiConverterTypeVisualInstruction.lower(value) } + /** * The content of a visual instruction. */ @@ -2638,24 +3008,23 @@ public struct VisualInstructionContent { public init( /** * The text to display. - */ text: String, + */text: String, /** - * A standardized maneuver type (if any). - */ maneuverType: ManeuverType?, + * A standardized maneuver type (if any). + */maneuverType: ManeuverType?, /** - * A standardized maneuver modifier (if any). - */ maneuverModifier: ManeuverModifier?, + * A standardized maneuver modifier (if any). + */maneuverModifier: ManeuverModifier?, /** - * If applicable, the number of degrees you need to go around the roundabout before exiting. - * - * For example, entering and exiting the roundabout in the same direction of travel - * (as if you had gone straight, apart from the detour) - * would be an exit angle of 180 degrees. - */ roundaboutExitDegrees: UInt16?, + * If applicable, the number of degrees you need to go around the roundabout before exiting. + * + * For example, entering and exiting the roundabout in the same direction of travel + * (as if you had gone straight, apart from the detour) + * would be an exit angle of 180 degrees. + */roundaboutExitDegrees: UInt16?, /** - * Detailed information about the lanes. This is typically only present in sub-maneuver instructions. - */ laneInfo: [LaneInfo]? - ) { + * Detailed information about the lanes. This is typically only present in sub-maneuver instructions. + */laneInfo: [LaneInfo]?) { self.text = text self.maneuverType = maneuverType self.maneuverModifier = maneuverModifier @@ -2664,8 +3033,10 @@ public struct VisualInstructionContent { } } + + extension VisualInstructionContent: Equatable, Hashable { - public static func == (lhs: VisualInstructionContent, rhs: VisualInstructionContent) -> Bool { + public static func ==(lhs: VisualInstructionContent, rhs: VisualInstructionContent) -> Bool { if lhs.text != rhs.text { return false } @@ -2693,14 +3064,19 @@ extension VisualInstructionContent: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeVisualInstructionContent: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> VisualInstructionContent { - try VisualInstructionContent( - text: FfiConverterString.read(from: &buf), - maneuverType: FfiConverterOptionTypeManeuverType.read(from: &buf), - maneuverModifier: FfiConverterOptionTypeManeuverModifier.read(from: &buf), - roundaboutExitDegrees: FfiConverterOptionUInt16.read(from: &buf), - laneInfo: FfiConverterOptionSequenceTypeLaneInfo.read(from: &buf) + return + try VisualInstructionContent( + text: FfiConverterString.read(from: &buf), + maneuverType: FfiConverterOptionTypeManeuverType.read(from: &buf), + maneuverModifier: FfiConverterOptionTypeManeuverModifier.read(from: &buf), + roundaboutExitDegrees: FfiConverterOptionUInt16.read(from: &buf), + laneInfo: FfiConverterOptionSequenceTypeLaneInfo.read(from: &buf) ) } @@ -2713,14 +3089,22 @@ public struct FfiConverterTypeVisualInstructionContent: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeVisualInstructionContent_lift(_ buf: RustBuffer) throws -> VisualInstructionContent { - try FfiConverterTypeVisualInstructionContent.lift(buf) + return try FfiConverterTypeVisualInstructionContent.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeVisualInstructionContent_lower(_ value: VisualInstructionContent) -> RustBuffer { - FfiConverterTypeVisualInstructionContent.lower(value) + return FfiConverterTypeVisualInstructionContent.lower(value) } + /** * A waypoint along a route. * @@ -2746,8 +3130,10 @@ public struct Waypoint { } } + + extension Waypoint: Equatable, Hashable { - public static func == (lhs: Waypoint, rhs: Waypoint) -> Bool { + public static func ==(lhs: Waypoint, rhs: Waypoint) -> Bool { if lhs.coordinate != rhs.coordinate { return false } @@ -2763,11 +3149,16 @@ extension Waypoint: Equatable, Hashable { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeWaypoint: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Waypoint { - try Waypoint( - coordinate: FfiConverterTypeGeographicCoordinate.read(from: &buf), - kind: FfiConverterTypeWaypointKind.read(from: &buf) + return + try Waypoint( + coordinate: FfiConverterTypeGeographicCoordinate.read(from: &buf), + kind: FfiConverterTypeWaypointKind.read(from: &buf) ) } @@ -2777,12 +3168,19 @@ public struct FfiConverterTypeWaypoint: FfiConverterRustBuffer { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeWaypoint_lift(_ buf: RustBuffer) throws -> Waypoint { - try FfiConverterTypeWaypoint.lift(buf) + return try FfiConverterTypeWaypoint.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeWaypoint_lower(_ value: Waypoint) -> RustBuffer { - FfiConverterTypeWaypoint.lower(value) + return FfiConverterTypeWaypoint.lower(value) } // Note that we don't yet support `indirect` for enums. @@ -2792,6 +3190,7 @@ public func FfiConverterTypeWaypoint_lower(_ value: Waypoint) -> RustBuffer { */ public enum CourseFiltering { + /** * Snap the user's course to the current step's linestring using the next index in the step's geometry. @@ -2803,65 +3202,104 @@ public enum CourseFiltering { case raw } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeCourseFiltering: FfiConverterRustBuffer { typealias SwiftType = CourseFiltering public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> CourseFiltering { let variant: Int32 = try readInt(&buf) switch variant { + case 1: return .snapToRoute - + case 2: return .raw - + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: CourseFiltering, into buf: inout [UInt8]) { switch value { + + case .snapToRoute: writeInt(&buf, Int32(1)) - + + case .raw: writeInt(&buf, Int32(2)) + } } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeCourseFiltering_lift(_ buf: RustBuffer) throws -> CourseFiltering { - try FfiConverterTypeCourseFiltering.lift(buf) + return try FfiConverterTypeCourseFiltering.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeCourseFiltering_lower(_ value: CourseFiltering) -> RustBuffer { - FfiConverterTypeCourseFiltering.lower(value) + return FfiConverterTypeCourseFiltering.lower(value) } + + extension CourseFiltering: Equatable, Hashable {} + + + public enum InstantiationError { + + + case OptionsJsonParseError } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeInstantiationError: FfiConverterRustBuffer { typealias SwiftType = InstantiationError public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> InstantiationError { let variant: Int32 = try readInt(&buf) switch variant { + + + + case 1: return .OptionsJsonParseError - default: throw UniffiInternalError.unexpectedEnumCase + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: InstantiationError, into buf: inout [UInt8]) { switch value { + + + + + case .OptionsJsonParseError: writeInt(&buf, Int32(1)) + } } } + extension InstantiationError: Equatable, Hashable {} extension InstantiationError: Foundation.LocalizedError { @@ -2870,6 +3308,119 @@ extension InstantiationError: Foundation.LocalizedError { } } +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * Controls how simulated locations deviate from the actual route line. + * This simulates real-world GPS behavior where readings often have systematic bias. + */ + +public enum LocationBias { + + /** + * Simulates GPS bias by offsetting locations to the left of the route direction. + * The f64 parameter specifies the offset distance in meters. + */ + case left(Double + ) + /** + * Simulates GPS bias by offsetting locations to the right of the route direction. + * The f64 parameter specifies the offset distance in meters. + */ + case right(Double + ) + /** + * Simulates GPS bias by randomly choosing left or right offset on initialization + * and maintaining that bias throughout the route. + * The f64 parameter specifies the offset distance in meters. + * + * This mimics real-world GPS behavior where bias direction is random but typically + * remains consistent during a trip. + */ + case random(Double + ) + /** + * No position bias - locations follow the route line exactly. + * + * This provides "perfect" GPS behavior, useful for testing basic route following + * without position uncertainty. + */ + case none +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeLocationBias: FfiConverterRustBuffer { + typealias SwiftType = LocationBias + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LocationBias { + let variant: Int32 = try readInt(&buf) + switch variant { + + case 1: return .left(try FfiConverterDouble.read(from: &buf) + ) + + case 2: return .right(try FfiConverterDouble.read(from: &buf) + ) + + case 3: return .random(try FfiConverterDouble.read(from: &buf) + ) + + case 4: return .none + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: LocationBias, into buf: inout [UInt8]) { + switch value { + + + case let .left(v1): + writeInt(&buf, Int32(1)) + FfiConverterDouble.write(v1, into: &buf) + + + case let .right(v1): + writeInt(&buf, Int32(2)) + FfiConverterDouble.write(v1, into: &buf) + + + case let .random(v1): + writeInt(&buf, Int32(3)) + FfiConverterDouble.write(v1, into: &buf) + + + case .none: + writeInt(&buf, Int32(4)) + + } + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeLocationBias_lift(_ buf: RustBuffer) throws -> LocationBias { + return try FfiConverterTypeLocationBias.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeLocationBias_lower(_ value: LocationBias) -> RustBuffer { + return FfiConverterTypeLocationBias.lower(value) +} + + + +extension LocationBias: Equatable, Hashable {} + + + // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. /** @@ -2877,6 +3428,7 @@ extension InstantiationError: Foundation.LocalizedError { */ public enum ManeuverModifier { + case uTurn case sharpRight case right @@ -2887,71 +3439,97 @@ public enum ManeuverModifier { case sharpLeft } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeManeuverModifier: FfiConverterRustBuffer { typealias SwiftType = ManeuverModifier public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ManeuverModifier { let variant: Int32 = try readInt(&buf) switch variant { + case 1: return .uTurn - + case 2: return .sharpRight - + case 3: return .right - + case 4: return .slightRight - + case 5: return .straight - + case 6: return .slightLeft - + case 7: return .left - + case 8: return .sharpLeft - + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: ManeuverModifier, into buf: inout [UInt8]) { switch value { + + case .uTurn: writeInt(&buf, Int32(1)) - + + case .sharpRight: writeInt(&buf, Int32(2)) - + + case .right: writeInt(&buf, Int32(3)) - + + case .slightRight: writeInt(&buf, Int32(4)) - + + case .straight: writeInt(&buf, Int32(5)) - + + case .slightLeft: writeInt(&buf, Int32(6)) - + + case .left: writeInt(&buf, Int32(7)) - + + case .sharpLeft: writeInt(&buf, Int32(8)) + } } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeManeuverModifier_lift(_ buf: RustBuffer) throws -> ManeuverModifier { - try FfiConverterTypeManeuverModifier.lift(buf) + return try FfiConverterTypeManeuverModifier.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeManeuverModifier_lower(_ value: ManeuverModifier) -> RustBuffer { - FfiConverterTypeManeuverModifier.lower(value) + return FfiConverterTypeManeuverModifier.lower(value) } + + extension ManeuverModifier: Equatable, Hashable {} + + // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. /** @@ -2961,6 +3539,7 @@ extension ManeuverModifier: Equatable, Hashable {} */ public enum ManeuverType { + case turn case newName case depart @@ -2979,138 +3558,192 @@ public enum ManeuverType { case exitRotary } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeManeuverType: FfiConverterRustBuffer { typealias SwiftType = ManeuverType public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ManeuverType { let variant: Int32 = try readInt(&buf) switch variant { + case 1: return .turn - + case 2: return .newName - + case 3: return .depart - + case 4: return .arrive - + case 5: return .merge - + case 6: return .onRamp - + case 7: return .offRamp - + case 8: return .fork - + case 9: return .endOfRoad - - case 10: return .continue - + + case 10: return .`continue` + case 11: return .roundabout - + case 12: return .rotary - + case 13: return .roundaboutTurn - + case 14: return .notification - + case 15: return .exitRoundabout - + case 16: return .exitRotary - + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: ManeuverType, into buf: inout [UInt8]) { switch value { + + case .turn: writeInt(&buf, Int32(1)) - + + case .newName: writeInt(&buf, Int32(2)) - + + case .depart: writeInt(&buf, Int32(3)) - + + case .arrive: writeInt(&buf, Int32(4)) - + + case .merge: writeInt(&buf, Int32(5)) - + + case .onRamp: writeInt(&buf, Int32(6)) - + + case .offRamp: writeInt(&buf, Int32(7)) - + + case .fork: writeInt(&buf, Int32(8)) - + + case .endOfRoad: writeInt(&buf, Int32(9)) - - case .continue: + + + case .`continue`: writeInt(&buf, Int32(10)) - + + case .roundabout: writeInt(&buf, Int32(11)) - + + case .rotary: writeInt(&buf, Int32(12)) - + + case .roundaboutTurn: writeInt(&buf, Int32(13)) - + + case .notification: writeInt(&buf, Int32(14)) - + + case .exitRoundabout: writeInt(&buf, Int32(15)) - + + case .exitRotary: writeInt(&buf, Int32(16)) + } } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeManeuverType_lift(_ buf: RustBuffer) throws -> ManeuverType { - try FfiConverterTypeManeuverType.lift(buf) + return try FfiConverterTypeManeuverType.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeManeuverType_lower(_ value: ManeuverType) -> RustBuffer { - FfiConverterTypeManeuverType.lower(value) + return FfiConverterTypeManeuverType.lower(value) } + + extension ManeuverType: Equatable, Hashable {} + + + public enum ModelError { - case PolylineGenerationError(error: String) + + + + case PolylineGenerationError(error: String + ) } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeModelError: FfiConverterRustBuffer { typealias SwiftType = ModelError public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ModelError { let variant: Int32 = try readInt(&buf) switch variant { - case 1: return try .PolylineGenerationError( - error: FfiConverterString.read(from: &buf) + + + + + case 1: return .PolylineGenerationError( + error: try FfiConverterString.read(from: &buf) ) - default: throw UniffiInternalError.unexpectedEnumCase + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: ModelError, into buf: inout [UInt8]) { switch value { + + + + + case let .PolylineGenerationError(error): writeInt(&buf, Int32(1)) FfiConverterString.write(error, into: &buf) + } } } + extension ModelError: Equatable, Hashable {} extension ModelError: Foundation.LocalizedError { @@ -3119,61 +3752,89 @@ extension ModelError: Foundation.LocalizedError { } } + public enum ParsingError { - case InvalidRouteObject(error: String) - case InvalidGeometry(error: String) - case MalformedAnnotations(error: String) - case InvalidStatusCode(code: String) + + + + case InvalidRouteObject(error: String + ) + case InvalidGeometry(error: String + ) + case MalformedAnnotations(error: String + ) + case InvalidStatusCode(code: String + ) case UnknownParsingError } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeParsingError: FfiConverterRustBuffer { typealias SwiftType = ParsingError public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ParsingError { let variant: Int32 = try readInt(&buf) switch variant { - case 1: return try .InvalidRouteObject( - error: FfiConverterString.read(from: &buf) + + + + + case 1: return .InvalidRouteObject( + error: try FfiConverterString.read(from: &buf) ) - case 2: return try .InvalidGeometry( - error: FfiConverterString.read(from: &buf) + case 2: return .InvalidGeometry( + error: try FfiConverterString.read(from: &buf) ) - case 3: return try .MalformedAnnotations( - error: FfiConverterString.read(from: &buf) + case 3: return .MalformedAnnotations( + error: try FfiConverterString.read(from: &buf) ) - case 4: return try .InvalidStatusCode( - code: FfiConverterString.read(from: &buf) + case 4: return .InvalidStatusCode( + code: try FfiConverterString.read(from: &buf) ) case 5: return .UnknownParsingError - default: throw UniffiInternalError.unexpectedEnumCase + + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: ParsingError, into buf: inout [UInt8]) { switch value { + + + + + case let .InvalidRouteObject(error): writeInt(&buf, Int32(1)) FfiConverterString.write(error, into: &buf) - + + case let .InvalidGeometry(error): writeInt(&buf, Int32(2)) FfiConverterString.write(error, into: &buf) - + + case let .MalformedAnnotations(error): writeInt(&buf, Int32(3)) FfiConverterString.write(error, into: &buf) - + + case let .InvalidStatusCode(code): writeInt(&buf, Int32(4)) FfiConverterString.write(code, into: &buf) - + + case .UnknownParsingError: writeInt(&buf, Int32(5)) + } } } + extension ParsingError: Equatable, Hashable {} extension ParsingError: Foundation.LocalizedError { @@ -3192,6 +3853,7 @@ extension ParsingError: Foundation.LocalizedError { */ public enum RouteDeviation { + /** * The user is proceeding on course within the expected tolerances; everything is normal. */ @@ -3202,46 +3864,67 @@ public enum RouteDeviation { case offRoute( /** * The deviation from the route line, in meters. - */ deviationFromRouteLine: Double + */deviationFromRouteLine: Double ) } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRouteDeviation: FfiConverterRustBuffer { typealias SwiftType = RouteDeviation public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> RouteDeviation { let variant: Int32 = try readInt(&buf) switch variant { + case 1: return .noDeviation - - case 2: return try .offRoute(deviationFromRouteLine: FfiConverterDouble.read(from: &buf)) - + + case 2: return .offRoute(deviationFromRouteLine: try FfiConverterDouble.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: RouteDeviation, into buf: inout [UInt8]) { switch value { + + case .noDeviation: writeInt(&buf, Int32(1)) - + + case let .offRoute(deviationFromRouteLine): writeInt(&buf, Int32(2)) FfiConverterDouble.write(deviationFromRouteLine, into: &buf) + } } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteDeviation_lift(_ buf: RustBuffer) throws -> RouteDeviation { - try FfiConverterTypeRouteDeviation.lift(buf) + return try FfiConverterTypeRouteDeviation.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteDeviation_lower(_ value: RouteDeviation) -> RustBuffer { - FfiConverterTypeRouteDeviation.lower(value) + return FfiConverterTypeRouteDeviation.lower(value) } + + extension RouteDeviation: Equatable, Hashable {} + + // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. /** @@ -3249,6 +3932,7 @@ extension RouteDeviation: Equatable, Hashable {} */ public enum RouteDeviationTracking { + /** * No checks will be done, and we assume the user is always following the route. */ @@ -3260,65 +3944,85 @@ public enum RouteDeviationTracking { /** * The minimum required horizontal accuracy of the user location, in meters. * Values larger than this will not trigger route deviation warnings. - */ minimumHorizontalAccuracy: UInt16, + */minimumHorizontalAccuracy: UInt16, /** - * The maximum acceptable deviation from the route line, in meters. - * - * If the distance between the reported location and the expected route line - * is greater than this threshold, it will be flagged as an off route condition. - */ maxAcceptableDeviation: Double + * The maximum acceptable deviation from the route line, in meters. + * + * If the distance between the reported location and the expected route line + * is greater than this threshold, it will be flagged as an off route condition. + */maxAcceptableDeviation: Double ) /** * An arbitrary user-defined implementation. * You decide with your own [`RouteDeviationDetector`] implementation! */ - case custom(detector: RouteDeviationDetector) + case custom(detector: RouteDeviationDetector + ) } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRouteDeviationTracking: FfiConverterRustBuffer { typealias SwiftType = RouteDeviationTracking public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> RouteDeviationTracking { let variant: Int32 = try readInt(&buf) switch variant { + case 1: return .none - - case 2: return try .staticThreshold( - minimumHorizontalAccuracy: FfiConverterUInt16.read(from: &buf), - maxAcceptableDeviation: FfiConverterDouble.read(from: &buf) - ) - - case 3: return try .custom(detector: FfiConverterTypeRouteDeviationDetector.read(from: &buf)) - + + case 2: return .staticThreshold(minimumHorizontalAccuracy: try FfiConverterUInt16.read(from: &buf), maxAcceptableDeviation: try FfiConverterDouble.read(from: &buf) + ) + + case 3: return .custom(detector: try FfiConverterTypeRouteDeviationDetector.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: RouteDeviationTracking, into buf: inout [UInt8]) { switch value { + + case .none: writeInt(&buf, Int32(1)) - - case let .staticThreshold(minimumHorizontalAccuracy, maxAcceptableDeviation): + + + case let .staticThreshold(minimumHorizontalAccuracy,maxAcceptableDeviation): writeInt(&buf, Int32(2)) FfiConverterUInt16.write(minimumHorizontalAccuracy, into: &buf) FfiConverterDouble.write(maxAcceptableDeviation, into: &buf) - + + case let .custom(detector): writeInt(&buf, Int32(3)) FfiConverterTypeRouteDeviationDetector.write(detector, into: &buf) + } } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteDeviationTracking_lift(_ buf: RustBuffer) throws -> RouteDeviationTracking { - try FfiConverterTypeRouteDeviationTracking.lift(buf) + return try FfiConverterTypeRouteDeviationTracking.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteDeviationTracking_lower(_ value: RouteDeviationTracking) -> RustBuffer { - FfiConverterTypeRouteDeviationTracking.lower(value) + return FfiConverterTypeRouteDeviationTracking.lower(value) } + + + // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. /** @@ -3326,90 +4030,130 @@ public func FfiConverterTypeRouteDeviationTracking_lower(_ value: RouteDeviation */ public enum RouteRequest { - case httpPost(url: String, headers: [String: String], body: Data) - case httpGet(url: String, headers: [String: String]) + + case httpPost(url: String, headers: [String: String], body: Data + ) + case httpGet(url: String, headers: [String: String] + ) } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRouteRequest: FfiConverterRustBuffer { typealias SwiftType = RouteRequest public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> RouteRequest { let variant: Int32 = try readInt(&buf) switch variant { - case 1: return try .httpPost( - url: FfiConverterString.read(from: &buf), - headers: FfiConverterDictionaryStringString.read(from: &buf), - body: FfiConverterData.read(from: &buf) - ) - - case 2: return try .httpGet( - url: FfiConverterString.read(from: &buf), - headers: FfiConverterDictionaryStringString.read(from: &buf) - ) - + + case 1: return .httpPost(url: try FfiConverterString.read(from: &buf), headers: try FfiConverterDictionaryStringString.read(from: &buf), body: try FfiConverterData.read(from: &buf) + ) + + case 2: return .httpGet(url: try FfiConverterString.read(from: &buf), headers: try FfiConverterDictionaryStringString.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: RouteRequest, into buf: inout [UInt8]) { switch value { - case let .httpPost(url, headers, body): + + + case let .httpPost(url,headers,body): writeInt(&buf, Int32(1)) FfiConverterString.write(url, into: &buf) FfiConverterDictionaryStringString.write(headers, into: &buf) FfiConverterData.write(body, into: &buf) - - case let .httpGet(url, headers): + + + case let .httpGet(url,headers): writeInt(&buf, Int32(2)) FfiConverterString.write(url, into: &buf) FfiConverterDictionaryStringString.write(headers, into: &buf) + } } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteRequest_lift(_ buf: RustBuffer) throws -> RouteRequest { - try FfiConverterTypeRouteRequest.lift(buf) + return try FfiConverterTypeRouteRequest.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeRouteRequest_lower(_ value: RouteRequest) -> RustBuffer { - FfiConverterTypeRouteRequest.lower(value) + return FfiConverterTypeRouteRequest.lower(value) } + + extension RouteRequest: Equatable, Hashable {} + + + public enum RoutingRequestGenerationError { + + + case NotEnoughWaypoints case JsonError case UnknownRequestGenerationError } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeRoutingRequestGenerationError: FfiConverterRustBuffer { typealias SwiftType = RoutingRequestGenerationError public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> RoutingRequestGenerationError { let variant: Int32 = try readInt(&buf) switch variant { + + + + case 1: return .NotEnoughWaypoints case 2: return .JsonError case 3: return .UnknownRequestGenerationError - default: throw UniffiInternalError.unexpectedEnumCase + + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: RoutingRequestGenerationError, into buf: inout [UInt8]) { switch value { + + + + + case .NotEnoughWaypoints: writeInt(&buf, Int32(1)) - + + case .JsonError: writeInt(&buf, Int32(2)) - + + case .UnknownRequestGenerationError: writeInt(&buf, Int32(3)) + } } } + extension RoutingRequestGenerationError: Equatable, Hashable {} extension RoutingRequestGenerationError: Foundation.LocalizedError { @@ -3418,45 +4162,65 @@ extension RoutingRequestGenerationError: Foundation.LocalizedError { } } + public enum SimulationError { + + + /** * Errors decoding the polyline string. */ - case PolylineError(error: String) + case PolylineError(error: String + ) /** * Not enough points in the input. */ case NotEnoughPoints } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeSimulationError: FfiConverterRustBuffer { typealias SwiftType = SimulationError public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SimulationError { let variant: Int32 = try readInt(&buf) switch variant { - case 1: return try .PolylineError( - error: FfiConverterString.read(from: &buf) - ) + + + + case 1: return .PolylineError( + error: try FfiConverterString.read(from: &buf) + ) case 2: return .NotEnoughPoints - default: throw UniffiInternalError.unexpectedEnumCase + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: SimulationError, into buf: inout [UInt8]) { switch value { + + + + + case let .PolylineError(error): writeInt(&buf, Int32(1)) FfiConverterString.write(error, into: &buf) - + + case .NotEnoughPoints: writeInt(&buf, Int32(2)) + } } } + extension SimulationError: Equatable, Hashable {} extension SimulationError: Foundation.LocalizedError { @@ -3473,6 +4237,7 @@ extension SimulationError: Foundation.LocalizedError { */ public enum StepAdvanceMode { + /** * Never advances to the next step automatically; * requires calling [`NavigationController::advance_to_next_step`](super::NavigationController::advance_to_next_step). @@ -3486,11 +4251,11 @@ public enum StepAdvanceMode { case distanceToEndOfStep( /** * Distance to the last waypoint in the step, measured in meters, at which to advance. - */ distance: UInt16, + */distance: UInt16, /** - * The minimum required horizontal accuracy of the user location, in meters. - * Values larger than this cannot trigger a step advance. - */ minimumHorizontalAccuracy: UInt16 + * The minimum required horizontal accuracy of the user location, in meters. + * Values larger than this cannot trigger a step advance. + */minimumHorizontalAccuracy: UInt16 ) /** * Automatically advances when the user's distance to the *next* step's linestring is less @@ -3500,64 +4265,81 @@ public enum StepAdvanceMode { /** * The minimum required horizontal accuracy of the user location, in meters. * Values larger than this cannot trigger a step advance. - */ minimumHorizontalAccuracy: UInt16, + */minimumHorizontalAccuracy: UInt16, /** - * At this (optional) distance, navigation should advance to the next step regardless - * of which `LineString` appears closer. - */ automaticAdvanceDistance: UInt16? + * At this (optional) distance, navigation should advance to the next step regardless + * of which `LineString` appears closer. + */automaticAdvanceDistance: UInt16? ) } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeStepAdvanceMode: FfiConverterRustBuffer { typealias SwiftType = StepAdvanceMode public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> StepAdvanceMode { let variant: Int32 = try readInt(&buf) switch variant { + case 1: return .manual - - case 2: return try .distanceToEndOfStep( - distance: FfiConverterUInt16.read(from: &buf), - minimumHorizontalAccuracy: FfiConverterUInt16.read(from: &buf) - ) - - case 3: return try .relativeLineStringDistance( - minimumHorizontalAccuracy: FfiConverterUInt16.read(from: &buf), - automaticAdvanceDistance: FfiConverterOptionUInt16.read(from: &buf) - ) - + + case 2: return .distanceToEndOfStep(distance: try FfiConverterUInt16.read(from: &buf), minimumHorizontalAccuracy: try FfiConverterUInt16.read(from: &buf) + ) + + case 3: return .relativeLineStringDistance(minimumHorizontalAccuracy: try FfiConverterUInt16.read(from: &buf), automaticAdvanceDistance: try FfiConverterOptionUInt16.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: StepAdvanceMode, into buf: inout [UInt8]) { switch value { + + case .manual: writeInt(&buf, Int32(1)) - - case let .distanceToEndOfStep(distance, minimumHorizontalAccuracy): + + + case let .distanceToEndOfStep(distance,minimumHorizontalAccuracy): writeInt(&buf, Int32(2)) FfiConverterUInt16.write(distance, into: &buf) FfiConverterUInt16.write(minimumHorizontalAccuracy, into: &buf) - - case let .relativeLineStringDistance(minimumHorizontalAccuracy, automaticAdvanceDistance): + + + case let .relativeLineStringDistance(minimumHorizontalAccuracy,automaticAdvanceDistance): writeInt(&buf, Int32(3)) FfiConverterUInt16.write(minimumHorizontalAccuracy, into: &buf) FfiConverterOptionUInt16.write(automaticAdvanceDistance, into: &buf) + } } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeStepAdvanceMode_lift(_ buf: RustBuffer) throws -> StepAdvanceMode { - try FfiConverterTypeStepAdvanceMode.lift(buf) + return try FfiConverterTypeStepAdvanceMode.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeStepAdvanceMode_lower(_ value: StepAdvanceMode) -> RustBuffer { - FfiConverterTypeStepAdvanceMode.lower(value) + return FfiConverterTypeStepAdvanceMode.lower(value) } + + extension StepAdvanceMode: Equatable, Hashable {} + + // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. /** @@ -3569,6 +4351,7 @@ extension StepAdvanceMode: Equatable, Hashable {} */ public enum TripState { + /** * The navigation controller is idle and there is no active trip. */ @@ -3581,45 +4364,45 @@ public enum TripState { * The index of the closest coordinate to the user's snapped location. * * This index is relative to the *current* [`RouteStep`]'s geometry. - */ currentStepGeometryIndex: UInt64?, + */currentStepGeometryIndex: UInt64?, /** - * A location on the line string that - */ snappedUserLocation: UserLocation, + * A location on the line string that + */snappedUserLocation: UserLocation, /** - * The ordered list of steps that remain in the trip. - * - * The step at the front of the list is always the current step. - * We currently assume that you cannot move backward to a previous step. - */ remainingSteps: [RouteStep], + * The ordered list of steps that remain in the trip. + * + * The step at the front of the list is always the current step. + * We currently assume that you cannot move backward to a previous step. + */remainingSteps: [RouteStep], /** - * Remaining waypoints to visit on the route. - * - * The waypoint at the front of the list is always the *next* waypoint "goal." - * Unlike the current step, there is no value in tracking the "current" waypoint, - * as the main use of waypoints is recalculation when the user deviates from the route. - * (In most use cases, a route will have only two waypoints, but more complex use cases - * may have multiple intervening points that are visited along the route.) - * This list is updated as the user advances through the route. - */ remainingWaypoints: [Waypoint], + * Remaining waypoints to visit on the route. + * + * The waypoint at the front of the list is always the *next* waypoint "goal." + * Unlike the current step, there is no value in tracking the "current" waypoint, + * as the main use of waypoints is recalculation when the user deviates from the route. + * (In most use cases, a route will have only two waypoints, but more complex use cases + * may have multiple intervening points that are visited along the route.) + * This list is updated as the user advances through the route. + */remainingWaypoints: [Waypoint], /** - * The trip progress includes information that is useful for showing the - * user's progress along the full navigation trip, the route and its components. - */ progress: TripProgress, + * The trip progress includes information that is useful for showing the + * user's progress along the full navigation trip, the route and its components. + */progress: TripProgress, /** - * The route deviation status: is the user following the route or not? - */ deviation: RouteDeviation, + * The route deviation status: is the user following the route or not? + */deviation: RouteDeviation, /** - * The visual instruction that should be displayed in the user interface. - */ visualInstruction: VisualInstruction?, + * The visual instruction that should be displayed in the user interface. + */visualInstruction: VisualInstruction?, /** - * The most recent spoken instruction that should be synthesized using TTS. - * - * Note it is the responsibility of the platform layer to ensure that utterances are not synthesized multiple times. This property simply reports the current spoken instruction. - */ spokenInstruction: SpokenInstruction?, + * The most recent spoken instruction that should be synthesized using TTS. + * + * Note it is the responsibility of the platform layer to ensure that utterances are not synthesized multiple times. This property simply reports the current spoken instruction. + */spokenInstruction: SpokenInstruction?, /** - * Annotation data at the current location. - * This is represented as a json formatted byte array to allow for flexible encoding of custom annotations. - */ annotationJson: String? + * Annotation data at the current location. + * This is represented as a json formatted byte array to allow for flexible encoding of custom annotations. + */annotationJson: String? ) /** * The navigation controller has reached the end of the trip. @@ -3627,48 +4410,37 @@ public enum TripState { case complete } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeTripState: FfiConverterRustBuffer { typealias SwiftType = TripState public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TripState { let variant: Int32 = try readInt(&buf) switch variant { + case 1: return .idle - - case 2: return try .navigating( - currentStepGeometryIndex: FfiConverterOptionUInt64.read(from: &buf), - snappedUserLocation: FfiConverterTypeUserLocation.read(from: &buf), - remainingSteps: FfiConverterSequenceTypeRouteStep.read(from: &buf), - remainingWaypoints: FfiConverterSequenceTypeWaypoint.read(from: &buf), - progress: FfiConverterTypeTripProgress.read(from: &buf), - deviation: FfiConverterTypeRouteDeviation.read(from: &buf), - visualInstruction: FfiConverterOptionTypeVisualInstruction.read(from: &buf), - spokenInstruction: FfiConverterOptionTypeSpokenInstruction.read(from: &buf), - annotationJson: FfiConverterOptionString.read(from: &buf) - ) - + + case 2: return .navigating(currentStepGeometryIndex: try FfiConverterOptionUInt64.read(from: &buf), snappedUserLocation: try FfiConverterTypeUserLocation.read(from: &buf), remainingSteps: try FfiConverterSequenceTypeRouteStep.read(from: &buf), remainingWaypoints: try FfiConverterSequenceTypeWaypoint.read(from: &buf), progress: try FfiConverterTypeTripProgress.read(from: &buf), deviation: try FfiConverterTypeRouteDeviation.read(from: &buf), visualInstruction: try FfiConverterOptionTypeVisualInstruction.read(from: &buf), spokenInstruction: try FfiConverterOptionTypeSpokenInstruction.read(from: &buf), annotationJson: try FfiConverterOptionString.read(from: &buf) + ) + case 3: return .complete - + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: TripState, into buf: inout [UInt8]) { switch value { + + case .idle: writeInt(&buf, Int32(1)) - - case let .navigating( - currentStepGeometryIndex, - snappedUserLocation, - remainingSteps, - remainingWaypoints, - progress, - deviation, - visualInstruction, - spokenInstruction, - annotationJson - ): + + + case let .navigating(currentStepGeometryIndex,snappedUserLocation,remainingSteps,remainingWaypoints,progress,deviation,visualInstruction,spokenInstruction,annotationJson): writeInt(&buf, Int32(2)) FfiConverterOptionUInt64.write(currentStepGeometryIndex, into: &buf) FfiConverterTypeUserLocation.write(snappedUserLocation, into: &buf) @@ -3679,23 +4451,36 @@ public struct FfiConverterTypeTripState: FfiConverterRustBuffer { FfiConverterOptionTypeVisualInstruction.write(visualInstruction, into: &buf) FfiConverterOptionTypeSpokenInstruction.write(spokenInstruction, into: &buf) FfiConverterOptionString.write(annotationJson, into: &buf) - + + case .complete: writeInt(&buf, Int32(3)) + } } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeTripState_lift(_ buf: RustBuffer) throws -> TripState { - try FfiConverterTypeTripState.lift(buf) + return try FfiConverterTypeTripState.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeTripState_lower(_ value: TripState) -> RustBuffer { - FfiConverterTypeTripState.lower(value) + return FfiConverterTypeTripState.lower(value) } + + extension TripState: Equatable, Hashable {} + + // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. /** @@ -3703,6 +4488,7 @@ extension TripState: Equatable, Hashable {} */ public enum WaypointKind { + /** * Starts or ends a leg of the trip. * @@ -3715,46 +4501,69 @@ public enum WaypointKind { case via } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeWaypointKind: FfiConverterRustBuffer { typealias SwiftType = WaypointKind public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> WaypointKind { let variant: Int32 = try readInt(&buf) switch variant { - case 1: return .break - + + case 1: return .`break` + case 2: return .via - + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: WaypointKind, into buf: inout [UInt8]) { switch value { - case .break: + + + case .`break`: writeInt(&buf, Int32(1)) - + + case .via: writeInt(&buf, Int32(2)) + } } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeWaypointKind_lift(_ buf: RustBuffer) throws -> WaypointKind { - try FfiConverterTypeWaypointKind.lift(buf) + return try FfiConverterTypeWaypointKind.lift(buf) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeWaypointKind_lower(_ value: WaypointKind) -> RustBuffer { - FfiConverterTypeWaypointKind.lower(value) + return FfiConverterTypeWaypointKind.lower(value) } + + extension WaypointKind: Equatable, Hashable {} -private struct FfiConverterOptionUInt16: FfiConverterRustBuffer { + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionUInt16: FfiConverterRustBuffer { typealias SwiftType = UInt16? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3771,11 +4580,14 @@ private struct FfiConverterOptionUInt16: FfiConverterRustBuffer { } } -private struct FfiConverterOptionUInt64: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionUInt64: FfiConverterRustBuffer { typealias SwiftType = UInt64? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3792,11 +4604,14 @@ private struct FfiConverterOptionUInt64: FfiConverterRustBuffer { } } -private struct FfiConverterOptionDouble: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionDouble: FfiConverterRustBuffer { typealias SwiftType = Double? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3813,11 +4628,14 @@ private struct FfiConverterOptionDouble: FfiConverterRustBuffer { } } -private struct FfiConverterOptionString: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionString: FfiConverterRustBuffer { typealias SwiftType = String? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3834,11 +4652,14 @@ private struct FfiConverterOptionString: FfiConverterRustBuffer { } } -private struct FfiConverterOptionTypeCourseOverGround: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeCourseOverGround: FfiConverterRustBuffer { typealias SwiftType = CourseOverGround? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3855,11 +4676,14 @@ private struct FfiConverterOptionTypeCourseOverGround: FfiConverterRustBuffer { } } -private struct FfiConverterOptionTypeSpeed: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeSpeed: FfiConverterRustBuffer { typealias SwiftType = Speed? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3876,11 +4700,14 @@ private struct FfiConverterOptionTypeSpeed: FfiConverterRustBuffer { } } -private struct FfiConverterOptionTypeSpokenInstruction: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeSpokenInstruction: FfiConverterRustBuffer { typealias SwiftType = SpokenInstruction? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3897,11 +4724,14 @@ private struct FfiConverterOptionTypeSpokenInstruction: FfiConverterRustBuffer { } } -private struct FfiConverterOptionTypeVisualInstruction: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeVisualInstruction: FfiConverterRustBuffer { typealias SwiftType = VisualInstruction? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3918,11 +4748,14 @@ private struct FfiConverterOptionTypeVisualInstruction: FfiConverterRustBuffer { } } -private struct FfiConverterOptionTypeVisualInstructionContent: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeVisualInstructionContent: FfiConverterRustBuffer { typealias SwiftType = VisualInstructionContent? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3939,11 +4772,14 @@ private struct FfiConverterOptionTypeVisualInstructionContent: FfiConverterRustB } } -private struct FfiConverterOptionTypeManeuverModifier: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeManeuverModifier: FfiConverterRustBuffer { typealias SwiftType = ManeuverModifier? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3960,11 +4796,14 @@ private struct FfiConverterOptionTypeManeuverModifier: FfiConverterRustBuffer { } } -private struct FfiConverterOptionTypeManeuverType: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeManeuverType: FfiConverterRustBuffer { typealias SwiftType = ManeuverType? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -3981,11 +4820,14 @@ private struct FfiConverterOptionTypeManeuverType: FfiConverterRustBuffer { } } -private struct FfiConverterOptionSequenceString: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionSequenceString: FfiConverterRustBuffer { typealias SwiftType = [String]? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -4002,11 +4844,14 @@ private struct FfiConverterOptionSequenceString: FfiConverterRustBuffer { } } -private struct FfiConverterOptionSequenceTypeLaneInfo: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionSequenceTypeLaneInfo: FfiConverterRustBuffer { typealias SwiftType = [LaneInfo]? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { - guard let value else { + guard let value = value else { writeInt(&buf, Int8(0)) return } @@ -4023,7 +4868,10 @@ private struct FfiConverterOptionSequenceTypeLaneInfo: FfiConverterRustBuffer { } } -private struct FfiConverterSequenceString: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterSequenceString: FfiConverterRustBuffer { typealias SwiftType = [String] public static func write(_ value: [String], into buf: inout [UInt8]) { @@ -4039,13 +4887,16 @@ private struct FfiConverterSequenceString: FfiConverterRustBuffer { var seq = [String]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - try seq.append(FfiConverterString.read(from: &buf)) + seq.append(try FfiConverterString.read(from: &buf)) } return seq } } -private struct FfiConverterSequenceTypeGeographicCoordinate: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterSequenceTypeGeographicCoordinate: FfiConverterRustBuffer { typealias SwiftType = [GeographicCoordinate] public static func write(_ value: [GeographicCoordinate], into buf: inout [UInt8]) { @@ -4061,13 +4912,16 @@ private struct FfiConverterSequenceTypeGeographicCoordinate: FfiConverterRustBuf var seq = [GeographicCoordinate]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - try seq.append(FfiConverterTypeGeographicCoordinate.read(from: &buf)) + seq.append(try FfiConverterTypeGeographicCoordinate.read(from: &buf)) } return seq } } -private struct FfiConverterSequenceTypeLaneInfo: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterSequenceTypeLaneInfo: FfiConverterRustBuffer { typealias SwiftType = [LaneInfo] public static func write(_ value: [LaneInfo], into buf: inout [UInt8]) { @@ -4083,13 +4937,16 @@ private struct FfiConverterSequenceTypeLaneInfo: FfiConverterRustBuffer { var seq = [LaneInfo]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - try seq.append(FfiConverterTypeLaneInfo.read(from: &buf)) + seq.append(try FfiConverterTypeLaneInfo.read(from: &buf)) } return seq } } -private struct FfiConverterSequenceTypeRoute: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterSequenceTypeRoute: FfiConverterRustBuffer { typealias SwiftType = [Route] public static func write(_ value: [Route], into buf: inout [UInt8]) { @@ -4105,13 +4962,16 @@ private struct FfiConverterSequenceTypeRoute: FfiConverterRustBuffer { var seq = [Route]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - try seq.append(FfiConverterTypeRoute.read(from: &buf)) + seq.append(try FfiConverterTypeRoute.read(from: &buf)) } return seq } } -private struct FfiConverterSequenceTypeRouteStep: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterSequenceTypeRouteStep: FfiConverterRustBuffer { typealias SwiftType = [RouteStep] public static func write(_ value: [RouteStep], into buf: inout [UInt8]) { @@ -4127,13 +4987,16 @@ private struct FfiConverterSequenceTypeRouteStep: FfiConverterRustBuffer { var seq = [RouteStep]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - try seq.append(FfiConverterTypeRouteStep.read(from: &buf)) + seq.append(try FfiConverterTypeRouteStep.read(from: &buf)) } return seq } } -private struct FfiConverterSequenceTypeSpokenInstruction: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterSequenceTypeSpokenInstruction: FfiConverterRustBuffer { typealias SwiftType = [SpokenInstruction] public static func write(_ value: [SpokenInstruction], into buf: inout [UInt8]) { @@ -4149,13 +5012,16 @@ private struct FfiConverterSequenceTypeSpokenInstruction: FfiConverterRustBuffer var seq = [SpokenInstruction]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - try seq.append(FfiConverterTypeSpokenInstruction.read(from: &buf)) + seq.append(try FfiConverterTypeSpokenInstruction.read(from: &buf)) } return seq } } -private struct FfiConverterSequenceTypeVisualInstruction: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterSequenceTypeVisualInstruction: FfiConverterRustBuffer { typealias SwiftType = [VisualInstruction] public static func write(_ value: [VisualInstruction], into buf: inout [UInt8]) { @@ -4171,13 +5037,16 @@ private struct FfiConverterSequenceTypeVisualInstruction: FfiConverterRustBuffer var seq = [VisualInstruction]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - try seq.append(FfiConverterTypeVisualInstruction.read(from: &buf)) + seq.append(try FfiConverterTypeVisualInstruction.read(from: &buf)) } return seq } } -private struct FfiConverterSequenceTypeWaypoint: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterSequenceTypeWaypoint: FfiConverterRustBuffer { typealias SwiftType = [Waypoint] public static func write(_ value: [Waypoint], into buf: inout [UInt8]) { @@ -4193,13 +5062,16 @@ private struct FfiConverterSequenceTypeWaypoint: FfiConverterRustBuffer { var seq = [Waypoint]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - try seq.append(FfiConverterTypeWaypoint.read(from: &buf)) + seq.append(try FfiConverterTypeWaypoint.read(from: &buf)) } return seq } } -private struct FfiConverterDictionaryStringString: FfiConverterRustBuffer { +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterDictionaryStringString: FfiConverterRustBuffer { public static func write(_ value: [String: String], into buf: inout [UInt8]) { let len = Int32(value.count) writeInt(&buf, len) @@ -4213,7 +5085,7 @@ private struct FfiConverterDictionaryStringString: FfiConverterRustBuffer { let len: Int32 = try readInt(&buf) var dict = [String: String]() dict.reserveCapacity(Int(len)) - for _ in 0 ..< len { + for _ in 0..=5.8) +@_documentation(visibility: private) +#endif public struct FfiConverterTypeUuid: FfiConverter { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Uuid { let builtinValue = try FfiConverterString.read(from: &buf) return UUID(uuidString: builtinValue)! @@ -4250,12 +5129,19 @@ public struct FfiConverterTypeUuid: FfiConverter { } } + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeUuid_lift(_ value: RustBuffer) throws -> Uuid { - try FfiConverterTypeUuid.lift(value) + return try FfiConverterTypeUuid.lift(value) } +#if swift(>=5.8) +@_documentation(visibility: private) +#endif public func FfiConverterTypeUuid_lower(_ value: Uuid) -> RustBuffer { - FfiConverterTypeUuid.lower(value) + return FfiConverterTypeUuid.lower(value) } /** @@ -4269,13 +5155,12 @@ public func FfiConverterTypeUuid_lower(_ value: Uuid) -> RustBuffer { * When there are now more locations to visit, returns the same state forever. */ public func advanceLocationSimulation(state: LocationSimulationState) -> LocationSimulationState { - try! FfiConverterTypeLocationSimulationState.lift(try! rustCall { - uniffi_ferrostar_fn_func_advance_location_simulation( - FfiConverterTypeLocationSimulationState.lower(state), $0 - ) - }) + return try! FfiConverterTypeLocationSimulationState.lift(try! rustCall() { + uniffi_ferrostar_fn_func_advance_location_simulation( + FfiConverterTypeLocationSimulationState.lower(state),$0 + ) +}) } - /** * Creates a [`RouteResponseParser`] capable of parsing OSRM responses. * @@ -4284,13 +5169,12 @@ public func advanceLocationSimulation(state: LocationSimulationState) -> Locatio * which contain richer information like banners and voice instructions for navigation. */ public func createOsrmResponseParser(polylinePrecision: UInt32) -> RouteResponseParser { - try! FfiConverterTypeRouteResponseParser.lift(try! rustCall { - uniffi_ferrostar_fn_func_create_osrm_response_parser( - FfiConverterUInt32.lower(polylinePrecision), $0 - ) - }) + return try! FfiConverterTypeRouteResponseParser.lift(try! rustCall() { + uniffi_ferrostar_fn_func_create_osrm_response_parser( + FfiConverterUInt32.lower(polylinePrecision),$0 + ) +}) } - /** * Creates a [`Route`] from OSRM data. * @@ -4298,93 +5182,85 @@ public func createOsrmResponseParser(polylinePrecision: UInt32) -> RouteResponse * supporting both vanilla OSRM and enhanced Valhalla (ex: from Stadia Maps and Mapbox) outputs * which contain richer information like banners and voice instructions for navigation. */ -public func createRouteFromOsrm(routeData: Data, waypointData: Data, polylinePrecision: UInt32) throws -> Route { - try FfiConverterTypeRoute.lift(rustCallWithError(FfiConverterTypeParsingError.lift) { - uniffi_ferrostar_fn_func_create_route_from_osrm( - FfiConverterData.lower(routeData), - FfiConverterData.lower(waypointData), - FfiConverterUInt32.lower(polylinePrecision), $0 - ) - }) +public func createRouteFromOsrm(routeData: Data, waypointData: Data, polylinePrecision: UInt32)throws -> Route { + return try FfiConverterTypeRoute.lift(try rustCallWithError(FfiConverterTypeParsingError.lift) { + uniffi_ferrostar_fn_func_create_route_from_osrm( + FfiConverterData.lower(routeData), + FfiConverterData.lower(waypointData), + FfiConverterUInt32.lower(polylinePrecision),$0 + ) +}) } - /** * Creates a [`RouteRequestGenerator`] * which generates requests to an arbitrary Valhalla server (using the OSRM response format). * * This is provided as a convenience for use from foreign code when creating your own [`routing_adapters::RouteAdapter`]. */ -public func createValhallaRequestGenerator(endpointUrl: String, profile: String, - optionsJson: String?) throws -> RouteRequestGenerator -{ - try FfiConverterTypeRouteRequestGenerator.lift(rustCallWithError(FfiConverterTypeInstantiationError.lift) { - uniffi_ferrostar_fn_func_create_valhalla_request_generator( - FfiConverterString.lower(endpointUrl), - FfiConverterString.lower(profile), - FfiConverterOptionString.lower(optionsJson), $0 - ) - }) +public func createValhallaRequestGenerator(endpointUrl: String, profile: String, optionsJson: String?)throws -> RouteRequestGenerator { + return try FfiConverterTypeRouteRequestGenerator.lift(try rustCallWithError(FfiConverterTypeInstantiationError.lift) { + uniffi_ferrostar_fn_func_create_valhalla_request_generator( + FfiConverterString.lower(endpointUrl), + FfiConverterString.lower(profile), + FfiConverterOptionString.lower(optionsJson),$0 + ) +}) } - /** * Helper function for getting the route as an encoded polyline. * * Mostly used for debugging. */ -public func getRoutePolyline(route: Route, precision: UInt32) throws -> String { - try FfiConverterString.lift(rustCallWithError(FfiConverterTypeModelError.lift) { - uniffi_ferrostar_fn_func_get_route_polyline( - FfiConverterTypeRoute.lower(route), - FfiConverterUInt32.lower(precision), $0 - ) - }) +public func getRoutePolyline(route: Route, precision: UInt32)throws -> String { + return try FfiConverterString.lift(try rustCallWithError(FfiConverterTypeModelError.lift) { + uniffi_ferrostar_fn_func_get_route_polyline( + FfiConverterTypeRoute.lower(route), + FfiConverterUInt32.lower(precision),$0 + ) +}) } - /** * Creates a location simulation from a set of coordinates. * * Optionally resamples the input line so that there is a maximum distance between points. */ -public func locationSimulationFromCoordinates(coordinates: [GeographicCoordinate], - resampleDistance: Double?) throws -> LocationSimulationState -{ - try FfiConverterTypeLocationSimulationState.lift(rustCallWithError(FfiConverterTypeSimulationError.lift) { - uniffi_ferrostar_fn_func_location_simulation_from_coordinates( - FfiConverterSequenceTypeGeographicCoordinate.lower(coordinates), - FfiConverterOptionDouble.lower(resampleDistance), $0 - ) - }) +public func locationSimulationFromCoordinates(coordinates: [GeographicCoordinate], resampleDistance: Double?, bias: LocationBias)throws -> LocationSimulationState { + return try FfiConverterTypeLocationSimulationState.lift(try rustCallWithError(FfiConverterTypeSimulationError.lift) { + uniffi_ferrostar_fn_func_location_simulation_from_coordinates( + FfiConverterSequenceTypeGeographicCoordinate.lower(coordinates), + FfiConverterOptionDouble.lower(resampleDistance), + FfiConverterTypeLocationBias.lower(bias),$0 + ) +}) } - /** * Creates a location simulation from a polyline. * * Optionally resamples the input line so that there is no more than the specified maximum distance between points. */ -public func locationSimulationFromPolyline(polyline: String, precision: UInt32, - resampleDistance: Double?) throws -> LocationSimulationState -{ - try FfiConverterTypeLocationSimulationState.lift(rustCallWithError(FfiConverterTypeSimulationError.lift) { - uniffi_ferrostar_fn_func_location_simulation_from_polyline( - FfiConverterString.lower(polyline), - FfiConverterUInt32.lower(precision), - FfiConverterOptionDouble.lower(resampleDistance), $0 - ) - }) +public func locationSimulationFromPolyline(polyline: String, precision: UInt32, resampleDistance: Double?, bias: LocationBias)throws -> LocationSimulationState { + return try FfiConverterTypeLocationSimulationState.lift(try rustCallWithError(FfiConverterTypeSimulationError.lift) { + uniffi_ferrostar_fn_func_location_simulation_from_polyline( + FfiConverterString.lower(polyline), + FfiConverterUInt32.lower(precision), + FfiConverterOptionDouble.lower(resampleDistance), + FfiConverterTypeLocationBias.lower(bias),$0 + ) +}) } - /** * Creates a location simulation from a route. * * Optionally resamples the route geometry so that there is no more than the specified maximum distance between points. */ -public func locationSimulationFromRoute(route: Route, resampleDistance: Double?) throws -> LocationSimulationState { - try FfiConverterTypeLocationSimulationState.lift(rustCallWithError(FfiConverterTypeSimulationError.lift) { - uniffi_ferrostar_fn_func_location_simulation_from_route( - FfiConverterTypeRoute.lower(route), - FfiConverterOptionDouble.lower(resampleDistance), $0 - ) - }) +public func locationSimulationFromRoute(route: Route, resampleDistance: Double?, bias: LocationBias)throws -> LocationSimulationState { + return try FfiConverterTypeLocationSimulationState.lift(try rustCallWithError(FfiConverterTypeSimulationError.lift) { + uniffi_ferrostar_fn_func_location_simulation_from_route( + FfiConverterTypeRoute.lower(route), + FfiConverterOptionDouble.lower(resampleDistance), + FfiConverterTypeLocationBias.lower(bias),$0 + ) +}) } private enum InitializationResult { @@ -4392,7 +5268,6 @@ private enum InitializationResult { case contractVersionMismatch case apiChecksumMismatch } - // Use a global variable to perform the versioning checks. Swift ensures that // the code inside is only computed once. private var initializationResult: InitializationResult = { @@ -4403,61 +5278,61 @@ private var initializationResult: InitializationResult = { if bindings_contract_version != scaffolding_contract_version { return InitializationResult.contractVersionMismatch } - if uniffi_ferrostar_checksum_func_advance_location_simulation() != 26307 { + if (uniffi_ferrostar_checksum_func_advance_location_simulation() != 26307) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_func_create_osrm_response_parser() != 16550 { + if (uniffi_ferrostar_checksum_func_create_osrm_response_parser() != 16550) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_func_create_route_from_osrm() != 42270 { + if (uniffi_ferrostar_checksum_func_create_route_from_osrm() != 42270) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_func_create_valhalla_request_generator() != 16275 { + if (uniffi_ferrostar_checksum_func_create_valhalla_request_generator() != 16275) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_func_get_route_polyline() != 31480 { + if (uniffi_ferrostar_checksum_func_get_route_polyline() != 31480) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_func_location_simulation_from_coordinates() != 30262 { + if (uniffi_ferrostar_checksum_func_location_simulation_from_coordinates() != 52416) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_func_location_simulation_from_polyline() != 12234 { + if (uniffi_ferrostar_checksum_func_location_simulation_from_polyline() != 14615) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_func_location_simulation_from_route() != 47899 { + if (uniffi_ferrostar_checksum_func_location_simulation_from_route() != 39027) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_method_navigationcontroller_advance_to_next_step() != 3820 { + if (uniffi_ferrostar_checksum_method_navigationcontroller_advance_to_next_step() != 3820) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_method_navigationcontroller_get_initial_state() != 63862 { + if (uniffi_ferrostar_checksum_method_navigationcontroller_get_initial_state() != 63862) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_method_navigationcontroller_update_user_location() != 3165 { + if (uniffi_ferrostar_checksum_method_navigationcontroller_update_user_location() != 3165) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_method_routeadapter_generate_request() != 59034 { + if (uniffi_ferrostar_checksum_method_routeadapter_generate_request() != 59034) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_method_routeadapter_parse_response() != 34481 { + if (uniffi_ferrostar_checksum_method_routeadapter_parse_response() != 34481) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_method_routedeviationdetector_check_route_deviation() != 50476 { + if (uniffi_ferrostar_checksum_method_routedeviationdetector_check_route_deviation() != 50476) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_method_routerequestgenerator_generate_request() != 63458 { + if (uniffi_ferrostar_checksum_method_routerequestgenerator_generate_request() != 63458) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_method_routeresponseparser_parse_response() != 44735 { + if (uniffi_ferrostar_checksum_method_routeresponseparser_parse_response() != 44735) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_constructor_navigationcontroller_new() != 60881 { + if (uniffi_ferrostar_checksum_constructor_navigationcontroller_new() != 60881) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_constructor_routeadapter_new() != 32290 { + if (uniffi_ferrostar_checksum_constructor_routeadapter_new() != 32290) { return InitializationResult.apiChecksumMismatch } - if uniffi_ferrostar_checksum_constructor_routeadapter_new_valhalla_http() != 3524 { + if (uniffi_ferrostar_checksum_constructor_routeadapter_new_valhalla_http() != 3524) { return InitializationResult.apiChecksumMismatch } @@ -4478,4 +5353,4 @@ private func uniffiEnsureInitialized() { } } -// swiftlint:enable all +// swiftlint:enable all \ No newline at end of file diff --git a/apple/Tests/FerrostarCoreTests/FerrostarCoreTests.swift b/apple/Tests/FerrostarCoreTests/FerrostarCoreTests.swift index 1a860c48..c5fc4423 100644 --- a/apple/Tests/FerrostarCoreTests/FerrostarCoreTests.swift +++ b/apple/Tests/FerrostarCoreTests/FerrostarCoreTests.swift @@ -395,6 +395,11 @@ final class FerrostarCoreTests: XCTestCase { await fulfillment(of: [routeDeviationCallbackExp], timeout: 1.0) await fulfillment(of: [loadedAltRoutesExp], timeout: 1.0) + // At this point, there is a brief window where the delegate call loading alternate routes has completed, + // but the state is still updating. This is a quick hack to fix the tests + // in the absence of something more reliable. + try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10) + XCTAssert(core.state?.isCalculatingNewRoute == false, "Expected to no longer be calculating a new route") } diff --git a/apple/Tests/FerrostarSwiftUITests/Views/MuteButtonTests.swift b/apple/Tests/FerrostarSwiftUITests/Views/MuteButtonTests.swift index 06ec0275..bdfe26b9 100644 --- a/apple/Tests/FerrostarSwiftUITests/Views/MuteButtonTests.swift +++ b/apple/Tests/FerrostarSwiftUITests/Views/MuteButtonTests.swift @@ -5,13 +5,13 @@ import XCTest final class MuteUIButtonTests: XCTestCase { func test_muted() { assertView { - MuteUIButton(isMuted: true, action: {}) + NavigationUIMuteButton(isMuted: true, action: {}) } } func test_unmuted() { assertView { - MuteUIButton(isMuted: false, action: {}) + NavigationUIMuteButton(isMuted: false, action: {}) } } @@ -19,13 +19,13 @@ final class MuteUIButtonTests: XCTestCase { func test_muted_darkMode() { assertView(colorScheme: .dark) { - MuteUIButton(isMuted: true, action: {}) + NavigationUIMuteButton(isMuted: true, action: {}) } } func test_unmuted_darkMode() { assertView(colorScheme: .dark) { - MuteUIButton(isMuted: false, action: {}) + NavigationUIMuteButton(isMuted: false, action: {}) } } } diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_muted.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_muted.1.png index 459825b4..e37fa447 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_muted.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_muted.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_muted_darkMode.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_muted_darkMode.1.png index 459825b4..b79f6187 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_muted_darkMode.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_muted_darkMode.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_unmuted.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_unmuted.1.png index b97d371d..f3d4d9c1 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_unmuted.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_unmuted.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_unmuted_darkMode.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_unmuted_darkMode.1.png index b97d371d..ebceb94d 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_unmuted_darkMode.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/MuteButtonTests/test_unmuted_darkMode.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigatingInnerGridViewTests/test_USStyle_speedLimit_inGridView.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigatingInnerGridViewTests/test_USStyle_speedLimit_inGridView.1.png index 02796bb9..edee9464 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigatingInnerGridViewTests/test_USStyle_speedLimit_inGridView.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigatingInnerGridViewTests/test_USStyle_speedLimit_inGridView.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigatingInnerGridViewTests/test_ViennaConventionStyle_speedLimit_inGridView.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigatingInnerGridViewTests/test_ViennaConventionStyle_speedLimit_inGridView.1.png index 9ca34fb9..57e73e5c 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigatingInnerGridViewTests/test_ViennaConventionStyle_speedLimit_inGridView.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigatingInnerGridViewTests/test_ViennaConventionStyle_speedLimit_inGridView.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testImageButton.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testImageButton.1.png index ee30fb36..fe0b9e94 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testImageButton.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testImageButton.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testImageButton_darkMode.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testImageButton_darkMode.1.png index eec048cb..dced7d97 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testImageButton_darkMode.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testImageButton_darkMode.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testTextButton.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testTextButton.1.png index 026ad980..4c6077e5 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testTextButton.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testTextButton.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testTextButton_darkMode.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testTextButton_darkMode.1.png index bd7cf58d..c0ee0d71 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testTextButton_darkMode.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIButtonTests/testTextButton_darkMode.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIZoomButtonTests/testNavigationUIZoomButton.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIZoomButtonTests/testNavigationUIZoomButton.1.png index 4d8f2153..c1a9c100 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIZoomButtonTests/testNavigationUIZoomButton.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIZoomButtonTests/testNavigationUIZoomButton.1.png differ diff --git a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIZoomButtonTests/testNavigationUIZoomButton_darkMode.1.png b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIZoomButtonTests/testNavigationUIZoomButton_darkMode.1.png index d0c73126..ced1fd2b 100644 Binary files a/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIZoomButtonTests/testNavigationUIZoomButton_darkMode.1.png and b/apple/Tests/FerrostarSwiftUITests/Views/__Snapshots__/NavigationUIZoomButtonTests/testNavigationUIZoomButton_darkMode.1.png differ diff --git a/common/Cargo.lock b/common/Cargo.lock index b615bc6b..16a54344 100644 --- a/common/Cargo.lock +++ b/common/Cargo.lock @@ -325,6 +325,31 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crypto-common" version = "0.1.6" @@ -375,7 +400,7 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "ferrostar" -version = "0.20.0" +version = "0.20.1" dependencies = [ "assert-json-diff", "geo", @@ -384,6 +409,7 @@ dependencies = [ "itertools 0.13.0", "polyline", "proptest", + "rand", "rstest", "serde", "serde-wasm-bindgen 0.6.5", @@ -519,14 +545,15 @@ dependencies = [ [[package]] name = "geo" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f811f663912a69249fa620dcd2a005db7254529da2d8a0b23942e81f47084501" +checksum = "81d088357a9cc60cec8253b3578f6834b4a3aa20edb55f5d1c030c36d8143f11" dependencies = [ "earcutr", "float_next_after", "geo-types", "geographiclib-rs", + "i_overlay", "log", "num-traits", "robust", @@ -626,6 +653,50 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "i_float" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fe043aae28ce70bd2f78b2f5f82a3654d63607c82594da4dabb8b6cb81f2b2" +dependencies = [ + "serde", +] + +[[package]] +name = "i_key_sort" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "347c253b4748a1a28baf94c9ce133b6b166f08573157e05afe718812bc599fcd" + +[[package]] +name = "i_overlay" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a469f68cb8a7cef375b2b0f581faf5859b4b50600438c00d46b71acc25ebbd0c" +dependencies = [ + "i_float", + "i_key_sort", + "i_shape", + "i_tree", + "rayon", +] + +[[package]] +name = "i_shape" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b44852d57a991c7dedaf76c55bc44f677f547ff899a430d29e13efd6133d7d8" +dependencies = [ + "i_float", + "serde", +] + +[[package]] +name = "i_tree" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155181bc97d770181cf9477da51218a19ee92a8e5be642e796661aee2b601139" + [[package]] name = "indexmap" version = "2.6.0" @@ -638,9 +709,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60" +checksum = "7e9ffc4d4892617c50a928c52b2961cb5174b6fc6ebf252b2fac9d21955c48b8" dependencies = [ "console", "lazy_static", @@ -953,6 +1024,26 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "regex" version = "1.11.0" @@ -1149,9 +1240,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -1241,9 +1332,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.79" +version = "2.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c" dependencies = [ "proc-macro2", "quote", @@ -1261,18 +1352,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" dependencies = [ "proc-macro2", "quote", @@ -1364,9 +1455,9 @@ checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "uniffi" -version = "0.28.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2db87def739fe4183947f8419d572d1849a4a09355eba4e988a2105cfd0ac6a7" +checksum = "51ce6280c581045879e11b400bae14686a819df22b97171215d15549efa04ddb" dependencies = [ "anyhow", "camino", @@ -1385,11 +1476,18 @@ dependencies = [ "uniffi", ] +[[package]] +name = "uniffi-bindgen-swift" +version = "0.1.0" +dependencies = [ + "uniffi", +] + [[package]] name = "uniffi_bindgen" -version = "0.28.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a112599c9556d1581e4a3d72019a74c2c3e122cc27f4af12577a429c4d5e614" +checksum = "5e9f25730c9db2e878521d606f54e921edb719cdd94d735e7f97705d6796d024" dependencies = [ "anyhow", "askama", @@ -1410,9 +1508,9 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.28.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b12684401d2a8508ca9c72a95bbc45906417e42fc80942abaf033bbf01aa33" +checksum = "88dba57ac699bd8ec53d6a352c8dd0e479b33f698c5659831bb1e4ce468c07bd" dependencies = [ "anyhow", "camino", @@ -1421,9 +1519,9 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.28.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a22dbe67c1c957ac6e7611bdf605a6218aa86b0eebeb8be58b70ae85ad7d73dc" +checksum = "d2c801f0f05b06df456a2da4c41b9c2c4fdccc6b9916643c6c67275c4c9e4d07" dependencies = [ "quote", "syn", @@ -1431,13 +1529,12 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.28.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0c35aaad30e3a9e6d4fe34e358d64dbc92ee09045b48591b05fc9f12e0905b" +checksum = "61049e4db6212d0ede80982adf0e1d6fa224e6118387324c5cfbe3083dfb2252" dependencies = [ "anyhow", "bytes", - "camino", "log", "once_cell", "paste", @@ -1446,9 +1543,9 @@ dependencies = [ [[package]] name = "uniffi_macros" -version = "0.28.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db66474c5c61b0f7afc3b4995fecf9b72b340daa5ca0ef3da7778d75eb5482ea" +checksum = "b40fd2249e0c5dcbd2bfa3c263db1ec981f7273dca7f4132bf06a272359a586c" dependencies = [ "bincode", "camino", @@ -1464,9 +1561,9 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.28.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d898893f102e0e39b8bcb7e3d2188f4156ba280db32db9e8af1f122d057e9526" +checksum = "c9ad57039b4fafdbf77428d74fff40e0908e5a1731e023c19cfe538f6d4a8ed6" dependencies = [ "anyhow", "bytes", @@ -1476,9 +1573,9 @@ dependencies = [ [[package]] name = "uniffi_testing" -version = "0.28.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6aa4f0cf9d12172d84fc00a35a6c1f3522b526daad05ae739f709f6941b9b6" +checksum = "21fa171d4d258dc51bbd01893cc9608c1b62273d2f9ea55fb64f639e77824567" dependencies = [ "anyhow", "camino", @@ -1489,9 +1586,9 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.28.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b044e9c519e0bb51e516ab6f6d8f4f4dcf900ce30d5ad07c03f924e2824f28e" +checksum = "f52299e247419e7e2934bef2f94d7cccb0e6566f3248b1d48b160d8f369a2668" dependencies = [ "anyhow", "textwrap", @@ -1508,9 +1605,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", "serde", diff --git a/common/Cargo.toml b/common/Cargo.toml index e9c4db07..9ea4ab43 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "uniffi-bindgen", + "uniffi-bindgen-swift", "ferrostar", ] resolver = "2" @@ -21,7 +22,7 @@ lto = "thin" opt-level = "s" [workspace.dependencies] -uniffi = "0.28.1" +uniffi = "0.28.2" [workspace.lints.rust] unsafe_code = "forbid" diff --git a/common/build-ios.sh b/common/build-ios.sh index 8c6d53dd..850c20fa 100755 --- a/common/build-ios.sh +++ b/common/build-ios.sh @@ -32,10 +32,11 @@ fat_simulator_lib_dir="target/ios-simulator-fat/release" generate_ffi() { echo "Generating framework module mapping and FFI bindings" - cargo run -p uniffi-bindgen generate --library target/aarch64-apple-ios/release/lib$1.dylib --language swift --out-dir target/uniffi-xcframework-staging + # NOTE: Convention requires the modulemap be named module.modulemap + cargo run -p uniffi-bindgen-swift -- target/aarch64-apple-ios/release/lib$1.a target/uniffi-xcframework-staging --swift-sources --headers --modulemap --module-name $1FFI --modulemap-filename module.modulemap mkdir -p ../apple/Sources/UniFFI/ mv target/uniffi-xcframework-staging/*.swift ../apple/Sources/UniFFI/ - mv target/uniffi-xcframework-staging/$1FFI.modulemap target/uniffi-xcframework-staging/module.modulemap # Convention requires this have a specific name + mv target/uniffi-xcframework-staging/module.modulemap target/uniffi-xcframework-staging/module.modulemap } create_fat_simulator_lib() { diff --git a/common/ferrostar/Cargo.toml b/common/ferrostar/Cargo.toml index 5a620391..5f650c8b 100644 --- a/common/ferrostar/Cargo.toml +++ b/common/ferrostar/Cargo.toml @@ -2,7 +2,7 @@ lints.workspace = true [package] name = "ferrostar" -version = "0.20.0" +version = "0.20.1" readme = "README.md" description = "The core of modern turn-by-turn navigation." keywords = ["navigation", "routing", "valhalla", "osrm"] @@ -28,14 +28,15 @@ wasm_js = [ ] [dependencies] -geo = "0.28.0" +geo = "0.29.0" polyline = "0.11.0" +rand = "0.8.5" serde = { version = "1.0.210", features = ["derive"] } -serde_json = { version = "1.0.128", default-features = false } +serde_json = { version = "1.0.132", default-features = false } serde-wasm-bindgen = { version = "0.6.5", optional = true } -thiserror = "1.0.64" +thiserror = "1.0.66" uniffi = { workspace = true, optional = true } -uuid = { version = "1.10.0", features = ["v4", "serde"] } +uuid = { version = "1.11.0", features = ["v4", "serde"] } getrandom = { version = "0.2.15", optional = true } wasm-bindgen = { version = "0.2.93", optional = true } web-time = { version = "1.1.0", features = ["serde"], optional = true } @@ -48,7 +49,7 @@ uniffi = { workspace = true, features = ["build"] } [dev-dependencies] assert-json-diff = "2.0.2" proptest = { version = "1.5.0", default-features = false } -insta = { version = "1.40.0", features = ["yaml", "redactions"] } +insta = { version = "1.41.1", features = ["yaml", "redactions"] } rstest = "0.23.0" wasm-bindgen-test = "0.3" diff --git a/common/ferrostar/src/algorithms.rs b/common/ferrostar/src/algorithms.rs index 83852350..7f9f7b15 100644 --- a/common/ferrostar/src/algorithms.rs +++ b/common/ferrostar/src/algorithms.rs @@ -12,8 +12,8 @@ use crate::{ navigation_controller::models::TripProgress, }; use geo::{ - Closest, ClosestPoint, Coord, EuclideanDistance, GeodesicBearing, HaversineDistance, - HaversineLength, LineLocatePoint, LineString, Point, + Bearing, Closest, Coord, Distance, Euclidean, Geodesic, Haversine, HaversineClosestPoint, + Length, LineLocatePoint, LineString, Point, }; #[cfg(test)] @@ -28,23 +28,6 @@ use std::time::SystemTime; #[cfg(all(test, feature = "web-time"))] use web_time::SystemTime; -/// Normalizes a bearing returned from several `geo` crate functions, -/// which may be negative, into a positive unsigned integer. -/// -/// NOTE: This function assumes that the input values are in the range -360 to +360, -/// and does not check the inputs for validity. -pub(crate) fn normalize_bearing(degrees: f64) -> u16 { - let rounded = degrees.round(); - let normalized = if rounded < 0.0 { - rounded + 360.0 - } else if rounded >= 360.0 { - rounded - 360.0 - } else { - rounded - }; - normalized.round() as u16 -} - /// Get the index of the closest *segment* to the user's location within a [`LineString`]. /// /// A [`LineString`] is a set of points (ex: representing the geometry of a maneuver), @@ -64,10 +47,13 @@ pub fn index_of_closest_segment_origin(location: UserLocation, line: &LineString // Iterate through all segments of the line .enumerate() // Find the line segment closest to the user's location - .min_by(|(_, line1), (_, line2)| { + .min_by(|(_, line_segment_1), (_, line_segment_2)| { // Note: lines don't implement haversine distances - let dist1 = line1.euclidean_distance(&point); - let dist2 = line2.euclidean_distance(&point); + // In case you're tempted to say that this looks like cross track distance, + // note that the Line type here is actually a line *segment*, + // and we actually want to find the closest segment, not the closest mathematical line. + let dist1 = Euclidean::distance(line_segment_1, &point); + let dist2 = Euclidean::distance(line_segment_2, &point); dist1.total_cmp(&dist2) }) .map(|(index, _)| index as u64) @@ -85,13 +71,8 @@ fn get_bearing_to_next_point( let current = points.next()?; let next = points.next()?; - // This function may return negative bearing values, but we want to always normalize to [0, 360) - let degrees = normalize_bearing(current.geodesic_bearing(next)); - - Some(CourseOverGround { - degrees, - accuracy: None, - }) + let degrees = Geodesic::bearing(current, next); + Some(CourseOverGround::new(degrees, None)) } /// Apply a snapped course to a user location. @@ -161,7 +142,7 @@ fn snap_point_to_line(point: &Point, line: &LineString) -> Option { // Bail early when we have two essentially identical points. // This can cause some issues with edge cases (captured in proptest regressions) // with the underlying libraries. - if line.euclidean_distance(point) < 0.000_001 { + if Euclidean::distance(line, point) < 0.000_001 { return Some(*point); } @@ -170,8 +151,7 @@ fn snap_point_to_line(point: &Point, line: &LineString) -> Option { return None; } - // TODO: Use haversine_closest_point once a new release is cut which doesn't panic on intersections - match line.closest_point(point) { + match line.haversine_closest_point(point) { Closest::Intersection(snapped) | Closest::SinglePoint(snapped) => { let (x, y) = (snapped.x(), snapped.y()); if is_valid_float(x) && is_valid_float(y) { @@ -210,7 +190,7 @@ fn snap_point_to_line(point: &Point, line: &LineString) -> Option { /// }; /// let off_line = point! { /// x: 1.0, -/// y: 0.5, +/// y: 0.5, /// }; /// /// // The origin is directly on the line @@ -220,13 +200,14 @@ fn snap_point_to_line(point: &Point, line: &LineString) -> Option { /// assert_eq!(deviation_from_line(&midpoint, &linestring), Some(0.0)); /// /// // This point, however is off the line. -/// // That's a huge number, because we're dealing with degrees ;) +/// // That's a huge number, because we're dealing with points jumping by degrees ;) +/// println!("{:?}", deviation_from_line(&off_line, &linestring)); /// assert!(deviation_from_line(&off_line, &linestring) -/// .map_or(false, |deviation| deviation - 39312.21257675703 < f64::EPSILON)); +/// .map_or(false, |deviation| deviation - 39316.14208341989 < f64::EPSILON)); /// ``` pub fn deviation_from_line(point: &Point, line: &LineString) -> Option { snap_point_to_line(point, line).and_then(|snapped| { - let distance = snapped.haversine_distance(point); + let distance = Haversine::distance(snapped, *point); if distance.is_nan() || distance.is_infinite() { None @@ -243,7 +224,7 @@ fn is_close_enough_to_end_of_linestring( ) -> bool { if let Some(end_coord) = current_step_linestring.coords().last() { let end_point = Point::from(*end_coord); - let distance_to_end = end_point.haversine_distance(current_position); + let distance_to_end = Haversine::distance(end_point, *current_position); distance_to_end <= threshold } else { @@ -310,8 +291,8 @@ pub fn should_advance_to_next_step( // If the user's distance to the snapped location on the *next* step is <= // the user's distance to the snapped location on the *current* step, // advance to the next step - current_position.haversine_distance(&next_step_closest_point) - <= current_position.haversine_distance(¤t_step_closest_point) + Haversine::distance(current_position, next_step_closest_point) + <= Haversine::distance(current_position, current_step_closest_point) } else { // The user's location couldn't be mapped to a single point on both the current and next step. // Fall back to the distance to end of step mode, which has some graceful fallbacks. @@ -366,7 +347,7 @@ pub(crate) fn advance_step(remaining_steps: &[RouteStep]) -> StepAdvanceStatus { /// The result is given in meters. /// The result may be [`None`] in case of invalid input such as infinite floats. fn distance_along(point: &Point, linestring: &LineString) -> Option { - let total_length = linestring.haversine_length(); + let total_length = linestring.length::(); if total_length == 0.0 { return Some(0.0); } @@ -379,9 +360,9 @@ fn distance_along(point: &Point, linestring: &LineString) -> Option { // Compute distance to the line (sadly Euclidean only; no haversine_distance in GeoRust // but this is probably OK for now) - let segment_distance_to_point = segment.euclidean_distance(point); + let segment_distance_to_point = Euclidean::distance(&segment, point); // Compute total segment length in meters - let segment_length = segment_linestring.haversine_length(); + let segment_length = segment_linestring.length::(); if segment_distance_to_point < closest_dist_to_point { let segment_fraction = segment.line_locate_point(point)?; @@ -410,7 +391,7 @@ fn distance_to_end_of_step( snapped_location: &Point, current_step_linestring: &LineString, ) -> Option { - let step_length = current_step_linestring.haversine_length(); + let step_length = current_step_linestring.length::(); distance_along(snapped_location, current_step_linestring) .map(|traversed| step_length - traversed) } @@ -536,7 +517,7 @@ proptest! { prop_assert!(is_valid_float(x) || (!is_valid_float(x1) && x == x1)); prop_assert!(is_valid_float(y) || (!is_valid_float(y1) && y == y1)); - prop_assert!(line.euclidean_distance(&snapped) < 0.000001); + prop_assert!(Euclidean::distance(&line, &snapped) < 0.000001); } else { // Edge case 1: extremely small differences in values let is_miniscule_difference = (x1 - x2).abs() < 0.00000001 || (y1 - y2).abs() < 0.00000001; @@ -635,7 +616,7 @@ proptest! { speed: None }; let user_location_point = Point::from(user_location); - let distance_from_end_of_current_step = user_location_point.haversine_distance(&end_of_step.into()); + let distance_from_end_of_current_step = Haversine::distance(user_location_point, end_of_step.into()); // Never advance to the next step when StepAdvanceMode is Manual prop_assert!(!should_advance_to_next_step(¤t_route_step.get_linestring(), next_route_step.as_ref(), &user_location, StepAdvanceMode::Manual)); @@ -730,12 +711,6 @@ proptest! { prop_assert!(index < (coord_len - 1) as u64); } - #[test] - fn test_bearing_correction_valid_range(bearing in -360f64..360f64) { - let result = normalize_bearing(bearing); - prop_assert!(result < 360); - } - #[test] fn test_bearing_fuzz(coords in vec(arb_coord(), 2..500), index in 0usize..1_000usize) { let line = LineString::new(coords); diff --git a/common/ferrostar/src/models.rs b/common/ferrostar/src/models.rs index 694f6ff2..176c2890 100644 --- a/common/ferrostar/src/models.rs +++ b/common/ferrostar/src/models.rs @@ -171,8 +171,18 @@ pub struct CourseOverGround { } impl CourseOverGround { - pub fn new(degrees: u16, accuracy: Option) -> Self { - Self { degrees, accuracy } + /// # Arguments + /// + /// - degrees: The direction in which the user's device is traveling, measured in clockwise degrees from + /// true north (N = 0, E = 90, S = 180, W = 270). + /// NOTE: Input values must lie in the range [0, 360). + /// - accuracy: the accuracy of the course value, measured in degrees. + pub fn new(degrees: f64, accuracy: Option) -> Self { + debug_assert!(degrees >= 0.0 && degrees < 360.0); + Self { + degrees: degrees.round() as u16, + accuracy, + } } } diff --git a/common/ferrostar/src/navigation_controller/mod.rs b/common/ferrostar/src/navigation_controller/mod.rs index 141d1659..cb1a8bec 100644 --- a/common/ferrostar/src/navigation_controller/mod.rs +++ b/common/ferrostar/src/navigation_controller/mod.rs @@ -12,7 +12,10 @@ use crate::{ }, models::{Route, UserLocation}, }; -use geo::{HaversineDistance, LineString, Point}; +use geo::{ + algorithm::{Distance, Haversine}, + geometry::{LineString, Point}, +}; use models::{NavigationControllerConfig, StepAdvanceStatus, TripState}; use std::clone::Clone; @@ -125,7 +128,7 @@ impl NavigationController { let next_waypoint: Point = waypoint.coordinate.into(); // TODO: This is just a hard-coded threshold for the time being. // More sophisticated behavior will take some time and use cases, so punting on this for now. - current_location.haversine_distance(&next_waypoint) < 100.0 + Haversine::distance(current_location, next_waypoint) < 100.0 } else { false }; diff --git a/common/ferrostar/src/navigation_controller/test_helpers.rs b/common/ferrostar/src/navigation_controller/test_helpers.rs index fd89e4d1..ca39f075 100644 --- a/common/ferrostar/src/navigation_controller/test_helpers.rs +++ b/common/ferrostar/src/navigation_controller/test_helpers.rs @@ -1,7 +1,7 @@ use crate::models::{BoundingBox, GeographicCoordinate, Route, RouteStep, Waypoint, WaypointKind}; #[cfg(feature = "alloc")] use alloc::string::ToString; -use geo::{line_string, BoundingRect, HaversineLength, LineString, Point}; +use geo::{line_string, BoundingRect, Haversine, Length, LineString, Point}; pub fn gen_dummy_route_step( start_lng: f64, @@ -24,7 +24,7 @@ pub fn gen_dummy_route_step( (x: start_lng, y: start_lat), (x: end_lng, y: end_lat) ] - .haversine_length(), + .length::(), duration: 0.0, road_name: None, instruction: "".to_string(), diff --git a/common/ferrostar/src/simulation.rs b/common/ferrostar/src/simulation.rs index 78f009a1..141964f3 100644 --- a/common/ferrostar/src/simulation.rs +++ b/common/ferrostar/src/simulation.rs @@ -9,7 +9,7 @@ //! `SimulatedLocationProvider` implementations which wrap this. //! //! ``` -//! use ferrostar::simulation::{advance_location_simulation, location_simulation_from_polyline}; +//! use ferrostar::simulation::{advance_location_simulation, location_simulation_from_polyline, LocationBias}; //! # use std::error::Error; //! # fn main() -> Result<(), Box> { //! @@ -22,6 +22,7 @@ //! // Passing `Some(number)` will resample your polyline at uniform distances. //! // This is often desirable to create a smooth simulated movement when you don't have a GPS trace. //! None, +//! LocationBias::None, //! )?; //! //! loop { @@ -38,9 +39,9 @@ //! # } //! ``` -use crate::algorithms::{normalize_bearing, trunc_float}; +use crate::algorithms::trunc_float; use crate::models::{CourseOverGround, GeographicCoordinate, Route, UserLocation}; -use geo::{coord, DensifyHaversine, GeodesicBearing, LineString, Point}; +use geo::{coord, Bearing, Densify, Geodesic, Haversine, LineString, Point}; use polyline::decode_polyline; #[cfg(any(test, feature = "wasm-bindgen"))] @@ -78,6 +79,37 @@ pub enum SimulationError { NotEnoughPoints, } +/// Controls how simulated locations deviate from the actual route line. +/// This simulates real-world GPS behavior where readings often have systematic bias. +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] +#[cfg_attr(any(feature = "wasm-bindgen", test), derive(Serialize, Deserialize))] +#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))] +#[cfg_attr(feature = "wasm-bindgen", tsify(into_wasm_abi, from_wasm_abi))] +pub enum LocationBias { + /// Simulates GPS bias by offsetting locations to the left of the route direction. + /// The f64 parameter specifies the offset distance in meters. + Left(f64), + + /// Simulates GPS bias by offsetting locations to the right of the route direction. + /// The f64 parameter specifies the offset distance in meters. + Right(f64), + + /// Simulates GPS bias by randomly choosing left or right offset on initialization + /// and maintaining that bias throughout the route. + /// The f64 parameter specifies the offset distance in meters. + /// + /// This mimics real-world GPS behavior where bias direction is random but typically + /// remains consistent during a trip. + Random(f64), + + /// No position bias - locations follow the route line exactly. + /// + /// This provides "perfect" GPS behavior, useful for testing basic route following + /// without position uncertainty. + None, +} + /// The current state of the simulation. #[derive(Clone, PartialEq)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] @@ -87,6 +119,7 @@ pub enum SimulationError { pub struct LocationSimulationState { pub current_location: UserLocation, remaining_locations: Vec, + bias: LocationBias, } /// Creates a location simulation from a set of coordinates. @@ -96,23 +129,24 @@ pub struct LocationSimulationState { pub fn location_simulation_from_coordinates( coordinates: &[GeographicCoordinate], resample_distance: Option, + bias: LocationBias, ) -> Result { if let Some((current, rest)) = coordinates.split_first() { if let Some(next) = rest.first() { - let current_point = Point::from(*current); - let next_point = Point::from(*next); - let bearing = current_point.geodesic_bearing(next_point); + let (jittered_current, bearing) = add_lateral_offset(*current, *next, &bias); + + let accuracy = match bias { + LocationBias::None => 0.0, + LocationBias::Left(m) | LocationBias::Right(m) | LocationBias::Random(m) => m, + }; + let current_location = UserLocation { - coordinates: *current, - horizontal_accuracy: 0.0, - course_over_ground: Some(CourseOverGround { - degrees: bearing.round() as u16, - accuracy: None, - }), + coordinates: jittered_current, + horizontal_accuracy: accuracy, + course_over_ground: Some(CourseOverGround::new(bearing, Some(5))), timestamp: SystemTime::now(), speed: None, }; - let remaining_locations = if let Some(distance) = resample_distance { // Interpolate so that there are no points further apart than the resample distance. let coords: Vec<_> = rest @@ -125,7 +159,7 @@ pub fn location_simulation_from_coordinates( }) .collect(); let linestring: LineString = coords.into(); - let densified_linestring = linestring.densify_haversine(distance); + let densified_linestring = linestring.densify::(distance); densified_linestring .points() .map(|point| GeographicCoordinate { @@ -144,6 +178,7 @@ pub fn location_simulation_from_coordinates( Ok(LocationSimulationState { current_location, remaining_locations, + bias, }) } else { Err(SimulationError::NotEnoughPoints) @@ -160,10 +195,11 @@ pub fn location_simulation_from_coordinates( pub fn location_simulation_from_route( route: &Route, resample_distance: Option, + bias: LocationBias, ) -> Result { // This function is purely a convenience for now, // but we eventually expand the simulation to be aware of route timing - location_simulation_from_coordinates(&route.geometry, resample_distance) + location_simulation_from_coordinates(&route.geometry, resample_distance, bias) } /// Creates a location simulation from a polyline. @@ -174,6 +210,7 @@ pub fn location_simulation_from_polyline( polyline: &str, precision: u32, resample_distance: Option, + bias: LocationBias, ) -> Result { let linestring = decode_polyline(polyline, precision).map_err(|error| SimulationError::PolylineError { @@ -183,7 +220,52 @@ pub fn location_simulation_from_polyline( .coords() .map(|c| GeographicCoordinate::from(*c)) .collect(); - location_simulation_from_coordinates(&coordinates, resample_distance) + location_simulation_from_coordinates(&coordinates, resample_distance, bias) +} + +fn add_lateral_offset( + current: GeographicCoordinate, + next: GeographicCoordinate, + bias: &LocationBias, +) -> (GeographicCoordinate, f64) { + let current_point = Point::from(current); + let next_point = Point::from(next); + let bearing = Geodesic::bearing(current_point, next_point); + + match bias { + LocationBias::None => (current, bearing), + LocationBias::Left(meters) | LocationBias::Right(meters) | LocationBias::Random(meters) => { + let sign = match bias { + LocationBias::Left(_) => -1.0, + LocationBias::Right(_) => 1.0, + LocationBias::Random(_) => { + if rand::random() { + 1.0 + } else { + -1.0 + } + } + LocationBias::None => unreachable!(), + }; + + // calculate perpendicular bearing (±90° from bearing) + let lateral_bearing_rad = (bearing + sign * 90.0).to_radians(); + + // offset to approximate degrees + let offset_deg = meters / 111111.0; + + let lat_offset = offset_deg * lateral_bearing_rad.cos(); + let lng_offset = offset_deg * lateral_bearing_rad.sin(); + + ( + GeographicCoordinate { + lat: current.lat + lat_offset, + lng: current.lng + lng_offset, + }, + bearing, + ) + } + } } /// Returns the next simulation state based on the desired strategy. @@ -197,17 +279,25 @@ pub fn location_simulation_from_polyline( #[cfg_attr(feature = "uniffi", uniffi::export)] pub fn advance_location_simulation(state: &LocationSimulationState) -> LocationSimulationState { if let Some((next_coordinate, rest)) = state.remaining_locations.split_first() { - let current_point = Point::from(state.current_location.coordinates); - let next_point = Point::from(*next_coordinate); - let bearing = normalize_bearing(current_point.geodesic_bearing(next_point)); + let (jittered_next, bearing) = add_lateral_offset( + *next_coordinate, + if let Some(future) = rest.first() { + *future + } else { + *next_coordinate + }, + &state.bias, + ); + + let accuracy = match state.bias { + LocationBias::None => 0.0, + LocationBias::Left(m) | LocationBias::Right(m) | LocationBias::Random(m) => m, + }; let next_location = UserLocation { - coordinates: *next_coordinate, - horizontal_accuracy: 0.0, - course_over_ground: Some(CourseOverGround { - degrees: bearing, - accuracy: None, - }), + coordinates: jittered_next, + horizontal_accuracy: accuracy, + course_over_ground: Some(CourseOverGround::new(bearing, Some(5))), timestamp: SystemTime::now(), speed: None, }; @@ -215,6 +305,7 @@ pub fn advance_location_simulation(state: &LocationSimulationState) -> LocationS LocationSimulationState { current_location: next_location, remaining_locations: Vec::from(rest), + bias: state.bias.clone(), } } else { state.clone() @@ -227,11 +318,12 @@ pub fn advance_location_simulation(state: &LocationSimulationState) -> LocationS pub fn js_location_simulation_from_coordinates( coordinates: JsValue, resample_distance: Option, + bias: LocationBias, ) -> Result { let coordinates: Vec = serde_wasm_bindgen::from_value(coordinates) .map_err(|error| JsValue::from_str(&error.to_string()))?; - location_simulation_from_coordinates(&coordinates, resample_distance) + location_simulation_from_coordinates(&coordinates, resample_distance, bias) .map(|state| serde_wasm_bindgen::to_value(&state).unwrap()) .map_err(|error| JsValue::from_str(&error.to_string())) } @@ -242,11 +334,12 @@ pub fn js_location_simulation_from_coordinates( pub fn js_location_simulation_from_route( route: JsValue, resample_distance: Option, + bias: LocationBias, ) -> Result { let route: Route = serde_wasm_bindgen::from_value(route) .map_err(|error| JsValue::from_str(&error.to_string()))?; - location_simulation_from_route(&route, resample_distance) + location_simulation_from_route(&route, resample_distance, bias) .map(|state| serde_wasm_bindgen::to_value(&state).unwrap()) .map_err(|error| JsValue::from_str(&error.to_string())) } @@ -258,8 +351,9 @@ pub fn js_location_simulation_from_polyline( polyline: &str, precision: u32, resample_distance: Option, + bias: LocationBias, ) -> Result { - location_simulation_from_polyline(polyline, precision, resample_distance) + location_simulation_from_polyline(polyline, precision, resample_distance, bias) .map(|state| serde_wasm_bindgen::to_value(&state).unwrap()) .map_err(|error| JsValue::from_str(&error.to_string())) } @@ -277,7 +371,7 @@ pub fn js_advance_location_simulation(state: JsValue) -> JsValue { mod tests { use super::*; use crate::algorithms::snap_user_location_to_line; - use geo::HaversineDistance; + use geo::{Distance, Haversine}; use rstest::rstest; #[rstest] @@ -301,6 +395,7 @@ mod tests { }, ], resample_distance, + LocationBias::None, ) .expect("Unable to initialize simulation"); @@ -324,6 +419,7 @@ mod tests { "wzvmrBxalf|GcCrX}A|Nu@jI}@pMkBtZ{@x^_Afj@Inn@`@veB", 6, None, + LocationBias::None, ) .expect("Unable to parse polyline"); insta::assert_yaml_snapshot!(state); @@ -333,8 +429,9 @@ mod tests { fn test_extended_interpolation_simulation() { let polyline = r#"umrefAzifwgF?yJf@?|C@?sJ?iL@_BBqD@cDzh@L|@?jBuDjCCl@u@^f@nB?|ABd@s@r@_AAiBBiC@kAlAHrEQ|F@pCNpA?pAAfB?~CkAtXsGRXlDw@rCo@jBc@SwAKoDr@}GLyAJ}AEs@]qBs@gE_@qC?aBBqAVkBZwBLmAFcBG_DOuB?}A^wAjA}Av@eBJoAAyA[sBbCUhAEIoCdAaCd@{@Fer@@ae@?aD?o[Ny@Vk@Sg@C_FCcDT[S_@Ow@F}oCXoAVe@_@e@?mE?cDNm@Og@Ok@Ck^N_BRu@a@OJqFFyDV[a@kAIkSLcF|AgNb@{@U_@JaEN}ETW[cA\_TbAkm@P_H\sE`AgFrCkKlAuGrEo\n@_B|@[~sBa@pAc@|AAh`Aa@jGEnGCrh@AfiAAjAx@TW`DO|CK\mEZ?~LBzBA|_@GtA?zPGlKQ?op@?uO@ggA?wE@uFEwXEyOCeFAkMAsKIot@?_FEoYAsI?yC?eH?}C?}GAy]Bux@Aog@AmKCmFC}YA}WVgBRu@vAaBlC{CxDCR?h@AhHQvGApDA|BAhHA`DC|GGzFDlM@jNA|J?bAkBtACvAArCClINfDdAfFGzW[|HI`FE@eMhHEt^KpJE"#; let max_distance = 10.0; - let mut state = location_simulation_from_polyline(polyline, 6, Some(max_distance)) - .expect("Unable to create initial state"); + let mut state = + location_simulation_from_polyline(polyline, 6, Some(max_distance), LocationBias::None) + .expect("Unable to create initial state"); let original_linestring = decode_polyline(polyline, 6).expect("Unable to decode polyline"); // Loop until state no longer changes @@ -348,7 +445,7 @@ mod tests { // The distance between each point in the simulation should be <= max_distance let current_point: Point = state.current_location.into(); let next_point: Point = new_state.current_location.into(); - let distance = current_point.haversine_distance(&next_point); + let distance = Haversine::distance(current_point, next_point); // I'm actually not 100% sure why this extra fudge is needed, but it's not a concern for today. assert!( distance <= max_distance + 7.0, @@ -358,7 +455,7 @@ mod tests { let snapped = snap_user_location_to_line(new_state.current_location, &original_linestring); let snapped_point: Point = snapped.coordinates.into(); - let distance = next_point.haversine_distance(&snapped_point); + let distance = Haversine::distance(next_point, snapped_point); assert!( distance <= max_distance, "Expected snapped point to be on the line; was {distance}m away" @@ -379,4 +476,90 @@ mod tests { ); insta::assert_yaml_snapshot!(states); } + + #[rstest] + #[case(LocationBias::None)] + #[case(LocationBias::Left(4.0))] + #[case(LocationBias::Right(4.0))] + #[case(LocationBias::Random(4.0))] + fn test_location_bias(#[case] bias: LocationBias) { + let coordinates = vec![ + GeographicCoordinate { lng: 0.0, lat: 0.0 }, + GeographicCoordinate { + lng: 0.0001, + lat: 0.0001, + }, + GeographicCoordinate { + lng: 0.0002, + lat: 0.0002, + }, + ]; + + let state = location_simulation_from_coordinates(&coordinates, None, bias.clone()) + .expect("Failed to create simulation"); + + if matches!(bias, LocationBias::None) { + assert_eq!(state.current_location.coordinates, coordinates[0]); + return; + } + + let expected_meters = match bias { + LocationBias::Left(m) | LocationBias::Right(m) | LocationBias::Random(m) => m, + LocationBias::None => unreachable!(), + }; + + let original_point: Point = coordinates[0].into(); + let offset_point: Point = state.current_location.coordinates.into(); + let distance = Haversine::distance(original_point, offset_point); + + assert!( + (distance - expected_meters).abs() < 0.1, + "Expected offset of {expected_meters}m but got {distance}m" + ); + } + + #[test] + fn test_bias_consistency() { + let coordinates = vec![ + GeographicCoordinate { lng: 0.0, lat: 0.0 }, + GeographicCoordinate { + lng: 0.0001, + lat: 0.0001, + }, + GeographicCoordinate { + lng: 0.0002, + lat: 0.0002, + }, + GeographicCoordinate { + lng: 0.0003, + lat: 0.0003, + }, + ]; + + let mut state = + location_simulation_from_coordinates(&coordinates, None, LocationBias::Random(4.0)) + .expect("Failed to create simulation"); + + let first_point: Point = state.current_location.coordinates.into(); + let first_original: Point = coordinates[0].into(); + let initial_distance = Haversine::distance(first_point, first_original); + + while let Some((next, _)) = state.remaining_locations.split_first() { + let new_state = advance_location_simulation(&state); + if new_state == state { + break; + } + + let current_point: Point = new_state.current_location.coordinates.into(); + let original_point: Point = (*next).into(); + let distance = Haversine::distance(current_point, original_point); + + assert!( + (distance - initial_distance).abs() < 0.1, + "Bias distance changed from {initial_distance}m to {distance}m" + ); + + state = new_state; + } + } } diff --git a/common/ferrostar/src/snapshots/ferrostar__simulation__tests__None.snap b/common/ferrostar/src/snapshots/ferrostar__simulation__tests__None.snap index 77f4cfcd..a2b758cd 100644 --- a/common/ferrostar/src/snapshots/ferrostar__simulation__tests__None.snap +++ b/common/ferrostar/src/snapshots/ferrostar__simulation__tests__None.snap @@ -9,7 +9,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 45 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 0.0001 @@ -18,6 +18,7 @@ expression: states lng: 0.0002 - lat: 0.0003 lng: 0.0003 + bias: None - current_location: coordinates: lat: 0.0001 @@ -25,13 +26,14 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 45 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 0.0002 lng: 0.0002 - lat: 0.0003 lng: 0.0003 + bias: None - current_location: coordinates: lat: 0.0002 @@ -39,18 +41,20 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 45 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 0.0003 lng: 0.0003 + bias: None - current_location: coordinates: lat: 0.0003 lng: 0.0003 horizontal_accuracy: 0 course_over_ground: - degrees: 45 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: [] + bias: None diff --git a/common/ferrostar/src/snapshots/ferrostar__simulation__tests__Some(10.0).snap b/common/ferrostar/src/snapshots/ferrostar__simulation__tests__Some(10.0).snap index 78579375..69471eac 100644 --- a/common/ferrostar/src/snapshots/ferrostar__simulation__tests__Some(10.0).snap +++ b/common/ferrostar/src/snapshots/ferrostar__simulation__tests__Some(10.0).snap @@ -9,7 +9,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 45 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 0.0001 @@ -22,6 +22,7 @@ expression: states lng: 0.00025 - lat: 0.0003 lng: 0.0003 + bias: None - current_location: coordinates: lat: 0.0001 @@ -29,7 +30,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 45 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 0.00015 @@ -40,6 +41,7 @@ expression: states lng: 0.00025 - lat: 0.0003 lng: 0.0003 + bias: None - current_location: coordinates: lat: 0.00015 @@ -47,7 +49,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 45 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 0.0002 @@ -56,6 +58,7 @@ expression: states lng: 0.00025 - lat: 0.0003 lng: 0.0003 + bias: None - current_location: coordinates: lat: 0.0002 @@ -63,13 +66,14 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 45 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 0.00025 lng: 0.00025 - lat: 0.0003 lng: 0.0003 + bias: None - current_location: coordinates: lat: 0.00025 @@ -77,18 +81,20 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 45 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 0.0003 lng: 0.0003 + bias: None - current_location: coordinates: lat: 0.0003 lng: 0.0003 horizontal_accuracy: 0 course_over_ground: - degrees: 45 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: [] + bias: None diff --git a/common/ferrostar/src/snapshots/ferrostar__simulation__tests__extended_interpolation_simulation.snap b/common/ferrostar/src/snapshots/ferrostar__simulation__tests__extended_interpolation_simulation.snap index 9af750be..65b7dbd5 100644 --- a/common/ferrostar/src/snapshots/ferrostar__simulation__tests__extended_interpolation_simulation.snap +++ b/common/ferrostar/src/snapshots/ferrostar__simulation__tests__extended_interpolation_simulation.snap @@ -9,7 +9,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332715 @@ -872,14 +872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332715 lng: -122.031601 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332695 @@ -1740,14 +1741,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332695 lng: -122.031601 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 181 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332616 @@ -2606,14 +2608,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332616 lng: -122.031602 horizontal_accuracy: 0 course_over_ground: - degrees: 181 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332616 @@ -3470,6 +3473,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332616 @@ -3477,7 +3481,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332616 @@ -4332,6 +4336,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332616 @@ -4339,7 +4344,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332616 @@ -5192,6 +5197,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332616 @@ -5199,7 +5205,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332616 @@ -6050,14 +6056,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332616 lng: -122.031203 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332615 @@ -6906,14 +6913,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332615 lng: -122.031155 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 92 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332613 @@ -7760,14 +7768,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332613 lng: -122.031066 horizontal_accuracy: 0 course_over_ground: - degrees: 92 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332612 @@ -8612,14 +8621,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332612 lng: -122.030984 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 181 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332528 @@ -9462,6 +9472,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332528 @@ -9469,7 +9480,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 181 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332445 @@ -10310,6 +10321,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332445 @@ -10317,7 +10329,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 181 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332361 @@ -11156,6 +11168,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332361 @@ -11163,7 +11176,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 181 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332277 @@ -12000,14 +12013,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332277 lng: -122.030988 horizontal_accuracy: 0 course_over_ground: - degrees: 181 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332193 @@ -12842,14 +12856,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332193 lng: -122.030988 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 181 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33211 @@ -13682,6 +13697,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33211 @@ -13689,7 +13705,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 181 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.332026 @@ -14520,6 +14536,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.332026 @@ -14527,7 +14544,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 181 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331942 @@ -15356,14 +15373,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331942 lng: -122.030991 horizontal_accuracy: 0 course_over_ground: - degrees: 181 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331911 @@ -16190,14 +16208,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331911 lng: -122.030991 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 126 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331884 @@ -17022,14 +17041,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331884 lng: -122.030945 horizontal_accuracy: 0 course_over_ground: - degrees: 126 - accuracy: ~ + degrees: 127 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331857 @@ -17852,14 +17872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331857 lng: -122.0309 horizontal_accuracy: 0 course_over_ground: - degrees: 127 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331787 @@ -18680,14 +18701,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331787 lng: -122.030898 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 137 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331764 @@ -19506,14 +19528,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331764 lng: -122.030871 horizontal_accuracy: 0 course_over_ground: - degrees: 137 - accuracy: ~ + degrees: 225 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331748 @@ -20330,14 +20353,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331748 lng: -122.030891 horizontal_accuracy: 0 course_over_ground: - degrees: 225 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331692 @@ -21152,14 +21176,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331692 lng: -122.030891 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 182 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331645 @@ -21972,14 +21997,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331645 lng: -122.030893 horizontal_accuracy: 0 course_over_ground: - degrees: 182 - accuracy: ~ + degrees: 132 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331626 @@ -22790,14 +22816,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331626 lng: -122.030867 horizontal_accuracy: 0 course_over_ground: - degrees: 132 - accuracy: ~ + degrees: 135 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.3316 @@ -23606,14 +23633,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.3316 lng: -122.030835 horizontal_accuracy: 0 course_over_ground: - degrees: 135 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331601 @@ -24420,14 +24448,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331601 lng: -122.030782 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 92 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331599 @@ -25232,6 +25261,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331599 @@ -25239,7 +25269,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 92 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331598 @@ -26042,14 +26072,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331598 lng: -122.030675 horizontal_accuracy: 0 course_over_ground: - degrees: 92 - accuracy: ~ + degrees: 186 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331559 @@ -26850,14 +26881,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331559 lng: -122.03068 horizontal_accuracy: 0 course_over_ground: - degrees: 186 - accuracy: ~ + degrees: 176 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331506 @@ -27656,14 +27688,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331506 lng: -122.030675 horizontal_accuracy: 0 course_over_ground: - degrees: 176 - accuracy: ~ + degrees: 177 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331453 @@ -28460,14 +28493,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331453 lng: -122.030671 horizontal_accuracy: 0 course_over_ground: - degrees: 177 - accuracy: ~ + degrees: 181 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33139 @@ -29262,14 +29296,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33139 lng: -122.030672 horizontal_accuracy: 0 course_over_ground: - degrees: 181 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331326 @@ -30062,14 +30097,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331326 lng: -122.030672 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 185 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331253 @@ -30860,14 +30896,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331253 lng: -122.03068 horizontal_accuracy: 0 course_over_ground: - degrees: 185 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331212 @@ -31656,14 +31693,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331212 lng: -122.03068 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331171 @@ -32450,14 +32488,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331171 lng: -122.030679 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331119 @@ -33242,14 +33281,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331119 lng: -122.030679 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 159 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.331039 @@ -34032,14 +34072,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.331039 lng: -122.030641 horizontal_accuracy: 0 course_over_ground: - degrees: 159 - accuracy: ~ + degrees: 165 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330957 @@ -34820,6 +34861,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330957 @@ -34827,7 +34869,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 165 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330875 @@ -35606,6 +35648,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330875 @@ -35613,7 +35656,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 165 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330792 @@ -36390,6 +36433,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330792 @@ -36397,7 +36441,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 165 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33071 @@ -37172,6 +37216,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33071 @@ -37179,7 +37224,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 165 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330628 @@ -37952,14 +37997,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330628 lng: -122.030503 horizontal_accuracy: 0 course_over_ground: - degrees: 165 - accuracy: ~ + degrees: 226 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330618 @@ -38730,14 +38776,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330618 lng: -122.030516 horizontal_accuracy: 0 course_over_ground: - degrees: 226 - accuracy: ~ + degrees: 166 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330531 @@ -39506,14 +39553,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330531 lng: -122.030488 horizontal_accuracy: 0 course_over_ground: - degrees: 166 - accuracy: ~ + degrees: 165 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330457 @@ -40280,6 +40328,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330457 @@ -40287,7 +40336,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 165 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330403 @@ -41052,14 +41101,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330403 lng: -122.030446 horizontal_accuracy: 0 course_over_ground: - degrees: 165 - accuracy: ~ + degrees: 74 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330413 @@ -41822,14 +41872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330413 lng: -122.030402 horizontal_accuracy: 0 course_over_ground: - degrees: 74 - accuracy: ~ + degrees: 85 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330419 @@ -42590,14 +42641,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330419 lng: -122.030314 horizontal_accuracy: 0 course_over_ground: - degrees: 85 - accuracy: ~ + degrees: 103 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330406 @@ -43356,6 +43408,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330406 @@ -43363,7 +43416,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 103 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330393 @@ -44120,14 +44173,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330393 lng: -122.030171 horizontal_accuracy: 0 course_over_ground: - degrees: 103 - accuracy: ~ + degrees: 101 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330386 @@ -44882,14 +44936,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330386 lng: -122.030126 horizontal_accuracy: 0 course_over_ground: - degrees: 101 - accuracy: ~ + degrees: 99 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33038 @@ -45642,14 +45697,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33038 lng: -122.030079 horizontal_accuracy: 0 course_over_ground: - degrees: 99 - accuracy: ~ + degrees: 82 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330383 @@ -46400,14 +46456,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330383 lng: -122.030053 horizontal_accuracy: 0 course_over_ground: - degrees: 82 - accuracy: ~ + degrees: 72 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330398 @@ -47156,6 +47213,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330398 @@ -47163,7 +47221,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 72 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330424 @@ -47910,14 +47968,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330424 lng: -122.029896 horizontal_accuracy: 0 course_over_ground: - degrees: 72 - accuracy: ~ + degrees: 75 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33044 @@ -48662,14 +48721,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33044 lng: -122.029823 horizontal_accuracy: 0 course_over_ground: - degrees: 75 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33044 @@ -49412,14 +49472,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33044 lng: -122.029774 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 93 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330438 @@ -50160,14 +50221,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330438 lng: -122.029733 horizontal_accuracy: 0 course_over_ground: - degrees: 93 - accuracy: ~ + degrees: 106 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330426 @@ -50906,6 +50968,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330426 @@ -50913,7 +50976,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 106 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330412 @@ -51650,14 +51713,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330412 lng: -122.029619 horizontal_accuracy: 0 course_over_ground: - degrees: 106 - accuracy: ~ + degrees: 103 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330405 @@ -52392,14 +52456,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330405 lng: -122.02958 horizontal_accuracy: 0 course_over_ground: - degrees: 103 - accuracy: ~ + degrees: 96 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330401 @@ -53132,14 +53197,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330401 lng: -122.02953 horizontal_accuracy: 0 course_over_ground: - degrees: 96 - accuracy: ~ + degrees: 86 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330405 @@ -53870,14 +53936,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330405 lng: -122.02945 horizontal_accuracy: 0 course_over_ground: - degrees: 86 - accuracy: ~ + degrees: 80 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330413 @@ -54606,14 +54673,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330413 lng: -122.029391 horizontal_accuracy: 0 course_over_ground: - degrees: 80 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330413 @@ -55340,14 +55408,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330413 lng: -122.029344 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 114 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330397 @@ -56072,14 +56141,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330397 lng: -122.0293 horizontal_accuracy: 0 course_over_ground: - degrees: 114 - accuracy: ~ + degrees: 135 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330359 @@ -56802,14 +56872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330359 lng: -122.029253 horizontal_accuracy: 0 course_over_ground: - degrees: 135 - accuracy: ~ + degrees: 125 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330331 @@ -57530,14 +57601,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330331 lng: -122.029202 horizontal_accuracy: 0 course_over_ground: - degrees: 125 - accuracy: ~ + degrees: 101 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330325 @@ -58256,14 +58328,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330325 lng: -122.029162 horizontal_accuracy: 0 course_over_ground: - degrees: 101 - accuracy: ~ + degrees: 88 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330326 @@ -58980,14 +59053,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330326 lng: -122.029117 horizontal_accuracy: 0 course_over_ground: - degrees: 88 - accuracy: ~ + degrees: 73 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33034 @@ -59702,14 +59776,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33034 lng: -122.029059 horizontal_accuracy: 0 course_over_ground: - degrees: 73 - accuracy: ~ + degrees: 172 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330274 @@ -60422,14 +60497,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330274 lng: -122.029048 horizontal_accuracy: 0 course_over_ground: - degrees: 172 - accuracy: ~ + degrees: 176 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330237 @@ -61140,14 +61216,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330237 lng: -122.029045 horizontal_accuracy: 0 course_over_ground: - degrees: 176 - accuracy: ~ + degrees: 85 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330242 @@ -61856,14 +61933,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330242 lng: -122.028973 horizontal_accuracy: 0 course_over_ground: - degrees: 85 - accuracy: ~ + degrees: 124 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330207 @@ -62570,14 +62648,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330207 lng: -122.028908 horizontal_accuracy: 0 course_over_ground: - degrees: 124 - accuracy: ~ + degrees: 128 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330188 @@ -63282,14 +63361,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330188 lng: -122.028878 horizontal_accuracy: 0 course_over_ground: - degrees: 128 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330188 @@ -63992,14 +64072,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330188 lng: -122.028776 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330187 @@ -64700,14 +64781,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330187 lng: -122.028673 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330187 @@ -65406,14 +65488,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330187 lng: -122.028571 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330186 @@ -66110,14 +66193,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330186 lng: -122.028468 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330186 @@ -66812,14 +66896,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330186 lng: -122.028366 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330185 @@ -67512,14 +67597,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330185 lng: -122.028264 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330185 @@ -68210,14 +68296,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330185 lng: -122.028161 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330184 @@ -68906,14 +68993,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330184 lng: -122.028059 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330184 @@ -69600,6 +69688,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330184 @@ -69607,7 +69696,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330184 @@ -70292,6 +70381,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330184 @@ -70299,7 +70389,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330184 @@ -70982,14 +71072,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330184 lng: -122.027754 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -71670,14 +71761,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 lng: -122.027653 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -72356,6 +72448,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -72363,7 +72456,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -73040,6 +73133,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -73047,7 +73141,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -73722,6 +73816,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -73729,7 +73824,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -74402,6 +74497,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -74409,7 +74505,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -75080,6 +75176,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -75087,7 +75184,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -75756,6 +75853,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -75763,7 +75861,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -76430,6 +76528,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -76437,7 +76536,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -77102,14 +77201,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 lng: -122.026913 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 109 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330175 @@ -77772,14 +77872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330175 lng: -122.026884 horizontal_accuracy: 0 course_over_ground: - degrees: 109 - accuracy: ~ + degrees: 124 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330163 @@ -78440,14 +78541,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330163 lng: -122.026862 horizontal_accuracy: 0 course_over_ground: - degrees: 124 - accuracy: ~ + degrees: 58 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330173 @@ -79106,14 +79208,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330173 lng: -122.026842 horizontal_accuracy: 0 course_over_ground: - degrees: 58 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330175 @@ -79770,14 +79873,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330175 lng: -122.02673 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 88 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330177 @@ -80432,14 +80536,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330177 lng: -122.026648 horizontal_accuracy: 0 course_over_ground: - degrees: 88 - accuracy: ~ + degrees: 135 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330166 @@ -81092,14 +81197,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330166 lng: -122.026634 horizontal_accuracy: 0 course_over_ground: - degrees: 135 - accuracy: ~ + degrees: 52 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330176 @@ -81750,14 +81856,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330176 lng: -122.026618 horizontal_accuracy: 0 course_over_ground: - degrees: 52 - accuracy: ~ + degrees: 70 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330184 @@ -82406,14 +82513,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330184 lng: -122.02659 horizontal_accuracy: 0 course_over_ground: - degrees: 70 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330184 @@ -83060,6 +83168,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330184 @@ -83067,7 +83176,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330184 @@ -83712,14 +83821,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330184 lng: -122.026369 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -84362,14 +84472,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 lng: -122.026259 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -85010,6 +85121,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -85017,7 +85129,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -85656,6 +85768,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -85663,7 +85776,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -86300,6 +86413,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 @@ -86307,7 +86421,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330183 @@ -86942,14 +87056,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330183 lng: -122.025817 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330182 @@ -87582,14 +87697,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330182 lng: -122.025707 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330182 @@ -88220,6 +88336,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330182 @@ -88227,7 +88344,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330182 @@ -88856,6 +88973,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330182 @@ -88863,7 +88981,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330182 @@ -89490,6 +89608,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330182 @@ -89497,7 +89616,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330182 @@ -90122,6 +90241,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330182 @@ -90129,7 +90249,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330182 @@ -90752,14 +90872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330182 lng: -122.025154 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330181 @@ -91380,14 +91501,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330181 lng: -122.025044 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330181 @@ -92006,6 +92128,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330181 @@ -92013,7 +92136,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330181 @@ -92630,6 +92753,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330181 @@ -92637,7 +92761,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330181 @@ -93252,6 +93376,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330181 @@ -93259,7 +93384,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330181 @@ -93872,14 +93997,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330181 lng: -122.024602 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33018 @@ -94490,14 +94616,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33018 lng: -122.024492 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33018 @@ -95106,6 +95233,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33018 @@ -95113,7 +95241,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33018 @@ -95720,14 +95848,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33018 lng: -122.024271 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 112 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330167 @@ -96332,14 +96461,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330167 lng: -122.024231 horizontal_accuracy: 0 course_over_ground: - degrees: 112 - accuracy: ~ + degrees: 128 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330155 @@ -96942,14 +97072,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330155 lng: -122.024212 horizontal_accuracy: 0 course_over_ground: - degrees: 128 - accuracy: ~ + degrees: 43 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330171 @@ -97550,14 +97681,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330171 lng: -122.024193 horizontal_accuracy: 0 course_over_ground: - degrees: 43 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330171 @@ -98156,6 +98288,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330171 @@ -98163,7 +98296,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330171 @@ -98760,14 +98893,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330171 lng: -122.024008 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 114 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330163 @@ -99362,14 +99496,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330163 lng: -122.023985 horizontal_accuracy: 0 course_over_ground: - degrees: 114 - accuracy: ~ + degrees: 63 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330171 @@ -99962,14 +100097,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330171 lng: -122.023965 horizontal_accuracy: 0 course_over_ground: - degrees: 63 - accuracy: ~ + degrees: 66 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330179 @@ -100560,14 +100696,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330179 lng: -122.023943 horizontal_accuracy: 0 course_over_ground: - degrees: 66 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330179 @@ -101156,14 +101293,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330179 lng: -122.023843 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33018 @@ -101750,14 +101888,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33018 lng: -122.023742 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33018 @@ -102342,14 +102481,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33018 lng: -122.023642 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330181 @@ -102932,14 +103072,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330181 lng: -122.023541 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330181 @@ -103520,14 +103661,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330181 lng: -122.023441 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 102 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330173 @@ -104106,14 +104248,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330173 lng: -122.023393 horizontal_accuracy: 0 course_over_ground: - degrees: 102 - accuracy: ~ + degrees: 115 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330163 @@ -104690,14 +104833,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330163 lng: -122.023366 horizontal_accuracy: 0 course_over_ground: - degrees: 115 - accuracy: ~ + degrees: 21 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33018 @@ -105272,14 +105416,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33018 lng: -122.023358 horizontal_accuracy: 0 course_over_ground: - degrees: 21 - accuracy: ~ + degrees: 94 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330177 @@ -105852,6 +105997,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330177 @@ -105859,7 +106005,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 94 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330174 @@ -106430,14 +106576,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330174 lng: -122.023237 horizontal_accuracy: 0 course_over_ground: - degrees: 94 - accuracy: ~ + degrees: 93 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33017 @@ -107006,14 +107153,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33017 lng: -122.023144 horizontal_accuracy: 0 course_over_ground: - degrees: 93 - accuracy: ~ + degrees: 137 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330158 @@ -107580,14 +107728,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330158 lng: -122.02313 horizontal_accuracy: 0 course_over_ground: - degrees: 137 - accuracy: ~ + degrees: 61 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330175 @@ -108152,14 +108301,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330175 lng: -122.023092 horizontal_accuracy: 0 course_over_ground: - degrees: 61 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330177 @@ -108722,6 +108872,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330177 @@ -108729,7 +108880,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330178 @@ -109290,6 +109441,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330178 @@ -109297,7 +109449,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33018 @@ -109856,14 +110008,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33018 lng: -122.022766 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 94 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330177 @@ -110420,14 +110573,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330177 lng: -122.022709 horizontal_accuracy: 0 course_over_ground: - degrees: 94 - accuracy: ~ + degrees: 95 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330173 @@ -110982,14 +111136,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330173 lng: -122.022652 horizontal_accuracy: 0 course_over_ground: - degrees: 95 - accuracy: ~ + degrees: 104 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330157 @@ -111542,14 +111697,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330157 lng: -122.022571 horizontal_accuracy: 0 course_over_ground: - degrees: 104 - accuracy: ~ + degrees: 103 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330142 @@ -112100,14 +112256,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330142 lng: -122.022489 horizontal_accuracy: 0 course_over_ground: - degrees: 103 - accuracy: ~ + degrees: 104 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330126 @@ -112656,14 +112813,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330126 lng: -122.022408 horizontal_accuracy: 0 course_over_ground: - degrees: 104 - accuracy: ~ + degrees: 127 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330108 @@ -113210,14 +113368,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330108 lng: -122.022378 horizontal_accuracy: 0 course_over_ground: - degrees: 127 - accuracy: ~ + degrees: 49 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330119 @@ -113762,14 +113921,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330119 lng: -122.022362 horizontal_accuracy: 0 course_over_ground: - degrees: 49 - accuracy: ~ + degrees: 94 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330113 @@ -114312,14 +114472,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330113 lng: -122.022265 horizontal_accuracy: 0 course_over_ground: - degrees: 94 - accuracy: ~ + degrees: 95 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330105 @@ -114860,14 +115021,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330105 lng: -122.022154 horizontal_accuracy: 0 course_over_ground: - degrees: 95 - accuracy: ~ + degrees: 139 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330094 @@ -115406,14 +115568,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330094 lng: -122.022142 horizontal_accuracy: 0 course_over_ground: - degrees: 139 - accuracy: ~ + degrees: 63 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330108 @@ -115950,14 +116113,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330108 lng: -122.022108 horizontal_accuracy: 0 course_over_ground: - degrees: 63 - accuracy: ~ + degrees: 93 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330103 @@ -116492,6 +116656,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330103 @@ -116499,7 +116664,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 93 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330098 @@ -117032,6 +117197,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330098 @@ -117039,7 +117205,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 93 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330093 @@ -117570,6 +117736,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330093 @@ -117577,7 +117744,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 93 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330088 @@ -118106,6 +118273,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330088 @@ -118113,7 +118281,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 93 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330083 @@ -118640,6 +118808,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330083 @@ -118647,7 +118816,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 93 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330078 @@ -119172,6 +119341,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330078 @@ -119179,7 +119349,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 93 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330074 @@ -119702,6 +119872,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330074 @@ -119709,7 +119880,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 93 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330069 @@ -120230,6 +120401,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330069 @@ -120237,7 +120409,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 93 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330064 @@ -120756,6 +120928,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330064 @@ -120763,7 +120936,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 93 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330059 @@ -121280,14 +121453,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330059 lng: -122.02103 horizontal_accuracy: 0 course_over_ground: - degrees: 93 - accuracy: ~ + degrees: 94 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330055 @@ -121802,14 +121976,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330055 lng: -122.020958 horizontal_accuracy: 0 course_over_ground: - degrees: 94 - accuracy: ~ + degrees: 95 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.33005 @@ -122322,14 +122497,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.33005 lng: -122.020886 horizontal_accuracy: 0 course_over_ground: - degrees: 95 - accuracy: ~ + degrees: 100 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330035 @@ -122840,14 +123016,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330035 lng: -122.02078 horizontal_accuracy: 0 course_over_ground: - degrees: 100 - accuracy: ~ + degrees: 109 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330019 @@ -123356,14 +123533,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330019 lng: -122.020722 horizontal_accuracy: 0 course_over_ground: - degrees: 109 - accuracy: ~ + degrees: 110 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.330002 @@ -123870,14 +124048,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.330002 lng: -122.020664 horizontal_accuracy: 0 course_over_ground: - degrees: 110 - accuracy: ~ + degrees: 115 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329965 @@ -124382,6 +124561,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329965 @@ -124389,7 +124569,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 115 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329928 @@ -124892,14 +125072,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329928 lng: -122.020466 horizontal_accuracy: 0 course_over_ground: - degrees: 115 - accuracy: ~ + degrees: 109 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329909 @@ -125400,14 +125581,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329909 lng: -122.020396 horizontal_accuracy: 0 course_over_ground: - degrees: 109 - accuracy: ~ + degrees: 110 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329889 @@ -125906,14 +126088,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329889 lng: -122.020327 horizontal_accuracy: 0 course_over_ground: - degrees: 110 - accuracy: ~ + degrees: 106 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329868 @@ -126410,14 +126593,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329868 lng: -122.020233 horizontal_accuracy: 0 course_over_ground: - degrees: 106 - accuracy: ~ + degrees: 105 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329847 @@ -126912,14 +127096,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329847 lng: -122.020138 horizontal_accuracy: 0 course_over_ground: - degrees: 105 - accuracy: ~ + degrees: 106 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329825 @@ -127412,14 +127597,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329825 lng: -122.020044 horizontal_accuracy: 0 course_over_ground: - degrees: 106 - accuracy: ~ + degrees: 105 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329804 @@ -127910,14 +128096,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329804 lng: -122.019949 horizontal_accuracy: 0 course_over_ground: - degrees: 105 - accuracy: ~ + degrees: 106 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329783 @@ -128406,14 +128593,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329783 lng: -122.019855 horizontal_accuracy: 0 course_over_ground: - degrees: 106 - accuracy: ~ + degrees: 122 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329759 @@ -128900,14 +129088,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329759 lng: -122.019807 horizontal_accuracy: 0 course_over_ground: - degrees: 122 - accuracy: ~ + degrees: 160 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329728 @@ -129392,14 +129581,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329728 lng: -122.019793 horizontal_accuracy: 0 course_over_ground: - degrees: 160 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329639 @@ -129882,6 +130072,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329639 @@ -129889,7 +130080,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32955 @@ -130370,14 +130561,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32955 lng: -122.019791 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329461 @@ -130856,14 +131048,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329461 lng: -122.019791 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329371 @@ -131340,6 +131533,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329371 @@ -131347,7 +131541,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329282 @@ -131822,6 +132016,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329282 @@ -131829,7 +132024,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329193 @@ -132302,6 +132497,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329193 @@ -132309,7 +132505,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329104 @@ -132780,14 +132976,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329104 lng: -122.019787 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.329015 @@ -133256,14 +133453,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.329015 lng: -122.019787 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328926 @@ -133730,6 +133928,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328926 @@ -133737,7 +133936,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328837 @@ -134202,6 +134401,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328837 @@ -134209,7 +134409,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328747 @@ -134672,6 +134872,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328747 @@ -134679,7 +134880,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328658 @@ -135140,6 +135341,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328658 @@ -135147,7 +135349,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328569 @@ -135606,14 +135808,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328569 lng: -122.019782 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32848 @@ -136070,14 +136273,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32848 lng: -122.019782 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328391 @@ -136532,6 +136736,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328391 @@ -136539,7 +136744,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328302 @@ -136992,6 +137197,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328302 @@ -136999,7 +137205,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328213 @@ -137450,6 +137656,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328213 @@ -137457,7 +137664,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328123 @@ -137906,14 +138113,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328123 lng: -122.019778 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.328034 @@ -138360,14 +138568,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.328034 lng: -122.019778 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327945 @@ -138812,6 +139021,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327945 @@ -138819,7 +139029,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327856 @@ -139262,14 +139472,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327856 lng: -122.019776 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 161 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327815 @@ -139710,14 +139921,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327815 lng: -122.019758 horizontal_accuracy: 0 course_over_ground: - degrees: 161 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327768 @@ -140156,6 +140368,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327768 @@ -140163,7 +140376,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327681 @@ -140600,6 +140813,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327681 @@ -140607,7 +140821,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327594 @@ -141042,6 +141256,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327594 @@ -141049,7 +141264,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327507 @@ -141482,6 +141697,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327507 @@ -141489,7 +141705,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32742 @@ -141920,6 +142136,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32742 @@ -141927,7 +142144,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327333 @@ -142356,6 +142573,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327333 @@ -142363,7 +142581,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327246 @@ -142790,6 +143008,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327246 @@ -142797,7 +143016,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327158 @@ -143222,6 +143441,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327158 @@ -143229,7 +143449,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.327071 @@ -143652,6 +143872,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.327071 @@ -143659,7 +143880,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326984 @@ -144080,6 +144301,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326984 @@ -144087,7 +144309,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326897 @@ -144506,6 +144728,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326897 @@ -144513,7 +144736,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32681 @@ -144930,6 +145153,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32681 @@ -144937,7 +145161,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326723 @@ -145352,6 +145576,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326723 @@ -145359,7 +145584,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326656 @@ -145772,6 +145997,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326656 @@ -145779,7 +146005,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326589 @@ -146190,6 +146416,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326589 @@ -146197,7 +146424,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326521 @@ -146606,6 +146833,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326521 @@ -146613,7 +146841,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326453 @@ -147020,14 +147248,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326453 lng: -122.019735 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32637 @@ -147432,6 +147661,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32637 @@ -147439,7 +147669,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326286 @@ -147842,6 +148072,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326286 @@ -147849,7 +148080,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326203 @@ -148250,14 +148481,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326203 lng: -122.019735 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32612 @@ -148656,14 +148888,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32612 lng: -122.019734 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.326037 @@ -149060,6 +149293,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.326037 @@ -149067,7 +149301,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325954 @@ -149462,6 +149696,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325954 @@ -149469,7 +149704,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32587 @@ -149862,6 +150097,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32587 @@ -149869,7 +150105,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325787 @@ -150260,6 +150496,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325787 @@ -150267,7 +150504,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325702 @@ -150656,6 +150893,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325702 @@ -150663,7 +150901,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325617 @@ -151050,6 +151288,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325617 @@ -151057,7 +151296,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325532 @@ -151442,6 +151681,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325532 @@ -151449,7 +151689,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325448 @@ -151832,6 +152072,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325448 @@ -151839,7 +152080,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325363 @@ -152220,6 +152461,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325363 @@ -152227,7 +152469,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325278 @@ -152606,14 +152848,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325278 lng: -122.019734 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325193 @@ -152990,14 +153233,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325193 lng: -122.019733 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325108 @@ -153372,6 +153616,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325108 @@ -153379,7 +153624,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.325023 @@ -153752,6 +153997,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.325023 @@ -153759,7 +154005,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324938 @@ -154130,6 +154376,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324938 @@ -154137,7 +154384,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324854 @@ -154506,6 +154753,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324854 @@ -154513,7 +154761,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324769 @@ -154880,6 +155128,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324769 @@ -154887,7 +155136,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324684 @@ -155252,6 +155501,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324684 @@ -155259,7 +155509,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324599 @@ -155622,14 +155872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324599 lng: -122.019733 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 211 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324561 @@ -155990,14 +156241,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324561 lng: -122.019762 horizontal_accuracy: 0 course_over_ground: - degrees: 211 - accuracy: ~ + degrees: 139 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32455 @@ -156356,14 +156608,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32455 lng: -122.01975 horizontal_accuracy: 0 course_over_ground: - degrees: 139 - accuracy: ~ + degrees: 175 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324469 @@ -156720,14 +156973,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324469 lng: -122.019742 horizontal_accuracy: 0 course_over_ground: - degrees: 175 - accuracy: ~ + degrees: 177 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32439 @@ -157082,14 +157336,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32439 lng: -122.019736 horizontal_accuracy: 0 course_over_ground: - degrees: 177 - accuracy: ~ + degrees: 100 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324375 @@ -157442,14 +157697,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324375 lng: -122.019633 horizontal_accuracy: 0 course_over_ground: - degrees: 100 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324361 @@ -157800,14 +158056,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324361 lng: -122.019633 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 181 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324286 @@ -158156,14 +158413,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324286 lng: -122.019634 horizontal_accuracy: 0 course_over_ground: - degrees: 181 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324212 @@ -158510,14 +158768,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324212 lng: -122.019634 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 181 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324137 @@ -158862,14 +159121,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324137 lng: -122.019635 horizontal_accuracy: 0 course_over_ground: - degrees: 181 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.324075 @@ -159212,6 +159472,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.324075 @@ -159219,7 +159480,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323987 @@ -159560,14 +159821,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323987 lng: -122.019633 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323899 @@ -159906,14 +160168,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323899 lng: -122.019633 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323812 @@ -160250,6 +160513,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323812 @@ -160257,7 +160521,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323724 @@ -160592,14 +160856,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323724 lng: -122.019631 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323636 @@ -160932,14 +161197,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323636 lng: -122.019631 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323548 @@ -161270,14 +161536,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323548 lng: -122.01963 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323505 @@ -161606,14 +161873,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323505 lng: -122.01963 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323434 @@ -161940,6 +162208,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323434 @@ -161947,7 +162216,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323362 @@ -162272,6 +162541,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323362 @@ -162279,7 +162549,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323291 @@ -162602,6 +162872,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323291 @@ -162609,7 +162880,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323219 @@ -162930,14 +163201,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323219 lng: -122.019626 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 178 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323153 @@ -163256,6 +163528,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323153 @@ -163263,7 +163536,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 178 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323086 @@ -163580,6 +163853,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323086 @@ -163587,7 +163861,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 178 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -163902,14 +164176,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 lng: -122.019617 horizontal_accuracy: 0 course_over_ground: - degrees: 178 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -164222,6 +164497,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -164229,7 +164505,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -164540,6 +164816,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -164547,7 +164824,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -164856,6 +165133,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -164863,7 +165141,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -165170,6 +165448,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -165177,7 +165456,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -165482,6 +165761,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -165489,7 +165769,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -165792,6 +166072,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -165799,7 +166080,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -166100,6 +166381,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -166107,7 +166389,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -166406,6 +166688,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -166413,7 +166696,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -166710,6 +166993,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -166717,7 +167001,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -167012,6 +167296,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -167019,7 +167304,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -167312,6 +167597,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -167319,7 +167605,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -167610,6 +167896,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -167617,7 +167904,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -167906,6 +168193,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -167913,7 +168201,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -168200,6 +168488,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -168207,7 +168496,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -168492,6 +168781,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 @@ -168499,7 +168789,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -168782,14 +169072,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 lng: -122.018033 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323019 @@ -169070,14 +169361,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323019 lng: -122.017927 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323019 @@ -169356,6 +169648,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323019 @@ -169363,7 +169656,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323019 @@ -169640,6 +169933,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323019 @@ -169647,7 +169941,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323019 @@ -169922,6 +170216,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323019 @@ -169929,7 +170224,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323019 @@ -170202,6 +170497,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323019 @@ -170209,7 +170505,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323019 @@ -170480,6 +170776,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323019 @@ -170487,7 +170784,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323019 @@ -170756,6 +171053,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323019 @@ -170763,7 +171061,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323019 @@ -171030,14 +171328,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323019 lng: -122.017232 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323018 @@ -171302,14 +171601,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323018 lng: -122.017171 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323019 @@ -171572,6 +171872,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323019 @@ -171579,7 +171880,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -171840,14 +172141,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 lng: -122.016965 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32302 @@ -172106,14 +172408,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32302 lng: -122.016862 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323021 @@ -172370,6 +172673,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323021 @@ -172377,7 +172681,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323022 @@ -172632,6 +172936,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323022 @@ -172639,7 +172944,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323023 @@ -172892,6 +173197,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323023 @@ -172899,7 +173205,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323024 @@ -173150,6 +173456,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323024 @@ -173157,7 +173464,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323025 @@ -173406,6 +173713,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323025 @@ -173413,7 +173721,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323026 @@ -173660,14 +173968,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323026 lng: -122.016375 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323026 @@ -173912,14 +174221,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323026 lng: -122.016298 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323027 @@ -174162,14 +174472,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323027 lng: -122.016222 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323027 @@ -174410,14 +174721,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323027 lng: -122.016145 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323028 @@ -174656,14 +174968,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323028 lng: -122.016044 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323028 @@ -174900,14 +175213,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323028 lng: -122.015943 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323029 @@ -175142,14 +175456,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323029 lng: -122.015836 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323029 @@ -175382,14 +175697,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323029 lng: -122.015729 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32303 @@ -175620,6 +175936,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32303 @@ -175627,7 +175944,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323031 @@ -175856,14 +176173,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323031 lng: -122.015515 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323031 @@ -176090,14 +176408,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323031 lng: -122.015408 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323032 @@ -176322,14 +176641,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323032 lng: -122.015301 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323032 @@ -176552,14 +176872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323032 lng: -122.015194 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323033 @@ -176780,14 +177101,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323033 lng: -122.015087 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323033 @@ -177006,14 +177328,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323033 lng: -122.014975 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323034 @@ -177230,6 +177553,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323034 @@ -177237,7 +177561,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323035 @@ -177452,14 +177776,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323035 lng: -122.014763 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323035 @@ -177672,14 +177997,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323035 lng: -122.014657 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323036 @@ -177890,6 +178216,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323036 @@ -177897,7 +178224,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -178106,14 +178433,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 lng: -122.014466 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -178320,6 +178648,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -178327,7 +178656,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -178532,6 +178861,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -178539,7 +178869,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -178742,6 +179072,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -178749,7 +179080,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -178950,6 +179281,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -178957,7 +179289,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -179156,6 +179488,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -179163,7 +179496,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -179360,6 +179693,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -179367,7 +179701,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -179562,6 +179896,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -179569,7 +179904,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -179762,6 +180097,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -179769,7 +180105,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -179960,14 +180296,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 lng: -122.013738 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323038 @@ -180156,14 +180493,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323038 lng: -122.013639 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323038 @@ -180350,6 +180688,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323038 @@ -180357,7 +180696,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323038 @@ -180542,6 +180881,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323038 @@ -180549,7 +180889,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323038 @@ -180732,6 +181072,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323038 @@ -180739,7 +181080,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323038 @@ -180920,14 +181261,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323038 lng: -122.013237 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -181106,14 +181448,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 lng: -122.013134 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -181290,6 +181633,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -181297,7 +181641,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -181472,6 +181816,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -181479,7 +181824,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -181652,14 +181997,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 lng: -122.012827 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323036 @@ -181830,14 +182176,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323036 lng: -122.012724 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323036 @@ -182006,6 +182353,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323036 @@ -182013,7 +182361,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323036 @@ -182180,6 +182528,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323036 @@ -182187,7 +182536,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323036 @@ -182352,6 +182701,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323036 @@ -182359,7 +182709,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323036 @@ -182522,14 +182872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323036 lng: -122.012303 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -182690,14 +183041,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 lng: -122.012195 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -182856,6 +183208,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -182863,7 +183216,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -183020,6 +183373,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 @@ -183027,7 +183381,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323037 @@ -183182,14 +183536,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323037 lng: -122.011871 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323038 @@ -183342,14 +183697,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323038 lng: -122.011772 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323038 @@ -183500,14 +183856,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323038 lng: -122.011672 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323039 @@ -183656,6 +184013,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323039 @@ -183663,7 +184021,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32304 @@ -183810,6 +184168,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32304 @@ -183817,7 +184176,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 89 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323041 @@ -183962,14 +184321,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323041 lng: -122.011445 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323041 @@ -184112,14 +184472,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323041 lng: -122.011338 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323042 @@ -184260,14 +184621,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323042 lng: -122.01123 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323042 @@ -184406,6 +184768,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323042 @@ -184413,7 +184776,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323042 @@ -184550,14 +184913,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323042 lng: -122.011022 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 89 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323043 @@ -184692,14 +185056,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323043 lng: -122.010923 horizontal_accuracy: 0 course_over_ground: - degrees: 89 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323043 @@ -184832,6 +185197,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323043 @@ -184839,7 +185205,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 90 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323043 @@ -184970,14 +185336,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323043 lng: -122.010723 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 106 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323031 @@ -185106,14 +185473,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323031 lng: -122.010671 horizontal_accuracy: 0 course_over_ground: - degrees: 106 - accuracy: ~ + degrees: 115 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.323021 @@ -185240,14 +185608,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.323021 lng: -122.010644 horizontal_accuracy: 0 course_over_ground: - degrees: 115 - accuracy: ~ + degrees: 138 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322977 @@ -185372,6 +185741,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322977 @@ -185379,7 +185749,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 138 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322942 @@ -185502,14 +185872,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322942 lng: -122.010556 horizontal_accuracy: 0 course_over_ground: - degrees: 138 - accuracy: ~ + degrees: 139 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322906 @@ -185630,14 +186001,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322906 lng: -122.010517 horizontal_accuracy: 0 course_over_ground: - degrees: 139 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32286 @@ -185756,6 +186128,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32286 @@ -185763,7 +186136,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322813 @@ -185880,14 +186253,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322813 lng: -122.010515 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322803 @@ -186002,14 +186376,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322803 lng: -122.010515 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 178 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322782 @@ -186122,14 +186497,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322782 lng: -122.010514 horizontal_accuracy: 0 course_over_ground: - degrees: 178 - accuracy: ~ + degrees: 177 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322708 @@ -186240,14 +186616,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322708 lng: -122.010509 horizontal_accuracy: 0 course_over_ground: - degrees: 177 - accuracy: ~ + degrees: 178 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322633 @@ -186356,14 +186733,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322633 lng: -122.010505 horizontal_accuracy: 0 course_over_ground: - degrees: 178 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322563 @@ -186470,14 +186848,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322563 lng: -122.010504 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322493 @@ -186582,14 +186961,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322493 lng: -122.010504 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322404 @@ -186692,6 +187072,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322404 @@ -186699,7 +187080,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322341 @@ -186800,6 +187181,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322341 @@ -186807,7 +187189,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322267 @@ -186906,14 +187288,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322267 lng: -122.010501 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322192 @@ -187010,14 +187393,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322192 lng: -122.010501 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.322111 @@ -187112,6 +187496,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.322111 @@ -187119,7 +187504,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32204 @@ -187212,6 +187597,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32204 @@ -187219,7 +187605,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321968 @@ -187310,14 +187696,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321968 lng: -122.010495 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 181 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321905 @@ -187406,6 +187793,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321905 @@ -187413,7 +187801,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 181 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321842 @@ -187500,14 +187888,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321842 lng: -122.010498 horizontal_accuracy: 0 course_over_ground: - degrees: 181 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321765 @@ -187592,14 +187981,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321765 lng: -122.010498 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 181 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321688 @@ -187682,14 +188072,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321688 lng: -122.010499 horizontal_accuracy: 0 course_over_ground: - degrees: 181 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321611 @@ -187770,6 +188161,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321611 @@ -187777,7 +188169,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321529 @@ -187856,14 +188248,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321529 lng: -122.010499 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321447 @@ -187940,14 +188333,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321447 lng: -122.010498 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321365 @@ -188022,6 +188416,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321365 @@ -188029,7 +188424,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321301 @@ -188102,6 +188497,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321301 @@ -188109,7 +188505,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321238 @@ -188180,6 +188576,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321238 @@ -188187,7 +188584,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 180 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321174 @@ -188256,14 +188653,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321174 lng: -122.010498 horizontal_accuracy: 0 course_over_ground: - degrees: 180 - accuracy: ~ + degrees: 128 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32114 @@ -188330,14 +188728,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32114 lng: -122.010444 horizontal_accuracy: 0 course_over_ground: - degrees: 128 - accuracy: ~ + degrees: 178 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321097 @@ -188402,14 +188801,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321097 lng: -122.010442 horizontal_accuracy: 0 course_over_ground: - degrees: 178 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.321053 @@ -188472,6 +188872,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.321053 @@ -188479,7 +188880,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320979 @@ -188540,14 +188941,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320979 lng: -122.010439 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 182 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320896 @@ -188606,6 +189008,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320896 @@ -188613,7 +189016,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 182 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320812 @@ -188670,14 +189073,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320812 lng: -122.010447 horizontal_accuracy: 0 course_over_ground: - degrees: 182 - accuracy: ~ + degrees: 198 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320728 @@ -188732,14 +189136,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320728 lng: -122.010482 horizontal_accuracy: 0 course_over_ground: - degrees: 198 - accuracy: ~ + degrees: 178 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.32067 @@ -188792,6 +189197,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.32067 @@ -188799,7 +189205,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 178 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320612 @@ -188850,6 +189256,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320612 @@ -188857,7 +189264,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 178 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320532 @@ -188906,6 +189313,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320532 @@ -188913,7 +189321,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 178 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320453 @@ -188960,14 +189368,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320453 lng: -122.010472 horizontal_accuracy: 0 course_over_ground: - degrees: 178 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320373 @@ -189012,14 +189421,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320373 lng: -122.01047 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 178 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320294 @@ -189062,6 +189472,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320294 @@ -189069,7 +189480,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 178 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320214 @@ -189110,6 +189521,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320214 @@ -189117,7 +189529,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 178 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320135 @@ -189156,14 +189568,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320135 lng: -122.010461 horizontal_accuracy: 0 course_over_ground: - degrees: 178 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.320055 @@ -189200,14 +189613,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.320055 lng: -122.010459 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 178 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319999 @@ -189242,14 +189656,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319999 lng: -122.010457 horizontal_accuracy: 0 course_over_ground: - degrees: 178 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319942 @@ -189282,14 +189697,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319942 lng: -122.010456 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319942 @@ -189320,14 +189736,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319942 lng: -122.01038 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 91 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319941 @@ -189356,14 +189773,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319941 lng: -122.010305 horizontal_accuracy: 0 course_over_ground: - degrees: 91 - accuracy: ~ + degrees: 90 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319941 @@ -189390,14 +189808,15 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319941 lng: -122.010229 horizontal_accuracy: 0 course_over_ground: - degrees: 90 - accuracy: ~ + degrees: 179 + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319867 @@ -189422,6 +189841,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319867 @@ -189429,7 +189849,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319792 @@ -189452,6 +189872,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319792 @@ -189459,7 +189880,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319708 @@ -189480,6 +189901,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319708 @@ -189487,7 +189909,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319623 @@ -189506,6 +189928,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319623 @@ -189513,7 +189936,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319539 @@ -189530,6 +189953,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319539 @@ -189537,7 +189961,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319454 @@ -189552,6 +189976,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319454 @@ -189559,7 +189984,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.31937 @@ -189572,6 +189997,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.31937 @@ -189579,7 +190005,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319285 @@ -189590,6 +190016,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319285 @@ -189597,7 +190024,7 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319223 @@ -189606,6 +190033,7 @@ expression: states lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319223 @@ -189613,13 +190041,14 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.319162 lng: -122.010218 - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.319162 @@ -189627,18 +190056,20 @@ expression: states horizontal_accuracy: 0 course_over_ground: degrees: 179 - accuracy: ~ + accuracy: 5 speed: ~ remaining_locations: - lat: 37.3191 lng: -122.010217 + bias: None - current_location: coordinates: lat: 37.3191 lng: -122.010217 horizontal_accuracy: 0 course_over_ground: - degrees: 179 - accuracy: ~ + degrees: 180 + accuracy: 5 speed: ~ remaining_locations: [] + bias: None diff --git a/common/ferrostar/src/snapshots/ferrostar__simulation__tests__state_from_polyline.snap b/common/ferrostar/src/snapshots/ferrostar__simulation__tests__state_from_polyline.snap index 41bd94f3..66d39455 100644 --- a/common/ferrostar/src/snapshots/ferrostar__simulation__tests__state_from_polyline.snap +++ b/common/ferrostar/src/snapshots/ferrostar__simulation__tests__state_from_polyline.snap @@ -1,5 +1,6 @@ --- source: ferrostar/src/simulation.rs +assertion_line: 417 expression: state --- current_location: @@ -8,8 +9,8 @@ current_location: lng: -149.543469 horizontal_accuracy: 0 course_over_ground: - degrees: 0 - accuracy: ~ + degrees: 288 + accuracy: 5 speed: ~ remaining_locations: - lat: 60.534782 @@ -30,3 +31,4 @@ remaining_locations: lng: -149.546937 - lat: 60.534991 lng: -149.548581 +bias: None diff --git a/common/uniffi-bindgen-swift/Cargo.toml b/common/uniffi-bindgen-swift/Cargo.toml new file mode 100644 index 00000000..9e4ac3a9 --- /dev/null +++ b/common/uniffi-bindgen-swift/Cargo.toml @@ -0,0 +1,18 @@ +lints.workspace = true + +[package] +name = "uniffi-bindgen-swift" +version = "0.1.0" +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +rust-version.workspace = true +publish = false + +[dependencies] +uniffi = { workspace = true, features = ["cli"] } + +[[bin]] +name = "uniffi-bindgen" +path = "src/main.rs" diff --git a/common/uniffi-bindgen-swift/src/main.rs b/common/uniffi-bindgen-swift/src/main.rs new file mode 100644 index 00000000..b1b0d730 --- /dev/null +++ b/common/uniffi-bindgen-swift/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + uniffi::uniffi_bindgen_swift(); +} diff --git a/guide/src/android-getting-started.md b/guide/src/android-getting-started.md index 336376bf..b53b5222 100644 --- a/guide/src/android-getting-started.md +++ b/guide/src/android-getting-started.md @@ -226,13 +226,16 @@ such as using a Valhalla [Route Provider](./route-providers.md#bundled-support). ## Set up voice guidance -Ferrostar is able to process spoken instructions generated from some routing engines. -The `com.stadiamaps.ferrostar.core.SpokenInstructionObserver` interface -specifies how to create your own observer. -A reference implementation is provided in the `AndroidTtsObserver` class, +If your routes include spoken instructions, +Ferrostar can trigger the speech synthesis at the right time. +Ferrostar includes the `AndroidTtsObserver` class, which uses the text-to-speech engine built into Android. -PRs welcome for other popular services (ex: Amazon Polly; -note that some APIs also provide SSML instructions which work great with this!). + +You can also use your own implementation, +such as a local AI model or cloud service like Amazon Polly. +The `com.stadiamaps.ferrostar.core.SpokenInstructionObserver` interface +specifies the required API. +PRs welcome to add other publicly accessible speech API implementations. **TODO documentation:** @@ -340,4 +343,4 @@ We've put together a minimal [demo app](https://github.com/stadiamaps/ferrostar/ This covers the basic “batteries included” configuration and pre-built UI. But there’s a lot of room for customization! -Skip on over to the customization chapters that interest you. \ No newline at end of file +Skip on over to the customization chapters that interest you. diff --git a/guide/src/ios-getting-started.md b/guide/src/ios-getting-started.md index dedd8069..8f74a15a 100644 --- a/guide/src/ios-getting-started.md +++ b/guide/src/ios-getting-started.md @@ -99,6 +99,60 @@ For limited testing, FOSSGIS maintains a public server with the URL `https://val For production use, you’ll need another solution like a [commercial vendor](./vendors.md) or self-hosting. +### Set up Voice Guidance + +If your routes include spoken instructions, +Ferrostar can trigger the speech synthesis at the right time. +Ferrostar includes the `SpokenInstructionObserver` class, +which can use `AVSpeechSynthesizer` or your own speech synthesis. + +The `SpeechSynthesizer` protocol +specifies the required interface, +and you can build your own implementation on this, +such as a local AI model or cloud service like Amazon Polly. +PRs welcome to add other publicly accessible speech API implementations. + +Your navigation view can store the spoken instruction observer as an instance variable: + +```swift +@State private var spokenInstructionObserver = SpokenInstructionObserver.initAVSpeechSynthesizer() +``` + +Then, you'll need to configure `FerrostarCore` to use it. + +```swift +ferrostarCore.spokenInstructionObserver = spokenInstructionObserver +``` + +Finally, you can use this to drive state on navigation view. +`DynamicallyOrientingNavigationView` has constructor arguments to configure the mute button UI. +See the demo app for an example. + +### Configure annotation parsing + +`FerrostarCore` includes support for parsing arbitrary annotations +from the route. +This technique is a de facto standard from OSRM, +and has been adopted by a wide range of open-source and proprietary solutions. +The routing APIs from Stadia Maps, Mapbox, and others +use this to include detailed information like speed limits, +expected travel speed, and more. + +Ferrostar includes a Valhalla extended OSRM annotation parser, +which works with Valhalla-powered APIs including Stadia Maps. +The implementation is completely generic, +so you can define your own model to include custom parameters. +PRs welcome for other public API annotation models. + +To set up annotation parsing, +simply pass the optional `annotation:` parameter +to the `FerrostarCore` constructor. +You can create a Valhalla extended OSRM annotation publisher like so: + +```swift +AnnotationPublisher.valhallaExtendedOSRM() +``` + ## Getting a route Before getting routes, you’ll need the user’s current location. @@ -178,4 +232,4 @@ We've put together a minimal [demo app](https://github.com/stadiamaps/ferrostar/ This covers the basic “batteries included” configuration and pre-built UI. But there’s a lot of room for customization! -Skip on over to the customization chapters that interest you. \ No newline at end of file +Skip on over to the customization chapters that interest you. diff --git a/web/package-lock.json b/web/package-lock.json index 8281fbf2..31670a54 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "@stadiamaps/ferrostar-webcomponents", - "version": "0.20.0", + "version": "0.20.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@stadiamaps/ferrostar-webcomponents", - "version": "0.20.0", + "version": "0.20.1", "license": "BSD-3-Clause", "dependencies": { "@stadiamaps/ferrostar": "file:../common/ferrostar/pkg", diff --git a/web/package.json b/web/package.json index c0b1b855..dd695c87 100644 --- a/web/package.json +++ b/web/package.json @@ -6,7 +6,7 @@ "CatMe0w (https://github.com/CatMe0w)", "Luke Seelenbinder " ], - "version": "0.20.0", + "version": "0.20.1", "license": "BSD-3-Clause", "type": "module", "main": "./dist/ferrostar-webcomponents.js", diff --git a/web/src/location.ts b/web/src/location.ts index b54bf9a1..d462fdfa 100644 --- a/web/src/location.ts +++ b/web/src/location.ts @@ -42,7 +42,7 @@ export class SimulatedLocationProvider { updateCallback: () => void = () => {}; setSimulatedRoute(route: any) { - this.simulationState = locationSimulationFromRoute(route, 10.0); + this.simulationState = locationSimulationFromRoute(route, 10.0, "None"); this.lastLocation = this.simulationState?.current_location; this.start(); }