/*
Kvantova jama
Ondrej Psencik


*/

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.lang.System.*;
import java.lang.Math.*;
import java.lang.*;
import java.lang.Thread;
import java.text.NumberFormat;
import java.math.*;


//Applet zije
public class KvantovaJama extends Applet implements ActionListener, AdjustmentListener{
int width=600;
int height=400;
SimPanel plocha;
SelArea selekty;
Button animace;
Button zobr,plus,minus,pred,po, restime;
Checkbox vypln;
Label cas,dtcas;
Label popis1,popis2, popis3;
Vlakno vlak;	
int stav=0;
Scrollbar rychlost, scrldt;


	public void init()
	{
	  resize(width,height);
	  setLayout(null);
	  setBackground(Color.lightGray);

	  Font f=new Font("Helvetica",Font.PLAIN,12);
	  setFont(f);

	  selekty=new SelArea(10,10,this);
	  add(selekty);

	  plocha=new SimPanel(340,40,createImage(250,270),selekty);
	  add(plocha);
	  
	  
	  animace=new Button("Run");
	  add(animace);
	  animace.setSize(50,30);
	  animace.setLocation(420,320);
	  animace.addActionListener(this);

/*	  zobr=new Button("Stop");
	  add(zobr);
	  zobr.setSize(50,30);
	  zobr.setLocation(420,320);
	  zobr.addActionListener(this);
	  */
/*  	  plus=new Button("+");
	  add(plus);
	  plus.setSize(15,15);
	  plus.setLocation(380,360);
	  plus.addActionListener(this);

  	  minus=new Button("-");
	  add(minus);
	  minus.setSize(15,15);
	  minus.setLocation(490,360);
	  minus.addActionListener(this);
*/
  	  restime=new Button("Reset");
	  add(restime);
	  restime.setSize(50,30);
	  restime.setLocation(480,320);
	  restime.addActionListener(this);


  	  pred=new Button("<");
	  add(pred);
	  pred.setSize(50,30);
	  pred.setLocation(360,320);
	  pred.addActionListener(this);

  	  po=new Button(">");
	  add(po);
	  po.setSize(50,30);
	  po.setLocation(540,320);
	  po.addActionListener(this);


		popis1=new Label("Časový krok:");
	  add(popis1);
	  popis1.setSize(popis1.getMinimumSize());
	  popis1.setLocation(20,316);

	/*	popis2=new Label("Aktualni cas(t):");
	  add(popis2);
	  popis2.setSize(popis2.getMinimumSize());
	  popis2.setLocation(290,375);
	  */
/*
		dtcas=new Label(Double.toString(plocha.dt));
	  add(dtcas);
	  dtcas.setSize(90,15);
	  dtcas.setLocation(400,360);
*/	  
	/*	cas=new Label(Double.toString(plocha.t));
	  add(cas);
	  cas.setSize(90,15);
	  cas.setLocation(400,380);
*/
		rychlost=new Scrollbar(Scrollbar.HORIZONTAL,90,1,1,100);
		rychlost.setSize(100,15); rychlost.setLocation(130,340);
		add(rychlost);
		rychlost.addAdjustmentListener(this);

		scrldt=new Scrollbar(Scrollbar.HORIZONTAL,10,1,1,50);
		scrldt.setSize(100,15); scrldt.setLocation(20,340);
		add(scrldt);
		scrldt.addAdjustmentListener(new AdjustmentListener(){
			  public void adjustmentValueChanged(AdjustmentEvent e)
			  {
			  	  plocha.dt=0.0001*e.getValue();
    		  }
			});


		popis3=new Label("Rychlost animace:");
	  add(popis3);
	  popis3.setSize(popis3.getMinimumSize());
	  popis3.setLocation(130,316);

	  vypln=new Checkbox ("Výplň grafu",true);
	  vypln.setSize(100,20);
	  vypln.setLocation(340,10);
    add(vypln);
    vypln.addItemListener(new ItemListener(){
    	
    	  public void itemStateChanged(ItemEvent e)
    	  { 
    	  	  if(e.getStateChange()==ItemEvent.SELECTED)
    	  	  {plocha.vypln=1; }
    	  	  else
    	  	  {plocha.vypln=0; }
				if(vlak==null)plocha.Kalkuluj();    	  	  
    	  }
     
	
    });
    plocha.vypln=1; plocha.Kalkuluj();
    animace.setVisible(true);

	  repaint();
	}
	

  public void adjustmentValueChanged(AdjustmentEvent e) 
	{
     plocha.simrychlost=100-e.getValue();
	}


	public void paint(Graphics g)
	{
     g.drawRoundRect(1,1,width-2,height-2,30,30);
	}
	
