content: package org.altbeacon.beacon.distance;
  
  import org.altbeacon.beacon.BeaconManager;
  import org.altbeacon.beacon.logging.LogManager;
  
  /**
   * This class estimates the distance between the mobile device and a BLE beacon based on the measured
   * RSSI and a txPower calibration value that represents the expected RSSI for an iPhone 5 receiving
   * the signal when it is 1 meter away.
   *
   * This class uses a best-fit curve equation with configurable coefficients.  The coefficients must
   * be supplied by the caller and are specific to the Android device being used.  See the
   * <code>ModelSpecificDistanceCalculator</code> for more information on the coefficients.
   *
   * Created by dyoung on 8/28/14.
   */
  public class CurveFittedDistanceCalculator implements DistanceCalculator {
  
      public static final String TAG = "CurveFittedDistanceCalculator";
      private double mCoefficient1;
      private double mCoefficient2;
      private double mCoefficient3;
  
      /**
       * Construct a calculator with coefficients specific for the device's signal vs. distance
       *
       * @param coefficient1
       * @param coefficient2
       * @param coefficient3
       */
      public CurveFittedDistanceCalculator(double coefficient1, double coefficient2, double coefficient3) {
          mCoefficient1 = coefficient1;
          mCoefficient2 = coefficient2;
          mCoefficient3 = coefficient3;
      }
  
      /**
       * Calculated the estimated distance in meters to the beacon based on a reference rssi at 1m
       * and the known actual rssi at the current location
       *
       * @param txPower
       * @param rssi
       * @return estimated distance
       */
      @Override
      public double calculateDistance(int txPower, double rssi) {
          if (rssi == 0) {
              return -1.0; // if we cannot determine accuracy, return -1.
          }
  
          LogManager.d(TAG, "calculating distance based on mRssi of %s and txPower of %s", rssi, txPower);
  
  
          double ratio = rssi*1.0/txPower;
          double distance;
          if (ratio < 1.0) {
              distance =  Math.pow(ratio,10);
          }
          else {
              distance =  (mCoefficient1)*Math.pow(ratio,mCoefficient2) + mCoefficient3;
          }
          LogManager.d(TAG, "avg mRssi: %s distance: %s", rssi, distance);
          return distance;
      }
  }
  