/* revs.java - jpq - 10/11/2000
 * l'allumeur de réverbères
 * modification et ajout de main() le 13/02/18
 */

import java.awt.event.*;
import java.awt.*;
import java.applet.*;
import java.util.*;

public class revs extends java.applet.Applet {
  static final long serialVersionUID = 180213L;
  controles C;
  dessin D;

  private int gparmi (String s, int i) {
    try {
      s = getParameter (s);
      i = Integer.parseInt (s);
    }
    catch (NumberFormatException e) {}
    catch (NullPointerException e) {}
    return i;
  }

  private double gparmd (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 (gparmi ("lignes", 10), gparmi ("colonnes", 40),
                    gparmd ("pra", 0.5),
                    gparmd ("pase", 0.8),gparmd ("pesa", 0.5),
                    gparmi ("nsimul", 100), gparmi ("dt", 10));
    C = new controles (D);
    D.C = C;
    add (C, BorderLayout.NORTH);
    add (D, BorderLayout.CENTER);
  }

  public void destroy ()
  { remove (D); remove (C); }

  public String getAppletInfo ()
  { return "revs par j.-p. Quelen"; }

////////////////////////////////////////////////////////////////////////////////
protected class dessin extends Canvas {
  static final long serialVersionUID = 180213L;
  int lignes, colonnes, nsimul, n, np1, nrayon, H, Hm20, W, npash, npasw;
  int dt, totsimul, totna, na;
  double pase, pesa, pra;
  Random rnd;
  boolean rev [], raz, simul;
  int [] tab;
  controles C;
  Image img;
  Graphics g;

  public dessin (int lignes, int colonnes, double pra, double pase, double pesa, int nsimul, int dt)
  { this.lignes = lignes;
    this.colonnes = colonnes;
    this.pra = pra;
    this.pase = pase;
    this.pesa = pesa;
    this.nsimul = nsimul;
    this.dt = dt;
    n = lignes * colonnes;
    np1 = n + 1;
    rev = new boolean [n];
    tab = new int [np1];
    rnd = new Random ();
    simul = raz = true;
    setFont (new Font ("Arial", Font.PLAIN, 10));
  }

  private void prevs (Graphics g1)
  { g.setColor (Color.black);
    g.fillRect (0, 0, W, H);
    int x = 0; int y = 0; int k = 0;
    for (int i = 0; i < lignes; i ++)
    { for (int j = 0; j < colonnes; j ++)
      { if (rev [k]) g.setColor (Color.yellow);
        else g.setColor (Color.darkGray);
        g.fillOval (x, y, nrayon, nrayon);
        k ++;
        x += npasw;
      }
      x = 0;
      y += npash;
    }
    g.setColor (Color.white);
    g.drawString (" Nb simul : " + Integer.toString (totsimul) +
                  "; réverbères allumés : " + Integer.toString (na) +
                  "; en moyenne : " + Double.toString ((double)(totna)/(double)(totsimul + 1)), 0, H - 2);
    if (dt > 0)
    { try { Thread.sleep (dt); }
      catch (Exception e) { }
    }
    g1.drawImage (img, 0, 0, this);
  }

  public void update (Graphics g1)
  { paint (g1); }

  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 ();
    }

    npasw = W / colonnes;
    Hm20 = H - 20;
    npash = Hm20 / lignes;
    nrayon = Math.min (npasw, npash);
    if (nrayon > 10) nrayon = nrayon - 5;
    else if (nrayon == 0)
    { nrayon = 1;
      if (npasw == 0) { npasw = 1; lignes = W; }
      if (npash == 0) { npash = 1; colonnes = Hm20; }
      raz = true;
    }
    if (raz)
// état initial
    { raz = false;
      totsimul = totna = na = 0;
      for (int i = 0; i < np1; i ++) tab [i] = 0;
      C.lbln.setText ("nb de réverbères : " + Integer.toString (n));
      if ((rev == null) || (rev.length < n)) rev = new boolean [n];
      else for (int i = 0; i < n; i ++) if (rev [i] = (rnd.nextDouble() < pra)) na ++;
      totna = na;
      tab [na] ++;
      gtab.maj (np1, tab);
    }
// changements d'états
    else if (simul)
    { simul = false;
      for (int isimul = 0; isimul < nsimul; isimul ++)
      { na = 0;
        for (int i = 0; i < n; i ++)
        { if (rev [i]) rev [i] = (rnd.nextDouble() > pesa);
          else rev [i] = (rnd.nextDouble() < pase);
          if (rev [i]) na ++;
        }
        totsimul ++;
        totna += na;
        prevs (g1);
        tab [na] ++;
        gtab.maj (np1, tab);
      }
    }
//
    prevs (g1);
  }
}
////////////////////////////////////////////////////////////////////////////////
protected class controles extends Panel implements ActionListener {
  static final long serialVersionUID = 180213L;
  dessin D;
  TextField tpra, tpase, tpesa, tsimul;
  Label lbln;
  Button ok, raz;
  Font f;
  Panel h, b;

