/* binomial1.java - jpq - 05/11/05
 * ajout de main() le 03/02/18
 */
 
import java.awt.event.*;
import java.awt.*;
import java.applet.*;

public class binomial1 extends java.applet.Applet {
  static final long serialVersionUID = 180203L;
  controles C;
  dessin D;
  table T;
 
  private int gparmi (String s, int i) {
    try {
	  s = getParameter (s);
	  i = Integer.parseInt (s);
	}
    catch (NumberFormatException e) {}
	catch (NullPointerException e) {}
    return Math.max (i, 1);
  }

  private double gparmd (String s, double d) {
    try {
	  s = getParameter (s);
	  d = Double.parseDouble (s);
	}
    catch (NumberFormatException e) {}
	catch (NullPointerException e) {}
	if (d <= 0.0 || d >= 1.0)
	  d = 0.5;
    return d;
  }

  public void init ()
  { setLayout (new BorderLayout ());
    int n = gparmi ("n", 1000);
    double p = gparmd ("p", 0.005);
    D = new dessin (n, p);
    T = new table (D);
    C = new controles (D, T);
    add (C, BorderLayout.NORTH);
    add (T, BorderLayout.SOUTH);
    add (D, BorderLayout.CENTER);
  }

  public void destroy ()
  { remove (D); remove (C); remove (T);}

  public String getAppletInfo ()
  { return "binomial1 par j.-p. Quelen"; }

////////////////////////////////////////////////////////////////////////////////
protected class dessin extends Canvas {
  static final long serialVersionUID = 180203L;
  Image img;
  int w, h;
  Graphics g;
  int n, bsup, max;
  double p;
  double [] histogramme = new double [21];
  double [] [] cnk = new double [2] [21];
  boolean retrace, bnormal, bpoisson;
  int imax, arrond = 2;
  double darrond = 100.0;
  double unsr2pi = 1.0 / Math.sqrt (2.0 * Math.PI);

  public dessin (int n, double p)
  { this.n = n;
  	this.max = n;
    this.p = p;
//    retrace = bnormal = bpoisson = false;
    init (n, max);
  }

  private void init (int n, int max)
  { this.n = n;
    bsup = max + 1;
    if (bsup > histogramme.length)
    { bsup += 20;
      histogramme = new double [bsup];
      cnk = new double [2] [bsup];
      bsup = n + 1;
    }
  }

  private String sarrondi (double d)
  { if (arrond > 0) d = Math.floor (d * darrond) / darrond;
    return Double.toString (d);
  }

  public void update (Graphics g)
  { paint (g); }

  public void paint (Graphics g1)
  { if (img == null || w != getSize().width || h != getSize().height) {
	  w = getSize().width;
      h = getSize().height;
      img = createImage (w, h);
      g = img.getGraphics ();
      g.setColor (Color.white);
      g.fillRect (1, 1, w - 2, h - 2);
      g.setColor (Color.black);
      g.drawRect (0, 0, w - 1, h - 1);
    }
    if (retrace)
    { retrace = false;
      int k = (n + 1) % 2;
      for (int i = 0; i < n; i ++)
      { cnk [k] [0] = cnk [k] [i + 1] = 1.0;
        int k1 = (k + 1) % 2;
        for (int j = 1; j <= i; j ++) cnk [k] [j] = cnk [k1] [j - 1] + cnk [k1] [j];
        k = k1;
      }
      double max = 0.0;
      if ((p == 0.0) || (p == 1.0))
      { for (int i = 0; i <= n; i ++) histogramme [i] = 0.0;
        k = (p == 0.0) ? 0 : n;
        histogramme [k] = 1.0;
        max = 1.0; imax = 0;
      }
      else
       for (int i = 0; i <= n; i ++)
       { double hi = cnk [0] [i] * Math.pow (p, i) * Math.pow (1.0 - p, n - i);
         if (hi > max) { max = hi; imax = i; }
         histogramme [i] = hi;
       }
      g.setColor (Color.white);
      g.fillRect (1, 1, getSize().width - 2, getSize().height - 2);

      if (bpoisson)
      { g.setColor (Color.blue);
        double lambda = p * n;
        double proba = Math.exp (- lambda);
        for (int i = 0; i <= n; i ++)
        { int x = i * (getSize().width - 50) / bsup + 20;
          int y = getSize().height - 40 - (int)(proba / max * (getSize().height - 80));
          g.fillRect (x - 1, y - 1, 3, 3);
          proba = proba * lambda / (i + 1);         
        }
      }

      if (bnormal)
      { g.setColor (Color.blue);
        int Xp = -1; int Yp = -1;
        for (int X = 20; X < getSize().width; X ++)
        { double x2 = ((double)(X - 20) / (getSize().width - 50) * bsup / n - p);
          x2 = x2 * x2 * n / (p * (1 - p));
          double y = Math.exp (- x2 / 2.0) * unsr2pi / Math.sqrt (p * (1 - p) * n); // modif 11/10/99
          int Y = getSize().height - 40 - (int)(y / max * (getSize().height - 80));
          if (Xp != -1) g.drawLine (Xp, Yp, X, Y);
          Xp = X; Yp = Y;
        }
      }

      g.setColor (Color.yellow);
      g.drawLine (20, getSize().height - 40, getSize().width, getSize().height - 40);
      g.drawLine (20, 40, 20, getSize().height - 40);
      g.setColor (Color.blue);
      g.drawString ("0", 5, getSize().height - 40);
      g.drawString (sarrondi (max), 5, 40);

      for (int j = 0; j < bsup; j ++)
      { int x = j * (getSize().width - 50) / bsup + 20;
        int y = getSize().height - 40 - (int)(histogramme [j] / max * (getSize().height - 80));
        g.setColor (Color.black);
        g.drawLine (x, y, x, getSize().height - 40);
        g.setColor (Color.blue);
        g.drawString (Integer.toString (j), x, getSize().height - 10);
      }
      g.setColor (Color.black);
      g.drawRect (0, 0, getSize().width - 1, getSize().height - 1);

      g1.drawImage (img, 0, 0, this);
    }
    else g1.drawImage (img, 0, 0, this);
  }
}
////////////////////////////////////////////////////////////////////////////////
protected class controles extends Panel implements ActionListener {
  static final long serialVersionUID = 180203L;
  dessin D;
  table T;
  TextField tn, tp, ta, tmax;
  Button ok, normal, poisson;

