/*
* File: Aircraft.java
*/
/**
* This package contains the files that support the GUI
* assignment for Semester 2 - 2000
*/
package gui2000;
import java.util.*;
/**
* The <code>Aircraft</code> class represents an individual aircraft
* in the simulated airspace.
* <P>Note: The <code>Aircraft</code> class is only accessible by objects that
* are members of the <code>gui2000</code> package.
* <UL>
* <LI> The call sign of the aircraft
* <LI> The position of the aircraft with respect to the centre of the
* airspace. It is represented as two signed integer values:
* <UL>
* <LI> the number of metres EAST of the centre and
* <LI> the number of metres NORTH
* </UL>
* Negative values represent distances WEST or SOUTH of the centre
* of the airspace.
* <LI> The current heading of the aircraft. The heading is given in degrees
* where a value of 0 means NORTH. Angles are measured colckwise from
* NORTH, so EAST has a value of 90 degrees.
* <LI> The height of the aircraft - in feet
* <LI> The speed of the aircraft measured in kilometres/hour (kph)
* </UL>
* @author T Balls
* @version 0.1, 12-12-99
*
* @see gui2000.Radar
* @see gui2000.Radio
*/
class Aircraft extends java.util.Observable
implements java.lang.Runnable,
java.io.Serializable
{ /**
* Create a new <code>Aircraft</code> object representing one
* particular aircraft in the simulated airspace.
* <P>
* In general, these objects will be loaded from a datafile.
* @param callSign the call sign for this aircraft that can be used
* to identify it over a radio link
* @param east the east/west distance (metres) from centre of the airspace
* @param north the north/south (metres) distance from centre of the airspace
* @param heading the heading in degrees - 0 is NORTH and angles are measured
* clockwise so EAST is 90
* @param height the height in feet above sea level of the aircraft
* @param speed the speed in kilometres per hour of the aircraft.
* @param climbRate in metres/sec represents how fast this aircraft may
* may climb (or dive) in order to change altitude
* @param turnRate in degrees/sec indicates the rate at which this aircraft can
* change heading
*
*/
Aircraft( String callSign,
int east,
int north,
int heading,
int height,
int speed,
int climbRate,
int turnRate,
int secToIncident,
String newCallSign )
{ this.callSign = callSign;
this.east = east;
this.heading = heading;
this.north = north;
this.height = height;
this.speed = speed;
this.climbRate = climbRate;
this.turnRate = turnRate;
this.secToIncident = secToIncident;
this.newCallSign = newCallSign;
}
private String callSign = null;
int east = 0;
int north = 0;
private int heading = 0;
int height =0;
private int speed = 0;
private int climbRate = 0;
private int turnRate = 0;
private int secToIncident = -1;
private String newCallSign = null;
/* Variables related to changes ordered */
private int targetHeading = 0;
private int targetHeight = 0;
private int climbing = 0; // 1 = climbing, -1 = descending
private int turning = 0; // 1 = turn right, -1 = turn left
/**
*
*/
public AircraftData getData()
{ AircraftData d = new AircraftData();
d.callSign = callSign;
d.east = east;
d.north = north;
d.heading = heading;
d.flightLevel = height/100;
d.speed = speed;
return d;
}
/**
* Parse, acknowledge and implement the command from air traffic control
*
* @param command the String to obey
*
* The command string should begin with one of the following four
* instructions:
* <UL>
* <LI> <code>RIGHT</code> to turn clockwise
* <LI> <code>LEFT</code> to turn anticlockwise
* <LI> <code>CLIMB</code> to increase altitude
* <LI> <code>DESCEND</code> to decrease altitude
* </UL>
* The single instruction string should be followed by an integer specifying
* a new flight level (100's of feet) or heading.
* <P>
* A pilot may query an order if it seems to be odd or impossible.
*/
void order( String command )
{ if( callSign.equals( "7600" ) ) return;
if( command.length() == 0 )
{ radio( "Missed your message" );
return;
}
StringTokenizer st = new StringTokenizer( command );
String replyString = null;
String theCommand = null;
String theValue = null;
int value = 0;
try
{ theCommand = st.nextToken();
theValue = st.nextToken();
value = Integer.parseInt(theValue.trim());
}
catch( Exception e )
{ radio( "Do not understand - please repeat" );
return;
}
if( theCommand.equals( "RIGHT" ) )
{ if( (value < 0) || (value > 359) )
{ radio( "Please repeat target bearing" );
return;
}
targetHeading = value;
turning = +1;
replyString = "Turning right to " + value + " degrees";
}
else if( theCommand.equals( "LEFT" ) )
{ if( (value < 0) || (value > 359) )
{ radio( "Please repeat target bearing" );
return;
}
targetHeading = value;
turning = -1;
replyString = "Turning left to " + value + " degrees";
}
else if( theCommand.equals( "CLIMB" ) )
{ if( value > 350 )
{ radio( "Sorry - I'm not a rocket can't get that high" +
"\n\tPlease re-send flight level" );
return;
}
if( value*100 < height )
{ radio( "Cannot comply, am currently at flight level " + height/100 );
return;
}
targetHeight = value*100;
climbing = +1;
replyString = "Climbing to flight level " + value;
}
else if( theCommand.equals( "DESCEND" ) )
{ if( value < 10 )
{ radio( "Isn't that rather low?" +
"\n\tPlease resend flight level" );
return;
}
if( value*100 > height )
{ radio( "Cannot comply, am currently at flight level " + height/100 );
return;
}
targetHeight = value*100;
climbing = -1;
replyString = "Descending to flight level " + value;
}
else
{ radio( "Do not understand - please repeat" );
return;
}
radio( "Wilco : " + replyString );
}
/*
* Send message to Observers
*/
void radio( String message )
{ if( callSign.equals( "7600" ) ) return;
setChanged();
notifyObservers( message );
}
private boolean running = true;
public void run()
{ int sec = 0;
while( running )
{ if( sec == secToIncident )
{ callSign = newCallSign;
}
if( turning != 0 )
{ changeHeading();
}
if( climbing != 0 )
{ changeHeight();
}
north += Math.round((10 * speed*1000/3600 * Math.cos( heading * Math.PI / 180 ))) / 10;
east += Math.round((10 * speed*1000/3600 * Math.sin( heading * Math.PI / 180 ))) / 10;
try
{ Thread.sleep(1000);
sec++;
}
catch( InterruptedException ie )
{}
}
}
private void changeHeading()
{ heading += turning * turnRate;
if( heading < 0 )
{ heading += 360;
}
if( heading > 359 )
{ heading -= 360;
}
if( Math.abs( heading - targetHeading ) < turnRate )
{ heading = targetHeading;
turning = 0;
radio( "Turn completed - heading is " + heading + " degrees" );
}
}
private void changeHeight()
{ height += climbing * climbRate;
if( Math.abs( height - targetHeight ) < climbRate )
{ height = targetHeight;
climbing = 0;
radio( "At new altitude of " + height + " feet" );
}
}
/**
* Provided for debugging purposes
*/
public String toString()
{ return "Aircraft: " + callSign
+ "\tPosition: " + east + "E " + north + "N"
+ "\tHeading: " + heading
+ "\tHeight: " + height
+ "\tSpeed: " + speed;
}
}
|