
//******************************************************************************
// ResampleTest.java:  Applet
//
//******************************************************************************
import java.applet.*;
import java.awt.*;
import ResampleTestFrame;

import resample.*;
import java.util.Date;
import java.io.*;                // test

//==============================================================================
// Main Class for applet ResampleTest
//
//==============================================================================

/** 
 *  Example-applet which demonstrates the use of the ResampleVector class.
 *  Most examples are taken from an introductory text about resampling
 *  statistics (www.statistics.com/text.html). See that text for detailed 
 *  explanation of the examples <p>
 *
 */

public class ResampleTest extends Applet
{

  static int appSizeX = 620;        // applet size
  static int appSizeY = 240;
  
  // STANDALONE APPLICATION SUPPORT:
  //    m_fStandAlone will be set to true if applet is run standalone
  //--------------------------------------------------------------------------
  boolean m_fStandAlone = false;
  List appList;
  Label resultLabel,iterLabel,nrLabel,partSizeLabel;
  Panel labelPanel,buttonPanel,mainPanel;
  Button stopButton;
  TextField iterTextField,nrTextField,partSizeTextField;


  // STANDALONE APPLICATION SUPPORT
  //   The main() method acts as the applet's entry point when it is run
  // as a standalone application. It is ignored if the applet is run from
  // within an HTML page.
  //--------------------------------------------------------------------------
  public static void main(String args[])
  {
    // Create Toplevel Window to contain applet ResampleTest
    //----------------------------------------------------------------------

    ResampleTestFrame frame = new ResampleTestFrame("ResampleTest");

    // Must show Frame before we size it so insets() will return valid values
    //----------------------------------------------------------------------
    frame.show();
    frame.hide();
    frame.resize(frame.insets().left + frame.insets().right  + appSizeX,
           frame.insets().top  + frame.insets().bottom + appSizeY);

    // The following code starts the applet running within the frame window.
    // It also calls GetParameters() to retrieve parameter values from the
    // command line, and sets m_fStandAlone to true to prevent init() from
    // trying to get them from the HTML page.
    //----------------------------------------------------------------------
    ResampleTest applet_ResampleTest = new ResampleTest();
    frame.add("Center", applet_ResampleTest);
    applet_ResampleTest.m_fStandAlone = true;
    applet_ResampleTest.init();
    applet_ResampleTest.start();
    frame.show();
  }

  // ResampleTest Class Constructor
  //--------------------------------------------------------------------------
  public ResampleTest()
  {
    // TODO: Add constructor code here
  }

  // APPLET INFO SUPPORT:
  //    The getAppletInfo() method returns a string describing the applet's
  // author, copyright date, or miscellaneous information.
    //--------------------------------------------------------------------------
  public String getAppletInfo()
  {
    return "Name: ResampleTest\r\n" +
           "Author: Christian Sy\r\n" +
           "Created with Microsoft Visual J++ Version 1.0";
  }


  // The init() method is called by the AWT when an applet is first loaded or
  // reloaded.  Override this method to perform whatever initialization your
  // applet needs, such as initializing data structures, loading images or
  // fonts, creating frame windows, setting the layout manager, or adding UI
  // components.
    //--------------------------------------------------------------------------
  public void init()
  {
        // If you use a ResourceWizard-generated "control creator" class to
        // arrange controls in your applet, you may want to call its
        // CreateControls() method from within this method. Remove the following
        // call to resize() before adding the call to CreateControls();
        // CreateControls() does its own resizing.
        //----------------------------------------------------------------------

    System.out.println ("\n Applet started \n");
    resize(appSizeX,appSizeY);    // 620/240
    setLayout (new BorderLayout());
  
    labelPanel = new Panel();
    labelPanel.add (new Label ("ResampleVector-Demo"));
    labelPanel.add (new Label ("Choose example: "));   
    add ("North",labelPanel);

    buttonPanel = new Panel();
    iterTextField = new TextField (10);
    iterTextField.setText ("1000");
    iterLabel = new Label ("Iterations:");
    buttonPanel.add (iterLabel);
    buttonPanel.add (iterTextField);
    partSizeTextField = new TextField (7);
    partSizeTextField.setText ("5");
    partSizeLabel = new Label ("Partsize:");
    buttonPanel.add (partSizeLabel);
    buttonPanel.add (partSizeTextField);
    nrTextField = new TextField (7);
    nrTextField.setText ("2");
    nrLabel = new Label ("Number interval:");
    buttonPanel.add (nrLabel);
    buttonPanel.add (nrTextField);

    nrTextField.hide();         // comment out these lines
    partSizeTextField.hide();   // if you call testRandomLocal
    partSizeLabel.hide();
    nrLabel.hide();

    add ("South",buttonPanel); 

    mainPanel = new Panel();
    appList = new List (10,false);
    appList.addItem ("TestRandom");
    appList.addItem ("Trucks");
    appList.addItem ("One Pair");
    appList.addItem ("Three Kind");
    appList.addItem ("Two Pair");
    appList.addItem ("Three Girls");
    appList.addItem ("Basketball");
    appList.addItem ("Bullseye");
    appList.addItem ("Archery");
    appList.addItem ("Birthday");
    appList.addItem ("Pennies");
    appList.addItem ("Four Girls");
    appList.addItem ("Nine Spades");
    appList.addItem ("Bridge");
    appList.addItem ("Four Girls One Boy");
    appList.addItem ("Three Girls");
    appList.addItem ("Couples");
    appList.addItem ("Hats");
    appList.addItem ("Compound");
    appList.addItem ("Pig Food");
    appList.addItem ("Fruitfly");
    appList.addItem ("FourTreat");
    appList.addItem ("Cablepol");
    appList.addItem ("Cancer");
    appList.addItem ("FourTreat1");    
    appList.addItem ("FourTreat2");
    appList.addItem ("Pigs");
    appList.addItem ("Pigs2");
    appList.addItem ("Pigs3");
    appList.addItem ("Liquor");
    appList.addItem ("Pigs4");    
    appList.addItem ("Ability1");
    appList.addItem ("Ability2");
    appList.addItem ("Ability3");
    appList.addItem ("Beer Poll");
    appList.addItem ("Sluggo");
     
    mainPanel.add(appList);
    add ("Center",mainPanel);

  }

