//
/* ----------------------------------------------------------------------------------------------
    transistor.java		トランジスタ						ver. 1.00 (JDK 1.02)
    														ueyama@infonet.co.jp  1999.03.26
---------------------------------------------------------------------------------------------- */

import java.applet.Applet;
import java.awt.*;
import java.lang.Math;
import java.util.*;

public class transistor extends Applet implements Runnable
{
	int			Ib=0;												// ベース電流
	int			Sw=0;												// コレクタ SW  0:OFF 1:ON
	int			Wait=128;											// 表示変更待ち時間 (msec)
	int			Ex[]=new int[128], Ey[]=new int[128];				// エミッタ電子位置座標
	int			Cx[]=new int[80], Cy[]=new int[80];					// コレクタ電子位置座標
	int			Bx[]=new int[80], By[]=new int[80];					// ベース正孔位置座標
	int			Qe0, Qb0, Qc0;										// 電子・正孔初期数
	int			Qem, Qbm;											// 電子・正孔増加目標数
	int			Qtye, Qtyc, Qtyb;									// 電子・正孔数
	boolean		Run=true;
	boolean		Er[]=new boolean[128], Cr[]=new boolean[80], Br[]=new boolean[80];
	boolean		Ec[]=new boolean[128];
	Image		Gif;
	Image		buf=null;
	Thread		th=null;
	int			R,G,B;
	Random		Rnd=new Random();
	int			Rt=8;
	
