import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.text.*;
import java.util.*;
import java.io.*;
import java.net.*;

/**
 * Title:
 * Description:
 * Copyright:    Copyright (c) 2002
 * Company:
 * @author
 * @version 1.0
 */

public class Resistan extends Applet implements AdjustmentListener, ActionListener, ItemListener, WindowListener, FocusListener, MouseListener {

  Frame frame;
  Panel panel;
  Panel subpanel;
  Panel scrollpanel;
  Panel tempPanel;
  Graphics g;
  Scrollbar scroll;
  Label dateLabel;
  TextArea helpText;
  Dialog helpDialog;

  MenuBar menu;

  Menu file;
  MenuItem run;
  MenuItem continueItem;
  MenuItem inputConfiguration;
  MenuItem saveConfiguration;
  MenuItem exit;
  Menu loadPreset;
  MenuItem defaultPreset;

  Menu fungicides;
  MenuItem select;
  MenuItem schedules;
  MenuItem characteristics;

  Menu fungus;
  MenuItem resistance;
  MenuItem inoculum;
  MenuItem lifeCycle;

  Menu plant;
  MenuItem susceptibility;
  MenuItem damage;

  Menu season;
  MenuItem lengthOfSeason;
  MenuItem startingDate;

  Menu economics;
  MenuItem costsPrice;
  MenuItem showPieChart;

  Menu viewMenu;
  MenuItem refresh;
  MenuItem viewLesions;
  MenuItem viewPercentLoss;
  MenuItem viewResidues;
  MenuItem viewResistances;

  Menu log;
  MenuItem show;

  Menu help;
  MenuItem launchHelp;

  Label color1;
  Label color2;
  Label color3;
  Label color4;
  Label color5;
  Label color6;
  Label color7;
  Label color8;
  Label color9;
  Label color10;

  public String[] fcides = new String[]{
    "None", "Dithiocarbamate", "Dicarboximide", "Benzimidazole", "Sterol-inhibitor"
  };

  public static final Font stdFont = new Font("Courier", Font.PLAIN, 12);
  public static final int popSize = 16;
  public static final int numFungicides = 4;
  public static final int xOrigin = 50;
  public static final int xEnd = 650;
  public static final int yOrigin = 450;
  public static final int yEnd = 50;
  public static final int plottingGap = 200;
  public static final NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
  public static final double pctResCalcLevel = 0.0;
  public static final int nStart = 1;
  public static final int nStop = 4;
  public static final int nFirstMask = 8;
  public static final String sHyphens = "#-----------------------------------\n";

  public static final Font boldFont = new Font("boldFont", Font.BOLD, 18);
  public static final Color bgColor = new Color(222, 222, 190);

  public static final String[] fungicideKeys = new String[]{
    "name", "cost", "dose_deposit_factor", "weathering_rate", "ed50_spore_mortality",
    "dose_response_slope", "ed50_inhib_lesion_devel", "ed50_inhib_sporulation",
    "mutation_rate", "resistance_level", "spore_survival", "lesion_development", "sporulation"
  };
  public static final String[] dateDoseKeys = new String[]{
    "dates", "doses"
  };
  public static final String[] fungusKeys = new String[]{
    "fungicide_resistances", "initial_inoculum", "released_over_days", "blow_in"
  };
  public static final String[] lifeCycleKeys = new String[]{
    "infection_efficiency", "latent_period", "infectious_period", "sporulation_rate",
    "spore_deposition", "lesion_limit", "overwintering_factor", "spores",
    "latent_lesions", "sporulating_lesions"
  };
  public static final String[] plantKeys = new String[]{
    "damage_constant", "maximum_crop_loss",
    "susceptibility_values"
  };
  public static final String[] seasonKeys = new String[]{
    "length_of_season", "first_day_of_season"
  };
  public static final String[] economicKeys = new String[]{
    "application_cost", "fixed_costs", "maximum_revenue"
  };

  int xPos = xOrigin;
  int yPos = yOrigin;
  int count = 0;
  int seasonNumber = 1;

  DecimalFormat df1 = new DecimalFormat("##0.0##");
  DecimalFormat df2 = new DecimalFormat("0.0####");
  DecimalFormat df3 = new DecimalFormat("####0.0#####");
  DecimalFormat df4 = new DecimalFormat("####0.00");
  DecimalFormat df5 = new DecimalFormat("####0.0");

  Color lesionColor = new Color(0, 0, 0);
  Color lossColor = new Color(255, 0, 0);
  Color fColor1a = new Color(0, 0, 255);
  Color fColor1b = new Color(0, 0, 170);
  Color fColor2a = new Color(204, 153, 0);
  Color fColor2b = new Color(153, 102, 0);
  Color fColor3a = new Color(0, 221, 0);
  Color fColor3b = new Color(0, 170, 0);
  Color fColor4a = new Color(255, 102, 255);
  Color fColor4b = new Color(204, 102, 204);

  Vector residue1xdata = new Vector();
  Vector residue1ydata = new Vector();
  Vector residue2xdata = new Vector();
  Vector residue2ydata = new Vector();
  Vector residue3xdata = new Vector();
  Vector residue3ydata = new Vector();
  Vector residue4xdata = new Vector();
  Vector residue4ydata = new Vector();

  Vector resistance1xdata = new Vector();
  Vector resistance1ydata = new Vector();
  Vector resistance2xdata = new Vector();
  Vector resistance2ydata = new Vector();
  Vector resistance3xdata = new Vector();
  Vector resistance3ydata = new Vector();
  Vector resistance4xdata = new Vector();
  Vector resistance4ydata = new Vector();

  Vector lesionsxdata = new Vector();
  Vector lesionsydata = new Vector();
  Vector pctLossxdata = new Vector();
  Vector pctLossydata = new Vector();

  Checkbox noneBox = new Checkbox(fcides[0], true);
  Checkbox fungicide1 = new Checkbox(fcides[1], false);
  Checkbox fungicide2 = new Checkbox(fcides[2], false);
  Checkbox fungicide3 = new Checkbox(fcides[3], false);
  Checkbox fungicide4 = new Checkbox(fcides[4], false);
  boolean[] fChosen = new boolean[]{false, false, false, false};

  Button done;

