📄 simulation.java
字号:
import java.util.concurrent.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.InterruptedException;
import java.awt.geom.Line2D.Float;
import java.util.ArrayList;
/**
* A simulation of an airspace containing aircraft, runways, and queues of aircraft.
*
* @author James M. Clarke
* @version 12/03/2007
*/
public class Simulation implements Runnable
{
// The lists of all the aircraft, runways, and queues in the simulation
private java.util.List<Aircraft> aircrafts = java.util.Collections.synchronizedList(new ArrayList<Aircraft>());
private java.util.List<Runway> runways = new ArrayList<Runway>();
private java.util.List<Queue> queues = new ArrayList<Queue>();
// ConcurrentQueues to communicate through
// List of events that have happened to planes
private java.util.Queue<AircraftEvent> aircraftEvents = new ConcurrentLinkedQueue<AircraftEvent>();
// Aircraft to get the GUI to add to the JList
private java.util.Queue<Aircraft> toAdd = new ConcurrentLinkedQueue<Aircraft>();
// Aircraft to get the GUI to remove from the JList
private java.util.Queue<Aircraft> toRemove = new ConcurrentLinkedQueue<Aircraft>();
// The frequency at which planes appear. A plane will appear every "frequency" units of time.
private float frequency = 1;
private int numberOfAircraft;
private int aircraftRemaining;
private int collisions;
private boolean isComplete;
private int timeTaken;
private Level myLevel;
/**
* Constructor for Simulation objects. Creates the initial runways and queues.
*/
public Simulation(Level inLevel)
{
super();
//Add the default runway and queue to the simulation
int airspacesize = 500;
int spacing = airspacesize / (inLevel.getRunways() + 1);
for (int i = 0; i<inLevel.getRunways(); i++)
{
runways.add(new Runway(new Position(265, spacing*(i+1)), (float) Math.PI/2, "Runway " + (i+1)));
}
queues.add(new Queue(new Position(400, 250), (float) Math.PI/2));
//convert from seconds to 10ms intervals
frequency = inLevel.getFrequency()*100F;
numberOfAircraft = inLevel.getNumberOfAircraft();
myLevel = inLevel;
}
public boolean isFinished()
{
return isComplete;
}
public int getCollisions()
{
return collisions;
}
public int getTimeTaken()
{
return timeTaken;
}
/**
* Accessor method for the list of aircraft being simulated
*
* @return a list of aircraft being simulated
*/
public java.util.List<Aircraft> getAircraft()
{
synchronized(aircrafts)
{
java.util.List<Aircraft> temp = new ArrayList<Aircraft>();
for (Aircraft a : aircrafts)
{
temp.add(a);
}
return temp;
}
}
/**
* Accessor method for the list of runways being simulated
*
* @return a list of runways being simulated
*/
public java.util.List<Runway> getRunways()
{
return runways;
}
/**
* Accessor method for the list of queues of aircraft being simulated
*
* @return a list of queues of aircraft being simulated
*/
public java.util.List<Queue> getQueues()
{
return queues;
}
/**
* Accessor method for the queue of requests from the GUI to change the state of aircraft
*
* @return a queue of requests to change the state of aircraft
*/
public java.util.Queue<AircraftEvent> getAircraftEvents()
{
return aircraftEvents;
}
/**
* Accessor method for the queue of aircraft the GUI should add to its list of aircraft.
* This method is provided so that GUIs which keep a list of aircraft in the simulation only need to add new aircraft, rather than refreshing the entire list.
*
* @return a queue of aircraft which the GUI should add to its list of aircraft
*/
public java.util.Queue<Aircraft> getToAdd()
{
return toAdd;
}
/**
* Accessor method for the queue of aircraft the GUI should remove from its list of aircraft
* This method is provided so that GUIs which keep a list of aircraft in the simulation only need to remove aircraft that have been removed, rather than refreshing the entire list.
*
* @return a queue of aircraft which the GUI should remove from its list of aircraft
*/
public java.util.Queue<Aircraft> getToRemove()
{
return toRemove;
}
/**
* Adds an aircraft to the simulation. Aircraft are generated in a random position at the edge of the simulation.
*/
// Add an aircraft to the simulation
public void add()
{
aircraftEvents.add( new AircraftEvent(null, 999, null) );
}
/**
* Returns a random number, where the random numbers have a Poisson distribution with mean "mean".
* This algorithm is taken from Knuth, "The Art of Computer Programming" volume 2.
* @param mean the mean of the distribution
* @return a random number
*/
public static int randomPoisson(int mean)
{
float l = (float) Math.exp(-mean);
int k = 0;
float u;
float p = 1;
java.util.Random r = new java.util.Random();
while(p>=l)
{
k = k+1;
u = r.nextFloat();
p = p * u;
}
return k-1;
}
/**
* Run the simulation. Every 10 milliseconds, the simulation will move on by one unit of time.
* @see java.lang.Runnable
*/
// The main loop
public void run()
{
// keep track of how much time has passed
int elapsed = 0;
int timeTillNext = 0;
aircraftRemaining = numberOfAircraft;
try
{
while (!isComplete)
{
// Randomly add planes to the simulation
if ((timeTillNext == 0) && (aircraftRemaining > 0)) { add(); aircraftRemaining--; timeTillNext = randomPoisson((int) (frequency/10))*10;}
elapsed++;
timeTillNext--;
// Clear out the pending events queue
while (!aircraftEvents.isEmpty())
{
AircraftEvent e = aircraftEvents.poll();
switch (e.getState()) {
case AircraftEvent.ADD: Aircraft a = new Aircraft(runways.get(0), queues.get(0));
synchronized(aircrafts)
{
aircrafts.add(a);
}
toAdd.add(a);
break;
case AircraftEvent.LAND:
if (e.getRunway() == null)
{
e.getAircraft().land();
}
else
{
e.getAircraft().land(e.getRunway());
}
break;
case AircraftEvent.TURNLEFT: e.getAircraft().turnLeft(); break;
case AircraftEvent.TURNRIGHT: e.getAircraft().turnRight(); break;
case AircraftEvent.GOTOQUEUE: e.getAircraft().goToQueue(); break;
case AircraftEvent.LEAVE: e.getAircraft().leave(); break;
}
}
// Remove the landed aircraft
ArrayList<Aircraft> toKill = new ArrayList<Aircraft>();
//Keep track of whether the simulation is finished or not
boolean aPlaneNotFinished = false;
//Loop through all the aurcraft checking whether we need to do anything with them and whether some are in the simulation
synchronized(aircrafts)
{
for (Aircraft b : aircrafts)
{
if (!(b.getState()==7)) {aPlaneNotFinished = true;}
if (!(b.getState() == 5) &&!(b.getState()==7))
{
//check if is landing and is at start of runway
if ((b.getState() == 0) && b.isLanded())
{
b.touchDown();
}
//check if is leaving level and is at edge of map
if ((b.getState() == 6) && (Position.distance(new Position(250, 250), b.where())>250))
{
//add it the list of things to remove
toKill.add(b);
toRemove.add(b);
}
//check if has reached entry point for the queue
if (b.getState() == 3)
{
if (b.isAtQueue()) {b.queue();}
}
// Animate the planes
b.findAngle();
b.move();
}
}
// End the level if everything is finished
if (!aPlaneNotFinished) { timeTaken = elapsed; isComplete = true; ATCSystem.getCurrentUser().addResult(new Result(myLevel, timeTaken, collisions));}
// Collision detection - check if the planes have become too close together
// For each aircraft
for (Aircraft b : aircrafts)
{
//which is in the air and have not been destroyed
if (!(b.getState()==5)&&!(b.getState()==7))
{
// check the other aircraft
for (Aircraft c : aircrafts)
{
//which are in the air
if (!b.equals(c))
{
//which are in the air and have not been destroyed
if (!(c.getState()==5)&&!(c.getState()==7))
{
//to see how far apart they are
if ( (Position.distance(b.where(),c.where())) < 20)
{
//If the planes have become too close together, destroy both of them
b.destroy();
c.destroy();
collisions++;
}
}
}
}
}
}
// remove everything we want to remove
aircrafts.removeAll(toKill);
}
// wait for 10ms
Thread.sleep(10);
}
}
//If anything goes wrong, we are fucked
catch (InterruptedException e)
{
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -