/* ptitsou.java
 * 15/10/03 - jpq
 * modification et ajout de main() le 12/02/18
 */
 
import java.awt.event.*;
import java.awt.*;
import java.applet.*;
import java.util.*;

public class ptitsou extends java.applet.Applet {
  static final long serialVersionUID = 180212L;
  controles C;
  dessin D;
  table T;

  private int gpn (String s, int i) {
    try {
      s = getParameter (s);
      i = Integer.parseInt (s);
    }
    catch (NumberFormatException e) {}
    catch (NullPointerException e) {}
    return i;
  }

  private double gpd (String s, double d) {
    try {
      s = getParameter (s);
      d = Double.parseDouble (s);
    }
    catch (NumberFormatException e) {}
    catch (NullPointerException e) {}
    return d;
  }

  public void init ()
  { setLayout (new BorderLayout ());
    D = new dessin (gpd ("min", -8.0), gpd ("max", 8.0), gpn ("nclasses", 16), gpn ("nsimuls", 1000), gpn ("npesees", 20000));
    T = new table (D);
    C = new controles (D, T);
    add (C, BorderLayout.NORTH);
    add (D, BorderLayout.CENTER);
    add (T, BorderLayout.SOUTH);
  }

  public void destroy ()
  { remove (D); remove (C); remove (T); }

  public String getAppletInfo ()
  { return "ptitsou par j.-p. Quelen"; }

////////////////////////////////////////////////////////////////////////////////
protected class dessin extends Canvas {
  static final long serialVersionUID = 180212L;
  Image img;
  Graphics g;
  int w, h, hmax, nclasses, nsimuls, histomin, histomax, npesees;
  int [] histogramme;
  double [] ref;
  int arrond = 2;
  double min, max;
  double darrond = 100.0;
  boolean retrace, pok;
  String surl, message;
  donnees don;

  public dessin (double min, double max, int nclasses, int nsimuls, int npesees)
  { this.min = min;
    this.max = max;
    this.nclasses = nclasses;
    this.nsimuls = nsimuls;
    this.npesees = npesees;
    don = new donnees (nsimuls, npesees);
    pok = true;
    init ();
  }

  private void init ()
  { if ((histogramme == null) || (nclasses > histogramme.length))
    { histogramme = new int [nclasses];
      ref = new double [nclasses];
    }
    for (int i = 0; i < nclasses; i ++)
    { histogramme [i] = 0;
      ref [i] = min + (max - min) * i / nclasses;
    }
    hmax = 0;
    retrace = true;
  }

  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 message (Graphics g, String s)
  { g.setColor (Color.black);
    g.drawString (s, 10, 10);
  }

  private void painthisto (Graphics g)
  { g.setColor (Color.black);
    g.drawRect (0, 0, w -1, h - 1);
    g.setColor (Color.blue);
    int wpas = w / nclasses;
    double hpas = (double)(h - 100) / hmax;
    for (int i = 0; i < nclasses; i ++)
    { int dy = (int)(hpas * histogramme [i]);
      g.drawRect (wpas * i, h - dy - 1, wpas, dy + 1);
    }
    g.setColor (Color.black);
    int Y = h - (int)(hpas * hmax) - 1;
    g.drawString (Integer.toString (hmax), 0, Y); 
    g.drawLine (20, Y, 40, Y);
  }

  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 ();
      if (T != null) T.retrace = true;
    }
    double total = don.valeurs.length;
    if (retrace)
    { retrace = false;
      hmax = 0;
      histomin = histomax = 0;
      for (int i = 0; i < total; i ++)
      { if (pok) don.simulation ();
      	double dv = don.valeurs [i];
        if (dv < min) histomin ++;
        else if (dv >= max) histomax ++;
        else
        { int k = 0;
          while ((k < nclasses) && (dv > ref [k])) k ++;
          histogramme [-- k] ++;
          if (histogramme [k] > hmax) hmax = histogramme [k];
        }
        if (pok)
        { g.setColor (Color.white);
          g.fillRect (0, 0, w, h);
          painthisto (g);
          g1.drawImage (img, 0, 0, this);
        }
      }
    }

    g.setColor (Color.white);
    g.fillRect (0, 0, w, h);
    painthisto (g);
    g1.drawImage (img, 0, 0, this);
  }
}
////////////////////////////////////////////////////////////////////////////////
protected class controles extends Panel implements ActionListener {
  static final long serialVersionUID = 180212L;
  dessin D;
  table T;
  Font f;
  Button ok, nv;
  TextField tmin, tmax, tnclasses, tnsimuls, tnpesees;

  private Label ajoutlbl (String s)
  { Label lbl = new Label (s);
    lbl.setBackground (Color.lightGray);
    lbl.setFont (f);
    return lbl;
  }