  // *********** Event-handler **************
  
  public boolean action (Event evt, Object what) {

   double result;
   int iterCount,partSize,nrResults;

   if (evt.target == appList) {
    System.out.println ("\n Example " + appList.getSelectedItem() + " running...\n");    
    System.out.println ("Calculation start at " + new Date ().toString() + "...");
    if (m_fStandAlone==false) 
      showStatus ("Calculation start at " + new Date ().toString() + "...");
    result = 0;
    iterCount = Integer.valueOf(iterTextField.getText()).intValue();
    partSize = Integer.valueOf(partSizeTextField.getText()).intValue();    // argh
    nrResults = Integer.valueOf(nrTextField.getText()).intValue();    

    switch (appList.getSelectedIndex()) {
      case 0: 
        testShuffle(iterCount);
        //testRW();
        //result = testRandomLocal (iterCount,nrResults,partSize); 
        result = testRandomProcess (iterCount,13);
        //testSave();
        //result = testRandomFull (iterCount);
        //result = testRandom(iterCount);
        break;
      case 1:
        result = trucks(iterCount);
        break;                    
      case 2:
        result = onePair(iterCount);
        break;
      case 3:
        result = threeKind(iterCount);
        break;
      case 4:
        result = twoPair(iterCount);
        break;
      case 5:
        result = threeGirls(iterCount);
        break;
      case 6:
        result = basketball(iterCount);
        break;
      case 7:
        result = bullseye(iterCount);
        break;
      case 8:
        result = archery(iterCount);
        break;
      case 9:
        result = birthday(iterCount);
        break;
      case 10:
        result = pennies(iterCount);
        break;      
      case 11:
        result = fourGirl(iterCount);
        break;
      case 12:
        result = nineSpades(iterCount);
        break;
      case 13:
        result = bridge(iterCount);
        break;
      case 14:
        result = fourGirlBoy(iterCount);
        break;
      case 15:
        result = threeGirls(iterCount);
        break;
      case 16:
        couples(iterCount);
        break;
      case 17:
        hats(iterCount);
        break;
      case 18:
        result = compound(iterCount);
        break;
      case 19:
        pigFood(iterCount);
        break;
      case 20:
        result = fruitfly(iterCount);
        break;
      case 21:
        result = fourTreat(iterCount);
        break;
      case 22:
        result = cablepol(iterCount);
        break;
      case 23:
        result = cancer(iterCount);
        break;
      case 24:
        result = fourTreat1(iterCount);
        break;
      case 25:
        result = fourTreat2(iterCount);
        break;
      case 26:
        result = pigs(iterCount);
        break;
      case 27:
        result = pigs2(iterCount);
        break;
      case 28:
        result = pigs3(iterCount);
        break;
      case 29:
        result = liquor(iterCount);
        break;
      case 30:
        result = pigs4(iterCount);
        break;
      case 31:
        result = ability1(iterCount);
        break;
      case 32:
        result = ability2(iterCount);
        break;
      case 33:
        result = ability3(iterCount);
        break;
      case 34:
        beerPoll(iterCount);
        break;
      case 35:
        sluggo(iterCount);
        break;
    }
    System.out.println ("\n Calculation complete at " + new Date().toString() + "! \n");
    System.out.println ("Result: " + result);
    if (m_fStandAlone==false) 
      showStatus ("Result: " + result);
    return (true);
   }
   else
     return false;
  }

  // Place additional applet clean up code here.  destroy() is called when
  // when you applet is terminating and being unloaded.
  //-------------------------------------------------------------------------
  public void destroy()
  {
    // TODO: Place applet cleanup code here
  }

  // ResampleTest Paint Handler
  //--------------------------------------------------------------------------
  public void paint(Graphics g)
  {
  }

  //    The start() method is called when the page containing the applet
  // first appears on the screen. The AppletWizard's initial implementation
  // of this method starts execution of the applet's thread.
  //--------------------------------------------------------------------------
  public void start()
  {
    // TODO: Place additional applet start code here
  }
  
  //    The stop() method is called when the page containing the applet is
  // no longer on the screen. The AppletWizard's initial implementation of
  // this method stops execution of the applet's thread.
  //--------------------------------------------------------------------------
  public void stop()
  {
  }

  public void showStatus (String msg) {

     if (m_fStandAlone)
       System.out.println (msg);
     else
       super.showStatus (msg);          // works only with applets !

  }

  public String getResultMsg (int value, int currentIter) {
    return (new String ("Result after " + currentIter + " trials: " + (double)value / currentIter));
  }


  // ********************** the examples **********************

  public double trucks (int iterCount) {

      ResampleVector A, Z;
      int i;
      RVHistogramLinear histo;

      Z = new ResampleVector (iterCount);
      A = new ResampleVector (20);
      for (i=1; i <= iterCount; i++)  {
        if (i % 1000 == 0) {
          showStatus (getResultMsg(Z.count (Z.RVGreater,3),i));
        }
        A.generate (20,1,10);
        Z.score (A.count (Z.RVEqual,1));
      }

      return (double)Z.count (Z.RVGreater,3) / iterCount; 
   }

  /**
   *  propability of getting one pair in a poker hand
   */

