/* desintegrv.java - jpq - 31/03/03
 * ajout de main() le 03/02/18
 */

import java.awt.event.*;
import java.awt.*;
import java.applet.*;
import java.util.*;

public class desintegrv 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 i;
  }

  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 nparticules = gparmi ("nparticules", 1000);
    double proba = gparmd ("proba", 0.02);
    int max = gparmi ("max", 50);
    int dt = gparmi ("dt", 0);
    D = new dessin (nparticules, proba, max, dt);
    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 "desintegrv par j.-p. Quelen"; }

////////////////////////////////////////////////////////////////////////////////
protected class dessin extends Panel {
  static final long serialVersionUID = 180203L;
  Image img;
  Graphics g;
  int nparticules, max, bsup, w, h, hmax, dt;
  double proba;
  int [] histogramme, x, y;
  boolean retrace;
  Random rnd;

  public dessin (int nparticules, double proba, int max, int dt)
  { this.nparticules = nparticules;
    this.proba = proba;
    this.max = max;
    this.dt = dt;
    retrace = false;
    rnd = new Random ();
    histogramme = new int [max];
    x = new int [nparticules];
    y = new int [nparticules];
  }

  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.black);
        g.fillRect (0, 0, w, h);
      }
    if (retrace)
    { retrace = false;
      for (int j = 0; j < histogramme.length; j ++) histogramme [j] = 0;
      int temps = 0;
      g.setColor (Color.black);
      g.fillRect (0, 0, w, h);
      if (nparticules > x.length)
      { x = new int [nparticules];
        y = new int [nparticules];
        }
      for (int i = 0; i < nparticules; i ++)
      { int xi = x [i] = (int)(rnd.nextDouble () * w);
        int yi = y [i] = (int)(rnd.nextDouble () * h);
        g.fillOval (xi - 4, yi - 4, 7, 7);
      }
      int nndes = nparticules;
      while (nndes > 0)
      { if (dt > 0)
        { try { Thread.sleep (dt); }
          catch (InterruptedException e) {}
        }
        if (temps >= histogramme.length)
        { max += max;
          int [] nh = new int [max];
          System.arraycopy (histogramme, 0, nh, 0, histogramme.length);
          histogramme = nh;
        }
        int nnndes = nndes;
        for (int i = 0; i < nndes; i ++)
         if (rnd.nextDouble () <= proba) nnndes --;
        nndes = nnndes;
        histogramme [temps ++] = nndes;
        g.setColor (Color.black);
        g.fillRect (0, 0, w, h);
        g.setColor (Color.darkGray);
        for (int i = nndes; i < nparticules; i ++)
          g.fillOval (x [i] - 4, y [i] - 4, 7, 7);
        g.setColor (Color.red);
        for (int i = 0; i < nndes; i ++)
        { int xi = (rnd.nextDouble () > 0.5) ? 1 : -1;
          xi += x [i];
          xi = Math.min (w, Math.max (xi, 0));
          x [i] = xi;
          int yi = (rnd.nextDouble () > 0.5) ? 1 : -1;
          yi += y [i];
          yi = Math.min (h, Math.max (yi, 0));
          y [i] = yi;
          g.fillOval (xi - 4, yi - 4, 7, 7);
        }
        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 tparticules, tproba, tdt;
  Button ok;
  Font f;

  private TextField atf (String s, int n)
  { Label lbl = new Label (s);
    lbl.setFont (f);
    lbl.setBackground (Color.lightGray);
    add (lbl);
    TextField tf = new TextField (n);
    tf.setFont (f);
    return tf;
  }

  private TextField ajouttf (String s, int n, int n1)
  { TextField tf = atf (s, n);
    tf.setText (Integer.toString (n1));
    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)
  { f = new Font ("Arial", Font.PLAIN, 10);
    this.D = D;
    this.T = T;
    setBackground (Color.lightGray);
    add (tdt = ajouttf ("dt (en ms) :", 2, D.dt));
    add (tparticules = ajouttf ("Nombre de particules :", 5, D.nparticules));
    add (tproba = atf ("Probabilité de désintégration :", 5));
    tproba.setText (Double.toString (D.proba));
    add (ok = ajoutb ("ok"));
  }

  private int pint (TextField tf, int i, boolean b)
  { try { i = Integer.parseInt (tf.getText ()); }
    catch (NumberFormatException nfe) { }
    if (b && (i <= 0)) i = 1;
    tf.setText (Integer.toString (i));
    return i;  
  }

  private double pdbl (TextField tf, double d)
  { double dd = d;
    try { dd = new Double (tf.getText ()) . doubleValue (); }
    catch (NumberFormatException nfe) { }
    if ((dd > 0.0) && (dd < 1.0)) d = dd;
    tf.setText (Double.toString (d));
    return d;  
  }

  public void actionPerformed (ActionEvent e)
  { if (e.getSource () == ok)
    { D.dt = pint (tdt, D.dt, false);
      D.nparticules = pint (tparticules, D.nparticules, true);
      D.proba = pdbl (tproba, D.proba);
      D.retrace = T.retrace = true;
      T.ta.setText ("");
      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 ("", 5, 50, TextArea.SCROLLBARS_HORIZONTAL_ONLY));
    retrace = false;
  }

  public void paint (Graphics g)
  { if (retrace)
    { retrace = false;
      String s1 = "temps    \t";
      String s2 = "effectifs \t";
      int n = D.histogramme.length;
      while (D.histogramme [-- n] == 0);
      for (int i = 0; i <= n; i ++)
      { int ip1 = i + 1;
        int dhi = D.histogramme [i];
        s1 += Integer.toString (ip1) + "\t";
        s2 += Integer.toString (dhi) + "\t";
      }
      ta.setText (s1 + "\n" + s2);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////

	public static void main (String [] args) {

// Création et lancement de l'applet
		desintegrv d = new desintegrv();
		d.init ();
		d.start ();

// Création de la fenêtre contenant l'applet
		Frame f = new Frame ("desintegrv");
		f.addWindowListener (new fermer ());
		f.add (d);
		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 we) {
			System.exit (0);
		}
	}

}
