// Queue.java // Written by Julian Devlin, 8/97, for the text book // "Introduction to Probability," by Charles M. Grinstead & J. Laurie Snell import java.applet.Applet; import java.awt.*; public class Queue extends java.applet.Applet { DLLFloat lx; DLLFloat ly; Float[] waitX; Float[] waitY; Float[] lenX; Float[] lenY; Float[] lenDistX; Float[] lenDistY; LineGraph lg; // AWT elements AreaBarGraph abg, qlbg; Label numl1, numl2, numl3; // Controls Label qlLab, wlLab, qldLab; TextField num1, num2, num3; Button go; Panel graphArea; Panel controls; Panel qlp, wlp, qldp; GridBagLayout gbl; GridBagConstraints cc; JRandom myRand; // Set up all controls and put them in the window public void init() { numl1 = new Label("Avg. arrival time ="); // Create controls num1 = new TextField("2", 2); numl2 = new Label("Avg. service time ="); num2 = new TextField("1", 2); numl3 = new Label("Total time ="); // Create controls num3 = new TextField("1000", 4); go = new Button("Simulate"); graphArea = new Panel(); // Set up window controls = new Panel(); qlp = new Panel(); wlp = new Panel(); qldp = new Panel(); qlp.setLayout(new BorderLayout()); wlp.setLayout(new BorderLayout()); qldp.setLayout(new BorderLayout()); qlLab = new Label("Queue Length"); wlLab = new Label("Wait Time Distribution"); qldLab = new Label("Queue Length Distribution"); qlp.add("South", qlLab); wlp.add("South", wlLab); qldp.add("South", qldLab); setLayout(new BorderLayout(5, 5)); gbl = new GridBagLayout(); cc = new GridBagConstraints(); controls.setLayout(gbl); cc.gridx = 0; cc.gridy = 0; gbl.setConstraints(numl1, cc); controls.add(numl1); cc.gridx = 1; gbl.setConstraints(num1, cc); controls.add(num1); cc.gridx = 0; cc.gridy = 1; gbl.setConstraints(numl2, cc); controls.add(numl2); cc.gridx = 1; gbl.setConstraints(num2, cc); controls.add(num2); cc.gridx = 0; cc.gridy = 2; gbl.setConstraints(numl3, cc); controls.add(numl3); cc.gridx = 1; gbl.setConstraints(num3, cc); controls.add(num3); cc.gridx = 0; cc.gridy = 3; cc.gridwidth = 2; gbl.setConstraints(go, cc); controls.add(go); /*Float[] xx1 = new Float[2]; Float[] yy1 = new Float[2]; xx1[0] = new Float(0); xx1[1] = new Float(1); yy1[0] = new Float(0); yy1[1] = new Float(0); Float[] xx2 = xx1; Float[] xx3 = xx1; Float[] yy2 = yy1; Float[] yy3 = yy1;*/ lg = new LineGraph(); // initialize a graphing space abg = new AreaBarGraph(); qlbg = new AreaBarGraph(); add("Center", graphArea); graphArea.setLayout(new GridLayout(3, 1)); graphArea.add(qlp); graphArea.add(wlp); graphArea.add(qldp); qlp.add("Center", lg); wlp.add("Center", abg); qldp.add("Center", qlbg); add("South", controls); myRand = new JRandom(); } // Make random numbers according to distribution public float nextRand(float l) { float temp = myRand.nextFloat(0, 1); return (float) (Math.log(1 - (double) temp) / (-1 * l)); } // Does the simulation, creating two arrays to store game states, then passes them // to a AreaBarGraph public void simulate(float l, float m, float t) { int[] wy; lx = new DLLFloat(); ly = new DLLFloat(); wy = new int[11]; // Choose different interval?? wy[0] = 0; waitX = new Float[11]; waitY = new Float[11]; float lastArrive = 0; float lastService = 0; float arrive, service; int people = 0; lx.add(new Float(0)); ly.add(new Float(0)); while (lastArrive < t && lastService < t) { // Keep going until simulation time runs out people++; arrive = nextRand(l); service = nextRand(m); lastArrive += arrive; if (lastArrive >= lastService) { // If everyone has been service ( length == 0 ) lastService = lastArrive + service; // service time is service after arrival time lx.end(); ly.end(); lx.add(new Float(lastArrive)); // we arrive, making the length of the q be 1 ly.add(new Float(1)); lx.add(new Float(lastService)); // and leave - it is zero again ly.add(new Float(0)); } else { // already people waiting lastService += service; // add service time to lastService lx.end(); ly.end(); lx.add(new Float(lastService)); // At that time, decrease q length by one ly.add(new Float(ly.curVal().floatValue() - 1)); // bump up all counts after this arrival while(lx.curVal().floatValue() > lastArrive) { // Should check for beginning, but there ly.setCurVal(new Float(ly.curVal().floatValue() + 1)); // will always be a first customer whose lx.back(1); // arrival time is guaranteed to be before ly.back(1); // this one. } lx.add(new Float(lastArrive)); // insert the actual arrival ly.add(new Float(ly.curVal().floatValue() + 1)); } if ((lastService - lastArrive) <= 50) // keep track of wait times of up to fifty wy[(int) Math.ceil((double) (lastService - lastArrive) / 5)]++; // bar graph to closest 5 } while (lastArrive < t) { // add in extra arrivals, even if services are past limit arrive = nextRand(l); lastArrive += arrive; lx.end(); ly.end(); while(lx.curVal().floatValue() > lastArrive) { // Should check for beginning, but there ly.setCurVal(new Float(ly.curVal().floatValue() + 1)); // will always be a first customer whose lx.back(1); // arrival time is guaranteed to be before ly.back(1); // this one. } lx.add(new Float(lastArrive)); // insert the actual arrival ly.add(new Float(ly.curVal().floatValue() + 1)); } // The wait time of the customers is only recorded for those who are completely processed in the time restraint. for (int i = 0; i < waitX.length; i++) { waitX[i] = new Float(i * 5); waitY[i] = new Float((float) wy[i] / (float) people); } qlp.remove(lg); wlp.remove(abg); qldp.remove(qlbg); qlp.remove(qlLab); wlp.remove(wlLab); qldp.remove(qldLab); lenX = lx.toArray(); lenY = ly.toArray(); lenDistX = new Float[11]; // do a distribution of queue lengths of up to 50 lenDistY = new Float[11]; for (int i = 0; i < lenDistX.length; i++) { lenDistX[i] = new Float(i * 5); lenDistY[i] = new Float(0); } lenDistY[0] = new Float((lenX[0].floatValue() - 0f) / (float) t); for (int i = 1; i < lenX.length; i++) { if (lenY[i].floatValue() <= 50) { lenDistY[(int) Math.ceil((double) lenY[i].floatValue() / 5)] = new Float( lenDistY[(int) Math.ceil((double) lenY[i].floatValue() / 5)].floatValue() + (lenX[i].floatValue() - lenX[i - 1].floatValue()) / (float) t); } } lg = new LineGraph(lenX, lenY); abg = new AreaBarGraph(waitX, waitY); // Create new AreaBarGraph qlbg = new AreaBarGraph(lenDistX, lenDistY); qlp.add("Center", lg); wlp.add("Center", abg); qldp.add("Center", qlbg); qlp.add("South", qlLab); wlp.add("South", wlLab); qldp.add("South", qldLab); validate(); // Debugging stuff /* Dimension d; d = lg.size(); qlLab.setText(String.valueOf(d.width) + " " + String.valueOf(d.height)); d = abg.size(); wlLab.setText(String.valueOf(d.width) + " " + String.valueOf(d.height)); d = qlbg.size(); qldLab.setText(String.valueOf(d.width) + " " + String.valueOf(d.height)); */ validate(); } // Watch for a click on the go button public boolean action(Event evt, Object arg) { if (evt.target instanceof Button) { if (evt.target == go && evt.id == Event.ACTION_EVENT) // When button is clicked { simulate(1f / Float.valueOf(num1.getText()).floatValue(), 1f / Float.valueOf(num2.getText()).floatValue(), Float.valueOf(num3.getText()).floatValue()); return true; // Generate correct number of tosses } } return super.handleEvent(evt); // Handle other events as usual } public Insets insets() { return new Insets(5,5,5,5); } }