  private TextField ajouttf (int n)
  { TextField tf = new TextField (Integer.toString (n));
    tf.setFont (f);
    return tf;
  }

  private TextField ajouttfd (double d)
  { TextField tf = new TextField (new Double(d).toString ());
    tf.setFont (f);
    return tf;
  }

  private Button ajoutb (String s)
  { Button b = new Button (s);
    b.setFont (f);
    b.addActionListener (this);
    return b;
  }

  public controles (dessin D, table T)
  { this.D = D;
    this.T = T;
    setLayout (new FlowLayout());
    setBackground (Color.lightGray);
    f = new Font ("Arial", Font.PLAIN, 10);
    add (ajoutlbl ("min :"));
    add (tmin = ajouttfd (D.min));
    add (ajoutlbl ("max :"));
    add (tmax = ajouttfd (D.max));
    add (ajoutlbl ("classes :"));
    add (tnclasses = ajouttf (D.nclasses));
    add (ok = ajoutb ("Ok"));
    add (ajoutlbl ("pesées :"));
    add (tnpesees = ajouttf (D.npesees));
    add (ajoutlbl ("simulations :"));
    add (tnsimuls = ajouttf (D.nsimuls));
    add (nv = ajoutb ("Simulation"));
  }

  public void actionPerformed (ActionEvent e)
  { if ((e.getSource () == ok) || (e.getSource () == nv))
    { if (D.pok = e.getSource () == nv)
      { try {D.npesees = Integer.parseInt (tnpesees.getText ()); }
        catch (NumberFormatException nfe) { }
        if (D.npesees <= 0) D.npesees = 1;
        try { D.nsimuls = Integer.parseInt (tnsimuls.getText ()); }
        catch (NumberFormatException nfe) { }
        if (D.nsimuls <= 0) D.nsimuls = 1;
        D.don = new donnees (D.nsimuls, D.npesees);
      }
      tnpesees.setText (Integer.toString (D.npesees));
      tnsimuls.setText (Integer.toString (D.nsimuls));
      try { D.min = new Double(tmin.getText()).doubleValue(); }
      catch (NumberFormatException nfe) { }
      try { D.max = new Double(tmax.getText()).doubleValue(); }
      catch (NumberFormatException nfe) { }
      if (D.min > D.max) { double d = D.min; D.min = D.max; D.max = d; }
      tmin.setText (new Double(D.min).toString());
      tmax.setText (new Double(D.max).toString());
      try { D.nclasses = Integer.parseInt (tnclasses.getText ()); }
      catch (NumberFormatException nfe) { }
      if (D.nclasses <= 0) D.nclasses = 1;
      tnclasses.setText (Integer.toString (D.nclasses));
      D.init ();
    }
    D.retrace = T.retrace = true;
    D.repaint ();
    T.repaint ();
  }
}

////////////////////////////////////////////////////////////////////////////////
protected class table extends Panel {
  static final long serialVersionUID = 180212L;
  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 s = "]-inf;" + D.sarrondi (D.min) + "]\t";
      for (int i = 0; i < D.nclasses; i ++) s = s + "[" + D.sarrondi (D.min + (D.max - D.min) * i / D.nclasses) + ";" + D.sarrondi (D.min + (D.max - D.min) * (i + 1) / D.nclasses) + "[\t";
      s += "]" + D.sarrondi (D.max) + ";inf[\n" + Integer.toString (D.histomin) + "\t";
      for (int i = 0; i < D.nclasses; i ++) s += Integer.toString (D.histogramme [i]) + "\t";
      s += Integer.toString (D.histomax);
      ta.setText (s);
    }
  }
}
////////////////////////////////////////////////////////////////////////////////
protected class donnees {
  static final long serialVersionUID = 180212L;
  double [] valeurs;
  int [] arrondi = {0, -1, -2, 2, 1, 0, -1, -2, 2, 1 };
  Random rnd;
  int indice, npesees;

  public donnees (int n, int npesees)
  { rnd = new Random ();
    valeurs = new double [n];
    indice = 0;
    this.npesees = npesees;
  }

  public void simulation ()
  { if (indice < valeurs.length)
    { int cumul = 0;
      for (int i = 0; i < npesees; i ++)
        cumul += arrondi [(int)(rnd.nextDouble () * 10)];
      valeurs [indice ++] = cumul * 0.01;
    }
  }
}

////////////////////////////////////////////////////////////////////////////////

    public static void main (String [] args) {
        int w = 700;
        int h = 400;

// Création et lancement de l'applet
        ptitsou p = new ptitsou();
        p.init ();
        p.start ();

// Création de la fenêtre contenant l'applet
        Frame f = new Frame ("ptitsou");
        f.addWindowListener (new fermer ());
        f.add (p);
        f.setSize (w, h);
        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);
        }
    }

}
