package clt;

import edu.csusb.danby.stat.HistogramIF;  //for HistogramSupporter interface


/**
* DiceModel class
* Keeps track of necessary info for Dice experiment	      			
* @author Charles S. Stanton			
* @version Sun Jul 14 11:49:25 PDT 2002		
*/	
public class DiceModel extends Object implements HistogramIF{

    private int ndice;			//number of dice
    private int xbins = ndice*5+1;
    private int xcount[] = new int[xbins]; 
         //note that this depends on number of dice!
    private double[] theoreticalCount; 
            //total_nrolls*p(x), where p(x) is theoretical value
    private int diceValues[];
    private int total_nrolls;
    protected static double recip2Pi = 1/ Math.sqrt(2.0*Math.PI);
    protected static double sigma = Math.sqrt(35.0/12.0);
    private double[] normalValues;
    private int sumX;



    
    public  DiceModel() {
        xbins = ndice*5+1;
        xcount = new int[xbins];
        diceValues = new int[ndice];
        total_nrolls = 0;
        theoreticalCount = new double[xbins]; 
        }
            
    public int getNDice(){
        return(ndice);
        }
        
/**
* change the number of dice to roll
* cummulative statistics are reset
*/
    public void setNDice(int _ndice){
        ndice = _ndice;
        xbins=ndice*5+1;  	//update xbins and xcount also
        xcount=new int[xbins];
        theoreticalCount= new double[xbins]; //reset theoreticalCount an die
        total_nrolls=0;
        diceValues = new int[ndice];
        }

    public int getSumX(){
        return(sumX);
        }	

    public int[] getDiceValues(){
        return diceValues;
        }		
    
    public int getTotalNRolls(){
        return total_nrolls;
        }
/*
*  These are the HistogramSupporter methods.
*/
    public int[] getBinCount(){
        return xcount;
        }
        
    public boolean drawTheoretical(){
        return true;
        }

    public boolean useClassMarkLabels(){
        return false;
        }

    public double[] getClassMarks(){ return null;}
    public String[] getClassMarkLabels(){return null;}
    
        
    public int getNumberBins(){
        return xbins;
        }
        
    public double[] getTheoreticalCount(){
        return(theoreticalCount);
        }
        
    public int getLowValue(){
        return(ndice);

        }
        
    public int getBinWidth(){
        return 1;
        }



/**
   rollem simulates the rolling of dice using random number  
   generators.							
   @param nrolls is the number of rolls to do.
 */
    public void rollem(int nrolls) {
        normalValues = new double[xbins];
        for (int i =0; i< xbins; i++){
            double seMean = sigma*Math.sqrt(ndice);
            normalValues[i] = recip2Pi/seMean*Math.exp( -1*
                    Math.pow((i+ndice-3.5*ndice)/seMean,2)/2.0);
            }	
        for (int j=0; j< nrolls; j++){
            sumX=0;
            for (int i=0; i< ndice; i++) {
            this.diceValues[i]=(int)Math.floor(1+Math.random()*6);
            sumX += diceValues[i];
            }
        xcount[sumX-ndice]++;
        }
        total_nrolls += nrolls;
        for (int i=0; i< xbins; i++){	
            theoreticalCount[i] = (double)total_nrolls* normalValues[i];
            }
        }  

/**
* reset the model
*/	
    public void reset() {
        xbins = ndice*5+1;
        xcount = new int[xbins];  //note that this depends on number of dice!
        theoreticalCount = new double[xbins];
        total_nrolls=0;
        diceValues = new int[ndice];
        }

        public void setNumberBins(int nBins){ xbins = nBins;}
}




