/*
 * -------------------------------------------------------------------------
 *      $Id: PredatorPrey.java,v 1.5 2004/05/26 18:26:28 estewart Exp $
 * -------------------------------------------------------------------------
 *      Copyright (c) 1999 Visual Numerics Inc. All Rights Reserved.
 *
 *      This software is confidential information which is proprietary to
 *      and a trade secret of Visual Numerics, Inc.  Use, duplication or
 *      disclosure is subject to the terms of an appropriate license
 *      agreement.
 *
 *      VISUAL NUMERICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 *      SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 *      BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 *      FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. VISUAL
 *      NUMERICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 *      AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
 *      ITS DERIVATIVES.
 *--------------------------------------------------------------------------
 */

package com.imsl.demo.PredatorPrey;
import com.imsl.chart.*;
import com.imsl.math.OdeRungeKutta;
import com.imsl.IMSLException;
import com.imsl.demo.gallery.Describe;
import java.awt.*;
import java.awt.event.*;


/**
 *
 * @author  brophy
 * @created April 24, 2001
 */
public class PredatorPrey extends JFrameChart implements MouseListener, MouseMotionListener {
    private AxisXY      axis;
    static private final int npoints = 100;
    private double      rabbits[], foxes[];
    private double      point[] = {1,3};
    private double      initialRabbit[] = {1};
    private double      initialFox[] = {3};
    private Data        dataSolved;
    private Data        dataError;
    private int            numberSolved;

    private void solve() throws IMSLException {
        OdeRungeKutta.Function f = new OdeRungeKutta.Function() {
            public void f(double t, double y[], double yprime[]) {
                yprime[0] = 2.0*y[0] - 2.0*y[0]*y[1];
                yprime[1] = -y[1] + y[1]*y[0];
            }
        };

        OdeRungeKutta q = new OdeRungeKutta(f);

        double dt = 10.0/(npoints-1);
        for (int k = 0;  k < npoints;  k++) {
            q.solve(k*dt, (k+1)*dt, point);
            rabbits[k] = point[0];
            foxes[k] = point[1];
        }
        numberSolved++;
    }

    public PredatorPrey(boolean exitOnClose) {
        if (!exitOnClose) {
            // remove the WindowListener,  installed by JFrameChart, that
            // exits the application when the window is closed.
            Object l[] = getListeners(java.awt.event.WindowListener.class);
            for (int k = 0;  k < l.length;  k++) {
                removeWindowListener((java.awt.event.WindowListener)l[k]);
            }
        }

        Describe des = new Describe(this, "/com/imsl/demo/PredatorPrey/PredatorPrey.html");
        des.show();
        Dimension ds = des.getSize();

        Dimension ss = getToolkit().getScreenSize();
        int w = Math.min(ss.width/2, ss.height-ds.height-32);
        setSize(w, w);
        setLocation(ss.width-ds.width, ds.height);
        setTitle("Predator Prey");

        rabbits = new double[npoints];
        foxes = new double[npoints];
        try {
            solve();
        } catch (Exception exception) {
            System.out.println(exception);
            return;
        }

        Chart chart = getChart();
        chart.getChartTitle().setTitle(new Text("Predator Prey Problem"));
        axis = new AxisXY(chart);
        axis.setAutoscaleInput(AxisXY.AUTOSCALE_OFF);
        axis.getAxisX().setWindow(0.0, 5.0);
        axis.getAxisY().setWindow(0.0, 5.0);
        axis.getAxisX().getAxisTitle().setTitle("Population Density, Rabbits");
        axis.getAxisY().getAxisTitle().setTitle("Population Density, Foxes");

        Data data = new Data(axis, rabbits, foxes);
        data.setDataType(Data.DATA_TYPE_LINE|Data.DATA_TYPE_MARKER);
        data.setMarkerType(Data.MARKER_TYPE_FILLED_SQUARE);
        data.setMarkerSize(0.75);
        data.setMarkerColor(Color.blue);
        data.setLineColor(Color.blue);

        data = new Data(axis, initialRabbit, initialFox);
        data.setDataType(Data.DATA_TYPE_MARKER);
        data.setMarkerType(Data.MARKER_TYPE_FILLED_CIRCLE);
        data.setMarkerSize(1.5);
        data.setMarkerColor(Color.red);

        double px[] = {2.5};
        double py[] = {4.7};
        dataSolved = new Data(axis, px, py);
        dataSolved.setLabelType(Data.LABEL_TYPE_TITLE);
        dataSolved.setTitle("Solved 1 ODE");
        dataSolved.setTextColor("darkgreen");

        double ex[] = {2.5};
        double ey[] = {4.0};
        dataError = new Data(axis, ex, ey);
        dataError.setLabelType(Data.LABEL_TYPE_TITLE);
        //dataError.setTitle("solved 1 ODE");
        dataError.setTextColor(Color.red);

        getPanel().addMouseListener(this);
        getPanel().addMouseMotionListener(this);
    }

    public void mouseMoved(MouseEvent event) {
    }

    public void mouseDragged(MouseEvent event) {
        updateInitialPoint(event);
    }

    public void mouseClicked(MouseEvent event) {
        updateInitialPoint(event);
    }

    private void updateInitialPoint(MouseEvent event) {
        axis.mapDeviceToUser(event.getX(), event.getY(), point);
        initialRabbit[0] = point[0];
        initialFox[0] = point[1];
        try {
            solve();
            dataSolved.setTitle("Solved "+numberSolved+" ODEs");
            dataError.setTitle("");
        } catch (IMSLException exception) {
            StringBuffer sb = new StringBuffer(exception.toString());
            int nCharsPerLine = 30;
            for (int k = nCharsPerLine;  k < sb.length();  k += nCharsPerLine) {
                for (int j = 0;  j < nCharsPerLine;  j++) {
                    if (sb.charAt(k-j) == ' ') {
                        sb.setCharAt(k-j, '\n');
                        k -= j;
                        break;
                    }
                }
            }
            dataError.setTitle(sb.toString());
        }
        repaint();
    }

    public void mousePressed(MouseEvent event) {
    }

    public void mouseReleased(MouseEvent event) {
    }

    public void mouseEntered(MouseEvent event) {
    }

    public void mouseExited(MouseEvent event) {
    }


    public static void main(String args[]) {
        boolean exitOnClose = true;
        if (args.length > 0  && args[0].equals("-noexit"))  exitOnClose = false;
        new PredatorPrey(exitOnClose).show();
    }
}