class CollisionException extends Exception{
	private int who, what;



	CollisionException(){
		who  = 0;
		what = 0;
	}



	CollisionException(int who, int what){
		this.who  = who;
		this.what = what;
	}


	
	public void info(){
		System.out.println("A COLLISION WAS DETECTED " + who + " has collided with " + what);
	}
}





class Crossing{
	private boolean[] occupationArray;

	

	Crossing(){
		occupationArray = new boolean[3]; 
		occupationArray[0] = false;
		occupationArray[1] = false;
		occupationArray[2] = false;
	}



	public synchronized void occupied(int who) throws CollisionException{
		occupationArray[who] = true;
	
		System.out.println(Thread.currentThread().getName() + " is at the crossing");
		
		if(who == 0 && occupationArray[1] == true)
			throw new CollisionException(0, 1);
		if(who == 0 && occupationArray[2] == true)
			throw new CollisionException(0, 2);
		if(occupationArray[0] == true && who != 0)
			throw new CollisionException(who, 0);
	}

	

	public synchronized void free(int who){
		occupationArray[who] = false;
	}
			
}





class Car extends Thread{
	Crossing cross;
	int direction; 			/* the values can be 1 to indicate left and 2 to indicate right */
	int distance;

	
	
	Car(){
		cross     = null;
		direction = 0;
		distance  = 0;
	}


	
	Car(Crossing cross, int direction, int distance, String name){
		super(name);

		this.cross     = cross;
		this.direction = direction;
		this.distance  = distance;
	}
	

	
	public void run(){
		try{
			for(int i = distance; i > 0; i--)
				Thread.sleep((int)Math.random()*20);
		
			cross.occupied(direction);
			Thread.sleep(1);
			cross.free(direction);

			System.out.println(getName() + " " + "crossed");
		}
		catch(InterruptedException ie){}
		catch(CollisionException ec){
			ec.info();
		}
	}
}





class Pedestrian extends Thread{
	private Crossing cross;
	private int distance;

	

	Pedestrian(){
		cross = null;
		distance = 0;
	}



	Pedestrian(Crossing cross, int distance){
		super("Pedestrian");
		this.cross    = cross;
		this.distance = distance;
	}



	public void run(){
		try{
			for(int i = distance; i > 0; i--)
				Thread.sleep((int)Math.random()*80);
	
			cross.occupied(0);
			Thread.sleep(1); 
			cross.free(0);
			System.out.println("Pedestrian has crossed over");
		}
		catch(InterruptedException ie){}
		catch(CollisionException ce){
			ce.info();
		}
	}
}





public class SafeCrossing{
	public static void main(String[] arv){
		Crossing cross        = new Crossing();
		Car carFromLeft       =  new Car(cross, 1, 10, "left");
		Car carFromRight      =  new Car(cross, 2, 5, "right");
		Pedestrian pedestrian = new Pedestrian(cross, 8);


		/* Starting the threads */
		carFromLeft.start();
		carFromRight.start();
		pedestrian.start();
	}
}
