/*
  2003/08/04  小松 研吾
*/

import java.applet.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.*;

public class SecondDegreeDiffApplet extends Applet implements ActionListener {
    // 変数宣言
    public Vector datax = new Vector();
    public Vector datay = new Vector();
    boolean check = false;
    double h;
    Button bt1, bt2;

    public void init() {
        // 変数宣言
        double x;
        // 刻み幅
        h = 0.01;

        // 初期条件
        x = 0;
        double y[];
        y = new double[2];
        y[0] = 1;
        y[1] = 1;

        double k[][];
        k = new double[4][2];
        for(int i=0; i<4; i++) {
            for(int j=0; j<2; j++)
                k[i][j] = 0;
        }

        for(int i=0; i<1; ++i) {
            // Runge-Kutta法
            for(int j=0; j<10/h ; j++) {
                k[0][0] = h * f1(x,       y[0],             y[1]            );
                k[0][1] = h * f2(x,       y[0],             y[1]            );
                k[1][0] = h * f1(x+h/2.0, y[0]+k[0][0]/2.0, y[1]+k[0][1]/2.0);
                k[1][1] = h * f2(x+h/2.0, y[0]+k[0][0]/2.0, y[1]+k[0][1]/2.0);
                k[2][0] = h * f1(x+h/2.0, y[0]+k[1][0]/2.0, y[1]+k[1][1]/2.0);
                k[2][1] = h * f2(x+h/2.0, y[0]+k[1][0]/2.0, y[1]+k[1][1]/2.0);
                k[3][0] = h * f1(x+h,     y[0]+k[2][0],     y[1]+k[2][1]    );
                k[3][1] = h * f2(x+h,     y[0]+k[2][0],     y[1]+k[2][1]    );

                y[0] += (k[0][0] + 2*k[1][0] + 2*k[2][0] + k[3][0]) / 6.0;
                y[1] += (k[0][1] + 2*k[1][1] + 2*k[2][1] + k[3][1]) / 6.0;
                x += h;

                datay.addElement(Double.toString(y[0]));
                datax.addElement(Double.toString(x));
            }
        }

        // Layoutを無効にする。
        setLayout(null);

        // ボタンを配置
        bt1 = new Button("計算");
        add(bt1);
        bt1.setBounds(5, 5, 50, 20);
        bt1.addActionListener(this);

        bt2 = new Button("clear");
        add(bt2);
        bt2.setBounds(60, 5, 50, 20);
        bt2.addActionListener(this);

    }

    public void actionPerformed(ActionEvent ev) {
        // どのオブジェクトに関するイベントかを取得する。
        Object obj = ev.getSource();
        if(obj == bt1) {
            check = true;
            repaint();
        } else if(obj == bt2) {
            check = false;
            repaint();
        }
    }

    public void paint(Graphics g) {
        // 変数宣言
        Dimension d = getSize();
        Color color = Color.red;
        int width = d.width;
        int height = d.height;

        // 背景色
        setBackground(Color.white);
        g.setColor(Color.black);
        // 表示域の周囲に四角形を描画
        g.drawRect(0, 0, width-1, height-1);
        // x, y軸を描画
        g.drawLine(0, height-20, width-1, height-20);
        g.drawLine(20, 0, 20, height-1);
//          // x=10ごとに目盛りを描画
//          for(int i=0; i<=width/10 ; ++i)
//              g.drawLine(10*i, height-20-2, 10*i, height-20);

        if(check) {
            // データ値の曲線を描画する
            g.setColor(Color.blue);
            double oldpltx, oldplty, pltx, plty;
            int cnum = datax.size();
            for(int i=0; i<cnum; i++) {
                oldpltx = Double.parseDouble((String)datax.elementAt(i));
                oldplty = Double.parseDouble((String)datay.elementAt(i));
                pltx = Double.parseDouble((String)datax.elementAt(i+1));
                plty = Double.parseDouble((String)datay.elementAt(i+1));
                g.drawLine(convertx(oldpltx, h), converty(height, oldplty, h),
                           convertx(pltx, h), converty(height, plty, h));
            }
        }
    }

    // x座標をアプレット上の座標に変換
    private static int convertx(double x, double h) {
        int pltx;
        pltx = Math.round(Math.round(x/h)) + 20;
        return pltx;
    }

    // y座標をアプレット上の座標に変換
    private static int converty(int height, double y, double h) {
        int plty;
        plty = height - Math.round(Math.round(y/h));
        return plty;
    }

    // 式1
    private static double f1(double x, double y0, double y1) {
        double value = 0;
        value = y1;
        return value;
    }

    // 式2
    private static double f2(double x, double y0, double y1) {
        double value = 0;
        value = 6*y0 - y1;
        return value;
    }
}
