import Foundation public enum PPGCoherencePolicy { public static let spotMaximumDurationSeconds = 120.0 public static let coherenceMaximumDurationSeconds = 300.0 public static let coherenceBufferDurationSeconds = 75.0 public static func maximumDurationSeconds(isCoherence: Bool) -> Double { isCoherence ? coherenceMaximumDurationSeconds : spotMaximumDurationSeconds } } public struct PPGLiveAcceptedBeat: Equatable, Sendable { public let sequence: Int public let timestampSeconds: Double public let intervalMs: Double public let confidence: Double } /// Deduplicates accepted intervals emitted by overlapping live-analysis windows. public struct PPGLiveBeatTracker: Sendable { private var lastPublishedTimestamp: Double? private var sequence = 0 public init() {} public mutating func ingest(_ intervals: [PulseInterval]) -> [PPGLiveAcceptedBeat] { let sorted = intervals .filter { $0.isAccepted && $0.endSeconds.isFinite && $0.durationMilliseconds.isFinite && (300...2_000).contains($0.durationMilliseconds) } .sorted { $0.endSeconds < $1.endSeconds } let previous = lastPublishedTimestamp let newIntervals = sorted.filter { interval in guard let previous else { return true } // Physiological intervals are at least 300 ms. A 250 ms boundary treats // small peak refinements as the same beat without swallowing a real one. return interval.endSeconds > previous + 0.25 } let beats = newIntervals.map { interval -> PPGLiveAcceptedBeat in sequence += 1 return PPGLiveAcceptedBeat( sequence: sequence, timestampSeconds: interval.endSeconds, intervalMs: interval.durationMilliseconds, confidence: min(max(interval.qualityScore, 0), 1) ) } if let latest = sorted.last?.endSeconds { lastPublishedTimestamp = max(lastPublishedTimestamp ?? latest, latest) } return beats } public mutating func reset() { lastPublishedTimestamp = nil sequence = 0 } }