  public controles (dessin D, table T)
  { this.D = D;
    this.T = T;
    setLayout (new FlowLayout());
    setBackground (Color.lightGray);
    Label l;
    add (l = new Label ("n ="));
    l.setBackground (Color.lightGray);
    add (tn = new TextField (4));
    tn.setText (Integer.toString (D.n));
    add (l = new Label ("p ="));
    l.setBackground (Color.lightGray);
    add (tp = new TextField (4));
    tp.setText (Double.toString (D.p));
    add (l = new Label ("max="));
    l.setBackground (Color.lightGray);
    add (tmax = new TextField (4));
    tmax.setText (Integer.toString (D.max));
    add (l = new Label ("déc."));
    l.setBackground (Color.lightGray);
    add (ta = new TextField (4));
    ta.setText (Integer.toString (D.arrond));
    add (ok = new Button ("Ok"));
    ok.addActionListener (this);
    add (normal = new Button ("N"));
    normal.addActionListener (this);
    add (poisson = new Button ("P"));
    poisson.addActionListener (this);
  }

  public void actionPerformed (ActionEvent e)
  { if ((e.getSource () == ok) || (e.getSource () == normal) || (e.getSource () == poisson))
    { int n = D.n;
      try { n = Integer.parseInt (tn.getText ()); }
      catch (NumberFormatException nfe) { }
      if (n <= 0) n = 1;
      tn.setText (Integer.toString (n));
      int max = D.max;
      try { max = Integer.parseInt (tmax.getText ()); }
      catch (NumberFormatException nfe) { }
      if (max < 0) max = 0;
      tmax.setText (Integer.toString (max));
      D.init (n, max);
      try { D.p = new Double(tp.getText ()).doubleValue(); }
      catch (NumberFormatException nfe) { }
      if (D.p < 0) D.p = 0; else if (D.p > 1) D.p = 1;
      tp.setText (Double.toString (D.p));
      try { D.arrond = Integer.parseInt (ta.getText ()); }
      catch (NumberFormatException nfe) { }
      ta.setText (Integer.toString (D.arrond));
      if (D.arrond >= 0) D.darrond = Math.pow (10.0, D.arrond);
      D.retrace = T.retrace = true;
      if (e.getSource () == normal) D.bnormal = ! D.bnormal;
      if (e.getSource () == poisson) D.bpoisson = ! D.bpoisson;
      D.repaint ();
      T.repaint ();
    }
  }
}
////////////////////////////////////////////////////////////////////////////////
protected class table extends Panel {
  static final long serialVersionUID = 180203L;
  TextArea ta;
  dessin D;
  boolean retrace;

  public table (dessin D)
  { this.D = D;
    setLayout (new FlowLayout());
    setBackground (Color.lightGray);
    add (ta = new TextArea ("", 3, 50, TextArea.SCROLLBARS_HORIZONTAL_ONLY));
//    retrace = false;
  }

  public void paint (Graphics g)
  { if (retrace)
    { retrace = false;
      String s1 = "n\t";
      String s2 = "p\t";
      for (int i = 0; i < D.bsup; i ++)
      { s1 = s1 + Integer.toString (i) + "\t";
        s2 = s2 + D.sarrondi (D.histogramme [i]) + "\t";
      }
      ta.setText (s1 + "\n" + s2);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////

	public static void main (String [] args) {

// Création et lancement de l'applet
		binomial1 b = new binomial1();
		b.init ();
		b.start ();

// Création de la fenêtre contenant l'applet
		Frame f = new Frame ("binomial1");
		f.addWindowListener (new fermer ());
		f.add (b);
		f.setSize (500, 400);
		f.setVisible (true);
	}

// Permet la fermeture de la fenêtre contenant l'applet
	protected static final class fermer extends WindowAdapter {
		public void windowClosing (WindowEvent we) {
			System.exit (0);
		}
	}

}
