import java.awt.Color;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Scanner;


/**
 * Main Class for JavaFormula1 Project
 * @author Morad
 * @version 3.0
 * @since 2.04.09
 */
public class MainClass {
	
	/**
	 * The main method of this system, gets input from text file.
	 * Writes output to output.txt file
	 * @param args
	 * @throws IOException 
	 * @throws ParseException 
	 */
	public static void main(String[] args) throws IOException, ParseException {
			
	    String command;
	    File f=new File("output.txt");	// declaration of output file
		FileWriter writer=null;			// writer buffer to file declaration
	    writer = new FileWriter(f);		// writer buffer creation 
		
		Scanner input=null;	
		
		DateFormat df = DateFormat.getDateInstance(DateFormat.DATE_FIELD);
	
		SysF1 sys=new SysF1();			// creation of sysF1 object
			
		input = new Scanner(new File("input.txt"));	// creation of connection to input file
		
	    //read the commands
			
		// loop which performed until end of input file [false in [input.hasnext()]		
		while(input.hasNext()){  
		    command = input.next();//read the command, must be first at line.
		       	/*
		    	 * command value determine which method will be activated in sys object.
		    	 */
		    if(command.equals("addRaceDriverToArray")){	
		    	/*
		    	 * Since we established the input method, we read from input file 
		    	 * more data which the method requires.
		    	 */
				sys.addRaceDriverToArray(input.next(),input.next()+" "+input.next(),
						       input.next(),df.parse(input.next()),
						       input.next(),input.nextInt(),input.nextInt(),input.nextInt());
							// This method creates and adds new Race Driver to Race Drivers array
			 }
		     else if (command.equals("addRaceCarToArray")){
		    	   sys.addCarToArray(input.nextInt(),input.nextInt(),input.next(),input.next(),	   
		    			            new Color(input.nextInt(),input.nextInt(),input.nextInt()),
		    			            input.nextInt(),input.nextDouble(),input.nextInt());
		    	   			// This method creates and adds new Race Car to Race Cars array
		     } 
		    else if (command.equals("addRaceCarToDriver")){
		    			// This method attach Race Driver to Race Car
		    	    String driverLicenseNumber=input.next();
		    	    int carLicensePlate=input.nextInt();
		    	    boolean isUpdated=sys.addRaceCarToDriver(driverLicenseNumber,carLicensePlate);
		    	    if(isUpdated){	/* if attached successfully, than true returned, and following message written 
		    	    				output file*/
		    	    		writer.write("addRaceCarToDriver returns: "+
		    	    		        "Successfully adding car "+carLicensePlate+
		    	    		        " to driver "+driverLicenseNumber+"\n");
		    	    }
		    	    else{
		    	    	 	writer.write("addRaceCarToDriver returns: "+
		    	    		        "Failed to add car "+carLicensePlate+
		    	    		        " to driver "+driverLicenseNumber+"\n");
		    	    }
		    	    	
		     }
		     else if(command.equals("getDriverRaceCar")){	/* This method finds the car of a Race Driver
		      													by searching on his driverLicenseNumber*/
		    	 String driverLicenseNumber=input.next();
		    	 RaceCar tempCar=sys.getDriverRaceCar(driverLicenseNumber);
		    	 if(tempCar==null)
		    		 writer.write("\ngetDriverRaceCar returns:\n"+
		    				       "driver "+driverLicenseNumber+" don't have a race car yet!\n");
		    	 else
		    		 writer.write("\ngetDriverRaceCar returns:\n"+
	    				       "driver "+driverLicenseNumber+" have a race car:\n"+
	    				       tempCar);
		     }
		     else if(command.equals("findTheBestRaceDriver")){
		    	 	/*
		    	 	 * This method finds best race driver by his points
		    	 	 */
		    	 writer.write("\nfindTheBestRaceDriver returns:\n"+sys.findTheBestRaceDriver()+"\n");
		     }
		     else if(command.equals("getSortedRaceCars")){
		    	 	/*
		    	 	 * This method returns sorted race car array.
		    	 	 */
		    	 sys.getSortedRaceCars();
		     }
		     else  System.out.printf("Command %s does not exist\n",command);
		}	// end of clause - while input has next
		
		writer.close();	// close writer buffer to output file
		input.close();	// close connection to input file
		System.out.println("[End process]");
		sys.printAll();
	}
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


import java.awt.Color;


public class Car {
	protected String manufacturer;
	protected String model;
	protected int year;
	protected int LicensePlate;
	protected Color colour;
	protected int numDoors;
	
