//
/* ----------------------------------------------------------------------------------------------
    decipher.java	暗号解読									ver. 2.00 (JDK 1.02)
    															ueyama@infonet.co.jp  2002.12.25
    															update: 2007.08.19
---------------------------------------------------------------------------------------------- */
import java.applet.*;
import java.awt.*;
import java.util.*;


public class decipher extends Applet implements Runnable
{
	String		Text[][]={{" the instructions which govern this operation must be",	// Neumann
					"given to the device in absolutely exhaustive detail.",
					" they include all numerical information which is",
					"required to solve the problem under consideration:",
					"initial and boundary values of the dependent variables,",
					"values of fixed parameters, tables of fixed functions",
					"which occur in the statement of the problem."},
				   {" in the control and protective circuits of complex",			// Shannon
					"electrical systems it is frequently necessary to make",
					"intricate interconnections of relay contacts and",
					"switches. examples of these circuits occur in automatic",
					"telephone exchanges, industrial motor control equipment",
					"and in almost any circuits designed to perform complex",
					"operations automatically.                     "}};
	int			Frqn[]= {64,12,24,32,100,18,16,44,58,1,5,33,20,57,61,16,1,49,52,74,22,8,16,2,14,1};	// 文字使用頻度
	int			Frqc[]= new int[31];									// 暗号文中の文字使用数
	int			Keyx[]= { 5,107,61,51,46,74,97,120,161,143,166,189,153,130,184,207,0,69,28,92,138,84,23,39,115,15};
	int			Keyy[]= {23, 46,46,23, 0,23,23, 23,  0, 23, 23, 23, 46, 46,  0,  0,0, 0,23, 0,  0,46, 0,46,  0,46};
	int			T=0, K=1;												// 暗号文、暗号鍵
	int			Qtyc;													// 暗号文の文字数
	int			Gx=28, Gy=514, Kx=559, Ky=458;							// グラフ目盛、キーボードの表示座標
	int			Lp=52;													// 暗号文表示 行ピッチ
	int			Sn;														// 解読文字 No.
	String		Key[] ={"abcdefghijklmnopqrstuvwxyz.,:? ",				// 文字データ
						"hulqcjaksoepiwgtmvydrzxfnb.,:? ", 				// 暗号鍵 11
						"lqrzvhgwejyausxpitmofkncdb.,:? ",				// 暗号鍵 12
						"createdrandomsecretkeyhere.,:? ",				// 暗号鍵 1R
						"ewfobrqhcdxjknlpitmyausgzv.,:? ",				// 暗号鍵 21
						"tmyglpehauzvjknscwfobrqdxi.,:? ",				// 暗号鍵 22
						"createdrandomsecretkeyhere.,:? "};				// 暗号鍵 2R
	int			Keyi[]= new int[31];									// 解読データ
	boolean		Sf=false;												// true: 解読の途中
	Image		Img;
	Thread		th=null;
	Graphics	gx;
	int			T0=0, T1=0;
	
