package brn.sim.scenario.txdor;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;

import brn.distsim.ormapper.util.DBSaver;
import brn.distsim.ormapper.util.DbBinaryLoader;
import brn.sim.builder.MacBuilder;
import brn.sim.builder.MetricBuilder;
import brn.sim.builder.RadioBuilder;
import brn.sim.builder.RateBuilder;
import brn.sim.builder.RouteBuilder;
import brn.sim.builder.FieldBuilder.FieldParams;
import brn.sim.builder.MacBuilder.M802_11Params;
import brn.sim.builder.MacBuilder.M802_11TxDivParams;
import brn.sim.builder.MetricBuilder.EtxParams;
import brn.sim.builder.PathLossBuilder.DistShadowingParams;
import brn.sim.builder.RadioBuilder.NoiseParams;
import brn.sim.builder.RateBuilder.ConstantParams;
import brn.sim.builder.RouteBuilder.BrnDsrParams;
import brn.sim.builder.RouteBuilder.TxDORParams;
import brn.sim.data.DiagramData;
import brn.sim.data.DiagramDataHist;
import brn.sim.data.FlowStats;
import brn.sim.data.MacStats;
import brn.sim.data.PropertiesData;

import jist.runtime.Util;
import jist.swans.Constants;

public class SingleFlow extends TxDOrSim {
  
  public static void main(String[] args) throws Throwable {
    SingleFlow test = new SingleFlow();
    test.run(args);
  }

  public static class SimulationResult {
    public String driver;
    public String version;
    public int simulationId;

    public int seed;
    public int nodes;
    public double shadowStdDev;
    public int csSize;
//    public int globFwdTable;
    public int useRts;
//    public int dataTxDiv;
//    public int ignoreRtsCtsNav;
//    public int useAckCancelation;
//    public int metricDelta;
    public int csSelection;
    public int dataRate;
    public int controlRate;
    public String metric;
//    public int promiscStorePackets;
//    public int noCandSets;
//    public int scaleRemainingHops;

    public double avgThroughput;
    /** ratio relative to the corresponding traditional transmission run */
    public double avgThroughputRatio;
    /** ratio relative to the corresponding traditional transmission run w/o rts */
    public double avgNonRtsThroughputRatio;
    public double avgDelay;
    public double avgDelayRatio;
    public double avgNonRtsDelayRatio;
    public int sendPackets;
    public int recvPackets;
    public double flowEnd;
    public double avgHopCount;

    public double radAvgDelaySpread;
    public double radAvgPowerDelta;
    public int radTxDivCount;

    public int macDrops;
    public int macDuplicates;
    public double macBackoffCuml;
    public int macShortRetries;
    public int macLongRetries;
    public int macCanceledAcks;
    public int macSendImmediate;
    public MacStats macStats;

    public int rtgDuplicate;
    public int rtgDrops;
  }

