/*
	Scatterplot applet takes pairs of numbers from a HTML
	TEXTAREA FORM field, and computes Means and R square
	Version 1.0 - 15 Aug 1999 Chris Thiel <cct@ktb.net>
	 To do: 
	     have an option to manually specify a scale
	     put scale on edge
*/

import java.lang.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Event;
import java.util.*;

public class Scatterplot extends Applet
{
	int MAX=50;
	int Margin =50;
	int n=0;
	String userInput=null;
	String s=null;
	float x[] = new float[MAX];
	float y[] = new float[MAX];
	float xMean, yMean;
    float B0, B1, R_square,Var_x,Var_y;
    double maxX = 0.0;
	double maxY = 0.0;
	double minX = 9999.9;
	double minY = 9999.9;
	double Xscale =1;
	double Yscale =1;

	int i=0;
	
/*
	Compute is the routine called to compute the Statistical Data
*/	

	public void  compute(){
	// Now calculate regression coeffecients
    	float Sx = 0, Sy =0;
    	float Sxx = 0, Sxy = 0, Syy = 0;
    	maxX = 0.0;
		maxY = 0.0;
		minX = 9999.9;
		minY = 9999.9;
		
    	for(int i=0; i< n; i++)
    	{
    		if (x[i] > maxX) maxX = x[i];
    		if (x[i] < minX) minX = x[i];
    		if (y[i] > maxY) maxY = y[i];
    		if (y[i] < minY) minY = y[i];
    		
      		
      		Sx += x[i]; 
      		Sy += y[i];
    	}
    	Xscale = (size().width-2*Margin) /(maxX -minX);
    	Yscale = (size().height-2*Margin)/(maxY -minY);
    	xMean = Sx / n;
    	yMean = Sy / n;
    	for(int i=0; i< n; i++)
    	{
      		Sxx += (x[i]-xMean) * (x[i]-xMean);
      		Sxy += (x[i]-xMean) * (y[i]-yMean);
      		Syy += (y[i]-yMean) * (y[i]-yMean);
    	}
    	B1=Sxy/Sxx;
    	B0 = yMean - B1 * xMean;
    	R_square=(Sxy*Sxy)/(Sxx*Syy);
	}
	
 /**parse the user's input String from an HTML document */
    public void setString (String userInput) {
	i=0; //reset number of pairs
	//convert new line chars from unix/win
	userInput.trim(); 
	while (userInput.indexOf("\n") >=0) {
	   userInput= 
	     userInput.substring(0, userInput.indexOf("\n")) + " ; " +
	     userInput.substring(userInput.indexOf("\n")+1);
	}
	//convert return chars from macs 
	while (userInput.indexOf("\r") >=0) {
	   userInput= 
	     userInput.substring(0, userInput.indexOf("\r")) + " ; " +
	     userInput.substring(userInput.indexOf("\r")+1);
	}
	if ( !(userInput.endsWith(" ; "))) userInput = userInput+" ; ";
	StringTokenizer t= new StringTokenizer(userInput, " ", false);
	
	// Now that the lines are cleaned up read in pairs  
	while ((t.hasMoreTokens()) && (i<MAX)) {
	  s = t.nextToken();
	  if (s.charAt(0)!=';'){	
	  x[i]=Float.valueOf(s).floatValue(); 
      y[i]=Float.valueOf(t.nextToken()).floatValue(); 
      if (t.hasMoreTokens() ) s=t.nextToken();// the ; separator
		i++;
	  }
	}//end of while loop
	n = i;
	if (n > 0) {compute();}
	repaint();
    }// of parsing the userInput string
    
    public void init() {
    	i =0;
		repaint();
	}
	/***********************************************************
		These routines do the ajustment so that the x, y 
		quantities can be placed proportionally on the 
		graph
	************************************************************/
	 int cartY (double coordinate) {
    	
    	return (int)(size().height - ((coordinate-minY) * Yscale) )-Margin;
    }
    
    int cartX (double coordinate) {
    	
    	return Margin+(int)(((coordinate-minX)*Xscale));
    }
    /***********************************************************/
	public void paint( Graphics g ) {
		int w=size().width-3;
		int h=size().height-3;
		g.drawString( "Number of Pairs Found:"+n, 30, 15 );
		if (n == MAX) {
			g.drawString( "WARNING: Maximum number of Pairs found", 5,170);
		 	g.drawString( "subsequent pairs ignored", 35,182);
		 	}
		 
		g.drawString("Regression Line Equation:",w-175,h-65);
    	g.drawString("y  = "+B1+" * x + "+B0,w-175,h-50);
    	g.drawString("r   = "+R_square,w-175,h-35); 
    	g.drawString("^",w-175,h-55);
    	g.drawString("2",w-170,h-40);
    	
		// draw dots
		for (int i = 0; i < n; i++){
			g.fillOval( cartX(x[i])-1,cartY(y[i])-1, 3, 3);
	   	}
	   	// draw Regression Line
		g.setColor(Color.red);
    	g.drawLine(cartX(minX), cartY(B1*minX+B0),
    			   cartX(maxX), cartY(B1*maxX+B0));
   
	   	//draw axes and scale:
	   	int Edge = (int)(Math.floor(Margin/2));
	    g.drawLine( Edge, 0, Edge, h-13);
	    g.drawLine( Edge, h-13, w, h-13);
	    int Ystep = (int)(Math.floor((maxY-minY)/4));
	    int Xstep = (int)(Math.floor((maxX-minX)/4));
	    int Ystart = (int)(Math.floor(minY/10)*10);
	    int Xstart = (int)(Math.floor(minX/10)*10);
		for (i=0; i<5;i++){
			g.drawString((i*Ystep+Ystart)+"-", 
						2, cartY(i*Ystep+Ystart));
		}
		for (i=0; i<5;i++){
			g.drawString(""+(i*Xstep+Xstart), 
						cartX(i*Xstep+Xstart), h);
		}

	}
}
    