//
//  power.java
//  power
//
//  Created by Chris Thiel on 2/8/05.
//  Copyright (c) 2005 Chris Thiel. All rights reserved.
//  A simple Java applet that allows statistics student 
//  see the relationship of the null hypothesis to different
//  alternatives, and the likelyhood of making a Type I or II error
//  (how alpha beta sigma relate to the power of a hypothesis test
//

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.EventListener;
import java.lang.Math;

public class power extends Applet implements ActionListener,MouseListener,AdjustmentListener,KeyListener, ItemListener {
	Label mu0L, muAL, sigmaL, nL;
	Label[] blank = new Label[28];
	TextField mu0T, muAT, sigmaT, nT;
	Panel wp= new Panel();
	Scrollbar horiz=new Scrollbar(Scrollbar.HORIZONTAL,1,20,-200,143);
    Scrollbar vert=new Scrollbar(Scrollbar.VERTICAL,1,20,1,220);
	double h = 0;
	int v = 1;
	int sdGap=50;
	int center=350;
	double Alpha, Beta;
	double mu0=0;
	double sigma=1;
	double muA=0;
	
	private boolean OneTailed = false;
	private boolean ShowFormula = true;
	double zsig=1.96;
	
     String message = "Power of a Hypothesis Test";
    private Font font1 = new Font("serif", Font.ITALIC + Font.BOLD, 36);
	private Font font2 = new Font("sansserif",0, 9);
	private Font font3 = new Font("serif",Font.BOLD, 18);
	private CheckboxGroup OneOrTwoTailed, AlphaLevel;
	private Checkbox HaGreater,HaLess, HaDiff, a05, a01;
	private Checkbox ShowForm;
    public void init() {
		setBackground(new Color(0xF0F0D0));
		OneOrTwoTailed = new CheckboxGroup();
		HaDiff = new Checkbox("\u03bca \u2260 \u03bc", OneOrTwoTailed, true);
		HaGreater = new Checkbox("\u03bca > \u03bc", OneOrTwoTailed,false);
		HaLess = new Checkbox("\u03bca < \u03bc", OneOrTwoTailed,false);
		
		AlphaLevel = new CheckboxGroup();
		a05=new Checkbox("\u03b1 = .05",AlphaLevel,true);
		ShowForm= new Checkbox ();
		
		a01=new Checkbox("\u03b1 = .01",AlphaLevel,false);
		ShowFormula=false;
		ShowForm.setState(false);
        setLayout (null);
		mu0L= new Label ("\u03bc  =",Label.RIGHT);
		muAL= new Label ("\u03bc  =");
		sigmaL= new Label ("\u03c3  =",Label.RIGHT);
		horiz.addAdjustmentListener(this);
        vert.addAdjustmentListener(this);
		
		nL= new Label (" n =");
		// alpha is 03b1, beta is 03b2
		
		
		mu0T = new TextField ( "0",5);
		muAT = new TextField ( "1",5);
		sigmaT = new TextField ( "1",5);
		nT = new TextField ( "1",5);
		
		setLayout(new BorderLayout());
		wp.setLayout(new GridLayout(16,2));
		
		for(int i=0;i<4;i++){
			blank[i]=new Label();
			wp.add(blank[i]);
			}
		
		wp.add(mu0L);wp.add(mu0T);
		wp.add(sigmaL); wp.add(sigmaT);
		mu0T.addActionListener(this);
		mu0T.addKeyListener(this);
		
		mu0T.addMouseListener(this);
		sigmaT.addActionListener(this);
		sigmaT.addKeyListener(this);
		for(int i=4;i<10;i++){
			blank[i]=new Label();
			wp.add(blank[i]);
			}
		
		blank[8].setText("n  =");
		blank[8].setAlignment(Label.RIGHT);
		wp.add(HaDiff);
		wp.add(HaGreater);
		blank[23]=new Label();wp.add(blank[23]);
		
		wp.add(HaLess);
		blank[24]=new Label("");
		blank[26]=new Label(" ");
		
		blank[25]=new Label("\u03b1 level");
	
		
		wp.add(blank[25]);
		
		wp.add(blank[24]);
		wp.add(blank[26]);	
		wp.add(blank[26]);
		wp.add(a05);
	
		blank[22]=new Label();wp.add(blank[22]);
		wp.add(a01);
		for(int i=10;i<16;i++){
			blank[i]=new Label();
			wp.add(blank[i]);
			}
		
		blank[21]=new Label("Formulas");wp.add(blank[21]);
		wp.add(ShowForm);	
		HaGreater.addItemListener(this);
		HaLess.addItemListener(this);
		HaDiff.addItemListener(this);
		a05.addItemListener(this);
		a01.addItemListener(this);
		
		ShowForm.addItemListener(this);
		
		
		
		add ("West", wp);
		//g.addActionListener(this);
		add("South",horiz);
        add("East",vert);
		vert.setValue(200);
		repaint();
    }
	private double round(double x){
		return Math.round(x*1000)/1000.0;
	}
	private double round4(double x){
		return Math.round(x*10000)/10000.0;
	}
	
