'''
ant db-eval-jpy -Ddriver.class=res/test/SimHiddenNode.py -Ddriver.version=test
insert into simulation.progress (simulationId,state) values (6,'FINISHED')
sed -e 's/]];/]];...\n/g' | 
sed -e 's/\[\]/\[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\]/g' | 
sed -e 's/\],/\];/g'
brn-suse093-7 10:3 brn-suse093-6 20:3 brn-suse093-5 30:3 brn-suse093-4 40:3 gorillaz 110:2 blur 120:2 chi 130:2 mks 140:2
'''

import sys
from math import ceil
from jarray import array, zeros
from java.lang import *
from java.util import *
from java.io import StringReader
import java.lang.reflect

from jist.swans import Constants
from jist.swans.net import NetAddress
from jist.swans.misc import Util

from brn.sim import *
from brn.sim.data import *
from brn.sim.builder import *
from brn.sim.handler import LinkQualityHandler
import brn.swans.Constants as BrnConstants

from brn.distsim.ormapper.util import *

true = 1
false = 0

NONE = DataManager.LEVEL_OFF
LESS = DataManager.LEVEL_IMPORTANT
BASIC = DataManager.LEVEL_BASIC
MORE = DataManager.LEVEL_ADDITIONAL
ALL = DataManager.LEVEL_ALL

def unique(s):
    """Return a list of the elements in s, but without duplicates.

    For example, unique([1,2,3,1,2,3]) is some permutation of [1,2,3],
    unique("abcabc") some permutation of ["a", "b", "c"], and
    unique(([1, 2], [2, 3], [1, 2])) some permutation of
    [[2, 3], [1, 2]].

    For best speed, all sequence elements should be hashable.  Then
    unique() will usually work in linear time.

    If not possible, the sequence elements should enjoy a total
    ordering, and if list(s).sort() doesn't raise TypeError it's
    assumed that they do enjoy a total ordering.  Then unique() will
    usually work in O(N*log2(N)) time.

    If that's not possible either, the sequence elements must support
    equality-testing.  Then unique() will usually work in quadratic
    time.
    """

    n = len(s)
    if n == 0:
        return []

    # Try using a dict first, as that's the fastest and will usually
    # work.  If it doesn't work, it will usually fail quickly, so it
    # usually doesn't cost much to *try* it.  It requires that all the
    # sequence elements be hashable, and support equality comparison.
    u = {}
    try:
        for x in s:
            u[x] = 1
    except TypeError:
        del u  # move on to the next method
    else:
        return u.keys()
    
    # We can't hash all the elements.  Second fastest is to sort,
    # which brings the equal elements together; then duplicates are
    # easy to weed out in a single pass.
    # NOTE:  Python's list.sort() was designed to be efficient in the
    # presence of many duplicate elements.  This isn't true of all
    # sort functions in all languages or libraries, so this approach
    # is more effective in Python than it may be elsewhere.
    try:
        t = list(s)
        t.sort()
    except TypeError:
        del t  # move on to the next method
    else:
        assert n > 0
        last = t[0]
        lasti = i = 1
        while i < n:
            if t[i] != last:
                t[lasti] = last = t[i]
                lasti += 1
            i += 1
        return t[:lasti]

    # Brute force is all that's left.
    u = []
    for x in s:
        if x not in u:
            u.append(x)
    return u

def filterLine(line, values, xvalues=True):
  x = line.getXInternal()
  y = line.getYInternal()
  if False==xvalues:
    y = line.getXInternal()
    x = line.getYInternal()
  idx = range(0,len(x))
  idx2 = filter((lambda v: y[v] in values), idx)
  return map((lambda v: x[v]), idx2)

def countRx(line,noNodes):
  #x = line.getXInternal()
  ret = [0]*noNodes
  y = line.getYInternal()
  for i in range(0,len(y)):
    ret[int(y[i])] += 1
  return ret

def intersect(seq1, seq2):
    res = []                     # start empty
    for x in seq1:               # scan seq1
        if x in seq2:            # common item?
            res.append(x)        # add to end
    return res
  
def int2bin(n, count=24):
  """returns the binary of integer n, using count number of digits"""
  return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)])
 
# PowerSet of a List
def PowerSet(orignal_list):
  list_size = len(orignal_list)
  num_sets = 2**list_size
  powerset = []
  # Don't include empty set
  for i in range(num_sets)[1:]:
    subset = []
    binary_digits = list(int2bin(i,list_size))
    list_indices = range(list_size)
    for (bit,index) in zip(binary_digits,list_indices):
      if bit == '1':
          subset.append(orignal_list[index])
    powerset.append(subset)
  return powerset

def createArray1(w,default=None):
  return [default]*w

def createArray2(w,h,default=None):
  return [ [default]*w for i in range(h) ]

def createArray3(a,b,c,default=None):
  return [ [ [default]*a for i in range(b) ] for i in range(c) ]

def array2(pyarr, type):
  pyarrj = [array(pyarr[i], type) for i in range(0,len(pyarr))]
  jarr = java.lang.reflect.Array.newInstance(Object.getClass(pyarrj[0]), len(pyarr))
  for i in range(0,len(pyarrj)):
    java.lang.reflect.Array.set(jarr, i, pyarrj[i])
  return jarr

def toJavaList(pyarray):
  jarr = ArrayList()
  [jarr.add(x) for x in pyarray]
  return jarr

def toJavaList2(pyarray):
  jarr = ArrayList()
  for x in pyarray:
    entry = ArrayList()
    [entry.add(y) for y in x]
    jarr.add(entry)
  return jarr

def toJavaListArray2(pyarr, type):
  pyarrj = [array(pyarr[i], type) for i in range(0,len(pyarr))]
  jarr = ArrayList()
  [jarr.add(x) for x in pyarrj]
  return jarr

class SimulationResult(Object):
    pass

class NodeEntry(Object):
    pass

class LinkEntry(Object):
    pass

#class SimulationResult2(Object):
#    pass

