/* desintegrv2.java - jpq - 12/07/08
 * desintégration du potassium en calcium avec une probabilité proba1 et en argon avec une probabilité proba2
 * ajout de main() le 05/02/18
 */

import java.awt.event.*;
import java.awt.*;
import java.applet.*;
import java.util.*;

public class desintegrv2 extends java.applet.Applet {
  static final long serialVersionUID = 180205L;
  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 () {
	setFont (new Font ("Arial", Font.PLAIN, 10));
  	setLayout (new BorderLayout ());
    int nparticules = gparmi ("nparticules", 1000);
    double proba1 = gparmd ("proba1", 0.02);
    double proba2 = gparmd ("proba2", 0.002);
    double p12 = proba1 + proba2;
    if (p12 > 1.0) {
	  proba2 = 0.0;
      p12 = proba1;
    }
    int max = gparmi ("max", 50);
    int dt = gparmi ("dt", 0);
    D = new dessin (nparticules, proba1, proba2, p12, max, dt);
    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); }

  public String getAppletInfo ()
  { return "desintegrv2 par j.-p. Quelen"; }

////////////////////////////////////////////////////////////////////////////////
protected class dessin extends Panel {
  static final long serialVersionUID = 180205L;
  Image img;
  Graphics g;
  int nparticules, max, bsup, w, h, hmax, dt, temps;
  double proba1, proba2, p12;
  int [] histogramme1, histogramme2, x, y;
  Color [] c;
  boolean retrace;
  Random rnd;

  public dessin (int nparticules, double proba1, double proba2, double p12, int max, int dt)
  { this.nparticules = nparticules;
    this.proba1 = proba1;
    this.proba2 = proba2;
    this. p12 = p12;
    this.max = max;
    this.dt = dt;
    retrace = false;
    rnd = new Random ();
    histogramme1 = new int [max]; // nbre de particules Ca
    histogramme2 = new int [max]; // nbre de particules Ar
    x = new int [nparticules];
    y = new int [nparticules];
    c = new Color [nparticules]; // couleur
  }

  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;
      temps = 1;
      g.setColor (Color.black);
      g.fillRect (0, 0, w, h);

      for (int i = 0; i < histogramme1.length; i ++)
      { histogramme1 [i] = 0;
      	histogramme2 [i] = 0;
      }

      if (nparticules > x.length)
      { x = new int [nparticules];
        y = new int [nparticules];
        c = new Color [nparticules];
      }

// création des coordonnées des particules et de leur couleur
      for (int i = 0; i < nparticules; i ++)
      { x [i] = (int)(rnd.nextDouble () * w);
        y [i] = (int)(rnd.nextDouble () * h);
        c [i] = Color.red;
      }

      int nndes = nparticules;
      int nparticules1 = 0;
      int nparticules2 = 0;

      while (nndes > 0)
      {
      	if (dt > 0)
        { try { Thread.sleep (dt); }
          catch (InterruptedException e) {}
        }

        if (temps >= histogramme1.length)
        { max += max;
          int [] nh1 = new int [max];
          System.arraycopy (histogramme1, 0, nh1, 0, histogramme1.length);
          histogramme1 = nh1;
          int [] nh2 = new int [max];
          System.arraycopy (histogramme2, 0, nh2, 0, histogramme2.length);
          histogramme2 = nh2;
        }


        for (int i = 0; i < nparticules; i ++)
        { if (c [i] == Color.red)
        	{ double rndnd = rnd.nextDouble ();
            if (rndnd <= proba1)
            { c [i] = Color.green;
            	nparticules1 ++;
            }
            else
              if (rndnd <= p12)
              { c [i] = Color.blue;
              	nparticules2 ++;
              }
          }
        }

        nndes = nparticules - nparticules1 - nparticules2;

        histogramme1 [temps] = nparticules1;
        histogramme2 [temps ++] = nparticules2;

        g.setColor (Color.black);
        g.fillRect (0, 0, w, h);

        for (int i = 0; i < nparticules; i ++)
        { int xi = x [i];
        	int yi = y [i];
        	Color ci = c [i];
        	if (ci == Color.red)
        	{ xi += (rnd.nextDouble () > 0.5) ? 1 : -1;
            xi = Math.min (w, Math.max (xi, 0));
            yi += (rnd.nextDouble () > 0.5) ? 1 : -1;
            yi = Math.min (h, Math.max (yi, 0));
            x [i] = xi;
            y [i] = yi;
          }
          g.setColor (ci);
          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 = 180205L;
  dessin D;
  table T;
  TextField tparticules, tproba1, tproba2, tdt;
  Button ok;
  Font f;

  private TextField atf (String s, int n)
  { if (s != "")
  	{ Label lbl = new Label (s);
      lbl.setBackground (Color.lightGray);
      add (lbl);
    }
    TextField tf = new TextField (n);
    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.addActionListener (this);
    return b;
  }

  public controles (dessin D, table T)
  { 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 (tproba1 = atf ("Probabilités de désintégration :", 5));
    add (tproba2 = atf ("", 5));
    tproba1.setText (Double.toString (D.proba1));
    tproba2.setText (Double.toString (D.proba2));
    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;
    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);
      double p1 = pdbl (tproba1, D.proba1);
      double p2 = pdbl (tproba2, D.proba2);
      double p12 = p1 + p2;
      if (p12 <= 1.0)
      { D.proba1 = p1;
      	D.proba2 = p2;
      	D.p12 = p12;
      	tproba1.setText (Double.toString (p1));
      	tproba2.setText (Double.toString (p2));
      }
      D.retrace = T.retrace = true;
      T.ta.setText ("");
      D.repaint ();
      T.repaint ();
    }
  }
}
////////////////////////////////////////////////////////////////////////////////
protected class table extends Panel {
  static final long serialVersionUID = 180205L;
  TextArea ta;
  dessin D;
  boolean retrace;

  public table (dessin D)
  { this.D = D;
    setLayout (new FlowLayout());
    setBackground (Color.lightGray);
    add (ta = new TextArea ("", 6, 50, TextArea.SCROLLBARS_HORIZONTAL_ONLY));
    retrace = false;
  }

  public void paint (Graphics g)
  { if (retrace)
    { retrace = false;
      String s1 = "temps         \t";
      String s2 = "particules K  \t";
      String s3 = "particules Ca \t";
      String s4 = "particules Ar \t";
      for (int i = 0; i < D.temps; i ++)
      { int dhi1 = D.histogramme1 [i];
        int dhi2 = D.histogramme2 [i];
        int dhi = D.nparticules - dhi1 - dhi2;
        s1 += Integer.toString (i) + "\t";
        s2 += Integer.toString (dhi) + "\t";
        s3 += Integer.toString (dhi1) + "\t";
        s4 += Integer.toString (dhi2) + "\t";
      }
      ta.setText (s1 + "\n" + s2 + "\n" + s3 + "\n" + s4);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////

	public static void main (String [] args) {

// Création et lancement de l'applet
		desintegrv2 d = new desintegrv2();
		d.init ();
		d.start ();

// Création de la fenêtre contenant l'applet
		Frame f = new Frame ("desintegrv2");
		f.addWindowListener (new fermer ());
		f.add (d);
		f.setSize (650, 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);
		}
	}

}