  public void evalSimulationResults(String dbUrl, String dbUser, String dbPasswd,
      String driver, String version,
      String dbResUrl, String dbResUser, String dbResPasswd) throws Throwable {
    DbBinaryLoader loader = new DbBinaryLoader(dbUrl, dbUser, dbPasswd);
    List lstIds = loader.loadSimulationIds(driver, version);
    DBSaver saver = new DBSaver(dbResUrl, dbResUser, dbResPasswd,
        dbResUrl, dbResUser, dbResPasswd);

    List results = new LinkedList();
    if (null == lstIds || lstIds.size() <= 0)
      throw new Error("no simulations found for driver " + driver +
          " and version " + version);

    for(int i = 0; i < lstIds.size(); i++) {
      SimulationResult result = new SimulationResult();
      result.simulationId = ((Integer)lstIds.get(i)).intValue();
      result.driver = driver;
      result.version = version;

      try {
        { // read configuration
          TxDOrParams params = (TxDOrParams)
            load(loader, result.simulationId, "Global, Config");
          result.seed = params.seed;
          result.nodes = params.nodes;
          result.shadowStdDev = ((DistShadowingParams)
              ((FieldParams)params.field).pathloss).stdDeviation;
          result.csSize = 1;
//          result.globFwdTable = 0;
          result.csSelection = -1;
//          result.metricDelta = 0;
          if (params.node.route instanceof RouteBuilder.TxDORParams) {
            TxDORParams txDORParams = ((RouteBuilder.TxDORParams)params.node.route);
            result.csSize = txDORParams.candidateSetSize;
//            result.globFwdTable = ((RouteBuilder.TxDORParams)params.node.route).globalForwarderTable ? 1 : 0;
//            result.metricDelta = ((RouteBuilder.TxDORParams)params.node.route).metricDelta;
            result.csSelection = txDORParams.candidateSelection;
//            result.noCandSets = txDORParams.noCandSets;
//            result.scaleRemainingHops = txDORParams.scaleRemainingHops ? 1 : 0;
          }
          MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params)params.node.mac;
          result.useRts = mac.thresholdRts < 1000 ? 1 : 0;
          result.dataRate = ((RateBuilder.ConstantParams)mac.rateSelection).dataBitrate;
          result.controlRate = ((RateBuilder.ConstantParams)mac.rateSelection).controlBitrate;
//          result.dataTxDiv = false ? 1 : 0;
//          result.ignoreRtsCtsNav = false ? 1 : 0;
//          result.useAckCancelation = false ? 1 : 0;
//          result.promiscStorePackets = false ? 1 : 0;
          if (params.node.mac instanceof MacBuilder.M802_11TxDivParams) {
//            result.dataTxDiv = ((MacBuilder.M802_11TxDivParams)params.node.mac).useDataTxDiv ? 1 : 0;
//            result.ignoreRtsCtsNav = ((MacBuilder.M802_11TxDivParams)params.node.mac).ignoreRtsCtsNav ? 1 : 0;
//            result.useAckCancelation = ((MacBuilder.M802_11TxDivParams)params.node.mac).useAckCancelation ? 1 : 0;
//            result.promiscStorePackets = ((MacBuilder.M802_11TxDivParams)params.node.mac).promiscStorePackets ? 1 : 0;
          }
          RouteBuilder.BrnDsrParams route = (BrnDsrParams) params.node.route;
          if (route.metric.getClass().equals(MetricBuilder.EttParams.class))
            result.metric = "ETT";
          else if (route.metric.getClass().equals(MetricBuilder.EtxParams.class))
            result.metric = "ETX";
          else
            result.metric = route.metric.getClass().getSimpleName();
        }

        { // flow parameters
          PropertiesData data = (PropertiesData)
            load(loader, result.simulationId, "All flows, Flow stats");
          FlowStats stats = (FlowStats) data.getProperties();
          result.avgThroughput = stats.getAvgThroughput();
          result.avgDelay = stats.getAvgDelay();
          result.sendPackets = stats.getSendPackets();
          result.recvPackets = stats.getRecvPackets();
          result.flowEnd = stats.getEnd();
          result.avgHopCount = stats.getAvgHopCount();
        }

        { // mac stats
          PropertiesData data = (PropertiesData)
            load(loader, result.simulationId, "Global, Mac, Stats", true);
          result.macStats = (MacStats) data.getProperties();
        }

        { // mac drops
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Mac, discard vs time", false);
          result.macDrops = null == data ? 0 : data.getY().length;
        }

        { // mac dups
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Mac, duplicate vs time", false);
          result.macDuplicates = null == data ? 0 : data.getY().length;
        }

        { // mac backoff
          DiagramDataHist data = (DiagramDataHist)
            load(loader, result.simulationId, "Global, Mac, backoff (cuml)");
          double[] bos = data.getY();
          double bo = .0;
          for (int j = 0; j < bos.length; j++) bo += bos[j];
          result.macBackoffCuml = bo;
        }

        { // mac short retries
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Mac, short retries vs time", false);
          result.macShortRetries = data == null ? 0 : data.getY().length;
        }

        { // mac long retries
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Mac, long retries vs time", false);
          result.macLongRetries = data == null ? 0 : data.getY().length;
        }

        { // mac ack cancelation
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Mac, ack cancelation", false);
          result.macCanceledAcks = data == null ? 0 : data.getY().length;
        }

        { // mac send immediate
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Mac, send immediate", false);
          result.macSendImmediate = data == null ? 0 : data.getY().length;
        }

        { //
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Routing, duplicate vs time", false);
          result.rtgDuplicate = data == null ? 0 : data.getY().length;
        }

        { //
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Routing, ", false);
          result.rtgDrops = data == null ? 0 : data.getY().length;
        }

        { // radio txdiv delay spread
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Radio, txdiv delay spread", false);
          double[] spreads = (data == null ? null : data.getY());
          result.radAvgDelaySpread = 0;
          if (null != spreads && spreads.length > 0) {
            double spread = .0;
            for (int j = 0; j < spreads.length; j++) spread += spreads[j];
            result.radAvgDelaySpread = spread / spreads.length;
          }
        }

        { // radio txdiv delay spread
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Global, Radio, txdiv power delta", false);
          double[] deltas = (data == null ? null : data.getY());
          result.radAvgPowerDelta = 0;
          result.radTxDivCount = 0;
          if (null != deltas && deltas.length > 0) {
            double delta = .0;
            for (int j = 0; j < deltas.length; j++) delta += deltas[j];
            result.radAvgPowerDelta = delta / deltas.length;
            result.radTxDivCount = deltas.length;
          }
        }

//        {
//          // TODO hugo
//          DescriptiveStatistics stats = DescriptiveStatistics.newInstance();
//          DiagramData data = (DiagramData)
//            load(loader, result.simulationId, "Flow 0, packet delay", true);
//          double[] y = data.getY();
//          for (int j = 1; j < y.length; j++)
//            stats.addValue(y[j] - y[j-1]);
//
//          DelayStats delayStats = new DelayStats(result.simulationId,
//              stats.getMin(),
//              stats.getPercentile(5.),
//              stats.getMean(),
//              stats.getPercentile(95.),
//              stats.getMax(),
//              stats.getStandardDeviation());
//          saver.save(delayStats, driver + "-" + version, false);
//        }

        {
          // TODO hugo
          DescriptiveStatistics stats = DescriptiveStatistics.newInstance();
          DiagramData data = (DiagramData)
            load(loader, result.simulationId, "Flow 0, packet arrival vs time", true);
          double[] y = data.getY();
          for (int j = 0; j < y.length; j++)
            stats.addValue(y[j]);
          double[] sortedY = stats.getSortedValues();
          stats.clear();
          for (int j = 0; j < y.length; j++)
            stats.addValue(y[j] - sortedY[j]);

          ReorderDensityStats rdStats = new ReorderDensityStats(result.simulationId,
              stats.getMin(),
              stats.getPercentile(5.),
              stats.getMean(),
              stats.getPercentile(95.),
              stats.getMax(),
              stats.getStandardDeviation());
          saver.save(rdStats, driver + "-" + version, false);
        }

        /* TODO
         * radio utilization
         * routing number of hops, routing drops
         */

      }
      catch (Error e) {
        System.err.println(e.getMessage());
        continue;
      }
      catch (Throwable e) {
        e.printStackTrace();
        continue;
      }

      results.add(result);
    }