	public Car (int LicensePlate, int year,String manufacturer, String model, 
			Color colour, int numDoors){
		this.manufacturer=manufacturer;
		this.model=model;
		this.year=year;
		this.LicensePlate=LicensePlate;
		this.colour=colour;
		this.numDoors=numDoors;
	}
	
	
	public String getManufacture(){
		return manufacturer;
	}
	public String getModel(){
		return model;
	}
	public int getYear(){
		return year;
	}
	public int getLicensePlate(){
		return LicensePlate;
	}
	public Color getColor(){
		return colour;
	}
	public int getNumDoors(){
		return numDoors;
	}
	
	public void setManufacture(String manufacturer){
		this.manufacturer=manufacturer;
	}
	public void setModel(String model){
		this.model=model;
	}
	public boolean setYear(int year){
		if (year<0)
			return false;
		this.year=year;
		return true;
	}
	public void setLicensePlate(int LicensePlate){
		this.LicensePlate=LicensePlate;
	}
	public void setColor(Color colour){
		this.colour=colour;
	}
	public void setNumDoors(int numDoors){
		this.numDoors=numDoors;
	}
	
	public String toString(){
		return LicensePlate + " " + year + " " + manufacturer + " " + model + 
		" "   + colour + " " + numDoors;
	}
		
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


import java.awt.Color;


public class RaceCar extends Car{
	protected double topSpeed;
	protected int totalRaces;
	protected RaceDriver driver;
	protected double performanceRate=totalRaces/driver.totalScore;


	
	public RaceCar(int LicensePlate,int manuYear,String manufacturer, String 
			model,  Color colour, int numDoors, double topSpeed, int totalRaces){
		super(LicensePlate, manuYear,manufacturer, model, colour, numDoors);
		this.topSpeed=topSpeed;
		this.totalRaces=totalRaces;	
	}
	public double getTopSpeed(){
		return topSpeed;
	}
	public int getRaces(){
		return totalRaces;
	}
	public double getPerRate(){
		return performanceRate;
	}
	public RaceDriver getDriver(){
		return driver;
	}
	
	public void setTopSpeed(double topSpeed){
		this.topSpeed=topSpeed;
	}
	public boolean setRaces(int totalRaces){
		if (totalRaces<0)
			return false;
		this.totalRaces=totalRaces;
		return true;
	}
	
	public void setPerRate(double performanceRate){
		this.performanceRate=performanceRate;
	}
	public void setDriver(RaceDriver driver2){
		this.driver=driver2;
	}
	
	public boolean addRaceDriver(RaceDriver driver){
		if (this.getDriver()==null){
			setDriver(driver);
			return true;
		}
		return false;
	}
	
	public boolean removeDriver(){
		if (this.getDriver()!=null){
			setDriver(null);
			return true;
		}
		return false;
	}
	
	public String toString(){
		return LicensePlate + " " + year + " " + manufacturer + " " + model + 
		" "   + colour + " " + numDoors + " " + topSpeed + " " + totalRaces;
	}
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


import java.util.Date;

public class Driver {
	protected String LicenseNumber;
	protected String fullName;
	protected String Nationality;
	protected Date dateOfBirth = new Date();
	
	public Driver (String LicenseNumber, String fullName, String Nationality, Date dateOfBirth){
		this.LicenseNumber=LicenseNumber;
		this.fullName=fullName;
		this.Nationality=Nationality;
		this.dateOfBirth=dateOfBirth;
	}
	public String getLicenseNumber(){
		return LicenseNumber;
	}
	public String getFullName(){
		return fullName;
	}
	public String getNationality(){
		return Nationality;
	}
	public Date getDateOfBirth(){
		return dateOfBirth;
	}

	
	public void setLicenseNumber(String LicenseNumber){
		this.LicenseNumber=LicenseNumber;
	}
	public void setFullName(String fullName){
		this.fullName=fullName;
	}
	public void setNationality(String Nationality){
		this.Nationality=Nationality;
	}
	public void setDateOfBirth(Date dateOfBirth){
		this.dateOfBirth=dateOfBirth;
	}
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


import java.util.Date;


public class RaceDriver extends Driver{
	protected String team;
	protected int worldChampionships;
	protected int totalScore;
	protected char skillLevel;
	protected int highestRaceFinish; // The winnings number for the Racer
	protected RaceCar car;
	 