   public double onePair(int iterCount) {

     int i;
     double nr;
     ResampleVector A, Z, B;

     A = new ResampleVector (52);
     for (nr = 1;nr <= 13;nr++) {
       for (i = 1;i <= 4;i++) {
         A.score (nr);                   // deck-initialization
       }        
     }
     
     Z = new ResampleVector (iterCount);
     for (i=1;i<=iterCount;i++)  {
       if (i % 1000 == 0) {
          showStatus (getResultMsg(Z.count (Z.RVEqual,1),i));
       }
       A.shuffle();
       B = A.take (0,4);
       Z.score (B.multiples (Z.RVEqual,2));             
     }

      return (double)Z.count(Z.RVEqual,1) / iterCount;
   }
   
  /**
   *  propability of getting a triple in a poker hand
   */

   public double threeKind(int iterCount) {

     int i;
     double nr;
     ResampleVector A, Z, B;

     A = new ResampleVector (52);
     for (nr = 1;nr <= 13;nr++) {
       for (i = 1;i <= 4;i++) {
         A.score (nr);                   // deck-initialization
       }        
     }
     
     Z = new ResampleVector (iterCount);
     for (i=1; i <= iterCount; i++)  {
       if (i % 1000 == 0) {
         showStatus (getResultMsg(Z.count (Z.RVEqual,1),i));
       }
       A.shuffle();
       B = A.take (0,4);
       Z.score (B.multiples (Z.RVEqual,3));              
     }

     return (double)Z.count (Z.RVEqual,1) / iterCount;
   }

  /**
   *  propability of getting two pairs in a poker hand
   */

   public double twoPair(int iterCount) {

     int i;
     double nr;
     ResampleVector A, Z, B;

     A = new ResampleVector (52);
     for (nr = 1;nr <= 13;nr++) {
       for (i = 1;i <= 4;i++) {
         A.score (nr);                   // deck-initialization
       }        
     }
     
   Z = new ResampleVector (iterCount);
     for (i=1;i <= iterCount; i++)  {
     if (i % 1000 == 0) {
      showStatus (getResultMsg(Z.count (Z.RVEqual,2),i));
     }
       A.shuffle();
       B = A.take (0,4);
       Z.score (B.multiples (Z.RVEqual,2));              
     }

     return (double)Z.count (Z.RVEqual,2) / iterCount;
   }

  /**
   *  propability that three of four childs are girls
   */

   public double threeGirls(int iterCount) {
   
     ResampleVector A, Z;
   int i;

     Z = new ResampleVector (iterCount);
     A = new ResampleVector (4);
     for (i = 1; i <= iterCount; i++)  {
     if (i % 1000 == 0) {
      showStatus (getResultMsg(Z.count (Z.RVEqual,3),i));
     }
       A.generate (4,1,2);
       Z.score (A.count (Z.RVEqual,1));
     }
     return (double)Z.count (Z.RVEqual,3) / iterCount;
   }

   public double basketball (int iterCount) {

     ResampleVector A, Z;
   int i;

     Z = new ResampleVector (iterCount);
     A = new ResampleVector (5);
     for (i=1;i <= iterCount; i++)  {
     if (i % 1000 == 0) {
      showStatus (getResultMsg(Z.count (Z.RVGreaterEqual,3),i));
     }
       A.generate (5,1,4);
       Z.score (A.count (Z.RVEqual,1));
     }
     return (double)Z.count (Z.RVGreaterEqual,3) / iterCount;

   }

   public double bullseye (int iterCount) {

   ResampleVector A, Z;
   int i;

     Z = new ResampleVector (iterCount);
     A = new ResampleVector (3);
     for (i=1;i <= iterCount; i++)  {
     if (i % 1000 == 0) {
      showStatus (getResultMsg(Z.count (Z.RVEqual,2),i));
     }
       A.generate (3,1,10);
       if (A.count (Z.RVEqual,1) == 1) {
         Z.score (A.filter(Z.RVGreaterEqual,2).count(Z.RVLessEqual,7));
       } 
     }

     return (double)Z.count (Z.RVEqual,2) / iterCount;

   }
   
   public double archery (int iterCount) {

     ResampleVector A, Z;
     int i;

     Z = new ResampleVector (iterCount);
     A = new ResampleVector (7);
     for (i=1;i <= iterCount; i++)  {
     if (i % 1000 == 0) {
      showStatus (getResultMsg(Z.count(Z.RVGreaterEqual,7),i));
     }
       A.generate (7,1,10);
       Z.score (3*A.count(Z.RVEqual,1) + A.filter(Z.RVGreaterEqual,2).count(Z.RVLessEqual,7));
     } 

      Z.setDescription ("Archery");
     mainPanel.add (new RVHistogramLinear (350,200,Z));          
     return (double)Z.count (Z.RVGreaterEqual,7) / iterCount;

   }

   public double birthday (int iterCount) {  

     ResampleVector A, Z;
     int i;

     Z = new ResampleVector (iterCount);
     A = new ResampleVector (25);
     for (i=1;i<=iterCount;i++)  {
       if (i % 1000 == 0) {
         showStatus (getResultMsg(Z.count (Z.RVGreater,0),i));
       }
       A.generate (25,1,365);
       Z.score (A.multiples(Z.RVGreater,1));
     }

     return (double)Z.count (Z.RVGreater,0) / iterCount;

   }

   public double pennies (int iterCount) {

     ResampleVector C, Z;
     int A,B,i,j;
     int flag;

     A = 10;
     B = 10;
     flag = 0;
     Z = new ResampleVector (iterCount);
     C = new ResampleVector (1);
     
     for (i=1;i<=iterCount;i++)  {
       for (j=1;j<=200;j++) {
         if (j % 100 == 0) {
           showStatus (getResultMsg(Z.count(Z.RVEqual,1),i));
         } 
         C.generate (1,1,2);
         if (C.count (Z.RVEqual,1) == 1) {
           B++;
           A--;
         }
         else {
           B--;
           A++;
         }
         if ((A==20) || (B==20))  
           flag = 1; 
       }   
       Z.score ((double)flag);
     }

     return (double)Z.count (Z.RVEqual,1) / iterCount;

   }

   
   public double fourGirl (int iterCount) {

    ResampleVector A, C, Z;
    RVHistogram H;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector (50);
    A.numbers (1,50);
    for (i=1;i<=iterCount;i++)  {
      if (i % 500 == 0) {
        showStatus (getResultMsg(Z.count(Z.RVEqual,4),i));
       } 
      A.shuffle();
      C = A.take (1,5);
      Z.score (C.filter(Z.RVGreaterEqual,1).count(Z.RVLessEqual,25));
    }
    mainPanel.add (new RVHistogramLinear (200,200,Z));
    return (double)Z.count (Z.RVEqual,4) / iterCount;

  }

