/* lgn.java - jpq - 24/12/01 - 7/01/02 - 7/11/09
 * simulation à partir d'une loi discrète
 * modification et ajout de main() le 09/02/18
 */

import java.awt.event.*;
import java.awt.*;
import java.applet.*;
import java.util.*;

public class lgn extends java.applet.Applet {
  static final long serialVersionUID = 180209L;
  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 i;
  }

  public void init ()
  { setFont (new Font ("Arial, Helvetica, sans-serif", Font.PLAIN, 10));
  	setLayout (new BorderLayout ());
    int Nsimul = gparmi ("Nsimul", 1000);
    int nn = gparmi ("nn", 6);
    int min = gparmi ("min", 1);
    double [] pn = new double [nn];
    pn [0] = 1.0;
    for (int i = 0; i < nn; i ++)
      pn [i] = gparmi ("n" + Integer.toString (i), 1);
    int arrondi = gparmi ("arrondi", 3);
    D = new dessin (pn, min, arrondi, Nsimul);
    T = new table (D);
    C = new controles (D, T);
    add ("North", C);
    add ("South", T);
    add ("Center", D);
  }

  public void destroy ()
  { remove (D); remove (C); }

  public String getAppletInfo ()
  { return "lgn par j.-p. Quelen"; }

////////////////////////////////////////////////////////////////////////////////
protected class dessin extends Panel {
  static final long serialVersionUID = 180209L;
  Image img;
  Graphics g;
  int w, h;
  int Nsimul, nn, min;
  double darrondi, total;
  int histogramme [];
  double [] pn, fn;
  Random r;
  boolean retrace;

  public dessin (double [] pn, int min, int arrondi, int Nsimul)
  { this.pn = pn;
    this.min = min;
    this.Nsimul = Nsimul;
    darrondi = Math.pow (10.0, arrondi);
    nn = pn.length;
    r = new Random ();
    fn = new double [nn];
    histogramme = new int [nn];
    Nsimul = 1;
//    retrace = false;
  }

  private void foncrepart ()
  { total = 0.0;
    for (int i = 0; i < nn; i ++) total += pn [i];
    double somme = 0.0;
    for (int i = 0; i < nn; i ++)
    { somme += pn [i];
      fn [i] = somme / total;
    }
    fn [nn - 1] = 1.0;
  }

  private void h (Graphics g, int i)
  { g.setColor (Color.white);
    g.fillRect (1, 1, getSize().width - 2, getSize().height - 2);
    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 (Integer.toString (i + 1), 5, 40);

    for (int j = 0; j < nn; j ++)
    { int x = j * (getSize().width - 50) / nn + 50;
      int y = getSize().height - 40 - histogramme [j] * (getSize().height - 80) / (i + 1);
      g.setColor (Color.black);
      g.drawLine (x, y, x, getSize().height - 40);
      g.setColor (Color.blue);
      g.drawString (Integer.toString (j + min), x, getSize().height - 10);
    }
      g.setColor (Color.black);
      g.drawRect (0, 0, getSize().width - 1, getSize().height - 1);
  }

  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);
		retrace = true;
      }
    if (retrace)
    { retrace = false;
      foncrepart ();
      for (int i = 0; i < nn; i ++) histogramme [i] = 0;
      for (int i = 0; i < Nsimul; i ++)
      { double d = r.nextDouble ();
        int j = 0;
        while (d >= fn [j]) j ++;
        histogramme [j] ++;
        h (g, i);
        g1.drawImage (img, 0, 0, this);
      }
    }
    else g1.drawImage (img, 0, 0, this);
//    else h (g, Nsimul -1);
  }
}
////////////////////////////////////////////////////////////////////////////////
protected class controles extends Panel implements ActionListener {
  static final long serialVersionUID = 180209L;
  dessin D;
  table T;
  TextField tmin, tNsimul, tpn;
  Button proba, simule, efface;

  private Label ajoutlbl (String s)
  { Label lbl = new Label (s);
    return lbl;
  }

  private TextField ajouttf (int n)
  { TextField tf = new TextField (n);
    return tf;
  }

  private Button ajoutbt (String s)
  { Button bt = new Button (s);
    bt.addActionListener (this);
    return bt;
  }

