// Class to run the simulation:

// Chute spews forth boxes:
class Chute { 
    final int LOW = 1;
    final int HIGH = 3;
    Chute() { }
    // assume Chute spews random, but unlimited, amount of boxes:
    int spewBoxes() {
        return (int) (Math.random()*(HIGH-LOW+1)+LOW);
    }
} 

// Bin holds boxes that spew forth from Bin:
class Bin { 
    int boxes;
    final int MAXBOXES = 7;
    Bin() { }
}    

// Worker unloads boxes from Bin and places them in the Truck:
class Worker { 
    int id;
    String name;
    double efficiency = 1;
    final int CYCLECOUNT = 4;
    int boxes; // boxes currently carrying
    final int LOW = 1;
    final int HIGH = 3;
    Worker() { }
    int extractBoxes() {
        return (int) (efficiency*Math.random()*(HIGH-LOW+1)+LOW);
    }
}

// Truck holds boxes left over:
class Truck {
    int boxes;
}

public class Simulation {

    public static void main(String[] args) {
	
        // Set up initial values:
	   int cycles = 0 ; // cycles so far
	   Worker worker1 = new Worker();
	   Chute  chute1  = new Chute();
	   Bin    bin1    = new Bin();
	   Truck  truck1  = new Truck();
	
	// Attempt to add boxes to Bin:

           System.out.println("-----------------------------------");
	   int boxesToAdd =  chute1.spewBoxes(); // boxes from Chute so far
	   
	   while ( (bin1.boxes + boxesToAdd) <= bin1.MAXBOXES ) {
	       
	       // Boxes go from Chute to Bin
	          System.out.println("Adding boxes to Bin:\t"+boxesToAdd);
		  cycles++;                      // increment count of cycles
		  bin1.boxes += boxesToAdd;      // increment boxes in Bin
		  
		  System.out.println("Current boxes in Bin:\t"+bin1.boxes);

               // Boxes go from Bin to Worker to Truck:
		  int boxesTaken = worker1.extractBoxes();
		  if (boxesTaken <= bin1.boxes) {
		      truck1.boxes += boxesTaken;
		      bin1.boxes -= boxesTaken;
		  } else {
		      truck1.boxes += bin1.boxes;
		      bin1.boxes = 0;
		  }
		  
		  System.out.println("Boxes taken by Worker:\t" + boxesTaken);
		  System.out.println("Boxes left in Bin:\t"     + bin1.boxes);
		  System.out.println("Boxes stored in Truck:\t" + truck1.boxes);
		  
               // Reduce Worker's capacity for carrying boxes every 4th cycle:
		  if (cycles % worker1.CYCLECOUNT == 0) {
		      worker1.efficiency *= 0.75;
		      System.out.println("New efficiency!\t"+worker1.efficiency);
		  }

	       // Obtain more boxes from Chute:
		  boxesToAdd = chute1.spewBoxes();
		  System.out.println("-----------------------------------");
		  
	   } // end while
	
        // Report results:
	   System.out.println("Final boxes on Truck:\t"  + truck1.boxes );
	   System.out.println("Count of cycles:\t"       + cycles );
	   System.out.println("Leftover boxes in Bin:\t" + bin1.boxes );
	   
    } // method main
        
} // class Simulation

// introduce encaps as next stage
// later could make portions static (Chute, Truck fields?)
// another class myMath to hold myRandom method?
