/*
To do Rhodes' modeling - 7/98 EFG
Interface tweaking - 10/98 EFG
Modified - 01/99 DR
*/

import java.awt.*;
import java.applet.Applet;

public class model extends Applet
{
TextField  textA1, textA2, textB1, textB2, textB3, textB4, textC1, textC2, textC3, textC4, textD1, textD2, textD3, textD4;
TextField  textB5, textB6, textB7, textB8, textC5, textC6, textC7, textC8, textD5, textD6, textD7, textD8;
TextField  textTimeScale;
TextField  textChaseTime;
TextField  textMy1;
TextField  textMy2;
Label      endXAxis1, endXAxis2;
Label      endYAxis1, endYAxis2;
Button     bDoGraph;
Graph		isotopeGraph, poolGraph;
static final int GraphSize = 200;

public void init() {

// Arrange the user interface using a gridbag.
GridBagConstraints gbc;
GridBagLayout  gb;
gb = new GridBagLayout();
setLayout(gb); // set the layout for the whole applet

// add the data entry fields
Label labelA1 = new Label("A1:");
textA1 = new TextField("90", 6);
Label labelA2 = new Label("A2:");
textA2 = new TextField("1", 6);
Label labelB1 = new Label("B1:");
textB1 = new TextField("0", 6);
Label labelB2 = new Label("B2:");
textB2 = new TextField("500", 6);
Label labelB3 = new Label("B3:");
textB3 = new TextField("100", 6);
Label labelB4 = new Label("B4:");
textB4 = new TextField("102", 6);
Label labelB5 = new Label("B5:");
textB5 = new TextField("0", 6);
Label labelB6 = new Label("B6:");
textB6 = new TextField("100", 6);
Label labelB7 = new Label("B7:");
textB7 = new TextField("2", 6);
Label labelB8 = new Label("B8:");
textB8 = new TextField("2", 6);
Label labelC1 = new Label("C1:");
textC1 = new TextField("0", 6);
Label labelC2 = new Label("C2:");
textC2 = new TextField("400", 6);
Label labelC3 = new Label("C3:");
textC3 = new TextField("60", 6);
Label labelC4 = new Label("C4:");
textC4 = new TextField("62", 6);
Label labelC5 = new Label("C5:");
textC5 = new TextField("0", 6);
Label labelC6 = new Label("C6:");
textC6 = new TextField("100", 6);
Label labelC7 = new Label("C7:");
textC7 = new TextField("2", 6);
Label labelC8 = new Label("C8:");
textC8 = new TextField("2", 6);
Label labelD1 = new Label("D1:");
textD1 = new TextField("0", 6);
Label labelD2 = new Label("D2:");
textD2 = new TextField("300", 6);
Label labelD3 = new Label("D3:");
textD3 = new TextField("40", 6);
Label labelD4 = new Label("D4:");
textD4 = new TextField("42", 6);
Label labelD5 = new Label("D5:");
textD5 = new TextField("0", 6);
Label labelD6 = new Label("D6:");
textD6 = new TextField("100", 6);
Label labelD7 = new Label("D7:");
textD7 = new TextField("2", 6);
Label labelD8 = new Label("D8:");
textD8 = new TextField("2", 6);
Label labelTime = new Label("TS:");
textTimeScale = new TextField("120.0", 6);
Label labelChase = new Label("TC:");
textChaseTime = new TextField("61", 6);
Label labelMA = new Label("MA:");
textMy1 = new TextField("100.0", 6);
Label labelMP = new Label("MP:");
textMy2 = new TextField("1000.0", 6);
Label gLabel1 = new Label("Isotope Abundance");
Label xLabel1 = new Label("Time (min)");
Label yLabel1 = new Label("Atom %");
Label startXAxis1 = new Label ("0");
Label startYAxis1 = new Label ("0");
endXAxis1 = new Label (textTimeScale.getText());
endYAxis1 = new Label (textMy1.getText());
isotopeGraph = new Graph(GraphSize, GraphSize);
isotopeGraph.graphImage = blankGraph(GraphSize, GraphSize);
bDoGraph = new Button ("Start");
Label gLabel2 = new Label("Pool Size");
Label xLabel2 = new Label("Time (min)");
Label yLabel2 = new Label("nmol.gfw(-1)");
Label startXAxis2 = new Label ("0");
Label startYAxis2 = new Label ("0");
endXAxis2 = new Label (textTimeScale.getText());
endYAxis2 = new Label (textMy2.getText());
poolGraph = new Graph(GraphSize, GraphSize);
poolGraph.graphImage = blankGraph(GraphSize, GraphSize);

gbc = new GridBagConstraints();
gbc.gridx = gbc.gridy = 0;
gb.setConstraints(labelA1,  gbc);
add(labelA1);
gbc.gridy = 1;
gb.setConstraints(labelA2,  gbc);
add(labelA2);
gbc.gridy = 2;
gb.setConstraints(labelTime,  gbc);
add(labelTime);
gbc.gridy = 3;
gb.setConstraints(labelChase,  gbc);
add(labelChase);
gbc.gridy = 4;
gb.setConstraints(labelMA,  gbc);
add(labelMA);
gbc.gridy = 5;
gb.setConstraints(labelMP,  gbc);
add(labelMP);

gbc.gridy = 7;
gbc.anchor = GridBagConstraints.NORTHEAST;
gb.setConstraints(endYAxis1,  gbc);
add(endYAxis1);
gbc.gridy = 9;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridheight = 3;
gb.setConstraints(yLabel1,  gbc);
add(yLabel1);
gbc.gridy = 11;
gbc.gridheight = 1;
gbc.anchor = GridBagConstraints.SOUTHEAST;
gb.setConstraints(startYAxis1,  gbc);
add(startYAxis1);

gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 0;
gb.setConstraints(textA1,  gbc);
add(textA1);
gbc.gridy = 1;
gb.setConstraints(textA2,  gbc);
add(textA2);
gbc.gridy = 2;
gb.setConstraints(textTimeScale,  gbc);
add(textTimeScale);
gbc.gridy = 3;
gb.setConstraints(textChaseTime,  gbc);
add(textChaseTime);
gbc.gridy = 4;
gb.setConstraints(textMy1,  gbc);
add(textMy1);
gbc.gridy = 5;
gb.setConstraints(textMy2,  gbc);
add(textMy2);

gbc.gridy = 6;
gbc.gridwidth = 5;
gb.setConstraints(gLabel1,  gbc);
add(gLabel1);
gbc.gridy = 7;
gbc.gridheight = 5;
gb.setConstraints(isotopeGraph,  gbc);
add(isotopeGraph);
gbc.gridy = 12;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.anchor = GridBagConstraints.NORTHWEST;
gb.setConstraints(startXAxis1,  gbc);
add(startXAxis1);

gbc = new GridBagConstraints();
gbc.gridx = 2;
gbc.gridy = 0;
gb.setConstraints(labelB1,  gbc);
add(labelB1);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelB2,  gbc);
add(labelB2);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelB3,  gbc);
add(labelB3);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelB4,  gbc);
add(labelB4);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelB5,  gbc);
add(labelB5);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelB6,  gbc);
add(labelB6);

