/******************************************************************
        Java Applet mc.java
        Modelling and simulation 
This applet provides a _simulation_ of the example to explain
teh idea of Monte Carlo simulation for the determination of 
the value of Area.

******************************************************************/

import java.applet.*;
import java.awt.*;

public class mc extends Applet implements Runnable
{
  Dimension offDimension, d;  // Variables used to create an
  Image offImage;             // offscreen image via the update() 
  Graphics offGraphics;       // method, to reduce flicker

  int xBorder = 15;     // Basic layout variables
  int yBorder = 45; 
  int margin = 50; 
     
  int tableHeight = 200;    // 
  int tableWidth = 200;                      // Define size of table
  int tableXcorner = xBorder;                // where needles are thrown
  int tableYcorner = yBorder;                // 
     
  int barWidth = 20;             // Define size of bar graph
  int barHeight = tableHeight;
  int barXcorner = xBorder+tableXcorner+tableWidth+margin;
  int barYcorner = tableYcorner; 

  double barTop = 0.80;     // Set limits for limits of bar graph
  double barBot = 0.77;  
  double barMid = (barTop+barBot)/2;
 
  int barValue;     // Dynamic value of the bar graph
   
  int plotWidth = 200;          // Define size of plot
  int plotHeight = tableHeight; 
  int plotXcorner = barXcorner+margin+barWidth+xBorder;
  int plotYcorner = tableYcorner; 

  double plotMax = 1.0;      // Set limits on the plot
  double plotMin = 0.0;
  double plotMid = (plotMax+plotMin)/2;    

  int barMaxPlot = (int) (plotHeight*(plotMax-barTop)/
			  (plotMax-plotMin));
  int barMinPlot = (int) (plotHeight*(plotMax-barBot)/
			  (plotMax-plotMin));  
  int barThick = (barMaxPlot==barMinPlot? 1 :
		  barMinPlot-barMaxPlot);  
 
  int pointerWidth=30;          // Bar graph pointer
  int pointerTop, pointerBot;  
   
  int power = 5;  // Orders of magnitude for the x-axis of the plot
   
  int n = 0;     // The number of sampling points thrown 
  int hit = 0;   // The number of sampling points which is in the figure S
  int i = 1;     // 

  double spX1, spY1;
  
  int x1,  y1;      // Used to draw sampling points
  int gx1, gx2, gy1, gy2;  // Used to make the plot

  int speed = 20;   // Sets speed with try-catch block
     
  double h = 0;             // double version of the number of hits
  double estArea, prevEstArea;  // Estimates of Area
  double prob = 1;          // Ratio of hits to trys
  double prev = 1;          // Ratio on the previous trial
  
  boolean oldScreen = false;
  boolean begin = false;
  boolean infigure = false;
  
  Thread t;
  Button b1, b2, b3, b4;

  public void init()                     
  {                                    
    setLayout(new FlowLayout(FlowLayout.LEFT));
    b1 = new Button("Start");
    b2 = new Button("Pomaly");
    b3 = new Button("Rychlo");
    b4 = new Button("Urob");
	 
    add(b1);
    add(b2);
    add(b3);
    add(b4);
	 
    t = new Thread(this);
    t.start();
  }
  
  public boolean action(Event e, Object o)
  {
    if (o.equals("Start"))
      {
	n = 0;
	hit = 0;
	oldScreen = false;
	begin = true;  
      }
    else if (o.equals("Urob"))
      { 
	t.stop();
      }
    else if (o.equals("Pomaly"))
      {
	speed = (speed>10? speed-10 : 10);         
      }                   
    else if (o.equals("Rychlo"))
      {
	speed = speed+10;
      } 
    return true;
  }
  
  public void run()      
  {                      
    while(true)       
      {
	if(begin)
	  {    
	    // Calculate the position of the sampling points...   
	    
	    spX1 = Math.random();
	    spY1 = Math.random();
	    infigure = false;
	    
	    // Check to see if it is in the figure S ...   

	    if( Math.sqrt((spX1-0.5)*(spX1-0.5)+(spY1-0.5)*(spY1-0.5)) < 0.5)
	      {
		hit++;
		infigure = true;
		//		break;  
	      }
	    
	    n++;   
	    prev = prob;
	    h = hit;
	    prob = h/n;
	    prevEstArea = prev;
	    estArea = prob;
	    
	    spX1 = tableWidth*spX1;
	    spY1 = tableHeight*spY1;

	    // Calculation for the plot
	    
	    gx1 = (int)(plotXcorner+Math.log(n)*
			plotWidth/(power*Math.log(10)));
	    gx2 = (int)(plotXcorner+Math.log(n+1)*
			plotWidth/(power*Math.log(10)));
	    gy1 = (int)(plotYcorner+(plotHeight/(plotMin-plotMax))*
			(prevEstArea-plotMax));
	    if (gy1<=plotYcorner) gy1 = plotYcorner+1;
	    if (gy1==plotYcorner+plotHeight) gy1=gy1-1;
	    gy2 = (int)(plotYcorner+(plotHeight/(plotMin-plotMax))*
			(estArea-plotMax));
	    if (gy2<=plotYcorner) gy2 = plotYcorner+1;      
	    if (gy2==plotYcorner+plotHeight) gy2=gy2-1;
	    
	    // Calculation for drawing the sampling points

	    x1 = (int) (xBorder+spX1);
	    //	    x2 = (int) (xBorder+needleX1+2);
	    y1 = (int) (yBorder+spY1);
	    //	    y2 = (int) (yBorder+needleY1+2);
	    repaint();
	  }
	try
	  {
	    Thread.currentThread().sleep(speed);
	  }
	catch(InterruptedException e) 
	  {
	  }	       	         
      }
  }
  
