@Override
  public void newCricketData(CricketData cd) {
    if (!cd.getConnection()) return;

    boolean recognized = true;
    String id = cd.getCricketID();
    PlayerPoint3d coord = cricketPositions.get(id);
    if (coord == null) {
      recognized = false;
      Logger.log("New Cricket Data from " + id + ", unrecognized CricketID.");
      return;
    }

    double x = coord.getPx();
    double y = coord.getPy();
    double z = coord.getPz();

    if (!beaconReadings.containsKey(id)) { // is the first time reading from this beacon
      Logger.logDbg(
          "Found Cricket Mote "
              + (recognized ? ("at (" + x + "," + y + "),") : "with unrecognized")
              + " ID="
              + id);
    }

    double dist = (double) (cd.getDistance() / 100); // convert distance from cm to meters
    beaconReadings.put(
        id,
        new CricketBeaconReading(
            System.currentTimeMillis(),
            x,
            y,
            z,
            dist)); // pythagorean theorem to find distance along ground
  }
 /** Stops the CricketDataBuffer. Allows the thread that reads Cricket data to terminate. */
 public synchronized void stop() {
   if (running) {
     Logger.log("stopping...");
     cricketIface.deregisterCricketDataListener(this);
     running = false;
   } else Logger.log("already stopped...");
 }
 /** Starts the CricketDataBuffer. Creates a thread for reading cricket data. */
 public synchronized void start() {
   if (!running) {
     Logger.log("starting...");
     running = true;
     cricketIface.registerCricketDataListener(this);
     //			new Thread(this).start();
   } else Logger.log("already started...");
 }
  /**
   * Reads a file with cricket beacons IDs and coordinates in order to associate each beacon with
   * its location instead of ID
   *
   * @param fileName the file to read, default is "cricketBeacons.txt"
   * @return a map of key-value pairs, where the key is the Cricket beacon ID and the value is the
   *     3-d coordinate of the beacon
   */
  private HashMap<String, PlayerPoint3d> readCricketFile(String fileName) {
    File f = new File(fileName);
    if (!f.exists()) {
      Logger.logErr(
          "Could not find Cricket beacons file: "
              + fileName
              + ", using cricketBeacons.txt instead.");
      fileName = "cricketBeacons.txt";
    }

    HashMap<String, PlayerPoint3d> beacons = new HashMap<String, PlayerPoint3d>();
    try {
      Scanner sc = new Scanner(new BufferedReader(new FileReader(fileName)));
      while (sc.hasNextLine()) {
        String cricketId = sc.next();
        if (cricketId.contains("//")
            || cricketId.contains("/*")
            || cricketId.contains("#")
            || cricketId.contains(";")) {
          // we've reached a commented line in the file
          sc.nextLine(); // skip this line
          continue;
        }
        PlayerPoint3d coords = new PlayerPoint3d();
        coords.setPx(sc.nextDouble());
        coords.setPy(sc.nextDouble());
        coords.setPz(sc.nextDouble());
        sc.nextLine(); // consume the rest of the line
        // store to hashmap entry
        beacons.put(cricketId, coords);
        Logger.logDbg(
            "Cricket Mote "
                + cricketId
                + " has coords: ("
                + coords.getPx()
                + ","
                + coords.getPy()
                + ","
                + coords.getPz()
                + ")");
      }
    } catch (FileNotFoundException e) {
      Logger.logErr("Could not find Cricket beacons file: " + fileName);
      e.printStackTrace();
    } catch (InputMismatchException e) {
      Logger.logErr("Error reading Cricket beacons file: " + fileName + ", bad input format.");
      e.printStackTrace();
    } catch (NoSuchElementException e) {
    }

    return beacons;
  }
  /** Currently does nothing */
  public void run() {
    Logger.log("thread starting...");
    while (running) {

      try {
        synchronized (this) {
          wait(CRICKET_BUFFER_REFRESH_PERIOD);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    Logger.log("thread terminating...");
  }
  @Override
  public void run() {
    // Wait until it's time to start.

    Logger.logDbg("Pausing for " + waitTime + " milliseconds");
    if (waitTime != 0) {
      synchronized (this) {
        try {
          this.wait(waitTime);
        } catch (InterruptedException e) {
          e.printStackTrace();
          Logger.logWarn("Interrupted while waiting. + " + e.getLocalizedMessage());
        }
      }
    }

    isDone = true;
    Logger.log("Behavior " + getName() + " done.");
  }