	public RaceDriver(String licenseNumber,String fullName, String Nationality,
			Date dateOfBirth,String team,int worldChampionships,int totalScore,
			int highestRaceFinish){
		super (licenseNumber,fullName,Nationality,dateOfBirth);
		this.team=team;
		this.worldChampionships=worldChampionships;
		this.totalScore=totalScore;	
		this.highestRaceFinish=highestRaceFinish;
	}
	

	public String getTeam(){
		return team;
	}
	public int getChampions(){
		return worldChampionships;
	}
	public int getTotalScore(){
		return totalScore;
	}
	public char getSkillLevel(){
		return skillLevel;
	}
	public int getHiRaceFinish(){
		return highestRaceFinish;
	}
	public RaceCar getCar(){
		return car;
	}

	public void setTeam(String team){
		this.team=team;
	}
	public void setChampions(int worldChampionships){
		this.worldChampionships=worldChampionships;
	}
	public void setTotalScore(int totalScore){
		this.totalScore=totalScore;
	}
	public void setSkillLevel(char skillLevel){
		this.skillLevel=skillLevel;
	}
	public void setHiRaceFinish(int highestRaceFinish){
		this.highestRaceFinish=highestRaceFinish;
	}	
	public void setCar(RaceCar car){
		this.car=car;
	}
	
	
	public boolean addRaceCar(RaceCar car){
		if (this.getCar()==null){
			setCar(car);
			return true;
		}
		return false;
	}
	
	public boolean removeCar(){
		if (this.getCar()!=null){
			setCar(null);
			return true;
		}
		return false;
	}

}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


import java.awt.Color;
import java.util.Date;

/**
 * System class for F1 project.
 * @author Morad
 * @version 2.0
 * @since 02.04.09
 */
public class SysF1 {
	/**
	 * Maximum length of any array in this system
	 */
	public static final int MAX_ARRAYS_LENGTH =50;
	/**
	 * Current length of race car array
	 */
	private int current_Length_Car_Array;
	/**
	 * Current length of race driver array
	 */
	private int current_Length_Driver_Array;
	/**
	 * Array of race cars in the system
	 */
	public RaceCar[] carsArr;
	/**
	 * Array of race drivers in the system
	 */
	public RaceDriver[] driversArr;
	/**
	 * Constructor for SysF1 class. 
	 * Perform initialization for race cars array and race drivers array.
	 * @see carsArr
	 * @see driversArr
	 */
	public SysF1() {
		carsArr=new RaceCar[MAX_ARRAYS_LENGTH];
		driversArr=new RaceDriver[MAX_ARRAYS_LENGTH];
	}
	
	/**
	 * This method finds the best race driver - the one with
maximum TotalScore and SkillLevel = D,
	 * also his race car color has to be BLACK. <br/> In case
there are more than one driver suitable 
	 * for this conditions, then return the first one we found. 
	 * @param driversArr
	 * @return best RaceDriver object
	 */
	public RaceDriver findTheBestRaceDriver(){
		int maxTotalScore=0;
		int temp=0;
		for (int i=0;i<driversArr.length;i++){
			if ((driversArr[i]!=null)&&(driversArr[i].totalScore>maxTotalScore)){
				temp=i;
				maxTotalScore=driversArr[i].totalScore;
			}				
		}
		if ((driversArr[temp]!=null)&&(driversArr[temp].totalScore>=300))
		return driversArr[temp];
		else return null;
	}
		



	/**
	 * This method sort race cars Array by performanceRate attribute in 
Acceding order. 
	 * @param driversArr
	 * @return sorted array
	 */
	public RaceCar[] getSortedRaceCars(){
		RaceCar temp;
		for(current_Length_Driver_Array=0;current_Length_Driver_Array<carsArr.
		length -1;current_Length_Driver_Array++)
			for(current_Length_Car_Array=0;current_Length_Car_Array<carsArr.
			length-1-current_Length_Driver_Array;current_Length_Car_Array++){
				
				//compare the two neighbors
				if((carsArr[current_Length_Car_Array]!=null)&&(carsArr[current_Length_Car_Array].performanceRate>
					carsArr[current_Length_Car_Array+1].performanceRate)){ 
					temp=carsArr[current_Length_Car_Array]; //swap
					carsArr[current_Length_Car_Array]=carsArr
					[current_Length_Car_Array+1]; 
					carsArr[current_Length_Car_Array+1]=temp;
				}
			}

		return carsArr;
		
	}
	