  public double nineSpades (int iterCount) {

    ResampleVector A, C, Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector (52);
    A.numbers (1,52);
    for (i=1;i<=iterCount;i++)  {
      A.shuffle();
      C = A.take (1,13);
      if (C.filter (Z.RVGreaterEqual,1).count (Z.RVLessEqual,13) == 9) 
        Z.score (C.filter(Z.RVGreaterEqual,14).count(Z.RVLessEqual,26));
    }
    return (double) Z.count (Z.RVEqual,4) / iterCount;
  }

  public double bridge (int iterCount) {

    ResampleVector A,C, Z;
    double[] nrArray = {1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4};
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector (52);
    A.set (nrArray);                         
    A.set (36,0,16);                         

    for (i=1;i<=iterCount;i++)  {
      A.shuffle();
      Z.score (A.take (1,13).sum());
    }
    mainPanel.add (new RVHistogramLinear (400,200,Z));    
    return (double) Z.count (Z.RVEqual,4) / iterCount;
  }

  public double fourGirlBoy (int iterCount) {

    ResampleVector A,C, Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector (50);
    A.numbers (1,50);

    for (i=1;i<=iterCount;i++)  {
      A.shuffle();
      C = A.take (1,4);
      if  (C.filter (Z.RVGreaterEqual,1).count (Z.RVLessEqual,25) == 4) 
        Z.score (A.take (5,5).filter(Z.RVGreaterEqual,26).count (Z.RVLessEqual,50));
    }
    return (double) Z.count (Z.RVEqual,1) / iterCount;
  }

  public void couples (int iterCount) {

    ResampleVector A,B, Z, C;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector (10);
    B = new ResampleVector (10);

    A.numbers (1,10);
    B.numbers (1,10);

    for (i=1;i<=iterCount;i++)  {
      B.shuffle();
      C = (ResampleVector)A.copy();          // use copy() for shorter notation
      C.subtract (B);
      Z.score (C.count (Z.RVEqual,0));
    }
    mainPanel.add (new RVHistogramLinear (200,200,Z));
  }

  public void hats (int iterCount) {

    ResampleVector A,B, Z,C;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector (6);
    B = new ResampleVector (6);

    A.numbers (1,6);
    B.numbers (1,6);

    for (i=1;i<=iterCount;i++)  {
       B.shuffle();
       C = (ResampleVector)A.copy();
       C.subtract (B);
       Z.score (C.count (Z.RVEqual,0));
    }
     mainPanel.add (new RVHistogramLinear (200,200,Z));
  }
   
  public double compound (int iterCount) {

    ResampleVector A,E,C, Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();           // initial size-parameter not necessary
    E = new ResampleVector ();           // if performance is not so important
    C = new ResampleVector ();

    A.numbers (1,52);

    for (i=1;i<=iterCount;i++)  {
       A.shuffle();
       C = A.take (1,13);
       if (C.filter (Z.RVGreaterEqual,1).count (Z.RVLessEqual,13) >= 5) {
         E.generate (5,1,2);
         Z.score (E.count (Z.RVEqual,1));
       }
    }
    return (double) Z.count (Z.RVEqual,4) / iterCount;
  }

  public void pigFood (int iterCount) {

    ResampleVector A,B,Z;
    int i;
    double[] valueArray = {496, 544, 464, 416, 512, 560, 608, 544, 480, 466, 512, 496}; 

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    B = new ResampleVector ();

    A.set (valueArray);
    for (i=1;i<=iterCount;i++)  {
       Z.score (A.sample(12).mean());
    }
    System.out.println (Z);
    mainPanel.add (new RVHistogramLinear (500,200,Z));
  }

  public double fruitfly (int iterCount) {

    ResampleVector A,Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                

    for (i=1;i<=iterCount;i++)  {
       A.generate (20,1,2);
       Z.score (A.count (Z.RVEqual,1));
    }

    mainPanel.add (new RVHistogramLinear (200,200,Z));
    return (double)(Z.count (Z.RVGreaterEqual,14) + Z.count (Z.RVLessEqual,6)) / iterCount;
  }

  public double fourTreat (int iterCount) {

    ResampleVector A,Z;
    int i,j,flag;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                

    for (i=1;i<=iterCount;i++)  {
      flag = 0;
      for (j=1;j<=4;j++)  {
        A.generate (20,1,2);
        if ((A.count (Z.RVEqual,1) >= 14) || (A.count (Z.RVEqual,1) <= 6)) { 
          flag = 1;
        }
        Z.score (flag);
      }
    }
    return (double)Z.count (Z.RVEqual,1) / iterCount;
  }

  public double cablepol (int iterCount) {

    ResampleVector A,Z;
    int i,j,flag;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                

    for (i=1;i<=iterCount;i++)  {
      A.generate (50,1,2); 
      Z.score (A.count (Z.RVEqual,1));
    }

    mainPanel.add (new RVHistogramLinear (400,200,Z));
    return (double) Z.count (Z.RVGreaterEqual,30) / iterCount;
  }

  public double cancer (int iterCount) {

    ResampleVector A,B,Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    B = new ResampleVector ();                

    for (i=1;i<=iterCount;i++)  {
      A.generate (6,1,12); 
      B.generate (6,1,12); 
      Z.score (A.filter (Z.RVGreaterEqual,1).count (Z.RVLessEqual,7) - B.filter(Z.RVGreaterEqual,1).count (Z.RVLessEqual,7));
    }


    mainPanel.add (new RVHistogramLinear (300,200,Z));
    return (double) Z.count (Z.RVGreaterEqual,3) / iterCount;
  }