gbc.gridy = 12;
gbc.gridwidth = 3;
gb.setConstraints(xLabel1,  gbc);
add(xLabel1);

gbc = new GridBagConstraints();
gbc.gridx = 3;
gbc.gridy = 0;
gb.setConstraints(textB1,  gbc);
add(textB1);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textB2,  gbc);
add(textB2);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textB3,  gbc);
add(textB3);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textB4,  gbc);
add(textB4);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textB5,  gbc);
add(textB5);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textB6,  gbc);
add(textB6);

gbc = new GridBagConstraints();
gbc.gridx = 4;
gbc.gridy = 0;
gb.setConstraints(labelB7,  gbc);
add(labelB7);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelB8,  gbc);
add(labelB8);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelC1,  gbc);
add(labelC1);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelC2,  gbc);
add(labelC2);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelC3,  gbc);
add(labelC3);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelC4,  gbc);
add(labelC4);

gbc = new GridBagConstraints();
gbc.gridx = 5;
gbc.gridy = 0;
gb.setConstraints(textB7,  gbc);
add(textB7);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textB8,  gbc);
add(textB8);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textC1,  gbc);
add(textC1);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textC2,  gbc);
add(textC2);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textC3,  gbc);
add(textC3);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textC4,  gbc);
add(textC4);