	public int Nullpdf(int x){
	// takes a screen x (which is always N[300,sdGap/sqrt[n]], 
	//and returns the screen y pdf based on the null hypothesis
	double s = 1.0/Math.sqrt(v);//sample sd 
	double z = (x-center)/(sdGap*1.0);
	
	double p=Math.exp(-.5*z*z/(s*s))/(s*2.506628275);
	int amp=150;
	if (v<10) {amp=300-6*v;} else {amp=100;}
	return (int)(365-p*amp);
	
	}
	
	public int Altpdf(int x){
	// takes a screen x (which is always N[300,sdGap/sqrt[n]], 
	//and returns the screen y pdf based on the alternative hypothesis
	double s = 1.0/Math.sqrt(v);//sample sd 
	double a = sdGap*1.0*h/sigma;
	double z = (x-center-a)/(sdGap*1.0);
	
	double p=Math.exp(-.5*z*z/(s*s))/(s*2.506628275);
	int amp=150;
	if (v<10) {amp=300-6*v;} else {amp=100;}
	return (int)(365-p*amp);
	
	}
	private double computeBeta(){
	double b=0.0;
	double s=sigma/Math.sqrt(v);
	double me=zsig*s;
	double deltaX=sigma/100.0;
	if (OneTailed && zsig<0){
		for (double i=mu0+me;i<mu0+9*sigma;i+=deltaX) 
			b+=deltaX*Math.exp(-.5*(i-muA)*(i-muA)/(s*s))/(s*2.506628275);
	} else { if (OneTailed && zsig>0) {
		for (double i=mu0-9*sigma;i<mu0+me;i+=deltaX) 
			b+=deltaX*Math.exp(-.5*(i-muA)*(i-muA)/(s*s))/(s*2.506628275);
	} else {
		for (double i=mu0-me;i<mu0+me;i+=deltaX) 
			b+=deltaX*Math.exp(-.5*(i-muA)*(i-muA)/(s*s))/(s*2.506628275);
	}}
	return b;
	}
	public int screenX (double x){
	// will return a horizontal screen coord based on current mu and sigma
		double z = (x-mu0)/(sigma);
		return (int)(center*1.0+z*sdGap*1.0);
	}
	public double NullX (int x){
	// returns the distribution's value based on the horiztal screen coord
	// this is the inverse funtion of screenX
	   return((x-center*1.0)/(sdGap*1.0));
	}
    public void paint (Graphics g) {
		mu0=Double.parseDouble(mu0T.getText());
		sigma=Float.valueOf(sigmaT.getText()).doubleValue();
		muA=mu0+h;
        g.setColor(Color.blue);
        g.setFont(font1);
        g.drawString(message, 160, 40);
		g.setColor(Color.black);
		g.setFont(font3);
		double me=zsig*sigma/Math.sqrt(v);
		// sqrt is \u221A
		
		//g.drawString(" me= "+(mu0+me)+"  h="+h+" mu="+mu0+"zsig="+zsig,150,60);
		if (OneTailed && zsig<0) {
			g.drawString("We reject the null hypothesis if  x\u0305 less than "+round4(mu0+me),170,80);
			}else { if (OneTailed && zsig>0) {
			g.drawString("We reject the null hypothesis if  x\u0305 greater than "+round4(mu0+me),170,80);
			}else { 
			g.drawString("We reject the null hypothesis if  x\u0305 less than "+round4(mu0-me),170,80);
			g.drawString("or greater than "+round4(mu0+me),200,100);
			}}
			// =/- \u00b1
		Beta=computeBeta();
		
		g.setFont(font3);
		g.setColor(Color.red);
		g.setColor(Color.magenta);
		g.drawString("z* = "+zsig,470, 140);
		g.setColor(Color.orange);
		g.drawString("\u03b2 = "+round4(Beta),470,160);
		g.setColor(Color.cyan);
		g.drawString("Power = "+round4(1.0-Beta),470,180);
		g.setColor(Color.red);
		g.drawString("H : \u03bc= "+round(mu0),470,100);
		g.setColor(Color.blue);
		g.drawString("H : \u03bc= "+round(muA),470, 120);
		g.setColor(Color.red);
		g.setFont(font2);
		g.drawString(  "0", 483,105);
		g.setColor(Color.blue);
		g.drawString(  "a", 483,125);
		//Shade rejection area on the H0 distribution
		g.setColor(Color.magenta);
		
		if(OneTailed){
			if (zsig<0){//one sided left
				for (int i=130;i<screenX(mu0+me);i=i+2){ 
					g.drawLine(i, 368,i, Nullpdf(i));
					}
				g.setColor(Color.pink);
				for(int i=screenX(mu0+me);i<600;i+=2) g.drawLine(i,368,i,Nullpdf(i));
				}else{ //then one sided right
				g.setColor(Color.magenta);
				for (int i=screenX(mu0+me);i<600;i+=2){
					g.drawLine(i,368,i,Nullpdf(i));
					}
				g.setColor(Color.pink);
				for(int i=130;i<screenX(mu0+me);i+=2) g.drawLine(i,368,i,Nullpdf(i));
				}
		}else{// two tailed
			for(int i=screenX(mu0+me);i<600;i+=2){
				g.drawLine(i,368,i, Nullpdf(i));
				}
			for (int i=130;i<screenX(mu0-me);i+=2){
				g.drawLine(i,368,i, Nullpdf(i));
				}
			g.setColor(Color.pink);
			for(int i=screenX(mu0-me);i<screenX(mu0+me);i+=2) g.drawLine(i,368,i,Nullpdf(i));
		}
		//Shade rejection area on the Ha distribution
		g.setColor(Color.yellow);
		
		if(OneTailed){
			if (zsig<0){// one tailed left
				g.setColor(Color.cyan);
				for (int i=131;i<screenX(mu0+me);i=i+2){ 
					g.drawLine(i, 368,i, Altpdf(i));
					}
				g.setColor(Color.yellow);
				for(int i=screenX(mu0+me)-1;i<601;i+=2) g.drawLine(i,368,i,Altpdf(i));
				if (ShowFormula) {
					g.setFont( new Font("serif", Font.ITALIC, 14));	
					g.setColor(Color.black);
					g.drawString("\u03b2=P(Z>",200,180);//beta
					g.drawLine(250,175,388,175);
					g.drawString(round(sigma)+" / \u221a"+v,255,190); //sigma, sqrt
					g.drawString("("+round(mu0)+round(zsig)+"("+round(sigma)+"/\u221a"+v+") )-("+round(muA)+")" , 255,168);
					g.drawString("=P(Z> ",205,228);
					g.drawString("("+round4(mu0+me)+")-("+round4(muA)+")",250,220);
					g.drawLine(250,223,388,223);
					g.drawString(round(sigma)+" / \u221a"+v,255,240); 
					g.drawString("=P(Z> "+round4((mu0+me-muA)/(sigma/Math.sqrt(v)))+")", 205 , 260);
					}
				}else{//one tailed right
				g.setColor(Color.cyan);
				for (int i=screenX(mu0+me)+1;i<601;i+=2){
					g.drawLine(i,368,i,Altpdf(i));
					}
				g.setColor(Color.yellow);
				for(int i=131;i<screenX(mu0+me)+1;i+=2) g.drawLine(i,368,i,Altpdf(i));
				if (ShowFormula) {
					g.setFont( new Font("serif", Font.ITALIC, 14));	
					g.setColor(Color.black);
					g.drawString("\u03b2=P(Z<",200,180);//beta
					g.drawLine(250,175,388,175);
					g.drawString(round(sigma)+" / \u221a"+v,255,190); //sigma, sqrt
					g.drawString("("+round(mu0)+"+"+round(zsig)+"("+round(sigma)+"/\u221a"+v+") )-("+round(muA)+")" , 255,168);
					g.drawString("=P(Z< ",205,228);
					g.drawString("("+round4(mu0+me)+")-("+round4(muA)+")",250,220);
					g.drawLine(250,223,388,223);
					g.drawString(round(sigma)+" / \u221a"+v,255,240); 
					g.drawString("=P(Z< "+round4((mu0+me-muA)/(sigma/Math.sqrt(v)))+")", 205 , 260);
					}
				}
		}else{// two tailed
			g.setColor(Color.cyan);
			for(int i=screenX(mu0+me)+1;i<601;i+=2){
				g.drawLine(i,368,i, Altpdf(i));
				}
			g.setColor(Color.cyan);
			for (int i=131;i<screenX(mu0-me);i+=2){
				g.drawLine(i,368,i, Altpdf(i));
				}
			g.setColor(Color.yellow);
			for(int i=screenX(mu0-me)+1;i<screenX(mu0+me);i+=2) g.drawLine(i,368,i,Altpdf(i));
			if (ShowFormula) {
				g.setFont( new Font("serif", Font.ITALIC, 14));	
				g.setColor(Color.black);
				g.drawString("\u03b2=P(", 170,163);
				g.drawString("("+round(mu0-me)+")-("+round(muA)+") < Z < ("+round(mu0+me)+")-("+round(muA)+")",220,160);//beta
				g.drawLine(215,163,300,163);
				g.drawLine(330,163,430,163);
				g.drawString(round(sigma)+" / \u221a"+v,225,180); //sigma, sqrt
				g.drawString(round(sigma)+" / \u221a"+v,375,180); //sigma, sqrt
				g.drawString("= P("+round((mu0-me-muA)/(sigma/Math.sqrt(v)))+" < Z < "+round((mu0+me-muA)/(sigma/Math.sqrt(v)))+")",205,228);
				}
		}
		
		g.setColor(Color.black);
		g.setFont(font2);
		blank[9].setText(" "+v);
		g.drawString(" "+round(mu0), center-8, 380);
		g.drawString(" "+round(mu0-sigma), center-sdGap-11, 380);g.drawString(" "+round(mu0+sigma), center+sdGap-8, 380);
		g.drawString(" "+round(mu0-2*sigma), center-2*sdGap-11, 380);g.drawString(" "+round(mu0+2*sigma), center+2*sdGap-8, 380);
		g.drawString(" "+round(mu0-3*sigma), center-3*sdGap-11, 380);g.drawString(" "+round(mu0+3*sigma), center+3*sdGap-8, 380);
		
		for(int i=center-3*sdGap;i<center+4*sdGap;i+=sdGap) g.drawLine(i,367,i,369);
		//for(double i=mu0-3.6*sigma;i<mu0+3.6*sigma;i=i+.2*sigma){
		//	g.drawLine(screenX(i), Erf(i),screenX(i+.2*sigma),Erf(i+.2*sigma));
		//}
		g.setFont(font2);
		g.setColor(Color.red);
		for(int i=130;i<600;i=i+2){
			g.drawLine(i,Nullpdf(i),i+2,Nullpdf(i+2));
		}
		g.setColor(Color.blue);
		for(int i=130;i<600;i=i+2){
			g.drawLine(i,Altpdf(i),i+2,Altpdf(i+2));
		}
		
    }
	public void mouseClicked(MouseEvent e){}
	public void mouseEntered(MouseEvent e){}
	public void mouseExited(MouseEvent e){
		mu0=Double.parseDouble(mu0T.getText());
		sigma=Float.valueOf(sigmaT.getText()).doubleValue();
		muA=mu0+h;
		repaint();
	
	}
	public void mouseReleased(MouseEvent e){}
	public void mousePressed(MouseEvent e){}
	public void actionPerformed(ActionEvent e){
		mu0=Double.parseDouble(mu0T.getText());
		sigma=Float.valueOf(sigmaT.getText()).doubleValue();
		muA=mu0+h;
		repaint();
	}
	public void keyPressed (KeyEvent e){
		
	}
	public void keyTyped (KeyEvent e){
		
	}
	public void keyReleased (KeyEvent e){
		repaint();
	}

