/** This function is called when all runs are done */
  void stop() {
    dataLayerSaver.clear();
    Coordinator.getInstance().getDataReceiver().removeDataConsumer(dataLayerSaver.getFilter());

    if (goodParameters != null) {
      if (log != null) {
        log.println();
        log.print(goodCounter);
        log.print(',');
        log.print(goodRepetition);
        log.print(',');
        log.print(error);
        log.print(',');
        log.println(goodParameters.getVariableValues());
        log.flush();
      }
    }

    if (log != null) {
      log.close();
      log = null;
    }
  }
  /**
   * Saves collected data, begins a new simulation step, and return the number of ticks for the new
   * step. If ticks number == 0, then end the batch process.
   *
   * @return
   */
  public synchronized long nextStep(DataSet dataSet) {
    // Save data
    if (saveDataFlag) {
      saveData();
    }

    // Save snapshots
    if (saveFinalSnapshots) {
      for (Render render : Coordinator.getInstance().getRenders()) {
        render.takeSnapshot("" + counter + "-" + repetition + "-");
      }
    }

    // Analyze data
    if (dataAnalyzer != null && dataSet != null) {
      double err = dataAnalyzer.analyze(dataSet, variableName);

      if (log != null) {
        log.print(counter);
        log.print(',');
        log.print(repetition);
        log.print(',');
        log.print(err);
        log.print(',');
        log.println(currentParameters.getVariableValues());
        log.flush();
      }

      if (err < error) {
        error = err;
        goodCounter = counter;
        goodRepetition = repetition;
        goodParameters = currentParameters;
      }
    }

    if (dataSet != null) {
      dataSet.clear();
    }

    dataLayerSaver.clear();

    repetition++;
    if (repetition >= numberOfRepetition) {
      if (parameterSweep != null) {
        if (!parameterSweep.setCurrentValuesAndAdvance()) {
          stop();
          return 0;
        }

        repetition = 0;
        counter++;
      } else {
        stop();
        return 0;
      }
    }

    currentParameters = VariableSetFactory.createVariableSet("batch@run@current@set");
    currentParameters.synchronizeWithParameters(Coordinator.getInstance().getParameters());

    for (Render render : Coordinator.getInstance().getRenders()) {
      render.setSnapshotNamePrefix("" + counter + "-" + repetition + "-");
    }

    dataLayerSaver.setFileNamePrefix("" + counter + "-" + repetition + "-");

    return numberOfTicks;
  }