  public double fourTreat1 (int iterCount) {  

    ResampleVector A,B,C,D,E,Z;
    int i,a,b,c,d;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    B = new ResampleVector ();                
    C = new ResampleVector ();                
    D = new ResampleVector ();                
    E = new ResampleVector ();                

    for (i=1;i<=iterCount;i++)  {
      A.generate (20,1,100); 
      B.generate (20,1,100); 
      C.generate (20,1,100); 
      D.generate (20,1,100); 
      a = A.count (Z.RVLessEqual,55);
      b = B.count (Z.RVLessEqual,55);
      c = C.count (Z.RVLessEqual,55);
      d = D.count (Z.RVLessEqual,55);
      E.score (a-b);
      E.score (a-c);
      E.score (a-d);
      E.score (b-c);
      E.score (b-d);
      E.score (c-d);
      E.abs();
      Z.score (E.max());
    }

    return (double) Z.count (Z.RVGreaterEqual,10) / iterCount;
  }

  public double fourTreat2 (int iterCount) {  

    ResampleVector A,W,Z;
    int i,j;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    W = new ResampleVector ();                

    for (i=1;i<=iterCount;i++)  {
      for (j=1;j<=4;j++) {
        A.generate (20,1,100); 
        W.score (A.filter (Z.RVGreaterEqual,1).count (Z.RVLessEqual,55));
      }
      W.subtract (W.mean());
      W.multiply (W);                    
      Z.score (W.sum());
      W.clear();
    }

    mainPanel.add (new RVHistogramLinear (300,200,Z));
    return (double) Z.count (Z.RVGreaterEqual,54) / iterCount;
  }

  public double pigs (int iterCount) {  

    ResampleVector A,Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    A.numbers (1,24);

    for (i=1;i<=iterCount;i++)  {
       A.shuffle();
       Z.score (A.take(1,12).count (Z.RVLessEqual,12));
    }

    mainPanel.add (new RVHistogramLinear (300,200,Z));
    return (double) (Z.count (Z.RVGreaterEqual,9) + Z.count (Z.RVLessEqual,3)) / iterCount;
  }


  public double pigs2 (int iterCount) {  

    ResampleVector A,Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                

    for (i=1;i<=iterCount;i++)  {
       A.generate(12,1,12);
       Z.score (A.count (Z.RVEqual,1));
    }

    return (double) (Z.count (Z.RVGreaterEqual,9) + Z.count (Z.RVLessEqual,3)) / iterCount;
  }

  public double pigs3 (int iterCount) {  
    
    ResampleVector A,Z;
    int i;
    double valueArrayA[] = {31,34,29, 26, 32, 35, 38, 34, 31, 29, 32, 31};
    double valueArrayB[] = {26, 24, 28, 29, 30, 29, 31, 29, 32, 26, 28, 32};

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    A.set (valueArrayA);
    A.set (valueArrayB,A.size());               // add array B

    for (i=1;i<=iterCount;i++)  {
       Z.score (A.sample(12).sum() - A.sample(12).sum());
    }

    mainPanel.add (new RVHistogramLinear (400,200,Z));
    return (double) (Z.count (Z.RVGreaterEqual,38) + Z.count (Z.RVLessEqual,-38)) / iterCount;
  }

  public double liquor (int iterCount) {  

    ResampleVector A,Z;
    int i;
    double valueArrayA[] = {482, 529, 489, 495, 455, 490, 525, 530, 429, 485, 454, 475,
         485, 485, 450, 475, 479, 485, 479, 495, 495, 475, 520, 510, 480, 429};
    double valueArrayB[] = {465, 455, 411, 415, 420, 455, 380, 400, 419, 475, 474, 450,
         410, 400, 505, 420};

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    A.set (valueArrayA);
    A.set (valueArrayB,A.size());               // append array B 

    for (i=1;i<=iterCount;i++)  {
       A.shuffle();
       Z.score (A.take(0,25).mean() - A.take(26,41).mean());
    }

    mainPanel.add (new RVHistogramLinear (400,200,Z));
    return (double) Z.count (Z.RVGreaterEqual,49) / iterCount;
  }
  
  public double pigs4 (int iterCount) {  
  
    ResampleVector A,Z;
    int i;
    double sumA,sumB,sumC,sumD,diffAB,diffAC,diffAD,diffBC,diffBD,diffCD;
    double valueArrayA[] = {34,29,26,32,35,38,31,34,30,29,32,31};
    double valueArrayB[] = {26,24,28 ,29,30,29,32,26,31,29,32,28};
    double valueArrayC[] = {30,30,32,31,29,27,25,30,31,32,34,33};
    double valueArrayD[] = {32,25,31,26,32,27,28,29,29,28,23,25}; 

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    A.set (valueArrayA);
    A.set (valueArrayB,A.size());               // append arrays B,C,D
    A.set (valueArrayC,A.size());               
    A.set (valueArrayD,A.size());               

    for (i=1;i<=iterCount;i++)  {
       A.shuffle();
       sumA = A.sample (12).sum();
       sumB = A.sample (12).sum();
       sumC = A.sample (12).sum();
       sumD = A.sample (12).sum();
       diffAB = sumA - sumB;
       diffAC = sumA - sumC;
       diffAD = sumA - sumD;
       diffBC = sumB - sumC;
       diffBD = sumB - sumD;
       diffCD = sumC - sumD;
       Z.score (diffAB*diffAB + diffAC*diffAC + diffAD*diffAD + 
         diffBC*diffBC + diffBD*diffBD + diffCD*diffCD);
    }

    mainPanel.add (new RVHistogramCompressed (400,200,Z));
    return (double) Z.count (Z.RVGreaterEqual,5299) / iterCount;
  }