    for (int i = 0; i < results.size(); i++) {
      SimulationResult res = (SimulationResult)results.get(i);
      if (res.csSize != 1 ) {
        res.avgThroughputRatio = -1.;
        res.avgNonRtsThroughputRatio = -1.;
        res.avgDelayRatio = -1.;
        res.avgNonRtsDelayRatio = -1.;

        for (int j = 0; j < results.size(); j++) {
          SimulationResult other = (SimulationResult)results.get(j);
          if (other.seed == res.seed
              &&other.nodes == res.nodes
              &&other.shadowStdDev == res.shadowStdDev
              &&other.useRts == res.useRts
              &&other.csSize == 1
              &&other.dataRate == res.dataRate
              &&other.controlRate == res.controlRate) {
            res.avgThroughputRatio = res.avgThroughput / other.avgThroughput;
            if (Double.isNaN(res.avgThroughputRatio))
              res.avgThroughputRatio = .0;
            other.avgThroughputRatio = 1.;
            res.avgDelayRatio = res.avgDelay / other.avgDelay;
            if (Double.isNaN(res.avgDelayRatio))
              res.avgDelayRatio = .0;
            other.avgDelayRatio = 1.;
            break;
          }
        }

        for (int j = 0; j < results.size(); j++) {
          SimulationResult other = (SimulationResult)results.get(j);
          if (other.seed == res.seed
              &&other.nodes == res.nodes
              &&other.shadowStdDev == res.shadowStdDev
              &&other.useRts == 0
              &&other.csSize == 1
              &&other.dataRate == res.dataRate
              &&other.controlRate == res.controlRate) {
            res.avgNonRtsThroughputRatio = res.avgThroughput / other.avgThroughput;
            if (Double.isNaN(res.avgNonRtsThroughputRatio))
              res.avgNonRtsThroughputRatio = .0;
            other.avgNonRtsThroughputRatio = 1.;
            res.avgNonRtsDelayRatio = res.avgDelay / other.avgDelay;
            if (Double.isNaN(res.avgNonRtsDelayRatio))
              res.avgNonRtsDelayRatio = .0;
            other.avgNonRtsDelayRatio = 1.;
            break;
          }
        }
      }
    }

//    System.out.println(SimulationResult.getHeader());
//    for (int i = 0; i < results.size(); i++) {
//      System.out.println(((SimulationResult)results.get(i)).toString());
//    }

