TieredGpsAlgorithm
Kalman-smoothed, speed-adaptive GPS cleaning — the algorithm Mileway's LocationProcessor actually runs today, extracted onto the MileageAlgorithm seam so its thresholds can be swept and its output can be shadow-compared against other algorithms.
milewayV1Profile reproduces LocationProcessor's hardcoded defaults exactly (same source: AbnormalDetectionConfig.DEFAULT + LocationTrackingConstants), so this class with that profile and DeviceEnvelope.Default is a drop-in numerical match for the shipped app.
Two deliberate divergences from the source, both forced by the seam this class conforms to rather than by choice:
LocationProcessor.process()also takesisPaused/suppressSpike/motionStill/harshAccel— caller-supplied context that has no home on Fix. MileageAlgorithm.process is deliberately Fix-only (see its doc), so those overrides are out of scope here; only the context recoverable from the fix stream itself (accuracy, speed, mock, elapsed time) is used.A hard "instant teleport" spike is folded into
abnormalDistanceMandspikeDistanceMin the source (double counted, spike-as-audit-tag). AlgorithmState's documented invariant requirescleanedM == originalM - abnormalM - mockMwith spike excluded fromoriginalMentirely — so here a spike is its own exclusive DistanceBucket.SPIKE, never also counted as DistanceBucket.ABNORMAL or folded intooriginalM. Total spike+abnormal+cleaned+mock distance is unchanged; which bucket a spike lands in is not.
DeviceEnvelope scales every threshold: the two absolute "ceiling" knobs scale as a ratio against their own default (so DeviceEnvelope.Default is a strict no-op regardless of what a tuning profile sets them to), the three multiplier fields apply directly.