Restaurants
This commit is contained in:
@@ -17,8 +17,8 @@ android {
|
|||||||
applicationId = "com.kouros.navigation"
|
applicationId = "com.kouros.navigation"
|
||||||
minSdk = 33
|
minSdk = 33
|
||||||
targetSdk = 37
|
targetSdk = 37
|
||||||
versionCode = 107
|
versionCode = 108
|
||||||
versionName = "0.3.0.107"
|
versionName = "0.3.0.108"
|
||||||
base.archivesName = "navi-$versionName"
|
base.archivesName = "navi-$versionName"
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -755,7 +755,11 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
|||||||
val duration = Duration.between(current, lastTrafficDate)
|
val duration = Duration.between(current, lastTrafficDate)
|
||||||
if (showTraffic && duration.abs().seconds > TRAFFIC_UPDATE) {
|
if (showTraffic && duration.abs().seconds > TRAFFIC_UPDATE) {
|
||||||
lastTrafficDate = current
|
lastTrafficDate = current
|
||||||
navigationViewModel.loadTraffic(carContext, location, surfaceRenderer.carOrientation)
|
navigationViewModel.loadTraffic(
|
||||||
|
carContext,
|
||||||
|
location,
|
||||||
|
surfaceRenderer.carOrientation
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,20 @@ import androidx.compose.ui.unit.Dp
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.kouros.data.R
|
import com.kouros.data.R
|
||||||
|
import com.kouros.navigation.data.ClosedColor
|
||||||
import com.kouros.navigation.data.Constants
|
import com.kouros.navigation.data.Constants
|
||||||
import com.kouros.navigation.data.Constants.homeVogelhart
|
import com.kouros.navigation.data.Constants.homeVogelhart
|
||||||
|
import com.kouros.navigation.data.HeavyColor
|
||||||
|
import com.kouros.navigation.data.LaneColor
|
||||||
import com.kouros.navigation.data.NavigationColorDark
|
import com.kouros.navigation.data.NavigationColorDark
|
||||||
import com.kouros.navigation.data.NavigationColorLight
|
import com.kouros.navigation.data.NavigationColorLight
|
||||||
|
import com.kouros.navigation.data.PharmacyColor
|
||||||
|
import com.kouros.navigation.data.QueuingColor
|
||||||
|
import com.kouros.navigation.data.RoadworksColor
|
||||||
import com.kouros.navigation.data.RouteColor
|
import com.kouros.navigation.data.RouteColor
|
||||||
|
import com.kouros.navigation.data.SlowColor
|
||||||
import com.kouros.navigation.data.SpeedColor
|
import com.kouros.navigation.data.SpeedColor
|
||||||
|
import com.kouros.navigation.data.StationaryColor
|
||||||
import com.kouros.navigation.data.ViewStyle
|
import com.kouros.navigation.data.ViewStyle
|
||||||
import com.kouros.navigation.utils.GeoUtils.createEndCollection
|
import com.kouros.navigation.utils.GeoUtils.createEndCollection
|
||||||
import com.kouros.navigation.utils.GeoUtils.createPointCollection
|
import com.kouros.navigation.utils.GeoUtils.createPointCollection
|
||||||
@@ -180,6 +188,12 @@ fun RouteLayer(routeData: String?) {
|
|||||||
fun TrafficLayer(trafficData: Map<String, String>) {
|
fun TrafficLayer(trafficData: Map<String, String>) {
|
||||||
trafficData.forEach {
|
trafficData.forEach {
|
||||||
val traffic = rememberGeoJsonSource(GeoJsonData.JsonString(it.value))
|
val traffic = rememberGeoJsonSource(GeoJsonData.JsonString(it.value))
|
||||||
|
LineLayer(
|
||||||
|
id = "traffic-${it.key}-casing",
|
||||||
|
source = traffic,
|
||||||
|
color = const(Color.White),
|
||||||
|
width = routeLineWidth(base = 2.dp, isCasing = true),
|
||||||
|
)
|
||||||
LineLayer(
|
LineLayer(
|
||||||
id = "traffic-${it.key}",
|
id = "traffic-${it.key}",
|
||||||
source = traffic,
|
source = traffic,
|
||||||
@@ -289,13 +303,13 @@ fun trafficImage(key: String): Expression<ImageValue> {
|
|||||||
|
|
||||||
fun trafficColor(key: String): Expression<ColorValue> {
|
fun trafficColor(key: String): Expression<ColorValue> {
|
||||||
when (key) {
|
when (key) {
|
||||||
"queuing" -> return const(Color(0xFFC46E53))
|
"queuing" -> return const(QueuingColor)
|
||||||
"slow" -> return const(Color(0xFFC43E3E))
|
"slow" -> return const(SlowColor)
|
||||||
"stationary" -> return const(Color(0xFF910A0A))
|
"stationary" -> return const(StationaryColor)
|
||||||
"heavy" -> return const(Color(0xFF6B0404))
|
"heavy" -> return const(HeavyColor)
|
||||||
"roadworks" -> return const(Color(0xFFDAA707))
|
"roadworks" -> return const(RoadworksColor)
|
||||||
"closed" -> return const(Color(0xFF210C0F))
|
"closed" -> return const(ClosedColor)
|
||||||
"lane" -> return const(Color(0xFFEFBAC1))
|
"lane" -> return const(LaneColor)
|
||||||
}
|
}
|
||||||
return const(Color.Blue)
|
return const(Color.Blue)
|
||||||
}
|
}
|
||||||
@@ -306,11 +320,14 @@ fun AmenityLayer(routeData: String?) {
|
|||||||
var color = const(Color.Red)
|
var color = const(Color.Red)
|
||||||
var img = image(painterResource(R.drawable.local_pharmacy_24px), drawAsSdf = true)
|
var img = image(painterResource(R.drawable.local_pharmacy_24px), drawAsSdf = true)
|
||||||
if (routeData.contains(Constants.CHARGING_STATION)) {
|
if (routeData.contains(Constants.CHARGING_STATION)) {
|
||||||
color = const(Color(0xFF054603))
|
color = const(PharmacyColor)
|
||||||
img = image(painterResource(R.drawable.ev_station_24px), drawAsSdf = true)
|
img = image(painterResource(R.drawable.ev_station_24px), drawAsSdf = true)
|
||||||
} else if (routeData.contains(Constants.FUEL_STATION)) {
|
} else if (routeData.contains(Constants.FUEL_STATION)) {
|
||||||
color = const(Color.Blue)
|
color = const(Color.Blue)
|
||||||
img = image(painterResource(R.drawable.local_gas_station_24), drawAsSdf = true)
|
img = image(painterResource(R.drawable.local_gas_station_24), drawAsSdf = true)
|
||||||
|
} else if (routeData.contains(Constants.RESTAURANT)) {
|
||||||
|
color = const(Color.Magenta)
|
||||||
|
img = image(painterResource(R.drawable.restaurant_24px), drawAsSdf = true)
|
||||||
}
|
}
|
||||||
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
||||||
SymbolLayer(
|
SymbolLayer(
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import androidx.car.app.CarContext
|
|||||||
import androidx.car.app.Screen
|
import androidx.car.app.Screen
|
||||||
import androidx.car.app.model.Action
|
import androidx.car.app.model.Action
|
||||||
import androidx.car.app.model.CarIcon
|
import androidx.car.app.model.CarIcon
|
||||||
|
import androidx.car.app.model.GridItem
|
||||||
|
import androidx.car.app.model.GridTemplate
|
||||||
import androidx.car.app.model.Header
|
import androidx.car.app.model.Header
|
||||||
import androidx.car.app.model.ItemList
|
import androidx.car.app.model.ItemList
|
||||||
import androidx.car.app.model.ListTemplate
|
import androidx.car.app.model.ListTemplate
|
||||||
@@ -16,6 +18,7 @@ import com.kouros.navigation.data.Category
|
|||||||
import com.kouros.navigation.data.Constants.CHARGING_STATION
|
import com.kouros.navigation.data.Constants.CHARGING_STATION
|
||||||
import com.kouros.navigation.data.Constants.FUEL_STATION
|
import com.kouros.navigation.data.Constants.FUEL_STATION
|
||||||
import com.kouros.navigation.data.Constants.PHARMACY
|
import com.kouros.navigation.data.Constants.PHARMACY
|
||||||
|
import com.kouros.navigation.data.Constants.RESTAURANT
|
||||||
import com.kouros.navigation.data.ViewStyle
|
import com.kouros.navigation.data.ViewStyle
|
||||||
import com.kouros.navigation.model.NavigationViewModel
|
import com.kouros.navigation.model.NavigationViewModel
|
||||||
|
|
||||||
@@ -30,22 +33,18 @@ class CategoriesScreen(
|
|||||||
var categories: List<Category> = listOf(
|
var categories: List<Category> = listOf(
|
||||||
Category(id = FUEL_STATION, name = carContext.getString(R.string.fuel_station)),
|
Category(id = FUEL_STATION, name = carContext.getString(R.string.fuel_station)),
|
||||||
Category(id = PHARMACY, name = carContext.getString(R.string.pharmacy)),
|
Category(id = PHARMACY, name = carContext.getString(R.string.pharmacy)),
|
||||||
Category(id = CHARGING_STATION, name = carContext.getString(R.string.charging_station))
|
Category(id = CHARGING_STATION, name = carContext.getString(R.string.charging_station)),
|
||||||
|
Category(id = RESTAURANT, name = carContext.getString(R.string.restaurant))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
init {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onGetTemplate(): Template {
|
override fun onGetTemplate(): Template {
|
||||||
val itemListBuilder = ItemList.Builder()
|
val itemListBuilder = ItemList.Builder()
|
||||||
.setNoItemsMessage("No categories to show")
|
.setNoItemsMessage("No categories to show")
|
||||||
categories.forEach {
|
categories.forEach {
|
||||||
itemListBuilder.addItem(
|
itemListBuilder.addItem(
|
||||||
Row.Builder()
|
GridItem.Builder()
|
||||||
.setTitle(it.name)
|
|
||||||
.setImage(carIcon(carContext, it.id, -1))
|
.setImage(carIcon(carContext, it.id, -1))
|
||||||
|
.setTitle(it.name)
|
||||||
.setOnClickListener {
|
.setOnClickListener {
|
||||||
category = it.id
|
category = it.id
|
||||||
screenManager
|
screenManager
|
||||||
@@ -55,7 +54,7 @@ class CategoriesScreen(
|
|||||||
surfaceRenderer,
|
surfaceRenderer,
|
||||||
category,
|
category,
|
||||||
navigationViewModel,
|
navigationViewModel,
|
||||||
)
|
)
|
||||||
) { obj: Any? ->
|
) { obj: Any? ->
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
setResult(obj)
|
setResult(obj)
|
||||||
@@ -63,20 +62,19 @@ class CategoriesScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setBrowsable(true)
|
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
surfaceRenderer.viewStyle = ViewStyle.AMENITY_VIEW
|
surfaceRenderer.viewStyle = ViewStyle.AMENITY_VIEW
|
||||||
|
|
||||||
val header = Header.Builder()
|
return GridTemplate.Builder()
|
||||||
.setStartHeaderAction(Action.BACK)
|
.setHeader(
|
||||||
.setTitle(carContext.getString(R.string.category_title))
|
Header.Builder()
|
||||||
.build()
|
.setStartHeaderAction(Action.BACK)
|
||||||
|
.setTitle(carContext.getString(R.string.category_title))
|
||||||
return ListTemplate.Builder()
|
.build()
|
||||||
.setHeader(header)
|
)
|
||||||
.setSingleList(itemListBuilder.build())
|
.setSingleList(itemListBuilder.build())
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
@@ -88,7 +86,7 @@ fun carIcon(context: CarContext, category: String, index: Int): CarIcon {
|
|||||||
CHARGING_STATION -> R.drawable.ev_station_24px
|
CHARGING_STATION -> R.drawable.ev_station_24px
|
||||||
FUEL_STATION -> R.drawable.local_gas_station_24
|
FUEL_STATION -> R.drawable.local_gas_station_24
|
||||||
PHARMACY -> R.drawable.local_pharmacy_24px
|
PHARMACY -> R.drawable.local_pharmacy_24px
|
||||||
else -> R.drawable.ic_place_white_24dp
|
else -> R.drawable.restaurant_24px
|
||||||
}
|
}
|
||||||
return CarIcon.Builder(IconCompat.createWithResource(context, resId)).build()
|
return CarIcon.Builder(IconCompat.createWithResource(context, resId)).build()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import com.kouros.navigation.data.Constants
|
|||||||
import com.kouros.navigation.data.Constants.CHARGING_STATION
|
import com.kouros.navigation.data.Constants.CHARGING_STATION
|
||||||
import com.kouros.navigation.data.Constants.FUEL_STATION
|
import com.kouros.navigation.data.Constants.FUEL_STATION
|
||||||
import com.kouros.navigation.data.Constants.PHARMACY
|
import com.kouros.navigation.data.Constants.PHARMACY
|
||||||
|
import com.kouros.navigation.data.Constants.RESTAURANT
|
||||||
import com.kouros.navigation.data.Constants.TAG
|
import com.kouros.navigation.data.Constants.TAG
|
||||||
import com.kouros.navigation.data.Place
|
import com.kouros.navigation.data.Place
|
||||||
import com.kouros.navigation.data.overpass.Elements
|
import com.kouros.navigation.data.overpass.Elements
|
||||||
@@ -52,7 +53,6 @@ class CategoryScreen(
|
|||||||
|
|
||||||
) : Screen(carContext), CategoryObserverCallback {
|
) : Screen(carContext), CategoryObserverCallback {
|
||||||
|
|
||||||
|
|
||||||
val repository = getSettingsRepository(carContext)
|
val repository = getSettingsRepository(carContext)
|
||||||
|
|
||||||
val settingsViewModel = getSettingsViewModel(carContext)
|
val settingsViewModel = getSettingsViewModel(carContext)
|
||||||
@@ -77,7 +77,6 @@ class CategoryScreen(
|
|||||||
})
|
})
|
||||||
|
|
||||||
navigationViewModel.elements.observe(this, categoryObserver)
|
navigationViewModel.elements.observe(this, categoryObserver)
|
||||||
//navigationViewModel.getAmenities(carContext, category, surfaceRenderer.lastLocation)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onGetTemplate(): Template {
|
override fun onGetTemplate(): Template {
|
||||||
@@ -94,12 +93,10 @@ class CategoryScreen(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
elements.forEach {
|
elements.forEach {
|
||||||
if (it.tags.operator != null) {
|
if (index++ < listLimit) {
|
||||||
if (index++ < listLimit) {
|
listBuilder.addItem(
|
||||||
listBuilder.addItem(
|
createItem(it, category, index)
|
||||||
createItem(it, category, index)
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,7 +130,7 @@ class CategoryScreen(
|
|||||||
CHARGING_STATION -> R.string.charging_station
|
CHARGING_STATION -> R.string.charging_station
|
||||||
FUEL_STATION -> R.string.fuel_station
|
FUEL_STATION -> R.string.fuel_station
|
||||||
PHARMACY -> R.string.pharmacy
|
PHARMACY -> R.string.pharmacy
|
||||||
else -> R.string.no_places
|
else -> R.string.restaurant
|
||||||
}
|
}
|
||||||
return carContext.getString(resId)
|
return carContext.getString(resId)
|
||||||
}
|
}
|
||||||
@@ -154,10 +151,10 @@ class CategoryScreen(
|
|||||||
}
|
}
|
||||||
.setTitle(name)
|
.setTitle(name)
|
||||||
.setImage(carIcon(carContext, category, index))
|
.setImage(carIcon(carContext, category, index))
|
||||||
if (category == CHARGING_STATION) {
|
when (category) {
|
||||||
row.addText("${it.tags.socketType2} X Typ 2 ${it.tags.socketType2Output}")
|
CHARGING_STATION -> row.addText("${it.tags.socketType2} X Typ 2 ${it.tags.socketType2Output}")
|
||||||
} else {
|
FUEL_STATION -> row.addText(carText("${it.e5} / ${it.e10} € ${it.tags.openingHours}"))
|
||||||
row.addText(carText(" ${it.e5} / ${it.e10} € ${it.tags.openingHours}"))
|
RESTAURANT, PHARMACY ->row.addText(carText(it.tags.openingHours))
|
||||||
}
|
}
|
||||||
if (it.distance < 1000) {
|
if (it.distance < 1000) {
|
||||||
row.addText("${(it.distance).toInt()} m")
|
row.addText("${(it.distance).toInt()} m")
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.kouros.navigation.car.screen
|
|||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
import android.util.Log
|
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.car.app.CarContext
|
import androidx.car.app.CarContext
|
||||||
import androidx.car.app.CarToast
|
import androidx.car.app.CarToast
|
||||||
@@ -13,7 +12,6 @@ import androidx.car.app.model.Action
|
|||||||
import androidx.car.app.model.Action.FLAG_DEFAULT
|
import androidx.car.app.model.Action.FLAG_DEFAULT
|
||||||
import androidx.car.app.model.Action.FLAG_IS_PERSISTENT
|
import androidx.car.app.model.Action.FLAG_IS_PERSISTENT
|
||||||
import androidx.car.app.model.CarColor
|
import androidx.car.app.model.CarColor
|
||||||
import androidx.car.app.model.CarIcon
|
|
||||||
import androidx.car.app.model.CarText
|
import androidx.car.app.model.CarText
|
||||||
import androidx.car.app.model.DurationSpan
|
import androidx.car.app.model.DurationSpan
|
||||||
import androidx.car.app.model.ForegroundCarColorSpan
|
import androidx.car.app.model.ForegroundCarColorSpan
|
||||||
@@ -26,7 +24,6 @@ import androidx.car.app.model.Template
|
|||||||
import androidx.car.app.navigation.model.MapController
|
import androidx.car.app.navigation.model.MapController
|
||||||
import androidx.car.app.navigation.model.MapWithContentTemplate
|
import androidx.car.app.navigation.model.MapWithContentTemplate
|
||||||
import androidx.car.app.versioning.CarAppApiLevels
|
import androidx.car.app.versioning.CarAppApiLevels
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
@@ -35,7 +32,6 @@ import androidx.lifecycle.lifecycleScope
|
|||||||
import com.kouros.data.R
|
import com.kouros.data.R
|
||||||
import com.kouros.navigation.car.SurfaceRenderer
|
import com.kouros.navigation.car.SurfaceRenderer
|
||||||
import com.kouros.navigation.car.navigation.RouteCarModel
|
import com.kouros.navigation.car.navigation.RouteCarModel
|
||||||
import com.kouros.navigation.data.Constants.TAG
|
|
||||||
import com.kouros.navigation.data.Place
|
import com.kouros.navigation.data.Place
|
||||||
import com.kouros.navigation.data.ViewStyle
|
import com.kouros.navigation.data.ViewStyle
|
||||||
import com.kouros.navigation.data.route.Routes
|
import com.kouros.navigation.data.route.Routes
|
||||||
@@ -377,7 +373,6 @@ class RoutePreviewScreen(
|
|||||||
surfaceRenderer.carOrientation
|
surfaceRenderer.carOrientation
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class RoutePreviewType {
|
enum class RoutePreviewType {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ fun createNumberIcon(category: String, number: String): IconCompat {
|
|||||||
CHARGING_STATION -> Color.GREEN
|
CHARGING_STATION -> Color.GREEN
|
||||||
FUEL_STATION -> Color.BLUE
|
FUEL_STATION -> Color.BLUE
|
||||||
PHARMACY -> Color.RED
|
PHARMACY -> Color.RED
|
||||||
else -> Color.WHITE
|
else -> Color.MAGENTA
|
||||||
}
|
}
|
||||||
paint.color = color
|
paint.color = color
|
||||||
canvas.drawCircle(size / 2f, size / 2f, size / 2f, paint)
|
canvas.drawCircle(size / 2f, size / 2f, size / 2f, paint)
|
||||||
|
|||||||
@@ -11,4 +11,14 @@ val SpeedColor = Color(0xFF262525)
|
|||||||
|
|
||||||
val MaxSpeedColor = Color(0xFFB71515)
|
val MaxSpeedColor = Color(0xFFB71515)
|
||||||
|
|
||||||
val PlaceColor = Color(0xFF868005)
|
val PlaceColor = Color(0xFF868005)
|
||||||
|
|
||||||
|
val QueuingColor = Color(0xFFC46E53)
|
||||||
|
val SlowColor = Color(0xFFC43E3E)
|
||||||
|
val StationaryColor = Color(0xFF910A0A)
|
||||||
|
val HeavyColor = Color(0xFF6B0404)
|
||||||
|
val RoadworksColor = Color(0xFFDAA707)
|
||||||
|
val ClosedColor = Color(0xFF280C10)
|
||||||
|
val LaneColor = Color(0xFFEFBAC1)
|
||||||
|
|
||||||
|
val PharmacyColor = Color(0xFF054603)
|
||||||
@@ -122,6 +122,8 @@ object Constants {
|
|||||||
|
|
||||||
const val CHARGING_STATION: String ="charging_station"
|
const val CHARGING_STATION: String ="charging_station"
|
||||||
|
|
||||||
|
const val RESTAURANT: String ="restaurant"
|
||||||
|
|
||||||
/** The initial location to use as an anchor for searches. */
|
/** The initial location to use as an anchor for searches. */
|
||||||
val homeVogelhart = location(11.5793748, 48.185749)
|
val homeVogelhart = location(11.5793748, 48.185749)
|
||||||
val homeHohenwaldeck = location( 11.594322, 48.1164817)
|
val homeHohenwaldeck = location( 11.594322, 48.1164817)
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ abstract class NavigationRepository {
|
|||||||
"Accept",
|
"Accept",
|
||||||
"application/json"
|
"application/json"
|
||||||
) // The format of response we want to get from the server
|
) // The format of response we want to get from the server
|
||||||
httpURLConnection.setRequestProperty("User-Agent", "email=nominatim@kouros-online.de")
|
httpURLConnection.setRequestProperty("User-Agent", "email=online@kouros-online.de")
|
||||||
httpURLConnection.requestMethod = "GET"
|
httpURLConnection.requestMethod = "GET"
|
||||||
val responseCode = httpURLConnection.responseCode
|
val responseCode = httpURLConnection.responseCode
|
||||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ class Overpass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.w("OverpassApi", searchQuery)
|
||||||
val responseCode = connection.responseCode
|
val responseCode = connection.responseCode
|
||||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
val response = connection.inputStream.bufferedReader().use { it.readText() }
|
val response = connection.inputStream.bufferedReader().use { it.readText() }
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ data class Tags(
|
|||||||
val capacity: String = "",
|
val capacity: String = "",
|
||||||
val motorcar: String = "",
|
val motorcar: String = "",
|
||||||
val network: String = "",
|
val network: String = "",
|
||||||
val openingHours: String = "",
|
@SerializedName("opening_hours") val openingHours: String = "",
|
||||||
val operator: String = "",
|
val operator: String = "",
|
||||||
val operatorShort: String = "",
|
val operatorShort: String = "",
|
||||||
val operatorWikidata: String = "",
|
val operatorWikidata: String = "",
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import com.kouros.navigation.data.NavigationRepository
|
|||||||
import com.kouros.navigation.data.Place
|
import com.kouros.navigation.data.Place
|
||||||
import com.kouros.navigation.data.Places
|
import com.kouros.navigation.data.Places
|
||||||
import com.kouros.navigation.data.SearchFilter
|
import com.kouros.navigation.data.SearchFilter
|
||||||
import com.kouros.navigation.data.fuel.FuelPrice
|
|
||||||
import com.kouros.navigation.data.fuel.FuelPrices
|
import com.kouros.navigation.data.fuel.FuelPrices
|
||||||
import com.kouros.navigation.data.fuel.Station
|
import com.kouros.navigation.data.fuel.Station
|
||||||
import com.kouros.navigation.data.fuel.Stations
|
import com.kouros.navigation.data.fuel.Stations
|
||||||
@@ -28,15 +27,14 @@ import com.kouros.navigation.data.nominatim.SearchResult
|
|||||||
import com.kouros.navigation.data.overpass.ElementSearch
|
import com.kouros.navigation.data.overpass.ElementSearch
|
||||||
import com.kouros.navigation.data.overpass.Elements
|
import com.kouros.navigation.data.overpass.Elements
|
||||||
import com.kouros.navigation.data.overpass.Overpass
|
import com.kouros.navigation.data.overpass.Overpass
|
||||||
|
import com.kouros.navigation.repository.SettingsRepository
|
||||||
import com.kouros.navigation.utils.GeoUtils.snapLocation
|
import com.kouros.navigation.utils.GeoUtils.snapLocation
|
||||||
import com.kouros.navigation.utils.GeoUtils.transferCoordinates
|
import com.kouros.navigation.utils.GeoUtils.transferCoordinates
|
||||||
import com.kouros.navigation.utils.bearingPositive
|
import com.kouros.navigation.utils.bearingPositive
|
||||||
import com.kouros.navigation.utils.countryCodeSpeedLimit
|
import com.kouros.navigation.utils.countryCodeSpeedLimit
|
||||||
import com.kouros.navigation.utils.getSettingsRepository
|
import com.kouros.navigation.utils.getSettingsRepository
|
||||||
import com.kouros.navigation.utils.getSettingsViewModel
|
|
||||||
import com.kouros.navigation.utils.isNumeric
|
import com.kouros.navigation.utils.isNumeric
|
||||||
import com.kouros.navigation.utils.location
|
import com.kouros.navigation.utils.location
|
||||||
import com.kouros.navigation.utils.settingsViewModel
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@@ -220,7 +218,11 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
|||||||
* Fetches traffic incident data and categorizes by severity.
|
* Fetches traffic incident data and categorizes by severity.
|
||||||
* Posts categorized traffic map to traffic LiveData.
|
* Posts categorized traffic map to traffic LiveData.
|
||||||
*/
|
*/
|
||||||
fun loadTraffic(context: Context, currentLocation: Location, carOrientation: Float) {
|
fun loadTraffic(
|
||||||
|
context: Context,
|
||||||
|
currentLocation: Location,
|
||||||
|
carOrientation: Float,
|
||||||
|
) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val data = repository.getTraffic(
|
val data = repository.getTraffic(
|
||||||
@@ -400,18 +402,8 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
|||||||
fun getAmenities(carContext: Context, category: String, location: Location, lastFuelUpdate: Long = 0) {
|
fun getAmenities(carContext: Context, category: String, location: Location, lastFuelUpdate: Long = 0) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val repository = getSettingsRepository(carContext)
|
val repository = getSettingsRepository(carContext)
|
||||||
var fuelPrices: List<Station>
|
|
||||||
val amenities = Overpass().getAmenities("amenity", category, location, 5.0)
|
val amenities = Overpass().getAmenities("amenity", category, location, 5.0)
|
||||||
val now = System.currentTimeMillis()
|
val fuelPrices = fuelStations(category, lastFuelUpdate, location, repository)
|
||||||
if (category == Constants.FUEL_STATION && ((now - lastFuelUpdate) > TANKER_KOENIG_DELAY)) {
|
|
||||||
fuelPrices = FuelPrices().getFuelPrices(location, 5)
|
|
||||||
repository.setLastFuelPrices(System.currentTimeMillis())
|
|
||||||
repository.setFuelPrices(gson.toJson(Stations(fuelPrices)))
|
|
||||||
} else {
|
|
||||||
val fuels = repository.fuelPricesFlow.first()
|
|
||||||
fuelPrices =
|
|
||||||
gson.fromJson(fuels, Stations::class.java).stations
|
|
||||||
}
|
|
||||||
val distAmenities = mutableListOf<Elements>()
|
val distAmenities = mutableListOf<Elements>()
|
||||||
amenities.forEach {
|
amenities.forEach {
|
||||||
val plLocation =
|
val plLocation =
|
||||||
@@ -428,6 +420,28 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun fuelStations(
|
||||||
|
category: String,
|
||||||
|
lastFuelUpdate: Long,
|
||||||
|
location: Location,
|
||||||
|
repository: SettingsRepository
|
||||||
|
): List<Station> {
|
||||||
|
var fuelPrices = emptyList<Station>()
|
||||||
|
if (category == Constants.FUEL_STATION) {
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
if ((now - lastFuelUpdate) > TANKER_KOENIG_DELAY) {
|
||||||
|
fuelPrices = FuelPrices().getFuelPrices(location, 5)
|
||||||
|
repository.setLastFuelPrices(System.currentTimeMillis())
|
||||||
|
repository.setFuelPrices(gson.toJson(Stations(fuelPrices)))
|
||||||
|
} else {
|
||||||
|
val fuels = repository.fuelPricesFlow.first()
|
||||||
|
fuelPrices =
|
||||||
|
gson.fromJson(fuels, Stations::class.java).stations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fuelPrices
|
||||||
|
}
|
||||||
|
|
||||||
fun addFuelPrice(fuel: Elements, fuelPrices: List<Station>, location: Location) {
|
fun addFuelPrice(fuel: Elements, fuelPrices: List<Station>, location: Location) {
|
||||||
fuelPrices.forEach {
|
fuelPrices.forEach {
|
||||||
if (fuel.tags.name.equals(it.brand, ignoreCase = true)) {
|
if (fuel.tags.name.equals(it.brand, ignoreCase = true)) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.kouros.navigation.utils
|
package com.kouros.navigation.utils
|
||||||
|
|
||||||
import android.location.Location
|
import android.location.Location
|
||||||
import android.util.Log
|
|
||||||
import kotlinx.serialization.json.buildJsonObject
|
import kotlinx.serialization.json.buildJsonObject
|
||||||
import kotlinx.serialization.json.put
|
import kotlinx.serialization.json.put
|
||||||
import org.maplibre.geojson.FeatureCollection
|
import org.maplibre.geojson.FeatureCollection
|
||||||
@@ -24,6 +23,8 @@ import kotlin.math.sin
|
|||||||
|
|
||||||
object GeoUtils {
|
object GeoUtils {
|
||||||
|
|
||||||
|
const val EARTH_RADIUS = 6371.0 // in km
|
||||||
|
|
||||||
fun snapLocation(location: Location, stepCoordinates: List<Point>): Location {
|
fun snapLocation(location: Location, stepCoordinates: List<Point>): Location {
|
||||||
val newLocation = Location(location)
|
val newLocation = Location(location)
|
||||||
val oldPoint = Point.fromLngLat(location.longitude, location.latitude)
|
val oldPoint = Point.fromLngLat(location.longitude, location.latitude)
|
||||||
@@ -151,11 +152,10 @@ object GeoUtils {
|
|||||||
* @return latMin, latMax, lngMin, lngMax
|
* @return latMin, latMax, lngMin, lngMax
|
||||||
*/
|
*/
|
||||||
fun calculateSquareRadius(lat: Double, lng: Double, radius: Double): String {
|
fun calculateSquareRadius(lat: Double, lng: Double, radius: Double): String {
|
||||||
val earthRadius = 6371.0 // earth radius in km
|
val latMin = lat - toDegrees(radius / EARTH_RADIUS)
|
||||||
val latMin = lat - toDegrees(radius / earthRadius)
|
val latMax = lat + toDegrees(radius / EARTH_RADIUS)
|
||||||
val latMax = lat + toDegrees(radius / earthRadius)
|
val lngMin = lng - toDegrees(radius / EARTH_RADIUS / cos(toRadians(lat)))
|
||||||
val lngMin = lng - toDegrees(radius / earthRadius / cos(toRadians(lat)))
|
val lngMax = lng + toDegrees(radius / EARTH_RADIUS / cos(toRadians(lat)))
|
||||||
val lngMax = lng + toDegrees(radius / earthRadius / cos(toRadians(lat)))
|
|
||||||
|
|
||||||
return "$lngMin,$latMin,$lngMax,$latMax"
|
return "$lngMin,$latMin,$lngMax,$latMax"
|
||||||
}
|
}
|
||||||
@@ -165,11 +165,10 @@ object GeoUtils {
|
|||||||
lon: Double,
|
lon: Double,
|
||||||
radius: Double
|
radius: Double
|
||||||
): String {
|
): String {
|
||||||
val earthRadius = 6371.0
|
val maxLat = lat + toDegrees(radius / EARTH_RADIUS)
|
||||||
val maxLat = lat + toDegrees(radius / earthRadius)
|
val minLat = lat - toDegrees(radius / EARTH_RADIUS)
|
||||||
val minLat = lat - toDegrees(radius / earthRadius)
|
val maxLon = lon + toDegrees(radius / EARTH_RADIUS / cos(toRadians(lat)))
|
||||||
val maxLon = lon + toDegrees(radius / earthRadius / cos(toRadians(lat)))
|
val minLon = lon - toDegrees(radius / EARTH_RADIUS / cos(toRadians(lat)))
|
||||||
val minLon = lon - toDegrees(radius / earthRadius / cos(toRadians(lat)))
|
|
||||||
|
|
||||||
return "$minLat,$minLon,$maxLat,$maxLon"
|
return "$minLat,$minLon,$maxLat,$maxLon"
|
||||||
}
|
}
|
||||||
@@ -229,21 +228,21 @@ object GeoUtils {
|
|||||||
fun movePoint(
|
fun movePoint(
|
||||||
latitude: Double,
|
latitude: Double,
|
||||||
longitude: Double,
|
longitude: Double,
|
||||||
distanceMeters: Double = 7.0,
|
distanceMeters: Double = 8.0,
|
||||||
bearingDegrees: Double = 0.0
|
bearingDegrees: Double = 0.0
|
||||||
): org.maplibre.spatialk.geojson.Point {
|
): org.maplibre.spatialk.geojson.Point {
|
||||||
val earthRadius = 6371000.0 // meters
|
val radius = EARTH_RADIUS * 1000 // meters
|
||||||
val bearingRadians = toRadians(bearingDegrees)
|
val bearingRadians = toRadians(bearingDegrees)
|
||||||
val lat1 = toRadians(latitude)
|
val lat1 = toRadians(latitude)
|
||||||
val lon1 = toRadians(longitude)
|
val lon1 = toRadians(longitude)
|
||||||
|
|
||||||
val lat2 = asin(
|
val lat2 = asin(
|
||||||
sin(lat1) * cos(distanceMeters / earthRadius) +
|
sin(lat1) * cos(distanceMeters / radius) +
|
||||||
cos(lat1) * sin(distanceMeters / earthRadius) * cos(bearingRadians)
|
cos(lat1) * sin(distanceMeters / radius) * cos(bearingRadians)
|
||||||
)
|
)
|
||||||
val lon2 = lon1 + atan2(
|
val lon2 = lon1 + atan2(
|
||||||
sin(bearingRadians) * sin(distanceMeters / earthRadius) * cos(lat1),
|
sin(bearingRadians) * sin(distanceMeters / radius) * cos(lat1),
|
||||||
cos(distanceMeters / earthRadius) - sin(lat1) * sin(lat2)
|
cos(distanceMeters / radius) - sin(lat1) * sin(lat2)
|
||||||
)
|
)
|
||||||
return org.maplibre.spatialk.geojson.Point(toDegrees(lon2), toDegrees(lat2))
|
return org.maplibre.spatialk.geojson.Point(toDegrees(lon2), toDegrees(lat2))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M280,880L280,514Q229,500 194.5,458Q160,416 160,360L160,80L240,80L240,360L280,360L280,80L360,80L360,360L400,360L400,80L480,80L480,360Q480,416 445.5,458Q411,500 360,514L360,880L280,880ZM680,880L680,560L560,560L560,280Q560,197 618.5,138.5Q677,80 760,80L760,880L680,880Z"/>
|
||||||
|
</vector>
|
||||||
@@ -73,4 +73,5 @@
|
|||||||
<string name="engine_type">Motortyp</string>
|
<string name="engine_type">Motortyp</string>
|
||||||
<string name="alternative_routes">Alternative Routen</string>
|
<string name="alternative_routes">Alternative Routen</string>
|
||||||
<string name="wait">Warten</string>
|
<string name="wait">Warten</string>
|
||||||
|
<string name="restaurant">Restaurant</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -57,4 +57,5 @@
|
|||||||
<string name="engine_type">Τύπος κινητήρα</string>
|
<string name="engine_type">Τύπος κινητήρα</string>
|
||||||
<string name="alternative_routes">Εναλλακτικές διαδρομές</string>
|
<string name="alternative_routes">Εναλλακτικές διαδρομές</string>
|
||||||
<string name="wait">Περιμένετε</string>
|
<string name="wait">Περιμένετε</string>
|
||||||
|
<string name="restaurant">Restaurant</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -57,4 +57,5 @@
|
|||||||
<string name="engine_type">Typ silnika</string>
|
<string name="engine_type">Typ silnika</string>
|
||||||
<string name="alternative_routes">Alternatywne trasy</string>
|
<string name="alternative_routes">Alternatywne trasy</string>
|
||||||
<string name="wait">Czekaj</string>
|
<string name="wait">Czekaj</string>
|
||||||
|
<string name="restaurant">Restaurant</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -60,4 +60,5 @@
|
|||||||
<string name="engine_type">Engine type</string>
|
<string name="engine_type">Engine type</string>
|
||||||
<string name="alternative_routes">Alternative routes</string>
|
<string name="alternative_routes">Alternative routes</string>
|
||||||
<string name="wait">Wait</string>
|
<string name="wait">Wait</string>
|
||||||
|
<string name="restaurant">Restaurant</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user