	public void init()
	{
		R=Integer.parseInt(getParameter("bg_red"));
		G=Integer.parseInt(getParameter("bg_green"));
		B=Integer.parseInt(getParameter("bg_blue"));
		setBackground(new Color(R,G,B));
		
		MediaTracker mt=new MediaTracker(this);
		Gif=getImage(getCodeBase(),"npn_tr.gif");
		mt.addImage(Gif, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
		buf=createImage(size().width,size().height);
		Qem=Qtye=Qe0=16; Qbm=Qtyb=Qb0=6; Qtyc=Qc0=16;				// 電子・正孔初期数
		carrier_initialize();
	}
	
	public void start()
	{
		if(th==null)
		{
			th=new Thread(this);
			th.start();
		}
	}
	
	public boolean inside(int x, int a, int b)
	{
		return (x<=Math.max(a,b) && x>=Math.min(a,b)) ? true:false;
	}
	
	public void carrier_initialize()								// 電子・正孔の初期配置
	{
		int i,j,k,m,x,y;
		
		for(i=0;i0)
		{
			Qem=Qe0*((Sw==1)?3:2)*(Ib+1)/2;
			Qbm=Qb0*2*(Ib+1)/2;
		}
		else
		{
			Qtyc=Qc0; Qtye=Qem=Qe0; Qtyb=Qbm=Qb0;
		}
	}
	
	public int move_x()												// 電子・正孔の進行
	{
		int x=Math.abs(Rnd.nextInt())%100;
		if(x<8) return 0;
		else if(x<16) return 1;
		else if(x<32) return 2;
		else if(x<64) return 3;
		else return 4;
	}
	
	public int move_y()												// 電子・正孔の揺動
	{
		int x=Math.abs(Rnd.nextInt())%100;
		if(x<10) return 2;
		else if(x<20) return 1;
		else if(x<30) return -1;
		else if(x<40) return -2;
		else return 0;
	}
	
	public int new_electron(int y, int n, int dis)					// 電子の供給
	{
		int i,j=0,x=105;
		
		for(i=0;i190)?202:194))
			{
				Ex[i]=x; Ey[i]=y;
				break;
			}
		}
		if(k0)
		{
			if(inside(Ex[k],190,213)) Ey[k]+=Math.abs(move_y());
			else if(inside(Ex[k],52,351)) Ex[k]+=Math.abs(move_y());
		}
		if(inside(Ex[i],213,343) && Ey[i]>194) Ey[i]--;
	}

	public void carrier_ec()
	{
		int i,j,k,x,y;
		
		for(i=0;i194) By[i]--;
			}
		}
	}
	
	public void carrier_eb()
	{
		int i,j,k=0,m=0,x=0,y=0;
		
		if(Qtye>Qem) Qtye=Qem;
		else
		{
			for(i=0,j=0; i0)? m:y;	Ex[i]=52; 
					Er[i]=false; Qtye++;
				}
			}
		}
		
		if(Qtyb>Qbm) Qtyb=Qbm;
		else
		{
			for(i=0,j=0; i0)? m:x;	By[i]=203;
					Br[i]=false; Qtyb++;
				}
			}
		}
		
		for(i=0;i0)
				{
					Bx[Qtyb]=m; By[Qtyb]=203; Br[Qtyb]=false;
					Br[i]=false; Qtyb++;
				}
			}
			if(k0)
			{
				if(By[k]>120) By[k]-=Math.abs(move_y())*3;
				else		  By[k]+=Math.abs(move_y())*3;
			}
			if(inside(Bx[i],60,185) && By[i]>194) By[i]--;

			if(Bx[i]<=55)											// エミッタ電極に到達
			{
				x=Math.abs(Rnd.nextInt())%23+190;
				m=new_hole(i);
				Bx[i]=(m>0)? m:x;
				By[i]=203;
			}
		}
		
		for(i=0;i182 && Er[i])									// ベース領域に入る
			{
				m=new_electron(Ey[i],i,170);
				Ey[Qtye]=(m>0)? m:Ey[i];
				Ex[Qtye]=52; Er[Qtye]=false; 
				Er[i]=false; Qtye++;
			}
			if(Ey[i]>=201)											// ベース電極に到達
			{
				y=Math.abs(Rnd.nextInt())%90+103;
				m=new_electron(y,i,170);
				Ey[i]=(m>0)? m:y;
				Ex[i]=52; 
			}
			if(Ex[i]>214 && Ec[i])									// コレクタ領域に入る
			{
				x=0; m=0;
				for(j=0;jx && Cr[j]) {x=Cx[j]; m=j;}
				}
				if(x>0)												// エミッタの電子として扱う
				{
					Cr[m]=false; Ec[i]=false;
					Ex[Qtye]=Cx[m]; Ey[Qtye]=Cy[m]; Er[Qtye]=false; Ec[Qtye]=false;
					Qtye++;
				}
			}
			if(Ex[i]>=351)											// コレクタ電極に到達
			{
				y=Math.abs(Rnd.nextInt())%90+103;
				m=new_electron(y,i,170);
				Ey[i]=(m>0)? m:y;
				Ex[i]=52;
			}
	//		showStatus("Qtye="+Qtye+",  Qtyb="+Qtyb+",  Qem="+Qem+",  Qbm="+Qbm);	// --------
		}
	}
	
	public void dsp_m(int n, int f, int d, Graphics g)				// 回路記号等の表示
	{																// d=0:シンボル横配列  1:縦
		int			x=0,y=0, w=0,h=0, ox=0,oy=0;
		Graphics	gx=g.create();
		switch(n)
		{
			case  0: x=418; y= 56; w=69; h=69; ox=  0; oy=307; break;	// 大電球
			case  1: x=218; y=222; w=46; h=46; ox=276; oy=307; break;	// 小電球
			case  2: x=298; y=  4; w=55; h=32; ox=460; oy=307; break;	// スイッチ
			case  3: x=149; y=277; w= 9; h=17; ox=276; oy=353; break;	// ベース電流値
			case  4: x=118; y=274; w=26; h=23; ox=515; oy=215; break;	// ベース電流減少ボタン
			case  5: x=163; y=274; w=26; h=23; ox=515; oy=146; break;	// ベース電流増加ボタン
			case  6: x=457; y=274; w=26; h=23; ox=515; oy=284; break;	// 一時停止ボタン
			case  7: x=457; y=274; w=26; h=23; ox=515; oy=330; break;	// 再開ボタン
			case  8: x=362; y=161; w=31; h=31; ox=510; oy= 22; break;	// +マーク
			case  9: x= 18; y=161; w=31; h=31; ox=510; oy= 84; break;	// −マーク
			case 10: x=423; y=274; w=26; h=23; ox=348; oy=353; break;	// 停止ボタン
			case 11: x=181; y=214; w=15; h=15; ox=400; oy=353; break;	// +マーク (小)
		}
		gx.clipRect(x,y,w,h);
		gx.drawImage(Gif,x-(ox+f*w*((d==0)?1:0)),y-(oy+f*h*d),this);
		gx.dispose();
	}
	
	public void paint(Graphics g)
	{
		int i;
		
		g.setColor(new Color(R,G,B));
		g.fillRect(0,0,size().width,size().height);
		g.drawImage(Gif,0,0,this);
		dsp_m(0,Ib*Sw,0,g);											// 大電球を描く
		dsp_m(1,Ib,0,g);											// 小電球
		dsp_m(2,Sw,1,g);											// スイッチ
		dsp_m(3,Ib,0,g);											// ベース電流値
		dsp_m(4,(Ib==0)?2:0,1,g);									// ベース電流減少ボタン
		dsp_m(5,(Ib==3)?2:0,1,g);									// ベース電流増加ボタン
		dsp_m((Run)?6:7,0,1,g);										// 一時停止・再開ボタン
		dsp_m(8,Sw,1,g);											// +マーク
		dsp_m(9,Sw,1,g);											// −マーク
		dsp_m(10,0,0,g);											// 停止ボタン
		dsp_m(11,Ib,0,g);											// +マーク (小)
		g.clipRect(60,103,291,99);
		g.setColor(new Color(51,102,255));							// 電子を描く
		for(i=0;i0) g.fillOval(Ex[i],Ey[i],8,8);
		for(i=0;i0)	carrier_eb();
			}
			Graphics offg=buf.getGraphics();
			paint(offg);
			Graphics ong=getGraphics();
			ong.drawImage(buf,0,0,this);
			try
			{
				th.sleep((Run)?Wait:500);
			}
			catch (InterruptedException e){};
		}
	}
	
	public boolean mouseDown(Event e, int x, int y)
	{
		int i,j,k;
		Graphics gb=getGraphics();
		
		if(inside(x,163,189) && inside(y,274,297) && Ib<3)			// ベース電流増加ボタン
		{
			dsp_m(5,1,1,gb);
			Ib++;
			carrier_qty_set();
		}
		if(inside(x,118,144) && inside(y,274,297) && Ib>0)			// ベース電流減少ボタン
		{
			dsp_m(4,1,1,gb);
			Ib--;
			if(Ib==0)
			{
				j=0; k=0;
				for(i=0;i188)
					{
						Cx[j]=Ex[i]; Cy[j]=Ey[i]; Cr[j]=true; Er[i]=false; j++;
					}
					else
					{
						Ex[k]=Ex[i]; Ey[k]=Ey[i]; Er[k]=true; Ec[k]=true; k++;
					}
				}
			}
			carrier_qty_set();
		}
		if(inside(x,298,353) && inside(y,4,36))						// スイッチ
		{
			Sw=1-Sw;
			if(Sw==0 && Ib==0) carrier_initialize();
			else carrier_qty_set();
		}
		if(inside(x,457,483) && inside(y,274,297))					// 停止・再開ボタン
		{
			dsp_m((Run)?6:7,1,1,gb);
			Run=!Run;
		}
		if(inside(x,423,449) && inside(y,274,297))					// 停止ボタン
		{
			Sw=0; Ib=0; Run=true;
			carrier_initialize();
			dsp_m(10,1,0,gb);
		}
		return true;
	}

	public void stop()
	{
		if(th!=null)
		{
			th.stop();
			th=null;
		}
	}
}
//
戻る