watch static method

Stream<LocationAnomaly> watch(
  1. Stream<Location> source, {
  2. LocationAnomalyConfig config = const LocationAnomalyConfig(),
})

Creates a stream of anomalies from a location stream.

Implementation

static Stream<LocationAnomaly> watch(
  Stream<Location> source, {
  LocationAnomalyConfig config = const LocationAnomalyConfig(),
}) {
  Location? previous;

  return source.asyncExpand((location) async* {
    final current = location;
    if (previous == null) {
      // Only set initial reference if accuracy is acceptable
      if (_hasAcceptableAccuracy(current, config)) {
        previous = current;
      }
      return;
    }

    final prev = previous!;

    // Check accuracy BEFORE potentially updating reference
    final prevAccuracyOk = _hasAcceptableAccuracy(prev, config);
    final currentAccuracyOk = _hasAcceptableAccuracy(current, config);

    if (!prevAccuracyOk || !currentAccuracyOk) {
      // Only update reference if current has good accuracy
      // This prevents reference drift from poor readings
      if (currentAccuracyOk) {
        previous = current;
      }
      return;
    }

    final timeDelta = current.timestamp.difference(prev.timestamp);
    if (timeDelta <= Duration.zero || timeDelta < config.minTimeDelta) {
      // Update reference for valid time progression
      previous = current;
      return;
    }

    final distance =
        LocationUtils.calculateDistance(prev.coords, current.coords);
    if (distance < config.minDistanceMeters) {
      // Update reference - valid location but not enough distance
      previous = current;
      return;
    }

    final speedKph = LocationUtils.calculateSpeedKph(distance, timeDelta);
    if (speedKph >= config.maxSpeedKph) {
      yield LocationAnomaly(
        previous: prev,
        current: current,
        distanceMeters: distance,
        speedKph: speedKph,
      );
      // After anomaly, update reference to current
      previous = current;
    } else {
      // Normal movement - update reference
      previous = current;
    }
  });
}