  public double ability1 (int iterCount) {      

    ResampleVector A,Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    A.numbers (1,10);

    for (i=1;i<=iterCount;i++)  {
       A.shuffle();
       Z.score (A.take(1,5).sum());
    }

    mainPanel.add (new RVHistogramLinear (400,200,Z));
    return (double) Z.count (Z.RVLessEqual,17) / iterCount;
  }

  public double ability2 (int iterCount) {      

    ResampleVector A,Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    A.numbers (1,10);

    for (i=1;i<=iterCount;i++)  {
       A.shuffle();
       Z.score (A.take(1,5).filter (Z.RVGreaterEqual,1).count (Z.RVLessEqual,5));
    }

    mainPanel.add (new RVHistogramLinear (400,200,Z));
    return (double) Z.count (Z.RVGreaterEqual,4) / iterCount;
  }

  public double ability3 (int iterCount) {      

    ResampleVector A,Z,B,M;
    int i;
    double sumC;
    double valueArrayA[] = {97,94,93,90,87,86,86,85,81,76};
    double valueArrayB[] = {114,120,107,113,118,101,109,110,100,99};

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    B = new ResampleVector ();                
    M = new ResampleVector ();                

    A.set (valueArrayA);
    B.set (valueArrayB);

    M =  A.copy();
    M.multiply(B);
    sumC = M.sum();

    for (i=1;i<=iterCount;i++)  {
       A.shuffle();
       M = A.copy();
       M.multiply(B);
       Z.score (sumC - M.sum());
    }

    mainPanel.add (new RVHistogramPartSums (400,200,Z,10));   // demonstration of PartSums-Histogram
                                                             
    return (double) Z.count (Z.RVLessEqual,0) / iterCount;
  }

  public void beerPoll (int iterCount) {      

    ResampleVector A,D,Z,C;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                
    D = new ResampleVector ();                

    A.set (52,1);
    A.set (26,2,A.size());
    D.set (57,1);
    D.set (21,2,D.size());

    for (i=1;i<=iterCount;i++)  {
       A.shuffle();
       C = A.copy();
       C.subtract (D);
       Z.score (C.count (Z.RVEqual,0));
    }

    mainPanel.add (new RVHistogramCompressed (400,200,Z));
  }

  public void sluggo (int iterCount) {      
    
    ResampleVector A,Z;
    int i;

    Z = new ResampleVector (iterCount);
    A = new ResampleVector ();                

    A.set (3,0);
    A.set (1,1,A.size());

    for (i=1;i<=iterCount;i++)  {
       A.shuffle();
       Z.score (A.sample(100).runs (Z.RVGreaterEqual,1));
    }

    mainPanel.add (new RVHistogramLinear (400,200,Z));
  }


   // *************** test-procedures *********************
   
  /** draw 5 cards of a deck [iterCount] times. Log the results
   *  and return the chi-square-value
   */
  
  public double testRandom(int iterCount) {

     int i,index,j,nrResults;
     double nr;
     ResampleVector A, Z, B, E;

     A = new ResampleVector (52);
     B = new ResampleVector (5);

     nrResults = 13;
     for (nr = 1;nr <= nrResults;nr++) {
       for (i = 1;i <= 4;i++) {
         A.score (nr);                   // deck-initialization
       }        
     }
      
     Z = new ResampleVector (nrResults+1);
     E = new ResampleVector (nrResults+1);
     Z.set (nrResults+1,0);                             // init
     E.set (1,0,0);                                      // ignore index 0
     E.set (nrResults,5*iterCount/nrResults,1);         // expected values

     for (i=1;i <= iterCount;i++)  {
       if (i % 1000 == 0) {
        showStatus (getResultMsg(i*i,i));
       }
       A.shuffle();
       B = A.take (0,4); 
       Z.scoreCounts (B); 
     }     

     System.out.println (Z.toString());
     System.out.println (E.toString());
     return Z.getChiSquare (E);
   }

   /* testRandomProcess */

  /** creates [iterCount] numbers with RandomInterval [1,nrResults]
   *  returns the chi-value 
    */

   public double testRandomProcess (int iterCount, int nrResults) {

     int i,index,j;
     double nr;
     ResampleVector A,Z,E;

     A = new ResampleVector (iterCount);
     A.generate (iterCount,1,nrResults);
     return A.getChiSquare (1,nrResults);      // returns acceptable values, 
                                              // => random quality of generate function ok
   }

   /* testRandomFull */

  /** 
   *  tests the random-generator with different intervals and 
   *  different result-ranges. For quality-test, a chi-table 
   *  is used (see Knuth ACP section 3.3.1 page 39)
   */

     /* random-generator tested with different intervals and 
        different result-ranges. For quality-test, a chi-table 
        is used (see Knuth ACP section 3.3.1 page 39. Note that for
        k different numbers, you have to use the table entry k-1)

        Results for [5%-95%]-runs:
        iterCount = 5000 : 133 from 1400 sequences out of range (9,5%)
        iterCount = 1000 : 106 from 1015 sequences out of range (10,4%)
        iterCount = 10000: 38 from 385  sequences out of range (9,9%)

        => for any run, approx. 10% are out of range, correct

        Results for [25%-75%]-runs:
        iterCount = 5000 : 516 from 1015 sequences out of range (50,84%)
        iterCount = 1000 : 612 from 1260 sequences out of range (48,57%)
        iterCount = 10000: 821 from 1645 sequences out of range (49,91%)
     
         => for any run, approx. 50% are out of range, correct
     
     */

