fix(map): pick the pass by time instead of a field that is never set
The map info panel chose which pass to describe with
allPasses.find { it.catNum == catnum && it.progress < 1 }
but OrbitalPass.progress defaults to 0 and nothing in the repository or the
prediction layer ever assigns it - PassesViewModel computes progress on its own
local copy of the list and never writes it back. The predicate was therefore
always true, so the lookup returned the satellite's *first* pass forever.
Simulated over an ISS timeline with three passes (10:00, 12:00, 14:00), 4 of 6
sampled instants were wrong: from 10:30 onwards the panel still pointed at the
10:00 pass with its countdown frozen at 00:00:00, instead of counting down to the
12:00 and 14:00 passes. Only re-fetching the pass list refreshed it.
Select by time now: the pass currently in progress, otherwise the earliest one
still upcoming. Extracted as the pure internal selectCurrentOrNextPass so it is
testable, with the reasoning recorded so the progress field is not reintroduced
as a filter here.
Restoring the old predicate fails 5 of the 6 new tests; with the fix
:feature:map:testDebugUnitTest, :core:domain:test, :core:data:testDebugUnitTest
and :feature:roaming:testDebugUnitTest are all green.
This commit is contained in:
1 parent
c7bb253981
commit
aac1fa0da5
2 files changed
+120
-18
No files matched your search
@@ -220,26 +220,23 @@ class MapViewModel(
|
||||
var orbitalPass = defaultPass
|
||||
var aosTime = 0L.toTimerString()
|
||||
var isTimeAos = true
|
||||
allPasses.find { pass -> pass.catNum == sat.data.catnum && pass.progress < 1 }
|
||||
?.let { satPass ->
|
||||
orbitalPass = satPass
|
||||
if (!satPass.isDeepSpace) {
|
||||
when {
|
||||
date.time < satPass.aosTime -> {
|
||||
// Pass hasn't started yet — count down to AOS
|
||||
isTimeAos = true
|
||||
aosTime = (satPass.aosTime - date.time).toTimerString()
|
||||
}
|
||||
|
||||
date.time < satPass.losTime -> {
|
||||
// Pass is in progress — count down to LOS
|
||||
isTimeAos = false
|
||||
aosTime = (satPass.losTime - date.time).toTimerString()
|
||||
}
|
||||
// else: pass has ended (losTime <= date.time) — keep default "00:00:00"
|
||||
}
|
||||
// Select by time, not by OrbitalPass.progress: that field defaults to 0
|
||||
// and is only ever filled in by PassesViewModel's own local copy, never
|
||||
// written back to the repository. Filtering on `progress < 1` therefore
|
||||
// always matched the satellite's *first* pass, so once it ended the map
|
||||
// countdown stuck at 00:00:00 and never advanced to the next pass.
|
||||
currentOrNextPass(sat.data.catnum, date.time)?.let { satPass ->
|
||||
orbitalPass = satPass
|
||||
if (!satPass.isDeepSpace) {
|
||||
if (date.time < satPass.aosTime) {
|
||||
isTimeAos = true
|
||||
aosTime = (satPass.aosTime - date.time).toTimerString()
|
||||
} else if (date.time < satPass.losTime) {
|
||||
isTimeAos = false
|
||||
aosTime = (satPass.losTime - date.time).toTimerString()
|
||||
}
|
||||
}
|
||||
}
|
||||
val azimuth = satPos.azimuth.toDegrees()
|
||||
val elevation = satPos.elevation.toDegrees()
|
||||
val osmPos = satPos.toMapGeoPos()
|
||||
@@ -266,6 +263,10 @@ class MapViewModel(
|
||||
return satData to orbitalPass
|
||||
}
|
||||
|
||||
/** Ongoing pass for [catnum] if any, otherwise its next upcoming pass. */
|
||||
private fun currentOrNextPass(catnum: Int, timeMillis: Long): OrbitalPass? =
|
||||
selectCurrentOrNextPass(allPasses, catnum, timeMillis)
|
||||
|
||||
private suspend fun getSatTrack(orbitalObject: OrbitalObject, pos: GeoPos, date: Date) {
|
||||
val endDate = Date(date.time + (orbitalObject.data.orbitalPeriod * 2.4 * 60000L).toLong())
|
||||
val track = satelliteRepo.getTrack(orbitalObject, pos, date.time, endDate.time)
|
||||
@@ -331,3 +332,20 @@ internal fun crossingLatitude(from: GeoPos, to: GeoPos, edgeLongitude: Double):
|
||||
val fraction = (edgeLongitude - from.longitude) / span
|
||||
return from.latitude + (to.latitude - from.latitude) * fraction
|
||||
}
|
||||
/**
|
||||
* Picks the pass to describe for [catnum] at [timeMillis]: the one in progress,
|
||||
* or else the earliest one still to come.
|
||||
*
|
||||
* Deliberately ignores OrbitalPass.progress. That field is a UI-side value filled
|
||||
* in by PassesViewModel on its own copy of the list; the repository always
|
||||
* reports 0, so any `progress` predicate here silently matches everything.
|
||||
*/
|
||||
internal fun selectCurrentOrNextPass(
|
||||
passes: List<OrbitalPass>,
|
||||
catnum: Int,
|
||||
timeMillis: Long
|
||||
): OrbitalPass? {
|
||||
val forSatellite = passes.filter { it.catNum == catnum }
|
||||
return forSatellite.firstOrNull { timeMillis >= it.aosTime && timeMillis < it.losTime }
|
||||
?: forSatellite.filter { it.aosTime > timeMillis }.minByOrNull { it.aosTime }
|
||||
}
|
||||
Reference in new issue
Block a user