// Path: measures/src/main/java/io/apisense/network/Measurement.java
// public abstract class Measurement {
//   public final String taskName;
// 
//   protected Measurement(String taskName) {
//     this.taskName = taskName;
//   }
// 
//   /**
//    * Ensure that the measurement is asynchronously called in an {@link ExecutorService}.
//    *
//    * @param callback The {@link MeasurementCallback} used
//    *                 for reporting success or failure of this measurement.
//    */
//   public final void call(MeasurementCallback callback) {
//     AsyncTask.execute(new MeasurementExecutor(this, callback));
//   }
// 
//   /**
//    * Actual, synchronous, process of a measurement.
//    * This method has to be called from another thread than the UI one.
//    *
//    * @return The results of this measurement.
//    * @throws MeasurementError If anything goes wrong during measurement.
//    */
//   public abstract MeasurementResult execute() throws MeasurementError;
// }
// 
// Path: measures/src/main/java/io/apisense/network/MeasurementError.java
// public class MeasurementError extends Exception {
//   public final String taskName;
// 
//   public MeasurementError(String taskName, String reason) {
//     super(reason);
//     this.taskName = taskName;
//   }
// 
//   public MeasurementError(String taskName, String reason, Throwable e) {
//     super(reason, e);
//     this.taskName = taskName;
//   }
// 
//   public MeasurementError(String taskName, Exception e) {
//     this(taskName, e.getMessage(), e);
//   }
// }


import android.support.annotation.NonNull;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.apisense.network.Measurement;
import io.apisense.network.MeasurementError;
      if (matcher.matches()) {
        ip = matcher.group(1);
        latency = Float.valueOf(matcher.group(2)).longValue(); // milliseconds
      }

      matcher = PING_RESPONSE_RTT_SUCCESS.matcher(line);

      if (matcher.matches()) {
        float min = Float.valueOf(matcher.group(1));
        float avg = Float.valueOf(matcher.group(2));
        float max = Float.valueOf(matcher.group(3));
        float mdev = Float.valueOf(matcher.group(4));

        rtt = new Rtt(min, avg, max, mdev);

        return new ICMPResult(startTimeMs, endTime, config, hostname, ip, latency, currentTtl, rtt);
      }

      matcher = PING_RESPONSE_TIMEOUT.matcher(line);

      if (matcher.matches()) {
        throw new PINGException("Packet is lost");
      }
    }

    throw new PINGException("Could not parse response");
  }

  @Override
  @NonNull
// Path: measures/src/main/java/io/apisense/network/Measurement.java
// public abstract class Measurement {
//   public final String taskName;
// 
//   protected Measurement(String taskName) {
//     this.taskName = taskName;
//   }
// 
//   /**
//    * Ensure that the measurement is asynchronously called in an {@link ExecutorService}.
//    *
//    * @param callback The {@link MeasurementCallback} used
//    *                 for reporting success or failure of this measurement.
//    */
//   public final void call(MeasurementCallback callback) {
//     AsyncTask.execute(new MeasurementExecutor(this, callback));
//   }
// 
//   /**
//    * Actual, synchronous, process of a measurement.
//    * This method has to be called from another thread than the UI one.
//    *
//    * @return The results of this measurement.
//    * @throws MeasurementError If anything goes wrong during measurement.
//    */
//   public abstract MeasurementResult execute() throws MeasurementError;
// }
// 
// Path: measures/src/main/java/io/apisense/network/MeasurementError.java
// public class MeasurementError extends Exception {
//   public final String taskName;
// 
//   public MeasurementError(String taskName, String reason) {
//     super(reason);
//     this.taskName = taskName;
//   }
// 
//   public MeasurementError(String taskName, String reason, Throwable e) {
//     super(reason, e);
//     this.taskName = taskName;
//   }
// 
//   public MeasurementError(String taskName, Exception e) {
//     this(taskName, e.getMessage(), e);
//   }
// }


// Path: measures/src/main/java/io/apisense/network/ping/ICMPTask.java
import android.support.annotation.NonNull;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.apisense.network.Measurement;
import io.apisense.network.MeasurementError;

      if (matcher.matches()) {
        ip = matcher.group(1);
        latency = Float.valueOf(matcher.group(2)).longValue(); // milliseconds
      }

      matcher = PING_RESPONSE_RTT_SUCCESS.matcher(line);

      if (matcher.matches()) {
        float min = Float.valueOf(matcher.group(1));
        float avg = Float.valueOf(matcher.group(2));
        float max = Float.valueOf(matcher.group(3));
        float mdev = Float.valueOf(matcher.group(4));

        rtt = new Rtt(min, avg, max, mdev);

        return new ICMPResult(startTimeMs, endTime, config, hostname, ip, latency, currentTtl, rtt);
      }

      matcher = PING_RESPONSE_TIMEOUT.matcher(line);

      if (matcher.matches()) {
        throw new PINGException("Packet is lost");
      }
    }

    throw new PINGException("Could not parse response");
  }

  @Override
  @NonNull
  public ICMPResult execute() throws MeasurementError {