total overhaul: fleetcode-1.0 api finished
[fleet.git] / src / edu / berkeley / fleet / two / ShipDescription.java
diff --git a/src/edu/berkeley/fleet/two/ShipDescription.java b/src/edu/berkeley/fleet/two/ShipDescription.java
new file mode 100644 (file)
index 0000000..13d56de
--- /dev/null
@@ -0,0 +1,211 @@
+package edu.berkeley.fleet.two;
+import edu.berkeley.fleet.api.*;
+import java.io.*;
+import java.util.*;
+
+/** NOT YET FINALIZED: A description (specification) of a ship */
+public class ShipDescription implements Iterable<DockDescription> {
+
+    private String name;
+    private LinkedHashMap<String,DockDescription> docks     = new LinkedHashMap<String,DockDescription>();
+    private HashMap<String,String>                sections  = new HashMap<String,String>();
+    private HashMap<String,Constant>              constants = new HashMap<String,Constant>();
+
+    public String getName() { return name; }
+    public String getSection(String sectionName) { return sections.get(sectionName); }
+    public DockDescription getDockDescription(String name) { return docks.get(name); }
+    public Iterator<DockDescription> iterator() { return docks.values().iterator(); }
+
+    public ShipDescription(String name, BufferedReader r) throws IOException {
+        this.name = name;
+        String sectionName = null;
+        StringBuffer sb = new StringBuffer();
+        while(true) {
+            String s = r.readLine();
+            if (s==null || s.startsWith("==")) {
+                if (sectionName != null) sections.put(sectionName, sb.toString());
+                if (s==null) break;
+                sb = new StringBuffer();
+                sectionName = s.trim();
+                while(sectionName.startsWith("="))
+                    sectionName = sectionName.substring(1);
+                while(sectionName.endsWith("="))
+                    sectionName = sectionName.substring(0, sectionName.length()-1);
+                sectionName = sectionName.trim().toLowerCase();
+                continue;
+            }
+            sb.append(s+"\n");
+        }
+        for(String s : sections.keySet())
+            processSection(s);
+    }
+
+    public Constant getConstant(String name) {
+        return constants.get(name);
+    }
+
+    private void processSection(String section) throws IOException {
+        if (section.equals("")) {
+            BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
+            for(String s = br.readLine(); s != null; s = br.readLine()) {
+                if (s.trim().length()==0) continue;
+                String key = s.substring(0, s.indexOf(':')).trim();
+                String val = s.substring(s.indexOf(':')+1).trim();
+                if (key.toLowerCase().equals("ship"))
+                    name = val.trim();
+            }
+        } else if (section.equals("constants")) {
+            BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
+            for(String s = br.readLine(); s != null; s = br.readLine()) {
+                if (s.indexOf(':')==-1) continue;
+                String key = s.substring(0, s.indexOf(':')).trim();
+                if (key.startsWith("constant")) {
+                    String constname = key.substring("constant".length()+1).trim();
+                    String val       = s.substring(s.indexOf(':')+1).trim();
+                    constants.put(constname, new Constant(val));
+                }
+            }
+        } else if (section.equals("ports")) {
+            BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
+            boolean rightSide = false;
+            DockDescription p = null;
+            for(String s = br.readLine(); s != null; s = br.readLine()) {
+                if (s.trim().length()==0) { rightSide = true; continue; }
+
+                String key = s.substring(0, s.indexOf(':')).trim();
+                boolean inbox = false;
+                key = key.replaceAll("  +", " ");
+                if      (key.equals("data in"))   { inbox = true;  }
+                else if (key.equals("data out"))  { inbox = false; }
+                else if (key.equals("in"))        { inbox = true;  }
+                else if (key.equals("out"))       { inbox = false; }
+                else if (key.startsWith("constant")) {
+                    String constname = key.substring("constant".length()+1).trim();
+                    String val       = s.substring(s.indexOf(':')+1).trim();
+                    p.addConstant(constname, new Constant(val));
+                    continue;
+                } else if (key.startsWith("shortcut to")) {
+                    continue;
+                }
+                else throw new RuntimeException("unknown port type: \""+key+"\"");
+
+                p = null;
+                String val = s.substring(s.indexOf(':')+1).trim();
+                String boxname = val.indexOf('.') != -1 ? val.substring(0, val.indexOf('.')) : val;
+                String dest    = val.indexOf('.') != -1 ? val.substring(val.indexOf('.')+1)  : "";
+                p = docks.get(boxname);
+                if (p==null) {
+                    p = new DockDescription(this, boxname, !rightSide, inbox);
+                    docks.put(boxname, p);
+                }
+            }
+        }
+    }
+
+    public void printTeX(PrintWriter pw) throws Exception {
+        ShipDescription sd = this;
+        pw.println("\\pagebreak");
+        pw.println("\\section*{The {\\tt "+sd.getName()+"} Ship}");
+        pw.println("\\addcontentsline{toc}{subsection}{"+sd.getName()+"}");
+        String tex = sd.getSection("tex");
+        /*
+        for(DockDescription bbd : sd) {
+            pw.println("{\\bf "+(bbd.isInputDock() ? "Input: " : "Output: ")+"{\\tt "+bbd.getName()+"}}\n\n");
+        }
+        */
+        int boxGap = 5;
+        int boxHeight = 25;
+        int boxWidth = 75;
+
+        int leftSize = 0;
+        int rightSize = 0;
+        for(DockDescription bbd : sd)
+            if (bbd.isLeft()) leftSize += (boxHeight+boxGap);
+            else              rightSize += (boxHeight+boxGap);
+
+        int totalHeight = Math.max(leftSize, rightSize);
+        int shipWidth = (int)(boxWidth * 1.5);
+        int totalWidth = boxGap*2 + boxWidth*2 + shipWidth;
+
+        pw.println("");
+        pw.println("\\begin{center}");
+        pw.println("\\begin{empfile}["+sd.getName()+"]");
+        pw.println("\\begin{emp}["+sd.getName()+"]("+(totalWidth+10)+","+(totalHeight+10)+")");
+        pw.println("  beginfig(1)");
+        pw.println("      pickup pencircle scaled 1pt;");
+        pw.println("      draw "+
+                   "("+((totalWidth-shipWidth)/2)+","+0+")--"+
+                   "("+((totalWidth-shipWidth)/2)+","+totalHeight+")--"+
+                   "("+(totalWidth-((totalWidth-shipWidth)/2))+","+totalHeight+")--"+
+                   "("+(totalWidth-((totalWidth-shipWidth)/2))+","+0+")--"+
+                   "("+((totalWidth-shipWidth)/2)+","+0+");");
+        int left = 0;
+        int right = 0;
+        for(DockDescription bbd : sd) {
+            int ypos = (totalHeight - (boxGap/2) - (bbd.isLeft() ? left : right));
+            int half = (totalWidth-shipWidth)/2;
+            int p1 = bbd.isLeft() ? (half-5) : ((totalWidth-half)+5);
+            int p3 = bbd.isLeft() ? (p1 - boxWidth) : (p1 + boxWidth);
+            if (bbd.isInputDock()) {
+                int p1x = p1;
+                p1 = p3;
+                p3 = p1x;
+            }
+            boolean goo = ((bbd.isLeft() && bbd.isInputDock()) || (!bbd.isLeft() && bbd.isOutputDock()));
+            int p2 = goo ? (p3 - (boxHeight/2)) : (p3 + (boxHeight/2));
+            if (bbd.isLeft()) left += (boxHeight+boxGap);
+            else              right += (boxHeight+boxGap);
+            if (goo) {
+                pw.println("      label.rt(btex \\tt "+bbd.getName()+" etex, ("+(p1+3)+","+(ypos-boxHeight/2)+"));");
+            } else {
+                pw.println("      label.lft(btex \\tt "+bbd.getName()+" etex, ("+(p1-3)+","+(ypos-boxHeight/2)+"));");
+            }
+            pw.println("      draw "+
+                       "  ("+p1+","+ypos+")--"+
+                       "  ("+p2+","+ypos+")--"+
+                       "  ("+p3+","+(ypos-(boxHeight/2))+")--"+
+                       "  ("+p2+","+(ypos-boxHeight)+")--"+
+                       "  ("+p1+","+(ypos-boxHeight)+")--"+
+                       "  ("+p1+","+ypos+");");
+            if (bbd.isLeft()) leftSize += boxHeight;
+            else              rightSize += boxHeight;
+        }
+        pw.println("  endfig;");
+        pw.println("\\end{emp}");
+        pw.println("\\end{empfile}");
+        pw.println("\\end{center}");
+        pw.println("");
+
+        if (tex!=null)
+            pw.println(tex);
+    }
+
+    public class Constant {
+        public long    setbits   = 0;
+        public long    clearbits = 0;
+        public boolean signExtend = false;
+        public int     numberOffset = 0;
+        public int     numberWidth = 0;
+        public Constant(String s) {
+            if (s.startsWith("0x")) {
+                setbits = Long.parseLong(s.substring(2), 16);
+                clearbits = ~setbits;
+            } else if (s.length() == 37) {
+                for(int i=36; i>=0; i--) {
+                    char c = s.charAt(36-i);
+                    switch(c) {
+                        case '0': clearbits |= (1<<i); break;
+                        case '1': setbits   |= (1<<i); break;
+                        case '.': break;
+                        case 's': signExtend = true;  numberOffset = i; numberWidth++; break;
+                        case 'u': signExtend = false; numberOffset = i; numberWidth++; break;
+                    }
+                }
+            } else {
+                setbits = Long.parseLong(s);
+                clearbits = ~setbits;
+            }
+        }
+    }
+
+}