	/**
	 * This methods finds the race car which belongs to a race driver
	 * with given driverLicenseNumber as parameter.
	 * @param driverLicenseNumber
	 * @return RaceCar of driver
	 */
	public RaceCar getDriverRaceCar(String driverLicenseNumber){
		for (int i=0;i<driversArr.length;i++)
			if ((driversArr[i]!=null) &&(driversArr[i].LicenseNumber.equals(driverLicenseNumber))){
			return driversArr[i].car;
			}

		return null;
	}

	/**
	 * This method creates and adds new Race Car to Race Cars array.
	 * @param licensePlate
	 * @param year
	 * @param manufacturer
	 * @param model
	 * @param colour
	 * @param numDoors
	 * @param topSpeed
	 * @param totalRaces
	 * @return true if new car added successfully to race cars array, 
	false if array has no room for more cars. 
	*/
	public boolean addCarToArray(int licensePlate,int year, String 
			manufacturer, String model,Color colour,int numDoors, double 
			topSpeed, int totalRaces) {
			for (current_Length_Car_Array=0;current_Length_Car_Array<
			carsArr.length;current_Length_Car_Array++){
				if (carsArr[current_Length_Car_Array]==null){
					carsArr[current_Length_Car_Array]=new RaceCar(licensePlate,
							year,manufacturer, model,colour,numDoors,topSpeed, totalRaces);
					return true;
				}
			}
			return false;
	 }	

	 
	 /** This method creates and adds new Race Driver to Race Drivers array.
	  * @param licenseNumber
	  * @param fullName
	  * @param nationality
	  * @param dateOfBirth
	  * @param team
	  * @param worldChampionships
	  * @param totalScore
	  * @param highestRaceFinish
	  * @return true if new race driver added successfully to race drivers 
	  array, false if array has no room for more drivers. 
	  */

	 
	 public boolean addRaceDriverToArray(String licenseNumber, String fullName
			 ,String nationality,Date dateOfBirth,String team, int 
			 worldChampionships,int totalScore, int highestRaceFinish) {	
			for (current_Length_Driver_Array=0;current_Length_Driver_Array<
			driversArr.length;current_Length_Driver_Array++){
				if (driversArr[current_Length_Driver_Array]==null){
					driversArr[current_Length_Driver_Array]=new RaceDriver
					(licenseNumber,fullName,nationality, dateOfBirth, team,worldChampionships,totalScore , highestRaceFinish);
					return true;
				}
			}
			return false;
	 }	

	 /**
	  * This method creates a connection between race driver to race car,
	  * the method finds a car by carLicensePlate in an array and finds race
driver in drivers
	  * array by driverLicenseNumber. If both objects are found then we can 
relate this specific car to specific 
	  * driver. The adding car to driver performed by sending car object to 
driver and driver object to car.
	  * If driver already has other car connecting a new car will fail, also 
if the car already connected to other driver
	  * new connection will fail. 
	  * @param driverLicenseNumber
	  * @param carLicensePlate
	  * @return true if both objects found and connected, false otherwise.
	  */

	 
	 public boolean addRaceCarToDriver(String driverLicenseNumber,int 
			 carLicensePlate) {
		 if(!driverLicenseNumber.equals("") || carLicensePlate>0){
			RaceCar tempCar = null;
			RaceDriver tempDriver=null;
			for(RaceCar car:carsArr){
				if(car!=null && car.getLicensePlate()==carLicensePlate){
					tempCar=car;
					for(RaceDriver driver:driversArr){
						if(driver!=null && driver.getLicenseNumber().equals
								(driverLicenseNumber)){
							tempDriver=driver;
						}
					}
				}
			}
			
			if(tempCar!=null && tempDriver!= null){
				if(tempCar.addRaceDriver(tempDriver)){
					if(tempDriver.addRaceCar(tempCar)){
						return true;
					}
				}
			}
		}
		 return false;
	 }
	 
	 /**
 	* This Printing all arrays data.
 	*/
	 public void printAll(){
		 for (int i=0;i<carsArr.length;i++)
			 System.out.println(carsArr[i]);
		 for (int j=0 ; j< driversArr.length; j++)
			 System.out.println(driversArr[j]);		 
	 }
}