// EhrenfestUrn.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 EhrenfestUrn extends java.applet.Applet
{
	Float[] xc1;		// Variables for simulation
	Float[] yc1;
	Float[] xc2;
	Float[] yc2;
	
	LineGraph lg1, lg2;				// AWT elements
	Label numl1, numl2;
	Button go;
	TextField num1, num2;
		
	Panel graphArea;
	Panel controls;

	GridBagLayout gbl;
	GridBagConstraints cc;

	// Set up all controls and put them in the window
	public void init() {
		numl1 = new Label("Number of balls = ");	// Create controls
		numl2 = new Label("Total number of time units = ");
		go = new Button("Go");
		num1 = new TextField("100", 4);
		num2 = new TextField("1000", 4);
		
		graphArea = new Panel();				// Set up window
		controls = new Panel();
		setLayout(new BorderLayout());
	
		add("South", controls);
		add("Center", graphArea);
	
		gbl = new GridBagLayout();
		controls.setLayout(gbl);
		
		cc = new GridBagConstraints();
		
		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;
		cc.gridwidth = 2;
		gbl.setConstraints(go, cc);
		controls.add(go);
		
		lg1 = new LineGraph(); // initialize a graphing space
		lg2 = new LineGraph();
		graphArea.setLayout(new GridLayout(2, 1));
		graphArea.add(lg1);
		graphArea.add(lg2);
	}
	
	// Handle events
	public boolean handleEvent(Event evt)
	{
		if (evt.target instanceof Button)
		{
			if (evt.target == go && evt.id == Event.ACTION_EVENT)	// When button is clicked
			{
        		simulate(Integer.valueOf(num1.getText()).intValue(),
        			Integer.valueOf(num2.getText()).intValue());
        		return true;					// Generate correct number of tosses
			}
		}
		return super.handleEvent(evt);	// Handle other events as usual
	}
	
	// Does the simulation, creating two arrays to store game states, then passes them
	// to a LineGraph
	public void simulate(int b, int n) {
		if (b % 2 == 1)
			b++;
		float yCoord = (float) b/ 2f;		// Running count of game score
		
		xc1 = new Float[n + 1];					// Make arrays
		yc1 = new Float[n + 1];
		xc1[0] = new Float(0);
		yc1[0] = new Float((float) b/ 2f);
		xc2 = new Float[n + 1];					// Make arrays
		yc2 = new Float[n + 1];
		xc2[n] = new Float(n);
		yc2[n] = new Float((float) b/ 2f);
		
		for (int i = 0; i < n; i++) {				// Do actual simulation
			if (yCoord == 0f) 
				yCoord++;
			else if (yCoord == b)
				yCoord--;
			else {
				if (Math.random() > yCoord / (float) b)
					yCoord++;
				else
					yCoord--;	
			}
			xc1[i + 1] = new Float(i + 1);
			yc1[i + 1] = new Float(yCoord);
			xc2[n - (i + 1)] = new Float(n - (i + 1));
			yc2[n - (i + 1)] = new Float(yCoord);
		}
		graphArea.remove(lg1);
		graphArea.remove(lg2);
		lg1 = new LineGraph(xc1, yc1);	// Create new LineGraph
		lg2 = new LineGraph(xc2, yc2);	// Create new LineGraph
		graphArea.add(lg1);							// Put up the graph
		graphArea.add(lg2);							// Put up the graph
		validate();
	}
	
	public Insets insets() {
    	return new Insets(5,5,5,5);
	}
}