  public void actionPerformed(ActionEvent e)
	{
		
		if(e.getActionCommand()=="Run"){
			if(stav==0){
					vlak=new Vlakno(plocha);
					vlak.start();
					stav=1;
					pred.setVisible(false);					
					po.setVisible(false);
					animace.setLabel("Stop");					
//					animace.setVisible(false);
//					zobr.setVisible(true);
			}
		} else

		if(e.getActionCommand()=="Reset"){
			plocha.t=1;
		//	cas.setText(Double.toString(plocha.t));
			repaint();
			if(animace.getLabel()=="Run")plocha.Kalkuluj();
		} else
		
		if(e.getActionCommand()=="Stop"){
			if(stav==1){
					if (vlak!=null) vlak.stop();
					vlak=null;
					
					pred.setVisible(true);					
					po.setVisible(true);					
					animace.setLabel("Run");					
					
					repaint();
					stav=0;
					if (vlak!=null)
					  while(vlak.isAlive());
					
					plocha.Kalkuluj();			  			
			}
		} else

		if(e.getActionCommand()=="+"){
			plocha.dt*=10.0;
		//	dtcas.setText(Double.toString(plocha.dt));
		//	dtcas.repaint();
		} else

		if(e.getActionCommand()=="-"){
			plocha.dt/=10.0;
		//	dtcas.setText(Double.toString(plocha.dt));
		//	dtcas.repaint();
		} else

		if(e.getActionCommand()==">"){
			plocha.t+=plocha.dt;
		//	cas.setText(Double.toString(plocha.t));
			repaint();
			plocha.Kalkuluj();			
		} else
		
		if(e.getActionCommand()=="<"){
			plocha.t-=plocha.dt;
		//	cas.setText(Double.toString(plocha.t));
			repaint();
			plocha.Kalkuluj();
		}

		

	}

}


//Deklarace Simulacniho panelu
class SimPanel extends Panel 
{
	Image MyBuffer;	
	Graphics MyGr,OldGr;
	MediaTracker mt;
  
  Color simbarva=new Color(102,130,162);
  Color grafbarva=Color.black;
  
  
  int simrychlost=10;
  
  int width=250;
  int height=270;
  int mult=10; //multiplikace osy
  double rozdilx=210;
  
  int vypln=0;
  double dt=0.001;
  double d=1;
  double t=1;
  double fixt,wtx;
	SelArea selekty;  	
	
	int []aryN=new int[11];
  double []aryCn=new double[11];
	
	public SimPanel(int x, int y, Image i, SelArea sel)
	{
		selekty=sel;
	  setSize(width,height);
	  setLocation(x,y);
	  mt=new MediaTracker(this);
	  MyBuffer = i;
	  mt.addImage(MyBuffer,1);
    try {mt.waitForAll();}
    catch(Exception e) {};

    MyGr=MyBuffer.getGraphics();

    MyGr.setColor(simbarva);
    MyGr.fillRoundRect(0,0,250,270,20,20);
    
    MyGr.setColor(grafbarva);
    MyGr.drawLine(20,20,20,250);
    MyGr.drawLine(20,250,230,250);
    MyGr.drawLine(230,250,230,20);

    Konverse();
    Kalkuluj();
    repaint();   
	}
	
	
	public double FIn(double x, int n)
	{
     return(Math.sqrt(2/d)*Math.sin((Math.PI*x*n)/d));
	}
	
	public double En(int n)
	{
	  return((Math.PI*Math.PI*n*n)/(2*d*d));
	}
	
	public void FI(double t, double x)
	{  double Cn,Re,Im;
		 int n;
		 
		 Re=0;
		 Im=0;
		 
	   for(int i=1;i<=10;i++){
	   	Cn=aryCn[i];
	   	n=aryN[i];
	   	Re+=Math.cos(En(n)*t)*Cn*FIn(x,n);
	   	Im+=Math.sin(En(n)*t)*Cn*FIn(x,n);
	   }	
		 wtx=Re*Re+Im*Im;
	}
	
	
	public void Konverse(int poradi)
	{
   	aryCn[poradi]=(double)(99-selekty.ArCn[poradi].getValue())/100;
	}

	public void Konverse()
	{
	   for(int i=1;i<=10;i++){
	   	aryCn[i]=(double)(99-selekty.ArCn[i].getValue())/100;
	   	aryN[i]=i;//Integer.valueOf(selekty.ArN[i].getText()).intValue();
	   }	
	}
	
