//
/* ----------------------------------------------------------------------------------------------
    tokenring.java		トークンリング						ver. 1.00 (JDK 1.02)
    														ueyama@infonet.co.jp  1999.08.17
---------------------------------------------------------------------------------------------- */

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


public class tokenring extends Applet implements Runnable
{
	int			Rr=150;												// ケーブル半径
	double		Ta=90.0;											// トークン位置(角度)
	int			Tx,Ty;												// トークン等位置(座標)
	int			Cx[]={225,15,26,213};								// コンピュータ位置
	int			Cy[]={15,15,213,213};								// コンピュータ位置
	int			Ct=-1;												// 送信コンピュータ
	int			Cr=-1;												// 受信コンピュータ
	int			Data[]=new int[300*300];
	int			Bg[][]=new int[11][11];
	boolean		Dsp[]=new boolean[13];
	boolean		Flg[]=new boolean[13];
	Thread		th=null;
	Graphics	gr;
	Image		Gif;
	Image		img;
	boolean		Run=false;
	boolean		Busy=false;
	boolean		Read=false;
	boolean		End=false;
	int			R,G,B;
	int			Wait=64;
	
	public void start()
	{
		if(th==null)
		{
			th=new Thread(this);
			th.start();
		}
	}
	
	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));
		gr=getGraphics();
		
		MediaTracker mt=new MediaTracker(this);
		Gif=getImage(getCodeBase(),"tokenrng.gif");
		mt.addImage(Gif, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
		img=createImage(300,300);
		t_pos(Ta,0,0,gr,0);
		Dsp[0]=true;
	}
	
	public boolean inside(int x, int a, int b)
	{
		return (x<=Math.max(a,b) && x>=Math.min(a,b)) ? true:false;
	}
	
	public boolean get_pixeldata()
	{
		update(img.getGraphics());
		PixelGrabber pg=new PixelGrabber(img,0,0,300,300,Data,0,300);
		try
		{
			pg.grabPixels();										// 画像データの取得
		}
		catch (InterruptedException ie) {return false;}
		if((pg.status() & ImageObserver.ABORT) !=0) {return false;}
		return true;
	}
	
	public void t_pos(double a, int n, int c, Graphics g, int m)	// トークン・データの表示
	{
		int x,y;
		Tx=(Rr*2+(int)(Math.cos(a*3.14159/180.0)*(Rr*2-11))-11)/2;
		Ty=(Rr*2-(int)(Math.sin(a*3.14159/180.0)*(Rr*2-11))-11)/2;
		for(x=0;x<11;x++) for(y=0;y<11;y++) Bg[x][y]=Data[(Ty+y)*300+Tx+x];
		get_p(Tx,Ty,m);
		if(Dsp[m]) dsp_g(Tx,Ty,n,c,g);
	}
	
	public int get_p(int x, int y, int m)
	{
		int n=-1;
		if(inside(y,22,44))
		{
			if(x<67) n=0;											// in to A
			if(x>223) n=7;											// out from D
		}
		if(inside(y,225,240))
		{
			if(x>24) n=1;											// in to B
			if(inside(x,254,265)) n=6;								// out from C
		}
		if(inside(x,15,33) && inside(y,65,75)) n=4;					// out from A
		if(inside(x,63,87) && y>262) n=5;							// out from B
		if(inside(x,210,237) && inside(y,273,262)) n=2;				// in to C
		if(inside(x,260,281) && y<75) n=3;							// in to D
		if(inside(y,30,64) || inside(y,239,262)) Dsp[m]=false;
		else Dsp[m]=true;
		return n;
	}
	
	public void dsp_g(int x, int y, int n, int c, Graphics g)		// 画像の表示
	{
		int			w=0, h=0, ox=0, oy=0, wc=0, hc=0;
		Graphics	gx=g.create();
		switch(n)
		{
			case  0: w= 11; h= 11; ox= 61; oy= 0; break;			// トークン
			case  1: w= 11; h= 11; ox= 72; oy= 0; break;			// 宛先 ヘッダ
			case  2: w= 11; h= 11; ox=116; oy= 0; break;			// 送り主 ヘッダ
			case  3: w= 11; h= 11; ox=160; oy= 0; break;			// 着信確認データ
			case  4: w= 11; h= 11; ox=204; oy= 0; break;			// データ
			case  5: w= 61; h= 60; ox=  0; oy= 0; break;			// コンピュータ
			case  6: w= 17; h= 21; ox= 61; oy=11; break;			// コンピュータ名
			case  7: w= 26; h= 23; ox= 61; oy=32; break;			// "<<" ボタン
			case  8: w= 26; h= 23; ox=113; oy=32; break;			// ">>" ボタン
			case  9: w= 26; h= 23; ox=191; oy=32; break;			// "||" ボタン
			case 10: w= 26; h= 23; ox=243; oy=32; break;			// "|>" ボタン
		}
		wc=w; hc=h;
		if(n<5)
		{
			switch(get_p(x, y, 11))
			{
				case 0: wc=x- 57; ox+=(11-wc); x= 68; break;
				case 1: wc=35- x; break;
				case 2: hc=y-262; oy+=(11-hc); y=274; break;
				case 3: hc=y- 64; oy+=(11-hc); y= 76; break;
				case 4: hc=y- 64; oy+=(11-hc); y= 76; break;
				case 5: hc=y-262; oy+=(11-hc); y=274; break;
				case 6: wc=x-254; ox+=(11-wc); x=265; break;
				case 7: wc=234-x; break;
			}
		}
		gx.clipRect(x,y,wc,hc);
		gx.drawImage(Gif,x-(ox+w*c),y-oy,this);
		gx.dispose();
	}
	
	public void dsp_c(int n, int c, Graphics g)						// コンピュータ名の表示
	{
		Graphics	gx=g.create();
		gx.clipRect(Cx[n]+22,Cy[n]+9,17,21);
		gx.drawImage(Gif,Cx[n]+22-(61+68*c+17*n),Cy[n]+9-11,this);
		gx.dispose();
	}
	
	public void dsp_r(int c, Graphics g)							// ネットワークケーブルの表示
	{
		int i,r;
		if(c==0)	g.setColor(new Color(102,102,102));
		else		g.setColor(new Color(128,102,102));
		g.fillOval(0,0,Rr*2-1,Rr*2-1);
		g.setColor(new Color(R,G,B));
		g.fillOval(11,11,Rr*2-22,Rr*2-22);
	}
	
	public void paint(Graphics g)
	{
		int i,j;
		dsp_r(0,g);													// ネットワークケーブルの表示
		for(i=0;i<4;i++)											// コンピュータの表示
		{
			j=0;
			if(Ct==i) j=1;
			if(Cr==i) j=2;
			dsp_g(Cx[i],Cy[i],5,0,g);
			dsp_c(i, j, g);
		}
		dsp_g(105,317,7,0,g);										// "<<" ボタンの表示
		dsp_g(169,317,8,0,g);										// ">>" ボタンの表示
		dsp_g(137,317,(Run)?9:10,0,g);								// "|>" or "||" ボタンの表示
	}
	
	public void t_els()												// トークン(データ)の後半を消去
	{
		int	r,g,b,x,y;
		double	a;
		
		a=(double)(Rr-(Ty+5))/(double)(Tx+5-Rr);
		for(x=0;x<11;x++)
		{
			for(y=0;y<11;y++)
			{
				if((Tx+5Rr && (double)(Ty+y)>(double)Rr-a*(double)(Tx+x-Rr)) || a<-200.0)
				{
					r=Bg[x][y] & 0x00ff0000; r/=0x10000;
					g=Bg[x][y] & 0x0000ff00; g/=0x100;
					b=Bg[x][y] & 0x000000ff;
					gr.setColor(new Color(r,g,b));
					gr.drawRect(Tx+x,Ty+y,1,1);
				}
			}
		}
	}
	
	public void dsp_data(boolean f, double a)						// ヘッダ・データ・フッタの表示
	{
		int i;
		boolean fd=true;
		if(f) fd=(Ta-4.5Ct*90+45) Flg[1]=true;
		if(Flg[1] && fd) t_pos(Ta-4.5,1,Cr,gr,1);					// 宛先の表示
		if(Flg[1] && (int)(Ta-4.5*2)%360>Ct*90+45) Flg[2]=true;
		if(Flg[2])
		{
			if(f) fd=(Ta-4.5*2Ct*90+45) Flg[i]=true;
				if(Flg[i] && fd) t_pos(Ta-i*4.5, 3,(i-3)%4,gr,i);	// データの表示
			}
		}
		if(Read && Flg[10])
		{
			i=(int)(Ta-4.5*11)%360;
			if((Cr>0  && i>Cr*90+45) || (Cr==0 && inside(i,40,50))) Flg[11]=true;
			if(Flg[11]) t_pos(Ta-11*4.5, 4,Cr,gr,11);				// 着信確認の表示
		}
	}
	
	public void run()
	{
		int	i,j=0,n,x=0;
		double	a=0.0;
		
		while(th!=null)
		{
			if(Run)
			{
				if((int)(Ta+45.0)%90==86 && Ct>=0 && Cr>=0)
				{
					n=(int)Ta%360; n/=90;
					if(Ct==n)
					{
						if(Busy && Read)							// 送信完了
						{
							a=Ta;
							while(Ta-4.5*11=0) Cr=1; else Ct=1;
			if(inside(mx,225,286))	if(Ct>=0) Cr=0; else Ct=0;
		}
		if(inside(my,213,273) && (Ct<0 || Cr<0))
		{
			if(inside(mx,26,87))	if(Ct>=0) Cr=2; else Ct=2;
			if(inside(mx,213,274))	if(Ct>=0) Cr=3; else Ct=3;
		}
		if(my>317)
		{
			if(inside(mx,105,131))
			{
				Wait*=2;
				dsp_g(105, 317, 7, 1, gr);							// "<<" ボタンの表示
				dsp_g(169, 317, 8, 0, gr);
			}
			if(inside(mx,137,163))
			{
				dsp_g(137,317,(Run)? 9:10,1,gr);					// "||" or "|>" ボタンの表示
				if(Ta==90.0) get_pixeldata();
				Run=!Run;
			}
			if(inside(mx,169,195) && Wait>16)
			{
				Wait/=2;
				dsp_g(169, 317, 8, 1, gr);							// ">>" ボタンの表示
			}
		}
		if(Ct>=0) dsp_c(Ct,1,gr);
		if(Cr>=0) dsp_c(Cr,2,gr);
		return true;
	}
	
	public boolean mouseUp(Event e, int mx, int my)
	{
		if(my>317)
		{
			if(inside(mx,105,131)) dsp_g(105, 317, 7, 0, gr);				// "<<" ボタン
			if(inside(mx,137,163)) dsp_g(137, 317, (Run)? 9:10, 0, gr);		// "||" or "|>" ボタン
			if(inside(mx,169,195)) dsp_g(169, 317, 8, (Wait>16)? 0:2, gr);	// ">>" ボタン
		}
		return true;
	}
	
	public void stop()
	{
		if(th!=null)
		{
			th.stop();
			th=null;
		}
	}
}
//
戻る