package target;


import java.util.*;  //For Random(), Vector, and Enumeration
import java.awt.geom.Point2D;
import edu.csusb.danby.stat.*;//For HistogramIF and such

/**
* TargetModel keeps track of data for TargetApplet
* @author Charles Stanton
* @version Tue Jul 09 11:03:09 PDT 2002
*/
public class TargetModel extends Object  {
    
    private int xbins, ybins, xybins; //Number of bins to construct
    double x,y,u,v; 			//latest value of x,y
    private Vector hits = new Vector();
    private int[] xcount, ycount, xSquaredCount, ySquaredCount, xySquaredCount;
    Random generator = new Random();
    private int sumX = 0;
    private int  sumXsquared=0;
    private int sumY = 0;
    private int  sumYsquared = 0;
    // parameters to get bivariate distribution
    private double covariance=0;
    private double uncovariance =1;//sqrt(1-covariance^2)
    private double alpha = 1; // sqrt((1+uncovariance)/2);
    private double beta = 0; // covariance/sqrt(2+uncovariance)
    private String[] classMarkLabels={"-4","","","","","-2","","","","",
    "0","","","","","2","","","","","","4"};
   private String[] xyClassMarkLabels={"0","","","","","-2","","","","",
    "0","","","","","2","","","","","","7"};
    
   private int numberHits=0;      //number of target hits

   /**
   * constructor for TargetModel
   */
    public TargetModel() {
        xbins = 21;
        ybins  =21;
        xybins = 21;
        xcount  = new int[xbins];
        ycount = new int[ybins];
        xSquaredCount = new int[xbins];
        ySquaredCount = new int[ybins];
        xySquaredCount = new int[xybins];
        }
/**
* simulates repetitions of bivariate normal and keeps track of statistics.
* @param repetitions the number of simulations to do
*/
    public void play(int repetitions) {
        int xindex, yindex, xSquaredIndex,
                     ySquaredIndex, xySquaredIndex ;
        
        Point2D p;  // p =(x,y)
        
        for (int i=0; i< repetitions; i++ ) {
            
            u = generator.nextGaussian();
            v = generator.nextGaussian();
            // x and y are Normal mean 0 variance 1 with the
            //specified covariance
            x = alpha*u + beta*v;    
            y = beta*u + alpha*v;
            p = new Point2D.Double(x,y);
            hits.addElement(p);

            //Now we update the statistics 
            sumX += x;
            sumY += y;
            sumXsquared += x*x;
            sumYsquared += y*y;
            xindex = scale(x);   //arrays are indexed 0..xbins
            yindex = scale(y);
            xSquaredIndex = scaleSquares(x*x);
            ySquaredIndex = scaleSquares(y*y);
            xySquaredIndex = scaleSquares(x*x+y*y);
            xcount[xindex]++;
            ycount[yindex]++;
            xSquaredCount[xSquaredIndex]++;
            ySquaredCount[ySquaredIndex]++;
            xySquaredCount[xySquaredIndex]++;
            }
    }
    /**
    * reset the statistics to initial conditions
    */
    public void reset() {
        hits = new Vector();
        sumX = 0;
        sumXsquared=0;
        sumY = 0;
        sumYsquared = 0;
        numberHits=0; 
        xcount  = new int[xbins];
        ycount = new int[ybins];
        xySquaredCount = new int[xbins];
        }
        

    private int scale(double x ) {  // Should redo to match xbins !
        int result;
        if ( x < -4.0) {
            result = 0;
            }
        else if ( x > 4.0) {
            result = 20;
            }
        else {
            result = (int)(2.5*x+10);
            }
        return  result;
        }

    
    private int scaleSquares(double x ) {  // Should redo to match xbins !
        int result;
        result = (int)Math.min(3*x,20);
        return  result;
        }
/* 
*	Here are the accessor methods 
* 	
*/
public int   getNumberHits(){ return numberHits;}
public Vector getHits(){ return hits;}
public double getX(){return x;}
public double getY(){return y;}
public int[] getXCount(){return xcount;}
public int[] getYCount(){return ycount;}
public int[] getXSquaredCount(){return xSquaredCount;}
public int[] getYSquaredCount(){return ySquaredCount;}
public int[] getXYSquaredCount(){return xySquaredCount;}
public double getCovariance(){return covariance;}
//public int getBins(){return xbins;}
//public int[] getCount(){return xcount;}
//public int getLowValue(){return 0;}
//public int getBinWidth(){return 0;}

    
/**
* setter method for covariance
* @param _covatiance the desired covariance
*/
    public void setCovariance( double _covariance){
          covariance = _covariance;
          uncovariance = Math.sqrt(1-covariance*covariance);
          alpha =  (1+uncovariance)/Math.sqrt(2+2*uncovariance);
          beta = covariance/Math.sqrt(2+2*uncovariance);
    }

/* 
*	Classes used to make histogram panel
*/

    public HistogramIF getXHistogramData() {
        return new HistogramIF(){
            public int getNumberBins(){return xbins;}
            public int[] getBinCount(){return xcount;}
            public int getLowValue(){return 0;} //Not actually used yet
            public boolean drawTheoretical(){return false;}  
            public boolean useClassMarkLabels(){return true;}
            public double[] getTheoreticalCount(){ return null;}
            public double[] getClassMarks(){ return null;}	// values for determining bins
            public String[] getClassMarkLabels(){ return classMarkLabels;} 
            public void setNumberBins(int n){ xbins =n;}
        };
    }

    public HistogramIF getYHistogramData() {
        return new HistogramIF(){
            public int getNumberBins(){return ybins;}
            public int[] getBinCount(){return ycount;}
            public int getLowValue(){return 0;}  //Not actually used yet
             public boolean drawTheoretical(){return false;}  
            public boolean useClassMarkLabels(){return true;}
            public double[] getTheoreticalCount(){ return null;}
            public double[] getClassMarks(){ return null;}	// values for determining bins
            public String[] getClassMarkLabels(){ return classMarkLabels;} 
             public void setNumberBins(int n){ ybins =n;}
        };
    }

    public HistogramIF getXYHistogramData() {
        return new HistogramIF(){
            public int getNumberBins(){return xybins;}
            public int[] getBinCount(){return xySquaredCount;}
            public int getLowValue(){return 0;}  //What should this be?
            public boolean drawTheoretical(){return false;}  
            public boolean useClassMarkLabels(){return true;}
            public double[] getTheoreticalCount(){ return null;}
            public double[] getClassMarks(){ return null;}	// values for determining bins
            public String[] getClassMarkLabels(){ return xyClassMarkLabels;} 
             public void setNumberBins(int n){ xybins =n;}
        };
    }
    

}