    for (int i = 0; i < results.size(); i++)
      saver.save(results.get(i), driver + "-" + version, false);
    saver.finalize();
  }


  public static final int ROUTING_DSR = 1;
  public static final int ROUTING_EXOR = 2;
  public static final int ROUTING_TDICOR = 3;
  
  /**
     * Benchmark TDiCOR vs. DSR at 6 Mbps
     */
    public static List getSimulationSuite23() {
      List ret = new ArrayList();
  
      for (int nodes = 25; nodes <= 100; nodes *= 2) {
        for (int seed = 1; seed <= 15; seed++) {
          for (int stdDev = 4; stdDev <= 12; stdDev += 4) {
            for (int csSize = 1; csSize <= 4; csSize++) {
              for (int useRts = 0; useRts <= 1; useRts++) {
                for (int bitrate = Constants.BANDWIDTH_6Mbps; bitrate <= Constants.BANDWIDTH_6Mbps; bitrate *= 2) {
                  TxDOrParams params = (csSize != 1 ?
                      TxDOrParams.defaultParams(new TxDOrParams()) :
                        TxDOrParams.unicastParams(new TxDOrParams()));
                  params.seed = seed;
                  params.nodes = nodes;
  
                  FieldParams field = (FieldParams) params.field;
                  field.fieldX = 2000;
                  field.fieldY = 2000;
  
                  DistShadowingParams pathLoss = (DistShadowingParams) field.pathloss;
                  pathLoss.stdDeviation = stdDev;
  
                  RadioBuilder.NoiseParams radio = (RadioBuilder.NoiseParams) params.node.radio;
                  radio.fieldX = field.fieldX;
                  radio.fieldY = field.fieldY;
                  radio.placement = Constants.PLACEMENT_RANDOM;
                  radio.threshold = .8;
                  radio.min_connectivity_betweenNodes = 2;
                  radio.connectivityBitRate = bitrate;
  
                  MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) params.node.mac;
                  mac.thresholdRts = (useRts == 1 ? 500 : 3000);
                  if (csSize > 1) {
                    ((MacBuilder.M802_11TxDivParams)mac).useDataTxDiv = true; //(dataTxDiv == 1 ? true : false);
                    ((MacBuilder.M802_11TxDivParams)mac).ignoreRtsCtsNav = false; //(ignoreRtsCtsNav == 1 ? true : false);
                    ((MacBuilder.M802_11TxDivParams)mac).useAckCancelation = true; //(useAckCancelation == 1 ? true : false);
                  }
                  RateBuilder.ConstantParams rate = (ConstantParams) mac.rateSelection;
                  rate.dataBitrate = bitrate;
                  rate.controlBitrate = Constants.BANDWIDTH_6Mbps;
  
                  if (csSize != 1) {
                    RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
                    route.candidateSetSize = csSize;
  //                  route.globalForwarderTable = false; //(globFwdTable == 1);
                    route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_CONSERVATIVE;
  //                  route.metricDelta = 0; //metricDelta;
                  }
  
                  RouteBuilder.BrnDsrParams route = (RouteBuilder.BrnDsrParams) params.node.route;
                  MetricBuilder.EtxParams metric = (EtxParams) route.metric;
                  metric.probes = new int[] {bitrate, 20};
  
                  ret.add(params.setParamsBatch());
                }
              }
            }
          }
        }
      }
  
      return ret;
    }

  /**
     * Benchmark TDiCOR vs. DSR at 9/12 Mbps and control rate 6
     */
    public static List getSimulationSuite28() {
      List ret = new ArrayList();
  
      for (int nodes = 25; nodes <= 100; nodes *= 2) {
        for (int seed = 1; seed <= 15; seed++) {
          for (int stdDev = 4; stdDev <= 12; stdDev += 4) {
            for (int csSize = 1; csSize <= 4; csSize++) {
              for (int useRts = 0; useRts <= 1; useRts++) {
                for (int bitrate = Constants.BANDWIDTH_12Mbps; bitrate <= Constants.BANDWIDTH_24Mbps; bitrate *= 2) {
                  TxDOrParams params = (csSize != 1 ?
                      TxDOrParams.defaultParams(new TxDOrParams()) :
                        TxDOrParams.unicastParams(new TxDOrParams()));
                  params.seed = seed;
                  params.nodes = nodes;
  
                  FieldParams field = (FieldParams) params.field;
                  field.fieldX = 2000;
                  field.fieldY = 2000;
  
                  DistShadowingParams pathLoss = (DistShadowingParams) field.pathloss;
                  pathLoss.stdDeviation = stdDev;
  
                  RadioBuilder.NoiseParams radio = (RadioBuilder.NoiseParams) params.node.radio;
                  radio.fieldX = field.fieldX;
                  radio.fieldY = field.fieldY;
                  radio.placement = Constants.PLACEMENT_RANDOM;
                  radio.threshold = .8;
                  radio.min_connectivity_betweenNodes = 2;
                  radio.connectivityBitRate = bitrate;
  
                  MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) params.node.mac;
                  mac.thresholdRts = (useRts == 1 ? 500 : 3000);
                  if (csSize > 1) {
                    ((MacBuilder.M802_11TxDivParams)mac).useDataTxDiv = true; //(dataTxDiv == 1 ? true : false);
                    ((MacBuilder.M802_11TxDivParams)mac).ignoreRtsCtsNav = false; //(ignoreRtsCtsNav == 1 ? true : false);
                    ((MacBuilder.M802_11TxDivParams)mac).useAckCancelation = true; //(useAckCancelation == 1 ? true : false);
                  }
                  RateBuilder.ConstantParams rate = (ConstantParams) mac.rateSelection;
                  rate.dataBitrate = bitrate;
                  rate.controlBitrate = Constants.BANDWIDTH_6Mbps;
  
                  if (csSize != 1) {
                    RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
                    route.candidateSetSize = csSize;
  //                  route.globalForwarderTable = false; //(globFwdTable == 1);
                    route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_CONSERVATIVE;
  //                  route.metricDelta = 0; //metricDelta;
                  }
  
                  RouteBuilder.BrnDsrParams route = (RouteBuilder.BrnDsrParams) params.node.route;
                  MetricBuilder.EtxParams metric = (EtxParams) route.metric;
                  metric.probes = new int[] {bitrate, 20};
  
                  ret.add(params.setParamsBatch());
                }
              }
            }
          }
        }
      }
  
      return ret;
    }

  /**
     * Benchmark TDiCOR vs. DSR at 9/12 Mbps data and control rate
     */
    public static List getSimulationSuite29() {
      List ret = new ArrayList();
  
      for (int nodes = 25; nodes <= 100; nodes *= 2) {
        for (int seed = 1; seed <= 15; seed++) {
          for (int stdDev = 4; stdDev <= 12; stdDev += 4) {
            for (int csSize = 1; csSize <= 4; csSize++) {
              for (int useRts = 0; useRts <= 1; useRts++) {
                for (int bitrate = Constants.BANDWIDTH_12Mbps; bitrate <= Constants.BANDWIDTH_24Mbps; bitrate *= 2) {
                          TxDOrParams params = (csSize != 1 ?
                              TxDOrParams.defaultParams(new TxDOrParams()) :
                                TxDOrParams.unicastParams(new TxDOrParams()));
                          params.seed = seed;
                          params.nodes = nodes;
  
                          FieldParams field = (FieldParams) params.field;
                          field.fieldX = 2000;
                          field.fieldY = 2000;
  
                          DistShadowingParams pathLoss = (DistShadowingParams) field.pathloss;
                          pathLoss.stdDeviation = stdDev;
  
                          RadioBuilder.NoiseParams radio = (RadioBuilder.NoiseParams) params.node.radio;
                          radio.fieldX = field.fieldX;
                          radio.fieldY = field.fieldY;
                          radio.placement = Constants.PLACEMENT_RANDOM;
                          radio.threshold = .8;
                          radio.min_connectivity_betweenNodes = 2;
                          radio.connectivityBitRate = bitrate;
  
                          MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) params.node.mac;
                          mac.thresholdRts = (useRts == 1 ? 500 : 3000);
                          if (csSize > 1) {
                            ((MacBuilder.M802_11TxDivParams)mac).useDataTxDiv = true; //(dataTxDiv == 1 ? true : false);
                            ((MacBuilder.M802_11TxDivParams)mac).ignoreRtsCtsNav = false; //(ignoreRtsCtsNav == 1 ? true : false);
                            ((MacBuilder.M802_11TxDivParams)mac).useAckCancelation = true; //(useAckCancelation == 1 ? true : false);
                          }
                          RateBuilder.ConstantParams rate = (ConstantParams) mac.rateSelection;
                          rate.dataBitrate = bitrate;
                          rate.controlBitrate = Constants.BANDWIDTH_6Mbps;
  
                          if (csSize != 1) {
                            RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
                            route.candidateSetSize = csSize;
  //                          route.globalForwarderTable = false; //(globFwdTable == 1);
                    route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_CONSERVATIVE;
  //                          route.metricDelta = 0; //metricDelta;
                          }
  
                          RouteBuilder.BrnDsrParams route = (RouteBuilder.BrnDsrParams) params.node.route;
                          MetricBuilder.EtxParams metric = (EtxParams) route.metric;
                          metric.probes = new int[] {bitrate, 20};
  
                          ret.add(params.setParamsBatch());
                        }
                      }
            }
          }
        }
      }
  
      return ret;
    }

  /**
     * Test ETT and compare to ETX
     */
    public static List getSimulationSuite30() {
      List ret = new ArrayList();
  
      for (int nodes = 25; nodes <= 100; nodes *= 2) {
        for (int seed = 1; seed <= 5; seed++) {
          for (int stdDev = 4; stdDev <= 12; stdDev += 4) {
            for (int etx = 0; etx <= 1; etx++) {
                for (int bitrate = Constants.BANDWIDTH_12Mbps; bitrate <= Constants.BANDWIDTH_24Mbps; bitrate *= 2) {
                  TxDOrParams params = //(csSize != 1 ?
                      //TxDOrParams.defaultParams(new TxDOrParams()) :
                        TxDOrParams.unicastParams(new TxDOrParams());
                  params.seed = seed;
                  params.nodes = nodes;
  
                  FieldParams field = (FieldParams) params.field;
                  field.fieldX = 2000;
                  field.fieldY = 2000;
  
                  DistShadowingParams pathLoss = (DistShadowingParams) field.pathloss;
                  pathLoss.stdDeviation = stdDev;
  
                  RadioBuilder.NoiseParams radio = (RadioBuilder.NoiseParams) params.node.radio;
                  radio.fieldX = field.fieldX;
                  radio.fieldY = field.fieldY;
                  radio.placement = Constants.PLACEMENT_RANDOM;
                  radio.threshold = .8;
                  radio.min_connectivity_betweenNodes = 2;
  
                  MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) params.node.mac;
                  mac.thresholdRts = 3000; //(useRts == 1 ? 500 : 3000);
  //                if (csSize > 1) {
  //                  ((MacBuilder.M802_11TxDivParams)mac).useDataTxDiv = true; //(dataTxDiv == 1 ? true : false);
  //                  ((MacBuilder.M802_11TxDivParams)mac).ignoreRtsCtsNav = false; //(ignoreRtsCtsNav == 1 ? true : false);
  //                  ((MacBuilder.M802_11TxDivParams)mac).useAckCancelation = true; //(useAckCancelation == 1 ? true : false);
  //              }
  
  //                if (csSize != 1) {
  //                  RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
  //                  route.candidateSetSize = csSize;
  //                  route.globalForwarderTable = false; //(globFwdTable == 1);
  //                  route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_CONSERVATIVE;
  //                  route.metricDelta = 0; //metricDelta;
  //            }
  
  
                  params.setMetricAndBitRate(1 == etx, 1 == etx ? 500 : 50000,
                      bitrate, Constants.BANDWIDTH_6Mbps);
  
                  ret.add(params.setParamsBatch());
          }
        }
      }
      }
      }
  
      return ret;
    }

  /**
   * Benchmark TDiCOR vs. DSR at 6/9 Mbps, promiscStorePackets and noCandSets
   */
  public static List getSimulationSuite31() {
    List ret = new ArrayList();
  
    for (int nodes = 25; nodes <= 100; nodes *= 2) {
      for (int seed = 1; seed <= 10; seed++) {
        for (int stdDev = 4; stdDev <= 12; stdDev += 4) {
          for (int csSize = 1; csSize <= 4; csSize++) {
            for (int useRts = 0; useRts <= 1; useRts++) {
              for (int bitrate = Constants.BANDWIDTH_6Mbps; bitrate <= Constants.BANDWIDTH_12Mbps; bitrate *= 2) {
                for (int promiscStorePackets = 0; promiscStorePackets <= 1; promiscStorePackets++) {
                  for (int noCandSets = 1; noCandSets <= 2; noCandSets++) {
                    if (csSize == 1
                        && (promiscStorePackets != 0
                            ||noCandSets != 1
                            ||useRts != 0))
                      continue;
                    if (csSize != 1
                        && useRts != 1)
                      continue;
  
                    TxDOrParams params = (csSize != 1 ?
                        TxDOrParams.defaultParams(new TxDOrParams()) :
                          TxDOrParams.unicastParams(new TxDOrParams()));
                    params.seed = seed;
                    params.nodes = nodes;
  
                    FieldParams field = (FieldParams) params.field;
                    field.fieldX = 2000;
                    field.fieldY = 2000;
  
                    DistShadowingParams pathLoss = (DistShadowingParams) field.pathloss;
                    pathLoss.stdDeviation = stdDev;
  
                    RadioBuilder.NoiseParams radio = (RadioBuilder.NoiseParams) params.node.radio;
                    radio.fieldX = field.fieldX;
                    radio.fieldY = field.fieldY;
                    radio.placement = Constants.PLACEMENT_RANDOM;
                    radio.threshold = .8;
                    radio.min_connectivity_betweenNodes = 2;
  
                    MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) params.node.mac;
                    mac.thresholdRts = (useRts == 1 ? 500 : 3000);
                    if (csSize > 1) {
                      ((MacBuilder.M802_11TxDivParams)mac).promiscStorePackets =
                          (promiscStorePackets == 1 ? true : false);
                    }
                    params.setMetricAndBitRate(false, 500, bitrate, Constants.BANDWIDTH_6Mbps);
  
                    if (csSize != 1) {
                      RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
                      route.candidateSetSize = csSize;
                      route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_ETT;
                      route.noCandSets = noCandSets;
                    }
  
                    ret.add(params.setParamsBatch());
                  }
                }
              }
            }
          }
        }
      }
    }
  
    return ret;
  }

  /**
   * Benchmark TDiCOR vs. DSR at 6/12 Mbps, promiscStorePackets and noCandSets
   */
  public static List getSimulationSuite32() {
    List ret = new ArrayList();
  
    for (int nodes = 25; nodes <= 100; nodes *= 2) {
      for (int seed = 1; seed <= 10; seed++) {
        for (int stdDev = 4; stdDev <= 12; stdDev += 4) {
          for (int csSize = 1; csSize <= 4; csSize++) {
            for (int bitrate = Constants.BANDWIDTH_6Mbps; bitrate <= Constants.BANDWIDTH_12Mbps; bitrate *= 2) {
              for (int promiscStorePackets = 0; promiscStorePackets <= 1; promiscStorePackets++) {
                for (int noCandSets = 1; noCandSets <= 2; noCandSets++) {
                  for (int scaleRemainingHops = 0; scaleRemainingHops <= 1; scaleRemainingHops++) {
                    if (csSize == 1
                        && (promiscStorePackets != 0
                            ||noCandSets != 1
                            ||scaleRemainingHops != 0))
                      continue;
                    if (csSize != 1
                        && promiscStorePackets != 1
                        && (noCandSets != 1 || scaleRemainingHops != 1))
                      continue;
                    if (csSize != 1
                        && promiscStorePackets == 1
                        && noCandSets != 1 && scaleRemainingHops != 1)
                      continue;
  
                    TxDOrParams params = (csSize != 1 ?
                        TxDOrParams.defaultParams(new TxDOrParams()) :
                          TxDOrParams.unicastParams(new TxDOrParams()));
                    params.seed = seed;
                    params.nodes = nodes;
  
                    FieldParams field = (FieldParams) params.field;
                    field.fieldX = 2000;
                    field.fieldY = 2000;
  
                    DistShadowingParams pathLoss = (DistShadowingParams) field.pathloss;
                    pathLoss.stdDeviation = stdDev;
  
                    NoiseParams radio = (NoiseParams) params.node.radio;
                    radio.fieldX = field.fieldX;
                    radio.fieldY = field.fieldY;
                    radio.placement = Constants.PLACEMENT_RANDOM;
                    radio.threshold = .8;
                    radio.min_connectivity_betweenNodes = 2;
  
                    M802_11Params mac = (M802_11Params) params.node.mac;
                    mac.thresholdRts = (csSize == 1 ? 3000 : 500);
                    if (csSize > 1) {
                      ((M802_11TxDivParams)mac).promiscStorePackets =
                          (promiscStorePackets == 1 ? true : false);
                    }
                    // 50000 for DSR/ETT, 500 for TDiCOR
                    // TODO ETX bounds for DSR/ETT
                    params.setMetricAndBitRate(false, (csSize != 1 ? 500 : 50000),
                        bitrate, Constants.BANDWIDTH_6Mbps);
  
                    Util.assertion(((MetricBuilder.EtxParams)
                        (((RouteBuilder.BrnDsrParams)params.node.route).metric)).globalLinkTable == true);
  
                    if (csSize != 1) {
                      RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
                      route.candidateSetSize = csSize;
                      route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_ETT;
                      route.noCandSets = noCandSets;
                      route.scaleRemainingHops = (scaleRemainingHops == 1);
                    }
  
                    ret.add(params.setParamsBatch());
                  }
                }
              }
            }
          }
        }
      }
    }
  
    return ret;
  }

  /**
   * Benchmark TDiCOR vs. DSR at 6/12 Mbps, promiscStorePackets and noCandSets
   */
  public static List getSimulationSuite33() {
    List ret = new ArrayList();
  
    for (int nodes = 25; nodes <= 200; nodes *= 2) {
      for (int seed = 1; seed <= 10; seed++) {
        for (int stdDev = 4; stdDev <= 12; stdDev += 4) {
          for (int csSize = 1; csSize <= 4; csSize++) {
            for (int bitrate = Constants.BANDWIDTH_6Mbps; bitrate <= Constants.BANDWIDTH_12Mbps; bitrate *= 2) {
              for (int promiscStorePackets = 0; promiscStorePackets <= 1; promiscStorePackets++) {
                for (int noCandSets = 1; noCandSets <= 2; noCandSets++) {
                  for (int scaleRemainingHops = 0; scaleRemainingHops <= 1; scaleRemainingHops++) {
                    if (csSize == 1
                        && (promiscStorePackets != 0
                            ||noCandSets != 1
                            ||scaleRemainingHops != 0))
                      continue;
                    if (csSize != 1
                        && promiscStorePackets != 1
                        && (noCandSets != 1 || scaleRemainingHops != 1))
                      continue;
                    if (csSize != 1
                        && promiscStorePackets == 1
                        && noCandSets != 1 && scaleRemainingHops != 1)
                      continue;
  
                    TxDOrParams params = (csSize != 1 ?
                        TxDOrParams.defaultParams(new TxDOrParams()) :
                          TxDOrParams.unicastParams(new TxDOrParams()));
                    params.seed = seed;
                    params.nodes = nodes;
  
                    FieldParams field = (FieldParams) params.field;
                    field.fieldX = 2000;
                    field.fieldY = 2000;
  
                    DistShadowingParams pathLoss = (DistShadowingParams) field.pathloss;
                    pathLoss.stdDeviation = stdDev;
  
                    NoiseParams radio = (NoiseParams) params.node.radio;
                    radio.fieldX = field.fieldX;
                    radio.fieldY = field.fieldY;
                    radio.placement = Constants.PLACEMENT_RANDOM;
                    radio.threshold = .8;
                    radio.min_connectivity_betweenNodes = 2;
  
                    M802_11Params mac = (M802_11Params) params.node.mac;
                    mac.thresholdRts = (csSize == 1 ? 3000 : 500);
                    if (csSize > 1) {
                      ((M802_11TxDivParams)mac).promiscStorePackets =
                          (promiscStorePackets == 1 ? true : false);
                    }
                    // 50000 for DSR/ETT, 500 for TDiCOR
                    // TODO ETX bounds for DSR/ETT
                    params.setMetricAndBitRate(false, (csSize != 1 ? 500 : 50000),
                        bitrate, Constants.BANDWIDTH_6Mbps);
  
                    Util.assertion(((MetricBuilder.EtxParams)
                        (((RouteBuilder.BrnDsrParams)params.node.route).metric)).globalLinkTable == true);
  
                    if (csSize != 1) {
                      RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
                      route.candidateSetSize = csSize;
                      route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_ETT;
                      route.noCandSets = noCandSets;
                      route.scaleRemainingHops = (scaleRemainingHops == 1);
                    }
  
                    ret.add(params.setParamsBatch());
                  }
                }
              }
            }
          }
        }
      }
    }
  
    return ret;
  }

  /**
   * Benchmark TDiCOR vs. DSR at 6/12/24/ Mbps
   */
  public static List getSimulationSuite34() {
    List ret = new ArrayList();
  
    // parameter density
    for (int nodes = 25; nodes <= 100; nodes *= 2) {
      for (int seed = 1; seed <= 10; seed++) {
        for (int stdDev = 4; stdDev <= 12; stdDev += 4) {
          for (int bitrate = Constants.BANDWIDTH_6Mbps; bitrate <= Constants.BANDWIDTH_12Mbps; bitrate *= 2) {
            for (int routing = 0; routing <= 2; routing++) {
              if (ROUTING_DSR == routing) {
                ret.add(getParams(nodes, seed, stdDev, 1,
                    bitrate, routing).setParamsBatch());
              } else {
                for (int csSize = 2; csSize <= 4; csSize++) {
                  ret.add(getParams(nodes, seed, stdDev, csSize,
                      bitrate, routing).setParamsBatch());
                }
              }
            }
          }
        }
      }
    }
  
    return ret;
  }

  public static TxDOrParams getParams(int nodes, int seed, int stdDev,
      int csSize, int bitrate, int routing) {
    TxDOrParams params = null;
    switch (routing) {
    case ROUTING_DSR:
      params = TxDOrParams.unicastParams(new TxDOrParams());
      Util.assertion(1 == csSize);
      break;
    case ROUTING_TDICOR:
      params = TxDOrParams.defaultParams(new TxDOrParams());
      Util.assertion(1 != csSize);
      break;
    case ROUTING_EXOR:
      // TODO
      Util.assertion(1 != csSize);
      break;
    }
    params.seed = seed;
    params.nodes = nodes;
 
    FieldParams field = (FieldParams) params.field;
    field.fieldX = 2000;
    field.fieldY = 2000;
 
    DistShadowingParams pathLoss = (DistShadowingParams) field.pathloss;
    pathLoss.stdDeviation = stdDev;
 
    RadioBuilder.NoiseParams radio = (RadioBuilder.NoiseParams) params.node.radio;
    radio.fieldX = field.fieldX;
    radio.fieldY = field.fieldY;
    radio.placement = Constants.PLACEMENT_RANDOM;
    radio.threshold = .8;
    radio.min_connectivity_betweenNodes = 2;
 
    MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) params.node.mac;
    mac.thresholdRts = (ROUTING_TDICOR == routing ? 3000 : 500);
    if (ROUTING_TDICOR == routing) {
      ((MacBuilder.M802_11TxDivParams)mac).promiscStorePackets =
          true;
    }
    // 50000 for DSR/ETT, 500 for TDiCOR
    // TODO ETX bounds for DSR/ETT
    params.setMetricAndBitRate(false, (ROUTING_TDICOR == routing ? 500 : 50000),
        bitrate, Constants.BANDWIDTH_6Mbps);
 
    Util.assertion(((MetricBuilder.EtxParams)
        (((RouteBuilder.BrnDsrParams)params.node.route).metric)).globalLinkTable == true);
 
    if (ROUTING_TDICOR == routing) {
      RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
      route.candidateSetSize = csSize;
      route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_ETT;
      route.noCandSets = 1;
      route.scaleRemainingHops = true;
    }
    return params;
  }

  /* (non-Javadoc)
   * @see brn.sim.AbstractDriver#getSimulationSuite()
   */
  public List getSimulationSuite(String version) {
    return getSimulationSuite33();
  }
}
