/* equidyn.java - jpq - 30/12/05 - 14/01/06 - 29/04/06
 * ajout de main() le 05/02/18
 */

import java.awt.event.*;
import java.awt.*;
import java.applet.*;
import java.util.*;

public class equidyn extends java.applet.Applet {
  static final long serialVersionUID = 180205L;
  dessin D;
  controles C;

  private long parms (String s, long n) {
    try {
	  s = getParameter (s);
	  n = Integer.parseInt (s);
	}
    catch (NumberFormatException e) {}
	catch (NullPointerException e) {}
	if (n < 0)
	  n = 1;
    return n;
  }

  private double dparms (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 = 1.0;
    return d;
  }

  public void init ()
  { setLayout (new BorderLayout ());
  	setFont (new Font ("Arial", Font.PLAIN, 10));
    D = new dessin (parms("bleu", 40), parms("vert", 40), parms("jaune", 0), parms("rouge", 0), parms("noir", 0),
	                dparms("p1", 0.8), dparms("p2", 0.8), parms("simul", 100));
    C = new controles (D);
    add (C, BorderLayout.NORTH);
    add (D, BorderLayout.CENTER);
  }

  public void destroy ()
  { remove (D); remove (C); }

  public String getAppletInfo ()
  { return "equidyn par j.-p. Quelen"; }

////////////////////////////////////////////////////////////////////////////////
protected class dessin extends Canvas {
  static final long serialVersionUID = 180205L;
  Image img;
  Graphics g;
  int w, h, wsur6;
  boolean retrace, chgt;
  long nB, nV, nJ, nR, nN, nB1, nV1, nJ1, nR1, simul, totalsimul;
  double p1, p2;
  Random rnd;

  public dessin (long nB, long nV, long nJ, long nR, long nN, double p1, double p2, long simul)
  { nB1 = this.nB = nB;
    nV1 = this.nV = nV;
    nJ1 = this.nJ = nJ;
    nR1 = this.nR = nR;
    this.nN = nN;
    this.p1 = p1;
    this.p2 = p2;
    this.simul = simul;
//    totalsimul = 0;
    if (nB + nV + nJ + nR + nN == 0) nN = 2;
    rnd = new Random ();
    retrace = true;
  }

  public void update (Graphics g)
  { paint (g); }

  private void efface (Graphics g)
  { g.setColor (Color.white);
    g.fillRect (0, 0, w, h);
    g.setColor (Color.black);
    g.drawRect (0, 0, w - 1, h - 1);
    for (int i = 1; i < 10; i ++)
    { int hi = (int)((double)(h * i) / 10.0);
    	g.drawLine (0, hi, 20, hi);
    	g.drawString ("0." + (10 - i), 25, hi);
    }
  }

  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 ();
      wsur6 = w / 6;
    }
    if (retrace)
    { retrace = false;
    	long total = nB + nV + nJ + nR + nN;
    	totalsimul += simul;
    	for (long i = 0; i < simul; i ++)
    	{ chgt = false;
        double d = rnd.nextDouble ();
        int b1 = 4;
        if (d <= (double) (nB1) / (double) (total)) b1 = 0;
        else if (d <= (double) (nB1 + nV1) / (double) (total)) b1 = 1;
        else if (d <= (double) (nB1 + nV1 + nJ1) / (double) (total)) b1 = 2;
        else if (d <= (double) (nB1 + nV1 + nJ1 + nR1) / (double) (total)) b1 = 3;
        int b2 = 4;
        d = rnd.nextDouble ();
        if (d <= (double) (nB1) / (double) (total)) b2 = 0;
        else if (d <= (double) (nB1 + nV1) / (double) (total)) b2 = 1;
        else if (d <= (double) (nB1 + nV1 + nJ1) / (double) (total)) b2 = 2;
        else if (d <= (double) (nB1 + nV1 + nJ1 + nR1) / (double) (total)) b2 = 3;
        if ((b1 == 0) && (b2 == 1) || (b1 == 1) && (b2 == 0))
        { d = rnd.nextDouble ();
        	if (d <= p1)
        	{ chgt = true;
        		nB1 --;
        		nV1 --;
        		nJ1 ++;
      	  	nR1 ++;
          }
        }
        else if ((b1 == 2) && (b2 == 3) || (b1 == 3) && (b2 == 2))
        { d = rnd.nextDouble ();
        	if (d <= p2)
      	  { chgt = true;
      		  nB1 ++;
        		nV1 ++;
        		nJ1 --;
        		nR1 --;
          }
        }
        if (chgt)
        { efface (g);
      	  g.setColor (Color.blue);
      	  int h1 = (int) (h * nB1 / total);
        	g.fillRect (wsur6, h - h1, 10, h1);
        	g.setColor (Color.green);
        	h1 = (int) (h * nV1 / total);
        	g.fillRect (2 * wsur6, h - h1, 10, h1);
        	g.setColor (Color.yellow);
        	h1 = (int) (h * nJ1 / total);
      	  g.fillRect (3 * wsur6, h - h1, 10, h1);
        	g.setColor (Color.red);
        	h1 = (int) (h * nR1 / total);
        	g.fillRect (4 * wsur6, h - h1, 10, h1);
        	g.setColor (Color.black);
        	h1 = (int) (h * nN / total);
        	g.fillRect (5 * wsur6, h - h1, 10, h1);
        	g1.drawImage (img, 0, 0, this);
        }
      }      
//        try { Thread.sleep (dt); }
//        catch (InterruptedException e) {}
    }
   	g.drawString (totalsimul + " tirages; b = " + nB1 + "; v = " + nV1 + "; j = " + nJ1 + "; r = " + nR1 + "; n = " + nN, 10, 20);
    g.setColor (Color.black);
    g.drawRect (0, 0, w - 1, h - 1);
    g1.drawImage (img, 0, 0, this);
  }
}
////////////////////////////////////////////////////////////////////////////////
protected class controles extends Panel implements ActionListener {
  static final long serialVersionUID = 180205L;dessin D;
  TextField tb, tv, tj, tr, tn, tp1, tp2, tsimul;
  Button ok, plus;
  Font f;

