// LawContinuous.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 LawContinuous
	extends java.applet.Applet
{
	TextArea disp;		// Area to display HT
	
	Panel dispArea;
	Panel controls;		// Panel for user controls
	
	Label numl1;			// Controls
	TextField num1;
	Button go;
	
	GridBagLayout gbl;
	GridBagConstraints cc;
	
	JRandom myRand;
		
	// Initialize applet
	public void init()
	{	
		numl1 = new Label("epsilon =");
		num1 = new TextField(".1", 4);
		
		go = new Button("Go");
		
		disp = new TextArea(15, 20);		// Create display area
		
		dispArea = new Panel();				// Set up window
		controls = new Panel();
		setLayout(new BorderLayout(5, 5));
		
		add("South", controls);
		add("Center", dispArea);
		
		dispArea.setLayout(new GridLayout(1, 1));
		dispArea.add(disp);
		
		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;
		cc.gridwidth = 2;
		gbl.setConstraints(go, cc);
		controls.add(go);
		
		validate();
		
		myRand = new JRandom();
	}
	
	// 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
			{
				disp.setText("");			// Reset output window
        		simulate(Float.valueOf(num1.getText()).floatValue());
        		return true;					// Generate correct number of tosses
			}
		}
		return super.handleEvent(evt);	// Handle other events as usual
	}
	
	public float normal(float x, float mu, float sigma) {
		return 1 / (sigma * (float)  Math.pow(2 * Math.PI, .5)) * 
			(float) Math.pow(Math.E, -1 * Math.pow(x - mu, 2) / (2 * 
				Math.pow((double) sigma, 2)));	
	}
	
	public float normalArea(float a, float b) {
		float mu = 0f;
		float sigma = 1f;
		int subdivisions = (int) Math.max(100, 20 * (double) Math.round(
			(double) b - (double) a + .5));
		float dx = (b - a) / (float) subdivisions;
		float sum = normal(a, mu, sigma) + normal(b, mu, sigma);
		float x;
		for (int k = 1; k < subdivisions; k++) {
			x = a + (float) k * dx;
			if (k % 2 == 1)
				sum += 4 * normal(x, mu, sigma);
			else
				sum += 2 * normal(x, mu, sigma);
		}
		return dx / 3 * sum;
	}
	
	// Calculate probabilities
    public void simulate(float e)
    {	
    	
    	float deviations;
    	float cheb;
    	float actual;
    	disp.appendText("n            P(|Sn / n| >= " + String.valueOf(e) +
    		" )" + "          Chebyshev bound\n\n");
    	
    
    	for (int n = 100; n <= 1000; n += 100) {
    		deviations = (float) Math.pow(n, .5) * e;
    		actual = 1 - normalArea(-1 * deviations, deviations);
    		cheb = 1 / ((float) n * (float) Math.pow((double) e, 2));
    		//disp.appendText(String.valueOf(n) + "                    " 
    			//+ String.valueOf(actual) + "                    " 
    			//+ String.valueOf(cheb) + "\n");
    		disp.appendText(String.valueOf(n));
    		for (int i = String.valueOf(n).length(); i < 10; i++)
    			disp.appendText(" ");
    		disp.appendText(String.valueOf(actual));
    		for (int i = String.valueOf(actual).length(); i < 25; i++)
    			disp.appendText(" ");
    		disp.appendText(String.valueOf(cheb));
    		disp.appendText("\n");
	    }
    }

}