Skip to content

Commit d72c9ce

Browse files
Scale recency limit with iOS timer delay to prevent false rejections
iOS backgrounds the app during walks, delaying 60s timers to 200-293s. The fixed 30s recency limit would reject genuine walks because the user naturally stopped before the delayed timer fired. Now adds the timer delay to the recency limit so on-time timers stay strict (30s) while delayed timers account for iOS backgrounding.
1 parent e10bee1 commit d72c9ce

File tree

1 file changed

+10
-6
lines changed

1 file changed

+10
-6
lines changed

Loop/Managers/ActivityDetectionManager.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -385,17 +385,21 @@ class ActivityDetectionManager {
385385
// For 120s actual: need 60. For 293s actual: need 146.
386386
let minAdditionalSteps = max(15, Int(elapsed / 60.0 * 30.0))
387387

388-
// Recency check: user must still be actively walking when the timer fires.
389-
// If the last step change was more than 30 seconds ago, the user stopped
390-
// walking before the confirmation window ended — reject even if total
391-
// steps were sufficient (prevents "walk 1 min, sit 1 min" false positives).
392-
let stepRecencyLimit: TimeInterval = 30
388+
// Recency check: user must have been walking recently.
389+
// Base limit: 30s — if the timer fires on time, user must still be
390+
// actively stepping. But iOS often backgrounds the app, delaying the
391+
// timer by 2-5x. A 60s timer can fire at 293s. The user may have
392+
// walked for 3 minutes (exceeding CAT) but stopped before the delayed
393+
// timer fires. Adding the timer delay to the recency limit ensures
394+
// the user isn't penalized for iOS backgrounding delays.
395+
let timerDelay = max(0, elapsed - timerInterval)
396+
let stepRecencyLimit: TimeInterval = 30 + timerDelay
393397
let now = Date()
394398
let stepIsRecent: Bool
395399
if let lastStep = lastStepTime {
396400
let sinceLast = now.timeIntervalSince(lastStep)
397401
stepIsRecent = sinceLast <= stepRecencyLimit
398-
self.fileLog.log("Recency check: last step change \(String(format: "%.1f", sinceLast))s ago (limit: \(stepRecencyLimit)s) → \(stepIsRecent ? "PASS" : "FAIL")")
402+
self.fileLog.log("Recency check: last step change \(String(format: "%.1f", sinceLast))s ago (limit: \(String(format: "%.0f", stepRecencyLimit))s = 30s base + \(String(format: "%.0f", timerDelay))s timer delay) → \(stepIsRecent ? "PASS" : "FAIL")")
399403
} else {
400404
stepIsRecent = false
401405
self.fileLog.log("Recency check: no step changes recorded → FAIL")

0 commit comments

Comments
 (0)