Package gld.sim

Source Code of gld.sim.SimModel$SimModelThread

/*-----------------------------------------------------------------------
* Copyright (C) 2001 Green Light District Team, Utrecht University
*
* This program (Green Light District) is free software.
* You may redistribute it and/or modify it under the terms
* of the GNU General Public License as published by
* the Free Software Foundation (version 2 or later).
*
* 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.
* See the documentation of Green Light District for further information.
*------------------------------------------------------------------------*/

package gld.sim;

import gld.Model;
import gld.GLDException;

import gld.algo.dp.*;
import gld.algo.edit.ShortestPathCalculator;
import gld.algo.tlc.*;
import gld.edit.Validation;
import gld.infra.*;
import gld.sim.stats.StatisticsController;
import gld.sim.stats.TrackerFactory;
import gld.utils.Arrayutils;
import gld.utils.NumberDispenser;
import gld.xml.*;

import java.awt.Point;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.*;


import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;


/**
*
* The heart of the simulation.
*
* @author Group Model
* @version 1.0
*/

public class SimModel extends Model implements XMLSerializable
{
 
  private static final String statsCyclesKey = "gld.sim.stats.sender.cycles";
  /** The pseudo-random-number-generator we need in this simulation */
  protected Random generator; 
  /** The second thread that runs the actual simulation */
  protected SimModelThread thread;
  /** The current cycle we're in */
  protected int curCycle;
  /** The Driving Policy in this Simulation */
  protected static DrivingPolicy dp;
  /** The TrafficLightControlling Algorithm */
  protected TLController tlc;
  /** The Thing that makes all Trafficlights shudder */
  protected SignController sgnctrl;
  /** Name of the simulation */
  protected String simName="untitled";
  /** A boolean to keep track if this sim has already run (ivm initialization) */
  protected boolean hasRun = false;
  /** Indicates if roadusers cross nodes or jump over them. */
  public static boolean CrossNodes = true;
 
  /** Indicates wheter the StatisticsSender thread must run or not */
  boolean active = false;
  protected StatisticsSender statsSenderThread = null;
  protected LinkedList spawnFreqsList = null;
  protected Iterator iFreqs = null;
  protected int nroFranja = 0;
 
  protected String file_franjas_key = "gld.sim.timeInterval.source";
  protected ResourceBundle rb = null;
 
  /**
   * Creates second thread
   */ 
  public SimModel() {
    thread = new SimModelThread();
    thread.start();
  //  threadUpdate = new SimModelFreqsUpdate();
    //System.out.println("va a arrancar el thread de configuracion de freqs");
  //  threadUpdate.start();
    curCycle = 0;
    generator = new Random();
    sgnctrl = new SignController(tlc, infra);
   
   
    //GASTON: getting resource bundle
    rb = ResourceBundle.getBundle("simulation");
   
    //GASTON: creting thread to send statistics
    statsSenderThread = new StatisticsSender();
    statsSenderThread.setModel(this);
    statsSenderThread.start();

  }
 
  public void setInfrastructure(Infrastructure i) {
    pause();
   
    super.setInfrastructure(i);
    if(tlc!=null)
      tlc.setInfrastructure(i);
    if(sgnctrl!=null)
      sgnctrl.setInfrastructure(i);
  }

  /** Returns the current cycle */
  public int getCurCycle() { return curCycle; }
  /** Sets the current cycle */
  public void setCurCycle(int c) { curCycle = c; }

  /** Returns the current Driving Policy */
  public static DrivingPolicy getDrivingPolicy() { return dp; }
  /** Sets the current DrivTLController */
  public void setDrivingPolicy(DrivingPolicy _dp) { dp = _dp; }

  /** Returns the current TLController */
  public TLController getTLController() { return tlc; }
  /** Sets the current TLController */
  public void setTLController(TLController _tlc) {
    tlc = _tlc;
    sgnctrl.setTLC(tlc);
  }
 
  /** Returns the random number generator */
  public Random getRandom() { return generator; }
  /** Sets the random number generator */
  public void setRandom(Random r) { generator = r; }

  /** Returns the name of the simulation */
  public String getSimName() { return simName; }
  /** Sets the name of the simulation */
  public void setSimName(String s) { simName = s; }

  /** Returns the pseudo-random-number generator of this Model */
  public Random getRNGen() {return generator;}

  /** Sets spawn frequency for given node and ru type. */
  public void setSpawnFrequency(EdgeNode en, int rutype, float newspawn) {
    en.setSpawnFrequency(rutype, newspawn);
    setChanged();
    notifyObservers();
  }

  /**
   * Stops the simulation.
   * This should only be called when the program exits.
   * To start a new simulation, the simulation should be paused
   * with a call to pause(), then followed by a call to reset(),
   * and finally resumed with unpause().
  */
  public void stop() {
    thread.die();
  }
 
  /**
   * Pauses the simulation
   */
  public void pause() {
    thread.pause();
  }
 