	public void Kalkuluj()
	{  int x,y,sx,sy;
     //MyGr.drawRoundRect(1,1,width-2,height-2,15,15);
     
     MyGr.setColor(simbarva);
     MyGr.fillRect(21,0,209,250);
    	FI(t,1/rozdilx);
    	x=21; y=(int)(wtx*mult);
     MyGr.setColor(grafbarva);

    	     
     if(vypln==0){
     for(int i=21; i<=230; i+=1){
      	sx=x; sy=y;     	
      	FI(t,(i-20.0)/rozdilx);
      	x=i; y=(int)(wtx*mult);
      	MyGr.setColor(new Color((y*2>255)?255:y*2,0,0));
      	
      	MyGr.drawLine(sx,250-sy,x,250-y);
      //	MyGr.drawLine(sx,280-sy,sx,279);//fill
     }}
     else{
     for(int i=21; i<=230; i+=1){
      	sx=x; sy=y;     	
      	FI(t,(i-20.0)/rozdilx);
      	x=i; y=(int)(wtx*mult);
      	MyGr.drawLine(sx,250-sy,x,250-y);
      	MyGr.setColor(new Color((y*2>255)?255:y*2,0,0));
      	MyGr.drawLine(sx,250-sy,sx,249);//fill
     }}
     	
     	
    repaint();
	}
	
	public void update(Graphics g)
	{
	  paint(g);	
	}
	
	public void paint(Graphics g)
	{
		g.drawImage(MyBuffer,0,0,this);		
	}
	
}

class SelArea extends Panel implements AdjustmentListener, ActionListener
{ 
	int width=320;
	int height=300;
  

  Button refresh;
  Scrollbar s;
  TextField t;
  Font f;
  KvantovaJama mparent;
  Label l;
  
  
  Scrollbar[] ArCn=new Scrollbar[11];
  	TextField[] ArN=new TextField[11];
  	int z;
  	
  Color pozadColor=new Color(177,176,105);
  
  public SelArea(int x, int y, KvantovaJama parent)
  	{  
  		mparent=parent;
		setSize(width,height);
		setLocation(x,y);
		setLayout(null);
		setBackground(Color.lightGray);

    refresh=new Button("Uplatni zmeny");
    refresh.setSize(80,20);
    refresh.setLocation(10,270);
  //  add(refresh);
  /*  refresh.addActionListener(new ActionListener(){
      	
      public void actionPerformed(ActionEvent e){
        mparent.plocha.Konverse();		    
        mparent.plocha.Kalkuluj();
      }
	   }
  	  );
*/

	  f=new Font("Helvetica",Font.PLAIN,14);
 	
 		l=new Label("Váha stavů:");
		l.setLocation(20,20);
		l.setBackground(pozadColor);
		l.setFont(f);

		add(l);
		l.setSize(170,30); 
		


	  f=new Font("Helvetica",Font.PLAIN,10);
	  setFont(f);

		
		for(int i=1;i<=10;i++){
			s=new Scrollbar(Scrollbar.VERTICAL,50,1,0,100);
			s.setSize(15,100); s.setLocation(i*30-15,100);
			add(s);
			if((i==5) || (i==6)) {s.setValue(0);}
			else s.setValue(100);
			z=i;
			s.addAdjustmentListener( new AdjustmentListener() {
				  int poradi=z;
				  
				  public void adjustmentValueChanged(AdjustmentEvent e)
				  {
		         mparent.plocha.Konverse(poradi);		    
		         if(mparent.animace.getLabel()=="Run")
		         	   mparent.plocha.Kalkuluj();
					}
			  }
			);
			ArCn[i]=s;
			l=new Label(Integer.toString(i));
			l.setSize(20,20); l.setLocation(i*30-18,70);
			add(l);
			l.setAlignment(Label.CENTER);
			l.setBackground(pozadColor);
			
			//ArN[i]=l;
		}
		
	}
	

 public void actionPerformed(ActionEvent e)
 {
     mparent.plocha.Konverse();
 }

 public void adjustmentValueChanged(AdjustmentEvent e) 
	{
	}
  	
  	

  	
  	public void paint(Graphics g)
	{
    g.setColor(pozadColor);
    g.fillRoundRect(1,1,width-2,height-2,15,15);		
    g.setColor(Color.black);
    g.drawRoundRect(1,1,width-2,height-2,15,15);		
    
	}
	


	
}

class Vlakno extends Thread
{
  SimPanel panel;
  
   public Vlakno(SimPanel panel)
	{
		this.panel=panel;
	}
	
	public void run()
	{
		//panel.t=0;
		while(true){
		  panel.t+=panel.dt;		
		  panel.Kalkuluj();
		  
		  try{sleep(panel.simrychlost);}
			catch(InterruptedException e){};
			
		}
	}
}