import java.applet.*; import java.awt.*; import java.util.*; import java.net.*; import java.io.*; public class FordFulk extends Applet { int WIRESHIFT=8,WIREARROW=16; double NODEGAPSCALE=1./2; double WIREFONTSCALE=1.,NODEFONTSCALE=3./2; double WIRECAPBALANCE=3./5,WIREFLGBALANCE=4./5; int WIREFLGRADIUS=8; FordFulkNet net; Color wirecolor=Color.blue, wiretextfgcolor=Color.yellow, wiretextbgcolor=Color.black, wireflgyescolor=Color.green, wireflgnocolor =Color.red, wirebackcolor =Color.green, nodeactivecolor=Color.magenta, nodepassedcolor=Color.blue, tgttextfgcolor =Color.white, tgttextbgcolor =Color.black, tgtarrowcolor =Color.cyan; String DATAFN; List codelist; TextField linenotext,stopattext,statustext; Button singlestep,nextlinestep,advancestep,continuerun,stopnow,resetnow; Choice codespeed; FordFulkTextArea guidearea; int lineno=0,stopat=0,linestot=0; boolean stopplus=false; static String cs_s[]={"fastest","100ms","1/2s","2s"},stext[]={"Working...","Delaying...","Ready."}; Hashtable guides=new Hashtable(); FordFulkThread thread; boolean suspendtest=true,suspendbug=true; long BUGGYSLEEP=100; static String sectionToString(FordFulkDataStream is,String sep) throws IOException { String s="",l; boolean f=true; while ((l=is.getLine())!=null) { if (f) f=false; else s+=sep; s+=l; } is.nextSection(); return s; } static StreamTokenizer sectionStreamTokenizer(FordFulkDataStream is) throws IOException { return new StreamTokenizer(new StringBufferInputStream(sectionToString(is,"\n"))); } static Vector readNumberChunk(FordFulkDataStream ffds,int divisor) throws IOException { StreamTokenizer fs=sectionStreamTokenizer(ffds); Vector r=new Vector(); do switch (fs.nextToken()) { case fs.TT_NUMBER: r.addElement(new Integer(new Double(fs.nval).intValue())); continue; case fs.TT_EOF: break; default: throw new IOException("Unexpected data type "+fs.ttype+",nval="+fs.nval+",sval="+fs.sval); } while (fs.ttype!=fs.TT_EOF); if ((r.size()%divisor)!=0) throw new IOException("Trailing specification of number data (div="+divisor+")"); return r; } public void initError(String s,Exception e) { s="Applet init error: "+s+" of \""+DATAFN+"\": "+e.toString(); showStatus(s); System.out.println(s); } public TextField labeledText(Panel p,String lab,String ini) { Panel p1=new Panel(); p1.setLayout(new GridBagLayout()); if (lab!=null) p1.add(new Label(lab)); TextField r=new TextField(ini,ini.length()); r.setEditable(false); p1.add(r); p.add(p1); return r; } public void init() { DATAFN=getParameter("DataFile"); setLayout(new GridLayout(1,0)); Vector pnts,wires,inis; { Panel p=new Panel(); GridBagLayout gb=new GridBagLayout(); p.setLayout(gb); GridBagConstraints gbc=new GridBagConstraints(); gbc.fill=GridBagConstraints.BOTH; gbc.gridwidth=GridBagConstraints.REMAINDER; gbc.weightx=1; p.setBackground(Color.lightGray); try { { Panel p1=new Panel(); p1.setLayout(new FlowLayout()); linenotext=labeledText(p1,"Line","- "); stopattext=labeledText(p1,"Stop","- "); { Panel p2=new Panel(); p2.setLayout(new GridBagLayout()); p2.add(new Label("Delay")); p2.add(codespeed=new Choice()); for (int i=0;i<4;i++) codespeed.addItem(cs_s[i]); codespeed.select(1); p1.add(p2); } statustext=labeledText(p1,null,stext[0]); gbc.weighty=0; gb.setConstraints(p1,gbc); p.add(p1); } { Panel p1=new Panel(); p1.setLayout(new GridLayout(2,3)); p1.add(singlestep =new Button("Single step" )); p1.add(nextlinestep=new Button("Stop @ next" )); p1.add(advancestep =new Button("Any further" )); p1.add(continuerun =new Button("Continue/Run")); p1.add(stopnow =new Button("Stop now" )); p1.add(resetnow =new Button("Reset & stop")); gbc.weighty=1; gb.setConstraints(p1,gbc); p.add(p1); } codelist=new List(20,false); FordFulkDataStream f=new FordFulkDataStream(new URL(getDocumentBase(),DATAFN).openStream()); String line; while ((line=f.getLine())!=null) { codelist.addItem(": "+line); linestot++; } int lnol=new Integer(linestot).toString().length(); for (int i=1;i<=linestot;i++) { String s="0000"+new Integer(i).toString(); codelist.replaceItem(s.substring(s.length()-lnol)+codelist.getItem(i-1),i-1); } f.nextSection(); for (;;) { Vector which; f.lineLimit(1); which=readNumberChunk(f,1); if (which.size()==0) break; int lj=0; String rng=""; boolean mult=false; for (int i=0;i in 1998.\n"+ "Redistribution permitted under GNU General Public License (AKA GPL) version 2 (exactly) found on ftp://prep.ai.mit.edu/pub/gnu/GPL." ); } public static void drawLine(Graphics g,Point p1,Point p2) { g.drawLine(p1.x,p1.y,p2.x,p2.y); } public static void drawString(Graphics g,String s,FordFulkPoint p,Color Bg,boolean docen,double fntscl) { Font of=g.getFont(); g.setFont(new Font(of.getName(),of.getStyle(),(int)(of.getSize()*fntscl))); FontMetrics m=g.getFontMetrics(); int w=m.stringWidth(s); if (docen) p.translate(-w/2.,+m.getAscent()/2.); Point ip=p.point(); if (Bg!=null) { int h=m.getAscent()+m.getDescent(); Color tc=g.getColor(); g.setColor(Bg); g.fillRect(ip.x,ip.y-m.getAscent(),w,h); g.setColor(tc); } g.drawString(s,ip.x,ip.y); g.setFont(of); } public static void fillCircleColor(Graphics g,Point p,int r,Color c) { if (c!=null) g.setColor(c); g.fillOval(p.x,p.y,r,r); } Enumeration l2e=null; FordFulkWire l3w=null,l5w=null,l20w=null; Vector l6v=null; int l7S=0,l9T=0,l17D=0,l18J=0,l19I=0; public synchronized void javaCleanCode(boolean hard) { FordFulk main=this; //for future separation Enumeration e=main.net.W.elements(); while (e.hasMoreElements()) { FordFulkWire w=(FordFulkWire)e.nextElement(); w.flgforw=w.flgback=null; if (hard) w.T=0; } for (int i=0;i0) ?main.wireflgyescolor:main.wireflgnocolor); for (int i=0;i<=3;i++) main.net.tgtseta(i,null); main.net.repaint(); return 3; case 6: main.net.A[main.net.iniS].state=main.nodeactivecolor; l6v=new Vector(); l6v.addElement(new Integer(main.net.iniS)); main.net.repaint(); break; case 7: if (l6v.size()==0) return 14; l7S=((Integer)l6v.elementAt(0)).intValue(); main.net.tgtseta(4,main.net.A[l7S]); main.net.repaint(); break; case 8: if (l7S==main.net.iniD) return 14; l9T=-1; break; case 9: while (++l9T=0;i=main.net.A[i].back) main.net.A[i].backused=true; for (i=0;i24,25->30 } main.net.tgtseta(0,main.net.A[l19I]); l20w=(FordFulkWire)main.net.W.get(new Point(l19I,l18J)); main.net.tgtseta(1,l20w); main.net.repaint(); break; case 20: case 26: if (l20w==null || l20w.flgforw!=main.wireflgyescolor) return lineno+2;//20->22,26->28 main.net.tgtseta(1,l20w); main.net.repaint(); break; case 21: l17D=Math.min(l17D,l20w.C-l20w.T); main.net.tgtsetD(new Integer(l17D).toString()); main.net.repaint(); break; case 27: l20w.T+=l17D; main.net.repaint(); break; case 22: case 28: if (l20w==null || l20w.flgback!=main.wireflgyescolor) return lineno-3;//22->19,28->25 break; case 23: l17D=Math.min(l17D,((FordFulkWire)main.net.W.get(new Point(l18J,l19I))).T); main.net.tgtsetD(new Integer(l17D).toString()); main.net.repaint(); return 19; case 29: ((FordFulkWire)main.net.W.get(new Point(l18J,l19I))).T-=l17D; main.net.repaint(); break; case 30: javaCleanCode(false); break; case 31: return 1; } return 0; } public synchronized void cycle() { statustext.setText(stext[0]); codeListSelect(); if (stopat==0) return; int newline; if ((newline=javaCode())==0) newline=lineno+1; if (newline>linestot) { newline=0; setNumText(stopattext,stopat=0,stopplus=false); } if (stopat==-1 || stopat==newline || (stopat0) { cl=ll; int i,j; if (s.charAt(0)=='\n') { appendText(line+"\n"); line=""; s=s.substring(1); continue; } while ((i=s.indexOf(' '))==0) s=s.substring(1); if (i==-1) i=s.length(); if ((j=s.substring(0,i).indexOf('\n'))!=-1) i=j; nline=new String(line); if (line.length()!=0) nline+=" "; nline+=s.substring(0,i); int thisw; if (m!=null) thisw=m.stringWidth(nline); else thisw=nline.length()*CHARWIDTH; if (thisw>cols && line.length()!=0) { appendText(line+"\n"); line=s.substring(0,i); } else line=nline; s=s.substring(i); } appendText(line); } } class FordFulkThread extends Thread { FordFulk main; static int cs_v[]={0,100,500,2000}; boolean justfortest; public FordFulkThread(FordFulk _main,boolean _justfortest) { main=_main; if (justfortest=_justfortest) setDaemon(true); } public void run() { if (justfortest) { while (main.suspendtest) { try { main.thread.countStackFrames(); main.suspendbug=false; main.thread.resume(); if (!main.suspendtest) break; } catch (IllegalThreadStateException e) {} try { sleep(main.BUGGYSLEEP); } catch (InterruptedException e) {} } stop(); return; } suspend(); main.suspendtest=false; if (main.suspendbug) System.out.println("Netscape Communicator suspend() bug, workarounding it..."); for (;;) { main.cycle(); if (main.stopat==0) { main.statustext.setText(main.stext[2]); while (main.stopat==0) { if (!main.suspendbug) suspend(); else try { sleep(main.BUGGYSLEEP); } catch (InterruptedException e) {} } } else { main.statustext.setText(main.stext[1]); if (main.guidearea.once) { main.guidearea.once=false; System.out.println("M$ Internet Explorer TextArea paint() override bug, workarounding it..."); } try { sleep((long)cs_v[main.codespeed.getSelectedIndex()]); } catch (InterruptedException e) {} } } } } class FordFulkDataStream extends DataInputStream { private String TERM="-"; private int togo=-1; public FordFulkDataStream(InputStream s) { super(s); } public void lineLimit(int _togo) { togo=_togo; } public String getLine() throws IOException { if (togo==0) return null; String l=readLine(); if (l==null) { togo=0; return null; } if (l.trim().compareTo(TERM)==0) { togo=0; return null; } togo--; return l; } public void nextSection() throws IOException { if (togo!=0) throw new IOException("nextSection() but togo=="+togo+"!"); togo=-1; } } class FordFulkPoint { double x,y; public FordFulkPoint(int _x,int _y) { x=_x; y=_y; } public FordFulkPoint(double _x,double _y) { x=_x; y=_y; } public FordFulkPoint(FordFulkPoint p) { x=p.x; y=p.y; } public FordFulkPoint(Point p) { x=p.x; y=p.y; } public FordFulkPoint(FordFulkPoint p1,FordFulkPoint p2,double w) { x=p1.point().x*(1-w)+p2.point().x*w; y=p1.point().y*(1-w)+p2.point().y*w; } public FordFulkPoint(FordFulkPoint p1,FordFulkPoint p2) //arit. avg { x=(p1.x+p2.x)/2; y=(p1.y+p2.y)/2; } public void sub(FordFulkPoint p) { x-=p.x; y-=p.y; } public void sub(Point p) { sub(new FordFulkPoint(p)); } public Point point() { return new Point((int)x,(int)y); } public Dimension dimension() { return new Dimension((int)x,(int)y); } public void translate(double _x,double _y) { x+=_x; y+=_y; } public void translate(FordFulkPoint p) { translate(p.x,p.y); } public void rotplus90() { double t=x; x=-y; y=t; } public void rotminus90() { double t=x; x=y; y=-t; } public double length() { return Math.sqrt(x*x+y*y); } public void multiply(double c) { x*=c; y*=c; } public void normalize(double len) { multiply(len/length()); } public void negate() { x=-x; y=-y; } public String toString() { return "FFP(x="+x+",y="+y+")"; } } interface FordFulkTargetable { public FordFulkPoint center(); public FordFulkPoint ffpSize(); } class FordFulkWire implements FordFulkTargetable { FordFulk main; int i,j; int C,T=0; Color flgforw=null,flgback=null; FordFulkPoint p1,p2; public FordFulkWire(FordFulk _main,int _i,int _j,int _C) { main=_main; i=_i; j=_j; C=_C; } public void setup12(int shift) { FordFulkPoint rln; p1=main.net.A[i].center(); p2=main.net.A[j].center(); rln=new FordFulkPoint(p2); rln.sub(p1); rln.rotplus90(); rln.normalize(shift); p1.translate(rln); p2.translate(rln); } public synchronized void drawArrow(Graphics g,int shift) { setup12(shift); anyArrow(main,g,p1,p2,main.net.nodeSize/2); } public static void anyArrow(FordFulk main,Graphics g,FordFulkPoint p1,FordFulkPoint p2,double shorten) { FordFulkPoint arrdir,arrwing,efix; arrdir=new FordFulkPoint(p2); arrdir.sub(p1); efix=new FordFulkPoint(arrdir); efix.normalize(-(shorten-1)); p2.translate(efix); FordFulk.drawLine(g,p1.point(),p2.point()); arrdir.normalize(main.WIREARROW); arrwing=new FordFulkPoint(arrdir); arrwing.rotplus90(); arrdir=new FordFulkPoint(arrdir,arrwing); arrdir.negate(); arrwing=new FordFulkPoint(p2); arrwing.translate(arrdir); FordFulk.drawLine(g,p2.point(),arrwing.point()); arrdir.rotminus90(); arrwing=new FordFulkPoint(p2); arrwing.translate(arrdir); FordFulk.drawLine(g,p2.point(),arrwing.point()); efix.negate(); p1.translate(efix); } public synchronized FordFulkPoint center() { setup12(main.WIRESHIFT); return new FordFulkPoint(p1,p2); } public FordFulkPoint ffpSize() { return new FordFulkPoint(1,1); } public synchronized void paint(Graphics g) { if (main==null) return; g.setColor(main.wirecolor); drawArrow(g,main.WIRESHIFT); g.setColor(main.wiretextfgcolor); FordFulk.drawString(g,T+"/"+C, new FordFulkPoint(p1,p2,main.WIRECAPBALANCE), main.wiretextbgcolor,true,main.WIREFONTSCALE); if (flgforw!=null) FordFulk.fillCircleColor(g, new FordFulkPoint(p1,p2,main.WIREFLGBALANCE).point(), main.WIREFLGRADIUS,flgforw); if (flgback!=null) FordFulk.fillCircleColor(g, new FordFulkPoint(p1,p2,1-main.WIREFLGBALANCE).point(), main.WIREFLGRADIUS,flgback); } } class FordFulkNode implements FordFulkTargetable { FordFulk main; int no; String no_s; Color state=null; int back=-1; boolean backused; Point pxy; public FordFulkNode(FordFulk _main,int _no,Point _pxy) { main=_main; pxy=_pxy; no_s=new Integer(no=_no).toString(); if (no==main.net.iniS) no_s+="s"; if (no==main.net.iniD) no_s+="d"; } public FordFulkPoint ffpSize() { return new FordFulkPoint(main.net.nodeSize,main.net.nodeSize); } public Dimension size() { return ffpSize().dimension(); } public FordFulkPoint ffpLocation() { return new FordFulkPoint( main.net.unitShift.x+main.net.unitSize.x*pxy.x, main.net.unitShift.y+main.net.unitSize.y*pxy.y); } public Point location() { return ffpLocation().point(); } public Rectangle bounds() { return new Rectangle(location(),size()); } public void justBack(Graphics g) { if (no<0 || back<0) return; FordFulkWire ffw=new FordFulkWire(main,no,back,0); g.setColor(main.wirebackcolor); ffw.drawArrow(g,0); } public void paint(Graphics g) { if (no<0) return; Rectangle me=bounds(); g.setColor(main.net.getBackground()); g.fillOval(me.x,me.y,me.width,me.height); g.setColor(main.net.getForeground()); g.drawOval(me.x,me.y,me.width,me.height); g.setColor(state); FordFulk.drawString(g,no_s,center(),null,true,main.NODEFONTSCALE); } public FordFulkPoint center() { FordFulkPoint xy=ffpLocation(),wh=ffpSize(); return new FordFulkPoint(xy.x+wh.x/2,xy.y+wh.y/2); } } class FordFulkNet extends Panel { FordFulk main; int nodes; FordFulkNode A[]; Hashtable W=new Hashtable(); int iniS,iniD; Vector blind=new Vector(); int nodesx=1,nodesy=1; double nodeSize; FordFulkPoint unitShift,unitSize; String tgts[]={"i","Eij","Eji","j","s","Est","t",null}; FordFulkTargetable tgta[]=new FordFulkTargetable[7]; public FordFulkNet(FordFulk _main) { main=_main; } public void setup(Vector pnts,Vector wires,Vector inis) { setBackground(Color.white); nodes=pnts.size()/2; iniS=((Integer)inis.elementAt(0)).intValue(); iniD=((Integer)inis.elementAt(1)).intValue(); Hashtable ndh=new Hashtable(); for (int i=0;i