  /**
   * Unpauses the simulation
   */
  public void unpause() {
    thread.unpause();
  }
 
  public boolean isRunning() {
    return thread.isRunning();
  }
 
  /**
   * Resets data
   */
  public void reset() throws SimulationRunningException {
    if (thread.isRunning()) throw new SimulationRunningException("Cannot reset data while simulation is running.");
    infra.reset();
    tlc.reset();
    curCycle = 0;
    generator = new Random();
    TrackerFactory.resetTrackers();

    setChanged();
    notifyObservers();
  }


  public void disableTraffic(Drivelane lane){
   
   
    try {
     
      Road actual_road = lane.getRoad();
      actual_road.setEnabled(false);
      Node[] nodes = infra.getAllNodes();
      for (int i=0;i<nodes.length;i++){
        nodes[i].remAllPaths();
        if (nodes[i] instanceof Junction){
          ((Junction)nodes[i]).updateAllAvailableRoads();
        }
      }
      ShortestPathCalculator spcalculator = new ShortestPathCalculator();
      spcalculator.calcAllShortestPaths(infra);
      /*Validation validation = new Validation(infra);
      validation.validate();*/
     
    }catch(Exception e){
      e.printStackTrace();
    }
     
   
  }

  public void enableTraffic(Drivelane lane){
    try {
     
      Road actual_road = lane.getRoad();
      actual_road.setEnabled(true);
      Node[] nodes = infra.getAllNodes();
      for (int i=0;i<nodes.length;i++){
        nodes[i].remAllPaths();
        if (nodes[i] instanceof Junction){
          ((Junction)nodes[i]).updateAllAvailableRoads();
        }
      }
      ShortestPathCalculator spcalculator = new ShortestPathCalculator();
      spcalculator.calcAllShortestPaths(infra);
    }catch(Exception e){
      e.printStackTrace();
    }
  }






  /**
   * Does 1 step in the simulation. All cars move, pedestrians get squashed etc...
   */
  public void doStep( ) {
   
    curCycle++;
   
    int statisticsInterval = Integer.parseInt(rb.getString(statsCyclesKey));
    if (curCycle% statisticsInterval == 0){
      //GASTON:we try to export runtime information
      sendStatistics();     
    }
    //System.out.println("CurTLC:"+tlc.getXMLName());
    if (! hasRun)
    {  initialize();
      hasRun=true;
    }
    try {
      Enumeration  specialNodes=Arrayutils.getEnumeration(infra.getSpecialNodes());
      while (specialNodes.hasMoreElements())
        ((SpecialNode)(specialNodes.nextElement())).doStep(this);
      moveAllRoadusers();
      spawnNewRoadusers();
      sgnctrl.switchSigns();
    }
    catch (Exception e) {
      System.out.println("The simulator made a booboo:");
      System.out.println(e.getMessage());
      e.printStackTrace();
    }
   
    setChanged();
    notifyObservers();
  }
 
  public void initialize ()
  {  SAVE_STATS = true;
    Enumeration e=Arrayutils.getEnumeration(infra.getSpecialNodes());
    while (e.hasMoreElements())
      ((SpecialNode)(e.nextElement())).start();
     
     
    //GASTON: we load the different spwan frequencies
    spawnFreqsList = new LinkedList();
    InputSource source = new InputSource(rb.getString(file_franjas_key));
    DOMParser parser = new DOMParser();
    try {
      parser.parse(source);
    } catch (SAXException e1) {
      e1.printStackTrace();
    } catch (IOException e1) {
      e1.printStackTrace();
    }
    Document doc = parser.getDocument();
    NodeList nodeList = doc.getElementsByTagName("franja");
    for (int i=0;i<nodeList.getLength();i++){
      System.out.println(nodeList.item(i).getNodeName());
      NodeList edgeNodesList = nodeList.item(i).getChildNodes();
      HashMap spawnFreqsHM = new HashMap();
      for (int j=0;j<edgeNodesList.getLength() ;j++){
        if (!edgeNodesList.item(j).getNodeName().equals("edgenode")) continue;
        String nodeid = null;
        NamedNodeMap nnm = edgeNodesList.item(j).getAttributes();
        if(nnm != null )
        {
          int len = nnm.getLength() ;
          Attr attr;
          for ( int a = 0; a< len; a++ )
          {
            attr = (Attr)nnm.item(a);
            System.out.print(' ' + attr.getNodeName() + "=\"" + attr.getNodeValue() '"' );
            if (attr.getNodeName().equals("id")) nodeid = attr.getNodeValue();
          }
          if (nodeid != null){
            NodeList spawnFreqsList = edgeNodesList.item(j).getChildNodes();
            String[] freqs = {"0.0","0.0","0.0"};
       
            for (int k=0;k < spawnFreqsList.getLength();k++)
            {
              org.w3c.dom.Node nodo= spawnFreqsList.item(k);
              int type = nodo.getNodeType();
              //if (type == org.w3c.dom.Node.)
              String nodeName = nodo.getNodeName();
              //String nodeValue = nodo.getNodeValue();
              //String nodeName = spawnFreqsList.item(k).getNodeName();
              //String nodeValue = spawnFreqsList.item(k).getFirstChild().getNodeValue();
              if (nodeName.equals("car")){
                org.w3c.dom.Node child = nodo.getFirstChild();
                freqs[0] = child.getNodeValue();
              }
              if (nodeName.equals("bus")){
                org.w3c.dom.Node child = nodo.getFirstChild();
                freqs[1] = child.getNodeValue();
              }
              if (nodeName.equals("bicycle")){
                org.w3c.dom.Node child = nodo.getFirstChild();
                freqs[2] = child.getNodeValue();
              }
            }
            spawnFreqsHM.put(nodeid,freqs)
          }
     
        }
   
      }
      spawnFreqsList.add(spawnFreqsHM);
 
       
 
    }
     
    iFreqs = spawnFreqsList.iterator();
    //updateSpawnFreqs();
   
  }
 
