Bimba.git

commit ea6caf4d7dc2c20fa99b60dac02418f7a0adfeea

Author: Adam Evyčędo <git@apiote.xyz>

add structs for route planning

%!v(PANIC=String method: strings: negative Repeat count)


diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 27ec7e12a54255f6867f2638aff16d32b741247c..a30a386b78e38c4f35b7e686668990530549dce9 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -116,11 +116,11 @@ 	implementation("com.github.jershell:kbson:0.5.0")
 	implementation("androidx.preference:preference-ktx:1.2.1")
 	implementation("androidx.work:work-runtime-ktx:2.10.0")
 	implementation("com.github.doyaaaaaken:kotlin-csv-jvm:1.10.0")
-	implementation("commons-io:commons-io:2.17.0")
+	implementation("commons-io:commons-io:2.18.0")
 	implementation("com.google.guava:guava:33.3.1-android")
 	implementation(project(":fruchtfleisch"))
-	implementation("ch.acra:acra-http:5.11.4")
-	implementation("ch.acra:acra-notification:5.11.4")
+	implementation("ch.acra:acra-http:5.12.0")
+	implementation("ch.acra:acra-notification:5.12.0")
 	implementation("com.squareup.okhttp3:okhttp:4.12.0")
 	implementation("com.squareup.moshi:moshi-kotlin:1.15.1")
 




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/transitousJourney.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/transitousJourney.kt
index 44fdaca97dc060fc611777eb0ceeba7d71982a2c..bd47fc72e1ba1bcaa102c8766b5930c268ad4b87 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/api/transitousJourney.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/transitousJourney.kt
@@ -5,35 +5,107 @@
 package xyz.apiote.bimba.czwek.api
 
 import android.content.Context
+import android.util.Log
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
 import xyz.apiote.bimba.czwek.R
 import xyz.apiote.bimba.czwek.api.transitous.api.RoutingApi
-import xyz.apiote.bimba.czwek.api.transitous.model.Mode
+import xyz.apiote.bimba.czwek.repo.Colour
+import xyz.apiote.bimba.czwek.repo.CongestionLevel
+import xyz.apiote.bimba.czwek.repo.Event
 import xyz.apiote.bimba.czwek.repo.Journey
 import xyz.apiote.bimba.czwek.repo.Leg
-import xyz.apiote.bimba.czwek.repo.StopsLeg
+import xyz.apiote.bimba.czwek.repo.LineStub
+import xyz.apiote.bimba.czwek.repo.LineType
+import xyz.apiote.bimba.czwek.repo.OccupancyStatus
+import xyz.apiote.bimba.czwek.repo.Place
+import xyz.apiote.bimba.czwek.repo.Position
 import xyz.apiote.bimba.czwek.repo.TrafficResponseException
-import xyz.apiote.bimba.czwek.repo.TransitLeg
+import xyz.apiote.bimba.czwek.repo.Vehicle
+import xyz.apiote.bimba.czwek.units.Metre
+import xyz.apiote.bimba.czwek.units.Mps
+import xyz.apiote.bimba.czwek.units.Second
 import java.time.ZoneId
 