  private Label ajoutlbl (String s)
  { Label l = new Label (s);
    l.setBackground (Color.lightGray);
    l.setFont (f);
    return l;
  }

  private TextField ajouttfi (int i, int j)
  { TextField T = new TextField (Integer.toString (i), j);
    T.setFont (f);
    return T;
  }

  private TextField ajouttfd (double d, int j)
  { TextField T = new TextField (Double.toString (d), j);
    T.setFont (f);
    return T;
  }

  public controles (dessin D)
  { this.D = D;
    setLayout (new GridLayout(2, 1));
    add (h = new Panel ());
    add (b = new Panel ());
    setBackground (Color.lightGray);
    f = new Font ("Arial", Font.PLAIN, 10);
    h.add (lbln = ajoutlbl ("nb de réverbères : " + Integer.toString (D.n)));
    h.add (ajoutlbl ("réverbères allumés :"));
    h.add (tpra = ajouttfd (D.pra, 2));
    h.add (ajoutlbl ("nb simul. :"));
    h.add (tsimul = ajouttfi (D.nsimul, 3));
    h.add (raz = new Button ("RAZ"));
    raz.addActionListener (this);
    raz.setFont (f);
    h.add (ok = new Button ("Ok"));
    ok.addActionListener (this);
    ok.setFont (f);
    b.add (ajoutlbl ("allumage d'un réverbère éteint :"));
    b.add (tpase = ajouttfd (D.pase, 2));
    b.add (ajoutlbl ("extinction d'un réverbère allumé :"));
    b.add (tpesa = ajouttfd (D.pesa, 2));
  }

  private int maji (TextField T, int n)
  { try { n = Integer.parseInt (T.getText ()); }
      catch (NumberFormatException nfe) { }
    if (n < 0) n = 0;
    return n;
  }

  private double majd (TextField T, double d)
  { try { d = new Double(T.getText ()).doubleValue(); }
      catch (NumberFormatException nfe) { }
    if (d < 0.0) d = 0.0;
    else if (d > 1.0) d = 1.0;
    return d;
  }

  public void majTi (TextField T, int i)
  { T.setText (Integer.toString (i)); }

  private void majTd (TextField T, double d)
  { T.setText (Double.toString (d)); }

  public void actionPerformed (ActionEvent e)
  { Object obj = e.getSource ();
    if (( obj == ok) || (obj == raz))
    { D.pra = majd (tpra, D.pra);
      D.pesa = majd (tpesa, D.pesa);
      D.pase = majd (tpase, D.pase);
      D.nsimul = maji (tsimul, D.nsimul);
      if (obj == raz) D.raz = true;
      majTd (tpra, D.pra);
      majTd (tpase, D.pase);
      majTd (tpesa, D.pesa);
      majTi (tsimul, D.nsimul);
      D.simul = true;
      D.repaint ();
    }
  }
}

////////////////////////////////////////////////////////////////////////////////

    public static void main (String [] args) {

        revs a = new revs();
        a.init ();
        a.start ();

        histog a1 = new histog();
        a1.init ();
        a1.start ();

        Frame f = new Frame ("revs");
        f.addWindowListener (new fermer ());
        f.add (a);
        f.setSize (500, 400);
        f.setVisible (true);

        Frame f1 = new Frame ("histog");
        f1.addWindowListener (new fermer ());
        f1.add (a1);
        f1.setSize (300, 200);
        f1.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);
        }
    }

}
////////////////////////////////////////////////////////////////////////////////
class gtab {
  static final long serialVersionUID = 180213L;
  static boolean change;
  static int dim;
  static int [] tableau;

  static public void maj (int d, int [] tab)
  { dim = d;
    tableau = tab;
    change = true;
  }
}