gbc.gridy = 12;
gbc.anchor = GridBagConstraints.NORTHEAST;
gb.setConstraints(endXAxis1,  gbc);
add(endXAxis1);

gbc = new GridBagConstraints();
gbc.gridx = 6;
gbc.gridy = 0;
gb.setConstraints(labelC5,  gbc);
add(labelC5);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelC6,  gbc);
add(labelC6);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelC7,  gbc);
add(labelC7);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelC8,  gbc);
add(labelC8);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelD1,  gbc);
add(labelD1);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelD2,  gbc);
add(labelD2);

gbc = new GridBagConstraints();
gbc.gridx = 7;
gbc.gridy = 0;
gb.setConstraints(textC5,  gbc);
add(textC5);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textC6,  gbc);
add(textC6);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textC7,  gbc);
add(textC7);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textC8,  gbc);
add(textC8);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textD1,  gbc);
add(textD1);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textD2,  gbc);
add(textD2);

gbc = new GridBagConstraints();
gbc.gridx = 8;
gbc.gridy = 0;
gb.setConstraints(labelD3,  gbc);
add(labelD3);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelD4,  gbc);
add(labelD4);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelD5,  gbc);
add(labelD5);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelD6,  gbc);
add(labelD6);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelD7,  gbc);
add(labelD7);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(labelD8,  gbc);
add(labelD8);

gbc.gridy = 7;
gbc.anchor = GridBagConstraints.NORTHEAST;
gb.setConstraints(endYAxis2,  gbc);
add(endYAxis2);
gbc.gridy = 9;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridheight = 3;
gb.setConstraints(yLabel2,  gbc);
add(yLabel2);
gbc.gridheight = 1;
gbc.gridy = 11;
gbc.anchor = GridBagConstraints.SOUTHEAST;
gb.setConstraints(startYAxis2,  gbc);
add(startYAxis2);

gbc = new GridBagConstraints();
gbc.gridx = 9;
gbc.gridy = 0;
gb.setConstraints(textD3,  gbc);
add(textD3);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textD4,  gbc);
add(textD4);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textD5,  gbc);
add(textD5);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textD6,  gbc);
add(textD6);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textD7,  gbc);
add(textD7);
gbc.gridy = GridBagConstraints.RELATIVE;
gb.setConstraints(textD8,  gbc);
add(textD8);

gbc.gridy = 6;
gbc.gridwidth = 5;
gb.setConstraints(gLabel2,  gbc);
add(gLabel2);
gbc.gridy = 7;
gbc.gridheight = 5;
gb.setConstraints(poolGraph,  gbc);
add(poolGraph);
gbc.gridy = 12;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.anchor = GridBagConstraints.NORTHWEST;
gb.setConstraints(startXAxis2,  gbc);
add(startXAxis2);


gbc = new GridBagConstraints();
gbc.gridx = 10;
gbc.gridy = 12;
gbc.gridwidth = 3;
gb.setConstraints(xLabel2,  gbc);
add(xLabel2);

gbc.gridx = 6;
gbc.gridy = 10;
gbc.gridwidth = 1;
gb.setConstraints(bDoGraph,  gbc);
add(bDoGraph);

gbc.gridx = 13;
gbc.gridy = 12;
gbc.anchor = GridBagConstraints.NORTHEAST;
gb.setConstraints(endXAxis2,  gbc);
add(endXAxis2);


}

/*
public void update (Graphics g) { paint(g); }

public void paint (Graphics g) {
g.drawImage (graphImage, 0, 0, this);
}

public void run () {
repaint();
}*/

public boolean action(Event e, Object arg) {
if (e.target == bDoGraph) {
doGraph();
}
else
System.out.println("Unrecognized event");

return super.action(e, arg);
}