-suspend fun getJourney(from: Double, to: Double, context: Context) {
+suspend fun getJourney(from: Place, to: Place, context: Context): List<Journey> {
 	if (!isNetworkAvailable(context)) {
 		throw TrafficResponseException(0, "", Error(0, R.string.error_offline, R.drawable.error_net))
 	}
 
 	return withContext(Dispatchers.IO) {
-		val response = RoutingApi().plan(from.toString(), to.toString())
-		val journeys = response.itineraries.map {
+		Log.d("Journeys", "from: ${from.planString()}")
+		Log.d("Journeys", "to: ${to.planString()}")
+		val response = RoutingApi().plan(from.planString(), to.planString(), maxTransfers = null)
+		Log.d("Journeys", "${response.itineraries}")
+		response.itineraries.map {
 			val legs: List<Leg> = it.legs.map {
-				if(it.mode in setOf(Mode.BUS)) {
-					StopsLeg()
-				} else {
-					TransitLeg()
-				}
+				Leg(
+					Event(
+						it.tripId ?: "",
+						null,
+						Time.fromOffsetTime(it.startTime, ZoneId.systemDefault()),
+						0u,
+						it.realTime,
+						Vehicle(
+							it.tripId ?: "",
+							Position(0.0, 0.0),
+							0u,
+							Mps(0),
+							LineStub(
+								it.routeShortName ?: "", // TODO is it nullable, yes e.g. for transit
+								LineType.fromTransitous2(it.mode),
+								Colour.fromHex(it.routeColor)
+							),
+							it.headsign ?: "",  // TODO is it nullable, yes e.g. for transit
+							CongestionLevel.UNKNOWN,
+							OccupancyStatus.UNKNOWN
+						),
+						boarding = 0xffu,
+						alerts = emptyList(),
+						exact = true,
+						terminusArrival = false
+					),
+					Event(
+						it.tripId ?: "",
+						Time.fromOffsetTime(it.endTime, ZoneId.systemDefault()),
+						null,
+						0u,
+						it.realTime,
+						Vehicle(
+							it.tripId ?: "",
+							Position(0.0, 0.0),
+							0u,
+							Mps(0),
+							LineStub(
+								it.routeShortName ?: "", // TODO is it nullable, yes e.g. for transit
+								LineType.fromTransitous2(it.mode),
+								Colour.fromHex(it.routeColor)
+							),
+							it.headsign ?: "",  // TODO is it nullable, yes e.g. for transit
+							CongestionLevel.UNKNOWN,
+							OccupancyStatus.UNKNOWN
+						),
+						boarding = 0xffu,
+						alerts = emptyList(),
+						exact = true,
+						terminusArrival = false
+					),
+					Place(it.from),
+					Place(it.to),
+					it.agencyName,
+					it.distance?.toDouble()?.let { Metre(it) },
+					Second(it.duration),
+					(it.intermediateStops ?: emptyList()).map { Place(it) },
+					/*it.legGeometry,
+					it.rental,
+					it.steps,*/
+				)
 			}
-			Journey(it.startTime.atZoneSameInstant(ZoneId.systemDefault()), it.endTime.atZoneSameInstant(
-				ZoneId.systemDefault()), legs)
+			Journey(
+				it.startTime.atZoneSameInstant(ZoneId.systemDefault()), it.endTime.atZoneSameInstant(
+					ZoneId.systemDefault()
+				), legs
+			)
 		}
 	}
 




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt
index ac05a4944b6d577160c3793997583c9c7126ccf1..2ab2919eb3cea85c2c7d2ea6f36b1af166550b71 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt
@@ -36,8 +36,8 @@ import com.google.openlocationcode.OpenLocationCode
 import xyz.apiote.bimba.czwek.AboutActivity
 import xyz.apiote.bimba.czwek.R
 import xyz.apiote.bimba.czwek.dashboard.ui.home.HomeFragment
+import xyz.apiote.bimba.czwek.dashboard.ui.journey.JourneyFragment
 import xyz.apiote.bimba.czwek.dashboard.ui.map.MapFragment
-import xyz.apiote.bimba.czwek.dashboard.ui.voyage.VoyageFragment
 import xyz.apiote.bimba.czwek.databinding.ActivityMainBinding
 import xyz.apiote.bimba.czwek.onboarding.FirstRunActivity
 import xyz.apiote.bimba.czwek.search.ResultsActivity
@@ -279,8 +279,7 @@ 		startActivity(ResultsActivity.getIntent(this, mode, query))
 	}
 
 	private fun setNavbarIcons(f: Fragment) {
-		// todo [voyage-planning]
-		// binding.bottomNavigation.menu[2].setIcon(R.drawable.voyage_outline)
+		binding.bottomNavigation.menu[2].setIcon(R.drawable.voyage_outline)
 		binding.bottomNavigation.menu[1].setIcon(R.drawable.home_outline)
 		binding.bottomNavigation.menu[0].setIcon(R.drawable.map_outline)
 		when (f) {
@@ -288,7 +287,7 @@ 			is HomeFragment -> {
 				binding.bottomNavigation.menu[1].setIcon(R.drawable.home_black)
 			}
 
-			is VoyageFragment -> {
+			is JourneyFragment -> {
 				binding.bottomNavigation.menu[2].setIcon(R.drawable.voyage_black)
 			}
 




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..899dcf61b0afec2a3bca1178f13e1c1f669d46dd
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt
@@ -0,0 +1,49 @@
+// SPDX-FileCopyrightText: Adam Evyčędo
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package xyz.apiote.bimba.czwek.dashboard.ui.journey
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import xyz.apiote.bimba.czwek.databinding.FragmentVoyageBinding
+
+class JourneyFragment : Fragment() {
+
+	private var _binding: FragmentVoyageBinding? = null
+
+	// This property is only valid between onCreateView and
+	// onDestroyView.
+	private val binding get() = _binding!!
+
+	override fun onCreateView(
+		inflater: LayoutInflater,
+		container: ViewGroup?,
+		savedInstanceState: Bundle?
+	): View {
+		val journeyViewModel =
+			ViewModelProvider(this)[JourneyViewModel::class.java]
+
+		_binding = FragmentVoyageBinding.inflate(inflater, container, false)
+		val root: View = binding.root
+
+		val textView: TextView = binding.textDashboard
+		journeyViewModel.text.observe(viewLifecycleOwner) {
+			textView.text = it
+		}
+
+		journeyViewModel.getJourney(requireContext())
+
+		return root
+	}
+
+	override fun onDestroyView() {
+		super.onDestroyView()
+		_binding = null
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyViewModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6daa824df19ef722f345bd453f8abbdb4bf4c23d
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyViewModel.kt
@@ -0,0 +1,42 @@
+// SPDX-FileCopyrightText: Adam Evyčędo
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package xyz.apiote.bimba.czwek.dashboard.ui.journey
+
+import android.content.Context
+import android.util.Log
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.launch
+import xyz.apiote.bimba.czwek.repo.ChangeOption
+import xyz.apiote.bimba.czwek.repo.Place
+import xyz.apiote.bimba.czwek.repo.Position
+import xyz.apiote.bimba.czwek.repo.Stop
+
+class JourneyViewModel : ViewModel() {
+
+	private val _text = MutableLiveData<String>().apply {
+		value = "This is voyage Fragment"
+	}
+	val text: LiveData<String> = _text
+
+	fun getJourney(context: Context) {
+		viewModelScope.launch {
+			Log.i("Journeys", "getting journeys")
+			val journeys = xyz.apiote.bimba.czwek.api.getJourney(
+				Place(Stop("", "", "", "", "", Position(0.0, 0.0), emptyList<ChangeOption>(), ""), 52.402815, 16.911795),
+				Place(Stop("", "", "", "", "", Position(0.0, 0.0), emptyList<ChangeOption>(), ""), 52.445433, 17.079231),
+				context
+			)
+			Log.i("Journeys", "got ${journeys.size} journeys")
+
+			journeys.forEach {
+				Log.i("Journeys", "$it")
+			}
+		}
+
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageFragment.kt
deleted file mode 100644
index dd4e43a5b5dced04c16bdedb0ec15706f9b978bc..0000000000000000000000000000000000000000
--- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageFragment.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-// SPDX-FileCopyrightText: Adam Evyčędo
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-package xyz.apiote.bimba.czwek.dashboard.ui.voyage
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
-import xyz.apiote.bimba.czwek.databinding.FragmentVoyageBinding
-
-class VoyageFragment : Fragment() {
-
-	private var _binding: FragmentVoyageBinding? = null
-
-	// This property is only valid between onCreateView and
-	// onDestroyView.
-	private val binding get() = _binding!!
-
-	override fun onCreateView(
-		inflater: LayoutInflater,
-		container: ViewGroup?,
-		savedInstanceState: Bundle?
-	): View {
-		val voyageViewModel =
-			ViewModelProvider(this)[VoyageViewModel::class.java]
-
-		_binding = FragmentVoyageBinding.inflate(inflater, container, false)
-		val root: View = binding.root
-
-		val textView: TextView = binding.textDashboard
-		voyageViewModel.text.observe(viewLifecycleOwner) {
-			textView.text = it
-		}
-		return root
-	}
-
-	override fun onDestroyView() {
-		super.onDestroyView()
-		_binding = null
-	}
-}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageViewModel.kt
deleted file mode 100644
index 7791ee8b3f17def24bd3200525907f396708e7a1..0000000000000000000000000000000000000000
--- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageViewModel.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-FileCopyrightText: Adam Evyčędo
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-package xyz.apiote.bimba.czwek.dashboard.ui.voyage
-
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-
-class VoyageViewModel : ViewModel() {
-
-	private val _text = MutableLiveData<String>().apply {
-		value = "This is voyage Fragment"
-	}
-	val text: LiveData<String> = _text
-}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Journey.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Journey.kt
index 2ec0e896acf1697ce72836b0a0a18b38cd4021fb..e4086f2b9190b63bde8d95d160183a1320ee4d3c 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Journey.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Journey.kt
@@ -4,45 +4,38 @@ // SPDX-License-Identifier: GPL-3.0-or-later
 
 package xyz.apiote.bimba.czwek.repo
 
+import xyz.apiote.bimba.czwek.api.transitous.model.Place
+import xyz.apiote.bimba.czwek.units.DistanceUnit
 import xyz.apiote.bimba.czwek.units.TimeUnit
 import java.time.ZonedDateTime
 
-class Journey(val startTime: ZonedDateTime, val endTime: ZonedDateTime, val legs: List<Leg>) {
-}
+data class Journey(val startTime: ZonedDateTime, val endTime: ZonedDateTime, val legs: List<Leg>)
 
-interface Leg {
-	fun origin(): Stop
-	fun destination(): Stop
-	fun duration(): TimeUnit
-	// TODO shape
-}
+data class Leg(
+	val start: Event,
+	val end: Event,
+	val origin: xyz.apiote.bimba.czwek.repo.Place,
+	val destination: xyz.apiote.bimba.czwek.repo.Place,
+	val agencyName: String?,
+	val distance: DistanceUnit?,
+	val duration: TimeUnit,
+	val intermediateStops: List<xyz.apiote.bimba.czwek.repo.Place>,
+	/* TODO
+	val shape: EncodedPolyline,
+	val rental: Rental?,
+	val steps: List<StepInstruction>?,*/
+)
 
-class TransitLeg(): Leg {
-	override fun origin(): Stop {
-		TODO("Not yet implemented")
-	}
+class Place(val stop: Stop, val latitude: Double, val longitude: Double) {
+	constructor(place: Place) : this(
+		stop = Stop(place),
+		latitude = place.lat.toDouble(),
+		longitude = place.lon.toDouble()
+	)
 
-	override fun destination(): Stop {
-		TODO("Not yet implemented")
+	fun planString(): String = if (stop.code == "") {
+		"${latitude},${longitude},0"
+	} else {
+		stop.code
 	}
-
-	override fun duration(): TimeUnit {
-		TODO("Not yet implemented")
-	}
-
 }
-
-class StopsLeg(): Leg {
-	override fun origin(): Stop {
-		TODO("Not yet implemented")
-	}
-
-	override fun destination(): Stop {
-		TODO("Not yet implemented")
-	}
-
-	override fun duration(): TimeUnit {
-		TODO("Not yet implemented")
-	}
-
-}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt
index 8448bc7210a18e9e0d352a657e4ef0db6139848a..6d17c0280d508948271195823838d292d570be3c 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt
@@ -61,7 +61,8 @@ 		s.zone,
 		null,
 		Position(s.position),
 		s.changeOptions.map { ChangeOption(it) },
-		null)
+		null
+	)
 
 	constructor(s: StopV2) : this(
 		s.code,
@@ -71,7 +72,8 @@ 		s.zone,
 		s.feedID,
 		Position(s.position),
 		s.changeOptions.map { ChangeOption(it) },
-		null)
+		null
+	)
 
 	constructor(s: StopV3) : this(
 		s.code,
@@ -81,9 +83,10 @@ 		s.zone,
 		s.feedID,
 		Position(s.position),
 		s.changeOptions.map { ChangeOption(it) },
-		null)
+		null
+	)
 
-	constructor(s: Match): this(
+	constructor(s: Match) : this(
 		s.id,
 		s.name,
 		s.areas.sortedBy { it.adminLevel }.map { it.name }.distinct().joinToString() + s.name,
@@ -94,8 +97,8 @@ 		emptyList(),
 		s.areas.sortedBy { it.adminLevel }.map { it.name }.distinct().joinToString()
 	)
 
-	constructor(s: Place): this(
-		s.stopId!!,
+	constructor(s: Place) : this(
+		s.stopId ?: "",
 		s.name,
 		s.name,
 		"",
@@ -173,7 +176,12 @@ 							Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
 						)
 
 						LineDecoration.COLOUR -> {
-							str.setSpan(background, str.getSpanStart(it), str.getSpanEnd(it), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
+							str.setSpan(
+								background,
+								str.getSpanStart(it),
+								str.getSpanEnd(it),
+								Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+							)
 							// str.setSpan(foreground, str.getSpanStart(it), str.getSpanEnd(it), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
 						}
 
@@ -199,6 +207,7 @@ 	}
 
 	enum class LineDecoration {
 		NONE, ITALICS, COLOUR;
+
 		companion object {
 			fun fromPreferences(context: Context) =
 				when (PreferenceManager.getDefaultSharedPreferences(context)




diff --git a/app/src/main/res/layout/fragment_voyage.xml b/app/src/main/res/layout/fragment_voyage.xml
index d203fb59097298684b55267db3e3f7250717b285..1795bb39213178519ebf3fd623efc5197b05db82 100644
--- a/app/src/main/res/layout/fragment_voyage.xml
+++ b/app/src/main/res/layout/fragment_voyage.xml
@@ -11,7 +11,7 @@ 	xmlns:app="http://schemas.android.com/apk/res-auto"
 	xmlns:tool="http://schemas.android.com/tools"
 	android:layout_width="match_parent"
 	android:layout_height="match_parent"
-	tool:context="xyz.apiote.bimba.czwek.dashboard.ui.voyage.VoyageFragment">
+	tool:context="xyz.apiote.bimba.czwek.dashboard.ui.journey.JourneyFragment">
 
 	<com.google.android.material.textview.MaterialTextView
 		android:id="@+id/text_dashboard"




diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml
index be717aeeddf1f9fb5849e9756457444ce8ea25d6..19ae61227a47d944e0f93cf24a0f06f7e2014d01 100644
--- a/app/src/main/res/menu/bottom_nav_menu.xml
+++ b/app/src/main/res/menu/bottom_nav_menu.xml
@@ -15,9 +15,8 @@ 	 		android:id="@+id/navigation_home"
 		android:icon="@drawable/home_outline"
 		android:title="@string/title_home" />
-	<!-- todo [voyage planning]
 	<item
 		android:id="@+id/navigation_voyage"
 		android:icon="@drawable/voyage_outline"
-		android:title="@string/title_voyage" />-->
+		android:title="Journey" />
 </menu>
\ No newline at end of file




diff --git a/app/src/main/res/navigation/front_navigation.xml b/app/src/main/res/navigation/front_navigation.xml
index 1049aa1728a3a4a9591aad523c1527025415d860..bf3bb598a0cfb6ad56cf4f2bf21faa7b892ca44b 100644
--- a/app/src/main/res/navigation/front_navigation.xml
+++ b/app/src/main/res/navigation/front_navigation.xml
@@ -26,7 +26,7 @@ 		tool:layout="@layout/fragment_map" />
 
 	<fragment
 		android:id="@+id/navigation_voyage"
-		android:name="xyz.apiote.bimba.czwek.dashboard.ui.voyage.VoyageFragment"
+		android:name="xyz.apiote.bimba.czwek.dashboard.ui.journey.JourneyFragment"
 		android:label="@string/title_journey"
 		tool:layout="@layout/fragment_voyage" />
 </navigation>
\ No newline at end of file




diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b00ba98ca26bb4cd3ff5911e98920bbbd4505df8..313313506c8e7518f9acce01caa8c71959f02a23 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -287,7 +287,7 @@ 	A community-run provider-neutral international public transport routing service. Coverage is available at https://transitous.org/sources/
 	<string name="transitous_attribution">Transitous (https://transitous.org) API provided by Spline (https://routing.spline.de). Localities (https://github.com/public-transport/transitous/tree/main/feeds) maintained by the community.</string>
 	<string name="local_time">local time</string>
 	<string name="arrow">Arrow pointing to the stop</string>
-    <string name="departure_arrived">arrived</string>
+	<string name="departure_arrived">arrived</string>
 	<string name="arrival_approximate">approx. arr.</string>
 	<string name="arrival">arrival</string>
 	<string name="departure_approximate">approx. dep.</string>




diff --git a/fruchtfleisch/build.gradle.kts b/fruchtfleisch/build.gradle.kts
index df25428f756486a6fc35db26cf06914a5427ee12..1cd1d02cb45b7590029e35f93a3e10b5468f1431 100644
--- a/fruchtfleisch/build.gradle.kts
+++ b/fruchtfleisch/build.gradle.kts
@@ -8,8 +8,8 @@     kotlin("jvm")
 }
 
 dependencies {
-    testImplementation("org.junit.jupiter:junit-jupiter:5.11.2")
-    testImplementation("org.junit.jupiter:junit-jupiter:5.11.2")
+    testImplementation("org.junit.jupiter:junit-jupiter:5.11.3")
+    testImplementation("org.junit.jupiter:junit-jupiter:5.11.3")
 
     //implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.10")
 }