import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
import java.awt.Graphics;

//Author:H.Hakan GENÇ - December 2015 - Turkiye
//GSM: +905052610452, E-mail:hasanhakangenc@hotmail.com

public class Float_Random_Walk extends Applet{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	String deger, deger2, deger3;
	int sayac=0; 
	double x, y;
	boolean akis=false, aralik1=false, aralik2=false;
	Grafik grafik;
	Thread XY_hareket;
	Panel panel1, panel2, panel3, panel4;

	public void init(){
		System.out.println(getCodeBase());
		Label sayacEtiketi = new Label("250 ile 2000 arası N Değerini Gir:                   ");
		TextField sayacDegeri = new TextField(10);
		Button tamam = new Button("Tamam");
		
		TextField xDegeri = new TextField(10);
		TextField yDegeri = new TextField(10);
		
		Label xyEtiketi = new Label ("Grafikte gösterilen aralığa uygun bir X ve Y değeri girin:");
		Button tamam2 = new Button ("Tamam");
		
		Label X = new Label("X:");
		Label Y = new Label("Y:");
		

		grafik = new Grafik("f0f0f0");
		add(grafik);
		
		panel1 = new Panel();
		panel2 = new Panel();
		panel3 = new Panel();
		panel4 = new Panel();
		
		panel1.setLayout(new FlowLayout(FlowLayout.LEFT));
		panel2.setLayout(new FlowLayout(FlowLayout.LEFT));
		panel3.setLayout(new FlowLayout(FlowLayout.LEFT));
		panel4.setLayout(new BorderLayout());
		
		panel1.add(sayacEtiketi);
		panel1.add(sayacDegeri);
		panel1.add(tamam);
		
		panel2.add(xyEtiketi);
		
		panel3.add(X);
		panel3.add(xDegeri);
		panel3.add(Y);
		panel3.add(yDegeri);
		panel3.add(tamam2);
				
	//	panel3.setLayout(new GridLayout(2,1));
		panel4.add(panel1,"North");
		panel4.add(panel2,"Center");
		panel4.add(panel3,"South");
		
		setLayout(new BorderLayout());
		add(grafik,"South");
		add(panel4,"North");
		
		
		sayacDegeri.setText("");
		tamam.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent event){	
					deger = sayacDegeri.getText();
					sayac = Integer.parseInt(deger);

					if(sayac>=250 && sayac <=2000 && sayac%250 == 0 ){
						sayacEtiketi.setText("Uygun Değer Girildi:                                 ");
						akis=true;
						aralik1=true;
						if(aralik1 && aralik2){
							grafik.guncelle(sayac,akis,XY_hareket,x,y);
						}
					}
					else{
						sayacEtiketi.setText("Lütfen Aralık İçinde ve 250'nin katı bir değer girin");
						akis=false;
						aralik1=false;
					}
					sayac=0;
			}
		});
		
		tamam2.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent event){
				deger2 = xDegeri.getText();
				deger3 = yDegeri.getText();
				x = Double.parseDouble(deger2);
				y = Double.parseDouble(deger3);
				if(x<=2.0 && y<=2.5 && x>0 && y>0){
					xyEtiketi.setText("Uygun Değer Girildi:                    ");
					akis=false;
					aralik2=true;
					sayac=0;
					grafik.guncelle(sayac,akis,XY_hareket,x,y);
				}
				else{
					xyEtiketi.setText("Lütfen aralığa uygun bir değer girin.");
					akis=false;
					aralik2=false;
				}
			}
		});
	}
	public void paint(Graphics g){
	}

}

class Grafik extends Canvas implements Runnable{

	private static final long serialVersionUID = 1L;
	
	int sayac=0, ntrials=5, nrun=0, j;
	double delta=0.01, tolerans=0.005, phi, rc;
	double x, y, xo, yo;
	double sum = 0, sum1=0;
	
	float[] v = new float[10];
	float[] adimlar = new float[10];
	double[] t = new double[]{12.706,4.303,3.182,2.776,2.571,2.447,2.365,2.306,2.262};
	
	int m=0, x_kor=0, y_kor=0;
	double r, rnd;
	boolean akis=false;
	
	float std, error, v_ortalama, adim_ortalama;

	int yukseklik, genislik;
	String renk;
	Thread XY_hareket;
	Image winBellek;
	Graphics gBellek;
	
	public Grafik (String renk){
		this.renk = renk;
		setBackground(Color.decode("#"+renk));
	}
	public void guncelle(int sayac, boolean akis, Thread XY_hareket, double x, double y){
		this.sayac = sayac;
		this.XY_hareket = XY_hareket;
		this.akis = akis;
		xo=x;
		yo=y;
		m=0;
		sum=0;
		sum1=0;
		nrun=0;
		for(int i=1;i<10;i++){
			v[i]=0;
			adimlar[i]=0;
		}
		std=error=v_ortalama=adim_ortalama=0;
	
		if(akis){
			XY_hareket = new Thread(this);
			XY_hareket.start();
			repaint();
		}
		else{
			x_kor = (int)(xo*1.6/delta)+250;
			y_kor = (int)(400-yo*1.6/delta)+10;
			repaint();
		}
	}