public void doGraph () {
bDoGraph.disable();

float A1 = floatFromTextField(textA1);
float A2 = floatFromTextField(textA2);
float B1 = floatFromTextField(textB1);
float B2 = floatFromTextField(textB2);
float B3 = floatFromTextField(textB3);
float B4 = floatFromTextField(textB4);
float B5 = floatFromTextField(textB5);
float B6 = floatFromTextField(textB6);
float B7 = floatFromTextField(textB7);
float B8 = floatFromTextField(textB8);
float C1 = floatFromTextField(textC1);
float C2 = floatFromTextField(textC2);
float C3 = floatFromTextField(textC3);
float C4 = floatFromTextField(textC4);
float C5 = floatFromTextField(textC5);
float C6 = floatFromTextField(textC6);
float C7 = floatFromTextField(textC7);
float C8 = floatFromTextField(textC8);
float D1 = floatFromTextField(textD1);
float D2 = floatFromTextField(textD2);
float D3 = floatFromTextField(textD3);
float D4 = floatFromTextField(textD4);
float D5 = floatFromTextField(textD5);
float D6 = floatFromTextField(textD6);
float D7 = floatFromTextField(textD7);
float D8 = floatFromTextField(textD8);

float timeScale = floatFromTextField(textTimeScale);
float chaseTime = floatFromTextField(textChaseTime);
float Y1 = floatFromTextField(textMy1);
float Y2 = floatFromTextField(textMy2);

endXAxis1.setText(textTimeScale.getText());
endXAxis2.setText(textTimeScale.getText());
endYAxis1.setText(textMy1.getText());
endYAxis2.setText(textMy2.getText());

isotopeGraph.graphImage = blankGraph(GraphSize, GraphSize);
poolGraph.graphImage = blankGraph(GraphSize, GraphSize);

float t;
float Z = timeScale / 2000;
for (t=0; t <= timeScale; t = t + Z) {
if (t > chaseTime) {
A1 = A2;
}
if (B3>0) { B1 = ((B1*B2)+(A1*Z*B3))/(B2+(Z*B3)); }
if (B3>0) { B2 = B2+(Z*B3); }
if (B4>0) { B1 = ((B1*B2)-(B1*Z*B4))/(B2-(Z*B4)); }
if (B4>0) { B2 = B2-(Z*B4); }
if (B7>0) { B5 = ((B5*B6)+(B1*Z*B7))/(B6+(Z*B7)); }
if (B7>0) { B6 = B6+(Z*B7); }
if (B8>0) { B5 = ((B5*B6)-(B5*Z*B8))/(B6-(Z*B8)); }
if (B8>0) { B6 = B6-(Z*B8); }
if (B8>0) { B1 = ((B1*B2)+(B5*Z*B8))/(B2+(Z*B8)); }
if (B8>0) { B2 = B2+(Z*B8); }
if (C3>0) { C1 = ((C1*C2)+(B1*Z*C3))/(C2+(Z*C3)); }
if (C3>0) { C2 = C2+(Z*C3); }
if (C4>0) { C1 = ((C1*C2)-(C1*Z*C4))/(C2-(Z*C4)); }
if (C4>0) { C2 = C2-(Z*C4); }
if (C7>0) { C5 = ((C5*C6)+(C1*Z*C7))/(C6+(Z*C7)); }
if (C7>0) { C6 = C6+(Z*C7); }
if (C8>0) { C5 = ((C5*C6)-(C5*Z*C8))/(C6-(Z*C8)); }
if (C8>0) { C6 = C6-(Z*C8); }
if (C8>0) { C1 = ((C1*C2)+(C5*Z*C8))/(C2+(Z*C8)); }
if (C8>0) { C2 = C2+(Z*C8); }
if (D3>0) { D1 = ((D1*D2)+(C1*Z*D3))/(D2+(Z*D3)); }
if (D3>0) { D2 = D2+(Z*D3); }
if (D4>0) { D1 = ((D1*D2)-(D1*Z*D4))/(D2-(Z*D4)); }
if (D4>0) { D2 = D2-(Z*D4); }
if (D7>0) { D5 = ((D5*D6)+(D1*Z*D7))/(D6+(Z*D7)); }
if (D7>0) { D6 = D6+(Z*D7); }
if (D8>0) { D5 = ((D5*D6)-(D5*Z*D8))/(D6-(Z*D8)); }
if (D8>0) { D6 = D6-(Z*D8); }
if (D8>0) { D1 = ((D1*D2)+(D5*Z*D8))/(D2+(Z*D8)); }
if (D8>0) { D2 = D2+(Z*D8); }
if (B2<0) { break; }
if (C2<0) { break; }
if (D2<0) { break; }
if (B6<0) { break; }
if (C6<0) { break; }
if (D6<0) { break; }

isotopeGraph.graphImage = addPoint(isotopeGraph.graphImage, (int) ((t / timeScale) * GraphSize), GraphSize - ((int) ((A1 / Y1) * GraphSize)), Color.black);
isotopeGraph.graphImage = addPoint(isotopeGraph.graphImage, (int) ((t / timeScale) * GraphSize), GraphSize - ((int) (((((B1*B2)+(B5*B6))/(B2+B6)) / Y1) * GraphSize)), Color.green);
isotopeGraph.graphImage = addPoint(isotopeGraph.graphImage, (int) ((t / timeScale) * GraphSize), GraphSize - ((int) (((((C1*C2)+(C5*C6))/(C2+C6)) / Y1) * GraphSize)), Color.blue);
isotopeGraph.graphImage = addPoint(isotopeGraph.graphImage, (int) ((t / timeScale) * GraphSize), GraphSize - ((int) (((((D1*D2)+(D5*D6))/(D2+D6)) / Y1) * GraphSize)), Color.red);
poolGraph.graphImage = addPoint(poolGraph.graphImage, (int) ((t / timeScale) * GraphSize), GraphSize - ((int) (((B2+B6) / Y2) * GraphSize)), Color.green);
poolGraph.graphImage = addPoint(poolGraph.graphImage, (int) ((t / timeScale) * GraphSize), GraphSize - ((int) (((C2+C6) / Y2) * GraphSize)), Color.blue);
poolGraph.graphImage = addPoint(poolGraph.graphImage, (int) ((t / timeScale) * GraphSize), GraphSize - ((int) (((D2+D6) / Y2) * GraphSize)), Color.red);
//add error checking re: B2, C2, D2, B6, C6, D6 < 0
}


isotopeGraph.repaint();
poolGraph.repaint();
bDoGraph.enable();
repaint();

}




