/* desintegr2.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 desintegr2 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 ()
  { setLayout (new BorderLayout ());
  	setFont (new Font ("Arial", Font.PLAIN, 10));
  	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;
    }
    D = new dessin (gparmi ("nparticules", 1000), proba1, proba2, p12, gparmi ("max", 50), gparmi ("dt", 0));
    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 "desintegr par j.-p. Quelen"; }

////////////////////////////////////////////////////////////////////////////////
protected class dessin extends Canvas implements MouseMotionListener {
  static final long serialVersionUID = 180205L;
  Image img;
  Graphics g;
  int nparticules, max, bsup, w, h, hmax, dt, xret, yret;
  double proba1, proba2, p12;
  int [] histogramme;
  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 ();
    addMouseMotionListener (this);
    setCursor (new Cursor (Cursor.CROSSHAIR_CURSOR));
  }

  private void h (Graphics g)
  { bsup = max - 1;
    while (bsup >= 0 && histogramme [bsup] == 0) bsup --;
    bsup ++;
    hmax = 0;
    for (int i = 0; i < bsup; i ++)
    { int hi = histogramme [i];
      if (hi > hmax) hmax = hi;
    }
    g.setColor (Color.white);
    g.fillRect (1, 1, w - 2, h - 2);
    g.setColor (Color.yellow);
    g.drawLine (20, h - 40, w, h - 40);
    g.drawLine (20, 40, 20, h - 40);
    g.setColor (Color.blue);
    g.drawString ("0", 5, h - 40);
    g.drawString (Integer.toString (hmax) + "_", 5, 40);

    for (int j = 0; j < bsup; j ++)
    { int x = j * (w - 20) / bsup + 20;
      int y = h - 40 - (int)((double)(histogramme [j] * (h - 80)) / hmax);
      Color c = Color.red;
      if (j % 3 == 1) c = Color.green;
      else if (j % 3 == 2) c = Color.blue;
      g.setColor (c);
      g.drawLine (x, y, x, h - 40);
      if ((j % 3 == 2) && ((j / 3) % 10 == 9))
      { g.setColor (Color.black);
        g.drawString (Integer.toString ((j / 3) + 1), x, h - 10);
      }
    }
      g.setColor (Color.black);
      g.drawRect (0, 0, w - 1, h - 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);
      }
    if (histogramme == null) histogramme = new int [max];
    if (retrace)
    { retrace = false;
      for (int j = 0; j < histogramme.length; j ++) histogramme [j] = 0;
      int temps = 0;
      int nndes = nparticules;
      int n1 = 0;
      int n2 = 0;
      while (nndes > 0)
      { if (temps + 2 >= histogramme.length)
        { max += max;
          int [] nh = new int [max];
          System.arraycopy (histogramme, 0, nh, 0, histogramme.length);
          histogramme = nh;
        }
        histogramme [temps ++] = nndes;
        histogramme [temps ++] = n1;
        histogramme [temps ++] = n2;
        h (g);
        g1.drawImage (img, 0, 0, this);
        if (dt > 0)
        { try { Thread.sleep (dt); }
          catch (InterruptedException e) {}
        }
        int nnndes = nndes;
        for (int i = 0; i < nndes; i ++)
        { double rndnd = rnd.nextDouble ();
          if (rndnd < proba1)
          { nnndes --;
            n1 ++;
          }
          else if (rndnd < p12)
          { nnndes --;
            n2 ++;
          }
        }    
        nndes = nnndes;
      }
    }
    g.setColor (Color.white);
    g.fillRect (0, 0, w, 25);
    g.setColor (Color.black);
    if (bsup > 0)
      g.drawString ("(" + ((xret - 20) * bsup / (3 * (w - 20))) + ", " + ((yret - h + 40) * hmax / (80 - h)) + ")", 10, 20);
    g.drawRect (0, 0, w - 1, h - 1);
    g1.drawImage (img, 0, 0, this);
  }

  public void mouseDragged (MouseEvent e)
  { e.consume ();
  	xret = e.getX () + 1;
  	yret = e.getY ();
  	repaint ();
  }

  public void mouseMoved (MouseEvent e)
  { e.consume ();
  	xret = e.getX () + 1;
  	yret = e.getY ();
  	repaint ();
  }

}
////////////////////////////////////////////////////////////////////////////////
protected class controles extends Panel implements ActionListener {
  static final long serialVersionUID = 180205L;
  dessin D;
  table T;
  TextField tparticules, tproba1, tproba2, tdt;
  Button ok;

  private Label ajoutlbl (String s)
  { Label lbl = new Label (s);
    lbl.setBackground (Color.lightGray);
    return lbl;
  }

  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 ("", 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
		desintegr2 d = new desintegr2();
		d.init ();
		d.start ();

// Création de la fenêtre contenant l'applet
		Frame f = new Frame ("desintegr2");
		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);
		}
	}

}