  Choice whichToSpray;
  String whichFungicide = fcides[1];
  int[][] dayArray = new int[][]{
    {0, 0, 0, 0, 0, 1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99},
    {0, 0, 0, 0, 0, 1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99},
    {0, 0, 0, 0, 0, 1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 15, 29, 43, 57, 71, 85, 99},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 15, 29, 43, 57, 71, 85, 99}
  };
  double[][] doseArray = new double[][]{
    {0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0},
    {0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0},
    {0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0},
    {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5},
    {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}
  };
  int firstSprayDate = 0;
  int daysBetween = 0;
  int doseForAll = 0;
  int index = 0;

  TextField[] dayText = new TextField[20];
  TextField[] doseText = new TextField[20];

  Button schedDone;
  Button okay;
  Button setDays;
  Button applyDose;
  TextField firstSpray;
  TextField days;
  TextField dose;
  int autospray = 1;
  int autodays = 1;
  double autodose = 0.0;

  Choice whichToModify;
  String whichCharacter = fcides[1];
  Button save;
  Button characterDone;
  FungicideConstants lpFcid = new FungicideConstants();
  TextField[] fungicideNameText = new TextField[5];
  TextField[] fungicideCostText = new TextField[5];
  TextField[] doseDepositText = new TextField[5];
  TextField[] weatheringRateText = new TextField[5];
  TextField[] sporeMortalityText = new TextField[5];
  TextField[] drSlopeText = new TextField[5];
  TextField[] lesionInhibText = new TextField[5];
  TextField[] sporeInhibText = new TextField[5];
  TextField[] mutationRateText = new TextField[5];
  TextField[] resistanceLevelText = new TextField[5];
  TextField[] sporeSurvivalText = new TextField[5];
  TextField[] lesionDevelText = new TextField[5];
  TextField[] sporulationText = new TextField[5];

  Button saveResistance;
  TextField[] resistText;
  double[] originalPctRes = new double[]{
    lpFcid.pctRes[0], lpFcid.pctRes[1], lpFcid.pctRes[2], lpFcid.pctRes[3], lpFcid.pctRes[4]
  };

  Button saveInoculum;
  double inoculumSpores = 5000;
  double inoculumSporesSetting = 5000;
  int inoculumDays = 35;
  double inoculumBlow = 0;
  TextField inoculumSporesText;
  TextField inoculumDaysText;
  TextField inoculumBlowText;

  Button saveCycle;
  double infectionEff = 0.1;
  double latentPeriod = 10;
  double infectiousPeriod = 35;
  double sporulationRate = 6000;
  double sporeDeposition = 0.0005;
  double lesionLimit = 15000000;
  double overWinteringFactor = 3;
  double sporeSurvivalRate = 0.5;
  double latentLesionRate = 0.9;
  double sporulatingLesionRate = 0.99;
  TextField infectionEffText;
  TextField latentPeriodText;
  TextField infectiousPeriodText;
  TextField sporulationRateText;
  TextField sporeDepositionText;
  TextField lesionLimitText;
  TextField overWinteringFactorText;
  TextField sporeSurvivalRateText;
  TextField latentLesionRateText;
  TextField sporulatingLesionRateText;

  Button saveDamage;
  double damageConstant = 680000;
  double maxCropLoss = 0.08;
  TextField damageConstantText;
  TextField maxCropLossText;

  Button saveSuscept;
  Button applySuscept;
  double[] susceptValues = new double[]{
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
  };
  double suscept = 1.0;
  double autoApply = 100.0;
  TextField[] susceptValuesText = new TextField[20];
  TextField applySusceptText;

  Button saveSeason;
  int seasonLength = 140;
  TextField seasonLengthText;

  Button saveStartingDate;
  String startingDateString = "June 1";
  SimpleDateFormat sdf = new SimpleDateFormat("MMMM d");
  Date today = sdf.parse(startingDateString, new ParsePosition(0));
  TextField startingDateText;

  Button saveCostsPrice;
  double applicationCost = 8.0;
  double fixedCosts = 880.0;
  double maxRevenue = 2000.0;
  TextField applicationCostText;
  TextField fixedCostsText;
  TextField maxRevenueText;

  // subpopulation specific objects
  Stage sporePop = new Stage();
  Stage latentPop = new Stage();
  Stage lesionPop = new Stage();

  // season dependent variables
  double damageCalc = 0.0;
  double pctLoss = 0.0;
  double pCumLoss = 0.0;

  double survivingPopulation = 0.0;
  double totalLLesions = 0.0;
  double totalSLesions = 0.0;
  double totalSpores = 0.0;
  double totalDeadLesions = 0.0;
  double visibleLesions = 0.0;
  double lesionSCF = 1.0;
  double newlyDead = 0.0;
  double deltaT = 0.1;

  int spraysApplied = 0;

  double totalFungicideCost = 0.0;
  double totalAppCost = 0.0;
  double totalCost = 0.0;
  double revenue = 0.0;
  double profitLoss = 0.0;

  double[] inocDose = new double[popSize];
  double[] sporeFitness = new double[popSize];
  double[] latentFitness = new double[popSize];
  double[] lesionFitness = new double[popSize];

  DataRecord record = new DataRecord();
  Dialog dataDialog;
  TextArea dialogText;
  Button dialogButton;

  Dialog pieDialog;

  boolean bShowLesions = true;
  boolean bShowPercentLoss = true;
  boolean bShowResidues = true;
  boolean bShowResistances = true;

  Properties configProps = new Properties();

  Label nameLabel;
  Label fungicideCostLabel;
  Label doseDepositLabel;
  Label weatheringRateLabel;
  Label ed50Label;
  Label drSlopeLabel;
  Label lesionInhibLabel;
  Label sporeInhibLabel;
  Label mutationRateLabel;
  Label resistanceLevelLabel;
  Label fitnessLabel;

  Label infEffLabel;
  Label latentPeriodLabel;
  Label infPeriodLabel;
  Label sporRateLabel;
  Label sporDepLabel;
  Label lesionLimitLabel;
  Label overWinterLabel;
  Label dailySurvivalLabel;

  Label appCostLabel;
  Label fixedCostLabel;
  Label maxRevLabel;

  /**Construct the applet*/
  public Resistan() {
  }

  /**Initialize the applet*/
  public void init() {

    frame = new Frame("Resistan Simulation");
    frame.setBackground(Color.white);
    frame.setLayout(new BorderLayout());
    frame.addWindowListener(this);

    menu = new MenuBar();
    createMenu();

    frame.setMenuBar(menu);

    panel = new Panel(new BorderLayout()) {
      public void update(Graphics g) {
        plot(g);
      }
    };
    panel.setBackground(bgColor);

    dataDialog = new Dialog(frame, "Data Dialog", false);
    dataDialog.setBackground(Color.lightGray);
    dataDialog.setLayout(new BorderLayout());
    dataDialog.addWindowListener(this);

    helpDialog = new Dialog(frame, "Help Dialog", false);
    helpDialog.setBackground(Color.lightGray);
    helpDialog.setLayout(new BorderLayout());
    helpDialog.addWindowListener(this);
    helpText = new TextArea();
    helpText.setEditable(false);
    helpText.setBackground(Color.lightGray);
    helpDialog.add(helpText, BorderLayout.CENTER);
    helpDialog.setSize(320, 240);
    helpDialog.hide();

    pieDialog = new Dialog(frame, "Pie Chart", false) {
      public void update(Graphics g) {
        paintPie(g);
      }
    };
    pieDialog.setBackground(Color.lightGray);
    pieDialog.addWindowListener(this);
    pieDialog.setSize(740, 480);

    createScroll();
    scrollpanel = new Panel(new BorderLayout());
    scrollpanel.setBackground(bgColor);
    scrollpanel.add(scroll, BorderLayout.SOUTH);

    StringBuffer buff = new StringBuffer("Today is ");
    sdf.format(today, buff, new FieldPosition(0));
    buff.append(" of season " + String.valueOf(seasonNumber));
    dateLabel = new Label(buff.toString(), Label.CENTER);
    scrollpanel.add(dateLabel, BorderLayout.NORTH);

    subpanel = new Panel(new GridLayout(2,5));
    subpanel.setBackground(bgColor);
    setColorBar();

    setLayout(new BorderLayout());

    tempPanel = new Panel(new BorderLayout());
    add(tempPanel, BorderLayout.CENTER);

    // add content panels in the beginNew() method,
    // when "Begin New" is clicked -- not here
    /*
    add(subpanel, BorderLayout.NORTH);
    add(panel, BorderLayout.CENTER);
    add(scrollpanel, BorderLayout.SOUTH);
    */

    frame.add(this, BorderLayout.CENTER);
    frame.show();
    frame.setSize(800, 700);

    initCalculations();
    doCalculations();
    logFirstDayCalculations();

    g = getGraphics();
    panel.repaint();
    panel.invalidate();
    frame.validate();
  }

  public void logFirstDayCalculations() {
    // log first day calculations
    StringBuffer logDateText = new StringBuffer();
    sdf.format(today, logDateText, new FieldPosition(0));
    record.currentDay.addElement(logDateText.toString());
    record.currentSuscept.addElement(String.valueOf(Math.round(100.0 * 100.0 * suscept) / 100.0));

    record.residue1.addElement(String.valueOf(Math.round(100.0 * lpFcid.residueF[1]) / 100.0));
    record.residue2.addElement(String.valueOf(Math.round(100.0 * lpFcid.residueF[2]) / 100.0));
    record.residue3.addElement(String.valueOf(Math.round(100.0 * lpFcid.residueF[3]) / 100.0));
    record.residue4.addElement(String.valueOf(Math.round(100.0 * lpFcid.residueF[4]) / 100.0));

    record.resistance1.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[1]) / 100.0));
    record.resistance2.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[2]) / 100.0));
    record.resistance3.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[3]) / 100.0));
    record.resistance4.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[4]) / 100.0));

    record.currentVisibleLesions.addElement(String.valueOf(Math.round(100.0 * visibleLesions) / 100.0));

    record.currentPercentLoss.addElement(String.valueOf(Math.round(100.0 * pctLoss) / 100.0));
  }

  /**Start the applet*/
  public void beginNew() {
    // start the simulation over
    remove(tempPanel);
    add(subpanel, BorderLayout.NORTH);
    add(panel, BorderLayout.CENTER);
    add(scrollpanel, BorderLayout.SOUTH);

    scroll.setValue(0);
    count = 0;
    seasonNumber = 1;
    panel.removeAll();

    // reinitialize the fungicide percent resistances
    for(int i = 0; i < 5; i++) {
      lpFcid.pctRes[i] = originalPctRes[i];
    } // end for i

    // reset inoculum spores to default values
    inoculumSpores = inoculumSporesSetting;

    record = new DataRecord();
    initCalculations();
    doCalculations();
    logFirstDayCalculations();

    panel.repaint();
    panel.invalidate();
    frame.validate();
  }

  public void nextSeason() {
    // continue to the next season
    scroll.setValue(0);
    count = 0;
    seasonNumber++;
    panel.removeAll();

    initCalculations();
    doCalculations();
    logFirstDayCalculations();

    panel.repaint();
    panel.invalidate();
    frame.validate();
  }

  /**Main method*/
  public static void main(String[] args) {
    Resistan resistan = new Resistan();
    resistan.init();
  }

  public void adjustmentValueChanged(AdjustmentEvent e) {
    int temp = scroll.getValue();

    // backwards scrollbar movement not allowed
    if(temp < count) {
      scroll.setValue(count);
      return;
    }
    count = temp;

    doCalculations();

    if(count == seasonLength - 1) {
      // the season is over
      endSeason();
    }

    // increment current date by one day
    //long millis = today.getTime();
    //millis += 1000*60*60*24;
    //today.setTime(millis);
    Calendar cal = Calendar.getInstance();
    cal.setTime(today);
    cal.add(Calendar.DATE, 1);
    today = cal.getTime();
    StringBuffer buff = new StringBuffer("Today is ");
    sdf.format(today, buff, new FieldPosition(0));
    buff.append(" of season " + String.valueOf(seasonNumber));
    dateLabel.setText(buff.toString());
    StringBuffer logDateText = new StringBuffer();
    sdf.format(today, logDateText, new FieldPosition(0));
    record.currentDay.addElement(logDateText.toString());
    record.currentSuscept.addElement(String.valueOf(Math.round(100.0 * 100.0 * suscept) / 100.0));

    // put data in array to be plotted
    // we plot residues for all four fungicides
    // as well as the resistances to all four fungicides
    // as well as totalSlesions and profitLoss
    xPos += (int)Math.floor((xEnd - xOrigin)/seasonLength);

    int fcideIndex = 1;
    yPos = yOrigin - (int)Math.round(4 * lpFcid.residueF[fcideIndex] * lpFcid.residueSCF[fcideIndex]);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    residue1xdata.addElement(new Integer(xPos));
    residue1ydata.addElement(new Integer(yPos));
    record.residue1.addElement(String.valueOf(Math.round(100.0 * lpFcid.residueF[fcideIndex]) / 100.0));

    fcideIndex = 2;
    yPos = yOrigin - (int)Math.round(4 * lpFcid.residueF[fcideIndex] * lpFcid.residueSCF[fcideIndex]);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    residue2xdata.addElement(new Integer(xPos));
    residue2ydata.addElement(new Integer(yPos));
    record.residue2.addElement(String.valueOf(Math.round(100.0 * lpFcid.residueF[fcideIndex]) / 100.0));

    fcideIndex = 3;
    yPos = yOrigin - (int)Math.round(4 * lpFcid.residueF[fcideIndex] * lpFcid.residueSCF[fcideIndex]);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    residue3xdata.addElement(new Integer(xPos));
    residue3ydata.addElement(new Integer(yPos));
    record.residue3.addElement(String.valueOf(Math.round(100.0 * lpFcid.residueF[fcideIndex]) / 100.0));

    fcideIndex = 4;
    yPos = yOrigin - (int)Math.round(4 * lpFcid.residueF[fcideIndex] * lpFcid.residueSCF[fcideIndex]);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    residue4xdata.addElement(new Integer(xPos));
    residue4ydata.addElement(new Integer(yPos));
    record.residue4.addElement(String.valueOf(Math.round(100.0 * lpFcid.residueF[fcideIndex]) / 100.0));

    fcideIndex = 1;
    yPos = yOrigin - (int)Math.round(4 * lpFcid.pctRes[fcideIndex]);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    resistance1xdata.addElement(new Integer(xPos));
    resistance1ydata.addElement(new Integer(yPos));
    record.resistance1.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[fcideIndex]) / 100.0));

    fcideIndex = 2;
    yPos = yOrigin - (int)Math.round(4 * lpFcid.pctRes[fcideIndex]);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    resistance2xdata.addElement(new Integer(xPos));
    resistance2ydata.addElement(new Integer(yPos));
    record.resistance2.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[fcideIndex]) / 100.0));

    fcideIndex = 3;
    yPos = yOrigin - (int)Math.round(4 * lpFcid.pctRes[fcideIndex]);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    resistance3xdata.addElement(new Integer(xPos));
    resistance3ydata.addElement(new Integer(yPos));
    record.resistance3.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[fcideIndex]) / 100.0));

    fcideIndex = 4;
    yPos = yOrigin - (int)Math.round(4 * lpFcid.pctRes[fcideIndex]);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    resistance4xdata.addElement(new Integer(xPos));
    resistance4ydata.addElement(new Integer(yPos));
    record.resistance4.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[fcideIndex]) / 100.0));

    yPos = yOrigin - (int)Math.round(4 * visibleLesions / lesionSCF);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    lesionsxdata.addElement(new Integer(xPos));
    lesionsydata.addElement(new Integer(yPos));
    record.currentVisibleLesions.addElement(String.valueOf(Math.round(100.0 * visibleLesions) / 100.0));

    yPos = yOrigin - (int)Math.round(4 * pctLoss);
    while(yPos < yEnd) {
      yPos += yOrigin - yEnd;
    }
    pctLossxdata.addElement(new Integer(xPos));
    pctLossydata.addElement(new Integer(yPos));
    record.currentPercentLoss.addElement(String.valueOf(Math.round(100.0 * pctLoss) / 100.0));

    panel.removeAll();
    panel.repaint();
    panel.invalidate();
    frame.validate();
  }

  public void focusLost(FocusEvent e) {

  }

  public void focusGained(FocusEvent e) {
    Component comp = e.getComponent();
    if(comp instanceof TextField) {
      ((TextField)comp).selectAll();
    }
  }

  public void windowClosing(WindowEvent e) {
    if(e.getSource() == dataDialog) {
      dataDialog.hide();
    } else if(e.getSource() == pieDialog) {
      pieDialog.hide();
    } else if(e.getSource() == helpDialog) {
      helpDialog.hide();
    } else if(e.getSource() == frame) {
      frame.dispose();
      destroy();
    }
    panel.repaint();
    panel.invalidate();
    frame.validate();
  }

  public void windowActivated(WindowEvent e) {

  }

  public void windowClosed(WindowEvent e) {

  }

  public void windowDeactivated(WindowEvent e) {

  }

  public void windowDeiconified(WindowEvent e) {

  }

  public void windowIconified(WindowEvent e) {

  }

  public void windowOpened(WindowEvent e) {

  }

  public void mouseExited(MouseEvent e) {

  }

  public void mouseEntered(MouseEvent e) {

  }

  public void mousePressed(MouseEvent e) {

  }

  public void mouseReleased(MouseEvent e) {

  }

  public void mouseClicked(MouseEvent e) {
    if(e.getSource() == nameLabel) {
      helpDialog.setTitle("Name");
      helpText.setText(wrapText("Name allows you to create a new name for your new fungicide. Fungicide names may not exceed 20 characters."));
    } else if(e.getSource() == fungicideCostLabel) {
      helpDialog.setTitle("Fungicide Cost");
      helpText.setText(wrapText("Fungicide Cost is used in the benefit-cost analysis at the end of the simulation.  The monetary units and the units of measure of the fungicide can be any arbitrary units that are consistent with the other units used in the simulation.  The default units are dollars per pound."));
    } else if(e.getSource() == doseDepositLabel) {
      helpDialog.setTitle("Dose->Deposit Factor");
      helpText.setText(wrapText("Dose->Deposit Factor converts the application dose of the fungicide to a deposit on the leaf surface.  It can be calculated by dividing the measured deposit in micrograms per square centimeter of plant surface immediately following a spray by the application dose.  The units in which the application dose is expressed (both the quantity of fungicide, and the unit of land area) may vary, as long as the same units are used consistently throughout the program.  The default application doses are expressed in pounds of active ingredient per acre."));
    } else if(e.getSource() == weatheringRateLabel) {
      helpDialog.setTitle("Weathering Rate");
      helpText.setText(wrapText("Weathering Rate expresses the rate at which the fungicide residue disappears from plant surfaces as a proportion lost per day (the exponent in a negative exponential function).  It is estimated by regressing the natural log of the measured residue in micrograms per square centimeter of plant surface versus time in days following the application.  This parameter is the negative slope of the regression line, and should represent an \"average\" from different parts of the crop canopy and following a wide range of environmental conditions. In the simulation, the residues of the fungicides are calculated as follows:\nresid(f) = resid(f) - attenu(f) * resid(f)\nwhere resid(f) is the residue of each of the fungicides (f) in micrograms per square centimeter and attenu(f) is the attenuation rate of each fungicide (proportion lost per day).  The time step for this state equation is one day."));
    } else if(e.getSource() == ed50Label) {
      helpDialog.setTitle("ED50 Spore Mortality");
      helpText.setText(wrapText("ED50 Spore Mortality is the dose of the fungicide that kills 50% of the fungus spores.  Simulation of the dose-response to the fungicide assumes that the probit kill is a linear function of the logarithm of the dose, a function that can be described with two parameters, a slope and an ED50 intercept.\nprobit(f,r) = 5 + slope(f) * log10 (resid(f) / ed50(f) / reslev(f,r))\nThis function is evaluated for each fungicide and for the subpopulations sensitive and resistant to each fungicide (f,r).  Reslev is the resistance level, which is 1.0 for the sensitive biotype and greater than one for the resistant biotype.  Probits are then transformed into proportion kill of each biotype (sensitive or resistant) by each fungicide, kill(f,r). " +
        "Despite the fact that a probit/log dose function does not always represent a good fit of the response of a fungus to a fungicide, this is one of the approximations that is made to simplify and streamline the simulation.  The dose must be expressed in micrograms of fungicide per square centimeter of surface and the response in proportion of the population killed.  Probit kill is then regressed versus log10 of the dose.  Two parameters are then estimated, the slope of the regression line and the ED50.  The ED50 of the fungicide in micrograms per square centimeter of leaf surface is the antilog of the point on the ordinate that corresponds to probit 5 on the abscissa, and its value depends on the target fungus."));
    } else if(e.getSource() == drSlopeLabel) {
      helpDialog.setTitle("Dose-Response Slope");
      helpText.setText(wrapText("Dose-Response Slope is the slope of the probit kill / log dose function for the target fungus.  (See the previous item.)"));
    } else if(e.getSource() == lesionInhibLabel) {
      helpDialog.setTitle("ED50 Inhibition of Lesion Development");
      helpText.setText(wrapText("ED50 Inhibition of Lesion Development is the dose of the fungicide that inhibits lesion development to 50% of the maximum inhibition for the fungicide.  Fungicide inhibition of lesion development is simulated as a saturation function:\ninhbles(f,r) = resid(f) / (ed50les(f) * reslev(f,r) + resid(f))\nwhere ed50les(f) is the fungicide dose that gives 50% inhibition of lesion development (the half-saturation constant) and reslev(f,r) is the resistance level.  (The resistance level of the sensitive biotype is 1.0)"));
    } else if(e.getSource() == sporeInhibLabel) {
      helpDialog.setTitle("ED50 Inhibition of Sporulation");
      helpText.setText(wrapText("ED50 Inhibition of Sporulation is the dose of the fungicide that inhibits sporulation to 50% of the maximum inhibition for the fungicide.  Fungicide inhibition of sporulation is simulated as a saturation function:\ninhbspo(f,r) = resid(f) / (ed50spo(f) * reslev(f,r) + resid(f))\nwhere ed50spo(f) is the fungicide dose that gives 50% inhibition of sporulation (the half-saturation constant) and reslev(f,r) is the resistance level.  (The resistance level of the sensitive biotype is 1.0)"));
    } else if(e.getSource() == mutationRateLabel) {
      helpDialog.setTitle("Mutation Rate");
      helpText.setText(wrapText("Mutation Rate represents the rate at which mutation to the resistant biotype occurs.  It is expressed as a percentage and serves as a lower limit on the percent resistance in the fungal population."));
    } else if(e.getSource() == resistanceLevelLabel) {
      helpDialog.setTitle("Resistance Level");
      helpText.setText(wrapText("Resistance Level is the factor by which the ED50 of the sensitive biotype is multiplied to get the ED50 of the resistant biotype.  For example, if the resistant biotype required 100 times the dose to achieve the same level of control as the sensitive biotype, the resistance level would be 100."));
    } else if(e.getSource() == fitnessLabel) {
      helpDialog.setTitle("Fitness of Resistant Biotype");
      helpText.setText(wrapText("Fitness of the Resistant Biotype can affect all three stages of fungal development; spore survival, lesion development and sporulation.  The effect on spore survival is used as a factor in determining the daily survival rate of spores.  The effects on lesion development and sporulation are used as factors in determining the flow from one growth stage to the next.  All three factors are expressed as proportions ranging from 0 to 1.  If the resistant and sensitive biotypes are equally fit, the factor is one.  The relative fitness of the resistant biotype cannot be measured or estimated easily from laboratory or field experiments.  It is most easily estimated by repeatedly readjusting the fitness factors after running Resistan until the simulated rate of reversion to the sensitive biotype approximates that observed in the field."));
    } else if(e.getSource() == infEffLabel) {
      helpDialog.setTitle("Infection Efficiency");
      helpText.setText(wrapText("Infection Efficiency is the proportion of landed spores that successfully infect per day.  It is estimated by depositing a known number of spores on a susceptible surface and counting the infections that result following incubation in a favorable environment.  The parameter is the number of infections per deposited spore."));
    } else if(e.getSource() == latentPeriodLabel) {
      helpDialog.setTitle("Latent Period");
      helpText.setText(wrapText("Latent Period is the time in days from initiation of infection until a sporulating lesion appears.  Both the Latent Period and the Infectious Period are average values over a wide range of environmental conditions."));
    } else if(e.getSource() == infPeriodLabel) {
      helpDialog.setTitle("Infectious Period");
      helpText.setText(wrapText("Infectious Period is the number of days that the lesion continues to produce spores. Both the Latent Period and the Infectious Period are average values over a wide range of environmental conditions."));
    } else if(e.getSource() == sporRateLabel) {
      helpDialog.setTitle("Sporulation Rate");
      helpText.setText(wrapText("Sporulation Rate is the number of spores produced per lesion per day, averaged over the infectious period."));
    } else if(e.getSource() == sporDepLabel) {
      helpDialog.setTitle("Spore Deposition");
      helpText.setText(wrapText("Spore Deposition is the proportion of the dispersed spores that actually land on susceptible tissue.  It is a very difficult parameter to estimate empirically and may have to be left as a \"tuning\" parameter, that is, a parameter whose value is iteratively readjusted after comparing simulated epidemics with real epidemics."));
    } else if(e.getSource() == lesionLimitLabel) {
      helpDialog.setTitle("Lesion Limit");
      helpText.setText(wrapText("Lesion Limit is the upper limit on the number of lesions per unit land area.  Its purpose is to prevent unlimited population growth in the event of an uncontrolled epidemic.  This may be an awkward unit with some fungi where disease is measured as a proportion of tissue infected or as lesions per unit of leaf area.  However, by using an average lesion size and an estimate of total leaf area per unit of land area, it is possible to express this value in the appropriate units."));
    } else if(e.getSource() == overWinterLabel) {
      helpDialog.setTitle("Overwintering Factor");
      helpText.setText(wrapText("Overwintering Factor is a simple proportionality factor to convert the final lesion count in one season to initial inoculum for the following season.  It is expressed as the number of spores dispersed (not yet deposited) at the start of the following season per sporulating lesion existing at the end of the season (not necessarily per overwintering lesion)."));
    } else if(e.getSource() == dailySurvivalLabel) {
      helpDialog.setTitle("Daily Survival Rate");
      helpText.setText(wrapText("Daily Survival Rates of Spores, Latent Lesions, and  Sporulating Lesions represent averages over a wide range of environmental conditions.  These are expressed as proportions of the respective populations."));
    } else if(e.getSource() == appCostLabel) {
      helpDialog.setTitle("Application Cost");
      helpText.setText(wrapText("Application Cost is the cost of a single spray application in the desired monetary units per unit of land area (e.g., dollars per acre).  This does not include the cost of the fungicide, which is set in the Fungicides menu under Characteristics...."));
    } else if(e.getSource() == fixedCostLabel) {
      helpDialog.setTitle("Fixed Costs");
      helpText.setText(wrapText("Fixed Costs are the total crop production costs, excluding the fungicide spray application cost and the cost of the fungicides, in the desired monetary units per unit of land area (e.g., dollars per acre)."));
    } else if(e.getSource() == maxRevLabel) {
      helpDialog.setTitle("Maximum Revenue");
      helpText.setText(wrapText("Maximum Revenue is the expected revenue from the crop without any losses resulting from the disease (e.g., dollars per acre)."));
    }
    helpDialog.show();
  }

  public String wrapText(String s) {
    String temp = "";
    StringTokenizer token = new StringTokenizer(s, " ");
    int wrapAt = 45;
    int chars = 0;
    String holder = "";
    while(token.hasMoreTokens()) {
      if(chars > wrapAt) {
        chars = 0;
        temp += "\n";
     }
     holder = token.nextToken();
     temp += holder;
     temp += " ";
     chars += holder.length() + 1;
    }
    return temp;
  }

  public void popupConfigInput() {
    dataDialog.removeAll();
    dataDialog.setTitle("Load Data File");
    dataDialog.setLayout(new BorderLayout());

    dialogText = new TextArea();
    dialogText.setBackground(Color.white);
    dataDialog.add(dialogText, BorderLayout.CENTER);

    dialogButton = new Button("Load Data File");
    dialogButton.addActionListener(this);
    dataDialog.add(dialogButton, BorderLayout.SOUTH);

    dataDialog.setSize(640, 480);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveConfigInput() {
    try {
      ByteArrayInputStream bais = new ByteArrayInputStream(dialogText.getText().getBytes());
      configProps.load(bais);
    } catch (Exception e) {
      e.printStackTrace();
    }
    processConfigInput();
    dataDialog.hide();
  }

  public void processConfigInput() {
    lpFcid = new FungicideConstants();

    for(int i = 1; i <= 4; i++) {
      fcides[i] = configProps.getProperty("fungicide" + i + "_" + fungicideKeys[0], "None");
      lpFcid.fungicideName[i] = fcides[i];
      lpFcid.fungicideCost[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[1], "0.0"))).doubleValue();
      lpFcid.doseDeposit[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[2], "0.0"))).doubleValue();
      lpFcid.weatheringRate[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[3], "0.0"))).doubleValue();
      lpFcid.sporeMortality[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[4], "0.0"))).doubleValue();
      lpFcid.drSlope[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[5], "0.0"))).doubleValue();
      lpFcid.lesionInhib[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[6], "0.0"))).doubleValue();
      lpFcid.sporeInhib[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[7], "0.0"))).doubleValue();
      lpFcid.mutationRate[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[8], "0.0"))).doubleValue();
      lpFcid.resistanceLevel[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[9], "0.0"))).doubleValue();
      lpFcid.sporeSurvival[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[10], "0.0"))).doubleValue();
      lpFcid.lesionDevel[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[11], "0.0"))).doubleValue();
      lpFcid.sporulation[i] = (new Double(configProps.getProperty("fungicide" + i + "_" + fungicideKeys[12], "0.0"))).doubleValue();
    } // end for i

    whichFungicide = fcides[1];
    StringTokenizer token;
    int j = 0;
    for(int i = 1; i <= 4; i++) {
      token = new StringTokenizer(configProps.getProperty("fungicide" + i + "_" + dateDoseKeys[0], ""), ",");
      j = 0;
      while(token.hasMoreTokens()) {
        dayArray[i][j] = (int)Math.round((new Double(token.nextToken())).doubleValue());
        j++;
      } // end while token.hasMoreTokens()

      token = new StringTokenizer(configProps.getProperty("fungicide" + i + "_" + dateDoseKeys[1], ""), ",");
      j = 0;
      while(token.hasMoreTokens()) {
        doseArray[i][j] = (new Double(token.nextToken())).doubleValue();
        j++;
      } // end while token.hasMoreTokens()
    } // end for i

    whichCharacter = fcides[1];
    token = new StringTokenizer(configProps.getProperty(fungusKeys[0], ""), ",");
    j = 1;
    while(token.hasMoreTokens()) {
      lpFcid.pctRes[j] = (new Double(token.nextToken())).doubleValue();
      originalPctRes[j] = lpFcid.pctRes[j];
      j++;
    } // end while token.hasMoreTokens()

    inoculumSpores = (new Double(configProps.getProperty(fungusKeys[1], "0.0"))).doubleValue();
    inoculumSporesSetting = inoculumSpores;
    inoculumDays = (int)Math.round((new Double(configProps.getProperty(fungusKeys[2], "0.0"))).doubleValue());
    inoculumBlow = (new Double(configProps.getProperty(fungusKeys[3], "0.0"))).doubleValue();

    infectionEff = (new Double(configProps.getProperty(lifeCycleKeys[0], "0.0"))).doubleValue();
    latentPeriod = (new Double(configProps.getProperty(lifeCycleKeys[1], "0.0"))).doubleValue();
    infectiousPeriod = (new Double(configProps.getProperty(lifeCycleKeys[2], "0.0"))).doubleValue();
    sporulationRate = (new Double(configProps.getProperty(lifeCycleKeys[3], "0.0"))).doubleValue();
    sporeDeposition = (new Double(configProps.getProperty(lifeCycleKeys[4], "0.0"))).doubleValue();
    lesionLimit = (new Double(configProps.getProperty(lifeCycleKeys[5], "0.0"))).doubleValue();
    overWinteringFactor = (new Double(configProps.getProperty(lifeCycleKeys[6], "0.0"))).doubleValue();
    sporeSurvivalRate = (new Double(configProps.getProperty(lifeCycleKeys[7], "0.0"))).doubleValue();
    latentLesionRate = (new Double(configProps.getProperty(lifeCycleKeys[8], "0.0"))).doubleValue();
    sporulatingLesionRate = (new Double(configProps.getProperty(lifeCycleKeys[9], "0.0"))).doubleValue();

    damageConstant = (new Double(configProps.getProperty(plantKeys[0], "0.0"))).doubleValue();
    maxCropLoss = (new Double(configProps.getProperty(plantKeys[1], "0.0"))).doubleValue();
    token = new StringTokenizer(configProps.getProperty(plantKeys[2], "0.0"), ",");
    j = 0;
    while(token.hasMoreTokens()) {
      susceptValues[j] = (new Double(token.nextToken())).doubleValue();
      j++;
    } // end while token.hasMoreTokens()

    seasonLength = (int)Math.round((new Double(configProps.getProperty(seasonKeys[0], "0"))).doubleValue());
    scroll.setMaximum(seasonLength);

    startingDateString = configProps.getProperty(seasonKeys[1], "June 1");
    today = sdf.parse(startingDateString, new ParsePosition(0));

    applicationCost = (new Double(configProps.getProperty(economicKeys[0], "0.0"))).doubleValue();
    fixedCosts = (new Double(configProps.getProperty(economicKeys[1], "0.0"))).doubleValue();
    maxRevenue = (new Double(configProps.getProperty(economicKeys[2], "0.0"))).doubleValue();
  }

  public void writeConfiguration() {
    dataDialog.removeAll();
    dataDialog.setTitle("Save Data File");
    dataDialog.setLayout(new BorderLayout());

    dialogText = new TextArea();
    dialogText.setBackground(Color.white);

    // output config info to dialog text box
    dialogText.append(sHyphens);
    dialogText.append("# Fungicide Characteristics\n");
    dialogText.append(sHyphens);
    dialogText.append("\n");

    for(int i = 1; i <= 4; i++) {
      dialogText.append(sHyphens);
      dialogText.append("fungicide" + i + "_" + fungicideKeys[0] + " : " + fcides[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[1] + " : " + lpFcid.fungicideCost[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[2] + " : " + lpFcid.doseDeposit[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[3] + " : " + lpFcid.weatheringRate[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[4] + " : " + lpFcid.sporeMortality[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[5] + " : " + lpFcid.drSlope[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[6] + " : " + lpFcid.lesionInhib[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[7] + " : " + lpFcid.sporeInhib[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[8] + " : " + lpFcid.mutationRate[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[9] + " : " + lpFcid.resistanceLevel[i] + "\n");
      dialogText.append("# Fitness of Resistant Biotype\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[10] + " : " + lpFcid.sporeSurvival[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[11] + " : " + lpFcid.lesionDevel[i] + "\n");
      dialogText.append("fungicide" + i + "_" + fungicideKeys[12] + " : " + lpFcid.sporulation[i] + "\n");
      dialogText.append(sHyphens);
      dialogText.append("\n");
    } // end for i

    dialogText.append(sHyphens);
    dialogText.append("# Spray Schedules\n");
    dialogText.append(sHyphens);
    dialogText.append("\n");

    for(int i = 1; i <= 4; i++) {
      dialogText.append(sHyphens);
      dialogText.append("fungicide" + i + "_" + dateDoseKeys[0] + " : " + dayArray[i][0]);
      for(int j = 1; j < dayArray[i].length; j++) {
        dialogText.append("," + dayArray[i][j]);
      } // end for j
      dialogText.append("\n");
      dialogText.append("fungicide" + i + "_" + dateDoseKeys[1] + " : " + doseArray[i][0]);
      for(int j = 1; j < doseArray[i].length; j++) {
        dialogText.append("," + doseArray[i][j]);
      } // end for j
      dialogText.append("\n");
      dialogText.append(sHyphens);
      dialogText.append("\n");
    } // end for i

    dialogText.append(sHyphens);
    dialogText.append("# Fungus\n");
    dialogText.append(sHyphens);

    dialogText.append(fungusKeys[0] + " : " + lpFcid.pctRes[1]);
    for(int j = 2; j < lpFcid.pctRes.length; j++) {
      dialogText.append("," + lpFcid.pctRes[j]);
    } // end for j
    dialogText.append("\n");
    dialogText.append(fungusKeys[1] + " : " + inoculumSporesSetting + "\n");
    dialogText.append(fungusKeys[2] + " : " + inoculumDays + "\n");
    dialogText.append(fungusKeys[3] + " : " + inoculumBlow + "\n");
    dialogText.append("\n");

    dialogText.append(sHyphens);
    dialogText.append("# Fungus Life Cycle\n");
    dialogText.append(sHyphens);

    dialogText.append(lifeCycleKeys[0] + " : " + infectionEff + "\n");
    dialogText.append(lifeCycleKeys[1] + " : " + latentPeriod + "\n");
    dialogText.append(lifeCycleKeys[2] + " : " + infectiousPeriod + "\n");
    dialogText.append(lifeCycleKeys[3] + " : " + sporulationRate + "\n");
    dialogText.append(lifeCycleKeys[4] + " : " + sporeDeposition + "\n");
    dialogText.append(lifeCycleKeys[5] + " : " + lesionLimit + "\n");
    dialogText.append(lifeCycleKeys[6] + " : " + overWinteringFactor + "\n");
    dialogText.append("# Daily Survival Rates\n");
    dialogText.append(lifeCycleKeys[7] + " : " + sporeSurvivalRate + "\n");
    dialogText.append(lifeCycleKeys[8] + " : " + latentLesionRate + "\n");
    dialogText.append(lifeCycleKeys[9] + " : " + sporulatingLesionRate + "\n");
    dialogText.append("\n");

    dialogText.append(sHyphens);
    dialogText.append("# Plant\n");
    dialogText.append(sHyphens);

    dialogText.append(plantKeys[0] + " : " + damageConstant + "\n");
    dialogText.append(plantKeys[1] + " : " + maxCropLoss + "\n");
    dialogText.append(plantKeys[2] + " : " + susceptValues[0]);
    for(int i = 1; i < susceptValues.length; i++) {
      dialogText.append("," + susceptValues[i]);
    } // end for i
    dialogText.append("\n");
    dialogText.append("\n");

    dialogText.append(sHyphens);
    dialogText.append("# Season\n");
    dialogText.append(sHyphens);

    dialogText.append(seasonKeys[0] + " : " + seasonLength + "\n");
    dialogText.append(seasonKeys[1] + " : " + startingDateString + "\n");
    dialogText.append("\n");

    dialogText.append(sHyphens);
    dialogText.append("# Economics\n");
    dialogText.append(sHyphens);

    dialogText.append(economicKeys[0] + " : " + applicationCost + "\n");
    dialogText.append(economicKeys[1] + " : " + fixedCosts + "\n");
    dialogText.append(economicKeys[2] + " : " + maxRevenue + "\n");
    dialogText.append("\n");

    dataDialog.add(dialogText, BorderLayout.CENTER);

    dataDialog.setSize(640, 480);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void showLog() {
    dataDialog.removeAll();
    dataDialog.setTitle("Current Season: " + seasonNumber);
    dataDialog.setLayout(new BorderLayout());

    dialogText = new TextArea();
    dialogText.setFont(stdFont);
    dialogText.setBackground(Color.white);
    addTextToLog();
    dataDialog.add(dialogText, BorderLayout.CENTER);

    dataDialog.setSize(640, 480);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  static String sSpace = " ";

  public String setLogText(String arg) {
    int width = 30;
    StringBuffer buffer = new StringBuffer();
    buffer.append(arg);
    for(int i = arg.length(); i < width; i++) {
      buffer.append(sSpace);
    }
    return buffer.toString();
  }

  public void addTextToLog() {
    StringBuffer temp = new StringBuffer();
    StringBuffer dataString = new StringBuffer();

    temp.append(setLogText("Date"));
    temp.append(setLogText("Susceptibility"));
    temp.append(setLogText("Lesions"));
    temp.append(setLogText("% Loss"));
    temp.append(setLogText(fcides[1] + " Residue"));
    temp.append(setLogText(fcides[1] + " Resistance"));
    temp.append(setLogText(fcides[2] + " Residue"));
    temp.append(setLogText(fcides[2] + " Resistance"));
    temp.append(setLogText(fcides[3] + " Residue"));
    temp.append(setLogText(fcides[3] + " Resistance"));
    temp.append(setLogText(fcides[4] + " Residue"));
    temp.append(setLogText(fcides[4] + " Resistance"));

    dialogText.append(temp.toString());
    dialogText.append("\n\n");

    int logIndex = (seasonNumber - 1) * seasonLength;
    for(int i = logIndex; i < record.currentDay.size(); i++) {
      dataString.append(setLogText((String)record.currentDay.elementAt(i)));
      dataString.append(setLogText((String)record.currentSuscept.elementAt(i)));
      dataString.append(setLogText((String)record.currentVisibleLesions.elementAt(i)));
      dataString.append(setLogText((String)record.currentPercentLoss.elementAt(i)));
      dataString.append(setLogText((String)record.residue1.elementAt(i)));
      dataString.append(setLogText((String)record.resistance1.elementAt(i)));
      dataString.append(setLogText((String)record.residue2.elementAt(i)));
      dataString.append(setLogText((String)record.resistance2.elementAt(i)));
      dataString.append(setLogText((String)record.residue3.elementAt(i)));
      dataString.append(setLogText((String)record.resistance3.elementAt(i)));
      dataString.append(setLogText((String)record.residue4.elementAt(i)));
      dataString.append(setLogText((String)record.resistance4.elementAt(i)));
      dataString.append("\n");
    }
    dialogText.append(dataString.toString());

    if(record.endYearNumber.size() > 0) {
      dialogText.append("\n\nSUMMARY:\n\n");
    }

    temp = new StringBuffer();
    if(record.endYearNumber.size() > 0) {
      // we have year end data that we need to show in the log
      temp.append(setLogText("End Year"));
      temp.append(setLogText("Active Lesions"));
      temp.append(setLogText("% Res to " + fcides[1]));
      temp.append(setLogText("% Res to " + fcides[2]));
      temp.append(setLogText("% Res to " + fcides[3]));
      temp.append(setLogText("% Res to " + fcides[4]));
      temp.append(setLogText("Profit"));
      dialogText.append(temp.toString());
      dialogText.append("\n\n");
    }

    dataString = new StringBuffer();
    for(int i = 0; i < record.endYearNumber.size(); i++) {
      dataString.append(setLogText((String)record.endYearNumber.elementAt(i)));
      dataString.append(setLogText((String)record.activeLesions.elementAt(i)));
      dataString.append(setLogText((String)record.pctResFungicideOne.elementAt(i)));
      dataString.append(setLogText((String)record.pctResFungicideTwo.elementAt(i)));
      dataString.append(setLogText((String)record.pctResFungicideThree.elementAt(i)));
      dataString.append(setLogText((String)record.pctResFungicideFour.elementAt(i)));
      dataString.append(setLogText((String)record.endYearProfit.elementAt(i)));
      dataString.append("\n");
    }
    dialogText.append(dataString.toString());
  }

  public void endSeason() {
    // compute the total spray application cost
    totalAppCost = spraysApplied * applicationCost;
    // compute the total cost incurred
    totalCost = totalFungicideCost + totalAppCost + fixedCosts;
    // compute the total revenue
    revenue = (1 - pCumLoss) * maxRevenue;
    // compute the total profit (or loss if negative)
    profitLoss = revenue - totalCost;

    totalSLesions = totalSLesions * overWinteringFactor;
    // test to see if further generations are possible
    if(totalSLesions > 0.95 * lesionLimit) {
      // no further generations possible
      endSimulation();
    }
    if(totalSLesions < 1.0) {
      totalSLesions = 1.0;
    } // end if totalSLesions
    inoculumSpores = totalSLesions;

    // record year end data to year end summary
    record.endYearNumber.addElement(String.valueOf(seasonNumber));
    record.activeLesions.addElement(String.valueOf(Math.round(100.0 * visibleLesions) / 100.0));
    record.pctResFungicideOne.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[1]) / 100.0));
    record.pctResFungicideTwo.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[2]) / 100.0));
    record.pctResFungicideThree.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[3]) / 100.0));
    record.pctResFungicideFour.addElement(String.valueOf(Math.round(100.0 * lpFcid.pctRes[4]) / 100.0));
    record.endYearProfit.addElement(String.valueOf(Math.round(100.0 * profitLoss) / 100.0));
  }

  public void endSimulation() {
    dataDialog.removeAll();
    dataDialog.setTitle("Simulation Ended");
    dataDialog.setLayout(new BorderLayout());

    dataDialog.add(new Label("Epidemic out of control. Further growing seasons impossible!", Label.CENTER), BorderLayout.CENTER);

    dataDialog.setSize(440, 120);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void createScroll() {
    scroll = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, seasonLength);
    scroll.addAdjustmentListener(this);
    scroll.setBackground(Color.white);
    scroll.setBlockIncrement(1);
    scroll.setUnitIncrement(1);
  }

  public void setColorBar() {
    subpanel.removeAll();

    color1 = new Label("");
    color1.setForeground(fColor1a);
    color2 = new Label("");
    color2.setForeground(fColor2a);
    color3 = new Label("");
    color3.setForeground(fColor3a);
    color4 = new Label("");
    color4.setForeground(fColor4a);
    color5 = new Label("");
    color5.setForeground(fColor1b);
    color6 = new Label("");
    color6.setForeground(fColor2b);
    color7 = new Label("");
    color7.setForeground(fColor3b);
    color8 = new Label("");
    color8.setForeground(fColor4b);
    color9 = new Label("Lesions");
    color9.setForeground(lesionColor);
    color10 = new Label("% Loss");
    color10.setForeground(lossColor);

    color1.setText(fcides[1] + " Residue");
    color5.setText(fcides[1] + " Resist");

    color2.setText(fcides[2] + " Residue");
    color6.setText(fcides[2] + " Resist");

    color3.setText(fcides[3] + " Residue");
    color7.setText(fcides[3] + " Resist");

    color4.setText(fcides[4] + " Residue");
    color8.setText(fcides[4] + " Resist");

    int tally = 0;

    if(bShowLesions) {
      subpanel.add(color9);
      tally++;
    }
    if(bShowPercentLoss) {
      subpanel.add(color10);
      tally++;
    }
    if(bShowResidues) {
      subpanel.add(color1);
      tally++;
    }
    if(bShowResistances) {
      subpanel.add(color5);
      tally++;
    }
    if(bShowResidues) {
      subpanel.add(color2);
      tally++;
    }
    if(bShowResistances) {
      subpanel.add(color6);
      tally++;
    }
    if(bShowResidues) {
      subpanel.add(color3);
      tally++;
    }
    if(bShowResistances) {
      subpanel.add(color7);
      tally++;
    }
    if(bShowResidues) {
      subpanel.add(color4);
      tally++;
    }
    if(bShowResistances) {
      subpanel.add(color8);
      tally++;
    }

    for(int i = tally; i < 10; i++) {
      subpanel.add(new Label(""));
    }

  }

  public void createMenu() {

    file = new Menu("Simulation");
    run = new MenuItem("Begin New");
    run.addActionListener(this);
    continueItem = new MenuItem("Continue");
    continueItem.addActionListener(this);
    inputConfiguration = new MenuItem("Load Data File");
    inputConfiguration.addActionListener(this);
    saveConfiguration = new MenuItem("Save Data File");
    saveConfiguration.addActionListener(this);
    loadPreset = new Menu("Load Preset");
    defaultPreset = new MenuItem("Default");
    defaultPreset.addActionListener(this);
    loadPreset.add(defaultPreset);
    exit = new MenuItem("Exit");
    exit.addActionListener(this);
    file.add(run);
    file.add(continueItem);
    file.add(inputConfiguration);
    file.add(saveConfiguration);
    file.add(loadPreset);
    file.add(exit);

    fungicides = new Menu("Fungicides");
    select = new MenuItem("Select...");
    select.addActionListener(this);
    schedules = new MenuItem("Schedules...");
    schedules.addActionListener(this);
    characteristics = new MenuItem("Characteristics...");
    characteristics.addActionListener(this);
    fungicides.add(select);
    fungicides.add(schedules);
    fungicides.add(characteristics);

    fungus = new Menu("Fungus");
    resistance = new MenuItem("Resistance...");
    resistance.addActionListener(this);
    inoculum = new MenuItem("Inoculum...");
    inoculum.addActionListener(this);
    lifeCycle = new MenuItem("Life Cycle...");
    lifeCycle.addActionListener(this);
    fungus.add(resistance);
    fungus.add(inoculum);
    fungus.add(lifeCycle);

    plant = new Menu("Plant");
    susceptibility = new MenuItem("Susceptibility...");
    susceptibility.addActionListener(this);
    damage = new MenuItem("Damage...");
    damage.addActionListener(this);
    plant.add(susceptibility);
    plant.add(damage);

    season = new Menu("Season");
    lengthOfSeason = new MenuItem("Length of Season...");
    lengthOfSeason.addActionListener(this);
    startingDate = new MenuItem("Starting Date...");
    startingDate.addActionListener(this);
    season.add(lengthOfSeason);
    season.add(startingDate);

    economics = new Menu("Economics");
    costsPrice = new MenuItem("Costs/Price...");
    costsPrice.addActionListener(this);
    showPieChart = new MenuItem("Show Pie Chart");
    showPieChart.addActionListener(this);
    economics.add(costsPrice);
    economics.add(showPieChart);

    viewMenu = new Menu("View");
    refresh = new MenuItem("Refresh");
    refresh.addActionListener(this);
    viewLesions = new MenuItem("* Lesions");
    viewLesions.addActionListener(this);
    viewPercentLoss = new MenuItem("* % Loss");
    viewPercentLoss.addActionListener(this);
    viewResidues = new MenuItem("* Residues");
    viewResidues.addActionListener(this);
    viewResistances = new MenuItem("* Resistances");
    viewResistances.addActionListener(this);
    viewMenu.add(refresh);
    viewMenu.add(viewLesions);
    viewMenu.add(viewPercentLoss);
    viewMenu.add(viewResidues);
    viewMenu.add(viewResistances);

    log = new Menu("Log");
    show = new MenuItem("Show Log");
    show.addActionListener(this);
    log.add(show);

    help = new Menu("Help");
    launchHelp = new MenuItem("Show Help");
    launchHelp.addActionListener(this);
    help.add(launchHelp);

    menu.add(file);
    menu.add(fungicides);
    menu.add(fungus);
    menu.add(plant);
    menu.add(season);
    menu.add(economics);
    menu.add(viewMenu);
    menu.add(log);
    menu.add(help);

  }

  public void actionPerformed(ActionEvent e) {
    if(e.getSource() == run) {
      beginNew();
    } else if(e.getSource() == continueItem) {
      nextSeason();
    } else if(e.getSource() == exit) {
      frame.dispose();
      destroy();
    } else if(e.getSource() == select) {
      selectionOptions();
    } else if(e.getSource() == schedules) {
      scheduleOptions();
    } else if(e.getSource() == characteristics) {
      characteristicOptions();
    } else if(e.getSource() == resistance) {
      resistanceOptions();
    } else if(e.getSource() == inoculum) {
      inoculumOptions();
    } else if(e.getSource() == lifeCycle) {
      lifeCycleOptions();
    } else if(e.getSource() == damage) {
      damageOptions();
    } else if(e.getSource() == lengthOfSeason) {
      lengthOfSeasonOptions();
    } else if(e.getSource() == startingDate) {
      startingDateOptions();
    } else if(e.getSource() == costsPrice) {
      costsPriceOptions();
    } else if(e.getSource() == susceptibility) {
      susceptibilityOptions();
    } else if(e.getSource() == showPieChart) {
      createPieChart();
    } else if(e.getSource() == okay) {
      saveSchedule();
      scheduleOptions();
    } else if(e.getSource() == setDays) {
      applyDays();
      scheduleOptions();
    } else if(e.getSource() == applyDose) {
      setDoses();
      scheduleOptions();
    } else if(e.getSource() == save) {
      saveCharacteristics();
      characteristicOptions();
    } else if(e.getSource() == saveResistance) {
      saveResistance();
    } else if(e.getSource() == saveInoculum) {
      saveInoculum();
    } else if(e.getSource() == saveCycle) {
      saveLifeCycle();
    } else if(e.getSource() == saveDamage) {
      saveDamage();
    } else if(e.getSource() == saveSeason) {
      saveLengthOfSeason();
    } else if(e.getSource() == saveStartingDate) {
      saveStartingDate();
    } else if(e.getSource() == saveCostsPrice) {
      saveCostsPrice();
    } else if(e.getSource() == saveSuscept) {
      saveSusceptibility();
    } else if(e.getSource() == applySuscept) {
      applySuscept();
    } else if(e.getSource() == show) {
      showLog();
    } else if(e.getSource() == viewLesions) {
      bShowLesions = !bShowLesions;
      if(bShowLesions) {
        viewLesions.setLabel("* Lesions");
      } else {
        viewLesions.setLabel("  Lesions");
      }
    } else if(e.getSource() == viewPercentLoss) {
      bShowPercentLoss = !bShowPercentLoss;
      if(bShowPercentLoss) {
        viewPercentLoss.setLabel("* % Loss");
      } else {
        viewPercentLoss.setLabel("  % Loss");
      }
    } else if(e.getSource() == viewResidues) {
      bShowResidues = !bShowResidues;
      if(bShowResidues) {
        viewResidues.setLabel("* Residues");
      } else {
        viewResidues.setLabel("  Residues");
      }
    } else if(e.getSource() == viewResistances) {
      bShowResistances = !bShowResistances;
      if(bShowResistances) {
        viewResistances.setLabel("* Resistances");
      } else {
        viewResistances.setLabel("  Resistances");
      }
    } else if(e.getSource() == defaultPreset) {
      setDefaultPreset();
    } else if(e.getSource() == inputConfiguration) {
      popupConfigInput();
    } else if(e.getSource() == dialogButton) {
      saveConfigInput();
      dataDialog.hide();
    } else if(e.getSource() == saveConfiguration) {
      writeConfiguration();
    } else if(e.getSource() == done) {
      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      frame.validate();
    } else if(e.getSource() == schedDone) {
      saveSchedule();
      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      frame.validate();
    } else if(e.getSource() == characterDone) {
      saveCharacteristics();
      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      frame.validate();
    } else if(e.getSource() == launchHelp) {
      try {
        getAppletContext().showDocument(new URL(getDocumentBase() + "help.html"), "_blank");
      } catch (Exception e1) {
      }
    } else if(e.getSource() == refresh) {
      panel.repaint();
      panel.invalidate();
      frame.validate();
    }
  }

  public void itemStateChanged(ItemEvent e) {
    // when a checkbox has been changed
    if(e.getSource() == noneBox) {
      fungicide1.setState(false);
      fungicide2.setState(false);
      fungicide3.setState(false);
      fungicide4.setState(false);
      for(int i = 0; i < 4; i++) {
        fChosen[i] = false;
      }
    } else if(e.getSource() == fungicide1) {
      noneBox.setState(false);
      if(e.getStateChange() == ItemEvent.SELECTED) {
        fChosen[0] = true;
      } else if(e.getStateChange() == ItemEvent.DESELECTED) {
        fChosen[0] = false;
      }
    } else if(e.getSource() == fungicide2) {
      noneBox.setState(false);
      if(e.getStateChange() == ItemEvent.SELECTED) {
        fChosen[1] = true;
      } else if(e.getStateChange() == ItemEvent.DESELECTED) {
        fChosen[1] = false;
      }
    } else if(e.getSource() == fungicide3) {
      noneBox.setState(false);
      if(e.getStateChange() == ItemEvent.SELECTED) {
        fChosen[2] = true;
      } else if(e.getStateChange() == ItemEvent.DESELECTED) {
        fChosen[2] = false;
      }
    } else if(e.getSource() == fungicide4) {
      noneBox.setState(false);
      if(e.getStateChange() == ItemEvent.SELECTED) {
        fChosen[3] = true;
      } else if(e.getStateChange() == ItemEvent.DESELECTED) {
        fChosen[3] = false;
      }
    } else if(e.getSource() == whichToSpray) {
      whichFungicide = (String)e.getItem();
      scheduleOptions();
    } else if(e.getSource() == whichToModify) {
      whichCharacter = (String)e.getItem();
      characteristicOptions();
    }
  }

  public void plot(Graphics g) {
    g.clearRect(0, 0, 800, 600);

    g.setColor(Color.black);
    // draw axes
    g.drawLine(xOrigin,yOrigin,xOrigin,yEnd);
    g.drawLine(xOrigin,yOrigin,xEnd,yOrigin);

    // label y axis
    g.drawString("100", 10, 55);
    g.drawString(" 80", 10, 135);
    g.drawString(" 60", 10, 215);
    g.drawString(" 40", 10, 295);
    g.drawString(" 20", 10, 375);
    g.drawString("  0", 10, 455);

    // label x axis
    int xReference = xOrigin;
    int yReference = yOrigin + 50;
    long totalIncrement = 0;
    Calendar cal = Calendar.getInstance();
    Date currentDate = sdf.parse(startingDateString, new ParsePosition(0));
    Date steadyDate = sdf.parse(startingDateString, new ParsePosition(0));
    cal.setTime(currentDate);
    StringBuffer axisLabel = new StringBuffer();
    while(totalIncrement < seasonLength) {
      axisLabel = new StringBuffer();
      sdf.format(currentDate, axisLabel, new FieldPosition(0));
      g.drawString(axisLabel.toString(), xReference, yReference);

      // update vars for next time around the loop
      cal.add(Calendar.MONTH, 1);
      currentDate = cal.getTime();
      totalIncrement = (currentDate.getTime() - steadyDate.getTime()) / (1000*60*60*24);
      xReference = (int)Math.floor(50 + totalIncrement * 600 / seasonLength);
    }

    int tempX1, tempX2, tempY1, tempY2;

    // plot residues

    if(bShowResidues) {
      g.setColor(fColor1a);
      for(int i = 0; i < residue1xdata.size() - 1; i++) {
        tempX1 = ((Integer)residue1xdata.elementAt(i)).intValue();
        tempX2 = ((Integer)residue1xdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)residue1ydata.elementAt(i)).intValue();
        tempY2 = ((Integer)residue1ydata.elementAt(i + 1)).intValue();
        if(Math.abs(tempY1 - tempY2) < plottingGap) {
          g.drawLine(tempX1, tempY1, tempX2, tempY2);
        }
      }
    }

    if(bShowResidues) {
      g.setColor(fColor2a);
      for(int i = 0; i < residue2xdata.size() - 1; i++) {
        tempX1 = ((Integer)residue2xdata.elementAt(i)).intValue();
        tempX2 = ((Integer)residue2xdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)residue2ydata.elementAt(i)).intValue();
        tempY2 = ((Integer)residue2ydata.elementAt(i + 1)).intValue();
        if(Math.abs(tempY1 - tempY2) < plottingGap) {
          g.drawLine(tempX1, tempY1, tempX2, tempY2);
        }
      }
    }


    if(bShowResidues) {
      g.setColor(fColor3a);
      for(int i = 0; i < residue3xdata.size() - 1; i++) {
        tempX1 = ((Integer)residue3xdata.elementAt(i)).intValue();
        tempX2 = ((Integer)residue3xdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)residue3ydata.elementAt(i)).intValue();
        tempY2 = ((Integer)residue3ydata.elementAt(i + 1)).intValue();
        if(Math.abs(tempY1 - tempY2) < plottingGap) {
          g.drawLine(tempX1, tempY1, tempX2, tempY2);
        }
      }
    }

    if(bShowResidues) {
      g.setColor(fColor4a);
      for(int i = 0; i < residue4xdata.size() - 1; i++) {
        tempX1 = ((Integer)residue4xdata.elementAt(i)).intValue();
        tempX2 = ((Integer)residue4xdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)residue4ydata.elementAt(i)).intValue();
        tempY2 = ((Integer)residue4ydata.elementAt(i + 1)).intValue();
        if(Math.abs(tempY1 - tempY2) < plottingGap) {
          g.drawLine(tempX1, tempY1, tempX2, tempY2);
        }
      }
    }


    if(bShowResistances) {
      g.setColor(fColor1b);
      for(int i = 0; i < resistance1xdata.size() - 1; i++) {
        tempX1 = ((Integer)resistance1xdata.elementAt(i)).intValue();
        tempX2 = ((Integer)resistance1xdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)resistance1ydata.elementAt(i)).intValue();
        tempY2 = ((Integer)resistance1ydata.elementAt(i + 1)).intValue();
        if(Math.abs(tempY1 - tempY2) < plottingGap) {
          g.drawLine(tempX1, tempY1, tempX2, tempY2);
        }
      }
    }

    if(bShowResistances) {
      g.setColor(fColor2b);
      for(int i = 0; i < resistance2xdata.size() - 1; i++) {
        tempX1 = ((Integer)resistance2xdata.elementAt(i)).intValue();
        tempX2 = ((Integer)resistance2xdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)resistance2ydata.elementAt(i)).intValue();
        tempY2 = ((Integer)resistance2ydata.elementAt(i + 1)).intValue();
        if(Math.abs(tempY1 - tempY2) < plottingGap) {
          g.drawLine(tempX1, tempY1, tempX2, tempY2);
        }
      }
    }

    if(bShowResistances) {
      g.setColor(fColor3b);
      for(int i = 0; i < resistance3xdata.size() - 1; i++) {
        tempX1 = ((Integer)resistance3xdata.elementAt(i)).intValue();
        tempX2 = ((Integer)resistance3xdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)resistance3ydata.elementAt(i)).intValue();
        tempY2 = ((Integer)resistance3ydata.elementAt(i + 1)).intValue();
        if(Math.abs(tempY1 - tempY2) < plottingGap) {
          g.drawLine(tempX1, tempY1, tempX2, tempY2);
        }
      }
    }

    if(bShowResistances) {
      g.setColor(fColor4b);
      for(int i = 0; i < resistance4xdata.size() - 1; i++) {
        tempX1 = ((Integer)resistance4xdata.elementAt(i)).intValue();
        tempX2 = ((Integer)resistance4xdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)resistance4ydata.elementAt(i)).intValue();
        tempY2 = ((Integer)resistance4ydata.elementAt(i + 1)).intValue();
        if(Math.abs(tempY1 - tempY2) < plottingGap) {
          g.drawLine(tempX1, tempY1, tempX2, tempY2);
        }
      }
    }

    if(bShowLesions) {
      g.setColor(lesionColor);
      for(int i = 0; i < lesionsxdata.size() - 1; i++) {
        tempX1 = ((Integer)lesionsxdata.elementAt(i)).intValue();
        tempX2 = ((Integer)lesionsxdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)lesionsydata.elementAt(i)).intValue();
        tempY2 = ((Integer)lesionsydata.elementAt(i + 1)).intValue();
        if(Math.abs(tempY1 - tempY2) < plottingGap) {
          g.drawLine(tempX1, tempY1, tempX2, tempY2);
        }
      }
    }

    if(bShowPercentLoss) {
      g.setColor(lossColor);
      for(int i = 0; i < pctLossxdata.size() - 1; i++) {
        tempX1 = ((Integer)pctLossxdata.elementAt(i)).intValue();
        tempX2 = ((Integer)pctLossxdata.elementAt(i + 1)).intValue();
        tempY1 = ((Integer)pctLossydata.elementAt(i)).intValue();
        tempY2 = ((Integer)pctLossydata.elementAt(i + 1)).intValue();
        g.drawLine(tempX1, tempY1, tempX2, tempY2);
      }
    }
  }

  public void selectionOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(6,2));
    dataDialog.setTitle("Fungicide Selections");

    done = new Button("Done");
    done.addActionListener(this);

    noneBox.addItemListener(this);
    fungicide1.setLabel(fcides[1]);
    fungicide1.addItemListener(this);
    fungicide2.setLabel(fcides[2]);
    fungicide2.addItemListener(this);
    fungicide3.setLabel(fcides[3]);
    fungicide3.addItemListener(this);
    fungicide4.setLabel(fcides[4]);
    fungicide4.addItemListener(this);

    dataDialog.add(noneBox);
    dataDialog.add(new Label(""));
    dataDialog.add(fungicide1);
    dataDialog.add(new Label(""));
    dataDialog.add(fungicide2);
    dataDialog.add(new Label(""));
    dataDialog.add(fungicide3);
    dataDialog.add(new Label(""));
    dataDialog.add(fungicide4);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(done);
    dataDialog.setSize(360, 200);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void scheduleOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(17,5));
    dataDialog.setTitle("Fungicide Spray Schedules");

    schedDone = new Button("Done");
    schedDone.addActionListener(this);

    okay = new Button("Save Settings");
    okay.addActionListener(this);

    setDays = new Button("Set Days");
    setDays.addActionListener(this);

    applyDose = new Button("Apply Dose");
    applyDose.addActionListener(this);

    int cols = 10;

    whichToSpray = new Choice();
    whichToSpray.add(fcides[1]);
    whichToSpray.add(fcides[2]);
    whichToSpray.add(fcides[3]);
    whichToSpray.add(fcides[4]);
    whichToSpray.addItemListener(this);
    whichToSpray.select(whichFungicide);

    index = 1;
    if(whichFungicide.equals(fcides[1])) {
      index = 1;
    } else if(whichFungicide.equals(fcides[2])) {
      index = 2;
    } else if(whichFungicide.equals(fcides[3])) {
      index = 3;
    } else if(whichFungicide.equals(fcides[4])) {
      index = 4;
    }

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(whichToSpray);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));

    dataDialog.add(new Label("Day"));
    dataDialog.add(new Label("Dose"));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label("Day"));
    dataDialog.add(new Label("Dose"));

    StringBuffer buff = new StringBuffer();

    dayText[0] = new TextField(String.valueOf(dayArray[index][0]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][0], buff, new FieldPosition(0));
    doseText[0] = new TextField(buff.toString(), cols);
    dayText[0].addFocusListener(this);
    doseText[0].addFocusListener(this);
    dataDialog.add(dayText[0]);
    dataDialog.add(doseText[0]);
    dataDialog.add(new Label(""));
    dayText[10] = new TextField(String.valueOf(dayArray[index][10]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][10], buff, new FieldPosition(0));
    doseText[10] = new TextField(buff.toString(), cols);
    dayText[10].addFocusListener(this);
    doseText[10].addFocusListener(this);
    dataDialog.add(dayText[10]);
    dataDialog.add(doseText[10]);

    dayText[1] = new TextField(String.valueOf(dayArray[index][1]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][1], buff, new FieldPosition(0));
    doseText[1] = new TextField(buff.toString(), cols);
    dayText[1].addFocusListener(this);
    doseText[1].addFocusListener(this);
    dataDialog.add(dayText[1]);
    dataDialog.add(doseText[1]);
    dataDialog.add(new Label(""));
    dayText[11] = new TextField(String.valueOf(dayArray[index][11]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][11], buff, new FieldPosition(0));
    doseText[11] = new TextField(buff.toString(), cols);
    dayText[11].addFocusListener(this);
    doseText[11].addFocusListener(this);
    dataDialog.add(dayText[11]);
    dataDialog.add(doseText[11]);

    dayText[2] = new TextField(String.valueOf(dayArray[index][2]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][2], buff, new FieldPosition(0));
    doseText[2] = new TextField(buff.toString(), cols);
    dayText[2].addFocusListener(this);
    doseText[2].addFocusListener(this);
    dataDialog.add(dayText[2]);
    dataDialog.add(doseText[2]);
    dataDialog.add(new Label(""));
    dayText[12] = new TextField(String.valueOf(dayArray[index][12]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][12], buff, new FieldPosition(0));
    doseText[12] = new TextField(buff.toString(), cols);
    dayText[12].addFocusListener(this);
    doseText[12].addFocusListener(this);
    dataDialog.add(dayText[12]);
    dataDialog.add(doseText[12]);

    dayText[3] = new TextField(String.valueOf(dayArray[index][3]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][3], buff, new FieldPosition(0));
    doseText[3] = new TextField(buff.toString(), cols);
    dayText[3].addFocusListener(this);
    doseText[3].addFocusListener(this);
    dataDialog.add(dayText[3]);
    dataDialog.add(doseText[3]);
    dataDialog.add(new Label(""));
    dayText[13] = new TextField(String.valueOf(dayArray[index][13]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][13], buff, new FieldPosition(0));
    doseText[13] = new TextField(buff.toString(), cols);
    dayText[13].addFocusListener(this);
    doseText[13].addFocusListener(this);
    dataDialog.add(dayText[13]);
    dataDialog.add(doseText[13]);

    dayText[4] = new TextField(String.valueOf(dayArray[index][4]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][4], buff, new FieldPosition(0));
    doseText[4] = new TextField(buff.toString(), cols);
    dayText[4].addFocusListener(this);
    doseText[4].addFocusListener(this);
    dataDialog.add(dayText[4]);
    dataDialog.add(doseText[4]);
    dataDialog.add(new Label(""));
    dayText[14] = new TextField(String.valueOf(dayArray[index][14]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][14], buff, new FieldPosition(0));
    doseText[14] = new TextField(buff.toString(), cols);
    dayText[14].addFocusListener(this);
    doseText[14].addFocusListener(this);
    dataDialog.add(dayText[14]);
    dataDialog.add(doseText[14]);

    dayText[5] = new TextField(String.valueOf(dayArray[index][5]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][5], buff, new FieldPosition(0));
    doseText[5] = new TextField(buff.toString(), cols);
    dayText[5].addFocusListener(this);
    doseText[5].addFocusListener(this);
    dataDialog.add(dayText[5]);
    dataDialog.add(doseText[5]);
    dataDialog.add(new Label(""));
    dayText[15] = new TextField(String.valueOf(dayArray[index][15]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][15], buff, new FieldPosition(0));
    doseText[15] = new TextField(buff.toString(), cols);
    dayText[15].addFocusListener(this);
    doseText[15].addFocusListener(this);
    dataDialog.add(dayText[15]);
    dataDialog.add(doseText[15]);

    dayText[6] = new TextField(String.valueOf(dayArray[index][6]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][6], buff, new FieldPosition(0));
    doseText[6] = new TextField(buff.toString(), cols);
    dayText[6].addFocusListener(this);
    doseText[6].addFocusListener(this);
    dataDialog.add(dayText[6]);
    dataDialog.add(doseText[6]);
    dataDialog.add(new Label(""));
    dayText[16] = new TextField(String.valueOf(dayArray[index][16]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][16], buff, new FieldPosition(0));
    doseText[16] = new TextField(buff.toString(), cols);
    dayText[16].addFocusListener(this);
    doseText[16].addFocusListener(this);
    dataDialog.add(dayText[16]);
    dataDialog.add(doseText[16]);

    dayText[7] = new TextField(String.valueOf(dayArray[index][7]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][7], buff, new FieldPosition(0));
    doseText[7] = new TextField(buff.toString(), cols);
    dayText[7].addFocusListener(this);
    doseText[7].addFocusListener(this);
    dataDialog.add(dayText[7]);
    dataDialog.add(doseText[7]);
    dataDialog.add(new Label(""));
    dayText[17] = new TextField(String.valueOf(dayArray[index][17]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][17], buff, new FieldPosition(0));
    doseText[17] = new TextField(buff.toString(), cols);
    dayText[17].addFocusListener(this);
    doseText[17].addFocusListener(this);
    dataDialog.add(dayText[17]);
    dataDialog.add(doseText[17]);

    dayText[8] = new TextField(String.valueOf(dayArray[index][8]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][8], buff, new FieldPosition(0));
    doseText[8] = new TextField(buff.toString(), cols);
    dayText[8].addFocusListener(this);
    doseText[8].addFocusListener(this);
    dataDialog.add(dayText[8]);
    dataDialog.add(doseText[8]);
    dataDialog.add(new Label(""));
    dayText[18] = new TextField(String.valueOf(dayArray[index][18]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][18], buff, new FieldPosition(0));
    doseText[18] = new TextField(buff.toString(), cols);
    dayText[18].addFocusListener(this);
    doseText[18].addFocusListener(this);
    dataDialog.add(dayText[18]);
    dataDialog.add(doseText[18]);

    dayText[9] = new TextField(String.valueOf(dayArray[index][9]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][9], buff, new FieldPosition(0));
    doseText[9] = new TextField(buff.toString(), cols);
    dayText[9].addFocusListener(this);
    doseText[9].addFocusListener(this);
    dataDialog.add(dayText[9]);
    dataDialog.add(doseText[9]);
    dataDialog.add(new Label(""));
    dayText[19] = new TextField(String.valueOf(dayArray[index][19]), cols);
    buff = new StringBuffer();
    df1.format(doseArray[index][19], buff, new FieldPosition(0));
    doseText[19] = new TextField(buff.toString(), cols);
    dayText[19].addFocusListener(this);
    doseText[19].addFocusListener(this);
    dataDialog.add(dayText[19]);
    dataDialog.add(doseText[19]);

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));

    dataDialog.add(new Label("First Spray:"));
    firstSpray = new TextField(String.valueOf(autospray), cols);
    firstSpray.addFocusListener(this);
    dataDialog.add(firstSpray);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label("Dose For All:"));
    buff = new StringBuffer();
    df1.format(autodose, buff, new FieldPosition(0));
    dose = new TextField(buff.toString(), cols);
    dose.addFocusListener(this);
    dataDialog.add(dose);

    dataDialog.add(new Label("Days Between:"));
    days = new TextField(String.valueOf(autodays), cols);
    days.addFocusListener(this);
    dataDialog.add(days);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(applyDose);

    dataDialog.add(new Label(""));
    dataDialog.add(setDays);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(okay);
    dataDialog.add(schedDone);

    dataDialog.setSize(640, 480);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();

  }

  public void saveSchedule() {
    try {
      autospray = (int)Math.round((new Double(firstSpray.getText())).doubleValue());
      autodays = (int)Math.round((new Double(days.getText())).doubleValue());
      autodose = (new Double(dose.getText())).doubleValue();

      for(int i = 0; i < dayText.length; i++) {
        dayArray[index][i] = (int)Math.round((new Double(dayText[i].getText())).doubleValue());
        if(dayArray[index][i] > 365) {
          dayArray[index][i] = 365;
        } else if(dayArray[index][i] < 0) {
          dayArray[index][i] = 0;
        }
        doseArray[index][i] = (new Double(doseText[i].getText())).doubleValue();
        if(doseArray[index][i] > 100.0) {
          doseArray[index][i] = 100.0;
        } else if(doseArray[index][i] < 0.0) {
          doseArray[index][i] = 0.0;
        }
      }
    } catch (Exception e) {
    }
  }

  public void applyDays() {
    try {
      autospray = (int)Math.round((new Double(firstSpray.getText())).doubleValue());
      autodays = (int)Math.round((new Double(days.getText())).doubleValue());
      autodose = (new Double(dose.getText())).doubleValue();

      int current = autospray;
      for(int i = 0; i < dayText.length; i++) {
        dayArray[index][i] = current;
        if(dayArray[index][i] > 365) {
          dayArray[index][i] = 365;
        } else if(dayArray[index][i] < 0) {
          dayArray[index][i] = 0;
        }
        current = current + autodays;
      }
    } catch (Exception e) {
    }
  }

  public void setDoses() {
    try {
      autospray = (int)Math.round((new Double(firstSpray.getText())).doubleValue());
      autodays = (int)Math.round((new Double(days.getText())).doubleValue());
      autodose = (new Double(dose.getText())).doubleValue();

      for(int i = 0; i < dayText.length; i++) {
        doseArray[index][i] = autodose;
        if(doseArray[index][i] > 100.0) {
          doseArray[index][i] = 100.0;
        } else if(doseArray[index][i] < 0.0) {
          doseArray[index][i] = 0.0;
        }
      }
    } catch (Exception e) {
    }
  }

  public void characteristicOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(17,3));
    dataDialog.setTitle("Fungicide Characteristics");

    int cols = 10;

    index = 1;
    if(whichCharacter.equals(fcides[1])) {
      index = 1;
    } else if(whichCharacter.equals(fcides[2])) {
      index = 2;
    } else if(whichCharacter.equals(fcides[3])) {
      index = 3;
    } else if(whichCharacter.equals(fcides[4])) {
      index = 4;
    }

    whichToModify = new Choice();
    whichToModify.add(fcides[1]);
    whichToModify.add(fcides[2]);
    whichToModify.add(fcides[3]);
    whichToModify.add(fcides[4]);
    whichToModify.addItemListener(this);
    whichToModify.select(whichCharacter);

    characterDone = new Button("Done");
    characterDone.addActionListener(this);

    save = new Button("Save Settings");
    save.addActionListener(this);

    StringBuffer buff = new StringBuffer();

    dataDialog.add(new Label(""));
    dataDialog.add(whichToModify);
    dataDialog.add(new Label(""));

    nameLabel = new Label("Name", Label.RIGHT);
    nameLabel.addMouseListener(this);
    dataDialog.add(nameLabel);
    fungicideNameText[index] = new TextField(lpFcid.fungicideName[index], cols);
    dataDialog.add(fungicideNameText[index]);
    dataDialog.add(new Label(""));

    fungicideCostLabel = new Label("Fungicide Cost", Label.RIGHT);
    fungicideCostLabel.addMouseListener(this);
    dataDialog.add(fungicideCostLabel);
    buff = new StringBuffer();
    df4.format(lpFcid.fungicideCost[index], buff, new FieldPosition(0));
    fungicideCostText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(fungicideCostText[index]);
    dataDialog.add(new Label(""));

    doseDepositLabel = new Label("Dose -> Deposit Factor", Label.RIGHT);
    doseDepositLabel.addMouseListener(this);
    dataDialog.add(doseDepositLabel);
    buff = new StringBuffer();
    df4.format(lpFcid.doseDeposit[index], buff, new FieldPosition(0));
    doseDepositText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(doseDepositText[index]);
    dataDialog.add(new Label(""));

    weatheringRateLabel = new Label("Weathering Rate", Label.RIGHT);
    weatheringRateLabel.addMouseListener(this);
    dataDialog.add(weatheringRateLabel);
    buff = new StringBuffer();
    df1.format(lpFcid.weatheringRate[index], buff, new FieldPosition(0));
    weatheringRateText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(weatheringRateText[index]);
    dataDialog.add(new Label(""));

    ed50Label = new Label("ED50 Spore Mortality", Label.RIGHT);
    ed50Label.addMouseListener(this);
    dataDialog.add(ed50Label);
    buff = new StringBuffer();
    df4.format(lpFcid.sporeMortality[index], buff, new FieldPosition(0));
    sporeMortalityText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(sporeMortalityText[index]);
    dataDialog.add(new Label(""));

    drSlopeLabel = new Label("Dose-Response Slope", Label.RIGHT);
    drSlopeLabel.addMouseListener(this);
    dataDialog.add(drSlopeLabel);
    buff = new StringBuffer();
    df4.format(lpFcid.drSlope[index], buff, new FieldPosition(0));
    drSlopeText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(drSlopeText[index]);
    dataDialog.add(new Label(""));

    lesionInhibLabel = new Label("ED50 Inhib of Lesion Dev", Label.RIGHT);
    lesionInhibLabel.addMouseListener(this);
    dataDialog.add(lesionInhibLabel);
    buff = new StringBuffer();
    df4.format(lpFcid.lesionInhib[index], buff, new FieldPosition(0));
    lesionInhibText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(lesionInhibText[index]);
    dataDialog.add(new Label(""));

    sporeInhibLabel = new Label("ED50 Inhib of Sporul", Label.RIGHT);
    sporeInhibLabel.addMouseListener(this);
    dataDialog.add(sporeInhibLabel);
    buff = new StringBuffer();
    df4.format(lpFcid.sporeInhib[index], buff, new FieldPosition(0));
    sporeInhibText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(sporeInhibText[index]);
    dataDialog.add(new Label(""));

    mutationRateLabel = new Label("Mutation Rate", Label.RIGHT);
    mutationRateLabel.addMouseListener(this);
    dataDialog.add(mutationRateLabel);
    buff = new StringBuffer();
    df3.format(lpFcid.mutationRate[index], buff, new FieldPosition(0));
    mutationRateText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(mutationRateText[index]);
    dataDialog.add(new Label(""));

    resistanceLevelLabel = new Label("Resistance Level", Label.RIGHT);
    resistanceLevelLabel.addMouseListener(this);
    dataDialog.add(resistanceLevelLabel);
    buff = new StringBuffer();
    df5.format(lpFcid.resistanceLevel[index], buff, new FieldPosition(0));
    resistanceLevelText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(resistanceLevelText[index]);
    dataDialog.add(new Label(""));

    fitnessLabel = new Label("Fitness of Resistant Biotype:", Label.LEFT);
    fitnessLabel.addMouseListener(this);
    dataDialog.add(fitnessLabel);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));

    dataDialog.add(new Label("Spore Survival", Label.RIGHT));
    buff = new StringBuffer();
    df1.format(lpFcid.sporeSurvival[index], buff, new FieldPosition(0));
    sporeSurvivalText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(sporeSurvivalText[index]);
    dataDialog.add(new Label(""));

    dataDialog.add(new Label("Lesion Development", Label.RIGHT));
    buff = new StringBuffer();
    df1.format(lpFcid.lesionDevel[index], buff, new FieldPosition(0));
    lesionDevelText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(lesionDevelText[index]);
    dataDialog.add(new Label(""));

    dataDialog.add(new Label("Sporulation", Label.RIGHT));
    buff = new StringBuffer();
    df1.format(lpFcid.sporulation[index], buff, new FieldPosition(0));
    sporulationText[index] = new TextField(buff.toString(), cols);
    dataDialog.add(sporulationText[index]);
    dataDialog.add(new Label(""));

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));

    dataDialog.add(new Label(""));
    dataDialog.add(save);
    dataDialog.add(characterDone);

    dataDialog.setSize(560,480);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveCharacteristics() {
    try {
      lpFcid.fungicideName[index] = fungicideNameText[index].getText();
      if(lpFcid.fungicideName[index].length() > 20) {
        lpFcid.fungicideName[index] = lpFcid.fungicideName[index].substring(0,20);
      }
      lpFcid.fungicideCost[index] = (new Double(fungicideCostText[index].getText())).doubleValue();
      if(lpFcid.fungicideCost[index] < 0.0) {
        lpFcid.fungicideCost[index] = 0.0;
      } else if(lpFcid.fungicideCost[index] > 999.99) {
        lpFcid.fungicideCost[index] = 999.99;
      }
      lpFcid.doseDeposit[index] = (new Double(doseDepositText[index].getText())).doubleValue();
      if(lpFcid.doseDeposit[index] < 0.0) {
        lpFcid.doseDeposit[index] = 0.0;
      } else if(lpFcid.doseDeposit[index] > 999.99) {
        lpFcid.doseDeposit[index] = 999.99;
      }
      lpFcid.weatheringRate[index] = (new Double(weatheringRateText[index].getText())).doubleValue();
      if(lpFcid.weatheringRate[index] < 0.0) {
        lpFcid.weatheringRate[index] = 0.0;
      } else if(lpFcid.weatheringRate[index] > 1.0) {
        lpFcid.weatheringRate[index] = 1.0;
      }
      lpFcid.sporeMortality[index] = (new Double(sporeMortalityText[index].getText())).doubleValue();
      if(lpFcid.sporeMortality[index] < 0.0) {
        lpFcid.sporeMortality[index] = 0.0;
      } else if(lpFcid.sporeMortality[index] > 999.99) {
        lpFcid.sporeMortality[index] = 999.99;
      }
      lpFcid.drSlope[index] = (new Double(drSlopeText[index].getText())).doubleValue();
      if(lpFcid.drSlope[index] < 0.0) {
        lpFcid.drSlope[index] = 0.0;
      } else if(lpFcid.drSlope[index] > 999.99) {
        lpFcid.drSlope[index] = 999.99;
      }
      lpFcid.lesionInhib[index] = (new Double(lesionInhibText[index].getText())).doubleValue();
      if(lpFcid.lesionInhib[index] < 0.0) {
        lpFcid.lesionInhib[index] = 0.0;
      } else if(lpFcid.lesionInhib[index] > 999.99) {
        lpFcid.lesionInhib[index] = 999.99;
      }
      lpFcid.sporeInhib[index] = (new Double(sporeInhibText[index].getText())).doubleValue();
      if(lpFcid.sporeInhib[index] < 0.0) {
        lpFcid.sporeInhib[index] = 0.0;
      } else if(lpFcid.sporeInhib[index] > 999.99) {
        lpFcid.sporeInhib[index] = 999.99;
      }
      lpFcid.mutationRate[index] = (new Double(mutationRateText[index].getText())).doubleValue();
      if(lpFcid.mutationRate[index] < 0.0) {
        lpFcid.mutationRate[index] = 0.0;
      } else if(lpFcid.mutationRate[index] > 1.0) {
        lpFcid.mutationRate[index] = 1.0;
      }
      lpFcid.resistanceLevel[index] = (new Double(resistanceLevelText[index].getText())).doubleValue();
      if(lpFcid.resistanceLevel[index] < 0.0) {
        lpFcid.resistanceLevel[index] = 0.0;
      } else if(lpFcid.resistanceLevel[index] > 999.9) {
        lpFcid.resistanceLevel[index] = 999.9;
      }
      lpFcid.sporeSurvival[index] = (new Double(sporeSurvivalText[index].getText())).doubleValue();
      if(lpFcid.sporeSurvival[index] < 0.0) {
        lpFcid.sporeSurvival[index] = 0.0;
      } else if(lpFcid.sporeSurvival[index] > 1.0) {
        lpFcid.sporeSurvival[index] = 1.0;
      }
      lpFcid.lesionDevel[index] = (new Double(lesionDevelText[index].getText())).doubleValue();
      if(lpFcid.lesionDevel[index] < 0.0) {
        lpFcid.lesionDevel[index] = 0.0;
      } else if(lpFcid.lesionDevel[index] > 1.0) {
        lpFcid.lesionDevel[index] = 1.0;
      }
      lpFcid.sporulation[index] = (new Double(sporulationText[index].getText())).doubleValue();
      if(lpFcid.sporulation[index] < 0.0) {
        lpFcid.sporulation[index] = 0.0;
      } else if(lpFcid.sporulation[index] > 1.0) {
        lpFcid.sporulation[index] = 1.0;
      }

      // set fungus name applet-wide
      fcides[index] = lpFcid.fungicideName[index];
    } catch (Exception e) {
    }
  }

  public void resistanceOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(6,2));
    dataDialog.setTitle("Fungicide Resistance");

    int cols = 10;
    resistText = new TextField[5];

    StringBuffer buff = new StringBuffer();
    for(int i = 1; i < resistText.length; i++) {
      //resistText[i] = new TextField(String.valueOf(lpFcid.pctRes[i]), cols);
      buff = new StringBuffer();
      df3.format(lpFcid.pctRes[i], buff, new FieldPosition(0));
      resistText[i] = new TextField(buff.toString(), cols);
      dataDialog.add(new Label(fcides[i], Label.RIGHT));
      dataDialog.add(resistText[i]);
    }

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));

    saveResistance = new Button("Save Settings");
    saveResistance.addActionListener(this);
    dataDialog.add(new Label(""));
    dataDialog.add(saveResistance);

    dataDialog.setSize(320, 200);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveResistance() {
    try {
      for(int i = 1; i < resistText.length; i++) {
        lpFcid.pctRes[i] = (new Double(resistText[i].getText())).doubleValue();
        if(lpFcid.pctRes[i] < 0.0) {
          lpFcid.pctRes[i] = 0.0;
        } else if(lpFcid.pctRes[i] > 100.0) {
          lpFcid.pctRes[i] = 100.0;
        }
        originalPctRes[i] = lpFcid.pctRes[i];
      }

      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      panel.validate();
    } catch (Exception e) {
    }
  }

  public void inoculumOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(4,6));
    dataDialog.setTitle("Initial Inoculum");

    int cols = 10;
    saveInoculum = new Button("Save Settings");
    saveInoculum.addActionListener(this);

    StringBuffer buff = new StringBuffer();
    df5.format(inoculumSpores, buff, new FieldPosition(0));
    inoculumSporesText = new TextField(buff.toString(), cols);
    inoculumDaysText = new TextField(String.valueOf(inoculumDays), cols);
    buff = new StringBuffer();
    df5.format(inoculumBlow, buff, new FieldPosition(0));
    inoculumBlowText = new TextField(buff.toString(), cols);

    dataDialog.add(new Label("This season's", Label.RIGHT));
    dataDialog.add(new Label("initial inoculum is", Label.LEFT));
    dataDialog.add(inoculumSporesText);
    dataDialog.add(new Label("spores released over", Label.CENTER));
    dataDialog.add(inoculumDaysText);
    dataDialog.add(new Label("days.", Label.LEFT));

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));

    dataDialog.add(inoculumBlowText);
    dataDialog.add(new Label("spores per day will", Label.RIGHT));
    dataDialog.add(new Label("blow in from other", Label.CENTER));
    dataDialog.add(new Label("areas throughout the", Label.LEFT));
    dataDialog.add(new Label("season."));
    dataDialog.add(new Label(""));

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(saveInoculum);

    dataDialog.setSize(800, 140);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveInoculum() {
    try {
      inoculumSpores = (new Double(inoculumSporesText.getText())).doubleValue();
      if(inoculumSpores < 0.0) {
        inoculumSpores = 0.0;
      } else if(inoculumSpores > 99999.9) {
        inoculumSpores = 99999.9;
      }
      inoculumSporesSetting = inoculumSpores;
      inoculumDays = (int)Math.round((new Double(inoculumDaysText.getText())).doubleValue());
      if(inoculumDays < 0) {
        inoculumDays = 0;
      } else if(inoculumDays > 365) {
        inoculumDays = 365;
      }
      inoculumBlow = (new Double(inoculumBlowText.getText())).doubleValue();
      if(inoculumBlow < 0.0) {
        inoculumBlow = 0.0;
      } else if(inoculumBlow > 9999.9) {
        inoculumBlow = 9999.9;
      }

      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      panel.validate();
    } catch (Exception e) {
    }
  }

  public void lifeCycleOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(12,3));
    dataDialog.setTitle("Fungus Life Cycle");

    int cols = 10;

    saveCycle = new Button("Save Settings");
    saveCycle.addActionListener(this);

    StringBuffer buff = new StringBuffer();

    buff = new StringBuffer();
    df1.format(infectionEff, buff, new FieldPosition(0));
    infectionEffText = new TextField(buff.toString(), cols);
    infEffLabel = new Label("Infection Efficiency", Label.RIGHT);
    infEffLabel.addMouseListener(this);
    dataDialog.add(infEffLabel);
    dataDialog.add(infectionEffText);
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df5.format(latentPeriod, buff, new FieldPosition(0));
    latentPeriodText = new TextField(buff.toString(), cols);
    latentPeriodLabel = new Label("Latent Period", Label.RIGHT);
    latentPeriodLabel.addMouseListener(this);
    dataDialog.add(latentPeriodLabel);
    dataDialog.add(latentPeriodText);
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df5.format(infectiousPeriod, buff, new FieldPosition(0));
    infectiousPeriodText = new TextField(buff.toString(), cols);
    infPeriodLabel = new Label("Infectious Period", Label.RIGHT);
    infPeriodLabel.addMouseListener(this);
    dataDialog.add(infPeriodLabel);
    dataDialog.add(infectiousPeriodText);
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df5.format(sporulationRate, buff, new FieldPosition(0));
    sporulationRateText = new TextField(buff.toString(), cols);
    sporRateLabel = new Label("Sporulation Rate", Label.RIGHT);
    sporRateLabel.addMouseListener(this);
    dataDialog.add(sporRateLabel);
    dataDialog.add(sporulationRateText);
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df2.format(sporeDeposition, buff, new FieldPosition(0));
    sporeDepositionText = new TextField(buff.toString(), cols);
    sporDepLabel = new Label("Spore Deposition", Label.RIGHT);
    sporDepLabel.addMouseListener(this);
    dataDialog.add(sporDepLabel);
    dataDialog.add(sporeDepositionText);
    dataDialog.add(new Label(""));

    lesionLimitText = new TextField(String.valueOf(lesionLimit), cols);
    lesionLimitLabel = new Label("Lesion Limit", Label.RIGHT);
    lesionLimitLabel.addMouseListener(this);
    dataDialog.add(lesionLimitLabel);
    dataDialog.add(lesionLimitText);
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df4.format(overWinteringFactor, buff, new FieldPosition(0));
    overWinteringFactorText = new TextField(buff.toString(), cols);
    overWinterLabel = new Label("Overwintering Factor", Label.RIGHT);
    overWinterLabel.addMouseListener(this);
    dataDialog.add(overWinterLabel);
    dataDialog.add(overWinteringFactorText);
    dataDialog.add(new Label(""));

    dailySurvivalLabel = new Label("Daily Survival Rates:", Label.RIGHT);
    dailySurvivalLabel.addMouseListener(this);
    dataDialog.add(dailySurvivalLabel);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df2.format(sporeSurvivalRate, buff, new FieldPosition(0));
    sporeSurvivalRateText = new TextField(buff.toString(), cols);
    dataDialog.add(new Label("Spores", Label.RIGHT));
    dataDialog.add(sporeSurvivalRateText);
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df2.format(latentLesionRate, buff, new FieldPosition(0));
    latentLesionRateText = new TextField(buff.toString(), cols);
    dataDialog.add(new Label("Latent Lesions", Label.RIGHT));
    dataDialog.add(latentLesionRateText);
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df2.format(sporulatingLesionRate, buff, new FieldPosition(0));
    sporulatingLesionRateText = new TextField(buff.toString(), cols);
    dataDialog.add(new Label("Sporulating Lesions", Label.RIGHT));
    dataDialog.add(sporulatingLesionRateText);
    dataDialog.add(new Label(""));

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(saveCycle);

    dataDialog.setSize(480, 360);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveLifeCycle() {
    try {
      infectionEff = (new Double(infectionEffText.getText())).doubleValue();
      if(infectionEff < 0.0) {
        infectionEff = 0.0;
      } else if(infectionEff > 1.0) {
        infectionEff = 1.0;
      }
      latentPeriod = (new Double(latentPeriodText.getText())).doubleValue();
      if(latentPeriod < 0.0) {
        latentPeriod = 0.0;
      } else if(latentPeriod > 99.9) {
        latentPeriod = 99.9;
      }
      infectiousPeriod = (new Double(infectiousPeriodText.getText())).doubleValue();
      if(infectiousPeriod < 0.0) {
        infectiousPeriod = 0.0;
      } else if(infectiousPeriod > 99.9) {
        infectiousPeriod = 99.9;
      }
      sporulationRate = (new Double(sporulationRateText.getText())).doubleValue();
      if(sporulationRate < 0.0) {
        sporulationRate = 0.0;
      } else if(sporulationRate > 9999.9) {
        sporulationRate = 9999.9;
      }
      sporeDeposition = (new Double(sporeDepositionText.getText())).doubleValue();
      if(sporeDeposition < 0.0) {
        sporeDeposition = 0.0;
      } else if(sporeDeposition > 1.0) {
        sporeDeposition = 1.0;
      }
      lesionLimit = (new Double(lesionLimitText.getText())).doubleValue();
      if(lesionLimit < 0.0) {
        lesionLimit = 0.0;
      }
      overWinteringFactor = (new Double(overWinteringFactorText.getText())).doubleValue();
      if(overWinteringFactor < 0.0) {
        overWinteringFactor = 0.0;
      } else if(overWinteringFactor > 99.99) {
        overWinteringFactor = 99.99;
      }
      sporeSurvivalRate = (new Double(sporeSurvivalRateText.getText())).doubleValue();
      if(sporeSurvivalRate < 0.0) {
        sporeSurvivalRate = 0.0;
      } else if(sporeSurvivalRate > 1.0) {
        sporeSurvivalRate = 1.0;
      }
      latentLesionRate = (new Double(latentLesionRateText.getText())).doubleValue();
      if(latentLesionRate < 0.0) {
        latentLesionRate = 0.0;
      } else if(latentLesionRate > 1.0) {
        latentLesionRate = 1.0;
      }
      sporulatingLesionRate = (new Double(sporulatingLesionRateText.getText())).doubleValue();
      if(sporulatingLesionRate < 0.0) {
        sporulatingLesionRate = 0.0;
      } else if(sporulatingLesionRate > 1.0) {
        sporulatingLesionRate = 1.0;
      }

      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      panel.validate();
    } catch (Exception e) {
    }
  }

  public void damageOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(3,3));
    dataDialog.setTitle("Damage");

    int cols = 10;

    damageConstantText = new TextField(String.valueOf(damageConstant), cols);
    dataDialog.add(new Label("Damage Constant", Label.RIGHT));
    dataDialog.add(damageConstantText);
    dataDialog.add(new Label(""));

    StringBuffer buff = new StringBuffer();
    df2.format(maxCropLoss, buff, new FieldPosition(0));
    maxCropLossText = new TextField(buff.toString(), cols);
    dataDialog.add(new Label("Maximum Crop Loss", Label.RIGHT));
    dataDialog.add(maxCropLossText);
    dataDialog.add(new Label(""));

    saveDamage = new Button("Save Settings");
    saveDamage.addActionListener(this);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(saveDamage);

    dataDialog.setSize(360, 110);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveDamage() {
    try {
      damageConstant = (new Double(damageConstantText.getText())).doubleValue();
      if(damageConstant < 1.0) {
        damageConstant = 1.0;
      } else if(damageConstant > 9.99E9) {
        damageConstant = 9.99E9;
      }
      maxCropLoss = (new Double(maxCropLossText.getText())).doubleValue();
      if(maxCropLoss < 0.0) {
        maxCropLoss = 0.0;
      } else if(maxCropLoss > 1.0) {
        maxCropLoss = 1.0;
      }

      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      frame.validate();
    } catch (Exception e) {
    }
  }

  public void lengthOfSeasonOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(2,3));
    dataDialog.setTitle("Length of Season");

    int cols = 10;

    seasonLengthText = new TextField(String.valueOf(seasonLength), cols);
    saveSeason = new Button("Save Settings");
    saveSeason.addActionListener(this);

    dataDialog.add(new Label("Length Of Season", Label.RIGHT));
    dataDialog.add(seasonLengthText);
    dataDialog.add(new Label("days", Label.LEFT));

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(saveSeason);

    dataDialog.setSize(320, 100);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveLengthOfSeason() {
    try {
      seasonLength = (int)Math.round((new Double(seasonLengthText.getText())).doubleValue());
      if(seasonLength < 1) {
        seasonLength = 1;
      } else if(seasonLength > 365) {
        seasonLength = 365;
      }
      scroll.setMaximum(seasonLength);

      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      frame.validate();
    } catch (Exception e) {
    }
  }

  public void startingDateOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(2,3));
    dataDialog.setTitle("Starting Date");

    int cols = 10;

    startingDateText = new TextField(startingDateString, cols);
    saveStartingDate = new Button("Save Settings");
    saveStartingDate.addActionListener(this);

    dataDialog.add(new Label("Starting Date", Label.RIGHT));
    dataDialog.add(startingDateText);
    dataDialog.add(new Label(""));

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(saveStartingDate);

    dataDialog.setSize(320, 100);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveStartingDate() {
    try {
      startingDateString = startingDateText.getText();
      today = sdf.parse(startingDateString, new ParsePosition(0));
      StringBuffer buff = new StringBuffer("Today is ");
      sdf.format(today, buff, new FieldPosition(0));
      buff.append(" of season " + String.valueOf(seasonNumber));
      dateLabel.setText(buff.toString());

      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      frame.validate();
    } catch (Exception e) {
    }
  }

  public void costsPriceOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(4,3));
    dataDialog.setTitle("Costs/Price");

    int cols = 10;

    StringBuffer buff = new StringBuffer();
    df4.format(applicationCost, buff, new FieldPosition(0));
    applicationCostText = new TextField(buff.toString(), cols);
    appCostLabel = new Label("Application Cost", Label.RIGHT);
    appCostLabel.addMouseListener(this);
    dataDialog.add(appCostLabel);
    dataDialog.add(applicationCostText);
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df4.format(fixedCosts, buff, new FieldPosition(0));
    fixedCostsText = new TextField(buff.toString(), cols);
    fixedCostLabel = new Label("Fixed Costs", Label.RIGHT);
    fixedCostLabel.addMouseListener(this);
    dataDialog.add(fixedCostLabel);
    dataDialog.add(fixedCostsText);
    dataDialog.add(new Label(""));

    buff = new StringBuffer();
    df4.format(maxRevenue, buff, new FieldPosition(0));
    maxRevenueText = new TextField(buff.toString(), cols);
    maxRevLabel = new Label("Maximum Revenue", Label.RIGHT);
    maxRevLabel.addMouseListener(this);
    dataDialog.add(maxRevLabel);
    dataDialog.add(maxRevenueText);
    dataDialog.add(new Label(""));

    saveCostsPrice = new Button("Save Settings");
    saveCostsPrice.addActionListener(this);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(saveCostsPrice);

    dataDialog.setSize(320, 160);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveCostsPrice() {
    try {
      applicationCost = (new Double(applicationCostText.getText())).doubleValue();
      if(applicationCost < 0.0) {
        applicationCost = 0.0;
      } else if(applicationCost > 99999.99) {
        applicationCost = 99999.99;
      }
      fixedCosts = (new Double(fixedCostsText.getText())).doubleValue();
      if(fixedCosts < 0.0) {
        fixedCosts = 0.0;
      } else if(fixedCosts > 99999.99) {
        fixedCosts = 99999.99;
      }
      maxRevenue = (new Double(maxRevenueText.getText())).doubleValue();
      if(maxRevenue < 0.0) {
        maxRevenue = 0.0;
      } else if(maxRevenue > 99999.99) {
        maxRevenue = 99999.99;
      }

      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      frame.validate();
    } catch (Exception e) {
    }
  }

  public void susceptibilityOptions() {
    dataDialog.removeAll();
    dataDialog.setLayout(new GridLayout(13,5));
    dataDialog.setTitle("Plant Susceptibility");

    int cols = 10;

    dataDialog.add(new Label("Day"));
    dataDialog.add(new Label("Susceptibility"));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label("Day"));
    dataDialog.add(new Label("Susceptibility"));

    int modFactor = (int)(seasonLength / 20.0);

    StringBuffer buff = new StringBuffer();
    for(int i = 0; i < 10; i++) {
      buff = new StringBuffer();
      df5.format(Math.round(1000.0 * susceptValues[i]) / 10.0, buff, new FieldPosition(0));
      susceptValuesText[i] = new TextField(buff.toString(), cols);
      susceptValuesText[i].addFocusListener(this);
      dataDialog.add(new Label(String.valueOf((i + 1) * modFactor)));
      dataDialog.add(susceptValuesText[i]);
      dataDialog.add(new Label(""));
      dataDialog.add(new Label(String.valueOf((i + 11) * modFactor)));
      buff = new StringBuffer();
      df5.format(Math.round(1000.0 * susceptValues[i + 10]) / 10.0, buff, new FieldPosition(0));
      susceptValuesText[i + 10] = new TextField(buff.toString(), cols);
      susceptValuesText[i + 10].addFocusListener(this);
      dataDialog.add(susceptValuesText[i + 10]);
    }

    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));

    applySuscept = new Button("Auto Apply");
    applySuscept.addActionListener(this);
    saveSuscept = new Button("Save Settings");
    saveSuscept.addActionListener(this);
    buff = new StringBuffer();
    df5.format(autoApply, buff, new FieldPosition(0));
    applySusceptText = new TextField(buff.toString(), cols);
    applySusceptText.addFocusListener(this);

    dataDialog.add(applySusceptText);
    dataDialog.add(applySuscept);
    dataDialog.add(new Label(""));
    dataDialog.add(new Label(""));
    dataDialog.add(saveSuscept);

    dataDialog.setSize(640, 440);
    dataDialog.show();
    dataDialog.invalidate();
    frame.validate();
  }

  public void saveSusceptibility() {
    try {
      for(int i = 0; i < susceptValuesText.length; i++) {
        susceptValues[i] = (new Double(susceptValuesText[i].getText())).doubleValue() / 100.0;
        if(susceptValues[i] < 0.0) {
          susceptValues[i] = 0.0;
        } else if(susceptValues[i] > 1.0) {
          susceptValues[i] = 1.0;
        }
      } // end for i

      dataDialog.hide();
      panel.repaint();
      panel.invalidate();
      frame.validate();
    } catch (Exception e) {
    }
  }

  public void applySuscept() {
    try {
      autoApply = Math.round(10.0 * (new Double(applySusceptText.getText())).doubleValue()) / 1000.0;
      for(int i = 0; i < susceptValues.length; i++) {
        susceptValues[i] = autoApply;
        if(susceptValues[i] < 0.0) {
          susceptValues[i] = 0.0;
        } else if(susceptValues[i] > 1.0) {
          susceptValues[i] = 1.0;
        }
      } // end for i
      autoApply *= 100.0;

      susceptibilityOptions();
    } catch (Exception e) {
    }
  }

  public void createPieChart() {
    pieDialog.show();
    pieDialog.repaint();
    pieDialog.invalidate();
    frame.validate();
  }

  public void paintPie(Graphics g) {
    g.clearRect(0, 0, 800, 600);
    int angle1 = (int)Math.round(360 * profitLoss / revenue);
    g.setColor(Color.green);
    g.fillArc(75, 75, 300, 300, 0, angle1);
    int angle2 = (int)Math.round(360 * fixedCosts / revenue);
    g.setColor(Color.red);
    g.fillArc(75, 75, 300, 300, angle1, angle2);
    int angle3 = (int)Math.round(360 * (totalCost - fixedCosts) / revenue);
    g.setColor(Color.blue);
    g.fillArc(75, 75, 300, 300, angle1 + angle2, angle3);

    // label pie chart
    g.setColor(Color.green);
    g.drawString("Profit", 500, 150);
    g.setColor(Color.blue);
    g.drawString("Fungicide Costs", 500, 175);
    g.setColor(Color.red);
    g.drawString("Fixed Costs", 500, 200);

    g.setColor(Color.black);
    g.drawString("Total Revenue = " + currencyFormat.format(revenue), 500, 300);
    g.drawString("    Total Costs = " + currencyFormat.format(totalCost), 500, 325);
    g.drawString("---------------------------", 500, 350);
    g.drawString("              Profit = " + currencyFormat.format(profitLoss), 500, 375);
  }

  public void initCalculations() {
    // reset graphing components
    residue1xdata = new Vector();
    residue1ydata = new Vector();
    residue2xdata = new Vector();
    residue2ydata = new Vector();
    residue3xdata = new Vector();
    residue3ydata = new Vector();
    residue4xdata = new Vector();
    residue4ydata = new Vector();

    resistance1xdata = new Vector();
    resistance1ydata = new Vector();
    resistance2xdata = new Vector();
    resistance2ydata = new Vector();
    resistance3xdata = new Vector();
    resistance3ydata = new Vector();
    resistance4xdata = new Vector();
    resistance4ydata = new Vector();

    lesionsxdata = new Vector();
    lesionsydata = new Vector();
    pctLossxdata = new Vector();
    pctLossydata = new Vector();

    xPos = xOrigin;
    yPos = yOrigin;
    today = sdf.parse(startingDateString, new ParsePosition(0));
    StringBuffer buff = new StringBuffer("Today is ");
    sdf.format(today, buff, new FieldPosition(0));
    buff.append(" of season " + String.valueOf(seasonNumber));
    dateLabel.setText(buff.toString());

    // subpopulation specific objects
    sporePop = new Stage();
    latentPop = new Stage();
    lesionPop = new Stage();

    // season dependent variables
    damageCalc = 0.0;
    pctLoss = 0.0;
    pCumLoss = 0.0;

    lesionSCF = 1.0;
    newlyDead = 0.0;
    deltaT = 0.1;

    spraysApplied = 0;

    totalFungicideCost = 0.0;
    totalAppCost = 0.0;
    totalCost = 0.0;
    revenue = 0.0;
    profitLoss = 0.0;

    lpFcid.residueF = new double[5];

    inocDose = new double[popSize];
    sporeFitness = new double[popSize];
    latentFitness = new double[popSize];
    lesionFitness = new double[popSize];

    // dynamically set the color bar
    setColorBar();

    // for each class
    for(int c = 0; c < popSize; c++) {
      // initialize subPopulations to 0
      sporePop.population[c].n = 0;
      latentPop.population[c].n = 0;
      lesionPop.population[c].n = 0;

      // assign values to the inocDose and fitness arrays
      inocDose[c] = (inoculumSpores * deltaT / inoculumDays) * sporeDeposition;
      sporeFitness[c] = 1.0;
      latentFitness[c] = 1.0;
      lesionFitness[c] = 1.0;

      // calculations for each fungus
      int nFcid = 0;
      int nMask = 0;
      for(nFcid = nStart, nMask = nFirstMask; nFcid <= nStop; nFcid++, nMask /= 2) {
        if((c & nMask) != 0) {
          inocDose[c] *= lpFcid.pctRes[nFcid] / 100.0;
          sporeFitness[c] *= lpFcid.sporeSurvival[nFcid];
          latentFitness[c] *= lpFcid.lesionDevel[nFcid];
          lesionFitness[c] *= lpFcid.sporulation[nFcid];
        } else {
          inocDose[c] *= 1 - (lpFcid.pctRes[nFcid] / 100.0);
        } // end nClass & nMask
      } // end for nFcid
    } // end for c
  }

  public void doCalculations() {
    int fcideIndex = 0;

    // for each fungus calculate the dose
    int sprayed = 5;
    for(int i = 0; i < numFungicides; i++) {
      if(fChosen[i]) {
        fcideIndex = i + 1;
      } else {
        fcideIndex = 0;
      }
      for(int j = 0; j < dayArray[fcideIndex].length; j++) {
        if((count + 1) == dayArray[fcideIndex][j]) {
          lpFcid.depositF[fcideIndex] = doseArray[fcideIndex][j] * lpFcid.doseDeposit[fcideIndex];
          if(!(fcideIndex == 0)) {
            sprayed = fcideIndex;
          }
        }
      } // end for j
    } // end for i

    if(sprayed < 5 && sprayed > 0) {
      // only increment the number of sprays applied if the fungicide is not "None"
      spraysApplied++;
    }

    // calculate susceptibility of the plant to infection
    double modFactor = seasonLength / 20.0;
    int index1 = (int)(count / modFactor) ;
    int index2 = (int)(count / modFactor) + 1;
    double a = (count / modFactor) - index1;
    if(index2 >= susceptValues.length) {
      index2--;
      index1--;
    }
    // interpolate susceptibility values
    suscept = susceptValues[index1] * (1 - a) + susceptValues[index2] * a;


    // timestep loop (10 timesteps per day)
    for(int step = 0; step < 10; step++) {
      // calculations for each fungus
      for(fcideIndex = 1; fcideIndex <= numFungicides; fcideIndex++) {
        lpFcid.residueF[fcideIndex] += lpFcid.depositF[fcideIndex] - (lpFcid.weatheringRate[fcideIndex] * lpFcid.residueF[fcideIndex] * deltaT);
        if(lpFcid.residueF[fcideIndex] <= 0) {
          lpFcid.residueF[fcideIndex] = 0.0;
          lpFcid.survivalFRes[fcideIndex] = 1.0;
          lpFcid.survivalFSens[fcideIndex] = 1.0;
          lpFcid.inhibLesFRes[fcideIndex] = 0.0;
          lpFcid.inhibLesFSens[fcideIndex] = 0.0;
          lpFcid.inhibSpFRes[fcideIndex] = 0.0;
          lpFcid.inhibSpFSens[fcideIndex] = 0.0;
        } else {
          // approximate the probit curve
          lpFcid.probitF[fcideIndex] = 5.0 + lpFcid.drSlope[fcideIndex] * base10log(lpFcid.residueF[fcideIndex] / lpFcid.sporeMortality[fcideIndex]);
          lpFcid.survivalFSens[fcideIndex] = (1.0 - (1.0 / (1.0 + 19466.6 * Math.exp(-1.97529 * lpFcid.probitF[fcideIndex]))));
          lpFcid.probitF[fcideIndex] = 5.0 + lpFcid.drSlope[fcideIndex] * base10log(lpFcid.residueF[fcideIndex] / lpFcid.sporeMortality[fcideIndex] / lpFcid.resistanceLevel[fcideIndex]);
          lpFcid.survivalFRes[fcideIndex] = (1.0 - (1.0 / (1.0 + 19466.6 * Math.exp(-1.97529 * lpFcid.probitF[fcideIndex]))));

          // fungistatic effects
          lpFcid.inhibLesFSens[fcideIndex] = lpFcid.residueF[fcideIndex] / (lpFcid.lesionInhib[fcideIndex] + lpFcid.residueF[fcideIndex]);
          lpFcid.inhibLesFRes[fcideIndex] = lpFcid.residueF[fcideIndex] / (lpFcid.lesionInhib[fcideIndex] * lpFcid.resistanceLevel[fcideIndex] + lpFcid.residueF[fcideIndex]);
          lpFcid.inhibSpFSens[fcideIndex] = lpFcid.residueF[fcideIndex] / (lpFcid.sporeInhib[fcideIndex] + lpFcid.residueF[fcideIndex]);
          lpFcid.inhibSpFRes[fcideIndex] = lpFcid.residueF[fcideIndex] / (lpFcid.sporeInhib[fcideIndex] * lpFcid.resistanceLevel[fcideIndex] + lpFcid.residueF[fcideIndex]);
        } // end if residueF
        if(step == 0) {
          lpFcid.depositF[fcideIndex] = 0.0;
        }
      } // end for fungus

      // population dynamics
      survivingPopulation = Math.max(0.0, (lesionLimit - totalSLesions) / lesionLimit);
      totalSpores = 0.0;
      totalLLesions = 0.0;
      totalSLesions = 0.0;
      totalDeadLesions = 0.0;

      // calculations for each resistance class
      for(int c = 0; c < popSize; c++) {
        sporePop.population[c].pSurvFcid = 1.0;
        latentPop.population[c].effect = 1.0;
        lesionPop.population[c].effect = 1.0;

        int nFcid = nStart;
        int nMask = nFirstMask;
        // calculations for each fungicide
        while(nFcid <= nStop) {
          if((c & nMask) != 0) {
            sporePop.population[c].pSurvFcid *= lpFcid.survivalFRes[nFcid];
            latentPop.population[c].effect *= (1.0 - lpFcid.inhibLesFRes[nFcid]);
            lesionPop.population[c].effect *= (1.0 - lpFcid.inhibSpFRes[nFcid]);
          } else {
            sporePop.population[c].pSurvFcid *= lpFcid.survivalFSens[nFcid];
            latentPop.population[c].effect *= (1.0 - lpFcid.inhibLesFSens[nFcid]);
            lesionPop.population[c].effect *= (1.0 - lpFcid.inhibSpFSens[nFcid]);
          } // end if nClass & nMask
          nFcid++;
          nMask /= 2;
        } // end while nFcid <= nStop

         // calculate flow rates
        sporePop.population[c].flow = sporePop.population[c].n * infectionEff * suscept;
        latentPop.population[c].flow = latentPop.population[c].n * latentPop.population[c].effect * latentFitness[c] * survivingPopulation / latentPeriod;
        lesionPop.population[c].flow = lesionPop.population[c].n * lesionFitness[c] * lesionPop.population[c].effect * sporulationRate * sporeDeposition;

        // calculate surviving proportions
        sporePop.population[c].pSurvTime = sporeSurvivalRate * sporeFitness[c];
        latentPop.population[c].pSurvTime = latentLesionRate;
        lesionPop.population[c].pSurvTime = sporulatingLesionRate;

        // add inoculum (if appropriate), blowin, and carry out the flow from each stage to the next
        sporePop.population[c].n += (((c == 0) ? inoculumBlow * sporeDeposition : 0) + lesionPop.population[c].flow - sporePop.population[c].flow) * deltaT;
        if(count < inoculumDays) {
          sporePop.population[c].n += inocDose[c];
        } // end if count
        latentPop.population[c].n += (sporePop.population[c].flow - latentPop.population[c].flow) * deltaT;
        lesionPop.population[c].n += latentPop.population[c].flow * deltaT;

        // apply mortalities due to fungicides and other causes
        sporePop.population[c].n -= Math.min((1.0 - sporePop.population[c].pSurvTime * sporePop.population[c].pSurvFcid) * sporePop.population[c].n * deltaT, sporePop.population[c].n);
        latentPop.population[c].n -= Math.min((1.0 - latentPop.population[c].pSurvTime) * latentPop.population[c].n * deltaT, latentPop.population[c].n);
        newlyDead = Math.min((1.0 - lesionPop.population[c].pSurvTime) / infectiousPeriod * lesionPop.population[c].n * deltaT, lesionPop.population[c].n);
        lesionPop.population[c].n -= newlyDead;

        // increment totals
        totalSpores += sporePop.population[c].n;
        totalLLesions += latentPop.population[c].n;
        totalSLesions += lesionPop.population[c].n;
        totalDeadLesions += newlyDead;
      } // end for each c

      // calculate percent resistance for each fungicide
      int nFcid = nStart;
      int nMask = nFirstMask;
      while(nFcid <= nStop) {
        lpFcid.pctRes[nFcid] = 0.0;
        for(int c = 0; c < popSize; c++) {
          if((c & nMask) != 0) {
            lpFcid.pctRes[nFcid] += lesionPop.population[c].n;
          } // end if c & nMask != 0
        } // end for c
        if(totalSLesions > pctResCalcLevel) {
          lpFcid.pctRes[nFcid] = lpFcid.pctRes[nFcid] / totalSLesions;
        } else {
          lpFcid.pctRes[nFcid] = 0.0;
        }
        lpFcid.pctRes[nFcid] *= 100;
        lpFcid.pctRes[nFcid] = Math.max(lpFcid.pctRes[nFcid], lpFcid.mutationRate[nFcid]);
        nFcid++;
        nMask /= 2;
      } // end while nFcid <= nStop

      // damage as a function of total lesions
      pCumLoss += maxCropLoss * (1.0 - pCumLoss) * deltaT * ((totalSLesions + totalDeadLesions) / (totalSLesions + totalDeadLesions + damageConstant));

    } // end for step

    // compute cumulative crop loss
    pctLoss = 100 * pCumLoss;
    visibleLesions = totalSLesions + totalDeadLesions;

    // increment total fungicide cost
    if(sprayed < 5) {
      totalFungicideCost += lpFcid.fungicideCost[sprayed];
    }

    /*
    for(fcideIndex = 1; fcideIndex <= numFungicides; fcideIndex++) {
      while(lpFcid.residueF[fcideIndex] * lpFcid.residueSCF[fcideIndex] > 50.0) {
        lpFcid.residueSCF[fcideIndex] = lpFcid.residueSCF[fcideIndex] / 10.0;
      } // end while residueSCF
    } // end for fungus
    */

    while(visibleLesions / lesionSCF > 100.0) {
      lesionSCF *= 10.0;
    } // end while visibleLesions

  } // end doCalculations()

  public double base10log(double aValue) {
    return Math.log(aValue) / Math.log(10.0);
  }

  public void setDefaultPreset() {
    fcides = new String[]{
      "None", "Dithiocarbamate", "Dicarboximide", "Benzimidazole", "Sterol-inhibitor"
    };

    whichFungicide = fcides[1];
    dayArray = new int[][]{
      {0, 0, 0, 0, 0, 1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99},
      {0, 0, 0, 0, 0, 1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99},
      {0, 0, 0, 0, 0, 1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 15, 29, 43, 57, 71, 85, 99},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 15, 29, 43, 57, 71, 85, 99}
    };
    doseArray = new double[][]{
      {0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0},
      {0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0},
      {0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0},
      {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5},
      {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}
    };

    // lpFcid stuff here
    whichCharacter = fcides[1];
    lpFcid = new FungicideConstants();

    originalPctRes = new double[]{
      lpFcid.pctRes[0], lpFcid.pctRes[1], lpFcid.pctRes[2], lpFcid.pctRes[3], lpFcid.pctRes[4]
    };

    inoculumSpores = 5000;
    inoculumSporesSetting = 5000;
    inoculumDays = 35;
    inoculumBlow = 0;

    infectionEff = 0.1;
    latentPeriod = 10;
    infectiousPeriod = 35;
    sporulationRate = 6000;
    sporeDeposition = 0.0005;
    lesionLimit = 15000000;
    overWinteringFactor = 3;
    sporeSurvivalRate = 0.5;
    latentLesionRate = 0.9;
    sporulatingLesionRate = 0.99;

    damageConstant = 680000;
    maxCropLoss = 0.08;
    susceptValues = new double[]{
      1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
      1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
    };

    seasonLength = 140;
    scroll.setMaximum(seasonLength);

    startingDateString = "June 1";
    today = sdf.parse(startingDateString, new ParsePosition(0));

    applicationCost = 8.0;
    fixedCosts = 880.0;
    maxRevenue = 2000.0;
  }

  public class Population {
    double n; // subpopulation size
    double flow; // flow rate to next stage
    double pSurvFcid; // proportion surviving fungicidal effects
    double pSurvTime; // surviving proportion of stage before application of fungicide
    double effect; // fungicide effect on population -- 0 to 1

    public Population() {
      // create new Population object
    }
  }

  public class Stage {
    Population[] population = new Population[]{
      new Population(), new Population(), new Population(), new Population(),
      new Population(), new Population(), new Population(), new Population(),
      new Population(), new Population(), new Population(), new Population(),
      new Population(), new Population(), new Population(), new Population(),
    };

    public Stage() {
      // create new Stage object
    }
  }

  public class FungicideConstants {
    // fungicide constants
    String[] fungicideName = new String[]{fcides[0], fcides[1], fcides[2], fcides[3], fcides[4]};
    double[] fungicideCost = new double[]{0.0, 2.0, 3.0, 5.0, 10.0};
    double[] doseDeposit = new double[]{0.0, 1.0, 5.0, 5.0, 5.0};
    double[] weatheringRate = new double[]{0.0, 0.54, 0.2, 0.15, 0.15};
    double[] sporeMortality = new double[]{10.0, 0.11, 1.25, 1.0, 0.75};
    double[] drSlope = new double[]{0.0, 1.13, 3.0, 3.0, 1.0};
    double[] lesionInhib = new double[]{10.0, 0.11, 1.25, 1.0, 0.75};
    double[] sporeInhib = new double[]{10.0, 0.11, 1.25, 1.0, 0.75};
    double[] mutationRate = new double[]{0.0, 0.0, 0.0001, 0.0001, 0.0001};
    double[] resistanceLevel = new double[]{1.0, 1.0, 100.0, 100.0, 10.0};
    double[] sporeSurvival = new double[]{1.0, 1.0, 0.9, 1.0, 0.95};
    double[] lesionDevel = new double[]{1.0, 1.0, 0.9, 1.0, 0.95};
    double[] sporulation = new double[]{1.0, 1.0, 0.9, 1.0, 0.95};

    // fungicide variables
    double[] depositF = new double[5];
    double[] residueF = new double[5];
    double[] probitF = new double[5];
    double[] survivalFRes = new double[5];
    double[] inhibLesFRes = new double[5];
    double[] inhibSpFRes = new double[5];
    double[] survivalFSens = new double[5];
    double[] inhibLesFSens = new double[5];
    double[] inhibSpFSens = new double[5];
    double[] residueSCF = new double[]{2.0, 2.0, 2.0, 2.0, 2.0};
    double[] pctRes = new double[]{0.0, 0.0, 0.0001, 0.0001, 0.0001};

    public FungicideConstants() {
      // create new FungicideConstants object
    }
  }

  public class DataRecord {
    public Vector currentDay = new Vector();
    public Vector currentSuscept = new Vector();
    public Vector currentVisibleLesions = new Vector();
    public Vector currentPercentLoss = new Vector();
    public Vector residue1 = new Vector();
    public Vector resistance1 = new Vector();
    public Vector residue2 = new Vector();
    public Vector resistance2 = new Vector();
    public Vector residue3 = new Vector();
    public Vector resistance3 = new Vector();
    public Vector residue4 = new Vector();
    public Vector resistance4 = new Vector();

    // year end summary vectors
    public Vector endYearNumber = new Vector();
    public Vector activeLesions = new Vector();
    public Vector pctResFungicideOne = new Vector();
    public Vector pctResFungicideTwo = new Vector();
    public Vector pctResFungicideThree = new Vector();
    public Vector pctResFungicideFour = new Vector();
    public Vector endYearProfit = new Vector();

    public DataRecord() {
      // create new DataRecord object
    }
  }
}
