--- /dev/null
+package com.billkuker.rocketry.motorsim.io;\r
+\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.OutputStream;\r
+import java.io.PrintWriter;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.net.URLEncoder;\r
+import java.text.DecimalFormat;\r
+import java.text.NumberFormat;\r
+import java.util.Iterator;\r
+\r
+import javax.measure.quantity.Duration;\r
+import javax.measure.quantity.Force;\r
+import javax.measure.quantity.Quantity;\r
+import javax.measure.unit.SI;\r
+import javax.measure.unit.Unit;\r
+\r
+import org.jscience.physics.amount.Amount;\r
+\r
+import com.billkuker.rocketry.motorsim.Burn;\r
+import com.billkuker.rocketry.motorsim.BurnSummary;\r
+import com.billkuker.rocketry.motorsim.GraphSimplifier;\r
+import com.billkuker.rocketry.motorsim.Motor;\r
+import com.billkuker.rocketry.motorsim.RocketScience;\r
+import com.billkuker.rocketry.motorsim.motors.kuker.PVC9;\r
+\r
+public class HTMLExporter {\r
+\r
+ @SuppressWarnings("deprecation")\r
+ private static String encode(String s) {\r
+ return URLEncoder.encode(s).replace("%B2", "%C2%B2");\r
+ }\r
+\r
+ private static <X extends Quantity, Y extends Quantity> String toChart(\r
+ final Unit<X> xUnit, final Unit<Y> yUnit, final Object source,\r
+ final String method, final Iterator<Amount<X>> domain, String title)\r
+ throws SecurityException, NoSuchMethodException,\r
+ IllegalArgumentException, IllegalAccessException,\r
+ InvocationTargetException {\r
+ NumberFormat nf = new DecimalFormat("#.##");\r
+ Method f = source.getClass().getMethod(method, Amount.class);\r
+\r
+ double xMin = 0, xMax = 0;\r
+ double yMin = 0, yMax = 0;\r
+\r
+ StringBuffer xVals = new StringBuffer();\r
+ StringBuffer yVals = new StringBuffer();\r
+\r
+ while (domain.hasNext()) {\r
+ Amount<X> aX = domain.next();\r
+ double x = aX.doubleValue(xUnit);\r
+ @SuppressWarnings("unchecked")\r
+ double y = ((Amount<Y>) f.invoke(source, aX)).doubleValue(yUnit);\r
+ xMin = x < xMin ? x : xMin;\r
+ xMax = x > xMax ? x : xMax;\r
+ yMin = y < yMin ? y : yMin;\r
+ yMax = y > yMax ? y : yMax;\r
+\r
+ xVals.append(nf.format(x));\r
+ xVals.append(",");\r
+ yVals.append(nf.format(y));\r
+ yVals.append(",");\r
+ }\r
+ xVals.deleteCharAt(xVals.length() - 1);\r
+ yVals.deleteCharAt(yVals.length() - 1);\r
+\r
+ // Get the non-preferred Y Unit\r
+ Unit<Y> yUnit2 = RocketScience.UnitPreference.SI\r
+ .getPreferredUnit(yUnit);\r
+ // if ( yUnit2.equals(yUnit) )\r
+ yUnit2 = RocketScience.UnitPreference.NONSI.getPreferredUnit(yUnit);\r
+ double y2Min, y2Max;\r
+ y2Min = Amount.valueOf(yMin, yUnit).doubleValue(yUnit2);\r
+ y2Max = Amount.valueOf(yMax, yUnit).doubleValue(yUnit2);\r
+\r
+ // Get the non-preferred X Unit\r
+ Unit<X> xUnit2 = RocketScience.UnitPreference.SI\r
+ .getPreferredUnit(xUnit);\r
+ // if ( xUnit2.equals(xUnit) )\r
+ xUnit2 = RocketScience.UnitPreference.NONSI.getPreferredUnit(xUnit);\r
+ double x2Min, x2Max;\r
+ x2Min = Amount.valueOf(xMin, xUnit).doubleValue(xUnit2);\r
+ x2Max = Amount.valueOf(xMax, xUnit).doubleValue(xUnit2);\r
+\r
+ boolean x2 = !xUnit.equals(xUnit2);\r
+ boolean y2 = x2 || !yUnit.equals(yUnit2);\r
+\r
+ StringBuffer sb = new StringBuffer();\r
+ sb.append("<img src='");\r
+ sb.append("http://chart.apis.google.com/chart?chxt=x,x,y,y"\r
+ + (y2 ? ",r,r" : "") + (x2 ? ",t,t" : "")\r
+ + "&chs=640x240&cht=lxy&chco=3072F3");\r
+ sb.append("&chds=" + nf.format(xMin) + "," + nf.format(xMax) + ","\r
+ + nf.format(yMin) + "," + nf.format(yMax));\r
+ sb.append("&chxr=" + "0," + nf.format(xMin) + "," + nf.format(xMax)\r
+ + "|2," + nf.format(yMin) + "," + nf.format(yMax));\r
+ if (y2)\r
+ sb.append("|4," + nf.format(y2Min) + "," + nf.format(y2Max));\r
+ if (x2)\r
+ sb.append("|6," + nf.format(x2Min) + "," + nf.format(x2Max));\r
+ sb.append("&chd=t:" + xVals.toString() + "|" + yVals.toString());\r
+ sb.append("&chxl=1:|" + encode(xUnit.toString()) + "|3:|"\r
+ + encode(yUnit.toString()));\r
+ if (y2)\r
+ sb.append("|5:|" + encode(yUnit2.toString()));\r
+ if (x2)\r
+ sb.append("|7:|" + encode(xUnit2.toString()));\r
+ sb.append("&chxp=1,50|3,50");\r
+ if (y2)\r
+ sb.append("|5,50");\r
+ if (x2)\r
+ sb.append("|7,50");\r
+ sb.append("&chtt=" + title);\r
+ sb.append("' width='640' height='240' alt='" + title + "' />");\r
+\r
+ return sb.toString();\r
+ }\r
+\r
+ public static void export(Burn b, OutputStream os) throws Exception {\r
+ PrintWriter out = new PrintWriter(os);\r
+\r
+ BurnSummary bs = new BurnSummary(b);\r
+ \r
+ out.println("<!--Begin motor " + b.getMotor().getName() + " HTML export from MotorSim-->");\r
+ out.print("<table class='motor'>");\r
+\r
+ out.print("<tr>");\r
+ out.print("<th colspan='6' class='title'>" + b.getMotor().getName() + "</th>");\r
+ out.print("</tr>");\r
+\r
+ out.print("<tr class='summary'>");\r
+ out.print("<th>Rating:</th>");\r
+ \r
+ out.print("<td>" + bs.getRating() + "</td>");\r
+ out.print("<th>Total Impulse:</th>");\r
+ \r
+ out.print("<td>"\r
+ + RocketScience.ammountToRoundedString(bs.totalImpulse())\r
+ + "</td>");\r
+ out.print("<th>Specific Impulse:</th>");\r
+ out.print("<td>"\r
+ + RocketScience.ammountToRoundedString(bs.specificImpulse())\r
+ + "</td>");\r
+ out.print("</tr>");\r
+ \r
+ \r
+ out.print("<tr class='summary'>");\r
+ out.print("<th>Max Thrust:</th>");\r
+ \r
+ \r
+ out.print("<td>"\r
+ + RocketScience.ammountToRoundedString(bs.maxThrust())\r
+ + "</td>");\r
+ out.print("<th>Average Thrust:</th>");\r
+ \r
+ out.print("<td>"\r
+ + RocketScience.ammountToRoundedString(bs.averageThrust())\r
+ + "</td>");\r
+ out.print("<th>Max Pressure:</th>");\r
+ out.print("<td>"\r
+ + RocketScience.ammountToRoundedString(bs.maxPressure())\r
+ + "</td>");\r
+ out.print("</tr>");\r
+\r
+ out.print("<tr>");\r
+ out.print("<td colspan='6' class='thrust'>");\r
+ GraphSimplifier<Duration, Force> thrust = new GraphSimplifier<Duration, Force>(\r
+ b, "thrust", b.getData().keySet().iterator());\r
+\r
+ out.print(toChart(SI.SECOND, SI.NEWTON, thrust, "value", thrust\r
+ .getDomain().iterator(), "Thrust"));\r
+ out.print("</td>");\r
+ /*\r
+ out.print("<td colspan='3' class='pressure'>");\r
+ GraphSimplifier<Duration, Pressure> pressure = new GraphSimplifier<Duration, Pressure>(\r
+ b, "pressure", b.getData().keySet().iterator());\r
+\r
+ out.print(toChart(SI.SECOND,\r
+ javax.measure.unit.SI.MEGA(javax.measure.unit.SI.PASCAL),\r
+ pressure, "value", pressure.getDomain().iterator(), "Pressure"));\r
+\r
+ out.print("</td>");\r
+ */\r
+ out.print("</tr>");\r
+ \r
+ out.print("<tr>");\r
+ out.print("<th colspan='3'>.ENG File</th>");\r
+ out.print("<th colspan='3'>MotorSim File</th>");\r
+ out.print("</tr>");\r
+ out.print("<tr>");\r
+ out.print("<td colspan='3'>");\r
+ out.print("<textarea>");\r
+ out.flush();\r
+ os.flush();\r
+ ENGExporter.export(b, os);\r
+ os.flush();\r
+ out.print("</textarea>");\r
+ out.print("</td>");\r
+ out.print("<td colspan='3'>");\r
+ out.print("<textarea>");\r
+ out.print(MotorIO.writeMotor(b.getMotor()).replace("<", "<").replace(">", ">"));\r
+ out.print("</textarea>");\r
+ out.print("</td>");\r
+ out.print("</tr>");\r
+ \r
+ out.print("</table>");\r
+\r
+ out.println("\n<!--End motor " + b.getMotor().getName() + "-->");\r
+ out.flush();\r
+ out.close();\r
+ }\r
+\r
+ public static void main(String args[]) throws Exception {\r
+\r
+ Motor m = new PVC9();\r
+ Burn b = new Burn(m);\r
+\r
+ File f = new File("test.html");\r
+ export(b, System.out);\r
+ export(b, new FileOutputStream(f));\r
+\r
+ /*\r
+ * \r
+ * EndBurner g = new EndBurner(); g.setLength(Amount.valueOf(70,\r
+ * SI.MILLIMETER)); g.setoD(Amount.valueOf(30, SI.MILLIMETER));\r
+ * g.setPuntDepth(Amount.valueOf(10, SI.MILLIMETER));\r
+ * g.setPuntDiameter(Amount.valueOf(10, SI.MILLIMETER));\r
+ * \r
+ * Chart<Length, Area> c = new Chart<Length, Area>(SI.MILLIMETER,\r
+ * SI.MILLIMETER.pow(2).asType(Area.class), g, "surfaceArea");\r
+ * c.setDomain(c.new IntervalDomain(Amount.valueOf(0, SI.CENTIMETER), g\r
+ * .webThickness()));\r
+ * \r
+ * GraphSimplifier<Length, Area> gs = new GraphSimplifier<Length,\r
+ * Area>(g, "surfaceArea", c.new IntervalDomain(Amount.valueOf(0,\r
+ * SI.CENTIMETER), g.webThickness()).iterator());\r
+ * \r
+ * System.out.print(toChart(SI.MILLIMETER,\r
+ * SI.MILLIMETER.pow(2).asType(Area.class), gs, "value", gs\r
+ * .getDomain().iterator(), "Area"));\r
+ */\r
+ }\r
+\r
+}\r