// Starts the simulation. It will end when no more packets are in the
  // medium
  public void runSimulator() {
    Event next;
    Packet p;

    while (true) {
      next = eventList.removeNext();

      if (next == null) {
        break;
      }

      if (traceLevel > 1) {
        System.out.println();
        System.out.println(
            "main(): event received.  t=" + next.getTime() + ", node=" + next.getEntity());
        if (next.getType() == FROMLAYER2) {
          p = next.getPacket();
          System.out.print("  src=" + p.getSource() + ", ");
          System.out.print("dest=" + p.getDest() + ", ");
          System.out.print("contents=[");
          for (int i = 0; i < NUMENTITIES - 1; i++) {
            System.out.print(p.getMincost(i) + ", ");
          }
          System.out.println(p.getMincost(NUMENTITIES - 1) + "]");
        } else if (next.getType() == LINKCHANGE) {
          System.out.println("  Link cost change.");
        }
      }

      time = next.getTime();

      if (next.getType() == FROMLAYER2) {
        p = next.getPacket();
        if ((next.getEntity() < 0) || (next.getEntity() >= NUMENTITIES)) {
          System.out.println("main(): Panic. Unknown event entity.");
        } else {
          entity[next.getEntity()].update(p);
        }
      } else if (next.getType() == LINKCHANGE) {
        if (time < 10001.0) {
          cost[0][1] = 20;
          cost[1][0] = 20;
          entity[0].linkCostChangeHandler(1, 20);
          entity[1].linkCostChangeHandler(0, 20);
        } else {
          cost[0][1] = 1;
          cost[1][0] = 1;
          entity[0].linkCostChangeHandler(1, 1);
          entity[1].linkCostChangeHandler(0, 1);
        }
      } else {
        System.out.println("main(): Panic.  Unknown event type.");
      }
    }

    System.out.println("Simulator terminated at t=" + time + ", no packets in medium.");
  }
  /**
   * ** Warning! This will allow an entity to send packets that they couldn't possibly send (e.g.
   * Entity 1 could send a packet from 0 to 3). This should be fixed later... ***
   */
  public static void toLayer2(Packet p) {
    Packet currentPacket;
    double arrivalTime;

    if ((p.getSource() < 0) || (p.getSource() >= NUMENTITIES)) {
      System.out.println("toLayer2(): WARNING: Illegal source id in " + "packet; ignoring.");
      return;
    }
    if ((p.getDest() < 0) || (p.getDest() >= NUMENTITIES)) {
      System.out.println("toLayer2(): WARNING: Illegal destination id " + "in packet; ignoring.");
      return;
    }
    if (p.getSource() == p.getDest()) {
      System.out.println(
          "toLayer2(): WARNING: Identical source and " + "destination in packet; ignoring.");
      return;
    }
    if (cost[p.getSource()][p.getDest()] == 999) {
      System.out.println(
          "toLayer2(): WARNING: Source and destination " + "not connected; ignoring.");
      return;
    }

    if (traceLevel > 2) {
      System.out.println("toLayer2(): source=" + p.getSource() + " dest=" + p.getDest());
      System.out.print("             costs:");
      for (int i = 0; i < NUMENTITIES; i++) {
        System.out.print(" " + p.getMincost(i));
      }
      System.out.println();
    }

    arrivalTime = eventList.getLastPacketTime(p.getSource(), p.getDest());
    if (arrivalTime == 0.0) {
      arrivalTime = time;
    }
    arrivalTime = arrivalTime + 1.0 + (rand.nextDouble() * 9.0);

    if (traceLevel > 2) {
      System.out.println("toLayer2(): Scheduling arrival of packet.");
    }

    currentPacket = new Packet(p);
    eventList.add(new Event(arrivalTime, FROMLAYER2, currentPacket.getDest(), currentPacket));
  }