  public controles (dessin D, table T)
  { this.D = D;
    this.T = T;
    setBackground (Color.lightGray);
    add (ajoutlbl ("min :"));
    add (tmin = ajouttf (3));
    add (ajoutlbl ("pn :"));
    add (tpn = ajouttf (20));
    add (proba = ajoutbt ("proba"));
    add (efface = ajoutbt ("efface"));
    add (ajoutlbl ("simulations :"));
    add (tNsimul = ajouttf (4));
    add (simule = ajoutbt ("simule"));
    tmin.setText (Integer.toString (D.min));
    tpnst ();
    tNsimul.setText (Integer.toString (D.Nsimul));
  }

  private void tpnst ()
  { String s = "";
    D.total = 0.0;
    for (int i = 0; i < D.nn; i ++) D.total += D.pn [i];
    for (int i = 0; i < D.nn; i ++)
      s += Double.toString (Math.floor (D.pn [i] / D.total * D.darrondi) / D.darrondi) + " "; 
    tpn.setText (s);
  }

  public void actionPerformed (ActionEvent e)
  { if (e.getSource () == simule)
    { T.ta.setText ("");
    	try { D.Nsimul = Integer.parseInt (tNsimul.getText ()); }
      catch (NumberFormatException nfe) { }
      if (D.Nsimul <= 0) D.Nsimul = 1;
      tNsimul.setText (Integer.toString (D.Nsimul));
      D.retrace = T.retrace = true;
      D.repaint ();
      T.repaint ();
    }
    else if (e.getSource () == efface) tpn.setText ("");
    else if (e.getSource () == proba)
    { try { D.min = Integer.parseInt (tmin.getText ()); }
      catch (NumberFormatException nfe) { }
      tmin.setText (Integer.toString (D.min));

      D.nn = 1; D.pn [0] = 1.0;

      int i = 0;
      StringTokenizer st = new StringTokenizer (tpn.getText ());
      while (st.hasMoreTokens ())
      { try { double d = -1.0;
      	      d = new Double (st.nextToken ()).doubleValue ();
              if (d >= 0.0)
              { if (i >= D.pn.length)
                { double [] pn1 = new double [D.pn.length * 2];
                	System.arraycopy (D.pn, 0, pn1, 0, D.pn.length);
                	D.pn = pn1;
                }
                D.pn [i ++] = d;
              }
            }
        catch (NumberFormatException nfe) { }
      }
      if (i > 0)
      { D.nn = i;
      	D.fn = new double [D.nn];
      	D.histogramme = new int [D.nn];
      }
      tpnst ();
    }
  }
}
////////////////////////////////////////////////////////////////////////////////
protected class table extends Panel {
  static final long serialVersionUID = 180209L;
  TextArea ta;
  dessin D;
  boolean retrace;

  public table (dessin D)
  { this.D = D;
    setLayout (new FlowLayout());
    setBackground (Color.lightGray);
    add (ta = new TextArea ("", 5, 50, TextArea.SCROLLBARS_HORIZONTAL_ONLY));
    retrace = false;
  }

  public void paint (Graphics g)
  { if (retrace)
    { retrace = false;
      String s1 = "valeurs\t";
      String s2 = "effectifs\t";
      String s3 = "fréq.\t";
      String s4 = "proba\t";
      for (int i = 0; i < D.nn; i ++)
      { s1 += Integer.toString (i + D.min) + "\t";
        s2 += Integer.toString (D.histogramme [i]) + "\t";
        double d = Math.floor ((double)D.histogramme [i] / (double)D.Nsimul * D.darrondi) / D.darrondi;
        s3 += new Double(d).toString() + "\t";
        d = Math.floor (D.pn [i] / D.total * D.darrondi) / D.darrondi;
        s4 += new Double(d).toString() + "\t";
      }
      ta.setText (s1 + "\n" + s2 + "\n" + s3 + "\n" + s4);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////

	public static void main (String [] args) {
		lgn a = new lgn();
		a.init ();
		a.start ();

		Frame f = new Frame ("lgn");
		f.addWindowListener (new fermer ());
		f.add (a);
		f.setSize (600, 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 e) {
			System.exit (0);
		}
	}

}