class SimHiddenNode(AbstractDriver):
    def __init__(self):
        pass

    #---------------------------------------------------------------------------
    # Driver Definition
    #---------------------------------------------------------------------------

    #def installHandlers(self, options):
    #  self.super__installHandlers(options)

      #linkQualityHandler = self.getDataManager().getContributor(LinkQualityHandler.ID)

      #if (None != linkQualityHandler and None != options.nodeParams[0].route):
      #  linkQualityHandler.setSampleLen(options.nodeParams[0].route.metric.tau / 1000)


#    def setupApplication(self, params, nodeId, node):
#        self.super__setupApplication(params,nodeId, node)
#
#        if not isinstance(params.nodeParams[0], NodeBuilder.AppParams):
#          return
#
#        appParams = AppBuilder.UdpNotifyParams()
#        appParams.start = 000
#        appParams.end = 250000
#        appParams.flowId = nodeId
#        #appParams.maxOutstandingPackets = -1
#        #params.nodeParams[0].flow.udpPayloadLen
#
#        if (nodeId <= params.nodeNumber[0]):
#            appParams.client = true
#            appParams.clientAddr = NetAddress(nodeId)
#            appParams.serverAddr = NetAddress(nodeId+params.nodeNumber[0])
#        else:
#            appParams.client = false
#            appParams.clientAddr = NetAddress(nodeId-params.nodeNumber[0])
#            appParams.serverAddr = NetAddress(nodeId)
#
#        builder = self.getBuilderProvider().getBuilder(appParams)
#        ret = builder.build(appParams, node)
#        self.getBuilderProvider().addHookUp(builder, appParams, node, ret)

    #---------------------------------------------------------------------------
    # Setup Parameter
    #---------------------------------------------------------------------------

    def getBerRadio(self):
        radio = RadioBuilder.NoiseAdditiveBerParams()
        radio.radioDesc = '''
          mac=802.11bg
          bitrates=6,9,12,18,24,36,48,54
          txpowers=19,19,19,19,19,18,16,15
          thresholds=5.4,5.8,7.0,9.5,11.3,14.9,18.6,20.6
          basicRates=6,12,24
          frequencies=2400
          frequency_spacings=5
          frequency_widths=20
          number_of_channels=1 '''
        radio.useAnnos = true
        radio.ccaModel = BrnConstants.RADIO_CCA_MODE1
        #nergyLevel_mW = Util.fromDB(-92.965 + .965);
        radio.ccaEnergyLevel_dBm = -91.44
        #nodeParams.radio.captureModel = BrnConstants.RADIO_CAPTURE_NONE;
        radio.captureEnergyLevel_dB = Util.fromDB(2);
        return radio
    
    def getThresholdRadio(self):
        radio = RadioBuilder.NoiseAdditiveParams()
        #radio = RadioBuilder.NoiseIndepParams()
        radio.radioDesc = '''
            sensitivity=-91.44 
            ambient_noise=4.2516e-010
          mac=802.11bg
          bitrates=6,9,12,18,24,36,48,54
          txpowers=19,19,19,19,19,18,16,15
          thresholds=5.4,5.8,7.0,9.5,11.3,14.9,18.6,20.6
          basicRates=6,12,24
          frequencies=2400
          frequency_spacings=5
          frequency_widths=20
          number_of_channels=1 '''
        radio.useAnnos = true
        return radio
      
    def getReceiver(self,field, nodeParams):
        nodeParams.radio = self.getBerRadio()
        #nodeParams.radio = self.getThresholdRadio();
        nodeParams.radio.fieldX = field.fieldX
        nodeParams.radio.fieldY = field.fieldY
        #nodeParams.radio.placement = Constants.PLACEMENT_GRID
        #nodeParams.radio.placementOpts = "5x5"
        nodeParams.radio.placement = Constants.PLACEMENT_MANUAL 
        nodeParams.radio.placementOpts = '282.494x210.4106: 86.2946x143.4466: 339.5293x17.039: 338.7066x130.8133: 221.6256x203.7057: 373.549x7.149: 112.6844x204.7621: 50.3338x2.0888: 71.4796x22.6795: 143.5478x179.6795: 307.5611x78.9896: 207.6851x49.8872: 296.736x236.8324: 209.0097x125.0367: 156.7916x210.9243: 60.1111x324.7711: 201.9642x193.8886: 99.2346x297.8131: 166.7675x343.3851: 114.7103x26.3367: 220.79x241.3338: 82.523x247.172: 263.299x326.1139: 321.3202x342.5137: 27.8487x170.7655: 134.8403x186.3928: 348.8375x69.289: 258.2174x99.6261: 341.7331x387.1084: 210.2313x154.4704: 357.3141x175.8907: 362.7455x268.9009: 344.0876x395.9033: 308.1311x246.5946: 11.4928x235.7724: 127.8575x362.1642: 208.1073x300.6962: 203.2921x341.8668: 140.1606x114.1046: 150.101x253.4018: 307.9187x351.2549: 88.591x63.1429: 20.7658x291.1235: 190.1405x54.8507: 32.5602x368.3264: 151.6639x29.2485: 91.0515x19.8032: 339.9184x59.5464: 352.4038x134.7987: 195.7055x114.442'

        # mac
        nodeParams.mac = MacBuilder.M802_11Params()
        #nodeParams.mac.macType = Constants.MAC_802_11g_PURE
        nodeParams.mac.useEifs = False
        nodeParams.mac.useAnnos = nodeParams.radio.useAnnos
        nodeParams.mac.useBitRateAnnos = true
        nodeParams.mac.rateSelection.dataBitrate = Constants.BANDWIDTH_6Mbps
        nodeParams.mac.rateSelection.controlBitrate = Constants.BANDWIDTH_6Mbps

        # net
        nodeParams.net = NetBuilder.IpNotifyParams()
        nodeParams.net.protocolMapper = array([ \
            Constants.NET_PROTOCOL_LINK_PROBE, \
            Constants.NET_PROTOCOL_UDP, \
            Constants.NET_PROTOCOL_TCP, \
            Constants.NET_PROTOCOL_MCEXOR, \
            Constants.NET_PROTOCOL_FLOODING, \
            Constants.NET_PROTOCOL_ARP \
          ], 'i')

        # route
        nodeParams.route = RouteBuilder.TableParams()
        nodeParams.route.protocol = Constants.NET_PROTOCOL_ARP

        # trans
        nodeParams.trans = TransBuilder.UdpParams()

        return nodeParams

    def getDsrNode(self,field, nodeParams):
      node = self.getReceiver(field, nodeParams)
      
      # rotue
      node.route = RouteBuilder.BrnDsrParams()
      node.route.protocol = Constants.NET_PROTOCOL_MCEXOR
      node.route.forwarding = BrnConstants.FORWARDING_UNICAST
      #node.route.forwarding = BrnConstants.FORWARDING_PASSIVEACK
      node.route.discovery = BrnConstants.DISCOVERY_PROACTIVE
      node.route.floodintOffset = 50000
      node.route.floodingPeriod = 10000
      node.route.floodingMax = 0
      node.route.bitrateFromLinkTable = false
      node.route.minLinkMetric = 50 * Constants.MILLI_SECOND
      
      # TODO staticroute

      node.route.metric = MetricBuilder.EttParams()
      node.route.metric.probes = array( [ \
                Constants.BANDWIDTH_6Mbps, 1500 \
          ] , 'i')
      node.route.metric.period = 1000
      node.route.metric.tau = 30000
      node.route.metric.globalLinkTable = true

      return node


    def envParams(self):
        params = AbstractParams()

        # general setup
        params.assertion = true
        params.endTime = 205
        params.seed = 1
        params.node = None

        # field
        params.field.fieldX = int(400)
        params.field.fieldY = int(400)
        params.field.spatial_mode = Constants.SPATIAL_HIER #SPATIAL_LINEAR 
        #params.field.mobility = Constants.MOBILITY_BOUNDLESS_SIM_AREA
        # vMin:vMax:aMin:aMax:deltaT:maxAngularChange[:vStart:angStart]
        #params.field.mobilityOpts = "1:1:0:0:.5:0:1:0"
        #params.field.pathloss = PathLossBuilder.FreeSpaceParams()
        params.field.pathloss = PathLossBuilder.LogDistanceParams()
        params.field.pathloss.exponent = 3.5
        pathLoss = PathLossBuilder.ShadowingParams()
        pathLoss.pathloss = params.field.pathloss
        pathLoss.stdDeviation = 0.
        pathLoss.exponential = true
        pathLoss.coherenceTime = 1000 * Constants.MILLI_SECOND
        params.field.pathloss = pathLoss
        params.field.fading = FadingBuilder.NoneParams()
        #params.field.fading = FadingBuilder.PunnooseRicianParams()
        #params.field.fading.maxVelocity = 2.
        #params.field.fading.K = 12
        #params.field.fading = FadingBuilder.RicianParams()
        #params.field.fading.K = 6

        return params


    def cbrParams(self):
        params = self.envParams()
        
        nodeParams =  NodeBuilder.FlowParams()
        nodeParams.flows = None
        nodeParams.trans = None

        params.nodeNumber = array( [50], 'i')
        params.nodeParams = array( [ self.getReceiver(params.field, nodeParams)], \
                                     NodeBuilder.NodeParams)

        nodeParams.route = RouteBuilder.TableParams()
        nodeParams.route.protocol = Constants.NET_PROTOCOL_ARP

        # max 460 packets per sec (g pure)
        # max 410 pps (bg)
        # scen 2 rate=[1,49.58,1,1,1,76.43,1,1,1,1,51.82,1,36.1,1,1,57.01,1,118.25,1,1,54.64,1,96.16,1,1,15.42,1,60.95,1,1,1,1,82.05,1,1,1,69.96,1,58.27,96.57,68.38,9.13,1,1,48.04,1,1,49.45,1,50.18]
        # scen 4 rate=[1,28.85,1,1,1,39.17,1,1,1,1,29.62,1,35.05,1,1,34.6,1,80.62,1,1,44.64,1,64.8,1,1,40.13,1,43.41,1,1,1,1,40.73,1,1,1,83.6,1,55.26,111.4,43.22,26.43,1,1,29.24,1,1,28.8,1,29.26]
        # scen 8 rate=[1,1,1,1,1,114.79,1,1,1,1,119.39,1,1,1,60.53,60.51,1,60.5,1,1,1,1,1,1,1,1,1,101.88,1,142.75,1,1,1,1,1,1,1,1,1,62.5,1,1,1,1,1,1,1,61.97,1,1]
        rate=[1,1,1,1,1,1,1,21.6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,39.27,1,1,49.66,1,1,1,1,1,1,27.19,1,1,1,63.62,1,53.49,51.72,46.22,26.55,1,1,1,1,1,1,1,1]
        flows = []
        for j in range(1,params.nodeNumber[0]+1):
          flow = FlowBuilder.CbrUdpParams()
          flow.flowId = j
          flow.start = 100000
          flow.end = 200000
          flow.udpTxRate = rate[j-1]
          flow.poissonArrival = True
          flow.clientAddr = NetAddress(j)
          flow.serverAddr = NetAddress.ANY 
          flows += [flow]
        params.nodeParams[0].flows = array(flows, Builder.Params)
        
        return params


    def dsrCbrParams(self, src = [33], dst = [8], rate = [410 * .07]):
        params = self.envParams()
        
        nodeParams =  NodeBuilder.FlowParams()
        nodeParams.flows = None
        nodeParams.trans = None

        params.nodeNumber = array( [50], 'i')
        params.nodeParams = array( [ self.getDsrNode(params.field, nodeParams)], \
                                     NodeBuilder.NodeParams)

        # max 460 packets per sec (g pure)
        # max 410 pps (bg)
        #src = [33]#[33, 6, 45]
        #dst = [8]#[8, 25, 32]
        flows = []
        for i in range(0,len(src)):
          flow = FlowBuilder.CbrUdpParams()
          flow.flowId = i
          flow.start = 100000
          flow.end   = 200000
          flow.udpTxRate = rate[i]
          flow.poissonArrival = True
          flow.clientAddr = NetAddress(src[i]) 
          flow.serverAddr = NetAddress(dst[i])
          flows += [flow]
        params.nodeParams[0].flows = array(flows, Builder.Params)
        #params.seed=12
        #params.nodeParams[0].mac.cwMax=32
        #fixedRoutes = [NetAddress(x) for x in [6, 48, 11, 28, 30, 15, 40, 18, 16, 45]]
        #params.nodeParams[0].route.metric.fixedRoutes = [fixedRoutes] 
        
        return params


    def dsrSingleHopCbrParams(self):
        params = self.envParams()
        
        nodeParams =  NodeBuilder.TrafficParams()
        nodeParams.traffic = None
        nodeParams.trans = None

        params.nodeNumber = array( [50], 'i')
        params.nodeParams = array( [ self.getDsrNode(params.field, nodeParams)], \
                                     NodeBuilder.NodeParams)

        flow = FlowBuilder.CbrUdpParams()
        flow.start = 100000
        flow.end   = 200000
        flow.udpTxRate = 410 * .07
        flow.poissonArrival = True

        nodeParams.traffic = TrafficBuilder.RandomSingleHopParams()
        nodeParams.traffic.seed          = 2
        nodeParams.traffic.maxHopDist    = 80
        nodeParams.traffic.distinctNodes = true
        nodeParams.traffic.flows         = 25
        nodeParams.traffic.flowParams    = flow
        
        return params

    
    #---------------------------------------------------------------------------
    # Scenario Definitions
    #---------------------------------------------------------------------------


    #---------------------------------------------------------------------------
    # Evaluation
    #---------------------------------------------------------------------------
    
    def getSimulationSuite(self, version):
      if ("50cbr1.6" == version):
        return self.getSimulationSuite50cbr1()
      if ("50dsrcbr1.7" == version):
        return self.getSimulationSuite50dsrcbr1()
      return None

    def evalSimulationResults(self, dbUrl, dbUser, dbPasswd, driver, version, \
                              dbResUrl, dbResUser, dbResPasswd):
      driver = driver.replace('\\', '/')
      if ("50cbr1.6" == version):
        self.evalSimulation(dbUrl, dbUser, dbPasswd, driver, version, \
            dbResUrl, dbResUser, dbResPasswd, self.eval50cbr1)
        return
      if ("50dsrcbr1.7" == version):
        self.evalSimulation(dbUrl, dbUser, dbPasswd, driver, version, \
            dbResUrl, dbResUser, dbResPasswd, self.eval50dsrcbr1)
        return
      if (len(version) > 4 and "test" == version[0:4]):
        self.evalSimulation(dbUrl, dbUser, dbPasswd, version[0:4], version[4:], \
            dbResUrl, dbResUser, dbResPasswd, self.evalTest)
        return
      if (len(version) > 4 and "tdsr" == version[0:4]):
        self.evalSimulation(dbUrl, dbUser, dbPasswd, 'test', version[4:], \
            dbResUrl, dbResUser, dbResPasswd, self.evalTestDsr)
        return
      if (len(version) > 4 and "coll" == version[0:4]):
        self.evalSimulation(dbUrl, dbUser, dbPasswd, 'test', version[4:], \
            dbResUrl, dbResUser, dbResPasswd, self.evalCollision)
        return
      raise Exception("No evaluator for version " + str(version))

    def evalTest(self, driver, version, simulationId, loader):
      params = self.load(loader, simulationId, "Global, Config")
      nodes = params.nodeNumber[0];
      nodeSet = range(1,nodes+1)

      flowPackets = [None]
      for i in nodeSet:
        data = self.load(loader, simulationId,
            "Node "+str(i)+", Trans, arrived packets per flow", false)
        flowPackets.append(data)

      txPackets = createArray1(len(nodeSet),0)
      rxPackets = createArray2(len(nodeSet),len(nodeSet),0)
      rx2Packets = createArray3(len(nodeSet),len(nodeSet),len(nodeSet),0)
      for i in nodeSet:
        # mac stats
        data = self.load(loader, simulationId, "Node "+str(i)+", Mac, Stats")
        macStats = data.getProperties()
        txPackets[i-1] = (macStats.broadcastSend)

        data = flowPackets[i]
        if data==None:
          continue
        line = data.getLine()
        for j in nodeSet:
          filteredLine = filterLine(line, [j]);
          rxPackets[i-1][j-1] = (len(filteredLine)) # PowerSet

        for k in nodeSet:
          if k <= i: continue
          data2 = flowPackets[k] 
          if data2==None:
              continue

          for j in nodeSet:
            filteredLine = filterLine(line, [j]);
            filteredLine2 = filterLine(data2.getLine(), [j]);
            newFiltered = unique(filteredLine + filteredLine2)
            rx2Packets[i-1][k-1][j-1] = (len(newFiltered))

      print str(i) + '  ' + str(txPackets)
      print '   '  + str(rxPackets).replace('],','];')
      print '   '  + str(rx2Packets).replace('],','];').replace(']];',']];\n')

      return None
    
    
    def evalTestDsr(self, driver, version, simulationId, loader):
      params = self.load(loader, simulationId, "Global, Config")
      nodes = params.nodeNumber[0];
      nodeSet = range(1,nodes+1)
      txstart = 100.
      txend = 200. 

      macSend = [None]
      netReceive = [None]
      macStats = [None]
      macReceiveVsTime = [] 
      macReceivePacketVsSrc = [None]
      for i in nodeSet:
        data = self.load(loader, simulationId,
            "Node "+str(i)+", Mac, receive src vs time", false)
        netReceive.append(data)
        data = self.load(loader, simulationId,
            "Node "+str(i)+", Mac, send vs time")
        macSend.append(data)
        data = self.load(loader, simulationId,
            "Node "+str(i)+", Mac, receive vs time")
        line = data.getLine()
        line = [line.getXInternal(), line.getYInternal()]
        line = [line[1][idx] for idx in range(0,len(line[0])) \
          if line[0][idx] >= txstart and line[0][idx] <= txend]
        macReceiveVsTime = unique(macReceiveVsTime + line)
        data = self.load(loader, simulationId,
            "Node "+str(i)+", Mac, receive packet vs src")
        macReceivePacketVsSrc.append(data)

      filteredLine = createArray2(len(nodeSet),len(nodeSet),None)
      minMsgId = min(macReceiveVsTime)
      maxMsgId = max(macReceiveVsTime)
      for i in nodeSet:
        lineI = macReceivePacketVsSrc[i].getLine()
        for j in nodeSet:
          filteredLineI = filterLine(lineI, [j]);
          filteredLine[i-1][j-1] = [x for x in filteredLineI if x >= minMsgId and x <= maxMsgId]

      txPackets = createArray1(len(nodeSet),0)
      rxPackets = createArray2(len(nodeSet),len(nodeSet),0)
      rx2Packets = createArray3(len(nodeSet),len(nodeSet),len(nodeSet),0)
      for i in nodeSet:
        line = macSend[i].getLine().getXInternal()
        txPackets[i-1] = len([p for p in line if p >= txstart and p <= txend])

        for j in nodeSet:
          if netReceive[i]==None:
            continue
          line = netReceive[i].getLine()
          packets = filterLine(line, [j], True)
          rxPackets[i-1][j-1] = len([x for x in packets if x >= txstart and x <= txend])

        for j in nodeSet:
          for k in nodeSet:
            if k <= i: # or lineK==None or lineI==None:
                continue
            rx2Packets[i-1][k-1][j-1] = len(unique(filteredLine[i-1][j-1] + filteredLine[k-1][j-1]))

      print str(i) + '  ' + str(txPackets)
      print '   '  + str(rxPackets).replace('],','];')
      print '   '  + str(rx2Packets).replace('],','];').replace(']];',']];\n')

      return None


    def evalCollision(self, driver, version, simulationId, loader):
      params = self.load(loader, simulationId, "Global, Config")
      nodes = params.nodeNumber[0];
      nodeSet = range(1,nodes+1)
      
      data = self.load(loader, simulationId, "Global, Radio, Packet Timebar")
      entries = data.getEntries()
      sender = [18, 26]
      send = [0, 0]
      send[0] = [x for x in entries if x.nodeId==sender[0] and x.start > 100.0 and x.color==5]
      send[1] = [x for x in entries if x.nodeId==sender[1] and x.start > 100.0 and x.color==5]
      print len(send[0]) # gesendet 0
      print len(send[1]) # gesendet 1
      col01 = [x0 for x0 in send[0] for x1 in send[1] if x0.start <= x1.start and x1.start <= x0.end]
      col10 = [x0 for x0 in send[0] for x1 in send[1] if x1.start <= x0.start and x0.start <= x1.end]
      print len(col01) # collision 1 schießt in 0
      print len(col10) # collision 0 schießt in 1
      return None
    
    def load(self, loader, simulationId, configPath, error=true):
        ret = loader.load(simulationId, configPath)
        if (None == ret and error):
            raise Exception("Object with path \"" + configPath + \
                            "\" not found for id " + str(simulationId))
        return ret
    
    def evalSimulation(self, dbUrl, dbUser, dbPasswd, driver, version, \
                 dbResUrl, dbResUser, dbResPasswd, callback):
      # get the simulation ids
      loader = DbBinaryLoader(dbUrl, dbUser, dbPasswd)
      lstIds = loader.loadSimulationIds(driver, version)
      saver = DBSaver(dbResUrl, dbResUser, dbResPasswd, dbResUrl, dbResUser, dbResPasswd)
      #results = LinkedList()
      if (None == lstIds or lstIds.size() <= 0):
        raise Exception("no simulations found for driver " + driver + \
            " and version " + version)

      for simulationId in lstIds:
          timeStartLoad = System.currentTimeMillis()
          print "Load simulation " + str(simulationId) + " from database"

          try:
            result = callback(driver, version, simulationId, loader)

            timeEndLoad = System.currentTimeMillis()
            if None != result:
              saver.save(result, driver + "-" + version, false)

            timeNow = System.currentTimeMillis()
            print "   loading : " + str(timeEndLoad-timeStartLoad) + " ms, storing: " +str(timeNow-timeEndLoad)+" ms"

            if simulationId % 25 == 0:
              print "rebuilding session"
              saver.rebuildSession()
          except Exception, inst:
              print "Skip simulation " + str(simulationId) + " (" + inst.getMessage() + ")"
              #inst.printStackTrace()
              continue
          #except:
          #    print "Unexpected error:", sys.exc_info()[0]
          #    continue