float floatFromTextField (TextField tf) {
String s;
float value;

s = tf.getText();

try {
value = Float.valueOf(s).floatValue();
} catch (Exception e) {
value = (float) 0.0;
}
return value;
}

Image blankGraph (int width, int height) {
Image tempImage;
Graphics tempGr;

tempImage = createImage(width, height);
tempGr = tempImage.getGraphics();



// draw a box around the graph
tempGr.setColor (Color.white);
tempGr.fillRect (0, 0, width, height);
tempGr.setColor (Color.black);
tempGr.drawRect (0, 0, width - 1, height - 1);
// draw ticks marks around edges
int i;
int hinterval = width / 5;
int vinterval = height / 5;
int TickLength = 2;
for (i = 0; i < 4; i++) {
tempGr.drawLine (hinterval * (i + 1), 0, hinterval * (i + 1), TickLength);
tempGr.drawLine (0, vinterval * (i + 1), TickLength, vinterval * (i + 1));
tempGr.drawLine (width - TickLength - 1, hinterval * (i + 1), height - 1, vinterval * (i + 1));
tempGr.drawLine (hinterval * (i + 1), height - TickLength - 1, hinterval * (i + 1), height);
}

return (tempImage);
}


Image addPoint (Image tempImage, int x, int y, Color pointColor) {
Graphics tempGr;

tempGr = tempImage.getGraphics();
tempGr.setColor (pointColor);
tempGr.fillRect (x, y, 1, 1);

return (tempImage);
}

}
class Graph extends Canvas {
public Image graphImage;
public int width;
public int height;
public Dimension preferredSize() {
return new Dimension (width, height);
}

Graph (int width, int height) {
this.width = width;
this.height = height;
resize(preferredSize());
}

public void update (Graphics g) { paint(g); }

public void paint (Graphics g) {
g.drawImage (graphImage, 0, 0, this);
}
}	