	public void init()
	{
		String bg=getParameter("bgcolor");								// 背景色の読み込み
		int bgc=Integer.valueOf(bg,16).intValue();
		setBackground(new Color(bgc)); 
		MediaTracker mt=new MediaTracker(this);
		Img=getImage(getCodeBase(), getParameter("figure"));			// gif ファイルの読み込み
		mt.addImage(Img, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
		for(int i=0; i<31; i++) Keyi[i]=-1;
		cip_cnt();														// 暗号文 文字数カウント
		new_key(3); new_key(6);											// 暗号鍵の生成
		gx=getGraphics();
	}
	
	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 dsp_g(int x, int y, int m, int n, int c)
	{
		int w=0, h=0, ox=0, oy=0;
		switch(c)
		{
			case	0:	w= 14; h=18; ox=  0; oy= 0;	break;				// 文字 (暗号文 平文 グラフ キートップ)
			case	1:	w= 18; h= 7; ox=  0; oy=72;	break;				// グラフ目盛 "XX%"
			case	2:	w= 20; h=20; ox=364; oy=54;	break;				// キートップ
			case	3:	w= 90; h= 9; ox=  0; oy=90;	break;				// 凡例
			case	4:	w= 31; h=19; ox=404; oy=54;	break;				// CLR キー
			case	5:	w= 83; h=11; ox=  0; oy=79;	break;				// "文字の使用頻度"
			case	6:	w=227; h=14; ox=  0; oy=99;	break;				// 暗号文・暗号鍵の変更
			case	7:	w=  6; h=10; ox=227; oy=99;	break;				// ラジオボタン 黒丸
		}
		Graphics gr=getGraphics();
		gr.clipRect(x,y,w,h);
		if(!(c==0 && n==3)) gr.clearRect(x,y,w,h);
		gr.drawImage(Img,x-(ox+m*w),y-(oy+n*h),this);
		gr.dispose();
	}
	
	public void cip_cnt()												// 暗号文 文字数カウント
	{
		int i,j,n;
		Qtyc=0;
		for(i=0; i<31; i++) Frqc[i]=0;
		for(j=0;j<7;j++)
		{
			for(i=0;i=0)?Keyi[n]:30, 1, 0);	// 解読済み文字の表示
			}
		}
		for(i=0; i<8; i++)												// グラフ目盛線の表示
		{
			if(i==0) gx.setColor(new Color(102,102,102));
			else	 gx.setColor(new Color(204,204,204));
			gx.drawLine(Gx-6, Gy-16*i, Gx+520, Gy-16*i);
			dsp_g(0, Gy-16*i-3, i, 0, 1);								// % の表示
		}
		for(i=0; i<26;i++)
		{
			m=de_ciph(i);
			dsp_grf(m*20+Gx, Frqc[m]*800/Qtyc, (Keyi[m]>=0)?0:1);		// 暗号文文字使用頻度グラフの表示
			n=Key[K].indexOf(Key[0].charAt(i));
			dsp_grf(i*20+Gx+7, Frqn[i], (deciph(i))?2:3);				// 英文の文字使用頻度グラフの表示
			dsp_g(n*20+Gx, Gy+8, n, 0 ,0);								// グラフの文字の表示
			dsp_g(i*20+Gx, Gy+28, (Keyi[i]>=0)?Keyi[i]:30, 1, 0);		// 解読済み文字の表示
			dsp_g(Kx+Keyx[i], Ky+Keyy[i], (deciph(i))?0:1, 0, 2);		// キートップの表示
			dsp_g(Kx+Keyx[i]+3, Ky+Keyy[i]+1, i, 3, 0);					// キーの文字の表示
		}
		dsp_g(350, 388, 1, 0, 3);										// 凡例 "一般英文文字頻度"
		dsp_g(454, 388, 0, 0, 3);										// 凡例 "暗号文の文字頻度"
	}

	public int de_ciph(int s)											// 一文字解読
	{
		int i;
		for(i=0; i<31; i++) if(Key[0].indexOf(Key[K].charAt(i))==s) break;
		return i;
	}

	public boolean deciph(int s)										// 解読済みか?
	{
		int i;
		for(i=0; i<31; i++) if(Keyi[i]==s) break;
		return (i<31)?true:false;
	}

	public void new_key(int k)											// 暗号鍵(ランダム)の生成
	{
		int i,j,d,n=0, ex[]=new int[26];
		Random rnd=new Random();
		for(i=0; i<26; i++) ex[i]=Math.abs(rnd.nextInt());
		for(i=0; i<26; i++)
		{
			d=0;
			for(j=0; j<26; j++) {if(ex[j]>d) {d=ex[j]; n=j;}}
			ex[n]=0; Key[k]=Key[k].substring(0,n)+Key[0].substring(i,i+1)+Key[k].substring(n+1);
		}
	}
	
	public void paint(Graphics g)
	{
		g.clearRect(0,0,size().width,size().height);
		dsp_grph();														// 暗号・解読文の表示
		dsp_g(  2, 382, 0, 0, 5);										// "文字の使用頻度"
		dsp_g(Kx+184, Ky+47, 0, 0, 4);									// CLR ボタン
		dsp_g(Kx, Ky+86, 0, 0, 6);										// 暗号文・鍵 変更部
		dsp_g(Kx+T*32+53, Ky+86, 0, 0, 7);								// 暗号文 ラジオボタン
		dsp_g(Kx+(K-1)%3*32+153, Ky+86, 0, 0, 7);						// 暗号鍵 ラジオボタン
	}
	
	public void run()
	{
		int i,j,n;
		while(th!=null)
		{
			try
			{
				th.sleep(128);
			}
			catch (InterruptedException e){};
			T0++;
			if(Sf && T0%5==0 && Sn<26)
			{
				T1++;
				if(Sf) dsp_g(Sn*20+Gx,Gy+8,Sn,(T1%2==0)?0:1,0);			// グラフの文字をウインク
				for(j=0;j<7;j++)
				{
					for(i=0;i400 && inside(mx,Gx,Gx+520))								// 解読文字指定  グラフ領域をクリック
		{
			Sn=(mx-Gx)/20;
			dsp_grf(Sn*20+Gx, Frqc[Sn]*800/Qtyc, 0);					// 暗号文文字使用頻度グラフの表示
			Sf=true;													// 解読中
		}
		else if(my<400 && my%Lp<18)										// 解読文字指定  暗号文をクリック
		{
			n=Key[0].indexOf(Text[T][my/Lp].charAt(mx/14));
			Sn=de_ciph(n);
			dsp_grf(Sn*20+Gx, Frqc[Sn]*800/Qtyc, 0);					// 暗号文文字使用頻度グラフの表示
			Sf=true;													// 解読中
		}
		if(inside(x, 36, 102) && y>85)									// 暗号文の変更
		{
			dsp_g(Kx+T*32+53, Ky+86, 1, 0, 7);							// 暗号文 ラジオボタン
			T=(x-36)/32;												// 新暗号文
			dsp_g(Kx+T*32+53, Ky+86, 0, 0, 7);							// 暗号文 ラジオボタン
			K=(K-1)%3+T*3+1;											// 新暗号鍵
			for(i=0; i<31; i++) Keyi[i]=-1;								// 解読データのクリア
			gx.clearRect(0,0,size().width,360);
			cip_cnt();													// 新暗号文の文字数カウント
			dsp_grph();													// 新暗号文の表示
		}
		if(inside(x, 137, 227) && y>85)									// 暗号鍵の変更
		{
			dsp_g(Kx+(K-1)%3*32+153, Ky+86, 1, 0, 7);					// 暗号鍵 ラジオボタン
			K=(x-137)/30+T*3+1;											// 新暗号鍵
			dsp_g(Kx+(K-1)%3*32+153, Ky+86, 0, 0, 7);					// 暗号鍵 ラジオボタン
			if(K==3 || K==6) new_key(K);								// 暗号鍵(ランダム)の生成
			cip_cnt();													// 新暗号文の文字数カウント
			dsp_grph();													// 新暗号文の表示
		}
		if(inside(x, 184, 215) && inside(y, 46, 66))					// クリアボタン
		{
			for(i=0; i<31; i++) Keyi[i]=-1;								// 解読データのクリア
			dsp_grph();													// 暗号・解読文の表示
		}
		return true;
	}
	
	public void stop()
	{
		if(th!=null)
		{
			th.stop();
			th=null;
		}
	}
}
//
戻る