	public void itemStateChanged(ItemEvent e){
		ShowFormula=ShowForm.getState();
		if(HaDiff.getState()==true) {
			if(a05.getState()==true){
				OneTailed=false;
				zsig=1.96;
			}else{
				OneTailed=false;
				zsig=2.576;
			}
		}else if(HaLess.getState()==true){
			if(a05.getState()==true){
				OneTailed=true;
				zsig=-1.645;
			}else {
				OneTailed=true;
				zsig=-2.326;
			}
		}else if(HaGreater.getState()==true){
			if(a05.getState()==true){
				OneTailed=true;
				zsig=1.645;
			}else{
				OneTailed=true;
				zsig=2.326;
			}
		}
		repaint();
	}
	public void adjustmentValueChanged(AdjustmentEvent e){
        //the next if statement checks to see if the AdjustmentEvent
        //came from horiz
        if(e.getAdjustable()==horiz){
            //sets the text in num to the value of horiz
            h = horiz.getValue();
			if(sigma<1) h=h/100.0;
			if(sigma<.1) h=h/10.0;
			
            muA=mu0+1.0*h;
        }
        if(e.getAdjustable()==vert){
            //sets the text in num to the value of horiz
            v = 201-vert.getValue();
			if (v>9){sdGap=50+v;}else{sdGap=50;}
                    }
		repaint();
    }


}