  private Label ajoutlbl (String s)
  { Label lbl = new Label (s);
    lbl.setBackground (Color.lightGray);
    return lbl;
  }

  private TextField ajouttf (long n, int k)
  { return new TextField (Long.toString (n), k);
  }

  private TextField ajouttfd (double d, int k)
  { return new TextField (Double.toString (d), k);
  }

  public controles (dessin D)
  { this.D = D;
    setBackground (Color.lightGray);
    setLayout(new GridLayout(2, 1));
    Panel p = new Panel ();
    add (p);
    p.add (ajoutlbl ("b :"));
    p.add (tb = ajouttf (D.nB, 5));
    p.add (ajoutlbl ("v :"));
    p.add (tv = ajouttf (D.nV, 5));
    p.add (ajoutlbl ("j :"));
    p.add (tj = ajouttf (D.nJ, 5));
    p.add (ajoutlbl ("r :"));
    p.add (tr = ajouttf (D.nR, 5));
    p.add (ajoutlbl ("n :"));
    p.add (tn = ajouttf (D.nN, 5));
    p = new Panel ();
    add (p);
    p.add (ajoutlbl ("p1 :"));
    p.add (tp1 = ajouttfd (D.p1, 5));
    p.add (ajoutlbl ("p2 :"));
    p.add (tp2 = ajouttfd (D.p2, 5));
    p.add (ajoutlbl (" tirages :"));
    p.add (tsimul = ajouttf (D.simul, 5));
    p.add (ok = new Button ("Ok"));
    ok.addActionListener (this);
    p.add (plus = new Button ("+"));
    plus.addActionListener (this);
  }

  private long longparse (TextField tf, long n)
  { long nn = n;
  	try { nn = new Long (tf.getText ()) . longValue ();
          if (nn < 0) nn = n;
  		  }
  	catch (NumberFormatException nfe) { }
  	return nn;
  }

  private double doubleparse (TextField tf, double d)
  { double dd = d;
  	try { dd = new Double (tf.getText ()) . doubleValue ();
          if ((dd < 0.0) || (dd > 1.0)) dd = d;
  		  }
  	catch (NumberFormatException nfe) { }
  	return dd;
  }

  private void longtexte (TextField tf, long n)
  { tf.setText (new Long (n) . toString ());
  }

  private void doubletexte (TextField tf, double d)
  { tf.setText (new Double (d) . toString ());
  }

  public void actionPerformed (ActionEvent e)
  { if ((e.getSource () == ok) || (e.getSource () == plus))
    { D.nB = longparse (tb, D.nB);
    	D.nV = longparse (tv, D.nV);
    	D.nJ = longparse (tj, D.nJ);
    	D.nR = longparse (tr, D.nR);
    	D.nN = longparse (tn, D.nN);
    	D.simul = longparse (tsimul, D.simul);
    	D.p1 = doubleparse (tp1, D.p1);
    	D.p2 = doubleparse (tp2, D.p2);
      if (D.nB + D.nV + D.nJ + D.nR + D.nN == 0) D.nN = 2;
      longtexte (tb, D.nB);
      longtexte (tv, D.nV);
      longtexte (tj, D.nJ);
      longtexte (tr, D.nR);
      longtexte (tn, D.nN);
      longtexte (tsimul, D.simul);
      doubletexte (tp1, D.p1);
      doubletexte (tp2, D.p2);
      if (e.getSource () == ok)
      { D.nB1 = D.nB;
      	D.nV1 = D.nV;
      	D.nJ1 = D.nJ;
      	D.nR1 = D.nR;
      	D.totalsimul = 0;
      }
      D.retrace = true;
      D.repaint ();
    } 
  }
}

////////////////////////////////////////////////////////////////////////////////

	public static void main (String [] args) {

// Création et lancement de l'applet
		equidyn e = new equidyn();
		e.init ();
		e.start ();

// Création de la fenêtre contenant l'applet
		Frame f = new Frame ("equidyn");
		f.addWindowListener (new fermer ());
		f.add (e);
		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);
		}
	}

}