  /** Gets the speed of the simulation */
  public int getSpeed() { return thread.getSleepTime(); }
  /** Sets the speed of the simulation */
  public void setSpeed(int s) { thread.setSleepTime(s); }


  /** New road users are placed on the roads when necessary. When roads are full,
   *  new road users are queued.
   */
  public void spawnNewRoadusers() throws InfraException,ClassNotFoundException
  {
    SpecialNode[] specialNodes = infra.getSpecialNodes();
    EdgeNode edge;
    Roaduser r;
    int num_edges=specialNodes.length;
    LinkedList wqueue;
    ListIterator list;
   
    for(int i=0;i<num_edges;i++) {
      if ( ! (specialNodes[i] instanceof EdgeNode) )
        break;
      else
        edge=(EdgeNode)(specialNodes[i]);
      boolean placed = false;
      wqueue = edge.getWaitingQueue();
      list = wqueue.listIterator();
      while(list.hasNext()) {
        r = (Roaduser) list.next();
        if(placeRoaduser(r, edge)) {
          list.remove();
        }
      }
     
      SpawnFrequency[] freqs = edge.getSpawnFrequencies();
      DestFrequency[][] destfreqs = edge.getDestFrequencies();
      int num_freqs = freqs.length;
      int cur_index;
      int[] freqIndexes = new int[num_freqs];
     
      for (int nrs=0;nrs<num_freqs;nrs++)
        freqIndexes[nrs] = nrs;      //Shuffle the indexes
       
      Arrayutils.randomizeIntArray(freqIndexes, generator);
     
      for(int j=0;j<num_freqs;j++) {
        //First try to place new road users on the road.
        cur_index = freqIndexes[j];
        if(freqs[cur_index].freq >= generator.nextFloat()) {
          int ruType = freqs[cur_index].ruType;
          /* Spawn road user of type freqs[i].ruType to a random destination.
          * When all drivelanes are full the road users are queued.
          */
          SpecialNode dest = getRandomDestination( specialNodes, edge, ruType, destfreqs );
          r = RoaduserFactory.genRoaduser(ruType, edge, dest, 0);
          r.setDrivelaneStartTime(curCycle);
          //System.out.println("Origen: " + edge.getId()+ " - Destino: "+dest.getId());
         
          // There might be space for r
          if(!placeRoaduser(r, edge)) {
            // There was no place on any possible lane.
            list.add(r);
          }
        }//end if
      }//end for
    }
  }
 
  /** A road user is placed on the given edge node. When road is full the ru is queued */
  private boolean placeRoaduser(Roaduser r, SpecialNode edge)
  {
    Drivelane found = findDrivelaneForRU(r,edge);
    if(found==null)
      return false;
    else {
      // There is room for me!
      try {
        //System.out.println("Adding RU with type:"+r.getType()+" to lane:"+found.getSign().getId()+" going to Node:"+found.getNodeLeadsTo().getId()+" at pos:"+found.getNodeLeadsTo().isConnectedAt(found.getRoad())+" with type:"+found.getType());
        found.addRoaduserAtEnd(r, found.getLength()-r.getLength());
        r.addDelay(curCycle - r.getDrivelaneStartTime());
        r.setDrivelaneStartTime(curCycle);
        return true;
      }
      catch(Exception e)
      { return false; }
    }
  }
 
  private Drivelane findDrivelaneForRU(Roaduser r, SpecialNode e)
  {
    SpecialNode dest = (SpecialNode) r.getDestNode();
    Drivelane[] lanes = (Drivelane[]) e.getShortestPaths(dest.getId(), r.getType()).clone();
    Arrayutils.randomizeArray(lanes);
    int num_lanes = lanes.length;
    for(int i=0;i<num_lanes;i++) {
      if(lanes[i].isLastPosFree(r.getLength()))
        return lanes[i];
    }
    //System.out.println("Couldnt place RU");
    return null;
 
 
  /** Get a completely random destination, don't choose moi*/
  public SpecialNode getRandomDestination(SpecialNode moi) throws InfraException
  SpecialNode[] dests=infra.getSpecialNodes();
    if (dests.length < 2 )
      throw new InfraException
      ("Cannot choose random destination. Not enough special nodes.");
    SpecialNode result;
    while (moi==(result=dests[(int)(generator.nextFloat()*dests.length)]));
    return result; 
  }
 
