fix(todo): only a full wait counts towards lying still (ADR 0033, D32)
Asking for fixes at a new interval brings one at once, so each doubling brought the next: on the emulator's walk the wait went from 30 s to 120 s within 40 s, and would reach 5 min within a couple of minutes, leaving someone who sets off again unnoticed for that long. A still fix now counts only once at least three quarters of the wait asked for has passed; a move still starts over at once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
31ff8d7e91
commit
62f5dbb2d6
4 changed files with 60 additions and 2 deletions
|
|
@ -58,6 +58,20 @@ object LocationDwell {
|
||||||
/** Whether the phone, [moved] metres since the last fix, lies still. */
|
/** Whether the phone, [moved] metres since the last fix, lies still. */
|
||||||
fun still(moved: Float): Boolean = moved < STILL_METRES
|
fun still(moved: Float): Boolean = moved < STILL_METRES
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many fixes the phone has lain still, [before] this one, [moved] metres
|
||||||
|
* from the last and [waited] milliseconds after it, [asked] being the wait
|
||||||
|
* asked for. A move starts over. A fix sooner than asked says nothing (a
|
||||||
|
* quarter short still counts, as Android may hand one over a little early):
|
||||||
|
* asking anew brings one at once, and counting those reached the longest
|
||||||
|
* wait within a minute or two.
|
||||||
|
*/
|
||||||
|
fun stillFixes(before: Int, moved: Float, waited: Long, asked: Long): Int = when {
|
||||||
|
!still(moved) -> 0
|
||||||
|
waited * 4 >= asked * 3 -> before + 1
|
||||||
|
else -> before
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How long until the next fix: as long as reaching the nearest circle,
|
* How long until the next fix: as long as reaching the nearest circle,
|
||||||
* [metres] away, takes at the fastest, doubled for each of [stillFixes]
|
* [metres] away, takes at the fastest, doubled for each of [stillFixes]
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,16 @@ class LocationWatchService : Service(), LocationListener {
|
||||||
val accuracy = if (fix.hasAccuracy()) fix.accuracy else null
|
val accuracy = if (fix.hasAccuracy()) fix.accuracy else null
|
||||||
LocationReminders.log(this, "fix, ${accuracy ?: "?"} m")
|
LocationReminders.log(this, "fix, ${accuracy ?: "?"} m")
|
||||||
if (!LocationDwell.usable(accuracy)) return
|
if (!LocationDwell.usable(accuracy)) return
|
||||||
stillFixes = if (before != null && LocationDwell.still(before.distanceTo(fix))) stillFixes + 1 else 0
|
stillFixes = if (before == null) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
LocationDwell.stillFixes(
|
||||||
|
before = stillFixes,
|
||||||
|
moved = before.distanceTo(fix),
|
||||||
|
waited = (fix.elapsedRealtimeNanos - before.elapsedRealtimeNanos) / 1_000_000,
|
||||||
|
asked = requested ?: 0,
|
||||||
|
)
|
||||||
|
}
|
||||||
last = fix
|
last = fix
|
||||||
LocationReminders.seen(this, fix.latitude, fix.longitude)
|
LocationReminders.seen(this, fix.latitude, fix.longitude)
|
||||||
ask(next(fix))
|
ask(next(fix))
|
||||||
|
|
|
||||||
|
|
@ -101,4 +101,37 @@ class LocationDwellTest {
|
||||||
assertTrue(LocationDwell.still(moved = 49f))
|
assertTrue(LocationDwell.still(moved = 49f))
|
||||||
assertFalse(LocationDwell.still(moved = 50f))
|
assertFalse(LocationDwell.still(moved = 50f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `a still fix after the wait asked for counts`() {
|
||||||
|
assertEquals(3, LocationDwell.stillFixes(before = 2, moved = 10f, waited = 60_000L, asked = 60_000L))
|
||||||
|
assertEquals(3, LocationDwell.stillFixes(before = 2, moved = 10f, waited = 45_000L, asked = 60_000L))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `a fix sooner than asked for says nothing of lying still`() {
|
||||||
|
assertEquals(2, LocationDwell.stillFixes(before = 2, moved = 10f, waited = 5_000L, asked = 60_000L))
|
||||||
|
assertEquals(2, LocationDwell.stillFixes(before = 2, moved = 10f, waited = 44_000L, asked = 60_000L))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `a move starts over, however soon it came`() {
|
||||||
|
assertEquals(0, LocationDwell.stillFixes(before = 3, moved = 50f, waited = 5_000L, asked = 240_000L))
|
||||||
|
assertEquals(0, LocationDwell.stillFixes(before = 3, moved = 900f, waited = 240_000L, asked = 240_000L))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `a phone lying still takes minutes to reach the longest wait`() {
|
||||||
|
// Each wait is asked anew, which brings a fix at once: the fix in the
|
||||||
|
// emulator's walk that doubled it within seconds, 5 Nov 2026.
|
||||||
|
var fixes = 0
|
||||||
|
var elapsed = 0L
|
||||||
|
while (LocationDwell.interval(metres = 1_000f, stillFixes = fixes) < LocationDwell.LATEST_MILLIS) {
|
||||||
|
val asked = LocationDwell.interval(metres = 1_000f, stillFixes = fixes)
|
||||||
|
fixes = LocationDwell.stillFixes(fixes, moved = 0f, waited = 5_000L, asked = asked)
|
||||||
|
fixes = LocationDwell.stillFixes(fixes, moved = 0f, waited = asked, asked = asked)
|
||||||
|
elapsed += 5_000L + asked
|
||||||
|
}
|
||||||
|
assertTrue(elapsed >= 7 * 60_000L)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -647,7 +647,9 @@ The developer's review of 4 Nov 2026, again beside Todoist's screens.
|
||||||
Google's. The price is a notification while places wait, on a channel of the least
|
Google's. The price is a notification while places wait, on a channel of the least
|
||||||
importance (`places_watched`), and the fixes, kept few (`LocationDwell.interval`):
|
importance (`places_watched`), and the fixes, kept few (`LocationDwell.interval`):
|
||||||
as long as reaching the nearest circle takes at 30 m/s, doubled for each fix the
|
as long as reaching the nearest circle takes at 30 m/s, doubled for each fix the
|
||||||
phone lay still (moved under 50 m), between 30 s and 5 min, at balanced accuracy on
|
phone lay still (moved under 50 m, and the wait asked for over, at least three
|
||||||
|
quarters of it, as asking anew brings a fix at once and an emulator's walk reached
|
||||||
|
2 min within 40 s), between 30 s and 5 min, at balanced accuracy on
|
||||||
the fused provider of Android's own, GPS before Android 12. What it costs a day
|
the fused provider of Android's own, GPS before Android 12. What it costs a day
|
||||||
wants measuring. A fix rougher than 100 m says nothing of a circle.
|
wants measuring. A fix rougher than 100 m says nothing of a circle.
|
||||||
- *Dwell*, so that driving past an EDEKA on the way to the next doesn't remind (the
|
- *Dwell*, so that driving past an EDEKA on the way to the next doesn't remind (the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue