diff options
| author | Claude <noreply@anthropic.com> | 2026-04-11 18:35:23 +0000 |
|---|---|---|
| committer | Claude <noreply@anthropic.com> | 2026-04-11 18:35:23 +0000 |
| commit | acb1d24e7b4a4c5c01c8fe5a50d702cbbaed2d5d (patch) | |
| tree | e3470ca7eb01a2fada73fcbea745d01e19d9a24d /android-app | |
| parent | ec2bc313ba88477aeefcb5c943ed387de2883ee8 (diff) | |
Throttle conditions API; delay particle view until data loaded
loadConditions now skips the API call if conditions were loaded
< 5 min ago and position hasn't moved > 2 nm — prevents 429 from
overlapping triggers (startup backstop, GPS first-fix, camera idle).
Dev log shows "conditions: skip age=Xs dist=Y.Znm" when throttled.
ParticleWindView starts hidden and is revealed only when the first
windArrow value arrives, so particles don't flash before the map loads.
https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
Diffstat (limited to 'android-app')
| -rw-r--r-- | android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt | 9 | ||||
| -rw-r--r-- | android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt | 27 |
2 files changed, 31 insertions, 5 deletions
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt b/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt index 35a0e91..b7db246 100644 --- a/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt +++ b/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt @@ -400,10 +400,8 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { mapView = findViewById(R.id.mapView) particleWindView = findViewById(R.id.particle_wind_view) - // Apply persisted particles preference immediately - if (!layerManager.particlesEnabled) { - particleWindView?.visibility = View.GONE - } + // Always start hidden; revealed by the windArrow observer once data arrives + particleWindView?.visibility = View.GONE if (NavApplication.isTesting) return @@ -503,6 +501,9 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { if (arrow != null) { mapHandler?.updateWindLayer(arrow) particleWindView?.setWind(arrow.directionDeg, arrow.speedKt) + if (layerManager.particlesEnabled) { + particleWindView?.visibility = View.VISIBLE + } } } } diff --git a/android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt b/android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt index e65cbd1..868b828 100644 --- a/android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt +++ b/android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt @@ -170,11 +170,27 @@ class MainViewModel( .create(AisHubApiService::class.java) } + private var lastConditionsLat = Double.NaN + private var lastConditionsLon = Double.NaN + private var lastConditionsMs = 0L + /** * Fetches current conditions snapshot for [lat]/[lon] and exposes it via [marineConditions]. - * Silently ignored on network failure — the UI keeps showing dashes. + * Throttled: skips if conditions loaded < 5 min ago and position < 2 nm from last load. */ fun loadConditions(lat: Double, lon: Double) { + val nowMs = System.currentTimeMillis() + val ageMs = nowMs - lastConditionsMs + val distNm = if (lastConditionsLat.isNaN()) Double.MAX_VALUE + else distanceNm(lastConditionsLat, lastConditionsLon, lat, lon) + if (ageMs < 5 * 60_000L && distNm < 2.0) { + NavLogger.i("conditions", "skip age=${ageMs / 1000}s dist=%.1fnm".format(distNm)) + return + } + lastConditionsLat = lat + lastConditionsLon = lon + lastConditionsMs = nowMs + conditionsJob?.cancel() conditionsJob = viewModelScope.launch { _conditionsLoading.value = true @@ -192,6 +208,15 @@ class MainViewModel( } } + private fun distanceNm(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double { + val dLat = Math.toRadians(lat2 - lat1) + val dLon = Math.toRadians(lon2 - lon1) + val a = sin(dLat / 2) * sin(dLat / 2) + + cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) * + sin(dLon / 2) * sin(dLon / 2) + return 3440.065 * 2 * kotlin.math.asin(kotlin.math.sqrt(a)) + } + /** * Fetch weather and wind arrow for [lat]/[lon]. Called once on first GPS fix. */ |