  /*Choose a destination*/
  private SpecialNode getRandomDestination( SpecialNode[] dests, SpecialNode here, int ruType, DestFrequency[][] destfreqs )
  {
    //GASTON: ESTA FUNCION DECIDE EL DESTINO. HABRÍA QUE CAMBIAR destfreqs para influir en la decisión
    //destIds: va a tener los ids de los posibles nodos destino
    /*destfreqs: es una matriz con las frecuencias(una fila por cada nodo de tipo EdgeNode, 1 columna por cada ruType (RoadUserType(ej: auto)) ).
    Cada nodo tiene una matriz destfreqs indicando las frecuencias hacia cada nodo destino posible*/
    int[] destIds = here.getShortestPathDestinations(ruType);
    float choice = generator.nextFloat() ; //genero un nro al azar entre 0 y 1
    float total = 0f ;
    /*All frequencies are between 0 and 1, but their total can be greater than 1*/
    for ( int i=0; i<destIds.length ; i++ )  { 
      //sumo todas las frecuencias (entre todos los nodos destino posible) para el ruType correspondiente
      for ( int j=0; j<destfreqs[i].length ; j++ ) {
        if ( destfreqs[destIds[i]][j].ruType == ruType ) {
          total += destfreqs[destIds[i]][j].freq ;
        }
      }
    }
   
    float sumSoFar = 0f ;
    int j = 0 ;
    int index = 0 ;
    boolean foundIndex = false ;
    while ( j<destIds.length && !foundIndex ) {
      //ac� se termina de decidir a qu� nodo destino se ir�
      for ( int i=0; i<destfreqs[j].length ; i++ ) {
        if ( destfreqs[destIds[j]][i].ruType == ruType ) {
          float now =  (destfreqs[destIds[j]][i].freq)/total ;
          if (now+sumSoFar >= choice ) {
            foundIndex = true ;
            index = j;
          }
          else {
            sumSoFar += now ;
          }
        }
      }
      j++;
    }
   
    return dests[destIds[index]] ;
  }
 
  /*Get a random index out of the lanes*/
  private int getRandomLaneNr(Drivelane[] lanes) {
    int ind = (int) Math.floor(generator.nextFloat()*(lanes.length));
    while(ind!=lanes.length)
      ind = (int) Math.floor(generator.nextFloat()*(lanes.length));
    return ind ;
  }
 
