/*
 * Created on Jan 18, 2005
 */
package javax.realtime.test.airplane;

import javax.realtime.DSS.DSS;

/**
 * A simple illustration of the airplane accident scenario described in
 * Asaf Degani's book <i>Taming HAL</i>.
 * @author gary
 */
public class TestAirplane {

	/**
	 * The main program.
	 * @param args one argument is used: a boolean indicating whether randomization
	 * should be used in selection among events scheduled at same time.  There are 
	 * two different interpretations of this:
	 * <il> <li> Under <i>native Java</i>, a pseudo random selection is made
	 * <li> Under <i>JPF</i>, all selections are tried nondeterministically, e.g., under
	 * backtracking
	 * </il>
	 */
	public static void main(String[] args) {
		
		// final int oneMillionNoOpsPerSecond = 1000000;
		// CPU cpu = new CPU( "CPU", oneMillionNoOpsPerSecond );
		
		boolean randomize = false;
		
		if ( args.length > 0 && args[0].equals("true")) {
			randomize = true;
		}

		try {		
			if ( DSS.usingJPF ) {
				System.out.println( "Running under JPF" );
			} else {
				System.out.println( "Running under native JVM" );			
			}
			
			/* 
			//Code from preliminary tests, commented out here to streamline code
			CycleBurner cycleBurner = new CycleBurner( "Cycle burner", 1, cpu );
			cycleBurner.initialize();
			DSS.activate( cycleBurner );
			
			DSS.printTime(); 
			System.out.println( 
					"Starting airplane example with randomize == " + 
					randomize );		
			
			// all seed processes now initialized (passivated)				
			DSS.runSimulation( randomize );

			int randomLow = 0;
			int randomHigh = 10;
			double randomMean = (double)((randomHigh + randomLow)/2);
			double normalMean = 50.0;
			double normalStandardDeviation = 25.0;
			double erandMean = 0.5;
			double erandStandardDeviation = erandMean;
			
			Random random = new Random( randomLow, randomHigh );
			Normal normal = new Normal( normalMean, normalStandardDeviation );
			Erand erand = new Erand( erandMean );
			
			int i;
			
			int randomSum = 0;
			double erandSum = 0.0;
			double normalSum = 0.0;
			
			// assuming mean as specified
			double randomVarianceSum = 0.0;
			double normalVarianceSum = 0.0;
			double erandVarianceSum = 0.0;

			int cycles = 100;
			for ( i = 0; i<cycles; i++ ) {
				int randomDraw = random.draw();
				double normalDraw = normal.draw();
				double erandDraw = erand.draw();
				
				randomSum += randomDraw;
				normalSum += normalDraw;
				erandSum += erandDraw;
				
				double randomDiff = (double)randomDraw - randomMean;
				randomVarianceSum += randomDiff * randomDiff;
				
				double normalDiff = (double)normalDraw - normalMean;
				normalVarianceSum += normalDiff * normalDiff;
				
				double erandDiff = (double)erandDraw - erandMean;
				erandVarianceSum += erandDiff * erandDiff;			
			}
			
			System.out.println( "Observed random mean = " + ((float)randomSum)/(float)cycles +
					", cf. " + randomMean );
			System.out.println( "Observed normal mean = " + ((float)normalSum)/(float)cycles +
					", cf. " + normalMean );
			System.out.println( "Observed erand mean = " + ((float)erandSum)/(float)cycles +
					", cf. " + erandMean );
			
			System.out.println( "Observed random s.d. = " + 
					Math.sqrt(((float)randomVarianceSum)/(float)cycles) );
			System.out.println( "Observed normal s.d. = " + 
					Math.sqrt(((float)normalVarianceSum)/(float)cycles) +
					", cf. " + normalStandardDeviation  );
			System.out.println( "Observed erand s.d. = " + 
					Math.sqrt(((float)erandVarianceSum)/(float)cycles) +
					", cf. " + erandStandardDeviation );
			
			if ( DSS.usingJPF ) {
				System.out.println( "Random choice " + erand.twoChoice() );
				
			RealtimeThread testAltitude = new TestAltitude( "Test Altitude" );
			testAltitude.initialize();
			DSS.activate(testAltitude);
			DSS.runSimulation();
			
			airplane = new Airplane( 0 );
			AsynchEvent flapsSet = new AsynchEvent();
			AsynchEventHandler flapsSetHandler = new AsynchEventHandler() {
				public void handleAsynchEvent() {
					DSS.printTime();
					System.out.println( "flaps set to " + 
							TestAirplane.airplane.getFlapsDegrees() + " degrees" );
				}
			};
			

			flapsSet.addHandler( flapsSetHandler );
			RealtimeThread changeFlaps = new ChangeFlaps( "Test Flaps", 0, flapsSet );
			changeFlaps.initialize();
			DSS.activate(changeFlaps);
			DSS.runSimulation();
			
			airplane = new Airplane( 0 );
			AsynchEvent gearChange = new AsynchEvent();
			AsynchEventHandler gearChangeHandler = new AsynchEventHandler() {
				public void handleAsynchEvent() {
					DSS.printTime();
					System.out.println( "gear now " + 
							TestAirplane.airplane.gearString( false ) );
				}
			};
			
			gearChange.addHandler( gearChangeHandler );
			RealtimeThread changeGear = 
				new ChangeLandingGear( "Gear Change", 0, airplane, gearChange);
			changeGear.initialize();
			DSS.activate( changeGear );
			DSS.runSimulation();
			*/
			
			airplane = new Airplane( 0 );
			
			// Pilot class performs scenario
			pilot = new Pilot( "pilot", 0 );
			pilot.initialize();
			DSS.activate( pilot );
			
			DSS.runSimulation();
			
		} catch ( Exception e ) {
			System.out.println( e );
			e.printStackTrace();
		}
	}
	
	public static Airplane airplane;
	public static Pilot pilot;
}

