gt:                 if (campaignLengthThree > 0) {
context: /*
   * OM Simulation Tool: This tool intends to test and evaluate the scientific
   * robustness of the protocol `6+1`. Therefore, it generates a huge amount of
   * virtual measurement campaigns based on real radon concentration data
   * following the mentioned protocol. <http://github.com/donschoe/omsimulation>
   * 
   * Copyright (C) 2012 Alexander Schoedon <a.schoedon@student.htw-berlin.de>
   * 
   * This program is free software: you can redistribute it and/or modify it under
   * the terms of the GNU General Public License as published by the Free Software
   * Foundation, either version 3 of the License, or (at your option) any later
   * version.
   * 
   * This program is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
   * details.
   * 
   * You should have received a copy of the GNU General Public License along with
   * this program. If not, see <http://www.gnu.org/licenses/>.
   */
  
  package de.bfs.radon.omsimulation.gui;
  
  import java.awt.Color;
  import java.awt.Cursor;
  import java.awt.Font;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.awt.event.FocusAdapter;
  import java.awt.event.FocusEvent;
  import java.beans.PropertyChangeEvent;
  import java.beans.PropertyChangeListener;
  import java.io.BufferedWriter;
  import java.io.File;
  import java.io.FileWriter;
  import java.io.IOException;
  import java.text.DecimalFormat;
  import java.util.Random;
  
  import javax.swing.JButton;
  import javax.swing.JCheckBox;
  import javax.swing.JComboBox;
  import javax.swing.JFileChooser;
  import javax.swing.JLabel;
  import javax.swing.JOptionPane;
  import javax.swing.JPanel;
  import javax.swing.JProgressBar;
  import javax.swing.JRadioButton;
  import javax.swing.JSpinner;
  import javax.swing.JTabbedPane;
  import javax.swing.JTextField;
  import javax.swing.SpinnerNumberModel;
  import javax.swing.SwingWorker;
  import javax.swing.event.ChangeEvent;
  import javax.swing.event.ChangeListener;
  import javax.swing.filechooser.FileNameExtensionFilter;
  
  import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
  import org.apache.commons.math.stat.descriptive.SummaryStatistics;
  
  import com.db4o.Db4oEmbedded;
  import com.db4o.ObjectContainer;
  import com.db4o.ObjectSet;
  
  import de.bfs.radon.omsimulation.data.OMBuilding;
  import de.bfs.radon.omsimulation.data.OMCampaign;
  import de.bfs.radon.omsimulation.data.OMHelper;
  import de.bfs.radon.omsimulation.data.OMRoom;
  import de.bfs.radon.omsimulation.data.OMSimulation;
  
  /**
   * @author A. Schoedon
   */
  public class OMPanelSimulation extends JPanel implements ActionListener {
  
    /**
     * Unique serial version ID.
     */
    private static final long     serialVersionUID = -2584829845531323801L;
  
    /**
     * Stores the status of the simulation process. Used to update the progress
     * bar.
     */
    private int                   status;
  
    /**
     * Stores the current log message which will be both written to the log file
     * and displayed at the progress bar.
     */
    private String                logMsg;
  
    /**
     * Stores the selected building which is used to run simulations with.
     */
    private OMBuilding            selectedObject;
  
    /**
     * Stores the absolute path to the OMB object which will be used for
     * simulations.
     */
    private String                ombFile;
  
    /**
     * Stores the absolute path to the OMS object which will be used analysing the
     * results later on.
     */
    private String                omsFile;
  
    /**
     * Stores the OMS simulation object which is used for analysing results later.
     */
    private OMSimulation          omsObject;
  
    /**
     * Stores a custom name for the object defined by the user.
     */
    private String                projectName;
  
    /**
     * Indicates whether the current simulation is systematic or random.
     */
    private boolean               isSystematic;
  
    /**
     * Stores the number of how many random campaigns will be simulated.
     */
    private int                   randomCampaigns;
  
    /**
     * Stores the ratio of 3-of-6-rooms simulations.
     */
    private int                   ratio3;
  
    /**
     * Stores the ratio of 4-of-6-rooms simulations.
     */
    private int                   ratio4;
  
    /**
     * Stores the ratio of 5-of-6-rooms simulations.
     */
    private int                   ratio5;
  
    /**
     * Stores the ratio of 6-of-6-rooms simulations.
     */
    private int                   ratio6;
  
    /**
     * Stores the random noise factor.
     */
    private int                   randomNoise;
  
    /**
     * UI: Label "This could take a while!"
     */
    private JLabel                lblWarning;
  
    /**
     * UI: Label "Select Project"
     */
    private JLabel                lblSelectProject;
  
    /**
     * UI: Label "Simulation Type"
     */
    private JLabel                lblSimulationType;
  
    /**
     * UI: Label "campaigns"
     */
    private JLabel                lblCampaigns;
  
    /**
     * UI: Label "Ratio"
     */
    private JLabel                lblRatio;
  
    /**
     * UI: Label "%"
     */
    private JLabel                lblPercent;
  
    /**
     * UI: Label for first orientation, content: "Select an OMB-Object file to run
     * simulations. Limited random simulations can be saved as OMS-Simulation
     * files used for analysis."
     */
    private JLabel                lblHelp;
  
    /**
     * UI: Label "Select OMB-File"
     */
    private JLabel                lblSelectOmbfile;
  
    /**
     * UI: Label "Save OMS-File"
     */
    private JLabel                lblOmsFile;
  
    /**
     * UI: Text field to enter the absolute path to the OMB object file.
     */
    private JTextField            txtOmbFile;
  
    /**
     * UI: Text field to enter the absolute path to the OMS object file.
     */
    private JTextField            txtOmsFile;
  
    /**
     * UI: Button to load an OMB file to panel.
     */
    private JButton               btnRefresh;
  
    /**
     * UI: Button to start the simulation process.
     */
    private JButton               btnStart;
  
    /**
     * UI: Button to open a file browser to load an OMB file.
     */
    private JButton               btnBrowseOmb;
  
    /**
     * UI: Button to open a file browser to save an OMS file.
     */
    private JButton               btnBrowseOms;
  
    /**
     * UI: Spinner for integer values to set the total number of random campaigns.
     */
    private JSpinner              spnrRandomCampaigns;
  
    /**
     * UI: Spinner for integer values to set the 3-of-6-rooms ratio.
     */
    private JSpinner              spnrRatio3;
  
    /**
     * UI: Spinner for integer values to set the 3-of-6-rooms ratio.
     */
    private JSpinner              spnrRatio4;
  
    /**
     * UI: Spinner for integer values to set the 3-of-6-rooms ratio.
     */
    private JSpinner              spnrRatio5;
  
    /**
     * UI: Spinner for integer values to set the 3-of-6-rooms ratio.
     */
    private JSpinner              spnrRatio6;
  
    /**
     * UI: Spinner for integer values to set the random noise.
     */
    private JSpinner              spnrRandomNoise;
  
    /**
     * UI: Checkbox for activating the ratio for 3-of-6-rooms simulations.
     */
    private JCheckBox             chckbxRatio3;
  
    /**
     * UI: Checkbox for activating the ratio for 4-of-6-rooms simulations.
     */
    private JCheckBox             chckbxRatio4;
  
    /**
     * UI: Checkbox for activating the ratio for 5-of-6-rooms simulations.
     */
    private JCheckBox             chckbxRatio5;
  
    /**
     * UI: Checkbox for activating the ratio for 6-of-6-rooms simulations.
     */
    private JCheckBox             chckbxRatio6;
  
    /**
     * UI: Checkbox for activating the random noise.
     */
    private JCheckBox             chckbxRandomNoise;
  
    /**
     * UI: Combobox to display all loaded buildings.
     */
    private JComboBox<OMBuilding> comboBoxSelectProject;
  
    /**
     * UI: Radio button to select systematic simulations.
     */
    private JRadioButton          rdbtnSystematic;
  
    /**
     * UI: Radio button to select random simulations.
     */
    private JRadioButton          rdbtnRandom;
  
    /**
     * UI: Progress bar to display the simulation status and messages.
     */
    private JProgressBar          progressBarSimulation;
  
    /**
     * Stores the refreshing process task which will be executed in a separate
     * thread to ensure the UI wont freeze.
     */
    private Refresh               refreshTask;
  
    /**
     * Stores the simulation process task which will be executed in a separate
     * thread to ensure the UI wont freeze.
     */
    private Simulation            simulationTask;
  
    /**
     * Gets the absolute path to the OMB object which will be used for
     * simulations.
     * 
     * @return The absolute path to the OMB object.
     */
    public String getOmbFile() {
      return this.ombFile;
    }
  
    /**
     * Sets the absolute path to the OMB object which will be used for
     * simulations.
     * 
     * @param ombFile
     *          The absolute path to the OMB object.
     */
    public void setOmbFile(String ombFile) {
      this.ombFile = ombFile;
    }
  
    /**
     * Gets the absolute path to the OMS object which will be used analysing the
     * results later on.
     * 
     * @return The absolute path to the OMS object.
     */
    public String getOmsFile() {
      return this.omsFile;
    }
  
    /**
     * Sets the absolute path to the OMS object which will be used analysing the
     * results later on.
     * 
     * @param omsFile
     *          The absolute path to the OMS object.
     */
    public void setOmsFile(String omsFile) {
      this.omsFile = omsFile;
    }
  
    /**
     * Gets the OMS simulation object which is used for analysing results later.
     * 
     * @return The OMS simulation object.
     */
    public OMSimulation getOmsObject() {
      return this.omsObject;
    }
  
    /**
     * Sets the OMS simulation object which is used for analysing results later.
     * 
     * @param omsObject
     *          The OMS simulation object.
     */
    public void setOmsObject(OMSimulation omsObject) {
      this.omsObject = omsObject;
    }
  
    /**
     * Gets the selected building which is used to run simulations with.
     * 
     * @return The selected building.
     */
    public OMBuilding getSelectedObject() {
      return this.selectedObject;
    }
  
    /**
     * Sets the selected building which is used to run simulations with.
     * 
     * @param selectedObject
     *          The selected building.
     */
    public void setSelectedObject(OMBuilding selectedObject) {
      this.selectedObject = selectedObject;
    }
  
    /**
     * Gets a custom name for the object defined by the user.
     * 
     * @return A custom name for the object defined by the user.
     */
    public String getProjectName() {
      return this.projectName;
    }
  
    /**
     * Sets a custom name for the object.
     * 
     * @param projectName
     *          A custom name for the object.
     */
    public void setProjectName(String projectName) {
      this.projectName = projectName;
    }
  
    /**
     * Sets the indicator whether the current simulation is systematic or random.
     * 
     * @return True if the current simulation is systematic.
     */
    public boolean isSystematic() {
      return this.isSystematic;
    }
  
    /**
     * Gets the indicator whether the current simulation is systematic or random.
     * 
     * @param isSystematic
     *          True if the current simulation is systematic.
     */
    public void setSystematic(boolean isSystematic) {
      this.isSystematic = isSystematic;
    }
  
    /**
     * Gets the number of how many random campaigns will be simulated.
     * 
     * @return The number of how many random campaigns will be simulated.
     */
    public int getRandomCampaigns() {
      return this.randomCampaigns;
    }
  
    /**
     * Sets the number of how many random campaigns will be simulated.
     * 
     * @param randomCampaigns
     *          The number of how many random campaigns will be simulated.
     */
    public void setRandomCampaigns(int randomCampaigns) {
      this.randomCampaigns = randomCampaigns;
    }
  
    /**
     * Gets the ratio of 3-of-6-rooms simulations.
     * 
     * @return The ratio of 3-of-6-rooms simulations.
     */
    public int getRatio3() {
      return this.ratio3;
    }
  
    /**
     * Sets the ratio of 3-of-6-rooms simulations.
     * 
     * @param ratio3
     *          The ratio of 3-of-6-rooms simulations.
     */
    public void setRatio3(int ratio3) {
      this.ratio3 = ratio3;
    }
  
    /**
     * Gets the ratio of 4-of-6-rooms simulations.
     * 
     * @return The ratio of 4-of-6-rooms simulations.
     */
    public int getRatio4() {
      return this.ratio4;
    }
  
    /**
     * Sets the ratio of 4-of-6-rooms simulations.
     * 
     * @param ratio4
     *          The ratio of 4-of-6-rooms simulations.
     */
    public void setRatio4(int ratio4) {
      this.ratio4 = ratio4;
    }
  
    /**
     * Gets the ratio of 5-of-6-rooms simulations.
     * 
     * @return The ratio of 5-of-6-rooms simulations.
     */
    public int getRatio5() {
      return this.ratio5;
    }
  
    /**
     * Sets the ratio of 5-of-6-rooms simulations.
     * 
     * @param ratio5
     *          The ratio of 5-of-6-rooms simulations.
     */
    public void setRatio5(int ratio5) {
      this.ratio5 = ratio5;
    }
  
    /**
     * Gets the ratio of 6-of-6-rooms simulations.
     * 
     * @return The ratio of 6-of-6-rooms simulations.
     */
    public int getRatio6() {
      return this.ratio6;
    }
  
    /**
     * Sets the ratio of 6-of-6-rooms simulations.
     * 
     * @param ratio6
     *          The ratio of 6-of-6-rooms simulations.
     */
    public void setRatio6(int ratio6) {
      this.ratio6 = ratio6;
    }
  
    /**
     * Gets the random noise factor.
     * 
     * @return The random noise factor.
     */
    public int getRandomNoise() {
      return this.randomNoise;
    }
  
    /**
     * Sets the random noise factor.
     * 
     * @param randomNoise
     *          The random noise factor.
     */
    public void setRandomNoise(int randomNoise) {
      this.randomNoise = randomNoise;
    }
  
    /**
     * Gets the status of the simulation process. Used to update the progress bar.
     * 
     * @return The status of the simulation process in percent.
     */
    public int getStatus() {
      return this.status;
    }
  
    /**
     * Sets the status of the simulation process. Used to update the progress bar.
     * 
     * @param status
     *          The status of the simulation process in percent.
     */
    public void setStatus(int status) {
      this.status = status;
    }
  
    /**
     * Gets the current log message which will be both written to the log file and
     * displayed at the progress bar.
     * 
     * @return The current log message.
     */
    public String getLogMsg() {
      return this.logMsg;
    }
  
    /**
     * Sets the current log message which will be both written to the log file and
     * displayed at the progress bar.
     * 
     * @param logMsg
     *          The current log message.
     */
    public void setLogMsg(String logMsg) {
      this.logMsg = logMsg;
    }
  
    /**
     * Inner class Refresh used to create the refreshing process task which will
     * be executed in a separate thread to ensure the UI wont freeze.
     * 
     * @author A. Schoedon
     */
    class Refresh extends SwingWorker<Void, Void> {
  
      /**
       * Updates the progress bar status and message..
       * 
       * @param s
       *          The log message.
       * @param i
       *          The status in percent.
       */
      private void tmpUpdate(String s, int i) {
        setLogMsg(s);
        setStatus(i);
        progressBarSimulation.setString(s);
        progressBarSimulation.setValue(i);
        try {
          Thread.sleep(100);
        } catch (InterruptedException ie) {
          ie.printStackTrace();
        }
      }
  
      /**
       * Loads the object from the OMB file to the panel.
       * 
       * @see javax.swing.SwingWorker#doInBackground()
       */
      @Override
      public Void doInBackground() {
        tmpUpdate("Getting objects from file '" + getOmbFile() + "'.", 1);
        ObjectContainer db4o = Db4oEmbedded.openFile(
            Db4oEmbedded.newConfiguration(), getOmbFile());
        ObjectSet<OMBuilding> result = db4o.queryByExample(OMBuilding.class);
        OMBuilding found;
        tmpUpdate("Refreshing list... ", 2);
        tmpUpdate("Adding items... ", 3);
        for (int i = 0; i < result.size(); i++) {
          double perc = (double) i / (double) result.size() * 100.0 + 3.0;
          while (perc > 99) {
            perc--;
          }
          found = (OMBuilding) result.next();
          comboBoxSelectProject.addItem(found);
          tmpUpdate("Added: " + found.getName(), (int) perc);
        }
        tmpUpdate("Finished. ", 100);
        db4o.close();
        return null;
      }
  
      /**
       * Executed in event dispatching thread after finishing the refresh task,
       * updates the interface.
       * 
       * @see javax.swing.SwingWorker#done()
       */
      @Override
      public void done() {
        btnRefresh.setEnabled(true);
        comboBoxSelectProject.setEnabled(true);
        tmpUpdate(" ", 0);
        progressBarSimulation.setStringPainted(false);
        progressBarSimulation.setIndeterminate(false);
        progressBarSimulation.setValue(0);
        progressBarSimulation.setVisible(false);
        setCursor(null);
      }
    }
  
    /**
     * The inner class Simulation used to create the simulation process task which
     * will be executed in a separate thread to ensure the UI wont freeze.
     * 
     * @author A. Schoedon
     */
    class Simulation extends SwingWorker<Void, Void> {
  
      /**
       * Stores the starting timestamp of the simulation to calculate the status
       * and remaining time later.
       */
      private double start;
  
      /**
       * Gets the starting timestamp of the simulation.
       * 
       * @return The starting timestamp of the simulation.
       */
      public double getStart() {
        return start;
      }
  
      /**
       * Sets the starting timestamp of the simulation to calculate the status and
       * remaining time later.
       * 
       * @param start
       *          The starting timestamp of the simulation.
       */
      public void setStart(double start) {
        this.start = start;
      }
  
      /**
       * Updates the progress bar status and message and writes the current action
       * to a log file if existing.
       * 
       * @param s
       *          The log message.
       * @param i
       *          The status in percent.
       */
      private void tmpUpdate(String s, int i) {
        setLogMsg(s);
        setStatus(i);
        progressBarSimulation.setString(s);
        progressBarSimulation.setValue(i);
        try {
          if (OMHelper.isLogOutputEnabled()) {
            OMHelper.writeLog(getLogMsg());
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
  
      /**
       * Writes messages to the log file which are not displayed at the progress
       * bar. This is used to increase performance.
       * 
       * @param s
       *          The log message.
       * @param i
       *          The status in percent.
       */
      private void logOnly(String s, int i) {
        setLogMsg(s);
        setStatus(i);
        try {
          if (OMHelper.isLogOutputEnabled()) {
            OMHelper.writeLog(getLogMsg());
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
  
      /**
       * Starts the main simulation task which is executed in background thread.
       * 
       * @see javax.swing.SwingWorker#doInBackground()
       */
      @Override
      public Void doInBackground() {
        try {
          int status = 0;
          setStart(System.currentTimeMillis());
          String logPath = getOmsFile();
          String logType = "random_simulation";
          if (isSystematic) {
            logPath = getOmbFile();
            logType = "systematic_simulation";
          }
          OMHelper.setLogOutput(logPath, logType);
          tmpUpdate("Starting ...", 1);
          OMBuilding building = getSelectedObject();
          tmpUpdate("Opened building: " + building, 1);
          int maxCampaigns = getRandomCampaigns();
          int ratioThree = getRatio3();
          int ratioFour = getRatio4();
          int ratioFive = getRatio5();
          int ratioSix = getRatio6();
          int randomNoise = getRandomNoise();
          if (isSystematic()) {
            generateSystematicCampaigns(building, randomNoise);
          } else {
            generateRandomCampaigns(building, maxCampaigns, ratioThree,
                ratioFour, ratioFive, ratioSix, randomNoise);
          }
          status = getStatus();
          String strFormat = "#.##";
          DecimalFormat decFormat = new DecimalFormat(strFormat);
          double total = (System.currentTimeMillis() - getStart()) / 1000;
          String unit = " seconds.";
          if (total > 100) {
            total = total / 60.0;
            unit = " minutes.";
            if (total > 100) {
              total = total / 60.0;
              unit = " hours.";
            }
          }
          if (status == 100) {
            tmpUpdate("Simulation finished after " + decFormat.format(total)
                + unit, status);
            JOptionPane.showMessageDialog(null, "Simulation finished after "
                + decFormat.format(total) + unit, "Success",
                JOptionPane.INFORMATION_MESSAGE);
          } else {
            tmpUpdate("Simulation failed. See log for details.", status);
            JOptionPane.showMessageDialog(null,
                "Simulation failed. See log for details.", "Failed",
                JOptionPane.ERROR_MESSAGE);
          }
          OMHelper.closeLog();
        } catch (IOException ioe) {
          tmpUpdate("Error: " + ioe.getMessage(), 0);
          tmpUpdate("Error: Completely Failed.", 0);
          JOptionPane.showMessageDialog(null,
              "Completely failed.\n" + ioe.getMessage(), "Error",
              JOptionPane.ERROR_MESSAGE);
          ioe.printStackTrace();
        }
        return null;
      }
  
      /**
       * Method to simulate systematic survey campaigns. It calculates summary
       * statistics for simulations with n > 1 million and descriptive statistics
       * for simulations with n <= 1 million. It writes a CSV file with the
       * results of the statistics in the end. This may take a while, grab a
       * coffee.
       * 
       * @param building
       *          An building consisting of all the rooms and their values.
       * @param randomNoise
       *          An integer which defines the random noise that is added to the
       *          values. A random noise of 0 means the original values wont be
       *          modified. The unit is [%].
       * @throws IOException
       *           If creating log file or writing logs fails.
       */
      private void generateSystematicCampaigns(OMBuilding building,
          int randomNoise) throws IOException {
        int valueCount = building.getValueCount();
        int total = valueCount - 7 * 24 + 1;
        if (total >= 1) {
          tmpUpdate(valueCount + " data records allow " + total
              + " possible times for starting a simulation.", 1);
          OMRoom[] variationSchemeSix[] = building.getVariationSchemeSix();
          OMRoom[] variationSchemeFive[] = building.getVariationSchemeFive();
          OMRoom[] variationSchemeFour[] = building.getVariationSchemeFour();
          OMRoom[] variationSchemeThree[] = building.getVariationSchemeThree();
          long x = 0;
          int campaignLengthSix = variationSchemeSix.length;
          int campaignLengthFive = variationSchemeFive.length;
          int campaignLengthFour = variationSchemeFour.length;
          int campaignLengthThree = variationSchemeThree.length;
          long perc = 1;
          OMCampaign campaign;
          SummaryStatistics roomAmSummaryStats = new SummaryStatistics();
          SummaryStatistics cellarAmSummaryStats = new SummaryStatistics();
          SummaryStatistics roomGmSummaryStats = new SummaryStatistics();
          SummaryStatistics cellarGmSummaryStats = new SummaryStatistics();
          SummaryStatistics roomMedSummaryStats = new SummaryStatistics();
          SummaryStatistics cellarMedSummaryStats = new SummaryStatistics();
          SummaryStatistics roomMaxSummaryStats = new SummaryStatistics();
          SummaryStatistics cellarMaxSummaryStats = new SummaryStatistics();
          DescriptiveStatistics roomAmDescriptiveStats = new DescriptiveStatistics();
          DescriptiveStatistics cellarAmDescriptiveStats = new DescriptiveStatistics();
          DescriptiveStatistics roomGmDescriptiveStats = new DescriptiveStatistics();
          DescriptiveStatistics cellarGmDescriptiveStats = new DescriptiveStatistics();
          DescriptiveStatistics roomMedDescriptiveStats = new DescriptiveStatistics();
          DescriptiveStatistics cellarMedDescriptiveStats = new DescriptiveStatistics();
          DescriptiveStatistics roomMaxDescriptiveStats = new DescriptiveStatistics();
          DescriptiveStatistics cellarMaxDescriptiveStats = new DescriptiveStatistics();
          boolean isDescriptive = false;
          long max = 0;
          if (campaignLengthSix > 0) {
            max = total * campaignLengthSix;
          } else {
            if (campaignLengthFive > 0) {
              max = total * campaignLengthFive;
            } else {
              if (campaignLengthFour > 0) {
                max = total * campaignLengthFour;
              } else {
                if (campaignLengthThree > 0) {
                  max = total * campaignLengthThree;
                } else {
                  max = 0;
                }
              }
            }
          }
          String totalCsvPath = getOmbFile()
              + "_systematic_simulation.campaigns.csv";
          File totalCsvFile = new File(totalCsvPath);
          FileWriter totalCsvWriter = new FileWriter(totalCsvFile);
          BufferedWriter totalCsvOutput = new BufferedWriter(totalCsvWriter);
          String strFormat = "#.#########";
          DecimalFormat decFormat = new DecimalFormat(strFormat);
          totalCsvOutput
              .write("\"ID\";\"CAMPAIGN\";\"START\";\"R_AM\";\"R_GM\";\"R_MED\";\"R_MAX\";\"C_AM\";\"C_GM\";\"C_MED\";\"C_MAX\"");
          totalCsvOutput.newLine();
          if (max <= 1000000) {
            isDescriptive = true;
            if (campaignLengthSix > 0) {
              tmpUpdate(
                  "Starting unlimited descriptive simulation for 6 different rooms.",
                  1);
              for (int a = 0; a < campaignLengthSix; a++) {
                perc = (x * 100) / max;
                tmpUpdate("Status: " + perc + "% (Estimated time left: "
                    + timeLeft(((double) x * 100.00) / (double) max) + ")",
                    (int) perc);
                for (int start = 0; start < total; start++) {
                  campaign = new OMCampaign(start, variationSchemeSix[a],
                      randomNoise);
                  roomAmDescriptiveStats.addValue(campaign.getRoomAverage());
                  cellarAmDescriptiveStats.addValue(campaign.getCellarAverage());
                  roomGmDescriptiveStats.addValue(campaign.getRoomLogAverage());
                  cellarGmDescriptiveStats.addValue(campaign
                      .getCellarLogAverage());
                  roomMedDescriptiveStats.addValue(campaign.getRoomMedian());
                  cellarMedDescriptiveStats.addValue(campaign.getCellarMedian());
                  roomMaxDescriptiveStats.addValue(campaign.getRoomMaximum());
                  cellarMaxDescriptiveStats.addValue(campaign.getCellarMaximum());
                  logOnly("Campaign: T=" + campaign.getStart() + ", R="
                      + campaign.getVariation(), (int) perc);
                  totalCsvOutput.write("\"" + x + "\";\""
                      + campaign.getVariation() + "\";\"" + campaign.getStart()
                      + "\";\"" + (int) campaign.getRoomAverage() + "\";\""
                      + (int) campaign.getRoomLogAverage() + "\";\""
                      + (int) campaign.getRoomMedian() + "\";\""
                      + (int) campaign.getRoomMaximum() + "\";\""
                      + (int) campaign.getCellarAverage() + "\";\""
                      + (int) campaign.getCellarLogAverage() + "\";\""
                      + (int) campaign.getCellarMedian() + "\";\""
                      + (int) campaign.getCellarMaximum() + "\"");
                  totalCsvOutput.newLine();
                  x++;
                }
              }
              perc = (x * 100) / max;
              tmpUpdate(
                  "Status: " + perc + "% - finished for 6 different rooms.",
                  (int) perc);
            } else {
              tmpUpdate(
                  "Warning: No variations for 6 different rooms available.",
                  (int) perc);
              if (campaignLengthFive > 0) {
                tmpUpdate(
                    "Starting unlimited descriptive simulation for 5 different rooms.",
                    (int) perc);
                for (int a = 0; a < campaignLengthFive; a++) {
                  perc = (x * 100) / max;
                  tmpUpdate("Status: " + perc + "% (Estimated time left: "
                      + timeLeft(((double) x * 100.00) / (double) max) + ")",
                      (int) perc);
                  for (int start = 0; start < total; start++) {
                    campaign = new OMCampaign(start, variationSchemeFive[a],
                        randomNoise);
                    roomAmDescriptiveStats.addValue(campaign.getRoomAverage());
                    cellarAmDescriptiveStats
                        .addValue(campaign.getCellarAverage());
                    roomGmDescriptiveStats.addValue(campaign.getRoomLogAverage());
                    cellarGmDescriptiveStats.addValue(campaign
                        .getCellarLogAverage());
                    roomMedDescriptiveStats.addValue(campaign.getRoomMedian());
                    cellarMedDescriptiveStats
                        .addValue(campaign.getCellarMedian());
                    roomMaxDescriptiveStats.addValue(campaign.getRoomMaximum());
                    cellarMaxDescriptiveStats.addValue(campaign
                        .getCellarMaximum());
                    logOnly("Campaign: T=" + campaign.getStart() + ", R="
                        + campaign.getVariation(), (int) perc);
                    totalCsvOutput.write("\"" + x + "\";\""
                        + campaign.getVariation() + "\";\"" + campaign.getStart()
                        + "\";\"" + (int) campaign.getRoomAverage() + "\";\""
                        + (int) campaign.getRoomLogAverage() + "\";\""
                        + (int) campaign.getRoomMedian() + "\";\""
                        + (int) campaign.getRoomMaximum() + "\";\""
                        + (int) campaign.getCellarAverage() + "\";\""
                        + (int) campaign.getCellarLogAverage() + "\";\""
                        + (int) campaign.getCellarMedian() + "\";\""
                        + (int) campaign.getCellarMaximum() + "\"");
                    totalCsvOutput.newLine();
                    x++;
                  }
                }
                perc = (x * 100) / max;
                tmpUpdate("Status: " + perc
                    + "% - finished for 5 different rooms.", (int) perc);
              } else {
                tmpUpdate(
                    "Warning: No variations for 5 different rooms available.",
                    (int) perc);
                if (campaignLengthFour > 0) {
                  tmpUpdate(
                      "Starting unlimited descriptive simulation for 4 different rooms.",
                      (int) perc);
                  for (int a = 0; a < campaignLengthFour; a++) {
                    perc = (x * 100) / max;
                    tmpUpdate("Status: " + perc + "% (Estimated time left: "
                        + timeLeft(((double) x * 100.00) / (double) max) + ")",
                        (int) perc);
                    for (int start = 0; start < total; start++) {
                      campaign = new OMCampaign(start, variationSchemeFour[a],
                          randomNoise);
                      roomAmDescriptiveStats.addValue(campaign.getRoomAverage());
                      cellarAmDescriptiveStats.addValue(campaign
                          .getCellarAverage());
                      roomGmDescriptiveStats.addValue(campaign
                          .getRoomLogAverage());
                      cellarGmDescriptiveStats.addValue(campaign
                          .getCellarLogAverage());
                      roomMedDescriptiveStats.addValue(campaign.getRoomMedian());
                      cellarMedDescriptiveStats.addValue(campaign
                          .getCellarMedian());
                      roomMaxDescriptiveStats.addValue(campaign.getRoomMaximum());
                      cellarMaxDescriptiveStats.addValue(campaign
                          .getCellarMaximum());
                      logOnly("Campaign: T=" + campaign.getStart() + ", R="
                          + campaign.getVariation(), (int) perc);
                      totalCsvOutput.write("\"" + x + "\";\""
                          + campaign.getVariation() + "\";\""
                          + campaign.getStart() + "\";\""
                          + (int) campaign.getRoomAverage() + "\";\""
                          + (int) campaign.getRoomLogAverage() + "\";\""
                          + (int) campaign.getRoomMedian() + "\";\""
                          + (int) campaign.getRoomMaximum() + "\";\""
                          + (int) campaign.getCellarAverage() + "\";\""
                          + (int) campaign.getCellarLogAverage() + "\";\""
                          + (int) campaign.getCellarMedian() + "\";\""
                          + (int) campaign.getCellarMaximum() + "\"");
                      totalCsvOutput.newLine();
                      x++;
                    }
                  }
                  perc = (x * 100) / max;
                  tmpUpdate("Status: " + perc
                      + "% - finished for 4 different rooms.", (int) perc);
                } else {
                  tmpUpdate(
                      "Warning: No variations for 4 different rooms available.",
                      (int) perc);
                  if (campaignLengthThree > 0) {
                    tmpUpdate(
                        "Starting unlimited descriptive simulation for 3 different rooms.",
                        (int) perc);
                    for (int a = 0; a < campaignLengthThree; a++) {
                      perc = (x * 100) / max;
                      tmpUpdate("Status: " + perc + "% (Estimated time left: "
                          + timeLeft(((double) x * 100.00) / (double) max) + ")",
                          (int) perc);
                      for (int start = 0; start < total; start++) {
                        campaign = new OMCampaign(start, variationSchemeThree[a],
                            randomNoise);
                        roomAmDescriptiveStats
                            .addValue(campaign.getRoomAverage());
                        cellarAmDescriptiveStats.addValue(campaign
                            .getCellarAverage());
                        roomGmDescriptiveStats.addValue(campaign
                            .getRoomLogAverage());
                        cellarGmDescriptiveStats.addValue(campaign
                            .getCellarLogAverage());
                        roomMedDescriptiveStats
                            .addValue(campaign.getRoomMedian());
                        cellarMedDescriptiveStats.addValue(campaign
                            .getCellarMedian());
                        roomMaxDescriptiveStats.addValue(campaign
                            .getRoomMaximum());
                        cellarMaxDescriptiveStats.addValue(campaign
                            .getCellarMaximum());
                        logOnly("Campaign: T=" + campaign.getStart() + ", R="
                            + campaign.getVariation(), (int) perc);
                        totalCsvOutput.write("\"" + x + "\";\""
                            + campaign.getVariation() + "\";\""
                            + campaign.getStart() + "\";\""
                            + (int) campaign.getRoomAverage() + "\";\""
                            + (int) campaign.getRoomLogAverage() + "\";\""
                            + (int) campaign.getRoomMedian() + "\";\""
                            + (int) campaign.getRoomMaximum() + "\";\""
                            + (int) campaign.getCellarAverage() + "\";\""
                            + (int) campaign.getCellarLogAverage() + "\";\""
                            + (int) campaign.getCellarMedian() + "\";\""
                            + (int) campaign.getCellarMaximum() + "\"");
                        totalCsvOutput.newLine();
                        x++;
                      }
                    }
                    perc = (x * 100) / max;
                    tmpUpdate("Status: " + perc
                        + "% - finished for 3 different rooms.", (int) perc);
                  } else {
                    tmpUpdate(
                        "Warning: No variations for 3 different rooms available.",
                        (int) perc);
                    tmpUpdate(
                        "Error: No variations generated yet, something went wrong.",
                        0);
                  }
                }
              }
            }
          } else {
            isDescriptive = false;
            if (campaignLengthSix > 0) {
              tmpUpdate(
                  "Starting unlimited summary simulation for 6 different rooms.",
                  (int) perc);
              for (int a = 0; a < campaignLengthSix; a++) {
                perc = (x * 100) / max;
                tmpUpdate("Status: " + perc + "% (Estimated time left: "
                    + timeLeft(((double) x * 100.00) / (double) max) + ")",
                    (int) perc);
                for (int start = 0; start < total; start++) {
                  campaign = new OMCampaign(start, variationSchemeSix[a],
                      randomNoise);
                  roomAmSummaryStats.addValue(campaign.getRoomAverage());
                  cellarAmSummaryStats.addValue(campaign.getCellarAverage());
                  roomGmSummaryStats.addValue(campaign.getRoomLogAverage());
                  cellarGmSummaryStats.addValue(campaign.getCellarLogAverage());
                  roomMedSummaryStats.addValue(campaign.getRoomMedian());
                  cellarMedSummaryStats.addValue(campaign.getCellarMedian());
                  roomMaxSummaryStats.addValue(campaign.getRoomMaximum());
                  cellarMaxSummaryStats.addValue(campaign.getCellarMaximum());
                  logOnly("Campaign: T=" + campaign.getStart() + ", R="
                      + campaign.getVariation(), (int) perc);
                  totalCsvOutput.write("\"" + x + "\";\""
                      + campaign.getVariation() + "\";\"" + campaign.getStart()
                      + "\";\"" + (int) campaign.getRoomAverage() + "\";\""
                      + (int) campaign.getRoomLogAverage() + "\";\""
                      + (int) campaign.getRoomMedian() + "\";\""
                      + (int) campaign.getRoomMaximum() + "\";\""
                      + (int) campaign.getCellarAverage() + "\";\""
                      + (int) campaign.getCellarLogAverage() + "\";\""
                      + (int) campaign.getCellarMedian() + "\";\""
                      + (int) campaign.getCellarMaximum() + "\"");
                  totalCsvOutput.newLine();
                  x++;
                }
              }
              perc = (x * 100) / max;
              tmpUpdate(
                  "Status: " + perc + "% - finished for 6 different rooms.",
                  (int) perc);
            } else {
              tmpUpdate(
                  "Warning: No variations for 6 different rooms available.",
                  (int) perc);
              if (campaignLengthFive > 0) {
                tmpUpdate(
                    "Starting unlimited summary simulation for 5 different rooms.",
                    (int) perc);
                for (int a = 0; a < campaignLengthFive; a++) {
                  perc = (x * 100) / max;
                  tmpUpdate("Status: " + perc + "% (Estimated time left: "
                      + timeLeft(((double) x * 100.00) / (double) max) + ")",
                      (int) perc);
                  for (int start = 0; start < total; start++) {
                    campaign = new OMCampaign(start, variationSchemeFive[a],
                        randomNoise);
                    roomAmSummaryStats.addValue(campaign.getRoomAverage());
                    cellarAmSummaryStats.addValue(campaign.getCellarAverage());
                    roomGmSummaryStats.addValue(campaign.getRoomLogAverage());
                    cellarGmSummaryStats.addValue(campaign.getCellarLogAverage());
                    roomMedSummaryStats.addValue(campaign.getRoomMedian());
                    cellarMedSummaryStats.addValue(campaign.getCellarMedian());
                    roomMaxSummaryStats.addValue(campaign.getRoomMaximum());
                    cellarMaxSummaryStats.addValue(campaign.getCellarMaximum());
                    logOnly("Campaign: T=" + campaign.getStart() + ", R="
                        + campaign.getVariation(), (int) perc);
                    totalCsvOutput.write("\"" + x + "\";\""
                        + campaign.getVariation() + "\";\"" + campaign.getStart()
                        + "\";\"" + (int) campaign.getRoomAverage() + "\";\""
                        + (int) campaign.getRoomLogAverage() + "\";\""
                        + (int) campaign.getRoomMedian() + "\";\""
                        + (int) campaign.getRoomMaximum() + "\";\""
                        + (int) campaign.getCellarAverage() + "\";\""
                        + (int) campaign.getCellarLogAverage() + "\";\""
                        + (int) campaign.getCellarMedian() + "\";\""
                        + (int) campaign.getCellarMaximum() + "\"");
                    totalCsvOutput.newLine();
                    x++;
                  }
                }
                perc = (x * 100) / max;
                tmpUpdate("Status: " + perc
                    + "% - finished for 5 different rooms.", (int) perc);
              } else {
                tmpUpdate(
                    "Warning: No variations for 5 different rooms available.",
                    (int) perc);
                if (campaignLengthFour > 0) {
                  tmpUpdate(
                      "Starting unlimited summary simulation for 4 different rooms.",
                      (int) perc);
                  for (int a = 0; a < campaignLengthFour; a++) {
                    perc = (x * 100) / max;
                    tmpUpdate("Status: " + perc + "% (Estimated time left: "
                        + timeLeft(((double) x * 100.00) / (double) max) + ")",
                        (int) perc);
                    for (int start = 0; start < total; start++) {
                      campaign = new OMCampaign(start, variationSchemeFour[a],
                          randomNoise);
                      roomAmSummaryStats.addValue(campaign.getRoomAverage());
                      cellarAmSummaryStats.addValue(campaign.getCellarAverage());
                      roomGmSummaryStats.addValue(campaign.getRoomLogAverage());
                      cellarGmSummaryStats.addValue(campaign
                          .getCellarLogAverage());
                      roomMedSummaryStats.addValue(campaign.getRoomMedian());
                      cellarMedSummaryStats.addValue(campaign.getCellarMedian());
                      roomMaxSummaryStats.addValue(campaign.getRoomMaximum());
                      cellarMaxSummaryStats.addValue(campaign.getCellarMaximum());
                      logOnly("Campaign: T=" + campaign.getStart() + ", R="
                          + campaign.getVariation(), (int) perc);
                      totalCsvOutput.write("\"" + x + "\";\""
                          + campaign.getVariation() + "\";\""
                          + campaign.getStart() + "\";\""
                          + (int) campaign.getRoomAverage() + "\";\""
                          + (int) campaign.getRoomLogAverage() + "\";\""
                          + (int) campaign.getRoomMedian() + "\";\""
                          + (int) campaign.getRoomMaximum() + "\";\""
                          + (int) campaign.getCellarAverage() + "\";\""
                          + (int) campaign.getCellarLogAverage() + "\";\""
                          + (int) campaign.getCellarMedian() + "\";\""
                          + (int) campaign.getCellarMaximum() + "\"");
                      totalCsvOutput.newLine();
                      x++;
                    }
                  }
                  perc = (x * 100) / max;
                  tmpUpdate("Status: " + perc
                      + "% - finished for 4 different rooms.", (int) perc);
                } else {
                  tmpUpdate(
                      "Warning: No variations for 4 different rooms available.",
                      (int) perc);
  