FileDocCategorySizeDatePackage
Aircraft.javaAPI DocExample8955Sun Feb 13 17:12:30 GMT 2000gui2000

Aircraft.java

/*   
 * 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;
   }
}