  /**
   *
   * moving all Roadusers to their new places
   *
   * @author Blah... why put an author tag at every 10-line piece of code? -> Just because we can! MUHAHAahahahahah!
   */
  public void moveAllRoadusers() throws InfraException
  // Line below is faster than the obvious alternative
    Enumeration  lanes=Arrayutils.getEnumeration(infra.getAllInboundLanes().toArray());
    Drivelane lane;
    while (lanes.hasMoreElements())  {
      lane=(Drivelane)(lanes.nextElement());
      // First you should check wheter they are already moved ......
      if(lane.getCycleMoved() != curCycle)
        moveLane(lane, null);
    }
  }


  /**
   * moving all roadusers from one lane to their new places
   *
   * @author Jilles V, Arne K, Chaim Z and Siets el S
   * @param lane The lane whose roadusers should be moved
   * @param callingLanes Vector of drivelanes, for recursive internal use only, this parameter should have the value null, when called from the outside
     * @version 1.0
   */
  protected void moveLane(Drivelane lane, Vector callingLanes) throws InfraException
  {
    LinkedList queue;
    ListIterator li;
    Drivelane sourceLane, destLane;
    Node node;
    Sign sign;
    Roaduser ru;

    int ru_pos, ru_des, ru_speed, ru_type, ru_len;

    //GASTON: we calculate the statistics for the lane, we will do it in every cycle.
    lane.processStats();
    //
   
    sign = lane.getSign();
    queue = lane.getQueue();
    li = queue.listIterator();
   
    while(li.hasNext())  {
      try
      {
        ru = (Roaduser) li.next();
      }
      catch(Exception e)
      {
        // When this exception is thrown you removed the first element of the queue, therefore re-create the iterator.
        System.out.println("CME");
        li = queue.listIterator();
        continue;       
      }
     
      if(!ru.didMove(curCycle)) {  // Only attempt to move this RU when it hasnt already
        ru.setCycleAsked(curCycle);
        ru_pos   = ru.getPosition();
        ru_speed = ru.getSpeed();
        ru_len   = ru.getLength();
       
        //Calculating the ranges per drivelane in which this roaduser could get intro 
        node = sign.getNode();
        ru_type = ru.getType();
        ru_des  = ru.getDestNode().getId();
       
        Drivelane[] possiblelanes = node.getShortestPaths(ru_des, ru_type);
        int lanes = possiblelanes.length;

        Point[] ranges = new Point[lanes];
       
        // Is our own lane free? If there is any ?????
        if(lanes>=1)
        {
          int i=lane.getPosFree(li,ru_pos,ru_len,ru_speed,ru);
          ranges[0] = new Point(i, ru_pos)//Range on own lane is [i, ru_pos]
 
          lanes--;
          //Is this lane clear, then figure out the other lanes
          if(i==0 && ru_pos-ru_speed <= 0)
          {
            for(; lanes>0; lanes--)  {
              Drivelane test_lane = possiblelanes[lanes];
              int range = test_lane.getLength()-1;
              int max = range - (ru_speed-ru_pos);
              while (test_lane.isLastPosFree(ru_len) && range > max )  {
                range--;           
              }         
              ranges[lanes] = new Point(range, test_lane.getLength()-1)//The range is [range,test_lane]
            }
          }
          else  //Don't even bother, empty the ranges of the other lanes
          {
            for(; lanes>0; lanes--)  {
              ranges[lanes] = new Point(0, 0)//The range is [range,test_lane]
            }
          }
       
        }
        // =======================================
       
        // The R stuff is now calculated
     
       
        // Handle Roadusers that possibly can cross a Node
        if(ru_pos-ru_speed < 0) {
          // Handle Roadusers that get to Special Nodes
          //System.out.println("Possibly can cross...");                   
          if(node instanceof SpecialNode) {
            //System.out.println("At a SpecialNode, will be removed");
              if(ru_pos==0 || 0==lane.getPosFree(li, 0, ru_len, ru_speed, ru)) {
                ru.setPosition(-1);
                ru.setPrevSign(-1);
              li.remove();
              tlc.updateRoaduserMove(ru, lane, sign, ru_pos, null, null, 0, possiblelanes, ranges, null);
              //Give RoadUser to Edgenode to unload stat information
              node.processStats(ru, curCycle, sign);
              ((SpecialNode)(node)).enter(ru);
              ru = null;
            }
          }
          // Handle Roadusers that are (or nearly) at a Sign
          else if(lane.getSign().getType()==Sign.NO_SIGN || lane.getSign().mayDrive()) {
            //System.out.println("nearly at Sign");
            // Can cross-check
            if(ru_pos==0 || 0==lane.getPosFree(li, 0, ru_len, ru_speed, ru)) {
              ru_type = ru.getType();
              ru_des  = ru.getDestNode().getId();


             
              //Drivelane[] lanesleadingfrom = node.getLanesLeadingFrom(lane, ru_type);
              Drivelane[] shortestpaths = node.getShortestPaths(ru_des, ru_type);
             
              Drivelane[] lanesleadingfrom = node.getAvailableLanesLeadingFrom(lane, ru_type);
              destLane = dp.getDirection(ru, lane, lanesleadingfrom, shortestpaths);
             
             
             
              //GASTON: I added this lines to check wheter we could find a path or not
              if (destLane==null){
                //if I we could not find an alternative path for the road users, we erase them from the lane.
                lane.getQueue().clear();
                return;                 
              }
              //FIN DEL CHEQUEO
             
              // Check if there is room on the node
              if(destLane.isLastPosFree(ru_len)) {
                // Let the RU touch the Sign to refresh/unload some statistical data
                // Remove the RU from the present lane, and place it on the destination lane
                try{
                  node.processStats(ru, curCycle, sign);
                  destLane.addRoaduserAtEnd(ru);
                  ru.setPrevSign(lane.getSign().getId());
                  li.remove();
                  tlc.updateRoaduserMove(ru, lane, sign, ru_pos, destLane, destLane.getSign(), ru.getPosition(), possiblelanes, ranges, destLane);
                }
                catch(Exception e) { System.out.println("Something screwd up in SimModel.moveLane where a Roaduser is about to cross:"+e); }
              }           
              // Otherwise, check if the next lane should move, and then do just that
              else {
                // If the position is not free, then check if it already moved this turn, if not:
                if (curCycle != destLane.getCycleAsked())
                {
                  //System.out.println("DestLane hasnt been asked whether it has moved..");
                  if (curCycle != destLane.getCycleMoved())
                  {
                    //System.out.println("Waiting for another lane to move..");
                    Vector ln = callingLanes;                   
                   
                    if (ln==null)
                    {
                      ln = new Vector();
                    }
                    // Detect when there is a cycle of waiting lanes   
                    boolean cycle = false;
                    if (ln.size()>0) if (ln.firstElement()==lane) cycle = true;
                   
                    if (cycle)
                    {
                      // If that's the case, they should all do one step
                     
                      Vector rus = new Vector();   
                   
                      // first remove all first cars of all drivelanes and store them in a vector
                      for (Enumeration e=ln.elements();e.hasMoreElements();)
                      {
                        Drivelane dl = (Drivelane) e.nextElement();
                        Roaduser r   = dl.getFirstRoaduser();
                        rus.addElement(r);
                        dl.remRoaduserAtStart();
                r.setPrevSign(dl.getSign().getId());
                node.processStats(r, curCycle, dl.getSign());
                      }
                     
                      // Rotate all roadusers one position to the right
                      Roaduser r = (Roaduser) rus.elementAt(rus.size()-1);
                      rus.remove(r);
                      rus.insertElementAt(r,0);
                     
                      // Now, all waiting drivelanes can move
                      for (Enumeration e=ln.elements();e.hasMoreElements();)
                      {
                        moveLane((Drivelane) e.nextElement(), null);
                      }
                     
                      // Now place all stored Roadusers back at the end of another drivelane
                      for (int i=0; i<rus.size(); i++)
                      {
                        Drivelane dlFrom = (Drivelane) ln.elementAt(i==0?rus.size()-1:i-1);
                        Drivelane dlTo = (Drivelane) ln.elementAt(i);
                        Roaduser rub = (Roaduser) rus.elementAt(i);
                        dlTo.addRoaduserAtEnd(rub);
                        rub.setCycleMoved(curCycle);
                        Drivelane[] pblanes = dlFrom.getSign().getNode().getShortestPaths(ru_des, ru_type);
                        // TO DO: updateRUMove, including ranges
                //tlc.updateRoaduserMove(ru, dlFrom, dlFrom.getSign(), 0, dlTo, dlTo.getSign(), rub.getPosition(), pbLanes, , destLane);
                      }
                      return;
                    }
                    else
                    {
                        ln.addElement(lane);
                        moveLane(destLane, ln);
                        if (lane.getCycleMoved()==curCycle) return;
                    }
                  }
                }
                // Let the RU touch the Sign to rerfesh/unload some statistical data
                // Ok now the lane that should have moved, moved so try again .........
                if(destLane.isLastPosFree(ru_len)) {
                  // If the position is free, then move
                  try{
                    node.processStats(ru, curCycle, sign);
                    destLane.addRoaduserAtEnd(ru);
                    ru.setPrevSign(lane.getSign().getId());
                    li.remove();
                    tlc.updateRoaduserMove(ru, lane, sign, ru_pos, destLane, destLane.getSign(), ru.getPosition(), possiblelanes, ranges, destLane);
                  }
                  catch(Exception e) {}
                }
                else {
                  // Apperently there was no space created on the lane
                  moveRoaduserOnLane(li, ru, ru_speed, lane);
                 
                  if(ru.getPosition()==ru_pos) {
                    // Couldnt move
                    tlc.updateRoaduserMove(ru, lane, sign, ru_pos, lane, sign, ru_pos, possiblelanes, ranges, destLane);
                  }
                  else {
                    // Did move some
                    tlc.updateRoaduserMove(ru, lane, sign, ru_pos, lane, sign, ru.getPosition(), possiblelanes, ranges, destLane);
                  }
                }
              }
            }
          }
          else {
            if(moveRoaduserOnLane(li, ru, ru_speed, lane)!=ru_speed) {
              // Light wasnt green, so just advanced some steps...
              // Did move some on this lane.
              tlc.updateRoaduserMove(ru, lane, sign, ru_pos, lane, sign, ru.getPosition(), possiblelanes, ranges, null);
            }
            // else Apparently I could overjump my neighbour orso :)
          }
        }
        else {
          /*  This is when the roaduser doesn't go around the corner
            The maximum amount of space per speed is travelled */
          moveRoaduserOnLane(li, ru, ru_speed, lane);     
          if(ru_pos == ru.getPosition()) { // Couldnt move
            tlc.updateRoaduserMove(ru, lane, sign, ru_pos, lane, sign, ru_pos, possiblelanes, ranges, null);
          }
          else // Did move some
            tlc.updateRoaduserMove(ru, lane, sign, ru_pos, lane, sign, ru.getPosition(), possiblelanes, ranges, null);
          }
        }
        if (ru!=null) ru.setCycleMoved(curCycle);               
      }
    }
    lane.setCycleAsked(curCycle);
    lane.setCycleMoved(curCycle);
  }
 
  protected int moveRoaduserOnLane(ListIterator li, Roaduser ru, int speed_left, Drivelane lane) {
    int ru_pos   = ru.getPosition()
    int ru_len   = ru.getLength();
    int best_pos = ru_pos;
    int max_pos = ru_pos;
    int target_pos = (ru_pos - speed_left > 0) ? ru_pos-speed_left : 0;
    //System.out.println("Targetpos:"+target_pos+" and hasPrev:"+li.hasPrevious());

    // Previous should be 'ru'
    Roaduser prv = (Roaduser) li.previous();
     
    if(prv==ru && li.hasPrevious()) {
      prv = (Roaduser) li.previous();
      int prv_pos = prv.getPosition();     
      max_pos = prv_pos + prv.getLength();
      if(target_pos < max_pos && ru instanceof PacCar && !(prv instanceof PacCar))
      {
        // eat it, car-cannibalism!
        if (prv instanceof CustomRoaduser) CustomFactory.removeCustom((CustomRoaduser)prv);
        best_pos = target_pos < prv_pos ? prv_pos : target_pos;
        prv = null;
        li.remove();
      }
      else
      {
        if(max_pos < target_pos)
          best_pos = target_pos;
        else
          best_pos = max_pos;
        li.next();
      }
      //System.out.println("RU had previous, now bestpos ="+best_pos);
    }
    else
      best_pos = target_pos;
   
    li.next();
    if(best_pos != ru_pos) {
      // The Roaduser can advance some positions
      ru.setPosition(best_pos);
      return (speed_left - (ru_pos-best_pos));
    }
    else
    {
      // check for aggressiveness
      if (dp instanceof AggressiveDP)  {
        AggressiveDP adp = (AggressiveDP) dp;
        Drivelane[] shortest = lane.getSign().getNode().getShortestPaths(ru.getDestNode().getId(), ru.getType());
        try{
          if (adp.checkNeighbourLanes(lane, ru, speed_left, shortest)) {
            li.remove();
            ru.setColor(Color.darkGray);
          }
        }
        catch(InfraException e) { System.out.println("Something has become a little too aggressive."); }
      }
      return 0;
    }
  }