  public void paint(Graphics g)         
  {                                  
    d = size();
    update(g);
  }
  
  public void update(Graphics g)
  {
    if((offGraphics==null)                // Setup an off-screen image
       ||(d.width!=offDimension.width)      // via the update() method.
       || (d.height!=offDimension.height)) //
      {
	offDimension = d;
	offImage = createImage(d.width, d.height);
	offGraphics = offImage.getGraphics();
      }
    
    if(!oldScreen)
      {                    
	offGraphics.setColor(Color.red);        
	offGraphics.drawRect(0,0, d.width, d.height); 
	offGraphics.setColor(getBackground());        
	offGraphics.fillRect(0,0, d.width, d.height); 
	offGraphics.setColor(Color.gray); 
	offGraphics.fillRect(plotXcorner, plotYcorner+barMaxPlot,
			     plotWidth, barMinPlot-barMaxPlot);
	offGraphics.drawString(" "+barMid+"-", barXcorner-45,
			       barYcorner+barHeight/2);
	offGraphics.drawString(" "+barTop+"-", barXcorner-45, 
			       barYcorner+5);
	offGraphics.drawString(" "+barBot+"-", barXcorner-45, 
			       barYcorner+3+barHeight);
	offGraphics.drawString("-"+plotMax, plotXcorner+plotWidth+2,
			       plotYcorner+5);
	offGraphics.drawString("-"+plotMin, plotXcorner+plotWidth+2,
			       plotYcorner+plotHeight+5);
	offGraphics.drawString("-"+plotMid, plotXcorner+plotWidth+2,
			       plotYcorner+plotHeight/2+5);	
	offGraphics.drawString("Estimate vs. log(number of tries)",
			       plotXcorner+5, plotYcorner+plotHeight+20);
  
	// Draw lines which relate the bar graph and the plot... 
        
	offGraphics.drawLine(barXcorner+barWidth+5, barYcorner, 
			     plotXcorner-5, barMaxPlot+plotYcorner);
	offGraphics.drawLine(barXcorner+barWidth+5, barYcorner+barHeight, 
			     plotXcorner-5, barMinPlot+plotYcorner);  
	
	// Draw tabletop and the plot axes
	
	offGraphics.setColor(Color.blue);
	offGraphics.drawRect(tableXcorner,tableYcorner, 
			     tableWidth, tableHeight);
	offGraphics.drawRect(plotXcorner, plotYcorner,plotWidth, plotHeight);
	
	offGraphics.drawOval(tableXcorner, tableYcorner,
			     (int)(tableWidth),(int)(tableHeight));
	
	oldScreen = true;                              
      }                                             
    
    else                                         
      {                                             
	offGraphics.setColor(getBackground());
	offGraphics.fillRect(0,0, d.width, yBorder-10);
      }

    // Write n and estArea to screen
    
    offGraphics.setColor(Color.black);
    offGraphics.drawString("Current estimate of area: "+estArea, 
			   plotXcorner+10, 20);
    offGraphics.drawString("Number of tries: "+n, 230, 20);
    offGraphics.drawString("Number of hits: "+hit, 230, 30);

    offGraphics.setColor(Color.black);
    
    // Make sure that none of the sampling points appear outside 
    // the table boundary: 
	
    x1 = (x1<tableXcorner?tableXcorner:x1);                     
    x1 = (x1>tableXcorner+tableWidth?
	  tableXcorner+tableWidth:x1);       

    y1 = (y1<tableYcorner?tableYcorner:y1);                     
    y1 = (y1>tableYcorner+tableHeight?
	  tableYcorner+tableHeight:y1);
    
    if (infigure) 
      {
	offGraphics.setColor(Color.green);
	offGraphics.drawOval(x1,y1,1,1);
      }
    else
      {
	offGraphics.drawOval(x1,y1,1,1);
      }

    // Draw the bar graph

    offGraphics.setColor(Color.gray);
    offGraphics.fillRect(barXcorner, barYcorner, 20, barHeight);
    
    offGraphics.setColor(Color.red);
    
    barValue = (int)(barHeight*(estArea-barTop)/(barBot-barTop));       
    if (barValue<0-pointerWidth/2) barValue=0-pointerWidth/2;
    if (barValue>barHeight+pointerWidth/2) barValue=barHeight+
					     pointerWidth/2;
    
    pointerTop = (barValue-pointerWidth/2<0 ? 
		  0 : barValue-pointerWidth/2); 
    pointerBot = (barValue+pointerWidth/2>barHeight? 
		  barHeight : barValue+pointerWidth/2);
    
    offGraphics.fillRect(barXcorner, barYcorner+pointerTop, 
			 barWidth, pointerBot-pointerTop);
    
    // Center line in the pointer
    
    offGraphics.setColor(Color.gray);
    if (barValue<0) barValue=0;
    if (barValue>barHeight) barValue=barHeight;  
    offGraphics.drawLine(barXcorner, barYcorner+barValue, 
			 barXcorner+barWidth-1, barYcorner+barValue);
    
    // Finally, draw the plot	
    
    offGraphics.setColor(Color.red);   
    
    offGraphics.drawLine(gx1,gy1,gx2,gy2);
    g.drawImage(offImage, 0, 0, this);
  }
}