   public double testRandomFull (int iterCount) {

     int nrResults,intervalNr,resultNr,interval,i;
     double nr,chi;
     ResampleVector A, Z, B, E, Chi;
     int[] arrNrResults = {2,5,10,20,50};
     double[] arrMinChi = {0.004,0.71,3.325,10,33};  // <5%
     double[] arrMaxChi = {3.84,9.49,16.92,30,66}; // >95% */
     //double[] arrMinChi = {0.1015,1.923,5.899,14.5,42};  // <25%
     //double[] arrMaxChi = {1.323,5.385,11.39,23,55.5}; // >75% 
     int[] arrInterval = {1,2,5,20,100,1000,iterCount};
     int chiOutOfRange,loop;

     chiOutOfRange = 0;

     for (loop=1; loop*iterCount <= 100000; loop++) {                
     for (resultNr=0; resultNr < arrNrResults.length; resultNr++) {
       nrResults = arrNrResults[resultNr];        
       Z = new ResampleVector (nrResults+1);
        E = new ResampleVector (nrResults+1);
       Chi = new ResampleVector (arrInterval.length);
       for (intervalNr=0; intervalNr < arrInterval.length; intervalNr++) {
          interval = arrInterval[intervalNr];
           A = new ResampleVector (interval);
          Z.clear();
          E.set (1,0,0);                                      // ignore index 0
          E.set (nrResults,(double)iterCount/(double)nrResults,1);           // expected values
           Z.set (nrResults+1,0);                             // init
          for (i=0; i < iterCount/interval; i++) {
            A.generate (interval,1,nrResults);
            Z.scoreCounts (A);
          }
          //System.out.println (Z.toString());
          //System.out.println (E.toString());      
          chi = Z.getChiSquare(E);
          if ((chi < arrMinChi[resultNr]) || (chi > arrMaxChi[resultNr])) 
            chiOutOfRange++;
          Chi.score (chi);             // score Chi-value
       }
       System.out.println ("Chi-Results for " + nrResults + ": " + Chi.toString());

     }
     System.out.println ("Chi out of range in " + chiOutOfRange + " from " + loop*arrNrResults.length*arrInterval.length);
     }
     return 0; // Z.getChiSquare (E);    
                                  
   }

   /* stirlingNr */

   /* help-function for testRandomLocal.
      Returns stirlingNr (n,m) (=number of possibilities of splitting
      a sequence of size n in m parts (where elements of the same part
      don't need to be neighbors in the sequence !)
      Formula see Knuth 602. No warranty :-)  
   
      A factor array is used. The elements are incremented in systemativ
      order to get all allowed combinations of numbers */

   private int stirlingNr (int n, int m) {   

     int sum,i,maxIndex,currIndex, currProduct;
     int[] factor;

     if ((n==m) || (m==1)) 
       return 1;
     else  {
       maxIndex = n-m;                   // n-m product-constituents
       factor = new int[maxIndex+1];     // factor-array
       for (i=1; i < factor.length; i++) 
         factor [i] = 1;                    // init. Index 0 is unused
       currIndex = maxIndex;
       sum = 1;

       // increment numbers and add to sum. Start with lowest numbers
       //  and move on from the right step by step to higher numbers
       // if you interpret each factor as digit, we move on strictly
       // from lower to higher numbers. Example:
       // (1 1 1) (1 1 2) (1 1 3) (1 2 2) (1 2 3) (1 3 3) ... with
       // maxIndex=3 and m=3

       while (factor[1] < m) {                    // increment numbers and add to sum
        if (factor[currIndex] < m) {
          factor[currIndex]++;
          for (i=currIndex+1; i <= maxIndex; i++)
            factor[i] = factor[currIndex];        // set all numbers right of the current number to same value
          currProduct = 1;
          for (i=1; i <= maxIndex; i++)           // calc product over all numbers
            currProduct *= factor[i];
          sum += currProduct;                      // add to result-sum
          currIndex = maxIndex;                    // move index to right end
        }
        else 
          currIndex--;                            // move index one position to left       
       }                                           // end while
       //System.out.println ("Stirling (" +n+ "," +m+ ") = " + sum);
       return sum;
     }
   }

   /* testRandomLocal */

   /** creates [iterCount] numbers with RandomInterval (1,[nrResults])
    *  divides the vector in partitions of size [partitionSize]
    *  performs a partition test (Knuth ACP section 3.3.1 p.57)
    *  and returns the chi-value. <p>

    * Results: local random tested for partSize = 5 and 10: behavior ok 
    *          (but make sure you have at least 5000 partitions 
    *          (iterCount/partSize = 5000), otherwise the
    *           chi-values are often out of acceptable range !)   
    */

   public double testRandomLocal (int iterCount, int nrResults, int partitionSize) {

     int i,index,j,r,d,k, nrDiffValues;
     double pr,dPowerK;
     ResampleVector A, Z, E, PartVec, PartCountVec, Test, EProp;

     Test  = new ResampleVector (partitionSize);
     A = new ResampleVector (iterCount);
     A.generate (iterCount,1,nrResults);
      E = new ResampleVector (partitionSize+1);
     E.set (1,0,0);                                      // ignore index 0
     
     /* calculate propability that sequence of length d contains 
        r different values if there are k possible results for a number */

     d = nrResults;
     k = partitionSize;
     dPowerK = 1;
     for (i=1; i <= k; i++) 
       dPowerK *= d;

     for (r=1; r <= partitionSize; r++) {
       
       pr = d;
       for (j=1; j <= r-1; j++) {
         pr *= d-j;
       }
       pr *= stirlingNr (k,r);       
       pr /= dPowerK;                 // too unprecise because of iterations !!
       Test.score (pr);
       E.set (1,pr*(double)iterCount/(double)partitionSize,r);      // expected values

     }

     System.out.println ("Test-Sum: " + Test.sum());
     Z = new ResampleVector (partitionSize+1);
     Z.set (partitionSize+1,0);
     PartVec = new ResampleVector (partitionSize);
     PartCountVec = new ResampleVector (nrResults+1);

     for (i=0; i < iterCount/partitionSize; i++) {         // split vector in partitions
       PartVec = A.take (i*partitionSize,(i+1)*partitionSize-1);
       PartCountVec.clear();
       PartCountVec.scoreCounts(PartVec);           // saves sorting
       nrDiffValues = 0;
       for (j=0; j < PartCountVec.size(); j++) {
         if (PartCountVec.elementAt(j) != 0)
           nrDiffValues++;
       }
       Z.setElementAt(Z.elementAt(nrDiffValues)+1,nrDiffValues);    // score nr of different elements for one draw            
     }
     //System.out.println (Z.toString());
     EProp = E.copy();
     EProp.divide (dPowerK);
     //System.out.println (EProp.toString());

     System.out.println (Z.toString());
     System.out.println (E.toString());
     return Z.getChiSquare (E);      // returns acceptable values, ?
                                    // => local random quality of generate function ok
   }