/*  public class SimModelFreqsUpdate extends Thread
  {
   
    public SimModelFreqsUpdate(){
    }
   
   
    public void run( ) {
      while (true) {
        try {
          sleep(1000);
          synchronized(this) {
            System.out.println("Se levanto el Thread!!");
            XMLLoader loader=new XMLLoader(new File("../RedesEjemplo/miRedPrueb3.infra"));
            loadAll(loader,getSimModel());
            newInfrastructure(model.getInfrastructure());
            loader.close();
            Enumeration  specialNodes = Arrayutils.getEnumeration(infra.getSpecialNodes());
            while (specialNodes.hasMoreElements())
              ((SpecialNode)(specialNodes.nextElement())).;
            EdgeNode specialNodes[] = infra.getSpecialNodes();
           
          }
        } catch (Exception e) { }
      }   
    }
   
   
   
  }

*/


  /**
   *
   * The second thread that runs the simulation.
   *
   * @author Joep Moritz
   * @version 1.0
   */
  public class SimModelThread extends Thread
  {
    /** Is the thread suspended? */
    private volatile boolean suspended;
    /** Is the thread alive? If this is set to false, the thread will die gracefully */
    private volatile boolean alive;
    /** The time in milliseconds this thread sleeps after a call to doStep() */
    private int sleepTime = 100;
   
    /** Returns the current sleep time */
    public int getSleepTime() { return sleepTime; }
    /** Sets the sleep time */
    public void setSleepTime(int s) { sleepTime = s; }
   
    /**
     * Starts the thread.
     */
    public SimModelThread( ) {
      alive = true;
      suspended = true;
    }
   
    /**
     * Suspends the thread.
     */
    public synchronized void pause( ) {
      suspended = true;
    }
   
    /**
     * Resumes the thread.
     */
    public synchronized void unpause( ) {
      suspended = false;
      notify();
    }
   
    /**
     * Stops the thread. Invoked when the program exitst.
     * This method cannot be named stop().
     */
    public synchronized void die( ) {
      alive = false;
      interrupt();
    }
   
    /**
     * Returns true if the thread is not suspended and not dead
     */
    public boolean isRunning( ) {
      return !suspended && alive;
    }
 
    /**
     * Invokes Model.doStep() and sleeps for sleepTime milliseconds
     */

    public void run( ) {
      while (alive) {
        try {
          sleep(sleepTime);
          synchronized(this) {
            while (suspended && alive)
              wait();
          }
          doStep();
        } catch (InterruptedException e) { }
      }   
    }
  }
 
  // Some XMLSerializable stuff
 
  public void load (XMLElement myElement,XMLLoader loader) throws XMLTreeException,IOException,XMLInvalidInputException
  super.load(myElement,loader);
    setInfrastructure(infra);
    Dictionary loadDictionary;
    try
    loadDictionary=infra.getMainDictionary();
    }
    catch (InfraException ohNo)
    {  throw new XMLInvalidInputException
      ("This is weird. The infra can't make a dictionary for the second "+
        "stage loader of the algorithms. Like : "+ohNo);
    }
    Dictionary infraDictionary=new Hashtable();
    infraDictionary.put("infra",infra);
    loadDictionary.put("infra",infraDictionary);
    boolean savedBySim=("simulator").equals(myElement.getAttribute("saved-by").getValue());
    if (savedBySim)
    {  thread.setSleepTime(myElement.getAttribute("speed").getIntValue());
      simName=myElement.getAttribute("sim-name").getValue();
      curCycle=myElement.getAttribute("current-cycle").getIntValue();
      TLCFactory factory=new TLCFactory(infra);
      tlc = null;
     
        try
        { tlc=factory.getInstanceForLoad
            (factory.getNumberByXMLTagName
       (loader.getNextElementName()));
          loader.load(this,tlc);  
          System.out.println("Loaded TLC "+tlc.getXMLName());  
        }
        catch (InfraException e2)
        { throw new XMLInvalidInputException
          ("Problem while TLC algorithm was processing infrastructure :"+e2);
        }
        tlc.loadSecondStage(loadDictionary);
        DPFactory dpFactory=new DPFactory(this,tlc);
            try
        { dp=dpFactory.getInstance
            (dpFactory.getNumberByXMLTagName
       (loader.getNextElementName()));
          loader.load(this,dp);  
          System.out.println("Loaded DP "+dp.getXMLName());  
        }
        catch (ClassNotFoundException e)
        { throw new XMLInvalidInputException
          ("Problem with creating DP in SimModel."+
           "Could not generate instance of DP type :"+e);
        }
        dp.loadSecondStage(loadDictionary);
        loader.load(this,sgnctrl);
        sgnctrl.setTLC(tlc);
     }
     else {
      curCycle = 0;
     }
     while (loader.getNextElementName().equals("dispenser"))
       loader.load(this,new NumberDispenser());
  }
 
  public XMLElement saveSelf ()
  {   XMLElement result=super.saveSelf();
    result.addAttribute(new XMLAttribute("sim-name",simName));
    result.addAttribute(new XMLAttribute("saved-by","simulator"));
    result.addAttribute(new  XMLAttribute("speed",thread.getSleepTime()));
    result.addAttribute(new XMLAttribute("current-cycle",curCycle));
      return result;
  }
 
  public void saveChilds (XMLSaver saver) throws IOException,XMLTreeException,XMLCannotSaveException
  super.saveChilds(saver)
    System.out.println("Saving TLC "+tlc.getXMLName());
    saver.saveObject(tlc);
    System.out.println("Saving DP "+dp.getXMLName());
    saver.saveObject(dp);
    saver.saveObject(sgnctrl);
  }
 
  protected void restartSpawnFreqs(){

    if (! hasRun)
    { 
      hasRun=true;
      initialize();
    }
    iFreqs = spawnFreqsList.iterator();
    nroFranja = 0;
  }
 
 
  protected void updateSpawnFreqs(){
   
    if (! hasRun)
    { 
      hasRun=true;
      initialize();
    }
   
    HashMap spawnFreqs = null;
   
    //while (true) {
      try {
   
        System.out.println("Se van a cambiar las frecuencias!!");
        if (!iFreqs.hasNext()){
          iFreqs = spawnFreqsList.iterator();
          nroFranja = 0;
        }
        nroFranja ++;
        System.out.println("Franja Horaria: " + nroFranja);
        spawnFreqs = (HashMap)iFreqs.next();
   
       
        Node[] nodos = infra.getAllNodes();
        int k = 0;
        for (int i=0;i<nodos.length;i++){
     
          if (nodos[i] instanceof EdgeNode){
            EdgeNode en = ((EdgeNode)nodos[i]);
            String[] freqs = (String[])spawnFreqs.get(Integer.toString(en.getId()));
            setSpawnFrequency(en,1,Float.parseFloat(freqs[0]));
            setSpawnFrequency(en,2,Float.parseFloat(freqs[1]));
            setSpawnFrequency(en,3,Float.parseFloat(freqs[2]));
          }
          //we could reinit the statistics, so they are not influenced by the old behaviour
          /*anyway, we will not reinit them here, they will be reinitiated after we export the
           * statistics of the current simulation
           */
           /*
          nodos[i].initStats();
          Drivelane[] lanes = nodos[i].getAllLanes();
          for (int j = 0; j < lanes.length; j++) {
            Drivelane drivelane = lanes[j];
            drivelane.initStats();
          }*/
        }
       
      } catch (Exception e) {
        System.out.println("Se lanzó una excepción");
        e.printStackTrace();
      }
      infra.reset();
   
    }
 
 
 
    /**
    * GASTON: Send the statistics to the DLC module.
    */
    public void sendStatistics()
    {
      active = true;
      //new StatisticsController(this);
    }
 
 
 
    public class StatisticsSender extends Thread{
     
      SimModel model = null;
     
     
      boolean alive = true;

     
      public void run() {
        while (alive) {
         
          try {
            synchronized(this){
              while (!active)
                sleep(500);
            }
           
            new StatisticsController(model,rb);
            active = false;
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
     

      public SimModel getModel() {
        return model;
      }

      /**
       * @param b
       */
      public void setAlive(boolean b) {
        alive = b;
      }

      /**
       * @param model
       */
      public void setModel(SimModel model) {
        this.model = model;
      }

    }
 
 
  /**
   * @return
   */
  public ResourceBundle getResourceBundle() {
    return rb;
  }

  /**
   * @param bundle
   */
  public void setResourceBundle(ResourceBundle bundle) {
    rb = bundle;
  }

}
TOP

Related Classes of gld.sim.SimModel$SimModelThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.