1 package com.billkuker.rocketry.motorsim.io;
\r
3 import java.io.OutputStream;
\r
4 import java.io.PrintWriter;
\r
5 import java.lang.reflect.InvocationTargetException;
\r
6 import java.lang.reflect.Method;
\r
7 import java.net.URLEncoder;
\r
8 import java.text.DecimalFormat;
\r
9 import java.text.NumberFormat;
\r
10 import java.util.Iterator;
\r
12 import javax.measure.quantity.Duration;
\r
13 import javax.measure.quantity.Force;
\r
14 import javax.measure.quantity.Quantity;
\r
15 import javax.measure.unit.SI;
\r
16 import javax.measure.unit.Unit;
\r
18 import org.jscience.physics.amount.Amount;
\r
20 import com.billkuker.rocketry.motorsim.Burn;
\r
21 import com.billkuker.rocketry.motorsim.BurnSummary;
\r
22 import com.billkuker.rocketry.motorsim.GraphSimplifier;
\r
23 import com.billkuker.rocketry.motorsim.RocketScience;
\r
25 public class HTMLExporter {
\r
27 @SuppressWarnings("deprecation")
\r
28 private static String encode(String s) {
\r
29 return URLEncoder.encode(s).replace("%B2", "%C2%B2");
\r
32 private static <X extends Quantity, Y extends Quantity> String toChart(
\r
33 final Unit<X> xUnit, final Unit<Y> yUnit, final Object source,
\r
34 final String method, final Iterator<Amount<X>> domain, String title)
\r
35 throws SecurityException, NoSuchMethodException,
\r
36 IllegalArgumentException, IllegalAccessException,
\r
37 InvocationTargetException {
\r
38 NumberFormat nf = new DecimalFormat("#.##");
\r
39 Method f = source.getClass().getMethod(method, Amount.class);
\r
41 double xMin = 0, xMax = 0;
\r
42 double yMin = 0, yMax = 0;
\r
44 StringBuffer xVals = new StringBuffer();
\r
45 StringBuffer yVals = new StringBuffer();
\r
47 while (domain.hasNext()) {
\r
48 Amount<X> aX = domain.next();
\r
49 double x = aX.doubleValue(xUnit);
\r
50 @SuppressWarnings("unchecked")
\r
51 double y = ((Amount<Y>) f.invoke(source, aX)).doubleValue(yUnit);
\r
52 xMin = x < xMin ? x : xMin;
\r
53 xMax = x > xMax ? x : xMax;
\r
54 yMin = y < yMin ? y : yMin;
\r
55 yMax = y > yMax ? y : yMax;
\r
57 xVals.append(nf.format(x));
\r
59 yVals.append(nf.format(y));
\r
62 xVals.deleteCharAt(xVals.length() - 1);
\r
63 yVals.deleteCharAt(yVals.length() - 1);
\r
65 // Get the non-preferred Y Unit
\r
66 Unit<Y> yUnit2 = RocketScience.UnitPreference.SI
\r
67 .getPreferredUnit(yUnit);
\r
68 // if ( yUnit2.equals(yUnit) )
\r
69 yUnit2 = RocketScience.UnitPreference.NONSI.getPreferredUnit(yUnit);
\r
70 double y2Min, y2Max;
\r
71 y2Min = Amount.valueOf(yMin, yUnit).doubleValue(yUnit2);
\r
72 y2Max = Amount.valueOf(yMax, yUnit).doubleValue(yUnit2);
\r
74 // Get the non-preferred X Unit
\r
75 Unit<X> xUnit2 = RocketScience.UnitPreference.SI
\r
76 .getPreferredUnit(xUnit);
\r
77 // if ( xUnit2.equals(xUnit) )
\r
78 xUnit2 = RocketScience.UnitPreference.NONSI.getPreferredUnit(xUnit);
\r
79 double x2Min, x2Max;
\r
80 x2Min = Amount.valueOf(xMin, xUnit).doubleValue(xUnit2);
\r
81 x2Max = Amount.valueOf(xMax, xUnit).doubleValue(xUnit2);
\r
83 boolean x2 = !xUnit.equals(xUnit2);
\r
84 boolean y2 = x2 || !yUnit.equals(yUnit2);
\r
86 StringBuffer sb = new StringBuffer();
\r
87 sb.append("<img src='");
\r
88 sb.append("http://chart.apis.google.com/chart?chxt=x,x,y,y"
\r
89 + (y2 ? ",r,r" : "") + (x2 ? ",t,t" : "")
\r
90 + "&chs=640x240&cht=lxy&chco=3072F3");
\r
91 sb.append("&chds=" + nf.format(xMin) + "," + nf.format(xMax) + ","
\r
92 + nf.format(yMin) + "," + nf.format(yMax));
\r
93 sb.append("&chxr=" + "0," + nf.format(xMin) + "," + nf.format(xMax)
\r
94 + "|2," + nf.format(yMin) + "," + nf.format(yMax));
\r
96 sb.append("|4," + nf.format(y2Min) + "," + nf.format(y2Max));
\r
98 sb.append("|6," + nf.format(x2Min) + "," + nf.format(x2Max));
\r
99 sb.append("&chd=t:" + xVals.toString() + "|" + yVals.toString());
\r
100 sb.append("&chxl=1:|" + encode(xUnit.toString()) + "|3:|"
\r
101 + encode(yUnit.toString()));
\r
103 sb.append("|5:|" + encode(yUnit2.toString()));
\r
105 sb.append("|7:|" + encode(xUnit2.toString()));
\r
106 sb.append("&chxp=1,50|3,50");
\r
108 sb.append("|5,50");
\r
110 sb.append("|7,50");
\r
111 sb.append("&chtt=" + title);
\r
112 sb.append("' width='640' height='240' alt='" + title + "' />");
\r
114 return sb.toString();
\r
117 public static void export(Burn b, OutputStream os) throws Exception {
\r
118 PrintWriter out = new PrintWriter(os);
\r
120 BurnSummary bs = new BurnSummary(b);
\r
122 out.println("<!--Begin motor " + b.getMotor().getName() + " HTML export from MotorSim-->");
\r
123 out.print("<table class='motor'>");
\r
126 out.print("<th colspan='6' class='title'>" + b.getMotor().getName() + "</th>");
\r
127 out.print("</tr>");
\r
129 out.print("<tr class='summary'>");
\r
130 out.print("<th>Rating:</th>");
\r
132 out.print("<td>" + bs.getRating() + "</td>");
\r
133 out.print("<th>Total Impulse:</th>");
\r
136 + RocketScience.ammountToRoundedString(bs.totalImpulse())
\r
138 out.print("<th>Specific Impulse:</th>");
\r
140 + RocketScience.ammountToRoundedString(bs.specificImpulse())
\r
142 out.print("</tr>");
\r
145 out.print("<tr class='summary'>");
\r
146 out.print("<th>Max Thrust:</th>");
\r
150 + RocketScience.ammountToRoundedString(bs.maxThrust())
\r
152 out.print("<th>Average Thrust:</th>");
\r
155 + RocketScience.ammountToRoundedString(bs.averageThrust())
\r
157 out.print("<th>Max Pressure:</th>");
\r
159 + RocketScience.ammountToRoundedString(bs.maxPressure())
\r
161 out.print("</tr>");
\r
164 out.print("<td colspan='6' class='thrust'>");
\r
165 GraphSimplifier<Duration, Force> thrust = new GraphSimplifier<Duration, Force>(
\r
166 b, "thrust", b.getData().keySet().iterator());
\r
168 out.print(toChart(SI.SECOND, SI.NEWTON, thrust, "value", thrust
\r
169 .getDomain().iterator(), "Thrust"));
\r
170 out.print("</td>");
\r
172 out.print("<td colspan='3' class='pressure'>");
\r
173 GraphSimplifier<Duration, Pressure> pressure = new GraphSimplifier<Duration, Pressure>(
\r
174 b, "pressure", b.getData().keySet().iterator());
\r
176 out.print(toChart(SI.SECOND,
\r
177 javax.measure.unit.SI.MEGA(javax.measure.unit.SI.PASCAL),
\r
178 pressure, "value", pressure.getDomain().iterator(), "Pressure"));
\r
180 out.print("</td>");
\r
182 out.print("</tr>");
\r
185 out.print("<th colspan='3'>.ENG File</th>");
\r
186 out.print("<th colspan='3'>MotorSim File</th>");
\r
187 out.print("</tr>");
\r
189 out.print("<td colspan='3'>");
\r
190 out.print("<textarea>");
\r
193 ENGExporter.export(b, os);
\r
195 out.print("</textarea>");
\r
196 out.print("</td>");
\r
197 out.print("<td colspan='3'>");
\r
198 out.print("<textarea>");
\r
199 out.print(MotorIO.writeMotor(b.getMotor()).replace("<", "<").replace(">", ">"));
\r
200 out.print("</textarea>");
\r
201 out.print("</td>");
\r
202 out.print("</tr>");
\r
204 out.print("</table>");
\r
206 out.println("\n<!--End motor " + b.getMotor().getName() + "-->");
\r