-
Notifications
You must be signed in to change notification settings - Fork 318
/
FasterRouteController.kt
100 lines (88 loc) · 3.89 KB
/
FasterRouteController.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package com.mapbox.navigation.core.fasterroute
import com.mapbox.api.directions.v5.models.DirectionsRoute
import com.mapbox.api.directions.v5.models.RouteOptions
import com.mapbox.base.common.logger.Logger
import com.mapbox.base.common.logger.model.Message
import com.mapbox.navigation.core.directions.session.DirectionsSession
import com.mapbox.navigation.core.directions.session.RoutesRequestCallback
import com.mapbox.navigation.core.routeoptions.RouteOptionsProvider
import com.mapbox.navigation.core.trip.session.TripSession
import com.mapbox.navigation.utils.internal.MapboxTimer
import com.mapbox.navigation.utils.internal.ThreadController
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.launch
internal class FasterRouteController(
private val directionsSession: DirectionsSession,
private val tripSession: TripSession,
private val routeOptionsProvider: RouteOptionsProvider,
private val fasterRouteDetector: FasterRouteDetector,
private val logger: Logger
) {
private val jobControl = ThreadController.getMainScopeAndRootJob()
private val fasterRouteTimer = MapboxTimer()
private var fasterRouteObserver: FasterRouteObserver? = null
fun attach(fasterRouteObserver: FasterRouteObserver) {
val previousFasterRouteObserver = this.fasterRouteObserver
this.fasterRouteObserver = fasterRouteObserver
if (previousFasterRouteObserver == null) {
val restartAfterMillis = fasterRouteObserver.restartAfterMillis()
check(TimeUnit.MILLISECONDS.toMinutes(restartAfterMillis) >= 2) {
"Faster route should be >= 2 minutes, $restartAfterMillis is out of range"
}
fasterRouteTimer.restartAfterMillis = restartAfterMillis
fasterRouteTimer.startTimer {
requestFasterRoute()
}
}
}
fun stop() {
this.fasterRouteObserver = null
fasterRouteTimer.stopJobs()
jobControl.job.cancelChildren()
}
private fun requestFasterRoute() {
val restartAfterMillis = fasterRouteObserver?.restartAfterMillis()
?: return
if (directionsSession.routes.isEmpty()) {
return
}
fasterRouteTimer.restartAfterMillis = restartAfterMillis
routeOptionsProvider.update(
directionsSession.getRouteOptions(),
tripSession.getRouteProgress(),
tripSession.getEnhancedLocation()
)
.let { routeOptionsResult ->
when (routeOptionsResult) {
is RouteOptionsProvider.RouteOptionsResult.Success ->
directionsSession.requestFasterRoute(
routeOptionsResult.routeOptions,
fasterRouteRequestCallback
)
is RouteOptionsProvider.RouteOptionsResult.Error -> Unit
}
}
}
private val fasterRouteRequestCallback = object : RoutesRequestCallback {
override fun onRoutesReady(routes: List<DirectionsRoute>) {
val currentRoute = directionsSession.routes.firstOrNull()
?: return
val routeProgress = tripSession.getRouteProgress()
?: return
jobControl.scope.launch {
val isAlternativeFaster = fasterRouteDetector.isRouteFaster(routes[0], routeProgress)
fasterRouteObserver?.onFasterRoute(currentRoute, routes, isAlternativeFaster)
}
}
override fun onRoutesRequestFailure(throwable: Throwable, routeOptions: RouteOptions) {
logger.i(
msg = Message("Faster route request failed"),
tr = throwable
)
}
override fun onRoutesRequestCanceled(routeOptions: RouteOptions) {
logger.i(msg = Message("Faster route request canceled"))
}
}
}