// Simulation of more workers and items! // Revision record: // Draft by DIS 2/27/2001 // Revised by Swamy 3/11/2001 // Some additional comments by DIS 3/11/2001 public class p4sp01 { public static int run=1; // initial number of cycles of the simulation // Welcome the user and start the simulation: public static void main(String[] args) { System.out.print("Welcome to BELT! Enter \"p\" to activate pausing: "); TokenReader in = new TokenReader(System.in); runSimulation(in,in.readString()); // flag for pausing } //method main // Run all runs of the simulation: public static void runSimulation(TokenReader in, String pause) { // Initialize stuff Worker w1=new Worker(1); Worker w2=new Worker(2); Worker w3=new Worker(3); Worker w4=new Worker(4); Belt b=new Belt(new Tray(),new Tray(),new Tray(),new Tray()); // Main loop to perform simulation runs while (b.getLastTrayItems()==0) { System.out.println("Current run: "+ run++ ); // post incr! b.Shift_and_Refill(); b.printContents("Old"); b.extractContents(w1,w2,w3,w4); b.printContents("New"); decreaseEff(w1,w2,w3,w4); b.report(); if (pause.equals("p")) in.waitUntilEnter(); // pause } // Report results: System.out.println("The Workers are overloaded!"); System.out.println("Leftovers: "+ b.getLastTrayItems() ); } // method runSimulation // Decrease worker efficiency for next run: public static void decreaseEff(Worker w1, Worker w2, Worker w3, Worker w4) { w1.changeEfficiency(); w2.changeEfficiency(); w3.changeEfficiency(); w4.changeEfficiency(); } } // Class Simulation // Class to contain irritating random() code. Not the best place, // to store them necessarily: class MyMath { // An error term to account for precision in double arithmetic public static double error=1e-5; // Return a random integer in range [low,high]: public static int random(int low, int high) { return (int)(Math.random()*(high-low+1) + low); } // Return a random double in range [low,high]: public static double random(double low, double high) { // Cannot say Math.random()*(high-low+1) since 1 is no longer the // "smallest" double value - causes trouble for eg. if high=1, low=0.85 double a=Math.random()*(high-low+error)+low; // Check if a>high - could be because error>0 if (a>high) a=high; return a; } } // class MyMath // Class Belt has Trays class Belt { private int totalItems; // total amount of items extracted from all Trays private Tray tray1; private Tray tray2; private Tray tray3; private Tray tray4; // Create new Belt with four Trays: Belt(Tray t1, Tray t2, Tray t3, Tray t4) { tray1 = t1; tray2 = t2; tray3 = t3; tray4 = t4; } // Print contents of all trays: public void printContents(String s) { System.out.print(s+" contents: "); System.out.print(tray1.getItems()+" "); System.out.print(tray2.getItems()+" "); System.out.print(tray3.getItems()+" "); System.out.print(tray4.getItems()); System.out.println(); } // Workers extract items from the trays in front of them // increment totalItems and update leftovers public void extractContents(Worker w1, Worker w2, Worker w3, Worker w4) { // each worker takes items from CURRENT tray in front of worker: totalItems += w1.extractItems(tray1)+w2.extractItems(tray2) + w3.extractItems(tray3)+w4.extractItems(tray4); } // Shift Trays to the right and refill first tray public void Shift_and_Refill() { tray4 = tray3; tray3 = tray2; tray2 = tray1; tray1 = new Tray(); // give the first tray new items tray1.fillTray(); } // Report findings: public void report() { System.out.println("Total items taken, so far: "+totalItems); } // Retrieve items on last tray: public int getLastTrayItems() { return tray4.getItems(); } } // Class Belt class Worker { // Setup variables representing worker capacity, // efficiency, efficiency loss: static private final int LOW_ITEM = 2; static private final int HIGH_ITEM = 6; static private final double HIGH_EFF = 1.0; static private final double LOW_EFF = 0.85; static private final double FACTOR = 0.95; // Stuff specific to each individual worker private int position; // position in the line, from L to R private double efficiency; // eff initially ranges 85% to 100% // Construct a new Worker and choose a random efficiency: public Worker(int position) { setEfficiency(); this.position = position; } // Set a random efficiency: private void setEfficiency() { efficiency = MyMath.random(LOW_EFF,HIGH_EFF); } // Reduce current Worker's efficiency: public void changeEfficiency() { efficiency *= FACTOR; } // Extract items from input Tray and update Tray's amount of items: public int extractItems(Tray tr) { // Amount of items current Worker is *able* to take: int items = (int)(efficiency*MyMath.random(LOW_ITEM,HIGH_ITEM) ); // Worker may choose to skip some boxes. // Reduce items depending on position and willingness to skip items: switch(position) { case 1: items -= (items*MyMath.random(0,1))/2; break; case 2: items -= (items*MyMath.random(0,1))/3; break; case 3: items -= (items*MyMath.random(0,1))/4; break; case 4: break; default: System.out.println("Unknown worker"+position);System.exit(0); } // Can remove at most the no. of items on the tray // So if items > # of items on tray empty the tray items=Math.min(items,tr.getItems()); tr.removeItems(items); // Return # of extracted items(possibly 0) return items; } } // Class Worker class Tray { static private final int MIN = 0; // minimum amount of items stored on a Tray static private final int MAX = 5; // maximum amount of items stored on a Tray private int items; // amount of items on current Tray // Construct an empty Tray public Tray() { } // Return the number of items on current Tray public int getItems() { return items; } // Reduce the number of items on current Tray by r // If r>no. of items currently on tray set items to 0 public void removeItems(int r) { items=items-r; if (items<0) items=0; } // Store a random amount of items on the current Tray public void fillTray() { items = MyMath.random(MIN,MAX); } // Return a Boolean value depending on whether or not current Tray is empty public boolean isEmpty() { return (items==0); } } // Class Tray