BatteryDropCondition.swift 1.4 KB

123456789101112131415161718192021222324252627282930313233343536
  1. // LoopFollow
  2. // BatteryDropCondition.swift
  3. import Foundation
  4. /// Fires when the phone-battery **falls by ≥ Δ % within N minutes**.
  5. ///
  6. /// * `alarm.delta`   ➜ percentage drop (e.g. 5 %)
  7. /// * `alarm.monitoringWindow` ➜ window in minutes (e.g. 15)
  8. /// * Uses `data.batteryHistory`, which must be sorted **oldest → newest**.
  9. struct BatteryDropCondition: AlarmCondition {
  10. static let type: AlarmType = .batteryDrop
  11. init() {}
  12. func evaluate(alarm: Alarm, data: AlarmData, now _: Date) -> Bool {
  13. // ───── 0. sanity ───────────────────────────────────────────────
  14. guard
  15. let drop = alarm.delta, drop > 0,
  16. let minutes = alarm.monitoringWindow, minutes > 0,
  17. let latest = data.batteryHistory.last
  18. else { return false }
  19. // find the sample *closest* to “minutes” ago
  20. let target = latest.timestamp.addingTimeInterval(-Double(minutes) * 60)
  21. guard let earlier = data.batteryHistory.min(by: {
  22. abs($0.timestamp.timeIntervalSince(target)) < abs($1.timestamp.timeIntervalSince(target))
  23. }) else { return false }
  24. // ignore if the earlier level was 100 % (false drop when just unplugged)
  25. guard earlier.batteryLevel < 100 else { return false }
  26. return (earlier.batteryLevel - latest.batteryLevel) >= drop
  27. }
  28. }