#      print "Writing #" + str(len(results)) + " results"
#      for result in results:
#          print "Writing result " + str(result.simid) + " to database"
#          saver.save(result, driver + "-" + version, false)
      saver.close()
      

    def runLocal(self):
      params = self.cbrParams()
      #params = self.dsrCbrParams()
      #params = self.dsrSingleHopCbrParams()
      rate = 40./100.
      route = [6]#[33, 41, 23, 37, 40, 26, 39, 42, 8]
      for j in range(1,params.nodeNumber[0]+1):
        if j in route:
          params.nodeParams[0].flows[j-1].udpTxRate = rate * 470.
        else:
          params.nodeParams[0].flows[j-1].udpTxRate = 1. / 470.

      level = BASIC
      params.handlerFieldLevel = level
      params.handlerRadioLevel = MORE
      params.handlerRadioDivLevel = LESS
      params.handlerMacLevel = ALL
      params.handlerRateLevel = level
      params.handlerNetLevel = MORE
      params.handlerRouteLevel= ALL
      params.handlerTransLevel = ALL
      params.handlerFlowLevel = ALL

      params.handlerRadioTimeBarLevel = NONE
      params.handlerMacTimeBarLevel = NONE
      params.handlerNetTimeBarLevel = NONE

      params.handlerForwardGraphLevel = level
      params.handlerLinkTableLevel = level
      params.handlerLinkQuality = NONE

      #params.dumpRadioNam = 'radio.nam';
      #params.dumpRadio = 'radio.tr';

      params.db = True
      #params.fileBinary = false
      #params.directory = "tmp"

      self.run(params)

    def runFile(self, fileName):
      params = Util.readObject(fileName);
      params.db=True

      params.handlerRadioTimeBarLevel = NONE
      params.handlerMacTimeBarLevel = NONE
      params.handlerRadioLevel = MORE
      params.handlerRouteLevel= MORE

      self.run(params);

    def setSimParams(self, params):
      level = NONE
      params.handlerFieldLevel = level
      params.handlerRadioLevel = BASIC
      params.handlerRadioDivLevel = level
      params.handlerMacLevel = ALL
      params.handlerRateLevel = level
      params.handlerNetLevel = BASIC
      params.handlerRouteLevel= MORE
      params.handlerTransLevel = ALL
      params.handlerFlowLevel = ALL

      params.handlerRadioTimeBarLevel = level
      params.handlerMacTimeBarLevel = level
      params.handlerNetTimeBarLevel = level

      params.handlerForwardGraphLevel = BASIC
      params.handlerLinkTableLevel = level
      params.handlerLinkQuality = level
      return params

    def getSimulationSuite50cbr1(self):
      list = ArrayList()
      
      rates = [x/100. for x in range(0,40)]
      #route = [33, 41, 23, 37, 40, 26, 39, 42, 8]
      route=[6, 48, 11, 28, 30, 15, 40, 18, 16, 45]
      
      for rate in rates:
        params = self.cbrParams()
        for j in range(1,params.nodeNumber[0]+1):
          if j in route:
            params.nodeParams[0].flows[j-1].udpTxRate = rate * 470.
          else:
            params.nodeParams[0].flows[j-1].udpTxRate = 1. / 470.
        list.add(self.setSimParams(params))
      return list

    """
SELECT simulationresult_0.driver, simulationresult_0.version, simulationresult_0.simid, simulationresult_0.rate, `simulationresult$$route_0`.elm AS 'node', `simulationresult$$rxpackets_0`.elm AS 'rxpackets', `simulationresult$$txpackets_0`.elm AS 'txpackets', `simulationresult$$pdr_0`.elm AS 'pdr', `simulationresult$$backoff_0`.elm AS 'backoff', `simulationresult$$drops_0`.elm AS 'drops'
FROM `simulationresult$$backoff` `simulationresult$$backoff_0`, `simulationresult$$drops` `simulationresult$$drops_0`, `simulationresult$$pdr` `simulationresult$$pdr_0`, `simulationresult$$route` `simulationresult$$route_0`, `simulationresult$$rxpackets` `simulationresult$$rxpackets_0`, `simulationresult$$txpackets` `simulationresult$$txpackets_0`, simulationresult simulationresult_0
WHERE `simulationresult$$route_0`.uid = simulationresult_0.primary_key AND `simulationresult$$rxpackets_0`.uid = simulationresult_0.primary_key AND `simulationresult$$txpackets_0`.uid = simulationresult_0.primary_key AND `simulationresult$$route_0`.idx = `simulationresult$$txpackets_0`.idx AND `simulationresult$$route_0`.idx = `simulationresult$$rxpackets_0`.idx AND `simulationresult$$pdr_0`.uid = simulationresult_0.primary_key AND `simulationresult$$route_0`.idx = `simulationresult$$pdr_0`.idx AND `simulationresult$$drops_0`.uid = simulationresult_0.primary_key AND `simulationresult$$drops_0`.idx = `simulationresult$$route_0`.idx AND `simulationresult$$backoff_0`.uid = simulationresult_0.primary_key AND `simulationresult$$backoff_0`.idx = `simulationresult$$route_0`.idx    

SELECT simulationresult_0.driver, simulationresult_0.version, simulationresult_0.simid, simulationresult_0.rate, linkentry_0.src, linkentry_0.dst, linkentry_0.txPackets, linkentry_0.rxPackets, linkentry_0.throughput, linkentry_0.drops, linkentry_0.q, linkentry_0.x, linkentry_0.pdr, linkentry_0.qdrops, linkentry_0.backoff
FROM linkentry linkentry_0, `simulationresult$$linkentries` `simulationresult$$linkentries_0`, simulationresult simulationresult_0
WHERE `simulationresult$$linkentries_0`.uid = simulationresult_0.primary_key AND `simulationresult$$linkentries_0`.elm = linkentry_0.primary_key
    """
    def eval50cbr1(self, driver, version, simulationId, loader):
      maxPPS = 470.
      txstart = 100.
      txend = 200. 
      #route = [33, 41, 23, 37, 40, 26, 39, 42, 8]
      route=[6, 48, 11, 28, 30, 15, 40, 18, 16, 45]
      linkEntries = ArrayList()

      params = self.load(loader, simulationId, "Global, Config")
      rate = params.nodeParams[0].flows[route[0]-1].udpTxRate
      data = self.load(loader, simulationId,
          "Global, Net, drop (hist)", false)
      netDrop = None
      if data != None:
        netDrop = data.getLine()
      data = self.load(loader, simulationId, "Global, Mac, backoff (cuml)")
      macBackoff = data.getLine()
      for i in range(1,len(route)):
        link = LinkEntry()
        linkEntries.add(link)
        src = route[i-1]
        dst = route[i]
        link.src = src
        link.dst = dst
        # drops        
        link.drops = float(0.)
        if netDrop != None:
          tmp = filterLine(netDrop, [src], False)
          if len(tmp):
            link.drops = float(tmp[0])
        # backoff
        link.backoff = float(0.)
        tmp = filterLine(macBackoff, [src], False)
        if len(tmp):
          link.backoff = tmp[0] / (txend-txstart) / 1000.
        # rxpackets
        link.rxPackets = 0
        data = self.load(loader, simulationId,
            "Node "+str(dst)+", Trans, arrived packets per flow", false)
        if data != None:
          link.rxPackets = len(filterLine(data.getLine(), [src])) 
        # tx packets
        data = self.load(loader, simulationId, "Node "+str(src)+", Mac, Stats")
        macStats = data.getProperties()
        link.txPackets = macStats.broadcastSend
        link.q = float(link.txPackets) / (txend-txstart) / maxPPS
        link.pdr = float(link.rxPackets) / float(link.txPackets)
        link.x = link.q * link.pdr
        link.throughput = link.rxPackets*1460*8/(txend-txstart)/1024
        link.qdrops = float(link.drops) / (txend-txstart) / maxPPS

      result = SimulationResult()
      result.simid = simulationId
      result.driver = driver
      result.version = version
      result.rate = rate
      result.linkEntries = linkEntries

      return result

    # 50dsrcbr1.1 (33->8)
    # 50dsrcbr1.2 (6->45)
    # 50dsrcbr1.5
    # 50dsrcbr1.6 flows (33->8), (6->45)
    # 50dsrcbr1.7 flows (33->8), (6->45)
    def getSimulationSuite50dsrcbr1(self):
      list = ArrayList()
      for rateA in [x/100. for x in range(0,25)]:
        for rateB in [x/100. for x in range(0,25)]:
          rate = [470. * rateA, 470. * rateB]
          params = self.dsrCbrParams([33, 6], [8, 45], rate)
          list.add(self.setSimParams(params))
      return list
    """
SELECT 
  SimulationResult_0.driver, 
  SimulationResult_0.version, 
  SimulationResult_0.simid, 
  `SimulationResult$$rate_0`.elm AS 'rate0', 
  `SimulationResult$$rate_1`.elm AS 'rate1', 
  NodeEntry_0.flow, 
  NodeEntry_0.transmitter, 
  `NodeEntry$$pdr_0`.idx + 1 AS 'receiver',
  concat(NodeEntry_0.transmitter,' ',`NodeEntry$$pdr_0`.idx + 1) as link, 
   NodeEntry_0.macBackoff, NodeEntry_0.netDrops, 
  NodeEntry_0.txPackets, 
  `NodeEntry$$rxPackets_0`.elm AS 'rxPackets', 
  `NodeEntry$$pdr_0`.elm AS 'pdr', 
  `NodeEntry$$x_0`.elm AS 'x', 
  `NodeEntry$$q_0`.elm AS 'q'
FROM eval50dsrcbr1_6.`NodeEntry$$pdr` `NodeEntry$$pdr_0`, eval50dsrcbr1_6.`NodeEntry$$q` `NodeEntry$$q_0`, eval50dsrcbr1_6.`NodeEntry$$rxPackets` `NodeEntry$$rxPackets_0`, eval50dsrcbr1_6.`NodeEntry$$x` `NodeEntry$$x_0`, eval50dsrcbr1_6.NodeEntry NodeEntry_0, eval50dsrcbr1_6.`SimulationResult$$nodeEntries` `SimulationResult$$nodeEntries_0`, eval50dsrcbr1_6.`SimulationResult$$rate` `SimulationResult$$rate_0`, eval50dsrcbr1_6.`SimulationResult$$rate` `SimulationResult$$rate_1`, eval50dsrcbr1_6.SimulationResult SimulationResult_0
WHERE SimulationResult_0.primary_key = `SimulationResult$$rate_0`.uid AND SimulationResult_0.primary_key = `SimulationResult$$nodeEntries_0`.uid AND `SimulationResult$$nodeEntries_0`.elm = NodeEntry_0.primary_key AND NodeEntry_0.primary_key = `NodeEntry$$pdr_0`.uid AND `NodeEntry$$pdr_0`.uid = `NodeEntry$$x_0`.uid AND `NodeEntry$$pdr_0`.idx = `NodeEntry$$x_0`.idx AND `NodeEntry$$rxPackets_0`.uid = `NodeEntry$$x_0`.uid AND `NodeEntry$$rxPackets_0`.idx = `NodeEntry$$x_0`.idx AND `NodeEntry$$rxPackets_0`.idx = `NodeEntry$$q_0`.idx AND `NodeEntry$$rxPackets_0`.uid = `NodeEntry$$q_0`.uid AND SimulationResult_0.primary_key = `SimulationResult$$rate_1`.uid AND ((`SimulationResult$$rate_0`.idx=0) AND (`SimulationResult$$rate_1`.idx=1))
  AND `NodeEntry$$rxPackets_0`.elm > 0
    """
    def eval50dsrcbr1(self, driver, version, simulationId, loader):
      maxPPS = 470.
      txstart = 100.
      txend = 200. 
      params = self.load(loader, simulationId, "Global, Config")
      nodes = params.nodeNumber[0];
      flows = len(params.nodeParams[0].flows)
      nodeSet = range(1,nodes+1)
      rate = createArray1(len(params.nodeParams[0].flows), 0)
      for i in range(0,len(params.nodeParams[0].flows)):
        rate[i] = params.nodeParams[0].flows[i].udpTxRate / maxPPS
      
      netDrop = None
      macBackoff = None
      data = self.load(loader, simulationId,
          "Global, Net, drop (hist)", false)
      if data != None:
        netDrop = data.getLine()
      data = self.load(loader, simulationId, "Global, Mac, backoff (cuml)")
      macBackoff = data.getLine()

      # rxPackets(rx,tx)
      rxPackets = [None]*(flows)
      for flow in range(0,flows):
        rxPackets[flow] = [None]*(nodes+1)
        for i in nodeSet:
          data = self.load(loader, simulationId,
                "Node "+str(i)+", Routing, receive flow "+str(flow), false)
          if None != data:
            rxPackets[flow][i] = countRx(data.getLine(),len(nodeSet)+1)

      nodeEntries = ArrayList()
      for i in nodeSet:
        for flow in range(0,flows):
          node = NodeEntry()
          node.transmitter = i
          node.flow = flow
          # drops        
          node.netDrops = float(0.)
          if netDrop != None:
            drops = filterLine(netDrop, [i], False)
            if len(drops):
              node.netDrops = float(drops[0])
          # backoff
          node.macBackoff = filterLine(macBackoff, [i], False)[0] / (txend-txstart) / 1000.
          # send
          data = self.load(loader, simulationId,
                "Node "+str(i)+", Mac, forward flow " + str(flow), false)
          if None == data:
            continue
          node.txPackets = len(data.getLine().getYInternal())
          # received + pdr + q + x
          node.rxPackets = createArray1(len(nodeSet),0)
          node.pdr = createArray1(len(nodeSet),0)
          node.q = createArray1(len(nodeSet),0)
          node.x = createArray1(len(nodeSet),0)
          for j in nodeSet:
            if rxPackets[flow][j]==None:
              continue
            node.rxPackets[j-1] = rxPackets[flow][j][i]
            node.pdr[j-1] = float(node.rxPackets[j-1]) / float(node.txPackets)
            node.q[j-1] = float(node.txPackets) / maxPPS / (txend-txstart)
            node.x[j-1] = float(node.rxPackets[j-1]) / maxPPS / (txend-txstart)
          node.rxPackets = array(node.rxPackets, 'd') 
          node.pdr = array(node.pdr, 'd')
          node.q = array(node.q, 'd') 
          node.x = array(node.x, 'd')
          nodeEntries.add(node)

      result = SimulationResult()
      result.simid = simulationId
      result.driver = driver
      result.version = version
      result.rate = array(rate, 'd')
      result.nodeEntries = nodeEntries

      return result
    
    """
SELECT 
  simulationresult_0.driver, 
  simulationresult_0.version, 
  simulationresult_0.simid, 
  simulationresult_0.rate, 
  nodeentry_0.transmitter, 
  nodeentry_0.txPackets, 
  nodeentry_0.netDrops, 
  nodeentry_0.macBackoff, 
  `nodeentry$$pdr_0`.idx + 1 AS 'receiver',
  concat(nodeentry_0.transmitter,' ',`nodeentry$$pdr_0`.idx + 1) as link, 
  `nodeentry$$rxpackets_0`.elm AS 'rxPackets', 
  `nodeentry$$pdr_0`.elm AS 'pdr', 
  `nodeentry$$x_0`.elm AS 'x', 
  `nodeentry$$q_0`.elm AS 'q'
FROM `nodeentry$$pdr` `nodeentry$$pdr_0`, `nodeentry$$q` `nodeentry$$q_0`, `nodeentry$$rxpackets` `nodeentry$$rxpackets_0`, `nodeentry$$x` `nodeentry$$x_0`, nodeentry nodeentry_0, `simulationresult$$nodeentries` `simulationresult$$nodeentries_0`, simulationresult simulationresult_0
WHERE `simulationresult$$nodeentries_0`.uid = simulationresult_0.primary_key AND nodeentry_0.primary_key = `simulationresult$$nodeentries_0`.elm AND `nodeentry$$pdr_0`.uid = nodeentry_0.primary_key AND `nodeentry$$rxpackets_0`.idx = `nodeentry$$pdr_0`.idx AND `nodeentry$$x_0`.uid = `nodeentry$$rxpackets_0`.uid AND `nodeentry$$rxpackets_0`.uid = `nodeentry$$pdr_0`.uid AND `nodeentry$$x_0`.idx = `nodeentry$$rxpackets_0`.idx AND `nodeentry$$q_0`.uid = `nodeentry$$x_0`.uid AND `nodeentry$$q_0`.idx = `nodeentry$$x_0`.idx
  AND not (concat(nodeentry_0.transmitter,' ',`nodeentry$$pdr_0`.idx + 1) in ('6 48','48 11','11 28','28 30','30 15','15 40','40 18','40 22','18 16','16 45','22 43','43 45')
    OR concat(nodeentry_0.transmitter,' ',`nodeentry$$pdr_0`.idx + 1) in ('33 41','41 23','23 37','37 40','40 26','26 39','39 42','42 8'))
    """
    def eval50dsrcbr1_5(self, driver, version, simulationId, loader):
      maxPPS = 470.
      txstart = 100.
      txend = 200. 
      params = self.load(loader, simulationId, "Global, Config")
      nodes = params.nodeNumber[0];
      nodeSet = range(1,nodes+1)
      rate = createArray1(len(params.nodeParams[0].flows), 0)
      for i in range(0,len(params.nodeParams[0].flows)):
        rate[i] = params.nodeParams[0].flows[i].udpTxRate / maxPPS
      
      macSend = [None]
      netReceive = [None]
      netDrop = None
      macBackoff = None
      for i in nodeSet:
        data = self.load(loader, simulationId,
            "Node "+str(i)+", Mac, receive src vs time", false)
        netReceive.append(data)
        data = self.load(loader, simulationId,
            "Node "+str(i)+", Mac, send vs time")
        macSend.append(data)
      data = self.load(loader, simulationId,
          "Global, Net, drop (hist)", false)
      if data != None:
        netDrop = data.getLine()
      data = self.load(loader, simulationId, "Global, Mac, backoff (cuml)")
      macBackoff = data.getLine()

      nodeEntries = ArrayList()
      for i in nodeSet:
        node = NodeEntry()
        node.transmitter = i
        nodeEntries.add(node)
        # drops        
        node.netDrops = float(0.)
        if netDrop != None:
          drops = filterLine(netDrop, [i], False)
          if len(drops):
            node.netDrops = float(drops[0])
        # backoff
        node.macBackoff = filterLine(macBackoff, [i], False)[0] / (txend-txstart) / 1000.
        # send
        line = macSend[i].getLine().getXInternal()
        node.txPackets = len([p for p in line if p >= txstart and p <= txend])
        # received + pdr + q + x
        node.rxPackets = createArray1(len(nodeSet),0)
        node.pdr = createArray1(len(nodeSet),0)
        node.q = createArray1(len(nodeSet),0)
        node.x = createArray1(len(nodeSet),0)
        for j in nodeSet:
          if netReceive[j]==None:
            continue
          line = netReceive[j].getLine()
          packets = filterLine(line, [i], True)
          node.rxPackets[j-1] = len([x for x in packets if x >= txstart and x <= txend])
          node.pdr[j-1] = float(node.rxPackets[j-1]) / float(node.txPackets)
          node.q[j-1] = float(node.txPackets) / maxPPS / (txend-txstart)
          node.x[j-1] = float(node.rxPackets[j-1]) / maxPPS / (txend-txstart)
        node.rxPackets = array(node.rxPackets, 'd') 
        node.pdr = array(node.pdr, 'd')
        node.q = array(node.q, 'd') 
        node.x = array(node.x, 'd')

      result = SimulationResult()
      result.simid = simulationId
      result.driver = driver
      result.version = version
      result.rate = array(rate, 'd')
      result.nodeEntries = nodeEntries

      return result

    
#---------------
# main
#---------------

if (1 < len(sys.argv)):
  driver = SimHiddenNode()
  driver.run(array(sys.argv[1:], String))