   public double fourKindOfFour(int iterCount) {

     int i;
     double nr;
     ResampleVector A, Z, B;

     A = new ResampleVector (52);
     for (nr = 1;nr <= 13;nr++) {
       for (i = 1;i <= 4;i++) {
         A.score (nr);                   // deck-initialization
       }        
     }
        
     Z = new ResampleVector (iterCount);
     for (i=1;i <= iterCount; i++)  {
     if (i % 1000 == 0) {
       showStatus (getResultMsg(Z.count (Z.RVEqual,1),i));    
     }
       A.shuffle();
       B = A.take (1,4);
       Z.score (B.multiples (Z.RVEqual,4));              
     }

     return (double)Z.count (Z.RVEqual,1) / iterCount;
   }

    public void testSort() {

     // 100 elements: heapsort 2.4 times faster
     //  50 elements: heapsort 1.67 times faster
     //  20 elements:  heapsort 1.13 times faster 
     //  10 elements: simplesort 1.2 times faster
     
     int i;
     double nr;
     ResampleVector A, Z, B;
     ResampleVector[] vecArray;
     int Border = 20;
     int iterCount = 40000;

     A = new ResampleVector (Border);
     A.generate (Border,1,100);   

     //A.removeElementAt (A.size()-1);     // comment it out, then you do heapsort, otherwise simplesort
     System.out.println ("\n "+ A.size());

     vecArray = new ResampleVector[iterCount];
     for (i=0; i < vecArray.length; i++) {
       vecArray[i] = A.copy();
     }

     System.out.println ("\n Sort started at " + new Date().toString());

     for (i=0; i < vecArray.length; i++) {
       vecArray[i].sort();
     }

   }

  /* testShuffle */

  /** 
   *  checks if the shuffle-method produces a random distribution.
   *  A vector of 20 elements is examined: each is element is
   *  checked on uniform distribution among the range [1,20]
   *  for each element position, a chi-square-value is calculated.
   *  In a chi-square-table we have to lookup the line with
   *  number of freedom-degrees m = 19.
   *  prop. >= 0,95%: 10.1 (and less)
   *  prop. <= 0,05%: 30.1 (and greater)
   *  Results: 2 times 10000 iterations done, chi-square-vectors:
   *
   *  [14.1 / 17.8 / 19.5 / 16.6 / 9.4 / 16.1 / 23.8 / 16.6 /
   *   10.9 / 17.2 / 11.9 / 16.7 / 19.1 / 16.9 / 20.0 / 27.5 /
   *   10.0 / 22.1 / 12.0 / 18.2]
   *  (2 critical values in the 10%-interval, of 20 elements => ok
   *
   *  [18.5 / 17.4 / 15.4 / 13.8 / 19.8 / 25.9 / 22.4 / 9.3 / 
   *   14.5 / 17.0 / 18.2 / 11.5 / 16.6 / 15.6 / 22.5 / 20.6 /
   *   21.7 / 11.8 / 18.3 / 12.2
   *  (1 critical value in the 10%-interval, of 20 elements => ok
   */

  public void testShuffle(int iterCount)  {

    int i,runs,j,currIndex;
    ResampleVector S,R[],Z,E;
    int SIZE = 20;

    S = new ResampleVector (SIZE);         // shuffle-vector
    R = new ResampleVector [SIZE+1];       // index-result-vector-array
    Z = new ResampleVector (SIZE);         // result-vector of chi-square-values
    E = new ResampleVector (SIZE+1);       // expected distribution

    S.numbers (1,SIZE);
    for (i=1; i <= SIZE; i++) {
      R[i] = new ResampleVector (SIZE+1);
      R[i].set (SIZE,0);       // R[i] = count indizes of value i
    } 
    E.set (SIZE,(double)iterCount / SIZE);

    for (i=0; i <= iterCount; i++) {       // shuffle-loop
      if (i % 1000 == 0) {
       showStatus (getResultMsg(0,i));    
      }
      S.shuffle();
      for (j=1; j <= SIZE; j++) {
        currIndex = S.indexOf (j);          // get index of element j
        R[j].setElementAt (
          R[j].elementAt(currIndex) + 1,currIndex); // inc index-field in result-vector
      }
    }

    for (j=1; j <= SIZE; j++) {            // calc chi-square for each element
      Z.score (R[j].getChiSquare(E));      
      //System.out.println ("Result-Vektor " + j + ": " + R[j].toString());
    }
    
    System.out.println ("Chi-Square-Vektor for all results: " + Z.toString());

  }

  public void testSave () {

    FileInputStream in;
    FileOutputStream out;
    ResampleVector Z;

    Z = new ResampleVector();
    Z.numbers (1,20);
    
    try {
      out = new FileOutputStream ("test10.dat");
      Z.write (out);
      Z.write (out);
      out.close();
      in = new FileInputStream ("test10.dat");
      Z.read (in);
      System.out.println (Z.toString());
      Z.read (in);
      in.close();
      System.out.println (Z.quantile(0.8));
      System.out.println (Z.quantileWhere(16.2));

    }
    catch (IOException e) {
    }

  }

}    // class resample-test