	public void run() {
	while(nrun<sayac){
		nrun+=250;
		for(j=1;j<=ntrials;j++){
			sum=0;
			m=0;		
			for (int i=1;i<=nrun;i++){
				x=xo;
				y=yo;
			while(akis){	
				rnd=Math.random();
				phi=2.0*Math.PI*rnd;
				
				rc=Math.sqrt(Math.pow(x-1, 2) + Math.pow(y-1, 2));
				
				// En kısa yol algoritması --- en kısa yol hesaplanıyor...
				if(y>1){
					if(x>1){
						r = 2 - x;	
						if(r>rc){
							r = rc;
						}
						if(r>(2.5-y)){
							r = 2.5 - y;
						}
					}
					else{
						r = x;
						if(r>(y-1)){
							r = y - 1;
						}
						if(r>(2.5-y)){
							r = 2.5 - y;
						}
					}
				}
				else{
					r = x - 1;
					if(r>(2-x)){
						r = 2 - x;
					}
					if(r>y){
						r = y;
					}
				}
				
				x = x + r*Math.cos(phi);
				y = y + r*Math.sin(phi);
				m++;
				
				// (x,y) sınırdamı kontrol ediliyor.
				
				if(x<(1+tolerans) && y<(1+tolerans)){
					akis=false;
				}
				else if(x>=(2-tolerans)){
					sum = sum + 30;
					akis=false;
				}
				else if(y>=(2.5-tolerans)){
					sum = sum + 20;
					akis=false;
				}
				
				else if(y > 1 && x < tolerans) akis=false;
				else if(y < 1 && x < (1 - tolerans)) akis=false;
				else if(y <= tolerans && x >= 1) akis=false;
				else if(y <= (1 + tolerans) && x < 1) akis=false;

				x_kor = (int)(x*1.6/delta)+250;
				y_kor = (int)(400-y*1.6/delta)+10;
				repaint();
				try{
					Thread.sleep(1, 1);
				}
				catch(InterruptedException e){
				}
			}
				akis=true;
			}
			if(nrun!=0){
				v[j]=(float)(sum/nrun);
				adimlar[j]=(float)(m/nrun);
			}
		}
		
		// V ve adım sayısının ortalama değerleri hesaplanıyor.
		sum = 0;
		sum1 = 0;
		for(int i=1;i<=ntrials;i++){
			sum = sum + v[i];
			sum1 = sum1 + adimlar[i];
		}
		v_ortalama=(float)sum/ntrials;
		adim_ortalama=(float)sum1/ntrials;
		
		// hata oranı hesaplanıyor.
		
		sum=0;
		for(int i=1;i<=ntrials;i++){
			sum = sum + Math.pow(v[i]-v_ortalama,2);
		}
		std = (float)Math.sqrt(sum/(ntrials-1));
		error = (float)(std*t[ntrials]/Math.sqrt(ntrials));
	}
	}
	
	public void paint(Graphics g){
		setBackground(Color.decode("#"+renk));
		yukseklik = this.getSize().height;
		genislik = this.getSize().width;
		
		winBellek = createImage(genislik,yukseklik);
		gBellek = winBellek.getGraphics();
		
		
		Font currentFont = g.getFont();
		Font newFont = currentFont.deriveFont(currentFont.getSize() * 1.2F);
		gBellek.setFont(newFont);
		gBellek.drawString("--------------------------------------",10,5);
		gBellek.drawString("--------------------------------------",10,20);
		for(int i=1;i<=ntrials;i++){
			gBellek.setColor(Color.decode("#000000"));
			gBellek.drawString("Nokta: "+Double.toString(xo)+", "+Double.toString(yo)+" Voltaj["+i+"]= "+v[i],5,20+i*30);
			gBellek.setColor(Color.BLUE);
			gBellek.drawString("Koşturma= "+nrun+" Adım Sayısı["+i+"]= "+adimlar[i],5,35+i*30);
		}
		gBellek.setColor(Color.decode("#000000"));
		gBellek.drawString("--------------------------------------",10,200);
		gBellek.drawString("--------------------------------------",10,215);
		gBellek.drawString("     N denemeleri = "+ntrials,5,230);
		gBellek.drawString("  Ortalama voltaj = "+v_ortalama,5,245);
		gBellek.drawString("   Ortalama adım = "+adim_ortalama,5,260);
		gBellek.drawString("           Hata payı = "+error,5,275);
	
		gBellek.setColor(Color.decode("#d7d7d8"));
		for(int i=1;i<=41;i++){
			gBellek.drawLine(250, 10+(10*i), 580, 10+(10*i));
		}
		for(int i=1;i<=33;i++){
			gBellek.drawLine(250+(10*i), 10, 250+(10*i), 420);
		}
		
		gBellek.setColor(Color.decode("#000000"));
		gBellek.drawLine(250, 0, 250, 440);
		gBellek.drawLine(230,420,590,420);
		gBellek.fill3DRect(x_kor, y_kor, 10, 10,true);
		gBellek.drawString("0.0", 230, 435);
		gBellek.drawString("2.0", 560, 435);
		gBellek.drawString("1.0", 400, 435);
		gBellek.drawString("2.5", 230, 25);
		gBellek.drawString("1.0", 230, 265);
		
		gBellek.setColor(Color.decode("#088225"));
		gBellek.drawString("20V", 400,20);
		gBellek.drawString("30V", 570, 250);
		gBellek.drawString("0V", 230,150);
		gBellek.drawString("0V", 380, 340);
		
		gBellek.setColor(Color.RED);
		gBellek.drawLine(250, 20, 570, 20);
		gBellek.drawLine(570, 20, 570, 420);
		gBellek.drawLine(410, 420, 570, 420);
		gBellek.drawLine(410, 420, 410, 260);
		gBellek.drawLine(410, 260, 250, 260);
		gBellek.drawLine(250, 260, 250, 20);
		
		g.drawImage(winBellek,0,0,this);
	}
	
	public void update(Graphics g){
		paint(g);
	}
	
	public Dimension getPreferredSize(){
		return new Dimension(550,500);
	}
}
