--- /dev/null
+<engine-database>\r
+ <engine-list>\r
+<engine FDiv="10" FFix="1" FStep="-1." Isp="71.7" Itot="2.32" Type="single-use" auto-calc-cg="1" auto-calc-mass="1" avgThrust="3.178" burn-time="0.73" cgDiv="10" cgFix="1" cgStep="-1." code="A8" delays="3,5" dia="18." exitDia="0." initWt="16.35" len="70." mDiv="10" mFix="1" mStep="-1." massFrac="20.18" mfg="Estes" peakThrust="9.73" propWt="3.3" tDiv="10" tFix="1" tStep="-1." throatDia="0.">\r
+<comments>Estes A8 RASP.ENG file made from NAR published data\r
+File produced October 3, 2000\r
+The total impulse, peak thrust, average thrust and burn time are\r
+the same as the averaged static test data on the NAR web site in\r
+the certification file. The curve drawn with these data points is as\r
+close to the certification curve as can be with such a limited\r
+number of points (32) allowed with wRASP up to v1.6.\r
+</comments>\r
+<data>\r
+<eng-data cg="35." f="0." m="3.3" t="0."/>\r
+<eng-data cg="35." f="0.512" m="3.28507" t="0.041"/>\r
+<eng-data cg="35." f="2.115" m="3.20474" t="0.084"/>\r
+<eng-data cg="35." f="4.358" m="3.0068" t="0.127"/>\r
+<eng-data cg="35." f="6.794" m="2.6975" t="0.166"/>\r
+<eng-data cg="35." f="8.588" m="2.41309" t="0.192"/>\r
+<eng-data cg="35." f="9.294" m="2.23506" t="0.206"/>\r
+<eng-data cg="35." f="9.73" m="1.96448" t="0.226"/>\r
+<eng-data cg="35." f="8.845" m="1.83238" t="0.236"/>\r
+<eng-data cg="35." f="7.179" m="1.70703" t="0.247"/>\r
+<eng-data cg="35." f="5.063" m="1.58515" t="0.261"/>\r
+<eng-data cg="35." f="3.717" m="1.48525" t="0.277"/>\r
+<eng-data cg="35." f="3.205" m="1.3425" t="0.306"/>\r
+<eng-data cg="35." f="2.884" m="1.14764" t="0.351"/>\r
+<eng-data cg="35." f="2.499" m="0.94092" t="0.405"/>\r
+<eng-data cg="35." f="2.371" m="0.726196" t="0.467"/>\r
+<eng-data cg="35." f="2.307" m="0.509957" t="0.532"/>\r
+<eng-data cg="35." f="2.371" m="0.320333" t="0.589"/>\r
+<eng-data cg="35." f="2.371" m="0.175326" t="0.632"/>\r
+<eng-data cg="35." f="2.243" m="0.109701" t="0.652"/>\r
+<eng-data cg="35." f="1.794" m="0.0637665" t="0.668"/>\r
+<eng-data cg="35." f="1.153" m="0.0302344" t="0.684"/>\r
+<eng-data cg="35." f="0.448" m="0.00860204" t="0.703"/>\r
+<eng-data cg="35." f="0." m="0." t="0.73"/>\r
+</data>\r
+</engine>\r
+ </engine-list>\r
+</engine-database>\r
--- /dev/null
+package net.sf.openrocket;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.swing.Action;
+
+import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
+import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
+import net.sf.openrocket.aerodynamics.FlightConditions;
+import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
+import net.sf.openrocket.document.OpenRocketDocument;
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.file.GeneralRocketLoader;
+import net.sf.openrocket.file.RocketLoadException;
+import net.sf.openrocket.file.motor.GeneralMotorLoader;
+import net.sf.openrocket.gui.main.UndoRedoAction;
+import net.sf.openrocket.l10n.ResourceBundleTranslator;
+import net.sf.openrocket.masscalc.BasicMassCalculator;
+import net.sf.openrocket.masscalc.MassCalculator;
+import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
+import net.sf.openrocket.motor.Motor;
+import net.sf.openrocket.motor.ThrustCurveMotor;
+import net.sf.openrocket.rocketcomponent.Configuration;
+import net.sf.openrocket.rocketcomponent.EngineBlock;
+import net.sf.openrocket.rocketcomponent.MassComponent;
+import net.sf.openrocket.rocketcomponent.NoseCone;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.simulation.FlightDataType;
+import net.sf.openrocket.simulation.exception.SimulationException;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.util.Coordinate;
+import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This class contains various integration tests that simulate user actions that
+ * might be performed.
+ */
+public class IntegrationTest extends BaseTestCase {
+
+ private OpenRocketDocument document;
+ private Action undoAction, redoAction;
+
+ private AerodynamicCalculator aeroCalc = new BarrowmanCalculator();
+ private MassCalculator massCalc = new BasicMassCalculator();
+ private Configuration config;
+ private FlightConditions conditions;
+
+
+ @BeforeClass
+ public static void initialize() {
+ ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {
+ @Override
+ protected void loadMotors() {
+ GeneralMotorLoader loader = new GeneralMotorLoader();
+ InputStream is = this.getClass().getResourceAsStream("Estes_A8.rse");
+ assertNotNull("Problem in unit test, cannot find Estes_A8.rse", is);
+ try {
+ for (Motor m : loader.load(is, "Estes_A8.rse")) {
+ addMotor((ThrustCurveMotor) m);
+ }
+ is.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail("IOException: " + e);
+ }
+ }
+ };
+ db.startLoading();
+ assertEquals(1, db.getMotorSets().size());
+ Application.setMotorSetDatabase(db);
+ Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
+ }
+
+ /**
+ * Tests loading a rocket design, modifying it, simulating it and the undo/redo
+ * mechanism in various combinations.
+ */
+ @Test
+ public void test1() throws RocketLoadException, IOException, SimulationException {
+ System.setProperty("openrocket.unittest", "true");
+
+ // Load the rocket
+ GeneralRocketLoader loader = new GeneralRocketLoader();
+ InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
+ assertNotNull("Problem in unit test, cannot find simplerocket.ork", is);
+ document = loader.load(is);
+ is.close();
+
+ undoAction = UndoRedoAction.newUndoAction(document );
+ redoAction = UndoRedoAction.newRedoAction(document);
+ config = document.getSimulation(0).getConfiguration();
+ conditions = new FlightConditions(config);
+
+
+ // Test undo state
+ checkUndoState(null, null);
+
+
+ // Compute cg+cp + altitude
+ checkCgCp(0.248, 0.0645, 0.320, 12.0);
+ checkAlt(48.2);
+
+
+ // Mass modification
+ document.addUndoPosition("Modify mass");
+ checkUndoState(null, null);
+ massComponent().setComponentMass(0.01);
+ checkUndoState("Modify mass", null);
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.230, 0.0745, 0.320, 12.0);
+ checkAlt(37.2);
+
+
+ // Non-change
+ document.addUndoPosition("No change");
+ checkUndoState("Modify mass", null);
+
+
+ // Non-funcitonal change
+ document.addUndoPosition("Name change");
+ checkUndoState("Modify mass", null);
+ massComponent().setName("Foobar component");
+ checkUndoState("Name change", null);
+
+
+ // Check cg+cp
+ checkCgCp(0.230, 0.0745, 0.320, 12.0);
+
+
+ // Aerodynamic modification
+ document.addUndoPosition("Remove component");
+ checkUndoState("Name change", null);
+ document.getRocket().getChild(0).removeChild(0);
+ checkUndoState("Remove component", null);
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.163, 0.0613, 0.275, 9.95);
+ checkAlt(45.0);
+
+
+ // Undo "Remove component" change
+ undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
+ assertTrue(document.getRocket().getChild(0).getChild(0) instanceof NoseCone);
+ checkUndoState("Name change", "Remove component");
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.230, 0.0745, 0.320, 12.0);
+ checkAlt(37.2);
+
+
+ // Undo "Name change" change
+ undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
+ assertEquals("Extra mass", massComponent().getName());
+ checkUndoState("Modify mass", "Name change");
+
+
+ // Check cg+cp
+ checkCgCp(0.230, 0.0745, 0.320, 12.0);
+
+
+ // Undo "Modify mass" change
+ undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
+ assertEquals(0, massComponent().getComponentMass(), 0);
+ checkUndoState(null, "Modify mass");
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.248, 0.0645, 0.320, 12.0);
+ checkAlt(48.2);
+
+
+ // Redo "Modify mass" change
+ redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
+ assertEquals(0.010, massComponent().getComponentMass(), 0.00001);
+ checkUndoState("Modify mass", "Name change");
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.230, 0.0745, 0.320, 12.0);
+ checkAlt(37.2);
+
+
+ // Mass modification
+ document.addUndoPosition("Modify mass2");
+ checkUndoState("Modify mass", "Name change");
+ massComponent().setComponentMass(0.015);
+ checkUndoState("Modify mass2", null);
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.223, 0.0795, 0.320, 12.0);
+ checkAlt(32.7);
+
+
+ // Perform component movement
+ document.startUndo("Move component");
+ document.getRocket().freeze();
+ RocketComponent bodytube = document.getRocket().getChild(0).getChild(1);
+ RocketComponent innertube = bodytube.getChild(2);
+ RocketComponent engineblock = innertube.getChild(0);
+ assertTrue(innertube.removeChild(engineblock));
+ bodytube.addChild(engineblock, 0);
+ checkUndoState("Modify mass2", null);
+ document.getRocket().thaw();
+ checkUndoState("Move component", null);
+ document.stopUndo();
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.221, 0.0797, 0.320, 12.0);
+ checkAlt(32.7);
+
+
+ // Modify mass without setting undo description
+ massComponent().setComponentMass(0.020);
+ checkUndoState("Modify mass2", null);
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.215, 0.0847, 0.320, 12.0);
+ checkAlt(29.0);
+
+
+ // Undo "Modify mass2" change
+ undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
+ assertEquals(0.015, massComponent().getComponentMass(), 0.0000001);
+ checkUndoState("Move component", "Modify mass2");
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.221, 0.0797, 0.320, 12.0);
+ checkAlt(32.7);
+
+
+ // Undo "Move component" change
+ undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
+ assertTrue(document.getRocket().getChild(0).getChild(1).getChild(2).getChild(0) instanceof EngineBlock);
+ checkUndoState("Modify mass2", "Move component");
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.223, 0.0795, 0.320, 12.0);
+ checkAlt(32.7);
+
+
+ // Redo "Move component" change
+ redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
+ assertTrue(document.getRocket().getChild(0).getChild(1).getChild(0) instanceof EngineBlock);
+ checkUndoState("Move component", "Modify mass2");
+
+
+ // Check cg+cp + altitude
+ checkCgCp(0.221, 0.0797, 0.320, 12.0);
+ checkAlt(32.7);
+
+
+ }
+
+ private String massComponentID = null;
+
+ private MassComponent massComponent() {
+ if (massComponentID == null) {
+ massComponentID = document.getRocket().getChild(0).getChild(1).getChild(0).getID();
+ }
+ return (MassComponent) document.getRocket().findComponent(massComponentID);
+ }
+
+
+ private void checkUndoState(String undoDesc, String redoDesc) {
+ if (undoDesc == null) {
+ assertEquals("Undo", undoAction.getValue(Action.NAME));
+ assertFalse(undoAction.isEnabled());
+ } else {
+ assertEquals("Undo (" + undoDesc + ")", undoAction.getValue(Action.NAME));
+ assertTrue(undoAction.isEnabled());
+ }
+ if (redoDesc == null) {
+ assertEquals("Redo", redoAction.getValue(Action.NAME));
+ assertFalse(redoAction.isEnabled());
+ } else {
+ assertEquals("Redo (" + redoDesc + ")", redoAction.getValue(Action.NAME));
+ assertTrue(redoAction.isEnabled());
+ }
+ }
+
+
+ private void checkCgCp(double cgx, double mass, double cpx, double cna) {
+ Coordinate cg, cp;
+
+ cg = massCalc.getCG(config, MassCalcType.LAUNCH_MASS);
+ assertEquals(cgx, cg.x, 0.001);
+ assertEquals(mass, cg.weight, 0.0005);
+
+ cp = aeroCalc.getWorstCP(config, conditions, null);
+ assertEquals(cpx, cp.x, 0.001);
+ assertEquals(cna, cp.weight, 0.1);
+ }
+
+
+ private void checkAlt(double expected) throws SimulationException {
+ Simulation simulation = document.getSimulation(0);
+ double actual;
+
+ // Simulate + check altitude
+ simulation.simulate();
+ actual = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
+ assertEquals(expected, actual, 0.5);
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.arch;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import org.junit.Test;
+
+/*
+ * Note: These tests have not been tested on Windows, they might fail there
+ * due to a different directory separator character.
+ */
+public class TestSystemInfo {
+
+ private String osname;
+ private String userhome;
+
+
+ public void setup() {
+ this.osname = System.getProperty("os.name");
+ this.userhome = System.getProperty("user.home");
+ }
+
+ public void tearDown() {
+ System.setProperty("os.name", this.osname);
+ System.setProperty("user.home", this.userhome);
+ }
+
+ @Test
+ public void testWindows() {
+ setup();
+
+ System.setProperty("os.name", "Windows Me");
+ System.setProperty("user.home", "C:/Users/my user");
+ assertEquals(SystemInfo.Platform.WINDOWS, SystemInfo.getPlatform());
+ if (System.getenv("APPDATA") != null) {
+ assertEquals(new File(System.getenv("APPDATA") + "/OpenRocket/"), SystemInfo.getUserApplicationDirectory());
+ } else {
+ assertEquals(new File("C:/Users/my user/OpenRocket/"), SystemInfo.getUserApplicationDirectory());
+ }
+
+ tearDown();
+ }
+
+ @Test
+ public void testMacOS() {
+ setup();
+
+ System.setProperty("os.name", "Mac OS X");
+ System.setProperty("user.home", "/Users/My User");
+ assertEquals(SystemInfo.Platform.MAC_OS, SystemInfo.getPlatform());
+ assertEquals(new File("/Users/My User/Library/Application Support/OpenRocket/"),
+ SystemInfo.getUserApplicationDirectory());
+
+ tearDown();
+ }
+
+ @Test
+ public void testUnix() {
+ setup();
+
+ System.setProperty("user.home", "/home/myuser");
+ for (String os : new String[] { "Linux", "Solaris", "Foobar" }) {
+ System.setProperty("os.name", os);
+
+ assertEquals(SystemInfo.Platform.UNIX, SystemInfo.getPlatform());
+ assertEquals(new File("/home/myuser/.openrocket"), SystemInfo.getUserApplicationDirectory());
+ }
+
+ tearDown();
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.communication;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+
+import net.sf.openrocket.util.BuildProperties;
+
+import org.junit.Test;
+
+
+public class BugReportTest {
+
+ private HttpURLConnectionMock setup() {
+ HttpURLConnectionMock connection = new HttpURLConnectionMock();
+ Communicator.setConnectionSource(new ConnectionSourceStub(connection));
+
+ connection.setUseCaches(true);
+ return connection;
+ }
+
+ private void check(HttpURLConnectionMock connection) {
+ assertEquals(Communicator.BUG_REPORT_URL, connection.getTrueUrl());
+ assertTrue(connection.getConnectTimeout() > 0);
+ assertEquals(BuildProperties.getVersion(), connection.getRequestProperty("X-OpenRocket-Version"));
+ assertTrue(connection.getInstanceFollowRedirects());
+ assertEquals("POST", connection.getRequestMethod());
+ assertFalse(connection.getUseCaches());
+ }
+
+
+ @Test
+ public void testBugReportSuccess() throws IOException {
+ HttpURLConnectionMock connection = setup();
+ connection.setResponseCode(Communicator.BUG_REPORT_RESPONSE_CODE);
+
+ String message =
+ "MyMessage\n"+
+ "is important\n"+
+ "h\u00e4h?";
+
+ BugReporter.sendBugReport(message);
+
+ check(connection);
+
+ String msg = connection.getOutputStreamString();
+ assertTrue(msg.indexOf("version=" + BuildProperties.getVersion()) >= 0);
+ assertTrue(msg.indexOf(Communicator.encode(message)) >= 0);
+ }
+
+
+ @Test
+ public void testBugReportFailure() throws IOException {
+ HttpURLConnectionMock connection = setup();
+ connection.setResponseCode(200);
+
+ String message =
+ "MyMessage\n"+
+ "is important\n"+
+ "h\u00e4h?";
+
+ try {
+ BugReporter.sendBugReport(message);
+ fail("Exception did not occur");
+ } catch (IOException e) {
+ // Success
+ }
+
+ check(connection);
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.communication;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+
+public class ConnectionSourceStub implements ConnectionSource {
+
+ private final HttpURLConnection connection;
+
+ public ConnectionSourceStub(HttpURLConnection connection) {
+ this.connection = connection;
+ }
+
+ @Override
+ public HttpURLConnection getConnection(String url) throws IOException {
+ if (connection instanceof HttpURLConnectionMock) {
+ ((HttpURLConnectionMock)connection).setTrueUrl(url);
+ }
+ return connection;
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.communication;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URL;
+import java.security.Permission;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.openrocket.util.BugException;
+
+public class HttpURLConnectionMock extends HttpURLConnection {
+
+ private static final URL MOCK_URL;
+ static {
+ try {
+ MOCK_URL = new URL("http://localhost/");
+ } catch (MalformedURLException e) {
+ throw new BugException(e);
+ }
+ }
+
+ private volatile boolean instanceFollowRedirects = false;
+ private volatile String requestMethod = "";
+ private volatile int responseCode;
+ private Map<String, String> requestProperties = new HashMap<String, String>();
+ private volatile int connectTimeout = -1;
+ private volatile String contentEncoding = "";
+
+ private volatile boolean doInput = false;
+ private volatile boolean doOutput = false;
+
+ private volatile byte[] content = null;
+ private volatile String contentType = null;
+ private volatile boolean useCaches = false;
+
+
+ private volatile InputStream inputStream = null;
+ private volatile ByteArrayOutputStream outputStream = null;
+
+ private volatile String trueUrl = null;
+
+
+ private volatile boolean connected = false;
+ private volatile int connectionDelay = 0;
+
+ private volatile boolean failed = false;
+
+
+
+
+ public HttpURLConnectionMock() {
+ super(MOCK_URL);
+ }
+
+ public HttpURLConnectionMock(URL u) {
+ super(u);
+ }
+
+
+
+ public String getTrueUrl() {
+ return trueUrl;
+ }
+
+ public void setTrueUrl(String url) {
+ assertNull(this.trueUrl);
+ this.trueUrl = url;
+ }
+
+
+ public boolean hasFailed() {
+ return failed;
+ }
+
+
+ public void setConnectionDelay(int delay) {
+ this.connectionDelay = delay;
+ }
+
+
+
+ @Override
+ public void connect() {
+ if (!connected) {
+ try {
+ Thread.sleep(connectionDelay);
+ } catch (InterruptedException e) {
+ }
+ connected = true;
+ }
+ }
+
+ @Override
+ public void disconnect() {
+
+ }
+
+ @Override
+ public boolean usingProxy() {
+ return false;
+ }
+
+
+
+
+ @Override
+ public boolean getInstanceFollowRedirects() {
+ return this.instanceFollowRedirects;
+ }
+
+ @Override
+ public void setInstanceFollowRedirects(boolean followRedirects) {
+ assertFalse(connected);
+ this.instanceFollowRedirects = followRedirects;
+ }
+
+ @Override
+ public String getRequestMethod() {
+ return this.requestMethod;
+ }
+
+ @Override
+ public void setRequestMethod(String method) throws ProtocolException {
+ assertFalse(connected);
+ this.requestMethod = method;
+ }
+
+ @Override
+ public int getResponseCode() throws IOException {
+ connect();
+ return this.responseCode;
+ }
+
+ public void setResponseCode(int code) {
+ this.responseCode = code;
+ }
+
+
+ @Override
+ public void addRequestProperty(String key, String value) {
+ assertFalse(connected);
+ assertFalse(this.requestProperties.containsKey(key.toLowerCase()));
+ this.requestProperties.put(key.toLowerCase(), value);
+ }
+
+
+ @Override
+ public void setRequestProperty(String key, String value) {
+ assertFalse(connected);
+ this.requestProperties.put(key.toLowerCase(), value);
+ }
+
+
+ @Override
+ public String getRequestProperty(String key) {
+ return this.requestProperties.get(key.toLowerCase());
+ }
+
+
+ @Override
+ public int getConnectTimeout() {
+ return this.connectTimeout;
+ }
+
+ @Override
+ public void setConnectTimeout(int timeout) {
+ assertFalse(connected);
+ this.connectTimeout = timeout;
+ }
+
+
+
+ @Override
+ public String getContentEncoding() {
+ connect();
+ return this.contentEncoding;
+ }
+
+ public void setContentEncoding(String encoding) {
+ this.contentEncoding = encoding;
+ }
+
+
+
+ @Override
+ public int getContentLength() {
+ connect();
+ if (content == null)
+ return 0;
+ return content.length;
+ }
+
+ public void setContent(byte[] content) {
+ this.content = content;
+ }
+
+ public void setContent(String content) {
+ try {
+ this.content = content.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ fail("UTF-8");
+ }
+ }
+
+
+ @Override
+ public String getContentType() {
+ connect();
+ return this.contentType;
+ }
+
+ public void setContentType(String type) {
+ this.contentType = type;
+ }
+
+
+
+ @Override
+ public boolean getDoInput() {
+ return this.doInput;
+ }
+
+
+ @Override
+ public void setDoInput(boolean doinput) {
+ assertFalse(connected);
+ this.doInput = doinput;
+ }
+
+
+ @Override
+ public boolean getDoOutput() {
+ return this.doOutput;
+ }
+
+
+ @Override
+ public void setDoOutput(boolean dooutput) {
+ assertFalse(connected);
+ this.doOutput = dooutput;
+ }
+
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ assertTrue(doInput);
+ assertNull(inputStream);
+ assertNotNull(content);
+
+ connect();
+ inputStream = new ByteArrayInputStream(content);
+ return inputStream;
+ }
+
+
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ assertTrue(doOutput);
+ assertNull(outputStream);
+ outputStream = new ByteArrayOutputStream();
+ return outputStream;
+ }
+
+ public byte[] getOutputStreamData() {
+ return outputStream.toByteArray();
+ }
+
+ public String getOutputStreamString() {
+ try {
+ return outputStream.toString("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ fail("UTF-8");
+ return null;
+ }
+ }
+
+
+
+ @Override
+ public void setUseCaches(boolean usecaches) {
+ assertFalse(connected);
+ this.useCaches = usecaches;
+ }
+
+
+
+ @Override
+ public boolean getUseCaches() {
+ return this.useCaches;
+ }
+
+
+
+
+
+
+
+
+ private void assertNull(Object o) {
+ try {
+ org.junit.Assert.assertNull(o);
+ } catch (AssertionError e) {
+ failed = true;
+ throw e;
+ }
+ }
+
+ private void assertNotNull(Object o) {
+ try {
+ org.junit.Assert.assertNotNull(o);
+ } catch (AssertionError e) {
+ failed = true;
+ throw e;
+ }
+ }
+
+ private void assertTrue(boolean o) {
+ try {
+ org.junit.Assert.assertTrue(o);
+ } catch (AssertionError e) {
+ failed = true;
+ throw e;
+ }
+ }
+
+ private void assertFalse(boolean o) {
+ try {
+ org.junit.Assert.assertFalse(o);
+ } catch (AssertionError e) {
+ failed = true;
+ throw e;
+ }
+ }
+
+ private void fail(String msg) {
+ failed = true;
+ org.junit.Assert.fail(msg);
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @Override
+ public InputStream getErrorStream() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public String getHeaderField(int n) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public long getHeaderFieldDate(String name, long Default) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public String getHeaderFieldKey(int n) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public Permission getPermission() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public String getResponseMessage() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public void setChunkedStreamingMode(int chunklen) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public void setFixedLengthStreamingMode(int contentLength) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+
+
+ @Override
+ public boolean getAllowUserInteraction() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public Object getContent() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object getContent(Class[] classes) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public long getDate() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public boolean getDefaultUseCaches() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public long getExpiration() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public String getHeaderField(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public int getHeaderFieldInt(String name, int Default) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public Map<String, List<String>> getHeaderFields() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public long getIfModifiedSince() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public long getLastModified() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getReadTimeout() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public Map<String, List<String>> getRequestProperties() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public URL getURL() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ @Override
+ public void setAllowUserInteraction(boolean allowuserinteraction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setDefaultUseCaches(boolean defaultusecaches) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public void setIfModifiedSince(long ifmodifiedsince) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public void setReadTimeout(int timeout) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+
+
+ @Override
+ public String toString() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+
+}
--- /dev/null
+package net.sf.openrocket.communication;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import net.sf.openrocket.util.BuildProperties;
+import net.sf.openrocket.util.ComparablePair;
+import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
+
+import org.junit.Test;
+
+public class UpdateInfoTest extends BaseTestCase {
+
+ /** The connection delay */
+ private static final int DELAY = 100;
+
+ /** How much long does the test allow it to take */
+ private static final int ALLOWANCE = 2000;
+
+
+ private HttpURLConnectionMock setup() {
+ HttpURLConnectionMock connection = new HttpURLConnectionMock();
+ Communicator.setConnectionSource(new ConnectionSourceStub(connection));
+
+ connection.setConnectionDelay(DELAY);
+ connection.setUseCaches(true);
+ connection.setContentType("text/plain");
+ return connection;
+ }
+
+ private void check(HttpURLConnectionMock connection) {
+ assertEquals(Communicator.UPDATE_INFO_URL + "?version=" + BuildProperties.getVersion(),
+ connection.getTrueUrl());
+ assertTrue(connection.getConnectTimeout() > 0);
+ assertEquals(BuildProperties.getVersion() + "+" + BuildProperties.getBuildSource(),
+ connection.getRequestProperty("X-OpenRocket-Version"));
+ assertNotNull(connection.getRequestProperty("X-OpenRocket-Country"));
+ assertNotNull(connection.getRequestProperty("X-OpenRocket-ID"));
+ assertNotNull(connection.getRequestProperty("X-OpenRocket-OS"));
+ assertNotNull(connection.getRequestProperty("X-OpenRocket-Java"));
+ assertTrue(connection.getInstanceFollowRedirects());
+ assertEquals("GET", connection.getRequestMethod());
+ assertFalse(connection.getUseCaches());
+ }
+
+
+ @Test
+ public void testUpdateAvailable() throws IOException {
+ HttpURLConnectionMock connection = setup();
+ connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
+
+ String content =
+ "Version: 6.6.6pre A \n" +
+ "Extra: information\n" +
+ "100:hundred\n" +
+ "50: m\u00e4 \n\n" +
+ "1: one\n" +
+ "-2: none";
+ connection.setContent(content);
+
+ UpdateInfoRetriever retriever = new UpdateInfoRetriever();
+ retriever.start();
+
+ // Info is null while processing
+ assertNull(retriever.getUpdateInfo());
+
+ waitfor(retriever);
+ assertFalse(connection.hasFailed());
+
+ UpdateInfo info = retriever.getUpdateInfo();
+ assertNotNull(info);
+
+ check(connection);
+
+ assertEquals("6.6.6pre A", info.getLatestVersion());
+
+ List<ComparablePair<Integer, String>> updates = info.getUpdates();
+ assertEquals(3, updates.size());
+ Collections.sort(updates);
+ assertEquals(1, (int)updates.get(0).getU());
+ assertEquals("one", updates.get(0).getV());
+ assertEquals(50, (int)updates.get(1).getU());
+ assertEquals("m\u00e4", updates.get(1).getV());
+ assertEquals(100, (int)updates.get(2).getU());
+ assertEquals("hundred", updates.get(2).getV());
+ }
+
+
+
+
+ @Test
+ public void testUpdateNotAvailable() throws IOException {
+ HttpURLConnectionMock connection = setup();
+ connection.setResponseCode(Communicator.UPDATE_INFO_NO_UPDATE_CODE);
+
+ String content =
+ "Version: 6.6.6pre A \n" +
+ "Extra: information\n" +
+ "100:hundred\n" +
+ "50: m\u00e4 \n\n" +
+ "1: one\n" +
+ "-2: none";
+ connection.setContent(content);
+
+ UpdateInfoRetriever retriever = new UpdateInfoRetriever();
+ retriever.start();
+
+ // Info is null while processing
+ assertNull(retriever.getUpdateInfo());
+
+ waitfor(retriever);
+ assertFalse(connection.hasFailed());
+
+ UpdateInfo info = retriever.getUpdateInfo();
+ assertNotNull(info);
+
+ check(connection);
+
+ assertEquals(BuildProperties.getVersion(), info.getLatestVersion());
+ assertEquals(0, info.getUpdates().size());
+ }
+
+
+
+ @Test
+ public void testInvalidResponses() {
+ HttpURLConnectionMock connection = setup();
+ connection.setResponseCode(404);
+ connection.setContent("Version: 1.2.3");
+
+ UpdateInfoRetriever retriever = new UpdateInfoRetriever();
+ retriever.start();
+ assertNull(retriever.getUpdateInfo());
+ waitfor(retriever);
+ assertFalse(connection.hasFailed());
+ assertNull(retriever.getUpdateInfo());
+ check(connection);
+
+
+ connection = setup();
+ connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
+ connection.setContentType("text/xml");
+
+ retriever = new UpdateInfoRetriever();
+ retriever.start();
+ assertNull(retriever.getUpdateInfo());
+ waitfor(retriever);
+ assertFalse(connection.hasFailed());
+ assertNull(retriever.getUpdateInfo());
+ check(connection);
+
+
+
+ connection = setup();
+ connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
+ String content =
+ "100:hundred\n" +
+ "50: m\u00e4 \n\n" +
+ "1: one\n";
+ connection.setContent(content);
+
+ retriever = new UpdateInfoRetriever();
+ retriever.start();
+ assertNull(retriever.getUpdateInfo());
+ waitfor(retriever);
+ assertFalse(connection.hasFailed());
+ assertNull(retriever.getUpdateInfo());
+ check(connection);
+
+
+ connection = setup();
+ connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
+ connection.setContent(new byte[0]);
+
+ retriever = new UpdateInfoRetriever();
+ retriever.start();
+ assertNull(retriever.getUpdateInfo());
+ waitfor(retriever);
+ assertFalse(connection.hasFailed());
+ assertNull(retriever.getUpdateInfo());
+ check(connection);
+
+ }
+
+ @Test
+ public void testRandomInputData() {
+
+ Random rnd = new Random();
+ for (int i=0; i<10; i++) {
+ int size = (int) ((1 + 0.3 * rnd.nextGaussian()) * Math.pow(i, 6));
+ byte[] buf = new byte[size];
+ rnd.nextBytes(buf);
+
+ HttpURLConnectionMock connection = setup();
+ connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
+ connection.setContent(buf);
+
+ UpdateInfoRetriever retriever = new UpdateInfoRetriever();
+ retriever.start();
+ assertNull(retriever.getUpdateInfo());
+ waitfor(retriever);
+ assertFalse(connection.hasFailed());
+ assertNull(retriever.getUpdateInfo());
+ check(connection);
+ }
+
+ }
+
+
+
+ private void waitfor(UpdateInfoRetriever retriever) {
+ long t = System.currentTimeMillis();
+
+ while (retriever.isRunning()) {
+ if (System.currentTimeMillis() >= t+ALLOWANCE) {
+ fail("retriever took too long to respond");
+ }
+
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) { }
+ }
+
+ System.out.println("Waiting took " + (System.currentTimeMillis()-t) + " ms");
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.database;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import net.sf.openrocket.motor.Manufacturer;
+import net.sf.openrocket.motor.Motor;
+import net.sf.openrocket.motor.ThrustCurveMotor;
+import net.sf.openrocket.util.Coordinate;
+
+import org.junit.Test;
+
+
+public class MotorSetDatabaseTest {
+
+ @Test
+ public void testMotorLoading() {
+
+ ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(true) {
+ @Override
+ protected void loadMotors() {
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ this.addMotor(new ThrustCurveMotor(Manufacturer.getManufacturer("A"),
+ "Foo", "Desc", Motor.Type.SINGLE, new double[] { 0 },
+ 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
+ new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}));
+ this.addMotor(new ThrustCurveMotor(Manufacturer.getManufacturer("A"),
+ "Bar", "Desc", Motor.Type.SINGLE, new double[] { 0 },
+ 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
+ new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}));
+ this.addMotor(new ThrustCurveMotor(Manufacturer.getManufacturer("A"),
+ "Foo", "Desc", Motor.Type.UNKNOWN, new double[] { 0 },
+ 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
+ new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}));
+ }
+ };
+
+ assertFalse(db.isLoaded());
+ db.startLoading();
+ assertFalse(db.isLoaded());
+ List<ThrustCurveMotorSet> list = db.getMotorSets();
+ assertTrue(db.isLoaded());
+
+ assertEquals(2, list.size());
+ assertEquals(1, list.get(0).getMotors().size());
+ assertEquals(1, list.get(1).getMotors().size());
+ assertEquals("Bar", list.get(0).getMotors().get(0).getDesignation());
+ assertEquals("Foo", list.get(1).getMotors().get(0).getDesignation());
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.database;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import net.sf.openrocket.motor.Manufacturer;
+import net.sf.openrocket.motor.Motor;
+import net.sf.openrocket.motor.ThrustCurveMotor;
+import net.sf.openrocket.util.Coordinate;
+
+import org.junit.Test;
+
+public class ThrustCurveMotorSetTest {
+
+
+ private static final ThrustCurveMotor motor1 = new ThrustCurveMotor(
+ Manufacturer.getManufacturer("A"),
+ "F12X", "Desc", Motor.Type.UNKNOWN, new double[] { },
+ 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
+ new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL});
+
+ private static final ThrustCurveMotor motor2 = new ThrustCurveMotor(
+ Manufacturer.getManufacturer("A"),
+ "F12H", "Desc", Motor.Type.SINGLE, new double[] { 5 },
+ 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
+ new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL});
+
+ private static final ThrustCurveMotor motor3 = new ThrustCurveMotor(
+ Manufacturer.getManufacturer("A"),
+ "F12", "Desc", Motor.Type.UNKNOWN, new double[] { 0, Motor.PLUGGED },
+ 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 2, 0},
+ new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL});
+
+ private static final ThrustCurveMotor motor4 = new ThrustCurveMotor(
+ Manufacturer.getManufacturer("A"),
+ "F12", "Desc", Motor.Type.HYBRID, new double[] { 0 },
+ 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 2, 0},
+ new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL});
+
+
+ @Test
+ public void testSimplifyDesignation() {
+ assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("J115"));
+ assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation(" J115 "));
+ assertEquals("H115", ThrustCurveMotorSet.simplifyDesignation("241H115-KS"));
+ assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("384 J115"));
+ assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("384-J115"));
+ assertEquals("A2", ThrustCurveMotorSet.simplifyDesignation("A2T"));
+ assertEquals("1/2A2T", ThrustCurveMotorSet.simplifyDesignation("1/2A2T"));
+ assertEquals("Micro Maxx II", ThrustCurveMotorSet.simplifyDesignation("Micro Maxx II"));
+ }
+
+ @Test
+ public void testAdding() {
+ ThrustCurveMotorSet set = new ThrustCurveMotorSet();
+
+ // Test empty set
+ assertNull(set.getManufacturer());
+ assertEquals(0, set.getMotors().size());
+
+ // Add motor1
+ assertTrue(set.matches(motor1));
+ set.addMotor(motor1);
+ assertEquals(motor1.getManufacturer(), set.getManufacturer());
+ assertEquals(motor1.getDesignation(), set.getDesignation());
+ assertEquals(Motor.Type.UNKNOWN, set.getType());
+ assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
+ assertEquals(motor1.getLength(), set.getLength(), 0.00001);
+ assertEquals(1, set.getMotors().size());
+ assertEquals(motor1, set.getMotors().get(0));
+ assertEquals(Collections.emptyList(), set.getDelays());
+
+ // Add motor1 again
+ assertTrue(set.matches(motor1));
+ set.addMotor(motor1);
+ assertEquals(motor1.getManufacturer(), set.getManufacturer());
+ assertEquals(motor1.getDesignation(), set.getDesignation());
+ assertEquals(Motor.Type.UNKNOWN, set.getType());
+ assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
+ assertEquals(motor1.getLength(), set.getLength(), 0.00001);
+ assertEquals(1, set.getMotors().size());
+ assertEquals(motor1, set.getMotors().get(0));
+ assertEquals(Collections.emptyList(), set.getDelays());
+
+ // Add motor2
+ assertTrue(set.matches(motor2));
+ set.addMotor(motor2);
+ assertEquals(motor1.getManufacturer(), set.getManufacturer());
+ assertEquals(motor3.getDesignation(), set.getDesignation());
+ assertEquals(Motor.Type.SINGLE, set.getType());
+ assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
+ assertEquals(motor1.getLength(), set.getLength(), 0.00001);
+ assertEquals(2, set.getMotors().size());
+ assertEquals(motor2, set.getMotors().get(0));
+ assertEquals(motor1, set.getMotors().get(1));
+ assertEquals(Arrays.asList(5.0), set.getDelays());
+
+ // Add motor3
+ assertTrue(set.matches(motor3));
+ set.addMotor(motor3);
+ assertEquals(motor1.getManufacturer(), set.getManufacturer());
+ assertEquals(motor3.getDesignation(), set.getDesignation());
+ assertEquals(Motor.Type.SINGLE, set.getType());
+ assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
+ assertEquals(motor1.getLength(), set.getLength(), 0.00001);
+ assertEquals(3, set.getMotors().size());
+ assertEquals(motor3, set.getMotors().get(0));
+ assertEquals(motor2, set.getMotors().get(1));
+ assertEquals(motor1, set.getMotors().get(2));
+ assertEquals(Arrays.asList(0.0, 5.0, Motor.PLUGGED), set.getDelays());
+
+ // Test that adding motor4 fails
+ assertFalse(set.matches(motor4));
+ try {
+ set.addMotor(motor4);
+ fail("Did not throw exception");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.file.iterator;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+
+import org.junit.Test;
+
+public class TestDirectoryIterator {
+
+ @Test
+ public void testDirectoryIterator() throws IOException {
+ DirectoryIterator iterator = new DirectoryIterator(new File("test/net/sf/openrocket/file"), new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ return pathname.getName().matches("^Test(Directory|File)Iterator.java");
+ }
+ }, true);
+
+ while (iterator.hasNext()) {
+ System.out.println("" + iterator.next());
+ }
+
+ }
+}
--- /dev/null
+package net.sf.openrocket.file.iterator;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import net.sf.openrocket.util.Pair;
+
+import org.junit.Test;
+
+public class TestFileIterator {
+
+ @Test
+ public void testFileIterator() {
+ final Pair<String, InputStream> one = new Pair<String, InputStream>("one", new ByteArrayInputStream(new byte[] { 1 }));
+ final Pair<String, InputStream> two = new Pair<String, InputStream>("two", new ByteArrayInputStream(new byte[] { 2 }));
+
+ FileIterator iterator = new FileIterator() {
+ private int count = 0;
+
+ @Override
+ protected Pair<String, InputStream> findNext() {
+ count++;
+ switch (count) {
+ case 1:
+ return one;
+ case 2:
+ return two;
+ default:
+ return null;
+ }
+ }
+ };
+
+ assertTrue(iterator.hasNext());
+ assertEquals(one, iterator.next());
+ assertEquals(two, iterator.next());
+ assertFalse(iterator.hasNext());
+ }
+}
--- /dev/null
+package net.sf.openrocket.file.motor;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+
+import net.sf.openrocket.motor.Motor;
+import net.sf.openrocket.motor.MotorDigest;
+import net.sf.openrocket.motor.ThrustCurveMotor;
+
+import org.junit.Test;
+
+public class TestMotorLoader {
+
+ @Test
+ public void testGeneralMotorLoader() throws IOException {
+ MotorLoader loader = new GeneralMotorLoader();
+
+ test(loader, "test1.eng", "c056cf25df6751f7bb8a94bc4f64750f");
+ test(loader, "test2.rse", "b2fe203ee319ae28b9ccdad26a8f21de");
+ test(loader, "test.zip", "b2fe203ee319ae28b9ccdad26a8f21de", "c056cf25df6751f7bb8a94bc4f64750f");
+
+ }
+
+ @Test
+ public void testRASPMotorLoader() throws IOException {
+ test(new RASPMotorLoader(), "test1.eng", "c056cf25df6751f7bb8a94bc4f64750f");
+ }
+
+ @Test
+ public void testRocksimMotorLoader() throws IOException {
+ test(new RockSimMotorLoader(), "test2.rse", "b2fe203ee319ae28b9ccdad26a8f21de");
+ }
+
+ @Test
+ public void testZipMotorLoader() throws IOException {
+ test(new ZipFileMotorLoader(), "test.zip", "b2fe203ee319ae28b9ccdad26a8f21de", "c056cf25df6751f7bb8a94bc4f64750f");
+ }
+
+
+ private void test(MotorLoader loader, String file, String... digests) throws IOException {
+ List<Motor> motors;
+
+ InputStream is = this.getClass().getResourceAsStream(file);
+ assertNotNull("File " + file + " not found", is);
+ motors = loader.load(is, file);
+ is.close();
+ assertEquals(digests.length, motors.size());
+
+ String[] d = new String[digests.length];
+ for (int i = 0; i < motors.size(); i++) {
+ d[i] = MotorDigest.digestMotor((ThrustCurveMotor) motors.get(i));
+ }
+
+ Arrays.sort(digests);
+ Arrays.sort(d);
+ assertTrue(Arrays.equals(d, digests));
+ }
+
+}
--- /dev/null
+D10 18 70 7 0.009800000000000001 0.0259 AT\r
+ 0.0070 23.0\r
+ 0.018 25.0\r
+ 0.027 20.25\r
+ 0.066 20.25\r
+ 0.073 18.5\r
+ 0.094 20.25\r
+ 0.112 20.75\r
+ 0.137 19.75\r
+ 0.163 21.5\r
+ 0.202 20.75\r
+ 0.231 20.75\r
+ 0.254 22.75\r
+ 0.27 20.75\r
+ 0.504 20.0\r
+ 0.536 18.25\r
+ 0.607 17.0\r
+ 0.687 14.75\r
+ 0.751 14.25\r
+ 0.84 11.25\r
+ 0.998 8.25\r
+ 1.024 8.25\r
+ 1.248 2.5\r
+ 1.385 0.0\r
--- /dev/null
+<engine-database>\r
+ <engine-list>\r
+ <engine mfg="Cesaroni Technology Inc." code="G115-13A" Type="reloadable" dia="38."\r
+len="127." initWt="195." propWt="61.8" delays="13" auto-calc-mass="1"\r
+auto-calc-cg="1" avgThrust="113.512" peakThrust="131.895" throatDia="0."\r
+exitDia="0." Itot="140.755" burn-time="1.24" massFrac="31.69" Isp="232.25"\r
+tDiv="10" tStep="-1." tFix="1" FDiv="10" FStep="-1." FFix="1" mDiv="10"\r
+mStep="-1." mFix="1" cgDiv="10" cgStep="-1." cgFix="1">\r
+ <data>\r
+ <eng-data t="0." f="0." m="61.8" cg="63.5"/>\r
+ <eng-data t="0.00787402" f="10.3447" m="61.7821" cg="63.5"/>\r
+ <eng-data t="0.0183727" f="117.671" m="61.4871" cg="63.5"/>\r
+ <eng-data t="0.0209974" f="128.447" m="61.3453" cg="63.5"/>\r
+ <eng-data t="0.0446194" f="131.895" m="59.9952" cg="63.5"/>\r
+ <eng-data t="0.0577428" f="125.861" m="59.2526" cg="63.5"/>\r
+ <eng-data t="0.0629921" f="119.395" m="58.97" cg="63.5"/>\r
+ <eng-data t="0.0787402" f="113.792" m="58.1638" cg="63.5"/>\r
+ <eng-data t="0.107612" f="115.947" m="56.7077" cg="63.5"/>\r
+ <eng-data t="0.149606" f="118.964" m="54.542" cg="63.5"/>\r
+ <eng-data t="0.188976" f="119.395" m="52.4819" cg="63.5"/>\r
+ <eng-data t="0.233596" f="121.981" m="50.1176" cg="63.5"/>\r
+ <eng-data t="0.278215" f="122.412" m="47.7237" cg="63.5"/>\r
+ <eng-data t="0.322835" f="122.843" m="45.3213" cg="63.5"/>\r
+ <eng-data t="0.380577" f="123.274" m="42.2014" cg="63.5"/>\r
+ <eng-data t="0.440945" f="122.843" m="38.9398" cg="63.5"/>\r
+ <eng-data t="0.480315" f="123.274" m="36.8126" cg="63.5"/>\r
+ <eng-data t="0.540682" f="122.843" m="33.5509" cg="63.5"/>\r
+ <eng-data t="0.590551" f="122.412" m="30.866" cg="63.5"/>\r
+ <eng-data t="0.622047" f="120.688" m="29.1851" cg="63.5"/>\r
+ <eng-data t="0.67979" f="120.257" m="26.1308" cg="63.5"/>\r
+ <eng-data t="0.734908" f="119.395" m="23.231" cg="63.5"/>\r
+ <eng-data t="0.790026" f="117.671" m="20.3625" cg="63.5"/>\r
+ <eng-data t="0.845144" f="116.809" m="17.5253" cg="63.5"/>\r
+ <eng-data t="0.88189" f="116.378" m="15.6442" cg="63.5"/>\r
+ <eng-data t="0.929134" f="113.361" m="13.2615" cg="63.5"/>\r
+ <eng-data t="0.979003" f="113.361" m="10.7794" cg="63.5"/>\r
+ <eng-data t="1.0315" f="111.206" m="8.19152" cg="63.5"/>\r
+ <eng-data t="1.07087" f="108.188" m="6.29532" cg="63.5"/>\r
+ <eng-data t="1.11286" f="108.188" m="4.30052" cg="63.5"/>\r
+ <eng-data t="1.16535" f="106.033" m="1.83186" cg="63.5"/>\r
+ <eng-data t="1.18373" f="112.499" m="0.95044" cg="63.5"/>\r
+ <eng-data t="1.18635" f="96.5506" m="0.829987" cg="63.5"/>\r
+ <eng-data t="1.19685" f="81.0335" m="0.420696" cg="63.5"/>\r
+ <eng-data t="1.2021" f="51.7235" m="0.267708" cg="63.5"/>\r
+ <eng-data t="1.2126" f="30.172" m="0.0789575" cg="63.5"/>\r
+ <eng-data t="1.21522" f="16.8101" m="0.0518866" cg="63.5"/>\r
+ <eng-data t="1.21785" f="7.75853" m="0.0377303" cg="63.5"/>\r
+ <eng-data t="1.24" f="0." m="0." cg="63.5"/>\r
+ </data>\r
+ </engine>\r
+</engine-list>\r
+</engine-database>\r
--- /dev/null
+package net.sf.openrocket.file.rocksim.export;
+
+import net.sf.openrocket.document.OpenRocketDocument;
+import net.sf.openrocket.file.rocksim.importt.RocksimLoader;
+import net.sf.openrocket.file.rocksim.importt.RocksimLoaderTest;
+import net.sf.openrocket.file.rocksim.importt.RocksimTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.StringWriter;
+
+/**
+ */
+public class RocksimDocumentDTOTest extends RocksimTestBase {
+
+ @Test
+ public void testDTO() throws Exception {
+ JAXBContext binder = JAXBContext.newInstance(RocksimDocumentDTO.class);
+ Marshaller marshaller = binder.createMarshaller();
+ marshaller.setProperty("jaxb.fragment", Boolean.TRUE);
+
+ NoseConeDTO noseCone = new NoseConeDTO();
+ noseCone.setBaseDia(10d);
+ noseCone.setCalcCG(1.3d);
+
+ StageDTO stage1 = new StageDTO();
+ stage1.addExternalPart(noseCone);
+
+ RocketDesignDTO design2 = new RocketDesignDTO();
+ design2.setName("Test");
+ design2.setStage3(stage1);
+
+ RocksimDesignDTO design = new RocksimDesignDTO();
+ design.setDesign(design2);
+ RocksimDocumentDTO message = new RocksimDocumentDTO();
+ message.setDesign(design);
+
+
+ StringWriter stringWriter = new StringWriter();
+ marshaller.marshal(message, stringWriter);
+
+ String response = stringWriter.toString();
+
+ System.err.println(response);
+ }
+
+ @Test
+ public void testRoundTrip() throws Exception {
+ OpenRocketDocument ord = RocksimLoaderTest.loadRocksimRocket3(new RocksimLoader());
+
+ Assert.assertNotNull(ord);
+ String result = new RocksimSaver().marshalToRocksim(ord);
+
+// System.err.println(result);
+
+ File output = new File("rt.rkt");
+ FileWriter fw = new FileWriter(output);
+ fw.write(result);
+ fw.flush();
+ fw.close();
+ }
+}
--- /dev/null
+/*
+ * BodyTubeHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.file.simplesax.PlainTextHandler;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.ExternalComponent;
+import net.sf.openrocket.rocketcomponent.Stage;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+/**
+ * BodyTubeHandler Tester.
+ *
+ */
+public class BodyTubeHandlerTest extends RocksimTestBase {
+
+ /**
+ * Method: constructor
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new BodyTubeHandler(null, new WarningSet());
+ Assert.fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException iae) {
+ //success
+ }
+
+ Stage stage = new Stage();
+ BodyTubeHandler handler = new BodyTubeHandler(stage, new WarningSet());
+ BodyTube component = (BodyTube) getField(handler, "bodyTube");
+ assertContains(component, stage.getChildren());
+ }
+
+ /**
+ * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testOpenElement() throws Exception {
+ Assert.assertEquals(PlainTextHandler.INSTANCE, new BodyTubeHandler(new Stage(), new WarningSet()).openElement(null, null, null));
+ Assert.assertNotNull(new BodyTubeHandler(new Stage(), new WarningSet()).openElement("AttachedParts", null, null));
+ }
+
+ /**
+ *
+ * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testCloseElement() throws Exception {
+ Stage stage = new Stage();
+ BodyTubeHandler handler = new BodyTubeHandler(stage, new WarningSet());
+ BodyTube component = (BodyTube) getField(handler, "bodyTube");
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("OD", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("OD", attributes, "0", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("OD", attributes, "75", warnings);
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
+ handler.closeElement("OD", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("ID", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "0", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "75", warnings);
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Len", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("IsMotorMount", attributes, "1", warnings);
+ Assert.assertTrue(component.isMotorMount());
+ handler.closeElement("IsMotorMount", attributes, "0", warnings);
+ Assert.assertFalse(component.isMotorMount());
+ handler.closeElement("IsMotorMount", attributes, "foo", warnings);
+ Assert.assertFalse(component.isMotorMount());
+
+ handler.closeElement("EngineOverhang", attributes, "-1", warnings);
+ Assert.assertEquals(-1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
+ handler.closeElement("EngineOverhang", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
+ handler.closeElement("EngineOverhang", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
+ handler.closeElement("EngineOverhang", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("FinishCode", attributes, "-1", warnings);
+ Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
+ handler.closeElement("FinishCode", attributes, "100", warnings);
+ Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
+ handler.closeElement("FinishCode", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ Assert.assertEquals("Test Name", component.getName());
+ }
+
+ /**
+ * Method: getComponent()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testGetComponent() throws Exception {
+ Assert.assertTrue(new BodyTubeHandler(new Stage(), new WarningSet()).getComponent() instanceof BodyTube);
+ }
+
+ /**
+ * Method: getMaterialType()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testGetMaterialType() throws Exception {
+ Assert.assertEquals(Material.Type.BULK, new BodyTubeHandler(new Stage(), new WarningSet()).getMaterialType());
+ }
+
+}
--- /dev/null
+/*
+ * FinSetHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import junit.framework.TestCase;
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
+import net.sf.openrocket.rocketcomponent.FinSet;
+import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
+import net.sf.openrocket.util.Coordinate;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+/**
+ * FinSetHandler Tester.
+ *
+ */
+public class FinSetHandlerTest extends TestCase {
+
+ /**
+ * Method: asOpenRocket(WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testAsOpenRocket() throws Exception {
+
+ FinSetHandler dto = new FinSetHandler(new BodyTube());
+
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ dto.closeElement("Name", attributes, "The name", warnings);
+ dto.closeElement("ShapeCode", attributes, "0", warnings);
+ dto.closeElement("Xb", attributes, "2", warnings);
+ dto.closeElement("FinCount", attributes, "4", warnings);
+ dto.closeElement("RootChord", attributes, "10", warnings);
+ dto.closeElement("TipChord", attributes, "11", warnings);
+ dto.closeElement("SemiSpan", attributes, "12", warnings);
+ dto.closeElement("MidChordLen", attributes, "13", warnings);
+ dto.closeElement("SweepDistance", attributes, "14", warnings);
+ dto.closeElement("Thickness", attributes, "200", warnings);
+ dto.closeElement("TipShapeCode", attributes, "1", warnings);
+ dto.closeElement("TabLength", attributes, "400", warnings);
+ dto.closeElement("TabDepth", attributes, "500", warnings);
+ dto.closeElement("TabOffset", attributes, "30", warnings);
+ dto.closeElement("RadialAngle", attributes, ".123", warnings);
+ dto.closeElement("PointList", attributes, "20,0|2,2|0,0", warnings);
+ dto.closeElement("LocationMode", attributes, "0", warnings);
+
+ WarningSet set = new WarningSet();
+ FinSet fins = dto.asOpenRocket(set);
+ assertNotNull(fins);
+ assertEquals(0, set.size());
+
+ assertEquals("The name", fins.getName());
+ assertTrue(fins instanceof TrapezoidFinSet);
+ assertEquals(4, fins.getFinCount());
+
+ assertEquals(0.012d, ((TrapezoidFinSet) fins).getHeight());
+ assertEquals(0.012d, fins.getSpan());
+
+ assertEquals(0.2d, fins.getThickness());
+ assertEquals(0.4d, fins.getTabLength());
+ assertEquals(0.5d, fins.getTabHeight());
+ assertEquals(0.03d, fins.getTabShift());
+ assertEquals(.123d, fins.getBaseRotation());
+
+ dto.closeElement("ShapeCode", attributes, "1", warnings);
+ fins = dto.asOpenRocket(set);
+ assertNotNull(fins);
+ assertEquals(0, set.size());
+
+ assertEquals("The name", fins.getName());
+ assertTrue(fins instanceof EllipticalFinSet);
+ assertEquals(4, fins.getFinCount());
+
+ assertEquals(0.2d, fins.getThickness());
+ assertEquals(0.4d, fins.getTabLength());
+ assertEquals(0.5d, fins.getTabHeight());
+ assertEquals(0.03d, fins.getTabShift());
+ assertEquals(.123d, fins.getBaseRotation());
+ }
+
+
+ /**
+ * Method: toCoordinates(String pointList)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testToCoordinates() throws Exception {
+ FinSetHandler holder = new FinSetHandler(new BodyTube());
+ Method method = FinSetHandler.class.getDeclaredMethod("toCoordinates", String.class, WarningSet.class);
+ method.setAccessible(true);
+
+ WarningSet warnings = new WarningSet();
+ //Null finlist
+ String finlist = null;
+ Coordinate[] result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(0 == result.length);
+
+ //Empty string finlist
+ finlist = "";
+ result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(0 == result.length);
+
+ //Invalid finlist (only x coordinate)
+ finlist = "10.0";
+ result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(0 == result.length);
+ assertEquals(1, warnings.size());
+ warnings.clear();
+
+ //Invalid finlist (non-numeric character)
+ finlist = "10.0,asdf";
+ result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(0 == result.length);
+ assertEquals(1, warnings.size());
+ warnings.clear();
+
+ //Invalid finlist (all delimiters)
+ finlist = "||||||";
+ result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(0 == result.length);
+ assertEquals(0, warnings.size());
+ warnings.clear();
+
+ //One point finlist - from a parsing view it's valid; from a practical view it may not be, but that's outside
+ //the scope of this test case
+ finlist = "10.0,5.0";
+ result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(1 == result.length);
+ assertEquals(0, warnings.size());
+ warnings.clear();
+
+ //Two point finlist - from a parsing view it's valid; from a practical view it may not be, but that's outside
+ //the scope of this test case
+ finlist = "10.0,5.0|3.3,4.4";
+ result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(2 == result.length);
+ assertEquals(0, warnings.size());
+ warnings.clear();
+
+ //Normal four point finlist.
+ finlist = "518.16,0|517.494,37.2145|1.31261,6.77283|0,0|";
+ result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(4 == result.length);
+ assertEquals(new Coordinate(0,0), result[0]);
+ assertEquals(0, warnings.size());
+ warnings.clear();
+
+ //Normal four point finlist with spaces.
+ finlist = "518.16 , 0 | 517.494 , 37.2145 | 1.31261,6.77283|0,0|";
+ result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(4 == result.length);
+ assertEquals(new Coordinate(0,0), result[0]);
+ assertEquals(new Coordinate(.51816,0), result[3]);
+ assertEquals(0, warnings.size());
+ warnings.clear();
+
+ //Reversed Normal four point finlist.
+ finlist = "0,0|1.31261,6.77283|517.494,37.2145|518.16,0|";
+ result = (Coordinate[])method.invoke(holder, finlist, warnings);
+ assertNotNull(result);
+ assertTrue(4 == result.length);
+ assertEquals(new Coordinate(0,0), result[0]);
+ assertEquals(new Coordinate(.51816,0), result[3]);
+ assertEquals(0, warnings.size());
+ warnings.clear();
+
+ }
+}
--- /dev/null
+/*
+ * InnerBodyTubeHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.file.simplesax.PlainTextHandler;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.InnerTube;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import org.junit.Assert;
+
+import java.util.HashMap;
+
+/**
+ * InnerBodyTubeHandler Tester.
+ *
+ */
+public class InnerBodyTubeHandlerTest extends RocksimTestBase {
+
+ /**
+ * Method: constructor
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new InnerBodyTubeHandler(null, new WarningSet());
+ Assert.fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException iae) {
+ //success
+ }
+
+ BodyTube tube = new BodyTube();
+ InnerBodyTubeHandler handler = new InnerBodyTubeHandler(tube, new WarningSet());
+ InnerTube component = (InnerTube) getField(handler, "bodyTube");
+ assertContains(component, tube.getChildren());
+ }
+
+ /**
+ * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testOpenElement() throws Exception {
+ Assert.assertEquals(PlainTextHandler.INSTANCE, new InnerBodyTubeHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
+ Assert.assertNotNull(new InnerBodyTubeHandler(new BodyTube(), new WarningSet()).openElement("AttachedParts", null, null));
+ }
+
+ /**
+ *
+ * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testCloseElement() throws Exception {
+ BodyTube tube = new BodyTube();
+ InnerBodyTubeHandler handler = new InnerBodyTubeHandler(tube, new WarningSet());
+ InnerTube component = (InnerTube) getField(handler, "bodyTube");
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("OD", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("OD", attributes, "0", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("OD", attributes, "75", warnings);
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
+ handler.closeElement("OD", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("ID", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "0", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "75", warnings);
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Len", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("IsMotorMount", attributes, "1", warnings);
+ Assert.assertTrue(component.isMotorMount());
+ handler.closeElement("IsMotorMount", attributes, "0", warnings);
+ Assert.assertFalse(component.isMotorMount());
+ handler.closeElement("IsMotorMount", attributes, "foo", warnings);
+ Assert.assertFalse(component.isMotorMount());
+
+ handler.closeElement("EngineOverhang", attributes, "-1", warnings);
+ Assert.assertEquals(-1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
+ handler.closeElement("EngineOverhang", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
+ handler.closeElement("EngineOverhang", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
+ handler.closeElement("EngineOverhang", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ Assert.assertEquals("Test Name", component.getName());
+ }
+
+ /**
+ * Method: setRelativePosition(RocketComponent.Position position)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testSetRelativePosition() throws Exception {
+ BodyTube tube = new BodyTube();
+ InnerBodyTubeHandler handler = new InnerBodyTubeHandler(tube, new WarningSet());
+ InnerTube component = (InnerTube) getField(handler, "bodyTube");
+ handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
+ Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
+ }
+
+ /**
+ * Method: getComponent()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetComponent() throws Exception {
+ Assert.assertTrue(new InnerBodyTubeHandler(new BodyTube(), new WarningSet()).getComponent() instanceof InnerTube);
+ }
+
+ /**
+ * Method: getMaterialType()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetMaterialType() throws Exception {
+ Assert.assertEquals(Material.Type.BULK, new InnerBodyTubeHandler(new BodyTube(), new WarningSet()).getMaterialType());
+ }
+
+}
--- /dev/null
+/*
+ * LaunchLugHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.file.simplesax.PlainTextHandler;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.ExternalComponent;
+import net.sf.openrocket.rocketcomponent.LaunchLug;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import org.junit.Assert;
+
+import java.util.HashMap;
+
+/**
+ * LaunchLugHandler Tester.
+ *
+ */
+public class LaunchLugHandlerTest extends RocksimTestBase {
+
+ /**
+ * Method: constructor
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new LaunchLugHandler(null, new WarningSet());
+ Assert.fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException iae) {
+ //success
+ }
+
+ BodyTube tube = new BodyTube();
+ LaunchLugHandler handler = new LaunchLugHandler(tube, new WarningSet());
+ LaunchLug component = (LaunchLug) getField(handler, "lug");
+ assertContains(component, tube.getChildren());
+ }
+
+ /**
+ * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testOpenElement() throws Exception {
+ Assert.assertEquals(PlainTextHandler.INSTANCE, new LaunchLugHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
+ }
+
+ /**
+ *
+ * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testCloseElement() throws Exception {
+ BodyTube tube = new BodyTube();
+ LaunchLugHandler handler = new LaunchLugHandler(tube, new WarningSet());
+ LaunchLug component = (LaunchLug) getField(handler, "lug");
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("OD", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getOuterRadius(), 0.001);
+ handler.closeElement("OD", attributes, "0", warnings);
+ Assert.assertEquals(0d, component.getOuterRadius(), 0.001);
+ handler.closeElement("OD", attributes, "75", warnings);
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getOuterRadius(), 0.001);
+ handler.closeElement("OD", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("ID", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "0", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "75", warnings);
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Len", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("FinishCode", attributes, "-1", warnings);
+ Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
+ handler.closeElement("FinishCode", attributes, "100", warnings);
+ Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
+ handler.closeElement("FinishCode", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ Assert.assertEquals("Test Name", component.getName());
+ }
+
+ /**
+ * Method: setRelativePosition(RocketComponent.Position position)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testSetRelativePosition() throws Exception {
+ BodyTube tube = new BodyTube();
+ LaunchLugHandler handler = new LaunchLugHandler(tube, new WarningSet());
+ LaunchLug component = (LaunchLug) getField(handler, "lug");
+ handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
+ Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
+ }
+
+ /**
+ * Method: getComponent()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetComponent() throws Exception {
+ Assert.assertTrue(new LaunchLugHandler(new BodyTube(), new WarningSet()).getComponent() instanceof LaunchLug);
+ }
+
+ /**
+ * Method: getMaterialType()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetMaterialType() throws Exception {
+ Assert.assertEquals(Material.Type.BULK, new LaunchLugHandler(new BodyTube(), new WarningSet()).getMaterialType());
+ }
+
+
+}
--- /dev/null
+/*
+ * MassObjectHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.file.simplesax.PlainTextHandler;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.MassComponent;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import org.junit.Assert;
+
+import java.util.HashMap;
+
+/**
+ * MassObjectHandler Tester.
+ *
+ */
+public class MassObjectHandlerTest extends RocksimTestBase {
+
+ /**
+ * Method: constructor
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new MassObjectHandler(null, new WarningSet());
+ Assert.fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException iae) {
+ //success
+ }
+
+ BodyTube tube = new BodyTube();
+ MassObjectHandler handler = new MassObjectHandler(tube, new WarningSet());
+ MassComponent component = (MassComponent) getField(handler, "mass");
+ assertContains(component, tube.getChildren());
+ }
+
+ /**
+ * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testOpenElement() throws Exception {
+ Assert.assertEquals(PlainTextHandler.INSTANCE, new MassObjectHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
+ }
+
+ /**
+ *
+ * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testCloseElement() throws Exception {
+ BodyTube tube = new BodyTube();
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ MassObjectHandler handler = new MassObjectHandler(tube, new WarningSet());
+ MassComponent component = (MassComponent) getField(handler, "mass");
+
+ handler.closeElement("Len", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10", warnings);
+ Assert.assertEquals(10d / (MassObjectHandler.MASS_LEN_FUDGE_FACTOR * RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH)
+ , component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / (MassObjectHandler.MASS_LEN_FUDGE_FACTOR * RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH)
+ , component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("KnownMass", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getComponentMass(), 0.001);
+ handler.closeElement("KnownMass", attributes, "100", warnings);
+ Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_MASS, component.getComponentMass(), 0.001);
+ handler.closeElement("KnownMass", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ }
+
+ /**
+ * Method: setRelativePosition(RocketComponent.Position position)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testSetRelativePosition() throws Exception {
+ BodyTube tube = new BodyTube();
+ MassObjectHandler handler = new MassObjectHandler(tube, new WarningSet());
+ MassComponent component = (MassComponent) getField(handler, "mass");
+ handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
+ Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
+ }
+
+ /**
+ * Method: getComponent()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetComponent() throws Exception {
+ Assert.assertTrue(new MassObjectHandler(new BodyTube(), new WarningSet()).getComponent() instanceof MassComponent);
+ }
+
+ /**
+ * Method: getMaterialType()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetMaterialType() throws Exception {
+ Assert.assertEquals(Material.Type.BULK, new MassObjectHandler(new BodyTube(), new WarningSet()).getMaterialType());
+ }
+}
--- /dev/null
+/*
+ * NoseConeHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.file.simplesax.PlainTextHandler;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.rocketcomponent.ExternalComponent;
+import net.sf.openrocket.rocketcomponent.NoseCone;
+import net.sf.openrocket.rocketcomponent.Stage;
+import net.sf.openrocket.rocketcomponent.Transition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+/**
+ * NoseConeHandler Tester.
+ *
+ */
+public class NoseConeHandlerTest extends RocksimTestBase {
+
+ /**
+ * Method: constructor
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new NoseConeHandler(null, new WarningSet());
+ Assert.fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException iae) {
+ //success
+ }
+
+ Stage stage = new Stage();
+ NoseConeHandler handler = new NoseConeHandler(stage, new WarningSet());
+ NoseCone component = (NoseCone) getField(handler, "noseCone");
+ assertContains(component, stage.getChildren());
+ }
+
+ /**
+ * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testOpenElement() throws Exception {
+ Assert.assertEquals(PlainTextHandler.INSTANCE, new NoseConeHandler(new Stage(), new WarningSet()).openElement(null, null, null));
+ Assert.assertNotNull(new NoseConeHandler(new Stage(), new WarningSet()).openElement("AttachedParts", null, null));
+ }
+
+ /**
+ *
+ * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testCloseElement() throws Exception {
+
+ Stage stage = new Stage();
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ NoseConeHandler handler = new NoseConeHandler(stage, warnings);
+ NoseCone component = (NoseCone) getField(handler, "noseCone");
+
+ handler.closeElement("ShapeCode", attributes, "0", warnings);
+ Assert.assertEquals(Transition.Shape.CONICAL, component.getType());
+ handler.closeElement("ShapeCode", attributes, "1", warnings);
+ Assert.assertEquals(Transition.Shape.OGIVE, component.getType());
+ handler.closeElement("ShapeCode", attributes, "17", warnings);
+ Assert.assertEquals(RocksimNoseConeCode.PARABOLIC.asOpenRocket(), component.getType()); //test of default
+ handler.closeElement("ShapeCode", attributes, "foo", warnings);
+ Assert.assertNotNull(component.getType());
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Len", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("BaseDia", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getAftRadius(), 0.001);
+ handler.closeElement("BaseDia", attributes, "100", warnings);
+ Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getAftRadius(), 0.001);
+ handler.closeElement("BaseDia", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+
+ final double aft = 100d;
+ component.setAftRadius(aft);
+
+ handler.closeElement("ConstructionType", attributes, "0", warnings);
+ component.setAftShoulderRadius(1.1d);
+ handler.closeElement("WallThickness", attributes, "-1", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(component.getAftRadius(), component.getThickness(), 0.001);
+ Assert.assertEquals(component.getAftShoulderThickness(), component.getAftShoulderThickness(), 0.001);
+ handler.closeElement("WallThickness", attributes, "100", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(aft, component.getThickness(), 0.001);
+ handler.closeElement("WallThickness", attributes, "foo", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("ConstructionType", attributes, "1", warnings);
+ component.setAftShoulderRadius(1.1d);
+ handler.closeElement("WallThickness", attributes, "-1", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(0d, component.getThickness(), 0.001);
+ Assert.assertEquals(0d, component.getAftShoulderThickness(), 0.001);
+ handler.closeElement("WallThickness", attributes, "1.1", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getThickness(), 0.001);
+ Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderThickness(), 0.001);
+
+ handler.closeElement("ShoulderLen", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getAftShoulderLength(), 0.001);
+ handler.closeElement("ShoulderLen", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderLength(), 0.001);
+ handler.closeElement("ShoulderLen", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderLength(), 0.001);
+ handler.closeElement("ShoulderLen", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("ShoulderOD", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getAftShoulderRadius(), 0.001);
+ handler.closeElement("ShoulderOD", attributes, "100", warnings);
+ Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getAftShoulderRadius(), 0.001);
+ handler.closeElement("ShoulderOD", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ component.setType(Transition.Shape.HAACK);
+ handler.closeElement("ShapeParameter", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getShapeParameter(), 0.001);
+ handler.closeElement("ShapeParameter", attributes, "100", warnings);
+ Assert.assertEquals(Transition.Shape.HAACK.maxParameter(), component.getShapeParameter(), 0.001);
+ handler.closeElement("ShapeParameter", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ Assert.assertEquals("Could not convert ShapeParameter value of foo. It is expected to be a number.",
+ warnings.iterator().next().toString());
+
+ warnings.clear();
+
+ component.setType(Transition.Shape.CONICAL);
+ component.setShapeParameter(0d);
+ handler.closeElement("ShapeParameter", attributes, "100", warnings);
+ Assert.assertEquals(0d, component.getShapeParameter(), 0.001);
+
+ handler.closeElement("FinishCode", attributes, "-1", warnings);
+ Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
+ handler.closeElement("FinishCode", attributes, "100", warnings);
+ Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
+ handler.closeElement("FinishCode", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ Assert.assertEquals("Test Name", component.getName());
+
+ handler.closeElement("Material", attributes, "Some Material", warnings);
+ handler.endHandler("NoseCone", attributes, null, warnings);
+ Assert.assertTrue(component.getMaterial().getName().contains("Some Material"));
+ }
+
+ /**
+ * Method: getComponent()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testGetComponent() throws Exception {
+ Assert.assertTrue(new NoseConeHandler(new Stage(), new WarningSet()).getComponent() instanceof NoseCone);
+ }
+
+ /**
+ * Method: getMaterialType()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testGetMaterialType() throws Exception {
+ Assert.assertEquals(Material.Type.BULK, new NoseConeHandler(new Stage(), new WarningSet()).getMaterialType());
+ }
+}
--- /dev/null
+/*
+ * ParachuteHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.file.simplesax.PlainTextHandler;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.Parachute;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import org.junit.Assert;
+
+import java.util.HashMap;
+
+/**
+ * ParachuteHandler Tester.
+ */
+public class ParachuteHandlerTest extends RocksimTestBase {
+
+ /**
+ * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testOpenElement() throws Exception {
+ Assert.assertEquals(PlainTextHandler.INSTANCE, new ParachuteHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
+ }
+
+ /**
+ * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testCloseElement() throws Exception {
+
+ BodyTube tube = new BodyTube();
+ ParachuteHandler handler = new ParachuteHandler(tube, new WarningSet());
+ Parachute component = (Parachute) getField(handler, "chute");
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ Assert.assertEquals("Test Name", component.getName());
+
+ handler.closeElement("DragCoefficient", attributes, "0.94", warnings);
+ Assert.assertEquals(0.94d, component.getCD(), 0.001);
+ handler.closeElement("DragCoefficient", attributes, "-0.94", warnings);
+ Assert.assertEquals(-0.94d, component.getCD(), 0.001);
+ handler.closeElement("DragCoefficient", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Dia", attributes, "-1", warnings);
+ Assert.assertEquals(-1d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getDiameter(), 0.001);
+ handler.closeElement("Dia", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getDiameter(), 0.001);
+ handler.closeElement("Dia", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("ShroudLineCount", attributes, "-1", warnings);
+ Assert.assertEquals(0, component.getLineCount());
+ handler.closeElement("ShroudLineCount", attributes, "10", warnings);
+ Assert.assertEquals(10, component.getLineCount());
+ handler.closeElement("ShroudLineCount", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("ShroudLineLen", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getLineLength(), 0.001);
+ handler.closeElement("ShroudLineLen", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLineLength(), 0.001);
+ handler.closeElement("ShroudLineLen", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ }
+
+ /**
+ * Method: constructor
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new ParachuteHandler(null, new WarningSet());
+ Assert.fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException iae) {
+ //success
+ }
+
+ BodyTube tube = new BodyTube();
+ ParachuteHandler handler = new ParachuteHandler(tube, new WarningSet());
+ Parachute component = (Parachute) getField(handler, "chute");
+ assertContains(component, tube.getChildren());
+ }
+
+ /**
+ * Method: setRelativePosition(RocketComponent.Position position)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testSetRelativePosition() throws Exception {
+ BodyTube tube = new BodyTube();
+ ParachuteHandler handler = new ParachuteHandler(tube, new WarningSet());
+ Parachute component = (Parachute) getField(handler, "chute");
+ handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
+ Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
+ }
+
+ /**
+ * Method: getComponent()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetComponent() throws Exception {
+ Assert.assertTrue(new ParachuteHandler(new BodyTube(), new WarningSet()).getComponent() instanceof Parachute);
+ }
+
+ /**
+ * Method: getMaterialType()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetMaterialType() throws Exception {
+ Assert.assertEquals(Material.Type.SURFACE, new ParachuteHandler(new BodyTube(), new WarningSet()).getMaterialType());
+ }
+
+ /**
+ * Method: endHandler()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testEndHandler() throws Exception {
+ BodyTube tube = new BodyTube();
+ ParachuteHandler handler = new ParachuteHandler(tube, new WarningSet());
+ Parachute component = (Parachute) getField(handler, "chute");
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("Xb", attributes, "-10", warnings);
+ handler.closeElement("LocationMode", attributes, "1", warnings);
+ handler.endHandler("Parachute", attributes, null, warnings);
+ Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
+ Assert.assertEquals(component.getPositionValue(), -10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, 0.001);
+
+ handler.closeElement("Xb", attributes, "-10", warnings);
+ handler.closeElement("LocationMode", attributes, "2", warnings);
+ handler.endHandler("Parachute", attributes, null, warnings);
+ Assert.assertEquals(RocketComponent.Position.BOTTOM, component.getRelativePosition());
+ Assert.assertEquals(component.getPositionValue(), 10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, 0.001);
+ }
+}
--- /dev/null
+<RockSimDocument>
+ <FileVersion>4</FileVersion>
+ <DesignInformation>
+ <RocketDesign>
+ <CalculateCD>1</CalculateCD>
+ <ProCalculateCD>1</ProCalculateCD>
+ <ProCalculateCN>1</ProCalculateCN>
+ <FixedCd>0.75</FixedCd>
+ <FixedCd2>0.8</FixedCd2>
+ <FixedCd3>0.81</FixedCd3>
+ <FixedCd2Alone>0.95</FixedCd2Alone>
+ <FixedCd3Alone>0.95</FixedCd3Alone>
+ <StageCount>1</StageCount>
+ <Stage3Mass>0.</Stage3Mass>
+ <Stage2Mass>0.</Stage2Mass>
+ <Stage1Mass>0.</Stage1Mass>
+ <Stage321CG>0.</Stage321CG>
+ <Stage32CG>0.</Stage32CG>
+ <Stage3CG>0.</Stage3CG>
+ <Stage2CGAlone>0.</Stage2CGAlone>
+ <Stage1CGAlone>0.</Stage1CGAlone>
+ <CPCalcFlags>1</CPCalcFlags>
+ <LaunchGuideLength>914.4</LaunchGuideLength>
+ <UseKnownMass>0</UseKnownMass>
+ <DefaultFinish>0</DefaultFinish>
+ <FinishMedium>0</FinishMedium>
+ <FinishCoatCount>1</FinishCoatCount>
+ <GlueType>0</GlueType>
+ <CPSimFlags>1</CPSimFlags>
+ <LastSerialNumber>7</LastSerialNumber>
+ <DisplayFlags>1</DisplayFlags>
+ <MetricsFlags>0</MetricsFlags>
+ <BarromanXN>0,567.719,0,0</BarromanXN>
+ <BarrowmanCNa>0,19.2193,0,0</BarrowmanCNa>
+ <RockSimXN>0,571.25,0,0</RockSimXN>
+ <RockSimCNa>0,28.2677,0,0</RockSimCNa>
+ <RockSimCNa90>0,0,0,0</RockSimCNa90>
+ <RockSimXN90>0,0,0,0</RockSimXN90>
+ <ViewType>0</ViewType>
+ <ViewStageCount>1</ViewStageCount>
+ <ViewTypeEdit>0</ViewTypeEdit>
+ <ViewStageCountEdit>1</ViewStageCountEdit>
+ <ZoomFactor>0.</ZoomFactor>
+ <ZoomFactorEdit>0.</ZoomFactorEdit>
+ <ScrollPosX>0</ScrollPosX>
+ <ScrollPosY>0</ScrollPosY>
+ <ScrollPosXEdit>0</ScrollPosXEdit>
+ <ScrollPosYEdit>0</ScrollPosYEdit>
+ <ThreeDFlags>0</ThreeDFlags>
+ <ThreeDFlagsEdit>0</ThreeDFlagsEdit>
+ <UseModelSprite>0</UseModelSprite>
+ <StaticMarginRef>0</StaticMarginRef>
+ <UserRefDiameter>0.</UserRefDiameter>
+ <SideMarkerHeight>10.</SideMarkerHeight>
+ <SideDimensionHeight>10.</SideDimensionHeight>
+ <BaseMarkerHeight>10.</BaseMarkerHeight>
+ <BaseDimensionHeight>10.</BaseDimensionHeight>
+ <ShowGlideCP>0</ShowGlideCP>
+ <ShowGridTypeSide>0</ShowGridTypeSide>
+ <ShowGridTypeBase>0</ShowGridTypeBase>
+ <GridSpacing>10.</GridSpacing>
+ <GridOpacity>0.15</GridOpacity>
+ <GridColor>black</GridColor>
+ <MaxDiaWithFins>259.588</MaxDiaWithFins>
+ <MaxDiaWithoutFins>56.388</MaxDiaWithoutFins>
+ <MaxLenWithFins>717.499</MaxLenWithFins>
+ <MaxLenWithoutFins>717.499</MaxLenWithoutFins>
+ <MinXExtent>0.</MinXExtent>
+ <MaxXExtent>717.499</MaxXExtent>
+ <CalculatedMaxStageDia>0,56.388,0,0</CalculatedMaxStageDia>
+ <CalculatedStageLen>0,717.499,0,0</CalculatedStageLen>
+ <Cd3>
+ <PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+ <X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+ <A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+ <B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+ <C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+ </PolyData>
+ </Cd3>
+ <Cd32>
+ <PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+ <X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+ <A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+ <B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+ <C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+ </PolyData>
+ </Cd32>
+ <Cd321>
+ <PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+ <X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+ <A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+ <B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+ <C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+ </PolyData>
+</Cd321>
+<Cb3>
+ <PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+ <X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+ <A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+ <B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+ <C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb3>
+<Cb32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb32>
+<Cb321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb321>
+<CNa3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa3>
+<CNa32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa32>
+<CNa321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa321>
+<CP3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP3>
+<CP32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP32>
+<CP321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP321>
+<SimulationEventList>
+</SimulationEventList>
+<Stage3Parts>
+<NoseCone>
+<PartMfg>Apogee</PartMfg>
+<KnownMass>24.0999</KnownMass>
+<Density>1049.21</Density>
+<Material>Polystyrene PS</Material>
+<Name>Nose cone</Name>
+<KnownCG>65.3999</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>94.7384</CalcMass>
+<CalcCG>208.434</CalcCG>
+<WettedSurface>0.0323955</WettedSurface>
+<PaintedSurface>0.0323955</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>19470</PartNo>
+<PartDesc>PNC-70A</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>1</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>2.</BarrowmanCNa>
+<BarrowmanXN>0.126958</BarrowmanXN>
+<RockSimCNa>2.</RockSimCNa>
+<RockSimXN>0.126958</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>0.</Station>
+<Len>272.999</Len>
+<BaseDia>56.2991</BaseDia>
+<FinishCode>0</FinishCode>
+<ShapeCode>1</ShapeCode>
+<ConstructionType>1</ConstructionType>
+<ShoulderLen>58.3997</ShoulderLen>
+<WallThickness>2.159</WallThickness>
+<ShapeParameter>0.</ShapeParameter>
+<ShoulderOD>53.1012</ShoulderOD>
+<BaseExtensionLen>0.</BaseExtensionLen>
+<CoreDia>0.</CoreDia>
+<CoreLen>0.</CoreLen>
+<AttachedParts>
+</AttachedParts>
+</NoseCone>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>44.4492</CalcMass>
+<CalcCG>222.25</CalcCG>
+<WettedSurface>0.0787423</WettedSurface>
+<PaintedSurface>0.0787423</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>Estes</PartNo>
+<PartDesc>BT-70</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>2</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>272.999</Station>
+<OD>56.388</OD>
+<ID>55.372</ID>
+<Len>444.5</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<FinSet>
+<PartMfg>Public Missiles</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1905.24</Density>
+<Material>G10 fiberglass</Material>
+<Name>Fin set</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>273.05</Xb>
+<CalcMass>75.5033</CalcMass>
+<CalcCG>110.067</CalcCG>
+<WettedSurface>0.0167742</WettedSurface>
+<PaintedSurface>0.0503225</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>FIN-A-04</PartNo>
+<PartDesc>Fins</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>4</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>16.5474</BarrowmanCNa>
+<BarrowmanXN>0.628599</BarrowmanXN>
+<RockSimCNa>23.7789</RockSimCNa>
+<RockSimXN>0.628599</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>546.049</Station>
+<FinCount>3</FinCount>
+<RootChord>165.1</RootChord>
+<TipChord>0.</TipChord>
+<SemiSpan>101.6</SemiSpan>
+<MidChordLen>130.909</MidChordLen>
+<SweepDistance>165.1</SweepDistance>
+<Thickness>1.5748</Thickness>
+<ShapeCode>0</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>1</TipShapeCode>
+<TabLength>0.</TabLength>
+<TabDepth>0.</TabDepth>
+<TabOffset>0.</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>1.02001</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>62.0607</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>13.7288</RockSimCNaPerFin>
+<TaperRatio>0.</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AttachedParts>
+</AttachedParts>
+</FinSet>
+<BodyTube>
+<PartMfg>Apogee</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>107.95</Xb>
+<CalcMass>1.7435</CalcMass>
+<CalcCG>55.5625</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>10062</PartNo>
+<PartDesc>13 mm</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>5</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>380.949</Station>
+<OD>13.8176</OD>
+<ID>13.1572</ID>
+<Len>111.125</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>13.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<FinSet>
+<PartMfg>Public Missiles</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1905.24</Density>
+<Material>G10 fiberglass</Material>
+<Name>Fin set</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>5.53666</CalcMass>
+<CalcCG>44.5707</CalcCG>
+<WettedSurface>0.00365927</WettedSurface>
+<PaintedSurface>0.00365927</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>FIN-A-06</PartNo>
+<PartDesc>Fins</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>7</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.671866</BarrowmanCNa>
+<BarrowmanXN>0.380349</BarrowmanXN>
+<RockSimCNa>2.4888</RockSimCNa>
+<RockSimXN>0.380349</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>349.199</Station>
+<FinCount>1</FinCount>
+<RootChord>66.675</RootChord>
+<TipChord>38.1</TipChord>
+<SemiSpan>34.925</SemiSpan>
+<MidChordLen>42.7843</MidChordLen>
+<SweepDistance>39.0017</SweepDistance>
+<Thickness>1.5875</Thickness>
+<ShapeCode>0</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>0</TipShapeCode>
+<TabLength>0.</TabLength>
+<TabDepth>0.</TabDepth>
+<TabOffset>0.</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.366519</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>44.069</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>2.87382</RockSimCNaPerFin>
+<TaperRatio>0.571429</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AttachedParts>
+</AttachedParts>
+</FinSet>
+</AttachedParts>
+</BodyTube>
+<ExternalPod>
+<PartMfg>Custom</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>0.</Density>
+<Name>Pod</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>76.2</Xb>
+<CalcMass>0.</CalcMass>
+<CalcCG>0.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>28.194</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>6</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>349.199</Station>
+<Detachable>1</Detachable>
+<AutoCalcRadialDistance>1</AutoCalcRadialDistance>
+<AutoCalcRadialAngle>1</AutoCalcRadialAngle>
+<AttachedParts>
+<FinSet>
+<PartMfg>Public Missiles</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1905.24</Density>
+<Material>G10 fiberglass</Material>
+<Name>Fin set</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>5.53666</CalcMass>
+<CalcCG>44.5707</CalcCG>
+<WettedSurface>0.00365927</WettedSurface>
+<PaintedSurface>0.00365927</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>FIN-A-06</PartNo>
+<PartDesc>Fins</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>7</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.671866</BarrowmanCNa>
+<BarrowmanXN>0.380349</BarrowmanXN>
+<RockSimCNa>2.4888</RockSimCNa>
+<RockSimXN>0.380349</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>349.199</Station>
+<FinCount>1</FinCount>
+<RootChord>66.675</RootChord>
+<TipChord>38.1</TipChord>
+<SemiSpan>34.925</SemiSpan>
+<MidChordLen>42.7843</MidChordLen>
+<SweepDistance>39.0017</SweepDistance>
+<Thickness>1.5875</Thickness>
+<ShapeCode>0</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>0</TipShapeCode>
+<TabLength>0.</TabLength>
+<TabDepth>0.</TabDepth>
+<TabOffset>0.</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.366519</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>44.069</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>2.87382</RockSimCNaPerFin>
+<TaperRatio>0.571429</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AttachedParts>
+</AttachedParts>
+</FinSet>
+</AttachedParts>
+</ExternalPod>
+</AttachedParts>
+</BodyTube>
+</Stage3Parts>
+<Stage2Parts>
+</Stage2Parts>
+<Stage1Parts>
+</Stage1Parts>
+<SideViewDims>
+</SideViewDims>
+<BaseViewDims>
+</BaseViewDims>
+<VertViewDims>
+</VertViewDims>
+</RocketDesign>
+</DesignInformation>
+<SimulationResultsList>
+</SimulationResultsList>
+</RockSimDocument>
--- /dev/null
+/*
+ * RingHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.file.simplesax.PlainTextHandler;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.Bulkhead;
+import net.sf.openrocket.rocketcomponent.CenteringRing;
+import net.sf.openrocket.rocketcomponent.EngineBlock;
+import net.sf.openrocket.rocketcomponent.RingComponent;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.rocketcomponent.TubeCoupler;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+/**
+ * RingHandler Tester.
+ */
+public class RingHandlerTest extends RocksimTestBase {
+
+ /**
+ * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testOpenElement() throws Exception {
+ Assert.assertEquals(PlainTextHandler.INSTANCE, new RingHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
+ }
+
+ /**
+ * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testCloseElement() throws Exception {
+
+ BodyTube tube = new BodyTube();
+ RingHandler handler = new RingHandler(tube, new WarningSet());
+ CenteringRing component = (CenteringRing) getField(handler, "ring");
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("OD", attributes, "0", warnings);
+ Assert.assertEquals(0d, component.getOuterRadius(), 0.001);
+ handler.closeElement("OD", attributes, "75", warnings);
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getOuterRadius(), 0.001);
+ handler.closeElement("OD", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("ID", attributes, "0", warnings);
+ Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "75", warnings);
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
+ handler.closeElement("ID", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Len", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ Assert.assertEquals("Test Name", component.getName());
+ }
+
+ /**
+ * Test a bulkhead.
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testBulkhead() throws Exception {
+ BodyTube tube = new BodyTube();
+ RingHandler handler = new RingHandler(tube, new WarningSet());
+ CenteringRing component = (CenteringRing) getField(handler, "ring");
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("OD", attributes, "75", warnings);
+ handler.closeElement("ID", attributes, "0", warnings);
+ handler.closeElement("Len", attributes, "10", warnings);
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ handler.closeElement("KnownMass", attributes, "109.9", warnings);
+ handler.closeElement("UsageCode", attributes, "1", warnings);
+ handler.closeElement("UseKnownCG", attributes, "1", warnings);
+ handler.endHandler("", attributes, "", warnings);
+
+ Assert.assertEquals(1, tube.getChildren().size());
+ RingComponent child = (RingComponent)tube.getChild(0);
+
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getOuterRadius(), 0.001);
+ Assert.assertEquals(0d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getInnerRadius(), 0.001);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getLength(), 0.001);
+ Assert.assertEquals("Test Name", child.getName());
+ Assert.assertEquals(109.9/1000, child.getMass(), 0.001);
+ Assert.assertEquals(0, child.getPositionValue(), 0.0);
+ Assert.assertEquals(RocketComponent.Position.TOP, child.getRelativePosition());
+ Assert.assertTrue(child instanceof Bulkhead);
+
+ }
+
+ /**
+ * Test a tube coupler.
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testTubeCoupler() throws Exception {
+ BodyTube tube = new BodyTube();
+ RingHandler handler = new RingHandler(tube, new WarningSet());
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("OD", attributes, "75", warnings);
+ handler.closeElement("ID", attributes, "70", warnings);
+ handler.closeElement("Len", attributes, "10", warnings);
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ handler.closeElement("KnownMass", attributes, "109.9", warnings);
+ handler.closeElement("UsageCode", attributes, "4", warnings);
+ handler.closeElement("UseKnownCG", attributes, "1", warnings);
+ handler.endHandler("", attributes, "", warnings);
+
+ Assert.assertEquals(1, tube.getChildren().size());
+ RingComponent child = (RingComponent)tube.getChild(0);
+ Assert.assertTrue(child instanceof TubeCoupler);
+
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getOuterRadius(), 0.001);
+ Assert.assertEquals(70d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getInnerRadius(), 0.001);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getLength(), 0.001);
+ Assert.assertEquals("Test Name", child.getName());
+ Assert.assertEquals(109.9/1000, child.getMass(), 0.001);
+ Assert.assertEquals(0, child.getPositionValue(), 0.0);
+ Assert.assertEquals(RocketComponent.Position.TOP, child.getRelativePosition());
+ }
+
+ /**
+ * Test a engine block.
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testEngineBlock() throws Exception {
+ BodyTube tube = new BodyTube();
+ RingHandler handler = new RingHandler(tube, new WarningSet());
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("OD", attributes, "75", warnings);
+ handler.closeElement("ID", attributes, "70", warnings);
+ handler.closeElement("Len", attributes, "10", warnings);
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ handler.closeElement("KnownMass", attributes, "109.9", warnings);
+ handler.closeElement("UsageCode", attributes, "2", warnings);
+ handler.closeElement("KnownCG", attributes, "4", warnings);
+ handler.closeElement("UseKnownCG", attributes, "1", warnings);
+ handler.endHandler("", attributes, "", warnings);
+
+ Assert.assertEquals(1, tube.getChildren().size());
+ RingComponent child = (RingComponent)tube.getChild(0);
+ Assert.assertTrue(child instanceof EngineBlock);
+
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getOuterRadius(), 0.001);
+ Assert.assertEquals(70d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getInnerRadius(), 0.001);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getLength(), 0.001);
+ Assert.assertEquals("Test Name", child.getName());
+ Assert.assertEquals(109.9/1000, child.getMass(), 0.001);
+ Assert.assertEquals(0, child.getPositionValue(), 0.0);
+ Assert.assertEquals(RocketComponent.Position.TOP, child.getRelativePosition());
+ Assert.assertEquals(4d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getCG().x, 0.000001);
+
+ }
+
+ /**
+ * Test a centering ring
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testRing() throws Exception {
+ BodyTube tube = new BodyTube();
+ RingHandler handler = new RingHandler(tube, new WarningSet());
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("OD", attributes, "75", warnings);
+ handler.closeElement("ID", attributes, "0", warnings);
+ handler.closeElement("Len", attributes, "10", warnings);
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ handler.closeElement("KnownMass", attributes, "109.9", warnings);
+ handler.closeElement("UsageCode", attributes, "0", warnings);
+ handler.closeElement("UseKnownCG", attributes, "1", warnings);
+ handler.endHandler("", attributes, "", warnings);
+
+ Assert.assertEquals(1, tube.getChildren().size());
+ RingComponent child = (RingComponent)tube.getChild(0);
+
+ Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getOuterRadius(), 0.001);
+ Assert.assertEquals(0d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getInnerRadius(), 0.001);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getLength(), 0.001);
+ Assert.assertEquals("Test Name", child.getName());
+ Assert.assertEquals(109.9/1000, child.getMass(), 0.001);
+ Assert.assertEquals(0, child.getPositionValue(), 0.0);
+ Assert.assertEquals(RocketComponent.Position.TOP, child.getRelativePosition());
+ Assert.assertTrue(child instanceof CenteringRing);
+ }
+
+ /**
+ * Method: constructor
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new RingHandler(null, new WarningSet());
+ Assert.fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException iae) {
+ //success
+ }
+
+ BodyTube tube = new BodyTube();
+ RingHandler handler = new RingHandler(tube, new WarningSet());
+ CenteringRing component = (CenteringRing) getField(handler, "ring");
+ }
+
+ /**
+ * Method: setRelativePosition(RocketComponent.Position position)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testSetRelativePosition() throws Exception {
+ BodyTube tube = new BodyTube();
+ RingHandler handler = new RingHandler(tube, new WarningSet());
+ CenteringRing component = (CenteringRing) getField(handler, "ring");
+ handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
+ Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
+ }
+
+
+ /**
+ * Method: getComponent()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetComponent() throws Exception {
+ Assert.assertTrue(new RingHandler(new BodyTube(), new WarningSet()).getComponent() instanceof CenteringRing);
+ }
+
+ /**
+ * Method: getMaterialType()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetMaterialType() throws Exception {
+ Assert.assertEquals(Material.Type.BULK, new RingHandler(new BodyTube(), new WarningSet()).getMaterialType());
+ }
+
+
+}
--- /dev/null
+/*
+ * RocksimContentHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import org.junit.Assert;
+
+/**
+ * RocksimContentHandler Tester.
+ *
+ */
+public class RocksimContentHandlerTest {
+
+ /**
+ *
+ * Method: getDocument()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetDocument() throws Exception {
+ RocksimContentHandler handler = new RocksimContentHandler();
+ Assert.assertNotNull(handler.getDocument());
+ }
+
+}
--- /dev/null
+/*
+ * RocksimLoaderTest.java
+ *
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.document.OpenRocketDocument;
+import net.sf.openrocket.file.RocketLoadException;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.LaunchLug;
+import net.sf.openrocket.rocketcomponent.Rocket;
+import net.sf.openrocket.rocketcomponent.Stage;
+import org.junit.Assert;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * RocksimLoader Tester.
+ */
+public class RocksimLoaderTest {
+
+ /**
+ * Test a bug reported via automated bug report. I have been unable to reproduce this bug
+ * (hanging finset off of an inner body tube) when creating a Rocksim file using Rocksim. The bug
+ * is reproducible when manually modifying the Rocksim file, which is what is tested here.
+ */
+ @org.junit.Test
+ public void testFinsOnInnerTube() throws Exception {
+ RocksimLoader loader = new RocksimLoader();
+ InputStream stream = this.getClass().getResourceAsStream("PodFins.rkt");
+ Assert.assertNotNull("Could not open PodFins.rkt", stream);
+ try {
+ OpenRocketDocument doc = loader.loadFromStream(new BufferedInputStream(stream));
+ Assert.assertNotNull(doc);
+ Rocket rocket = doc.getRocket();
+ Assert.assertNotNull(rocket);
+ } catch (IllegalStateException ise) {
+ Assert.fail(ise.getMessage());
+ }
+ Assert.assertTrue(loader.getWarnings().size() == 2);
+ }
+
+ /**
+ * Method: loadFromStream(InputStream source)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testLoadFromStream() throws Exception {
+ RocksimLoader loader = new RocksimLoader();
+ //Stupid single stage rocket
+ OpenRocketDocument doc = loadRocksimRocket(loader);
+ InputStream stream;
+
+ Assert.assertNotNull(doc);
+ Rocket rocket = doc.getRocket();
+ Assert.assertNotNull(rocket);
+ Assert.assertEquals("FooBar Test", doc.getRocket().getName());
+ Assert.assertTrue(loader.getWarnings().isEmpty());
+
+ stream = this.getClass().getResourceAsStream("rocksimTestRocket2.rkt");
+ Assert.assertNotNull("Could not open rocksimTestRocket2.rkt", stream);
+ doc = loader.loadFromStream(new BufferedInputStream(stream));
+
+ Assert.assertNotNull(doc);
+ rocket = doc.getRocket();
+ Assert.assertNotNull(rocket);
+
+ //Do some simple asserts; the important thing here is just validating that the mass and cg were
+ //not overridden for each stage.
+ Assert.assertEquals("Three Stage Everything Included Rocket", doc.getRocket().getName());
+ Assert.assertEquals(1, loader.getWarnings().size());
+ Assert.assertEquals(3, rocket.getStageCount());
+ Stage stage1 = (Stage) rocket.getChild(0);
+ Assert.assertFalse(stage1.isMassOverridden());
+ Assert.assertFalse(stage1.isCGOverridden());
+ Stage stage2 = (Stage) rocket.getChild(1);
+ Assert.assertFalse(stage2.isMassOverridden());
+ Assert.assertFalse(stage2.isCGOverridden());
+ Stage stage3 = (Stage) rocket.getChild(2);
+ Assert.assertFalse(stage3.isMassOverridden());
+ Assert.assertFalse(stage3.isCGOverridden());
+
+ stream = this.getClass().getResourceAsStream("rocksimTestRocket3.rkt");
+ Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
+ doc = loader.loadFromStream(new BufferedInputStream(stream));
+
+ Assert.assertNotNull(doc);
+ rocket = doc.getRocket();
+ Assert.assertNotNull(rocket);
+ Assert.assertEquals("Three Stage Everything Included Rocket - Override Total Mass/CG", doc.getRocket().getName());
+ Assert.assertEquals(3, rocket.getStageCount());
+ stage1 = (Stage) rocket.getChild(0);
+ stage2 = (Stage) rocket.getChild(1);
+ stage3 = (Stage) rocket.getChild(2);
+
+ //Do some 1st level and simple asserts; the idea here is to not do a deep validation as that
+ //should have been covered elsewhere. Assert that the stage overrides are correct.
+ Assert.assertEquals(2, stage1.getChildCount());
+ Assert.assertEquals("Nose cone", stage1.getChild(0).getName());
+ Assert.assertEquals("Body tube", stage1.getChild(1).getName());
+ Assert.assertTrue(stage1.isMassOverridden());
+ Assert.assertEquals(0.185d, stage1.getOverrideMass(), 0.001);
+ Assert.assertTrue(stage1.isCGOverridden());
+ Assert.assertEquals(0.3d, stage1.getOverrideCG().x, 0.001);
+ Assert.assertEquals(4, loader.getWarnings().size());
+
+ Assert.assertEquals(1, stage2.getChildCount());
+ Assert.assertEquals("2nd Stage Tube", stage2.getChild(0).getName());
+ Assert.assertTrue(stage2.isMassOverridden());
+ Assert.assertEquals(0.21d, stage2.getOverrideMass(), 0.001);
+ Assert.assertTrue(stage2.isCGOverridden());
+ Assert.assertEquals(0.4d, stage2.getOverrideCG().x, 0.001);
+
+ BodyTube bt = (BodyTube) stage2.getChild(0);
+ LaunchLug ll = (LaunchLug) bt.getChild(6);
+ Assert.assertEquals(1.22d, ll.getRadialDirection(), 0.001);
+
+ Assert.assertEquals(2, stage3.getChildCount());
+ Assert.assertEquals("Transition", stage3.getChild(0).getName());
+ Assert.assertEquals("Body tube", stage3.getChild(1).getName());
+ Assert.assertTrue(stage2.isMassOverridden());
+ Assert.assertEquals(0.33d, stage3.getOverrideMass(), 0.001);
+ Assert.assertTrue(stage2.isCGOverridden());
+ Assert.assertEquals(0.5d, stage3.getOverrideCG().x, 0.001);
+ }
+
+ public static OpenRocketDocument loadRocksimRocket(RocksimLoader theLoader) throws IOException, RocketLoadException {
+ InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket1.rkt");
+ try {
+ Assert.assertNotNull("Could not open rocksimTestRocket1.rkt", stream);
+ return theLoader.loadFromStream(new BufferedInputStream(stream));
+ } finally {
+ stream.close();
+ }
+ }
+
+ public static OpenRocketDocument loadRocksimRocket3(RocksimLoader theLoader) throws IOException, RocketLoadException {
+ InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket3.rkt");
+ try {
+ Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
+ return theLoader.loadFromStream(new BufferedInputStream(stream));
+ } finally {
+ stream.close();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * BaseRocksimTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.gui.util.SwingPreferences;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.startup.Application;
+import org.junit.Assert;
+import org.junit.Before;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+/**
+ * A base class for the Rocksim tests. Includes code from the junitx.addons project.
+ */
+public abstract class RocksimTestBase {
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Before
+ public void setUp() throws Exception {
+ Application.setPreferences( new SwingPreferences() );
+ }
+
+
+ public void assertContains(RocketComponent child, List<RocketComponent> components) {
+ Assert.assertTrue("Components did not contain child", components.contains(child));
+ }
+
+ /**
+ * Returns the value of the field on the specified object. The name
+ * parameter is a <code>String</code> specifying the simple name of the
+ * desired field.<p>
+ *
+ * The object is first searched for any matching field. If no matching
+ * field is found, the superclasses are recursively searched.
+ *
+ * @exception NoSuchFieldException if a field with the specified name is
+ * not found.
+ */
+ public static Object getField(Object object,
+ String name)
+ throws NoSuchFieldException {
+ if (object == null) {
+ throw new IllegalArgumentException("Invalid null object argument");
+ }
+ for (Class cls = object.getClass(); cls != null; cls = cls.getSuperclass()) {
+ try {
+ Field field = cls.getDeclaredField(name);
+ field.setAccessible(true);
+ return field.get(object);
+ } catch (Exception ex) {
+ /* in case of an exception, we will throw a new
+ * NoSuchFieldException object */
+ ;
+ }
+ }
+ throw new NoSuchFieldException("Could get value for field " +
+ object.getClass().getName() + "." + name);
+ }
+
+ /**
+ * Returns the value of the field on the specified class. The name
+ * parameter is a <code>String</code> specifying the simple name of the
+ * desired field.<p>
+ *
+ * The class is first searched for any matching field. If no matching
+ * field is found, the superclasses are recursively searched.
+ *
+ * @exception NoSuchFieldException if a field with the specified name is
+ * not found.
+ */
+ public static Object getField(Class cls,
+ String name)
+ throws NoSuchFieldException {
+ if (cls == null) {
+ throw new IllegalArgumentException("Invalid null cls argument");
+ }
+ Class base = cls;
+ while (base != null) {
+ try {
+ Field field = base.getDeclaredField(name);
+ field.setAccessible(true);
+ return field.get(base);
+ } catch (Exception ex) {
+ /* in case of an exception, we will throw a new
+ * NoSuchFieldException object */
+ ;
+ }
+ base = base.getSuperclass();
+ }
+ throw new NoSuchFieldException("Could get value for static field " +
+ cls.getName() + "." + name);
+ }
+
+
+}
--- /dev/null
+/*
+ * StreamerHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.file.simplesax.PlainTextHandler;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.rocketcomponent.Streamer;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+/**
+ * StreamerHandler Tester.
+ */
+public class StreamerHandlerTest extends RocksimTestBase {
+
+ /**
+ * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testOpenElement() throws Exception {
+ Assert.assertEquals(PlainTextHandler.INSTANCE, new StreamerHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
+ }
+
+ /**
+ * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testCloseElement() throws Exception {
+
+ BodyTube tube = new BodyTube();
+ StreamerHandler handler = new StreamerHandler(tube, new WarningSet());
+ Streamer component = (Streamer) getField(handler, "streamer");
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("Width", attributes, "0", warnings);
+ Assert.assertEquals(0d/ RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getStripWidth(), 0.001);
+ handler.closeElement("Width", attributes, "10", warnings);
+ Assert.assertEquals(10d/ RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getStripWidth(), 0.001);
+ handler.closeElement("Width", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Len", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getStripLength(), 0.001);
+ handler.closeElement("Len", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getStripLength(), 0.001);
+ handler.closeElement("Len", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getStripLength(), 0.001);
+ handler.closeElement("Len", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ Assert.assertEquals("Test Name", component.getName());
+
+ handler.closeElement("DragCoefficient", attributes, "0.94", warnings);
+ Assert.assertEquals(0.94d, component.getCD(), 0.001);
+ handler.closeElement("DragCoefficient", attributes, "-0.94", warnings);
+ Assert.assertEquals(-0.94d, component.getCD(), 0.001);
+ handler.closeElement("DragCoefficient", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ }
+
+ /**
+ * Method: constructor
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new StreamerHandler(null, new WarningSet());
+ Assert.fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException iae) {
+ //success
+ }
+
+ BodyTube tube = new BodyTube();
+ StreamerHandler handler = new StreamerHandler(tube, new WarningSet());
+ Streamer component = (Streamer) getField(handler, "streamer");
+ assertContains(component, tube.getChildren());
+ }
+
+ /**
+ * Method: setRelativePosition(RocketComponent.Position position)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testSetRelativePosition() throws Exception {
+ BodyTube tube = new BodyTube();
+ StreamerHandler handler = new StreamerHandler(tube, new WarningSet());
+ Streamer component = (Streamer) getField(handler, "streamer");
+ handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
+ Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
+ }
+
+ /**
+ * Method: getComponent()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testGetComponent() throws Exception {
+ Assert.assertTrue(new StreamerHandler(new BodyTube(), new WarningSet()).getComponent() instanceof Streamer);
+ }
+
+ /**
+ * Method: getMaterialType()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testGetMaterialType() throws Exception {
+ Assert.assertEquals(Material.Type.SURFACE, new StreamerHandler(new BodyTube(), new WarningSet()).getMaterialType());
+ }
+
+ /**
+ * Method: endHandler()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @Test
+ public void testEndHandler() throws Exception {
+ BodyTube tube = new BodyTube();
+ StreamerHandler handler = new StreamerHandler(tube, new WarningSet());
+ Streamer component = (Streamer) getField(handler, "streamer");
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ handler.closeElement("Xb", attributes, "-10", warnings);
+ handler.closeElement("LocationMode", attributes, "1", warnings);
+ handler.endHandler("Streamer", attributes, null, warnings);
+ Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
+ Assert.assertEquals(component.getPositionValue(), -10d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, 0.001);
+
+ handler.closeElement("Xb", attributes, "-10", warnings);
+ handler.closeElement("LocationMode", attributes, "2", warnings);
+ handler.endHandler("Streamer", attributes, null, warnings);
+ Assert.assertEquals(RocketComponent.Position.BOTTOM, component.getRelativePosition());
+ Assert.assertEquals(component.getPositionValue(), 10d/ RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, 0.001);
+
+ handler.closeElement("Thickness", attributes, "0.02", warnings);
+ Assert.assertEquals(0.01848, handler.computeDensity(RocksimDensityType.ROCKSIM_BULK, 924d), 0.001);
+
+ //Test Density Type 0 (Bulk)
+ handler.closeElement("Density", attributes, "924.0", warnings);
+ handler.closeElement("DensityType", attributes, "0", warnings);
+ handler.endHandler("Streamer", attributes, null, warnings);
+ Assert.assertEquals(0.01848d, component.getMaterial().getDensity(), 0.001);
+
+ //Test Density Type 1 (Surface)
+ handler.closeElement("Density", attributes, "0.006685", warnings);
+ handler.closeElement("DensityType", attributes, "1", warnings);
+ handler.endHandler("Streamer", attributes, null, warnings);
+ Assert.assertTrue(Math.abs(0.06685d - component.getMaterial().getDensity()) < 0.00001);
+
+ //Test Density Type 2 (Line)
+ handler.closeElement("Density", attributes, "0.223225", warnings);
+ handler.closeElement("DensityType", attributes, "2", warnings);
+ handler.closeElement("Len", attributes, "3810.", warnings);
+ handler.closeElement("Width", attributes, "203.2", warnings);
+ handler.endHandler("Streamer", attributes, null, warnings);
+
+ Assert.assertEquals(1.728190092, component.getMass(), 0.001);
+
+ }
+
+}
--- /dev/null
+/*
+ * TransitionHandlerTest.java
+ */
+package net.sf.openrocket.file.rocksim.importt;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.file.simplesax.PlainTextHandler;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.rocketcomponent.ExternalComponent;
+import net.sf.openrocket.rocketcomponent.Stage;
+import net.sf.openrocket.rocketcomponent.Transition;
+import org.junit.Assert;
+
+import java.util.HashMap;
+
+/**
+ * TransitionHandler Tester.
+ */
+public class TransitionHandlerTest extends RocksimTestBase {
+
+ /**
+ * Method: constructor
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new TransitionHandler(null, new WarningSet());
+ Assert.fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException iae) {
+ //success
+ }
+
+ Stage stage = new Stage();
+ TransitionHandler handler = new TransitionHandler(stage, new WarningSet());
+ Transition component = (Transition) getField(handler, "transition");
+ assertContains(component, stage.getChildren());
+ }
+
+ /**
+ * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testOpenElement() throws Exception {
+ Assert.assertEquals(PlainTextHandler.INSTANCE, new TransitionHandler(new Stage(), new WarningSet()).openElement(null, null, null));
+ }
+
+ /**
+ * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testCloseElement() throws Exception {
+
+ Stage stage = new Stage();
+ HashMap<String, String> attributes = new HashMap<String, String>();
+ WarningSet warnings = new WarningSet();
+
+ TransitionHandler handler = new TransitionHandler(stage, new WarningSet());
+ Transition component = (Transition) getField(handler, "transition");
+
+ handler.closeElement("ShapeCode", attributes, "0", warnings);
+ Assert.assertEquals(Transition.Shape.CONICAL, component.getType());
+ handler.closeElement("ShapeCode", attributes, "1", warnings);
+ Assert.assertEquals(Transition.Shape.OGIVE, component.getType());
+ handler.closeElement("ShapeCode", attributes, "17", warnings);
+ Assert.assertEquals(RocksimNoseConeCode.PARABOLIC.asOpenRocket(), component.getType()); //test of default
+ handler.closeElement("ShapeCode", attributes, "foo", warnings);
+ Assert.assertNotNull(component.getType());
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Len", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
+ handler.closeElement("Len", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("FrontDia", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getForeRadius(), 0.001);
+ handler.closeElement("FrontDia", attributes, "100", warnings);
+ Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getForeRadius(), 0.001);
+ handler.closeElement("FrontDia", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("RearDia", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getAftRadius(), 0.001);
+ handler.closeElement("RearDia", attributes, "100", warnings);
+ Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getAftRadius(), 0.001);
+ handler.closeElement("RearDia", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ final double aft = 100d;
+ component.setAftRadius(aft);
+
+ handler.closeElement("ConstructionType", attributes, "0", warnings);
+ component.setAftShoulderRadius(1.1d);
+ component.setForeShoulderRadius(1.1d);
+ handler.closeElement("WallThickness", attributes, "-1", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(component.getAftRadius(), component.getThickness(), 0.001);
+ Assert.assertEquals(component.getAftShoulderThickness(), component.getAftShoulderThickness(), 0.001);
+ Assert.assertEquals(component.getForeShoulderThickness(), component.getForeShoulderThickness(), 0.001);
+ handler.closeElement("WallThickness", attributes, "100", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(aft, component.getThickness(), 0.001);
+ handler.closeElement("WallThickness", attributes, "foo", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("ConstructionType", attributes, "1", warnings);
+ component.setAftShoulderRadius(1.1d);
+ component.setForeShoulderRadius(1.1d);
+ handler.closeElement("WallThickness", attributes, "-1", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(0d, component.getThickness(), 0.001);
+ Assert.assertEquals(0d, component.getAftShoulderThickness(), 0.001);
+ Assert.assertEquals(0d, component.getForeShoulderThickness(), 0.001);
+ handler.closeElement("WallThickness", attributes, "1.1", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getThickness(), 0.001);
+ Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderThickness(), 0.001);
+ Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getForeShoulderThickness(), 0.001);
+
+
+ handler.closeElement("FrontShoulderLen", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getForeShoulderLength(), 0.001);
+ handler.closeElement("FrontShoulderLen", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getForeShoulderLength(), 0.001);
+ handler.closeElement("FrontShoulderLen", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getForeShoulderLength(), 0.001);
+ handler.closeElement("FrontShoulderLen", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("RearShoulderLen", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getAftShoulderLength(), 0.001);
+ handler.closeElement("RearShoulderLen", attributes, "10", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderLength(), 0.001);
+ handler.closeElement("RearShoulderLen", attributes, "10.0", warnings);
+ Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderLength(), 0.001);
+ handler.closeElement("RearShoulderLen", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("FrontShoulderDia", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getForeShoulderRadius(), 0.001);
+ handler.closeElement("FrontShoulderDia", attributes, "100", warnings);
+ Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getForeShoulderRadius(), 0.001);
+ handler.closeElement("FrontShoulderDia", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("RearShoulderDia", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getAftShoulderRadius(), 0.001);
+ handler.closeElement("RearShoulderDia", attributes, "100", warnings);
+ Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getAftShoulderRadius(), 0.001);
+ handler.closeElement("RearShoulderDia", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ component.setType(Transition.Shape.HAACK);
+ handler.closeElement("ShapeParameter", attributes, "-1", warnings);
+ Assert.assertEquals(0d, component.getShapeParameter(), 0.001);
+ handler.closeElement("ShapeParameter", attributes, "100", warnings);
+ Assert.assertEquals(Transition.Shape.HAACK.maxParameter(), component.getShapeParameter(), 0.001);
+ handler.closeElement("ShapeParameter", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ Assert.assertEquals("Could not convert ShapeParameter value of foo. It is expected to be a number.",
+ warnings.iterator().next().toString());
+
+ warnings.clear();
+
+ component.setType(Transition.Shape.CONICAL);
+ component.setShapeParameter(0d);
+ handler.closeElement("ShapeParameter", attributes, "100", warnings);
+ Assert.assertEquals(0d, component.getShapeParameter(), 0.001);
+
+ handler.closeElement("FinishCode", attributes, "-1", warnings);
+ Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
+ handler.closeElement("FinishCode", attributes, "100", warnings);
+ Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
+ handler.closeElement("FinishCode", attributes, "foo", warnings);
+ Assert.assertEquals(1, warnings.size());
+ warnings.clear();
+
+ handler.closeElement("Name", attributes, "Test Name", warnings);
+ Assert.assertEquals("Test Name", component.getName());
+
+ handler.closeElement("Material", attributes, "Some Material", warnings);
+ handler.endHandler("Transition", attributes, null, warnings);
+ Assert.assertTrue(component.getMaterial().getName().contains("Some Material"));
+ }
+
+ /**
+ * Method: getComponent()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetComponent() throws Exception {
+ Assert.assertTrue(new TransitionHandler(new Stage(), new WarningSet()).getComponent() instanceof Transition);
+ }
+
+ /**
+ * Method: getMaterialType()
+ *
+ * @throws Exception thrown if something goes awry
+ */
+ @org.junit.Test
+ public void testGetMaterialType() throws Exception {
+ Assert.assertEquals(Material.Type.BULK, new TransitionHandler(new Stage(), new WarningSet()).getMaterialType());
+ }
+
+
+}
--- /dev/null
+<RockSimDocument>
+<FileVersion>3</FileVersion>
+<DesignInformation>
+<RocketDesign>
+ <Name>FooBar Test</Name>
+<CalculateCD>1</CalculateCD>
+<ProCalculateCD>1</ProCalculateCD>
+<ProCalculateCN>1</ProCalculateCN>
+<FixedCd>0.75</FixedCd>
+<FixedCd2>0.8</FixedCd2>
+<FixedCd3>0.81</FixedCd3>
+<FixedCd2Alone>0.95</FixedCd2Alone>
+<FixedCd3Alone>0.95</FixedCd3Alone>
+<StageCount>1</StageCount>
+<Stage3Mass>0.</Stage3Mass>
+<Stage2Mass>0.</Stage2Mass>
+<Stage1Mass>0.</Stage1Mass>
+<Stage321CG>0.</Stage321CG>
+<Stage32CG>0.</Stage32CG>
+<Stage3CG>0.</Stage3CG>
+<Stage2CGAlone>0.</Stage2CGAlone>
+<Stage1CGAlone>0.</Stage1CGAlone>
+<CPCalcFlags>1</CPCalcFlags>
+<LaunchGuideLength>914.4</LaunchGuideLength>
+<UseKnownMass>0</UseKnownMass>
+<DefaultFinish>0</DefaultFinish>
+<FinishMedium>0</FinishMedium>
+<FinishCoatCount>1</FinishCoatCount>
+<GlueType>0</GlueType>
+<CPSimFlags>1</CPSimFlags>
+<LastSerialNumber>11</LastSerialNumber>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<BarromanXN>0,1215.49,0,0</BarromanXN>
+<BarrowmanCNa>0,35.9506,0,0</BarrowmanCNa>
+<RockSimXN>0,1226.38,0,0</RockSimXN>
+<RockSimCNa>0,47.5027,0,0</RockSimCNa>
+<RockSimCNa90>0,0,0,0</RockSimCNa90>
+<RockSimXN90>0,0,0,0</RockSimXN90>
+<ViewType>0</ViewType>
+<ViewStageCount>1</ViewStageCount>
+<ViewTypeEdit>0</ViewTypeEdit>
+<ViewStageCountEdit>1</ViewStageCountEdit>
+<ZoomFactor>0.</ZoomFactor>
+<ZoomFactorEdit>0.</ZoomFactorEdit>
+<ScrollPosX>0</ScrollPosX>
+<ScrollPosY>0</ScrollPosY>
+<ScrollPosXEdit>0</ScrollPosXEdit>
+<ScrollPosYEdit>0</ScrollPosYEdit>
+<ThreeDFlags>0</ThreeDFlags>
+<ThreeDFlagsEdit>0</ThreeDFlagsEdit>
+<UseModelSprite>0</UseModelSprite>
+<StaticMarginRef>0</StaticMarginRef>
+<UserRefDiameter>0.</UserRefDiameter>
+<SideMarkerHeight>10.</SideMarkerHeight>
+<SideDimensionHeight>10.</SideDimensionHeight>
+<BaseMarkerHeight>10.</BaseMarkerHeight>
+<BaseDimensionHeight>10.</BaseDimensionHeight>
+<ShowGlideCP>0</ShowGlideCP>
+<ShowGridTypeSide>0</ShowGridTypeSide>
+<ShowGridTypeBase>0</ShowGridTypeBase>
+<GridSpacing>10.</GridSpacing>
+<GridOpacity>0.15</GridOpacity>
+<GridColor>black</GridColor>
+<MaxDiaWithFins>424.688</MaxDiaWithFins>
+<MaxDiaWithoutFins>66.04</MaxDiaWithoutFins>
+<MaxLenWithFins>1417.95</MaxLenWithFins>
+<MaxLenWithoutFins>1332.23</MaxLenWithoutFins>
+<MinXExtent>0.</MinXExtent>
+<MaxXExtent>1417.95</MaxXExtent>
+<CalculatedMaxStageDia>0,66.04,0,0</CalculatedMaxStageDia>
+<CalculatedStageLen>0,1332.23,0,0</CalculatedStageLen>
+<Cd3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cd3>
+<Cd32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cd32>
+<Cd321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cd321>
+<Cb3>
+<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb3>
+<Cb32>
+<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb32>
+<Cb321>
+<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb321>
+<CNa3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa3>
+<CNa32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa32>
+<CNa321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa321>
+<CP3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP3>
+<CP32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP32>
+<CP321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP321>
+<SimulationEventList>
+</SimulationEventList>
+<Stage3Parts>
+<NoseCone>
+<PartMfg>Apogee</PartMfg>
+<KnownMass>24.1</KnownMass>
+<Density>1049.21</Density>
+<Material>Polystyrene PS</Material>
+<Name>Nose cone</Name>
+<KnownCG>65.3999</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>126.438</CalcMass>
+<CalcCG>348.443</CalcCG>
+<WettedSurface>0.0356487</WettedSurface>
+<PaintedSurface>0.0356487</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>19470</PartNo>
+<PartDesc>PNC-70A</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>2</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>2.</BarrowmanCNa>
+<BarrowmanXN>0.264319</BarrowmanXN>
+<RockSimCNa>2.</RockSimCNa>
+<RockSimXN>0.264319</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>0.</Station>
+<Len>396.875</Len>
+<BaseDia>57.15</BaseDia>
+<FinishCode>0</FinishCode>
+<ShapeCode>0</ShapeCode>
+<ConstructionType>1</ConstructionType>
+<ShoulderLen>58.3997</ShoulderLen>
+<WallThickness>2.159</WallThickness>
+<ShapeParameter>0.</ShapeParameter>
+<ShoulderOD>53.1012</ShoulderOD>
+<BaseExtensionLen>66.675</BaseExtensionLen>
+<CoreDia>0.</CoreDia>
+<CoreLen>0.</CoreLen>
+<AttachedParts>
+</AttachedParts>
+</NoseCone>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>10.636</CalcMass>
+<CalcCG>180.34</CalcCG>
+<WettedSurface>0.0748306</WettedSurface>
+<PaintedSurface>0.0748306</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>EST 3090</PartNo>
+<PartDesc>BT-80</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>3</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>463.55</Station>
+<OD>66.04</OD>
+<ID>65.786</ID>
+<Len>360.68</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+</AttachedParts>
+</BodyTube>
+<Transition>
+<PartMfg>BalsaMachining.com</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>128.148</Density>
+<Material>Balsa</Material>
+<Name>Transition</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>39.355</CalcMass>
+<CalcCG>37.0332</CalcCG>
+<WettedSurface>0.0096001</WettedSurface>
+<PaintedSurface>0.0096001</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>TA7080</PartNo>
+<PartDesc>Transition T70 to T80 2 in long</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>7</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>-0.92852</BarrowmanCNa>
+<BarrowmanXN>0.848729</BarrowmanXN>
+<RockSimCNa>-0.92852</RockSimCNa>
+<RockSimXN>0.848729</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>824.23</Station>
+<FrontDia>66.04</FrontDia>
+<RearDia>53.34</RearDia>
+<Len>50.8</Len>
+<FinishCode>0</FinishCode>
+<FrontShoulderLen>35.56</FrontShoulderLen>
+<RearShoulderLen>35.56</RearShoulderLen>
+<ConstructionType>0</ConstructionType>
+<WallThickness>0.</WallThickness>
+<FrontShoulderDia>55.118</FrontShoulderDia>
+<RearShoulderDia>53.34</RearShoulderDia>
+<CoreDia>0.</CoreDia>
+<ShapeCode>0</ShapeCode>
+<ShapeParameter>0.</ShapeParameter>
+<EquivNoseLen>264.12</EquivNoseLen>
+<EquivNoseOffset>213.32</EquivNoseOffset>
+<AttachedParts>
+</AttachedParts>
+</Transition>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>44.449</CalcMass>
+<CalcCG>222.25</CalcCG>
+<WettedSurface>0.0787423</WettedSurface>
+<PaintedSurface>0.0787423</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>Estes</PartNo>
+<PartDesc>BT-70</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>8</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>875.03</Station>
+<OD>56.388</OD>
+<ID>55.372</ID>
+<Len>444.5</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<FinSet>
+<PartMfg>Public Missiles</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1905.24</Density>
+<Material>G10 fiberglass</Material>
+<Name>Fin set</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>260.35</Xb>
+<CalcMass>153.85</CalcMass>
+<CalcCG>155.575</CalcCG>
+<WettedSurface>0.0339112</WettedSurface>
+<PaintedSurface>0.101734</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>FIN-A-01</PartNo>
+<PartDesc>Fins</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>9</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>34.8792</BarrowmanCNa>
+<BarrowmanXN>1.26026</BarrowmanXN>
+<RockSimCNa>46.4312</RockSimCNa>
+<RockSimXN>1.26026</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>1135.38</Station>
+<FinCount>3</FinCount>
+<RootChord>184.15</RootChord>
+<TipChord>0.</TipChord>
+<SemiSpan>184.15</SemiSpan>
+<MidChordLen>264.956</MidChordLen>
+<SweepDistance>282.575</SweepDistance>
+<Thickness>1.5875</Thickness>
+<ShapeCode>0</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>0</TipShapeCode>
+<TabLength>0.</TabLength>
+<TabDepth>0.</TabDepth>
+<TabOffset>0.</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.990003</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>89.5773</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>26.8071</RockSimCNaPerFin>
+<TaperRatio>0.</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AttachedParts>
+</AttachedParts>
+</FinSet>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>13.008</CalcMass>
+<CalcCG>228.6</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>EST 3086</PartNo>
+<PartDesc>BT-50</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>11</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>875.03</Station>
+<OD>24.7904</OD>
+<ID>24.13</ID>
+<Len>457.2</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>1</IsMotorMount>
+<MotorDia>24.</MotorDia>
+<EngineOverhang>12.7</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+</AttachedParts>
+</BodyTube>
+</AttachedParts>
+</BodyTube>
+</Stage3Parts>
+<Stage2Parts>
+</Stage2Parts>
+<Stage1Parts>
+</Stage1Parts>
+<SideViewDims>
+</SideViewDims>
+<BaseViewDims>
+</BaseViewDims>
+<VertViewDims>
+</VertViewDims>
+</RocketDesign>
+</DesignInformation>
+<SimulationResultsList>
+<SimulationResults>
+<MaxAltitude>445.129</MaxAltitude>
+<MaxVelocity>68.7587</MaxVelocity>
+<MaxAcceleration>76.6476</MaxAcceleration>
+<TimeToApogee>10.8263</TimeToApogee>
+<OptimalDelay>4.765</OptimalDelay>
+<MultiDelayCount>1</MultiDelayCount>
+<VelocityAtDeplyment>33.4284</VelocityAtDeplyment>
+<AltitudeAtDeployment>405.535</AltitudeAtDeployment>
+<DelayTime>2</DelayTime>
+<EjectTime>8.06125</EjectTime>
+<FinalState>4</FinalState>
+<TimeToBurnout>6.06125</TimeToBurnout>
+<TimeToLanding>22.4787</TimeToLanding>
+<TimeToEject>8.06125</TimeToEject>
+<MinLaunchGuideLen>1.35915</MinLaunchGuideLen>
+<MaxVertVelocity>65.9349</MaxVertVelocity>
+<MaxHorzVelocity>1.0686</MaxHorzVelocity>
+<MaxVertAcceleration>76.5426</MaxVertAcceleration>
+<MaxHorzAcceleration>4.01173</MaxHorzAcceleration>
+<MaxRange>172.076</MaxRange>
+<LaunchStartVelocity>0.</LaunchStartVelocity>
+<LaunchStartRollRate>0.</LaunchStartRollRate>
+<LaunchGuideType>0</LaunchGuideType>
+<LaunchGuideLen>1828.8</LaunchGuideLen>
+<LaunchWindDirection>0</LaunchWindDirection>
+<LaunchWindSpeed>0.</LaunchWindSpeed>
+<LaunchDirection>0</LaunchDirection>
+<LaunchAngle>0.0523599</LaunchAngle>
+<LaunchGuideAzimuth>0.</LaunchGuideAzimuth>
+<LaunchGuideElevation>0.</LaunchGuideElevation>
+<LaunchBarometer>770.314</LaunchBarometer>
+<LaunchLatitude>43.</LaunchLatitude>
+<LaunchLongitude>0.</LaunchLongitude>
+<LaunchHumidity>70.</LaunchHumidity>
+<LaunchTemperature>7.22222</LaunchTemperature>
+<LaunchAltitude>304.8</LaunchAltitude>
+<LaunchLandingAltitude>0.</LaunchLandingAltitude>
+<CompStateMask>0</CompStateMask>
+<LaunchWindPreset>3</LaunchWindPreset>
+<LaunchWindLowSpeed>1.34112</LaunchWindLowSpeed>
+<LaunchWindHighSpeed>3.53162</LaunchWindHighSpeed>
+<LaunchWindTurbulencePreset>2</LaunchWindTurbulencePreset>
+<LaunchWindFrequency>0.01</LaunchWindFrequency>
+<LaunchWindDeltaFrequency>0.02</LaunchWindDeltaFrequency>
+<LaunchUseRandomConditions>0</LaunchUseRandomConditions>
+<LaunchCloudCoverPreset>5</LaunchCloudCoverPreset>
+<LaunchCCLow>0.</LaunchCCLow>
+<LaunchCCHigh>0.1</LaunchCCHigh>
+<LaunchThermalPosPreset>1</LaunchThermalPosPreset>
+<LaunchThermalPos>0.</LaunchThermalPos>
+<LaunchMultipleThermals>0</LaunchMultipleThermals>
+<LaunchMaxThermals>3</LaunchMaxThermals>
+<LaunchThermalDia>300.</LaunchThermalDia>
+<LaunchThermalHeight>2000.</LaunchThermalHeight>
+<LaunchThermalSpeedPreset>1</LaunchThermalSpeedPreset>
+<LaunchThermalSpeed>5.99999</LaunchThermalSpeed>
+<LaunchWindTableSize>0</LaunchWindTableSize>
+<LaunchWindAltTable>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</LaunchWindAltTable>
+<LaunchWindSpeedTable>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</LaunchWindSpeedTable>
+<LaunchWindDirectionTable>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</LaunchWindDirectionTable>
+<LaunchLossPreset>2</LaunchLossPreset>
+<LaunchLossPercent>0.99</LaunchLossPercent>
+<LaunchSiteDia>2000.</LaunchSiteDia>
+<LaunchDriftRangeToLoss>1500.</LaunchDriftRangeToLoss>
+<LaunchPayloadDamagePreset>2</LaunchPayloadDamagePreset>
+<LaunchPayloadDamagePercent>0.98</LaunchPayloadDamagePercent>
+<LaunchEngineMisfirePreset>1</LaunchEngineMisfirePreset>
+<LaunchEngineMisfirePercent>0.</LaunchEngineMisfirePercent>
+<LaunchVariableIgnitionDelay>0</LaunchVariableIgnitionDelay>
+<LaunchVariableIgnitionDelaySec>0.08</LaunchVariableIgnitionDelaySec>
+<LaunchRecDeviceFailurePreset>1</LaunchRecDeviceFailurePreset>
+<LaunchRecDeviceFailurePercent>0.</LaunchRecDeviceFailurePercent>
+<LaunchAriframeFailurePreset>1</LaunchAriframeFailurePreset>
+<LaunchAirframeFailurePercent>0.</LaunchAirframeFailurePercent>
+<LaunchTrackLossPreset>1</LaunchTrackLossPreset>
+<LaunchTeckLossPercent>0.</LaunchTeckLossPercent>
+<CNaMultiplier>1.</CNaMultiplier>
+<CdMultiplier>1.</CdMultiplier>
+<CPOffset>0.</CPOffset>
+<SaveSimAsText>0</SaveSimAsText>
+<OutputAtMaxRes>0</OutputAtMaxRes>
+<MaxSimTim>3600.</MaxSimTim>
+<MassUncertainty>0.</MassUncertainty>
+<MOIUncertainty>0.</MOIUncertainty>
+<CGUncertainty>0.</CGUncertainty>
+<CdUncertainty>0.</CdUncertainty>
+<CnaUncertainty>0.</CnaUncertainty>
+<CPUncertainty>0.</CPUncertainty>
+<FinCantUncertainty>0.</FinCantUncertainty>
+<TotImpulseUncertainty>0.</TotImpulseUncertainty>
+<PropellantUncertainty>0.</PropellantUncertainty>
+<ThrustAxisUncertainty>0.</ThrustAxisUncertainty>
+<WindDirectionUncertainty>0.</WindDirectionUncertainty>
+<WindVelocityUncertainty>0.</WindVelocityUncertainty>
+<LaunchGuideAzimuthUncertainty>0.</LaunchGuideAzimuthUncertainty>
+<LaunchGuideElevationUncertainty>0.</LaunchGuideElevationUncertainty>
+<IgnitionUncertainty>0.</IgnitionUncertainty>
+<CATOUncertainty>0.</CATOUncertainty>
+<DeploymentUncertainty>0.</DeploymentUncertainty>
+<RecoveryDeviceUncertainty>0.</RecoveryDeviceUncertainty>
+<SimulationName>[E6-2] </SimulationName>
+<VelocityAtLaunchGuideEnd>15.4098</VelocityAtLaunchGuideEnd>
+<WindStartAltitude>0.</WindStartAltitude>
+<TimeToWindShear>0.</TimeToWindShear>
+<TimeToFreeFlight>0.25875</TimeToFreeFlight>
+<TimeToMaxVelocity>5.69125</TimeToMaxVelocity>
+<TimeToMaxAcceleration>0.11125</TimeToMaxAcceleration>
+<Nsims>10</Nsims>
+<CalcResolution>1</CalcResolution>
+<SamplesPerSecond>800.</SamplesPerSecond>
+<SimulationType>0</SimulationType>
+<LocationDataServerName>Earth</LocationDataServerName>
+<LocationDataServerDisplayName>Standard earth condistions.</LocationDataServerDisplayName>
+<ExecutionTime>4.078</ExecutionTime>
+<RangeAtLanding>-172.076</RangeAtLanding>
+<DirectionAtLanding>0.</DirectionAtLanding>
+<VelocityAtLanding>56.537</VelocityAtLanding>
+<XVelcoityAtLanding>-3.38254</XVelcoityAtLanding>
+<YVelocityAtLanding>-56.4357</YVelocityAtLanding>
+<ZVelocityAtLanding>0.</ZVelocityAtLanding>
+<StageSeparationTime>0,0,8.06125,0,0</StageSeparationTime>
+<StageEjectTime>-1,-1,-1,-1,-1</StageEjectTime>
+<TimeToDeployment>0,0,0,0,0</TimeToDeployment>
+<DeploymentType>32,32,32,32,32</DeploymentType>
+<SamplesPerSecondDescent>1.</SamplesPerSecondDescent>
+<CalculationFlags>1</CalculationFlags>
+<Mass0>0.233111</Mass0>
+<CG0>0.739954</CG0>
+<LaterialMOI0>0.0208295</LaterialMOI0>
+<RadialMOI0>0.000194272</RadialMOI0>
+<GUID>{b33e529e-1ada-4524-9885-7382d7cf4d64}</GUID>
+<Booster1Staging>
+<SimulationEvent>
+<PartSerialNo>0</PartSerialNo>
+<Type>0</Type>
+<DeployAltitude>0.</DeployAltitude>
+<DeplyTime>0.</DeplyTime>
+<HasDeployed>0</HasDeployed>
+<DeployedAt_Altitude>0.</DeployedAt_Altitude>
+<DeployedAt_Velocity>0.</DeployedAt_Velocity>
+<DeployedAt_Range>0.</DeployedAt_Range>
+<DeployedAt_Time>0.</DeployedAt_Time>
+<DeviceID>-1</DeviceID>
+<TestType>0,0,0</TestType>
+<TestCondition>0,0,0</TestCondition>
+<TestValueAltitude>0,0,0</TestValueAltitude>
+<TestValueDegrees>0,0,0</TestValueDegrees>
+<TestValuePressure>0,0,0</TestValuePressure>
+<TestValueMach>0,0,0</TestValueMach>
+<TestValueTime>0,0,0</TestValueTime>
+<TestValueQ>0,0,0</TestValueQ>
+</SimulationEvent>
+</Booster1Staging>
+<Booster2Staging>
+<SimulationEvent>
+<PartSerialNo>0</PartSerialNo>
+<Type>0</Type>
+<DeployAltitude>0.</DeployAltitude>
+<DeplyTime>0.</DeplyTime>
+<HasDeployed>0</HasDeployed>
+<DeployedAt_Altitude>0.</DeployedAt_Altitude>
+<DeployedAt_Velocity>0.</DeployedAt_Velocity>
+<DeployedAt_Range>0.</DeployedAt_Range>
+<DeployedAt_Time>0.</DeployedAt_Time>
+<DeviceID>-1</DeviceID>
+<TestType>0,0,0</TestType>
+<TestCondition>0,0,0</TestCondition>
+<TestValueAltitude>0,0,0</TestValueAltitude>
+<TestValueDegrees>0,0,0</TestValueDegrees>
+<TestValuePressure>0,0,0</TestValuePressure>
+<TestValueMach>0,0,0</TestValueMach>
+<TestValueTime>0,0,0</TestValueTime>
+<TestValueQ>0,0,0</TestValueQ>
+</SimulationEvent>
+</Booster2Staging>
+<SimulationEvents>
+</SimulationEvents>
+<Stage1Engines>
+</Stage1Engines>
+<Stage2Engines>
+</Stage2Engines>
+<Stage3Engines>
+<EngineSet>
+<EngineCount>1</EngineCount>
+<EngineCode>E6</EngineCode>
+<IgnitionDelay>0.</IgnitionDelay>
+<EngineMfg>Apogee</EngineMfg>
+<EngineOverhang>0.50038</EngineOverhang>
+<CasingCG>0.</CasingCG>
+<MountSerialNo>5</MountSerialNo>
+<EjectionDelay>2.</EjectionDelay>
+<RotateXaboutY>0.</RotateXaboutY>
+<RotateEngineAxisAboutX>0.</RotateEngineAxisAboutX>
+</EngineSet>
+</Stage3Engines>
+<DropItems>
+</DropItems>
+</SimulationResults>
+</SimulationResultsList>
+</RockSimDocument>
--- /dev/null
+<RockSimDocument>
+<FileVersion>3</FileVersion>
+<DesignInformation>
+<RocketDesign>
+<Name>Three Stage Everything Included Rocket</Name>
+<CalculateCD>1</CalculateCD>
+<ProCalculateCD>1</ProCalculateCD>
+<ProCalculateCN>1</ProCalculateCN>
+<FixedCd>0.75</FixedCd>
+<FixedCd2>0.8</FixedCd2>
+<FixedCd3>0.81</FixedCd3>
+<FixedCd2Alone>0.95</FixedCd2Alone>
+<FixedCd3Alone>0.95</FixedCd3Alone>
+<StageCount>3</StageCount>
+<Stage3Mass>0.</Stage3Mass>
+<Stage2Mass>0.</Stage2Mass>
+<Stage1Mass>0.</Stage1Mass>
+<Stage321CG>0.</Stage321CG>
+<Stage32CG>0.</Stage32CG>
+<Stage3CG>0.</Stage3CG>
+<Stage2CGAlone>0.</Stage2CGAlone>
+<Stage1CGAlone>0.</Stage1CGAlone>
+<CPCalcFlags>1</CPCalcFlags>
+<LaunchGuideLength>914.4</LaunchGuideLength>
+<UseKnownMass>0</UseKnownMass>
+<DefaultFinish>0</DefaultFinish>
+<FinishMedium>0</FinishMedium>
+<FinishCoatCount>1</FinishCoatCount>
+<GlueType>0</GlueType>
+<CPSimFlags>1</CPSimFlags>
+<LastSerialNumber>25</LastSerialNumber>
+<DisplayFlags>7</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<BarromanXN>0,29.6333,326.159,887.03</BarromanXN>
+<BarrowmanCNa>0,2,4.93008,33.0782</BarrowmanCNa>
+<RockSimXN>0,29.6333,384.174,883.929</RockSimXN>
+<RockSimCNa>0,2,6.91103,47.1184</RockSimCNa>
+<RockSimCNa90>0,0,0,0</RockSimCNa90>
+<RockSimXN90>0,0,0,0</RockSimXN90>
+<ViewType>0</ViewType>
+<ViewStageCount>3</ViewStageCount>
+<ViewTypeEdit>0</ViewTypeEdit>
+<ViewStageCountEdit>3</ViewStageCountEdit>
+<ZoomFactor>0.</ZoomFactor>
+<ZoomFactorEdit>0.</ZoomFactorEdit>
+<ScrollPosX>0</ScrollPosX>
+<ScrollPosY>0</ScrollPosY>
+<ScrollPosXEdit>0</ScrollPosXEdit>
+<ScrollPosYEdit>0</ScrollPosYEdit>
+<ThreeDFlags>0</ThreeDFlags>
+<ThreeDFlagsEdit>0</ThreeDFlagsEdit>
+<UseModelSprite>0</UseModelSprite>
+<StaticMarginRef>0</StaticMarginRef>
+<UserRefDiameter>0.</UserRefDiameter>
+<SideMarkerHeight>10.</SideMarkerHeight>
+<SideDimensionHeight>10.</SideDimensionHeight>
+<BaseMarkerHeight>10.</BaseMarkerHeight>
+<BaseDimensionHeight>10.</BaseDimensionHeight>
+<ShowGlideCP>0</ShowGlideCP>
+<ShowGridTypeSide>0</ShowGridTypeSide>
+<ShowGridTypeBase>0</ShowGridTypeBase>
+<GridSpacing>10.</GridSpacing>
+<GridOpacity>0.15</GridOpacity>
+<GridColor>black</GridColor>
+<MaxDiaWithFins>339.43</MaxDiaWithFins>
+<MaxDiaWithoutFins>66.3</MaxDiaWithoutFins>
+<MaxLenWithFins>2104.53</MaxLenWithFins>
+<MaxLenWithoutFins>2104.53</MaxLenWithoutFins>
+<MinXExtent>0.</MinXExtent>
+<MaxXExtent>1150.33</MaxXExtent>
+<CalculatedMaxStageDia>0,66.3,66.3,66.3</CalculatedMaxStageDia>
+<CalculatedStageLen>0,296.8,954.2,2104.53</CalculatedStageLen>
+<Cd3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cd3>
+<Cd32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cd32>
+<Cd321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cd321>
+<Cb3>
+<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb3>
+<Cb32>
+<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb32>
+<Cb321>
+<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb321>
+<CNa3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa3>
+<CNa32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa32>
+<CNa321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa321>
+<CP3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP3>
+<CP32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP32>
+<CP321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP321>
+<SimulationEventList>
+</SimulationEventList>
+<Stage3Parts>
+<NoseCone>
+<PartMfg>Aerospace Speciality Products</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>128.148</Density>
+<Material>Balsa</Material>
+<Name>Nose cone</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>42.0747</CalcMass>
+<CalcCG>75.3029</CalcCG>
+<WettedSurface>0.0152945</WettedSurface>
+<PaintedSurface>0.0152945</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>BNC80S</PartNo>
+<PartDesc><![CDATA[T-80H Balsa Nose Cone "S"]]></PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>1</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>2.</BarrowmanCNa>
+<BarrowmanXN>0.0296333</BarrowmanXN>
+<RockSimCNa>2.</RockSimCNa>
+<RockSimXN>0.0296333</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>0.</Station>
+<Len>88.9</Len>
+<BaseDia>66.3</BaseDia>
+<FinishCode>0</FinishCode>
+<ShapeCode>3</ShapeCode>
+<ConstructionType>0</ConstructionType>
+<ShoulderLen>38.1</ShoulderLen>
+<WallThickness>0.</WallThickness>
+<ShapeParameter>0.</ShapeParameter>
+<ShoulderOD>64.3</ShoulderOD>
+<BaseExtensionLen>0.</BaseExtensionLen>
+<CoreDia>0.</CoreDia>
+<CoreLen>0.</CoreLen>
+<AttachedParts>
+<MassObject>
+<PartMfg>Custom</PartMfg>
+<KnownMass>20.</KnownMass>
+<Density>0.</Density>
+<Material>Custom</Material>
+<Name>Clay</Name>
+<KnownCG>17.8</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>17.8</Xb>
+<CalcMass>0.</CalcMass>
+<CalcCG>0.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>2</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>17.8</Station>
+<TypeCode>0</TypeCode>
+<Len>0.</Len>
+<AttachedParts>
+</AttachedParts>
+</MassObject>
+<BodyTube>
+<PartMfg>Apogee</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Attachment Rod</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>6.1</Xb>
+<CalcMass>2.47301</CalcMass>
+<CalcCG>78.85</CalcCG>
+<WettedSurface>0.00684683</WettedSurface>
+<PaintedSurface>0.00684683</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>10062</PartNo>
+<PartDesc>13 mm</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>3</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>6.1</Station>
+<OD>13.82</OD>
+<ID>13.16</ID>
+<Len>157.7</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Plate</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>78.9</Xb>
+<CalcMass>7.86272</CalcMass>
+<CalcCG>1.585</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-(2)0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>4</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>85.</Station>
+<OD>66.</OD>
+<ID>13.82</ID>
+<Len>3.17</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Ring>
+<PartMfg>Custom</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1400.</Density>
+<Material>Carbon Fiber</Material>
+<Name>Sleeve </Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>17.5527</CalcMass>
+<CalcCG>13.85</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>5</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>2</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>136.1</Station>
+<OD>27.7</OD>
+<ID>13.82</ID>
+<Len>27.7</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>3</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Parachute>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>170.</KnownMass>
+<Density>0.006685</Density>
+<Material>Rip stop nylon</Material>
+<Name>Nose Cone Parachute</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>142.6</Xb>
+<CalcMass>15.8812</CalcMass>
+<CalcCG>34.5417</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>1</DensityType>
+<PartNo>LP-50</PartNo>
+<PartDesc>50 In. 16 lines</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>6</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>148.7</Station>
+<Dia>414.5</Dia>
+<SpillHoleDia>0.</SpillHoleDia>
+<SideCount>15</SideCount>
+<ShroudLineCount>16</ShroudLineCount>
+<Thickness>0.05</Thickness>
+<ShroudLineLen>1350.</ShroudLineLen>
+<ChuteCount>1</ChuteCount>
+<ShroudLineMassPerMM>0.00032972</ShroudLineMassPerMM>
+<ShroudLineMaterial>Carpet String (Apogee 29500)</ShroudLineMaterial>
+<DragCoefficient>0.95</DragCoefficient>
+<AttachedParts>
+</AttachedParts>
+</Parachute>
+</AttachedParts>
+</BodyTube>
+</AttachedParts>
+</NoseCone>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>15.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>100.</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>5.80486</CalcMass>
+<CalcCG>100.</CalcCG>
+<WettedSurface>0.0414942</WettedSurface>
+<PaintedSurface>0.0414942</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>EST 3090</PartNo>
+<PartDesc>BT-80</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>7</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(54,250,21)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>88.9</Station>
+<OD>66.04</OD>
+<ID>65.79</ID>
+<Len>200.</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>190.2</Xb>
+<CalcMass>7.65502</CalcMass>
+<CalcCG>1.59</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>8</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>279.1</Station>
+<OD>65.02</OD>
+<ID>25.4</ID>
+<Len>3.18</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>165.</Xb>
+<CalcMass>7.62626</CalcMass>
+<CalcCG>1.585</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-(2)0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>9</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>253.9</Station>
+<OD>65.</OD>
+<ID>25.4</ID>
+<Len>3.17</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<BodyTube>
+<PartMfg>Public Missiles Ltd.</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>958.705</Density>
+<Material>Kraft phenolic</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>137.9</Xb>
+<CalcMass>9.8818</CalcMass>
+<CalcCG>35.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>KS-1.1</PartNo>
+<PartDesc>KwikSwitch MMT 29mm</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>-1.58371</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>10</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>226.8</Station>
+<OD>32.26</OD>
+<ID>29.21</ID>
+<Len>70.</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>1</IsMotorMount>
+<MotorDia>29.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+</AttachedParts>
+</BodyTube>
+</AttachedParts>
+</BodyTube>
+</Stage3Parts>
+<Stage2Parts>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>2nd Stage Tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>10.4685</CalcMass>
+<CalcCG>180.34</CalcCG>
+<WettedSurface>0.0748306</WettedSurface>
+<PaintedSurface>0.0748306</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>EST 3090</PartNo>
+<PartDesc>BT-80</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>11</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(54,250,21)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>288.9</Station>
+<OD>66.04</OD>
+<ID>65.79</ID>
+<Len>360.68</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>15.025</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Tube coupler</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>-10.</Xb>
+<CalcMass>20.465</CalcMass>
+<CalcCG>35.45</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>TC-2.56</PartNo>
+<PartDesc>Tube Coupler</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>12</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>278.9</Station>
+<OD>65.79</OD>
+<ID>63.25</ID>
+<Len>70.9</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>4</UsageCode>
+<AutoSize>1</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<MassObject>
+<PartMfg>Custom</PartMfg>
+<KnownMass>40.</KnownMass>
+<Density>0.</Density>
+<Material>Custom</Material>
+<Name>Electronics</Name>
+<KnownCG>138.3</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>138.3</Xb>
+<CalcMass>0.</CalcMass>
+<CalcCG>0.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>13</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>427.2</Station>
+<TypeCode>0</TypeCode>
+<Len>0.</Len>
+<AttachedParts>
+</AttachedParts>
+</MassObject>
+<FinSet>
+<PartMfg>Quest</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>128.148</Density>
+<Material>Balsa</Material>
+<Name>Fin set</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>228.6</Xb>
+<CalcMass>1.32269</CalcMass>
+<CalcCG>19.05</CalcCG>
+<WettedSurface>0.0028791</WettedSurface>
+<PaintedSurface>0.0086373</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>Payloader One</PartNo>
+<PartDesc>Fin</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.0830777</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>14</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>2.93008</BarrowmanCNa>
+<BarrowmanXN>0.52856</BarrowmanXN>
+<RockSimCNa>5.49629</RockSimCNa>
+<RockSimXN>0.52856</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>517.5</Station>
+<FinCount>3</FinCount>
+<RootChord>38.1</RootChord>
+<TipChord>24.9</TipChord>
+<SemiSpan>45.7</SemiSpan>
+<MidChordLen>45.7</MidChordLen>
+<SweepDistance>6.6</SweepDistance>
+<Thickness>2.39</Thickness>
+<ShapeCode>0</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>2</TipShapeCode>
+<TabLength>0.</TabLength>
+<TabDepth>0.</TabDepth>
+<TabOffset>0.</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.139993</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>54.2741</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>2.83538</RockSimCNaPerFin>
+<TaperRatio>0.653543</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AttachedParts>
+</AttachedParts>
+</FinSet>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>302.</Xb>
+<CalcMass>7.65502</CalcMass>
+<CalcCG>1.59</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>15</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>590.9</Station>
+<OD>65.02</OD>
+<ID>25.4</ID>
+<Len>3.18</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>335.5</Xb>
+<CalcMass>7.62626</CalcMass>
+<CalcCG>1.585</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-(2)0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>16</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>624.4</Station>
+<OD>65.</OD>
+<ID>25.4</ID>
+<Len>3.17</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<BodyTube>
+<PartMfg>Public Missiles Ltd.</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>958.705</Density>
+<Material>Kraft phenolic</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>587.4</Xb>
+<CalcMass>9.8818</CalcMass>
+<CalcCG>35.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>KS-1.1</PartNo>
+<PartDesc>KwikSwitch MMT 29mm</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>-1.58371</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>17</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>1</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>587.4</Station>
+<OD>32.26</OD>
+<ID>29.21</ID>
+<Len>70.</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>1</IsMotorMount>
+<MotorDia>29.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<Ring>
+<PartMfg>Semroc</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Engine block</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>2.69315</CalcMass>
+<CalcCG>2.39</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>TB-7</PartNo>
+<PartDesc>Thrust Block</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>18</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>587.4</Station>
+<OD>29.21</OD>
+<ID>14.61</ID>
+<Len>4.78</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>2</UsageCode>
+<AutoSize>1</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+</AttachedParts>
+</BodyTube>
+</AttachedParts>
+</BodyTube>
+</Stage2Parts>
+<Stage1Parts>
+<Transition>
+<PartMfg>BalsaMachining.com</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>128.148</Density>
+<Material>Balsa</Material>
+<Name>Transition</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>8.62096</CalcMass>
+<CalcCG>25.1578</CalcCG>
+<WettedSurface>0.00986655</WettedSurface>
+<PaintedSurface>0.00986655</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>TA6080</PartNo>
+<PartDesc>Transition T60 to T80 2.25 in long</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>19</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>-1.20451</BarrowmanCNa>
+<BarrowmanXN>0.675971</BarrowmanXN>
+<RockSimCNa>-1.20451</RockSimCNa>
+<RockSimXN>0.675971</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>649.58</Station>
+<FrontDia>66.04</FrontDia>
+<RearDia>41.4</RearDia>
+<Len>57.15</Len>
+<FinishCode>0</FinishCode>
+<FrontShoulderLen>20.</FrontShoulderLen>
+<RearShoulderLen>38.1</RearShoulderLen>
+<ConstructionType>1</ConstructionType>
+<WallThickness>3.</WallThickness>
+<FrontShoulderDia>64.77</FrontShoulderDia>
+<RearShoulderDia>41.38</RearShoulderDia>
+<CoreDia>0.</CoreDia>
+<ShapeCode>0</ShapeCode>
+<ShapeParameter>0.</ShapeParameter>
+<EquivNoseLen>153.172</EquivNoseLen>
+<EquivNoseOffset>96.022</EquivNoseOffset>
+<AttachedParts>
+</AttachedParts>
+</Transition>
+<BodyTube>
+<PartMfg>LOC/Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>33.5306</CalcMass>
+<CalcCG>209.2</CalcCG>
+<WettedSurface>0.0604643</WettedSurface>
+<PaintedSurface>0.0604643</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC BT-2.14</PartNo>
+<PartDesc>Airframe tube</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>20</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(54,250,21)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>706.73</Station>
+<OD>46.</OD>
+<ID>45.</ID>
+<Len>418.4</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<FinSet>
+<PartMfg>Quest</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Elliptical Fins</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>69.7</Xb>
+<CalcMass>36.2048</CalcMass>
+<CalcCG>46.</CalcCG>
+<WettedSurface>0.00676907</WettedSurface>
+<PaintedSurface>0.0203072</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>-0.519061</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>21</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>3.64017</BarrowmanCNa>
+<BarrowmanXN>0.802926</BarrowmanXN>
+<RockSimCNa>6.19583</RockSimCNa>
+<RockSimXN>0.802926</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>776.43</Station>
+<FinCount>3</FinCount>
+<RootChord>92.</RootChord>
+<TipChord>46.</TipChord>
+<SemiSpan>46.9</SemiSpan>
+<MidChordLen>46.9</MidChordLen>
+<SweepDistance>33.49</SweepDistance>
+<Thickness>3.18</Thickness>
+<ShapeCode>1</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>0</TipShapeCode>
+<TabLength>0.</TabLength>
+<TabDepth>0.</TabDepth>
+<TabOffset>0.</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.349066</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>43.8444</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>3.30201</RockSimCNaPerFin>
+<TaperRatio>0.5</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AttachedParts>
+</AttachedParts>
+</FinSet>
+<CustomFinSet>
+<PartMfg>Public Missiles</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1905.24</Density>
+<Material>G10 fiberglass</Material>
+<Name>Custom Fins</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>241.7</Xb>
+<CalcMass>256.292</CalcMass>
+<CalcCG>78.9922</CalcCG>
+<WettedSurface>0.0355266</WettedSurface>
+<PaintedSurface>0.10658</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>FIN-C-02</PartNo>
+<PartDesc>Fins</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.357967</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>22</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>25.7124</BarrowmanCNa>
+<BarrowmanXN>0.996591</BarrowmanXN>
+<RockSimCNa>34.6308</RockSimCNa>
+<RockSimXN>0.996926</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>948.43</Station>
+<FinCount>3</FinCount>
+<RootChord>152.4</RootChord>
+<TipChord>83.83</TipChord>
+<SemiSpan>146.72</SemiSpan>
+<MidChordLen>146.81</MidChordLen>
+<SweepDistance>39.42</SweepDistance>
+<Thickness>2.38</Thickness>
+<ShapeCode>2</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>2</TipShapeCode>
+<TabLength>101.6</TabLength>
+<TabDepth>10.6</TabDepth>
+<TabOffset>35.6</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>89.2598</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>19.9941</RockSimCNaPerFin>
+<TaperRatio>0.550066</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AverageChord>121.07</AverageChord>
+<EffectiveTipChord>83.8257</EffectiveTipChord>
+<PointList>152.4,0|126.202,146.715|36.455,146.715|0,0|</PointList>
+<AutoCalcGridStepX>0,0,0,0,0,0,0</AutoCalcGridStepX>
+<GridStepCountX>10,10,10,10,10,10,10</GridStepCountX>
+<UseAbsoluteGridStepsX>0,0,0,0,0,0,0</UseAbsoluteGridStepsX>
+<GridStepSizeX>0.5,10,0.5,0.5,0.00018939,0.001,1</GridStepSizeX>
+<SnapToSizeX>0.25,5,0.1,0.1,0.00018939,0.001,1</SnapToSizeX>
+<AutoCalcGridStepY>0,0,0,0,0,0,0</AutoCalcGridStepY>
+<GridStepCountY>10,10,10,10,10,10,10</GridStepCountY>
+<UseAbsoluteGridStepsY>0,0,0,0,0,0,0</UseAbsoluteGridStepsY>
+<GridStepSizeY>0.5,10,0.5,0.5,0.00018939,0.001,1</GridStepSizeY>
+<SnapToSizeY>0.25,5,0.1,0.1,0.00018939,0.001,1</SnapToSizeY>
+<AttachedParts>
+</AttachedParts>
+</CustomFinSet>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>379.5</Xb>
+<CalcMass>2.55395</CalcMass>
+<CalcCG>1.59</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC FCR-1.52-1.14</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>23</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>1086.23</Station>
+<OD>45.</OD>
+<ID>24.79</ID>
+<Len>3.18</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>1</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>272.</Xb>
+<CalcMass>2.55395</CalcMass>
+<CalcCG>1.59</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC FCR-1.52-1.14</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>24</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>978.73</Station>
+<OD>45.</OD>
+<ID>24.79</ID>
+<Len>3.18</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>1</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>259.7</Xb>
+<CalcMass>5.22902</CalcMass>
+<CalcCG>91.95</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>EST 3086</PartNo>
+<PartDesc>BT-50</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>25</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>966.43</Station>
+<OD>24.79</OD>
+<ID>24.13</ID>
+<Len>183.9</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>1</IsMotorMount>
+<MotorDia>24.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+</AttachedParts>
+</BodyTube>
+</AttachedParts>
+</BodyTube>
+</Stage1Parts>
+<SideViewDims>
+</SideViewDims>
+<BaseViewDims>
+</BaseViewDims>
+<VertViewDims>
+</VertViewDims>
+</RocketDesign>
+</DesignInformation>
+<SimulationResultsList>
+</SimulationResultsList>
+</RockSimDocument>
--- /dev/null
+<RockSimDocument>
+<FileVersion>3</FileVersion>
+<DesignInformation>
+<RocketDesign>
+<Name>Three Stage Everything Included Rocket - Override Total Mass/CG</Name>
+<CalculateCD>1</CalculateCD>
+<ProCalculateCD>1</ProCalculateCD>
+<ProCalculateCN>1</ProCalculateCN>
+<FixedCd>0.75</FixedCd>
+<FixedCd2>0.8</FixedCd2>
+<FixedCd3>0.81</FixedCd3>
+<FixedCd2Alone>0.95</FixedCd2Alone>
+<FixedCd3Alone>0.95</FixedCd3Alone>
+<StageCount>3</StageCount>
+<Stage3Mass>185.</Stage3Mass>
+<Stage2Mass>210.</Stage2Mass>
+<Stage1Mass>330.</Stage1Mass>
+<Stage321CG>0.</Stage321CG>
+<Stage32CG>0.</Stage32CG>
+<Stage3CG>300.</Stage3CG>
+<Stage2CGAlone>400.</Stage2CGAlone>
+<Stage1CGAlone>500.</Stage1CGAlone>
+<CPCalcFlags>1</CPCalcFlags>
+<LaunchGuideLength>914.4</LaunchGuideLength>
+<UseKnownMass>0</UseKnownMass>
+<DefaultFinish>0</DefaultFinish>
+<FinishMedium>0</FinishMedium>
+<FinishCoatCount>1</FinishCoatCount>
+<GlueType>0</GlueType>
+<CPSimFlags>1</CPSimFlags>
+<LastSerialNumber>32</LastSerialNumber>
+<DisplayFlags>7</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<BarromanXN>0,29.6333,327.236,966.855</BarromanXN>
+<BarrowmanCNa>0,2,4.95647,83.562</BarrowmanCNa>
+<RockSimXN>0,29.6333,385.082,953.76</RockSimXN>
+<RockSimCNa>0,2,6.95476,97.0629</RockSimCNa>
+<RockSimCNa90>0,0,0,0</RockSimCNa90>
+<RockSimXN90>0,0,0,0</RockSimXN90>
+<ViewType>0</ViewType>
+<ViewStageCount>3</ViewStageCount>
+<ViewTypeEdit>0</ViewTypeEdit>
+<ViewStageCountEdit>3</ViewStageCountEdit>
+<ZoomFactor>0.</ZoomFactor>
+<ZoomFactorEdit>0.</ZoomFactorEdit>
+<ScrollPosX>0</ScrollPosX>
+<ScrollPosY>0</ScrollPosY>
+<ScrollPosXEdit>0</ScrollPosXEdit>
+<ScrollPosYEdit>0</ScrollPosYEdit>
+<ThreeDFlags>0</ThreeDFlags>
+<ThreeDFlagsEdit>0</ThreeDFlagsEdit>
+<UseModelSprite>0</UseModelSprite>
+<StaticMarginRef>0</StaticMarginRef>
+<UserRefDiameter>0.</UserRefDiameter>
+<SideMarkerHeight>10.</SideMarkerHeight>
+<SideDimensionHeight>10.</SideDimensionHeight>
+<BaseMarkerHeight>10.</BaseMarkerHeight>
+<BaseDimensionHeight>10.</BaseDimensionHeight>
+<ShowGlideCP>0</ShowGlideCP>
+<ShowGridTypeSide>0</ShowGridTypeSide>
+<ShowGridTypeBase>0</ShowGridTypeBase>
+<GridSpacing>10.</GridSpacing>
+<GridOpacity>0.15</GridOpacity>
+<GridColor>black</GridColor>
+<MaxDiaWithFins>334.83</MaxDiaWithFins>
+<MaxDiaWithoutFins>66.</MaxDiaWithoutFins>
+<MaxLenWithFins>2155.23</MaxLenWithFins>
+<MaxLenWithoutFins>2155.23</MaxLenWithoutFins>
+<MinXExtent>0.</MinXExtent>
+<MaxXExtent>1150.33</MaxXExtent>
+<CalculatedMaxStageDia>0,66,66,66</CalculatedMaxStageDia>
+<CalculatedStageLen>0,347.5,1004.9,2155.23</CalculatedStageLen>
+<Cd3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cd3>
+<Cd32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cd32>
+<Cd321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cd321>
+<Cb3>
+<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb3>
+<Cb32>
+<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb32>
+<Cb321>
+<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</Cb321>
+<CNa3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa3>
+<CNa32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa32>
+<CNa321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CNa321>
+<CP3>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP3>
+<CP32>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP32>
+<CP321>
+<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
+<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
+<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
+<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
+<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
+</PolyData>
+</CP321>
+<SimulationEventList>
+</SimulationEventList>
+<Stage3Parts>
+<NoseCone>
+<PartMfg>Aerospace Speciality Products</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>128.148</Density>
+<Material>Balsa</Material>
+<Name>Nose cone</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>42.6368</CalcMass>
+<CalcCG>76.0242</CalcCG>
+<WettedSurface>0.0152192</WettedSurface>
+<PaintedSurface>0.0152192</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>BNC80S</PartNo>
+<PartDesc><![CDATA[T-80H Balsa Nose Cone "S"]]></PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>1</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>2.</BarrowmanCNa>
+<BarrowmanXN>0.0296333</BarrowmanXN>
+<RockSimCNa>2.</RockSimCNa>
+<RockSimXN>0.0296333</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>0.</Station>
+<Len>88.9</Len>
+<BaseDia>66.</BaseDia>
+<FinishCode>0</FinishCode>
+<ShapeCode>3</ShapeCode>
+<ConstructionType>0</ConstructionType>
+<ShoulderLen>38.1</ShoulderLen>
+<WallThickness>0.</WallThickness>
+<ShapeParameter>0.</ShapeParameter>
+<ShoulderOD>65.9</ShoulderOD>
+<BaseExtensionLen>0.</BaseExtensionLen>
+<CoreDia>0.</CoreDia>
+<CoreLen>0.</CoreLen>
+<AttachedParts>
+<MassObject>
+<PartMfg>Custom</PartMfg>
+<KnownMass>20.</KnownMass>
+<Density>0.</Density>
+<Material>Custom</Material>
+<Name>Clay</Name>
+<KnownCG>17.8</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>17.8</Xb>
+<CalcMass>0.</CalcMass>
+<CalcCG>0.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>2</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>17.8</Station>
+<TypeCode>0</TypeCode>
+<Len>0.</Len>
+<AttachedParts>
+</AttachedParts>
+</MassObject>
+<BodyTube>
+<PartMfg>Apogee</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Attachment Rod</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>6.1</Xb>
+<CalcMass>2.47301</CalcMass>
+<CalcCG>78.85</CalcCG>
+<WettedSurface>0.00684683</WettedSurface>
+<PaintedSurface>0.00684683</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>10062</PartNo>
+<PartDesc>13 mm</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>3</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>6.1</Station>
+<OD>13.82</OD>
+<ID>13.16</ID>
+<Len>157.7</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Plate</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>78.9</Xb>
+<CalcMass>7.86272</CalcMass>
+<CalcCG>1.585</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-(2)0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>4</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>85.</Station>
+<OD>66.</OD>
+<ID>13.82</ID>
+<Len>3.17</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Ring>
+<PartMfg>Custom</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1400.</Density>
+<Material>Carbon Fiber</Material>
+<Name>Sleeve </Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>17.5527</CalcMass>
+<CalcCG>13.85</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>5</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>2</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>136.1</Station>
+<OD>27.7</OD>
+<ID>13.82</ID>
+<Len>27.7</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>3</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Parachute>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>170.</KnownMass>
+<Density>0.006685</Density>
+<Material>Rip stop nylon</Material>
+<Name>Nose Cone Parachute</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>142.6</Xb>
+<CalcMass>15.8812</CalcMass>
+<CalcCG>34.5417</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>1</DensityType>
+<PartNo>LP-50</PartNo>
+<PartDesc>50 In. 16 lines</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>6</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>148.7</Station>
+<Dia>414.5</Dia>
+<SpillHoleDia>0.</SpillHoleDia>
+<SideCount>15</SideCount>
+<ShroudLineCount>16</ShroudLineCount>
+<Thickness>0.05</Thickness>
+<ShroudLineLen>1350.</ShroudLineLen>
+<ChuteCount>1</ChuteCount>
+<ShroudLineMassPerMM>0.00032972</ShroudLineMassPerMM>
+<ShroudLineMaterial>Carpet String (Apogee 29500)</ShroudLineMaterial>
+<DragCoefficient>0.95</DragCoefficient>
+<AttachedParts>
+</AttachedParts>
+</Parachute>
+</AttachedParts>
+</BodyTube>
+</AttachedParts>
+</NoseCone>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>15.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>100.</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>5.805</CalcMass>
+<CalcCG>100.</CalcCG>
+<WettedSurface>0.0414942</WettedSurface>
+<PaintedSurface>0.0414942</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>EST 3090</PartNo>
+<PartDesc>BT-80</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>7</SerialNo>
+<DisplayFlags>1</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(54,250,21)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>88.9</Station>
+<OD>66.</OD>
+<ID>65.79</ID>
+<Len>200.</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>190.2</Xb>
+<CalcMass>7.65502</CalcMass>
+<CalcCG>1.59</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>8</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>279.1</Station>
+<OD>65.02</OD>
+<ID>25.4</ID>
+<Len>3.18</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>165.</Xb>
+<CalcMass>7.62626</CalcMass>
+<CalcCG>1.585</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-(2)0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>9</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>253.9</Station>
+<OD>65.</OD>
+<ID>25.4</ID>
+<Len>3.17</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<BodyTube>
+<PartMfg>Public Missiles Ltd.</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>958.705</Density>
+<Material>Kraft phenolic</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>137.9</Xb>
+<CalcMass>9.8818</CalcMass>
+<CalcCG>35.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>KS-1.1</PartNo>
+<PartDesc>KwikSwitch MMT 29mm</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>-1.58371</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>10</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>226.8</Station>
+<OD>32.26</OD>
+<ID>29.21</ID>
+<Len>70.</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>1</IsMotorMount>
+<MotorDia>29.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+</AttachedParts>
+</BodyTube>
+<LaunchLug>
+<PartMfg>Apogee</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Launch lug</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>77.2</Xb>
+<CalcMass>1.11942</CalcMass>
+<CalcCG>38.1</CalcCG>
+<WettedSurface>0.00374518</WettedSurface>
+<PaintedSurface>0.00199411</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>13056</PartNo>
+<PartDesc><![CDATA[1/4" X 3]]></PartDesc>
+<RadialLoc>37.185</RadialLoc>
+<RadialAngle>3.14</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>26</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>166.1</Station>
+<OD>8.33</OD>
+<ID>7.26</ID>
+<Len>76.2</Len>
+<FinishCode>0</FinishCode>
+<AttachedParts>
+</AttachedParts>
+</LaunchLug>
+<ExternalPod>
+<PartMfg>Custom</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>0.</Density>
+<Name>Pod</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>200.</Xb>
+<CalcMass>0.</CalcMass>
+<CalcCG>0.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>36.175</RadialLoc>
+<RadialAngle>-1.50735</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>29</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>288.9</Station>
+<Detachable>1</Detachable>
+<AutoCalcRadialDistance>1</AutoCalcRadialDistance>
+<AutoCalcRadialAngle>1</AutoCalcRadialAngle>
+<AttachedParts>
+<BodyTube>
+<PartMfg>Apogee</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>958.705</Density>
+<Material>Kraft phenolic</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>0.400397</CalcMass>
+<CalcCG>29.3</CalcCG>
+<WettedSurface>0.00116902</WettedSurface>
+<PaintedSurface>0.00116902</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>9601</PartNo>
+<PartDesc>6 mm</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>30</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(54,250,21)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>288.9</Station>
+<OD>6.35</OD>
+<ID>5.59</ID>
+<Len>58.6</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+</AttachedParts>
+</BodyTube>
+</AttachedParts>
+</ExternalPod>
+</AttachedParts>
+</BodyTube>
+</Stage3Parts>
+<Stage2Parts>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>2nd Stage Tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>10.468</CalcMass>
+<CalcCG>180.34</CalcCG>
+<WettedSurface>0.0748306</WettedSurface>
+<PaintedSurface>0.0748306</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>EST 3090</PartNo>
+<PartDesc>BT-80</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>11</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(54,250,21)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>288.9</Station>
+<OD>66.</OD>
+<ID>65.79</ID>
+<Len>360.68</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>15.025</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Tube coupler</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>-10.</Xb>
+<CalcMass>20.465</CalcMass>
+<CalcCG>35.45</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>TC-2.56</PartNo>
+<PartDesc>Tube Coupler</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>12</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>278.9</Station>
+<OD>65.79</OD>
+<ID>63.25</ID>
+<Len>70.9</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>4</UsageCode>
+<AutoSize>1</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<MassObject>
+<PartMfg>Custom</PartMfg>
+<KnownMass>40.</KnownMass>
+<Density>0.</Density>
+<Material>Custom</Material>
+<Name>Electronics</Name>
+<KnownCG>138.3</KnownCG>
+<UseKnownCG>1</UseKnownCG>
+<Xb>138.3</Xb>
+<CalcMass>0.</CalcMass>
+<CalcCG>0.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>13</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>427.2</Station>
+<TypeCode>0</TypeCode>
+<Len>0.</Len>
+<AttachedParts>
+</AttachedParts>
+</MassObject>
+<FinSet>
+<PartMfg>Quest</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>128.148</Density>
+<Material>Balsa</Material>
+<Name>Fin set</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>228.6</Xb>
+<CalcMass>1.32269</CalcMass>
+<CalcCG>19.05</CalcCG>
+<WettedSurface>0.0028791</WettedSurface>
+<PaintedSurface>0.0086373</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>Payloader One</PartNo>
+<PartDesc>Fin</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.0830777</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>14</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>2.95647</BarrowmanCNa>
+<BarrowmanXN>0.52856</BarrowmanXN>
+<RockSimCNa>5.54523</RockSimCNa>
+<RockSimXN>0.52856</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>517.5</Station>
+<FinCount>3</FinCount>
+<RootChord>38.1</RootChord>
+<TipChord>24.9</TipChord>
+<SemiSpan>45.7</SemiSpan>
+<MidChordLen>45.7</MidChordLen>
+<SweepDistance>6.6</SweepDistance>
+<Thickness>2.39</Thickness>
+<ShapeCode>0</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>2</TipShapeCode>
+<TabLength>0.</TabLength>
+<TabDepth>0.</TabDepth>
+<TabOffset>0.</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.139993</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>54.2541</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>2.86063</RockSimCNaPerFin>
+<TaperRatio>0.653543</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AttachedParts>
+</AttachedParts>
+</FinSet>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>302.</Xb>
+<CalcMass>7.65502</CalcMass>
+<CalcCG>1.59</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>15</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>590.9</Station>
+<OD>65.02</OD>
+<ID>25.4</ID>
+<Len>3.18</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>335.5</Xb>
+<CalcMass>7.62626</CalcMass>
+<CalcCG>1.585</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC CR-2.56-(2)0.95</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>16</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>624.4</Station>
+<OD>65.</OD>
+<ID>25.4</ID>
+<Len>3.17</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>0</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<BodyTube>
+<PartMfg>Public Missiles Ltd.</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>958.705</Density>
+<Material>Kraft phenolic</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>587.4</Xb>
+<CalcMass>9.8818</CalcMass>
+<CalcCG>35.</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>KS-1.1</PartNo>
+<PartDesc>KwikSwitch MMT 29mm</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>-1.58371</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>17</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>1</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>587.4</Station>
+<OD>32.26</OD>
+<ID>29.21</ID>
+<Len>70.</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>1</IsMotorMount>
+<MotorDia>29.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<Ring>
+<PartMfg>Semroc</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Engine block</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>2.69315</CalcMass>
+<CalcCG>2.39</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>TB-7</PartNo>
+<PartDesc>Thrust Block</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>18</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>587.4</Station>
+<OD>29.21</OD>
+<ID>14.61</ID>
+<Len>4.78</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>2</UsageCode>
+<AutoSize>1</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+</AttachedParts>
+</BodyTube>
+<LaunchLug>
+<PartMfg>Apogee</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Launch lug</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>265.8</Xb>
+<CalcMass>1.11942</CalcMass>
+<CalcCG>38.1</CalcCG>
+<WettedSurface>0.00374518</WettedSurface>
+<PaintedSurface>0.00199411</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>13056</PartNo>
+<PartDesc><![CDATA[1/4" X 3]]></PartDesc>
+<RadialLoc>37.185</RadialLoc>
+<RadialAngle>1.22</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>27</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>554.7</Station>
+<OD>8.33</OD>
+<ID>7.26</ID>
+<Len>76.2</Len>
+<FinishCode>0</FinishCode>
+<AttachedParts>
+</AttachedParts>
+</LaunchLug>
+</AttachedParts>
+</BodyTube>
+</Stage2Parts>
+<Stage1Parts>
+<Transition>
+<PartMfg>BalsaMachining.com</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>128.148</Density>
+<Material>Balsa</Material>
+<Name>Transition</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>8.61936</CalcMass>
+<CalcCG>25.1551</CalcCG>
+<WettedSurface>0.0098623</WettedSurface>
+<PaintedSurface>0.0098623</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>TA6080</PartNo>
+<PartDesc>Transition T60 to T80 2.25 in long</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>19</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>-1.213</BarrowmanCNa>
+<BarrowmanXN>0.675973</BarrowmanXN>
+<RockSimCNa>-1.213</RockSimCNa>
+<RockSimXN>0.675973</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>649.58</Station>
+<FrontDia>66.</FrontDia>
+<RearDia>41.4</RearDia>
+<Len>57.15</Len>
+<FinishCode>0</FinishCode>
+<FrontShoulderLen>20.</FrontShoulderLen>
+<RearShoulderLen>38.1</RearShoulderLen>
+<ConstructionType>1</ConstructionType>
+<WallThickness>3.</WallThickness>
+<FrontShoulderDia>64.77</FrontShoulderDia>
+<RearShoulderDia>41.38</RearShoulderDia>
+<CoreDia>0.</CoreDia>
+<ShapeCode>0</ShapeCode>
+<ShapeParameter>0.</ShapeParameter>
+<EquivNoseLen>153.339</EquivNoseLen>
+<EquivNoseOffset>96.1895</EquivNoseOffset>
+<AttachedParts>
+</AttachedParts>
+</Transition>
+<BodyTube>
+<PartMfg>LOC/Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>0.</CalcMass>
+<CalcCG>nan.</CalcCG>
+<WettedSurface>0.0544179</WettedSurface>
+<PaintedSurface>0.0544179</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC BT-2.14</PartNo>
+<PartDesc>Airframe tube</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>20</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(54,250,21)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>706.73</Station>
+<OD>41.4</OD>
+<ID>41.</ID>
+<Len>418.4</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>0</IsMotorMount>
+<MotorDia>0.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>0</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+<FinSet>
+<PartMfg>Quest</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Elliptical Fins</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>69.7</Xb>
+<CalcMass>36.2048</CalcMass>
+<CalcCG>46.</CalcCG>
+<WettedSurface>0.00676907</WettedSurface>
+<PaintedSurface>0.0203072</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>-0.519061</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>21</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>3.61024</BarrowmanCNa>
+<BarrowmanXN>0.802926</BarrowmanXN>
+<RockSimCNa>6.03948</RockSimCNa>
+<RockSimXN>0.802926</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>776.43</Station>
+<FinCount>3</FinCount>
+<RootChord>92.</RootChord>
+<TipChord>46.</TipChord>
+<SemiSpan>46.9</SemiSpan>
+<MidChordLen>46.9</MidChordLen>
+<SweepDistance>33.49</SweepDistance>
+<Thickness>3.18</Thickness>
+<ShapeCode>1</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>0</TipShapeCode>
+<TabLength>0.</TabLength>
+<TabDepth>0.</TabDepth>
+<TabOffset>0.</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.349066</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>41.5444</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>3.21868</RockSimCNaPerFin>
+<TaperRatio>0.5</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AttachedParts>
+</AttachedParts>
+</FinSet>
+<CustomFinSet>
+<PartMfg>Public Missiles</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1905.24</Density>
+<Material>G10 fiberglass</Material>
+<Name>Custom Fins</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>241.7</Xb>
+<CalcMass>256.292</CalcMass>
+<CalcCG>78.9922</CalcCG>
+<WettedSurface>0.0355266</WettedSurface>
+<PaintedSurface>0.10658</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>FIN-C-02</PartNo>
+<PartDesc>Fins</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.357967</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>22</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>25.7037</BarrowmanCNa>
+<BarrowmanXN>0.996526</BarrowmanXN>
+<RockSimCNa>34.1865</RockSimCNa>
+<RockSimXN>0.996822</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>948.43</Station>
+<FinCount>3</FinCount>
+<RootChord>152.4</RootChord>
+<TipChord>84.53</TipChord>
+<SemiSpan>146.72</SemiSpan>
+<MidChordLen>146.81</MidChordLen>
+<SweepDistance>39.07</SweepDistance>
+<Thickness>2.38</Thickness>
+<ShapeCode>2</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>2</TipShapeCode>
+<TabLength>101.6</TabLength>
+<TabDepth>10.6</TabDepth>
+<TabOffset>35.6</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>87.0529</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>19.7376</RockSimCNaPerFin>
+<TaperRatio>0.554659</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<AverageChord>121.39</AverageChord>
+<EffectiveTipChord>84.5261</EffectiveTipChord>
+<PointList>152.4,0|126.202,146.715|36.455,146.715|0,0|</PointList>
+<AutoCalcGridStepX>0,0,0,0,0,0,0</AutoCalcGridStepX>
+<GridStepCountX>10,10,10,10,10,10,10</GridStepCountX>
+<UseAbsoluteGridStepsX>0,0,0,0,0,0,0</UseAbsoluteGridStepsX>
+<GridStepSizeX>0.5,10,0.5,0.5,0.00018939,0.001,1</GridStepSizeX>
+<SnapToSizeX>0.25,5,0.1,0.1,0.00018939,0.001,1</SnapToSizeX>
+<AutoCalcGridStepY>0,0,0,0,0,0,0</AutoCalcGridStepY>
+<GridStepCountY>10,10,10,10,10,10,10</GridStepCountY>
+<UseAbsoluteGridStepsY>0,0,0,0,0,0,0</UseAbsoluteGridStepsY>
+<GridStepSizeY>0.5,10,0.5,0.5,0.00018939,0.001,1</GridStepSizeY>
+<SnapToSizeY>0.25,5,0.1,0.1,0.00018939,0.001,1</SnapToSizeY>
+<AttachedParts>
+</AttachedParts>
+</CustomFinSet>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>379.5</Xb>
+<CalcMass>1.99074</CalcMass>
+<CalcCG>1.59</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC FCR-1.52-1.14</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>23</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>1086.23</Station>
+<OD>41.4</OD>
+<ID>24.79</ID>
+<Len>3.18</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>1</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<Ring>
+<PartMfg>LOC Precision</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>724.996</Density>
+<Material>Aircraft plywood (LOC)</Material>
+<Name>Centering ring</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>272.</Xb>
+<CalcMass>1.99074</CalcMass>
+<CalcCG>1.59</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>LOC FCR-1.52-1.14</PartNo>
+<PartDesc>Centering Ring</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>24</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>978.73</Station>
+<OD>41.4</OD>
+<ID>24.79</ID>
+<Len>3.18</Len>
+<FinishCode>0</FinishCode>
+<UsageCode>0</UsageCode>
+<AutoSize>1</AutoSize>
+<AttachedParts>
+</AttachedParts>
+</Ring>
+<BodyTube>
+<PartMfg>Estes</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Body tube</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>259.7</Xb>
+<CalcMass>5.22902</CalcMass>
+<CalcCG>91.95</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>EST 3086</PartNo>
+<PartDesc>BT-50</PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>rgb(0,0,250)</AbientColor>
+<DiffuseColor>rgb(0,0,250)</DiffuseColor>
+<SpecularColor>rgb(255,255,255)</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>25</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>rgb(0,0,250)</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>966.43</Station>
+<OD>24.79</OD>
+<ID>24.13</ID>
+<Len>183.9</Len>
+<FinishCode>0</FinishCode>
+<IsMotorMount>1</IsMotorMount>
+<MotorDia>24.</MotorDia>
+<EngineOverhang>0.5</EngineOverhang>
+<FrontExtension>0.</FrontExtension>
+<RearExtension>0.</RearExtension>
+<IsInsideTube>1</IsInsideTube>
+<isStrapOnTube>0</isStrapOnTube>
+<AttachedParts>
+</AttachedParts>
+</BodyTube>
+<TubeFinSet>
+<PartMfg>Custom</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1121.29</Density>
+<Material>Paper</Material>
+<Name>Tube fins</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>12.6878</CalcMass>
+<CalcCG>24.79</CalcCG>
+<WettedSurface>0.0688063</WettedSurface>
+<PaintedSurface>0.0688063</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>35.395</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>28</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>10.866</BarrowmanCNa>
+<BarrowmanXN>0.707815</BarrowmanXN>
+<RockSimCNa>10.866</RockSimCNa>
+<RockSimXN>0.707815</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>706.73</Station>
+<OD>24.79</OD>
+<ID>24.13</ID>
+<Len>49.58</Len>
+<FinishCode>0</FinishCode>
+<TubeCount>9</TubeCount>
+<MinTubeAngle>0.715549</MinTubeAngle>
+<MaxTubesAllowed>9</MaxTubesAllowed>
+<AttachedParts>
+</AttachedParts>
+</TubeFinSet>
+<RingTail>
+<PartMfg>Custom</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>688.794</Density>
+<Material>Cardboard</Material>
+<Name>Ringtail</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>0.</Xb>
+<CalcMass>2.93707</CalcMass>
+<CalcCG>10.</CalcCG>
+<WettedSurface>0.00474229</WettedSurface>
+<PaintedSurface>0.00444249</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>31</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>2</LocationMode>
+<Color>rgb(255,9,18)</Color>
+<BarrowmanCNa>39.6386</BarrowmanCNa>
+<BarrowmanXN>1.10463</BarrowmanXN>
+<RockSimCNa>39.6386</RockSimCNa>
+<RockSimXN>1.10463</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>1105.13</Station>
+<FinCount>3</FinCount>
+<RootChord>20.</RootChord>
+<TipChord>20.</TipChord>
+<SemiSpan>7.495</SemiSpan>
+<MidChordLen>7.495</MidChordLen>
+<SweepDistance>0.</SweepDistance>
+<Thickness>3.</Thickness>
+<ShapeCode>0</ShapeCode>
+<FinishCode>0</FinishCode>
+<TipShapeCode>0</TipShapeCode>
+<TabLength>0.</TabLength>
+<TabDepth>0.</TabDepth>
+<TabOffset>0.</TabOffset>
+<SweepMode>1</SweepMode>
+<SweepAngle>0.</SweepAngle>
+<RockSimXNPerFin>0.</RockSimXNPerFin>
+<RockSimRadialXNPerFin>0.</RockSimRadialXNPerFin>
+<RockSimCNaPerFin>0.</RockSimCNaPerFin>
+<TaperRatio>0.</TaperRatio>
+<CantAngle>0.</CantAngle>
+<CantPivotPoint>0.</CantPivotPoint>
+<OD>56.39</OD>
+<ID>55.37</ID>
+<Len>20.</Len>
+<TubeDensity>1121.29</TubeDensity>
+<TubeDensityType>0</TubeDensityType>
+<TubeMaterial>Paper</TubeMaterial>
+<AttachedParts>
+</AttachedParts>
+</RingTail>
+<Streamer>
+<PartMfg>Apogee</PartMfg>
+<KnownMass>0.</KnownMass>
+<Density>1309.</Density>
+<Material>Mylar</Material>
+<Name>Streamer</Name>
+<KnownCG>0.</KnownCG>
+<UseKnownCG>0</UseKnownCG>
+<Xb>149.4</Xb>
+<CalcMass>5.67514</CalcMass>
+<CalcCG>50.8</CalcCG>
+<WettedSurface>0.</WettedSurface>
+<PaintedSurface>0.</PaintedSurface>
+<GlueJointLength>0.</GlueJointLength>
+<DensityType>0</DensityType>
+<PartNo>29006</PartNo>
+<PartDesc><![CDATA[4" Wide Mylar]]></PartDesc>
+<RadialLoc>0.</RadialLoc>
+<RadialAngle>0.</RadialAngle>
+<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
+<Opacity>1.</Opacity>
+<Specular>0.</Specular>
+<SpecularPower>1.</SpecularPower>
+<Ambient>0.</Ambient>
+<Diffuse>1.</Diffuse>
+<AbientColor>blue</AbientColor>
+<DiffuseColor>blue</DiffuseColor>
+<SpecularColor>white</SpecularColor>
+<UseSingleColor>1</UseSingleColor>
+<SerialNo>32</SerialNo>
+<DisplayFlags>0</DisplayFlags>
+<MetricsFlags>0</MetricsFlags>
+<LocationMode>0</LocationMode>
+<Color>blue</Color>
+<BarrowmanCNa>0.</BarrowmanCNa>
+<BarrowmanXN>0.</BarrowmanXN>
+<RockSimCNa>0.</RockSimCNa>
+<RockSimXN>0.</RockSimXN>
+<SimpleColorModel>1</SimpleColorModel>
+<ProduceTemplate>0</ProduceTemplate>
+<TemplateUnits>8</TemplateUnits>
+<Removed>0</Removed>
+<Station>856.13</Station>
+<Len>1422.4</Len>
+<Width>101.6</Width>
+<Thickness>0.03</Thickness>
+<StreamerCount>1</StreamerCount>
+<DragCoefficient>0.127</DragCoefficient>
+<IsFolded>0</IsFolded>
+<AutoCalcCd>1</AutoCalcCd>
+<AttachedParts>
+</AttachedParts>
+</Streamer>
+</AttachedParts>
+</BodyTube>
+</Stage1Parts>
+<SideViewDims>
+</SideViewDims>
+<BaseViewDims>
+</BaseViewDims>
+<VertViewDims>
+</VertViewDims>
+</RocketDesign>
+</DesignInformation>
+<SimulationResultsList>
+</SimulationResultsList>
+</RockSimDocument>
--- /dev/null
+package net.sf.openrocket.gui;
+
+import org.junit.Test;
+
+public class TestGUI {
+
+ @Test
+ public void test() {
+ // No-op
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.gui.configdialog;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sf.openrocket.gui.adaptors.DoubleModel;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.CenteringRing;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class FinSetConfigTest extends BaseTestCase {
+
+ static Method method;
+
+ @BeforeClass
+ public static void classSetup() throws Exception {
+ method = FinSetConfig.class.getDeclaredMethod("computeFinTabLength", List.class, Double.class, Double.class, DoubleModel.class, RocketComponent.class);
+ Assert.assertNotNull(method);
+ method.setAccessible(true);
+ }
+
+ /**
+ * Test no centering rings.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testComputeFinTabLength() throws Exception {
+ DoubleModel dm = new DoubleModel(1d);
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ RocketComponent parent = new BodyTube();
+
+ Double result = (Double)method.invoke(null, rings, 10d, 11d, dm, parent);
+ Assert.assertEquals(0.0001, 11d, result.doubleValue());
+ result = (Double)method.invoke(null, null, 10d, 11d, dm, parent);
+ Assert.assertEquals(11d, result.doubleValue(), 0.0001);
+ }
+
+ /**
+ * Test 2 rings both ahead of the fin.
+ */
+ @Test
+ public void testCompute2LeadingRings() throws Exception {
+ DoubleModel dm = new DoubleModel(1d);
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ RocketComponent parent = new BodyTube();
+
+ CenteringRing ring1 = new CenteringRing();
+ ring1.setLength(0.004);
+ ring1.setRelativePosition(RocketComponent.Position.TOP);
+ ring1.setPositionValue(0.43);
+ CenteringRing ring2 = new CenteringRing();
+ ring2.setLength(0.004);
+ ring2.setRelativePosition(RocketComponent.Position.TOP);
+ ring2.setPositionValue(0.45);
+ rings.add(ring1);
+ rings.add(ring2);
+ parent.addChild(ring1);
+ parent.addChild(ring2);
+
+ Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
+ Assert.assertEquals(0.01, result.doubleValue(), 0.0001);
+
+ }
+
+ /**
+ * Test one ring, ahead of the fin.
+ */
+ @Test
+ public void testCompute1Ring() throws Exception {
+ DoubleModel dm = new DoubleModel(1d);
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ CenteringRing ring1 = new CenteringRing();
+ ring1.setLength(0.004);
+ ring1.setRelativePosition(RocketComponent.Position.TOP);
+ ring1.setPositionValue(0.43);
+ rings.add(ring1);
+
+ RocketComponent parent = new BodyTube();
+ parent.addChild(ring1);
+
+ Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
+ Assert.assertEquals(0.01, result.doubleValue(), 0.0001);
+ }
+
+ /**
+ * Test one ring ahead of the fin, one ring within the root chord.
+ */
+ @Test
+ public void testComputeOneLeadingOneRingWithinRoot() throws Exception {
+ DoubleModel dm = new DoubleModel(1d);
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ CenteringRing ring1 = new CenteringRing();
+ ring1.setRelativePosition(RocketComponent.Position.TOP);
+ ring1.setLength(0.004);
+ ring1.setPositionValue(0.43);
+ CenteringRing ring2 = new CenteringRing();
+ ring2.setRelativePosition(RocketComponent.Position.TOP);
+ ring2.setLength(0.004);
+ ring2.setPositionValue(0.45);
+ rings.add(ring1);
+ rings.add(ring2);
+
+ RocketComponent parent = new BodyTube(1d, 0.01);
+ parent.addChild(ring1);
+ parent.addChild(ring2);
+
+ Double result = (Double)method.invoke(null, rings, 0.45d, 0.01, dm, parent);
+ Assert.assertEquals(0.01 - 0.004, result.doubleValue(), 0.0001);
+ }
+
+ /**
+ * Test one ring ahead of the fin, one ring beyond the root chord.
+ */
+ @Test
+ public void testComputeOneLeadingOneTrailingRing() throws Exception {
+ DoubleModel dm = new DoubleModel(1d);
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ CenteringRing ring1 = new CenteringRing();
+ ring1.setRelativePosition(RocketComponent.Position.TOP);
+ ring1.setLength(0.004);
+ ring1.setPositionValue(0.43);
+ CenteringRing ring2 = new CenteringRing();
+ ring2.setRelativePosition(RocketComponent.Position.TOP);
+ ring2.setLength(0.004);
+ ring2.setPositionValue(0.48);
+ rings.add(ring1);
+ rings.add(ring2);
+
+ RocketComponent parent = new BodyTube();
+ Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, ring1);
+ Assert.assertEquals(0.01, result.doubleValue(), 0.0001);
+ }
+
+ /**
+ * Test one ring within the root chord, another ring beyond the root chord.
+ */
+ @Test
+ public void testComputeOneWithinRootOneTrailingRing() throws Exception {
+ DoubleModel dm = new DoubleModel(1d);
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ CenteringRing ring1 = new CenteringRing();
+ ring1.setRelativePosition(RocketComponent.Position.TOP);
+ ring1.setLength(0.004);
+ ring1.setPositionValue(0.4701);
+ CenteringRing ring2 = new CenteringRing();
+ ring2.setLength(0.004);
+ ring2.setRelativePosition(RocketComponent.Position.TOP);
+ ring2.setPositionValue(0.48);
+ rings.add(ring1);
+ rings.add(ring2);
+ RocketComponent parent = new BodyTube(1.0d, 0.1d);
+ parent.addChild(ring1);
+ parent.addChild(ring2);
+ Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
+ Assert.assertEquals(0.0059, result.doubleValue(), 0.0001);
+ }
+
+ /**
+ * Test both rings within the root chord.
+ */
+ @Test
+ public void testBothRingsWithinRootChord() throws Exception {
+ DoubleModel dm = new DoubleModel(1d);
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ RocketComponent parent = new BodyTube(1.0000d, 0.1d);
+ CenteringRing ring1 = new CenteringRing();
+ ring1.setRelativePosition(RocketComponent.Position.TOP);
+ ring1.setLength(0.004);
+ ring1.setPositionValue(0.4701);
+ parent.addChild(ring1);
+ CenteringRing ring2 = new CenteringRing();
+ ring2.setLength(0.004);
+ ring2.setRelativePosition(RocketComponent.Position.TOP);
+ ring2.setPositionValue(0.4750);
+ parent.addChild(ring2);
+ rings.add(ring1);
+ rings.add(ring2);
+
+ Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
+ Assert.assertEquals(0.0009, result.doubleValue(), 0.0002);
+ }
+
+
+ /**
+ * Test both rings beyond the root chord.
+ */
+ @Test
+ public void testBothRingsBeyondRootChord() throws Exception {
+ DoubleModel dm = new DoubleModel(1d);
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ CenteringRing ring1 = new CenteringRing();
+ ring1.setRelativePosition(RocketComponent.Position.TOP);
+ ring1.setLength(0.004);
+ ring1.setPositionValue(0.48);
+ CenteringRing ring2 = new CenteringRing();
+ ring2.setRelativePosition(RocketComponent.Position.TOP);
+ ring2.setLength(0.004);
+ ring2.setPositionValue(0.49);
+ rings.add(ring1);
+ rings.add(ring2);
+ RocketComponent parent = new BodyTube(1.0d, 0.1d);
+ parent.addChild(ring1);
+ parent.addChild(ring2);
+
+ Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
+ Assert.assertEquals(0.0, result.doubleValue(), 0.0001);
+ }
+
+ /**
+ * Test both rings within the root chord - the top ring has an adjacent ring (so 3 rings total).
+ */
+ @Test
+ public void test3RingsWithinRootChord() throws Exception {
+ DoubleModel dm = new DoubleModel(1d);
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ CenteringRing ring1 = new CenteringRing();
+ ring1.setRelativePosition(RocketComponent.Position.ABSOLUTE);
+ ring1.setLength(0.004);
+ ring1.setPositionValue(0.47);
+ CenteringRing ring2 = new CenteringRing();
+ ring2.setRelativePosition(RocketComponent.Position.ABSOLUTE);
+ ring2.setLength(0.004);
+ ring2.setPositionValue(0.4702);
+ CenteringRing ring3 = new CenteringRing();
+ ring3.setRelativePosition(RocketComponent.Position.ABSOLUTE);
+ ring3.setLength(0.004);
+ ring3.setPositionValue(0.4770);
+ rings.add(ring1);
+ rings.add(ring2);
+ rings.add(ring3);
+ BodyTube parent = new BodyTube(1.0d, 0.1d);
+ parent.setPositionValue(0);
+ parent.addChild(ring1);
+ parent.addChild(ring2);
+ parent.addChild(ring3);
+
+ Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
+ Assert.assertEquals(0.0028, result.doubleValue(), 0.0001);
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.gui.print;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class TestPaperSize {
+
+ @Test
+ public void testGetDefaultForCountry() {
+ assertEquals(PaperSize.LETTER, PaperSize.getDefaultForCountry("US"));
+ assertEquals(PaperSize.LETTER, PaperSize.getDefaultForCountry("cA"));
+ assertEquals(PaperSize.LETTER, PaperSize.getDefaultForCountry("mx"));
+
+ assertEquals(PaperSize.A4, PaperSize.getDefaultForCountry("FI"));
+ assertEquals(PaperSize.A4, PaperSize.getDefaultForCountry("xy"));
+
+ assertNull(PaperSize.getDefaultForCountry("FIN"));
+ assertNull(PaperSize.getDefaultForCountry("a"));
+ assertNull(PaperSize.getDefaultForCountry("A4"));
+ assertNull(PaperSize.getDefaultForCountry(null));
+ }
+
+ @Test
+ public void testGetSizeFromString() {
+ assertEquals(PaperSize.LETTER, PaperSize.getSizeFromString("Letter"));
+ assertEquals(PaperSize.LEGAL, PaperSize.getSizeFromString(" legal\t"));
+ assertEquals(PaperSize.A4, PaperSize.getSizeFromString(" A4\n"));
+ assertEquals(PaperSize.A3, PaperSize.getSizeFromString("A3"));
+
+ assertNull(PaperSize.getSizeFromString("#A4"));
+ assertNull(PaperSize.getSizeFromString(""));
+ assertNull(PaperSize.getSizeFromString(null));
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.l10n;
+
+import static org.junit.Assert.*;
+
+import java.util.MissingResourceException;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.auto.Mock;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JMock.class)
+public class TestClassBasedTranslator {
+ Mockery context = new JUnit4Mockery();
+
+ @Mock
+ Translator translator;
+
+ @Test
+ public void testClassName() {
+ ClassBasedTranslator cbt = new ClassBasedTranslator(null, 0);
+ assertEquals("TestClassBasedTranslator", cbt.getClassName());
+
+ cbt = new ClassBasedTranslator(null, "foobar");
+ assertEquals("foobar", cbt.getClassName());
+ }
+
+ @Test
+ public void testGetWithClassName() {
+ ClassBasedTranslator cbt = new ClassBasedTranslator(translator, 0);
+
+ // @formatter:off
+ context.checking(new Expectations() {{
+ oneOf(translator).get("TestClassBasedTranslator.fake.key"); will(returnValue("foobar"));
+ }});
+ // @formatter:on
+
+ assertEquals("foobar", cbt.get("fake.key"));
+ }
+
+
+ @Test
+ public void testGetWithoutClassName() {
+ ClassBasedTranslator cbt = new ClassBasedTranslator(translator, 0);
+
+ // @formatter:off
+ context.checking(new Expectations() {{
+ oneOf(translator).get("TestClassBasedTranslator.fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
+ oneOf(translator).get("fake.key"); will(returnValue("barbaz"));
+ }});
+ // @formatter:on
+
+ assertEquals("barbaz", cbt.get("fake.key"));
+ }
+
+
+ @Test
+ public void testMissing() {
+ ClassBasedTranslator cbt = new ClassBasedTranslator(translator, 0);
+
+ // @formatter:off
+ context.checking(new Expectations() {{
+ oneOf(translator).get("TestClassBasedTranslator.fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
+ oneOf(translator).get("fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
+ }});
+ // @formatter:on
+
+ try {
+ fail("Returned: " + cbt.get("fake.key"));
+ } catch (MissingResourceException e) {
+ assertEquals("Neither key 'TestClassBasedTranslator.fake.key' nor 'fake.key' could be found", e.getMessage());
+ }
+
+ }
+}
--- /dev/null
+package net.sf.openrocket.l10n;
+
+import static org.junit.Assert.*;
+
+import java.util.MissingResourceException;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.auto.Mock;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(JMock.class)
+public class TestExceptionSuppressingTranslator {
+ Mockery context = new JUnit4Mockery();
+
+ @Mock
+ Translator translator;
+
+ @Test
+ public void testSuccessful() {
+ ExceptionSuppressingTranslator est = new ExceptionSuppressingTranslator(translator);
+
+ // @formatter:off
+ context.checking(new Expectations() {{
+ oneOf(translator).get("fake.key"); will(returnValue("foobar"));
+ }});
+ // @formatter:on
+
+ assertEquals("foobar", est.get("fake.key"));
+ }
+
+
+ @Test
+ public void testFailure() {
+ ExceptionSuppressingTranslator est = new ExceptionSuppressingTranslator(translator);
+
+ assertFalse("Prerequisite failed", ExceptionSuppressingTranslator.errorReported);
+
+ // @formatter:off
+ context.checking(new Expectations() {{
+ oneOf(translator).get("fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
+ oneOf(translator).get("fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
+ oneOf(translator).get("fake.key2"); will(throwException(new MissingResourceException("a", "b", "c")));
+ }});
+ // @formatter:on
+
+ // Test first failure
+ assertEquals("fake.key", est.get("fake.key"));
+ assertTrue(ExceptionSuppressingTranslator.errorReported);
+
+ // Test second failure
+ assertEquals("fake.key", est.get("fake.key"));
+ assertTrue(ExceptionSuppressingTranslator.errorReported);
+
+ // Test failure with other key
+ assertEquals("fake.key2", est.get("fake.key2"));
+ assertTrue(ExceptionSuppressingTranslator.errorReported);
+ }
+
+
+}
--- /dev/null
+package net.sf.openrocket.l10n;
+
+import static org.junit.Assert.*;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+
+import org.junit.Test;
+
+public class TestResourceBundleTranslator {
+
+ @Test
+ public void testSuccessfulUS() {
+ ResourceBundleTranslator trans = new ResourceBundleTranslator("l10n.messages", Locale.US);
+ assertEquals("messages.properties", trans.get("debug.currentFile"));
+ }
+
+ @Test
+ public void testSuccessfulFR() {
+ ResourceBundleTranslator trans = new ResourceBundleTranslator("l10n.messages", Locale.FRENCH);
+ assertEquals("messages_fr.properties", trans.get("debug.currentFile"));
+ }
+
+ @Test
+ public void testFailure() {
+ ResourceBundleTranslator trans = new ResourceBundleTranslator("l10n.messages", Locale.US);
+ try {
+ fail("Returned: " + trans.get("missing"));
+ } catch (MissingResourceException e) {
+ // Expected
+ }
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.logging;
+
+import static org.junit.Assert.*;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Random;
+
+import org.junit.Test;
+
+
+public class CyclicBufferTest {
+
+ @Test
+ public void testBasic() {
+ CyclicBuffer<Integer> buffer = new CyclicBuffer<Integer>(5);
+ LinkedList<Integer> correct = new LinkedList<Integer>();
+
+ Random rnd = new Random();
+ for (int i=0; i<50; i++) {
+ int n = rnd.nextInt();
+ buffer.add(n);
+ correct.add(n);
+ if (correct.size() > 5)
+ correct.remove();
+ assertEquals(correct, buffer.asList());
+ }
+ }
+
+ @Test
+ public void testComplex() {
+ CyclicBuffer<Integer> buffer = new CyclicBuffer<Integer>(5);
+
+ testContents(buffer);
+ assertEquals(0, buffer.getOverwriteCount());
+
+ buffer.offer(1);
+ testContents(buffer, 1);
+ assertEquals(0, buffer.getOverwriteCount());
+
+ buffer.add(2);
+ testContents(buffer, 1, 2);
+ assertEquals(0, buffer.getOverwriteCount());
+
+ buffer.add(3);
+ testContents(buffer, 1, 2, 3);
+ assertEquals(0, buffer.getOverwriteCount());
+
+ assertEquals(1, (int)buffer.remove());
+ testContents(buffer, 2, 3);
+ assertEquals(0, buffer.getOverwriteCount());
+
+ assertEquals(2, (int)buffer.peek());
+ testContents(buffer, 2, 3);
+ assertEquals(0, buffer.getOverwriteCount());
+
+ buffer.offer(-2);
+ testContents(buffer, 2, 3, -2);
+ assertEquals(0, buffer.getOverwriteCount());
+
+ buffer.offer(-3);
+ testContents(buffer, 2, 3, -2, -3);
+ assertEquals(0, buffer.getOverwriteCount());
+
+ buffer.offer(-4);
+ testContents(buffer, 2, 3, -2, -3, -4);
+ assertEquals(0, buffer.getOverwriteCount());
+
+ buffer.offer(5);
+ testContents(buffer, 3, -2, -3, -4, 5);
+ assertEquals(1, buffer.getOverwriteCount());
+
+ buffer.offer(6);
+ testContents(buffer, -2, -3, -4, 5, 6);
+ assertEquals(2, buffer.getOverwriteCount());
+
+ assertEquals(-2, (int)buffer.peek());
+ testContents(buffer, -2, -3, -4, 5, 6);
+ assertEquals(2, buffer.getOverwriteCount());
+
+ assertEquals(-2, (int)buffer.remove());
+ testContents(buffer, -3, -4, 5, 6);
+ assertEquals(2, buffer.getOverwriteCount());
+
+ assertEquals(-3, (int)buffer.remove());
+ testContents(buffer, -4, 5, 6);
+ assertEquals(2, buffer.getOverwriteCount());
+
+ assertEquals(-4, (int)buffer.poll());
+ testContents(buffer, 5, 6);
+ assertEquals(2, buffer.getOverwriteCount());
+
+ assertEquals(5, (int)buffer.remove());
+ testContents(buffer, 6);
+ assertEquals(2, buffer.getOverwriteCount());
+
+ assertEquals(6, (int)buffer.poll());
+ testContents(buffer);
+ assertEquals(2, buffer.getOverwriteCount());
+
+ assertNull(buffer.peek());
+ assertNull(buffer.poll());
+ testContents(buffer);
+ assertEquals(2, buffer.getOverwriteCount());
+ }
+
+
+ @Test
+ public void testRandom() {
+ CyclicBuffer<Integer> buffer = new CyclicBuffer<Integer>(4);
+ LinkedList<Integer> correct = new LinkedList<Integer>();
+
+ Random rnd = new Random();
+ for (int i=0; i<500; i++) {
+
+ if (rnd.nextBoolean()) {
+ int n = rnd.nextInt();
+ buffer.add(n);
+ correct.add(n);
+ if (correct.size() > 4)
+ correct.remove();
+ } else {
+ Integer n = buffer.poll();
+ if (correct.size() > 0) {
+ assertEquals(correct.remove(), n);
+ } else {
+ assertNull(n);
+ }
+ }
+
+ assertEquals(correct, buffer.asList());
+ }
+ }
+
+
+ private void testContents(CyclicBuffer<Integer> buffer, int ... values) {
+
+ // Test using iterator
+ Iterator<Integer> iterator = buffer.iterator();
+ for (int v: values) {
+ assertTrue(iterator.hasNext());
+ assertEquals(v, (int)iterator.next());
+ }
+ assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException ignore) { }
+
+ // Test using list
+ List<Integer> list = buffer.asList();
+ assertEquals("List: " + list, values.length, list.size());
+ for (int i=0; i<values.length; i++) {
+ assertEquals(values[i], (int)list.get(i));
+ }
+
+ }
+
+
+}
--- /dev/null
+package net.sf.openrocket.logging;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.junit.Test;
+
+public class LogLevelBufferLoggerTest {
+
+ @Test
+ public void testLogger() {
+ LogLevelBufferLogger logger = new LogLevelBufferLogger(4);
+
+ logger.debug("debug 1");
+ logger.debug("debug 2");
+ logger.user("user 1");
+ logger.info("info 1");
+ logger.info("info 2");
+ logger.warn("warn 1");
+ logger.debug("debug 3");
+ logger.debug("debug 4");
+ logger.user("user 2");
+ logger.info("info 3");
+ logger.error("error 1");
+ logger.debug("debug 5");
+ logger.warn("warn 2");
+ logger.debug("debug 6");
+ logger.user("user 3");
+ logger.info("info 4");
+ logger.debug("debug 7");
+ logger.info("info 5");
+ logger.debug("debug 8");
+ logger.info("info 6");
+
+ List<LogLine> list = logger.getLogs();
+ assertEquals(16, list.size());
+
+ assertEquals("user 1", list.get(0).getMessage());
+ assertEquals("warn 1", list.get(1).getMessage());
+ assertEquals("user 2", list.get(2).getMessage());
+ assertEquals("===== 2 INFO lines removed =====", list.get(3).getMessage());
+ assertEquals("info 3", list.get(4).getMessage());
+ assertEquals("error 1", list.get(5).getMessage());
+ assertEquals("===== 4 DEBUG lines removed =====", list.get(6).getMessage());
+ assertEquals("debug 5", list.get(7).getMessage());
+ assertEquals("warn 2", list.get(8).getMessage());
+ assertEquals("debug 6", list.get(9).getMessage());
+ assertEquals("user 3", list.get(10).getMessage());
+ assertEquals("info 4", list.get(11).getMessage());
+ assertEquals("debug 7", list.get(12).getMessage());
+ assertEquals("info 5", list.get(13).getMessage());
+ assertEquals("debug 8", list.get(14).getMessage());
+ assertEquals("info 6", list.get(15).getMessage());
+
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.logging;
+
+import static net.sf.openrocket.logging.LogLevel.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class LogLevelTest {
+
+ @Test
+ public void testLevels() {
+ assertTrue(DEBUG.atLeast(DEBUG));
+ assertFalse(DEBUG.atLeast(INFO));
+ assertTrue(ERROR.atLeast(WARN));
+
+ assertTrue(ERROR.moreThan(WARN));
+ assertFalse(ERROR.moreThan(ERROR));
+
+ assertEquals(5, LENGTH);
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.logging;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Test;
+
+public class LoggingTest {
+
+ @Test
+ public void testLoggers() {
+ // Ensure a sane stack trace
+ actualTest();
+ }
+
+ private void actualTest() {
+ BufferLogger log3 = new BufferLogger(3);
+ BufferLogger log4 = new BufferLogger(4);
+
+ DelegatorLogger delegator = new DelegatorLogger();
+ delegator.addLogger(log3);
+ delegator.addLogger(log4);
+
+ delegator.debug("one");
+ delegator.debug("two");
+ delegator.info("three");
+ delegator.warn(1, "four");
+ delegator.error("five");
+
+ List<LogLine> logs = log4.getLogs();
+ assertEquals(4, logs.size());
+ assertTrue(logs.get(0).toString(), logs.get(0).toString().matches(
+ " *[0-9]+ +[0-9]+\\.[0-9]+ +DEBUG \\(-\\) two"));
+ assertTrue(logs.get(1).toString(), logs.get(1).toString().matches(
+ " *[0-9]+ +[0-9]+\\.[0-9]+ +INFO \\(LoggingTest.java:[0-9]+\\) three"));
+ assertTrue(logs.get(2).toString(), logs.get(2).toString().matches(
+ " *[0-9]+ +[0-9]+\\.[0-9]+ +WARN \\(LoggingTest.java:[0-9]+ LoggingTest.java:[0-9]+\\) four"));
+ assertTrue(logs.get(3).toString(), logs.get(3).toString().matches(
+ " *[0-9]+ +[0-9]+\\.[0-9]+ +ERROR \\(LoggingTest.java:[0-9]+\\) five"));
+
+ logs = log3.getLogs();
+ assertEquals(3, logs.size());
+ assertTrue(logs.get(0).toString(), logs.get(0).toString().matches(
+ " *[0-9]+ +[0-9]+\\.[0-9]+ +INFO \\(LoggingTest.java:[0-9]+\\) three"));
+ assertTrue(logs.get(1).toString(), logs.get(1).toString().matches(
+ " *[0-9]+ +[0-9]+\\.[0-9]+ +WARN \\(LoggingTest.java:[0-9]+ LoggingTest.java:[0-9]+\\) four"));
+ assertTrue(logs.get(2).toString(), logs.get(2).toString().matches(
+ " *[0-9]+ +[0-9]+\\.[0-9]+ +ERROR \\(LoggingTest.java:[0-9]+\\) five"));
+
+ }
+
+ public static void main(String[] args) {
+ PrintStreamLogger logger = new PrintStreamLogger();
+
+ logger.debug("a debug message");
+ logger.info("an info message");
+ logger.warn("a warning message");
+ logger.error("an error message");
+
+ logger.debug(4, "Debugging");
+ }
+}
--- /dev/null
+package net.sf.openrocket.logging;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class TraceExceptionTest {
+
+ private TraceException getViaAccess() {
+
+ /*
+ * The SubClass test bases on the fact that getViaAccess method is defined on a row number < 20
+ * and the return statement is on a row number > 20.
+ *
+ * The JRE sometimes adds an additional "access$NNN" method call between the calls with the
+ * row number equal to the method definition line.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+ return new TraceException(0, 1);
+ }
+
+
+ @Test
+ public void testBasic() {
+ TraceException trace = new TraceException();
+ assertMatch("\\(TraceExceptionTest.java:[2-9][0-9]\\)", trace);
+ }
+
+
+ @Test
+ public void testOneLevelUp() {
+ // @formatter:off - these need to be on the same line number
+ TraceException trace = getOneLevelUp(); TraceException ref = new TraceException();
+ // @formatter:on
+ assertEquals(ref.getMessage(), trace.getMessage());
+ }
+
+ private TraceException getOneLevelUp() {
+ return new TraceException(1);
+ }
+
+
+ @Test
+ public void testTwoLevels() {
+ TraceException trace = getTwoLevels();
+ assertMatch("\\(TraceExceptionTest.java:[2-9][0-9] TraceExceptionTest.java:[2-9][0-9]\\)", trace);
+ }
+
+ private TraceException getTwoLevels() {
+ return new TraceException(0, 1);
+ }
+
+
+ @Test
+ public void testViaSubclass() {
+ /*
+ * This tests that TraceException.getMessage ignores the synthetic "access$0" method calls.
+ */
+
+ TraceException trace = new SubClass().getTrace();
+ assertMatch("\\(TraceExceptionTest.java:[2-9][0-9] TraceExceptionTest.java:[2-9][0-9]\\)", trace);
+ }
+
+ private class SubClass {
+ private TraceException getTrace() {
+ return getViaAccess();
+ }
+ }
+
+
+
+
+
+ private void assertMatch(String regex, TraceException trace) {
+ boolean match = trace.getMessage().matches(regex);
+ if (!match) {
+ trace.printStackTrace();
+ assertTrue("Was: " + trace.getMessage(), match);
+ }
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.models.gravity;
+
+import static org.junit.Assert.assertEquals;
+import net.sf.openrocket.util.WorldCoordinate;
+
+import org.junit.Test;
+
+
+public class WGSGravityModelTest {
+
+ private WGSGravityModel model = new WGSGravityModel();
+
+ @Test
+ public void testSurfaceGravity() {
+ // Equator
+ test(0, 0, 0, 9.780);
+ // Mid-latitude
+ test(45, 0, 0, 9.806);
+ // Mid-latitude
+ test(45, 99, 0, 9.806);
+ // South pole
+ test(-90, 0, 0, 9.832);
+ }
+
+ @Test
+ public void testAltitudeEffect() {
+ test(45, 0, -100, 9.806);
+ test(45, 0, 0, 9.806);
+ test(45, 0, 10, 9.806);
+ test(45, 0, 100, 9.806);
+ test(45, 0, 1000, 9.803);
+ test(45, 0, 10000, 9.775);
+ test(45, 0, 100000, 9.505);
+ }
+
+ private void test(double lat, double lon, double alt, double g) {
+ WorldCoordinate wc = new WorldCoordinate(lat, lon, alt);
+ assertEquals(g, model.getGravity(wc), 0.001);
+ assertEquals(g, model.getGravity(wc), 0.001);
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.motor;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class ManufacturerTest {
+
+ @Test
+ public void testExisting() {
+
+ Manufacturer m1, m2, m3, m4, m5;
+
+ m1 = Manufacturer.getManufacturer("aerotech");
+ m2 = Manufacturer.getManufacturer("a ");
+ m3 = Manufacturer.getManufacturer("-isp-");
+ m4 = Manufacturer.getManufacturer("at/rcs");
+ m5 = Manufacturer.getManufacturer("e");
+
+ assertTrue(m1 == m2);
+ assertTrue(m1 == m3);
+ assertTrue(m1 == m4);
+ assertFalse(m1 == m5);
+
+ }
+
+ @Test
+ public void testNew() {
+
+ Manufacturer m1, m2, m3;
+
+ m1 = Manufacturer.getManufacturer("Unknown");
+ m2 = Manufacturer.getManufacturer(" Unknown/ ");
+ m3 = Manufacturer.getManufacturer("Unknown/a");
+
+ assertEquals(m1.getDisplayName(), "Unknown");
+ assertEquals(m2.getDisplayName(), "Unknown");
+ assertTrue(m1 == m2);
+
+ assertEquals(m3.getDisplayName(), "Unknown/a");
+ assertFalse(m1 == m3);
+
+ }
+
+ @Test
+ public void testSimpleName() {
+
+ Manufacturer m1, m2, m3, m4;
+
+ m1 = Manufacturer.getManufacturer("cs");
+ m2 = Manufacturer.getManufacturer("Cesaroni Technology");
+ m3 = Manufacturer.getManufacturer("Cesaroni Technology Inc");
+ m4 = Manufacturer.getManufacturer("Cesaroni Technology Inc.");
+
+ assertEquals(m1.getDisplayName(), "Cesaroni Technology Inc.");
+ assertEquals(m1.toString(), "Cesaroni Technology Inc.");
+ assertEquals(m1.getSimpleName(), "Cesaroni Technology");
+
+ assertTrue(m1 == m2);
+ assertTrue(m1 == m3);
+ assertTrue(m1 == m4);
+
+ }
+
+ @Test
+ public void testMatches() {
+
+ Manufacturer m1;
+
+ m1 = Manufacturer.getManufacturer("aerotech");
+
+ assertTrue(m1.matches("a"));
+ assertTrue(m1.matches("a/"));
+ assertTrue(m1.matches("a/rcs"));
+ assertTrue(m1.matches("a/rms"));
+ assertTrue(m1.matches("aerotech ...-/%#_!"));
+ assertTrue(m1.matches(" .isp/"));
+
+ assertFalse(m1.matches("aero/tech"));
+ assertFalse(m1.matches("aero.tech"));
+ assertFalse(m1.matches("aero_tech"));
+ assertFalse(m1.matches("aero tech"));
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.motor;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import net.sf.openrocket.motor.MotorDigest.DataType;
+import net.sf.openrocket.util.TextUtil;
+
+import org.junit.Test;
+
+
+public class MotorDigestTest {
+
+ private static final double[] timeArray = {
+ 0.0, 0.123456789, 0.4115, Math.nextAfter(Math.nextAfter(1.4445, 0), 0)
+ };
+
+ private static final double[] massArray = {
+ 0.54321, 0.43211
+ };
+
+ private static final double[] thrustArray = {
+ 0.0, 0.2345678, 9999.3335, 0.0
+ };
+
+ private static final int[] intData = {
+ // Time (ms)
+ 0, 4, 0, 123, 412, 1445,
+ // Mass specific (0.1g)
+ 1, 2, 5432, 4321,
+ // Thrust (mN)
+ 5, 4, 0, 235, 9999334, 0
+ };
+
+
+ @Test
+ public void testMotorDigest() throws NoSuchAlgorithmException {
+
+ MessageDigest correct = MessageDigest.getInstance("MD5");
+ for (int value: intData) {
+ correct.update((byte) ((value >>> 24) & 0xFF));
+ correct.update((byte) ((value >>> 16) & 0xFF));
+ correct.update((byte) ((value >>> 8) & 0xFF));
+ correct.update((byte) (value & 0xFF));
+ }
+
+ MotorDigest motor = new MotorDigest();
+ motor.update(DataType.TIME_ARRAY, timeArray);
+ motor.update(DataType.MASS_SPECIFIC, massArray);
+ motor.update(DataType.FORCE_PER_TIME, thrustArray);
+
+
+ assertEquals(TextUtil.hexString(correct.digest()), motor.getDigest());
+ }
+
+
+ @Test
+ public void testCommentDigest() throws NoSuchAlgorithmException, UnsupportedEncodingException {
+
+ assertEquals(md5("Hello world!"), MotorDigest.digestComment("Hello world! "));
+ assertEquals(md5("Hello world!"), MotorDigest.digestComment("\nHello\tworld!\n\r"));
+ assertEquals(md5("Hello world!"), MotorDigest.digestComment("Hello\r\r\r\nworld!"));
+ assertEquals(md5("Hello\u00e4 world!"), MotorDigest.digestComment("Hello\u00e4\r\r\nworld!"));
+
+ }
+
+
+ private static String md5(String source)
+ throws NoSuchAlgorithmException, UnsupportedEncodingException {
+ MessageDigest digest = MessageDigest.getInstance("MD5");
+ return TextUtil.hexString(digest.digest(source.getBytes("UTF-8")));
+ }
+}
--- /dev/null
+package net.sf.openrocket.motor;
+
+import static org.junit.Assert.assertEquals;
+import net.sf.openrocket.util.Coordinate;
+import net.sf.openrocket.util.Inertia;
+
+import org.junit.Test;
+
+public class ThrustCurveMotorTest {
+
+ private final double EPS = 0.000001;
+
+ private final double radius = 0.025;
+ private final double length = 0.10;
+ private final double longitudinal = Inertia.filledCylinderLongitudinal(radius, length);
+ private final double rotational = Inertia.filledCylinderRotational(radius);
+
+ private final ThrustCurveMotor motor =
+ new ThrustCurveMotor(Manufacturer.getManufacturer("foo"),
+ "X6", "Description of X6", Motor.Type.RELOAD,
+ new double[] {0, 2, Motor.PLUGGED}, radius*2, length,
+ new double[] {0, 1, 3, 4}, // time
+ new double[] {0, 2, 3, 0}, // thrust
+ new Coordinate[] {
+ new Coordinate(0.02,0,0,0.05),
+ new Coordinate(0.02,0,0,0.05),
+ new Coordinate(0.02,0,0,0.05),
+ new Coordinate(0.03,0,0,0.03)
+ });
+
+ @Test
+ public void testMotorData() {
+
+ assertEquals("X6", motor.getDesignation());
+ assertEquals("X6-5", motor.getDesignation(5.0));
+ assertEquals("Description of X6", motor.getDescription());
+ assertEquals(Motor.Type.RELOAD, motor.getMotorType());
+
+ }
+
+ @Test
+ public void testInstance() {
+ MotorInstance instance = motor.getInstance();
+
+ verify(instance, 0, 0.05, 0.02);
+ instance.step(0.0, 0, null);
+ verify(instance, 0, 0.05, 0.02);
+ instance.step(0.5, 0, null);
+ verify(instance, 0.5, 0.05, 0.02);
+ instance.step(1.5, 0, null);
+ verify(instance, (1.5 + 2.125)/2, 0.05, 0.02);
+ instance.step(2.5, 0, null);
+ verify(instance, (2.125 + 2.875)/2, 0.05, 0.02);
+ instance.step(3.0, 0, null);
+ verify(instance, (2+3.0/4 + 3)/2, 0.05, 0.02);
+ instance.step(3.5, 0, null);
+ verify(instance, (1.5 + 3)/2, 0.045, 0.0225);
+ instance.step(4.5, 0, null);
+ // mass and cg is simply average of the end points
+ verify(instance, 1.5/4, 0.035, 0.0275);
+ instance.step(5.0, 0, null);
+ verify(instance, 0, 0.03, 0.03);
+ }
+
+ private void verify(MotorInstance instance, double thrust, double mass, double cgx) {
+ assertEquals("Testing thrust", thrust, instance.getThrust(), EPS);
+ assertEquals("Testing mass", mass, instance.getCG().weight, EPS);
+ assertEquals("Testing cg x", cgx, instance.getCG().x, EPS);
+ assertEquals("Testing longitudinal inertia", mass*longitudinal, instance.getLongitudinalInertia(), EPS);
+ assertEquals("Testing rotational inertia", mass*rotational, instance.getRotationalInertia(), EPS);
+ }
+
+
+}
--- /dev/null
+package net.sf.openrocket.optimization;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import net.sf.openrocket.optimization.general.Point;
+import net.sf.openrocket.optimization.general.multidim.SearchPattern;
+
+import org.junit.Test;
+
+public class TestSearchPattern {
+
+ @Test
+ public void testRegularSimplex() {
+ for (int dim = 1; dim < 20; dim++) {
+ List<Point> points = SearchPattern.regularSimplex(dim);
+ assertEquals(dim, points.size());
+
+ for (int i = 0; i < dim; i++) {
+ // Test dot product
+ for (int j = i + 1; j < dim; j++) {
+ double[] x = points.get(i).asArray();
+ double[] y = points.get(j).asArray();
+ double dot = 0;
+ for (int k = 0; k < dim; k++) {
+ dot += x[k] * y[k];
+ }
+ assertEquals(0.5, dot, 0.000000001);
+ }
+
+ // Test positive coordinates
+ for (int j = 0; j < dim; j++) {
+ assertTrue(points.get(i).get(j) >= 0);
+ }
+
+ // Test length
+ assertEquals(1.0, points.get(i).length(), 0.000000001);
+ }
+ }
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.optimization.rocketoptimization;
+
+import static org.junit.Assert.*;
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.optimization.general.OptimizationException;
+import net.sf.openrocket.optimization.general.Point;
+import net.sf.openrocket.rocketcomponent.Rocket;
+import net.sf.openrocket.unit.Unit;
+import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.unit.Value;
+import net.sf.openrocket.util.Pair;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.auto.Mock;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JMock.class)
+public class TestRocketOptimizationFunction {
+ Mockery context = new JUnit4Mockery();
+
+ @Mock
+ OptimizableParameter parameter;
+ @Mock
+ OptimizationGoal goal;
+ @Mock
+ SimulationDomain domain;
+ @Mock
+ SimulationModifier modifier1;
+ @Mock
+ SimulationModifier modifier2;
+ @Mock
+ RocketOptimizationListener listener;
+
+ @Test
+ public void testNormalEvaluation() throws InterruptedException, OptimizationException {
+ final Rocket rocket = new Rocket();
+ final Simulation simulation = new Simulation(rocket);
+
+ final double p1 = 0.4;
+ final double p2 = 0.7;
+ final double ddist = -0.43;
+ final Value dref = new Value(ddist, Unit.NOUNIT2);
+ final double pvalue = 9.81;
+ final Value pvalueValue = new Value(9.81, Unit.NOUNIT2);
+ final double gvalue = 8.81;
+ final Point point = new Point(p1, p2);
+
+ // @formatter:off
+ context.checking(new Expectations() {{
+ oneOf(modifier1).modify(simulation, p1);
+ oneOf(modifier2).modify(simulation, p2);
+ oneOf(domain).getDistanceToDomain(simulation); will(returnValue(new Pair<Double,Value>(ddist, dref)));
+ oneOf(parameter).computeValue(simulation); will(returnValue(pvalue));
+ oneOf(parameter).getUnitGroup(); will(returnValue(UnitGroup.UNITS_NONE));
+ oneOf(goal).getMinimizationParameter(pvalue); will(returnValue(gvalue));
+ oneOf(modifier1).getCurrentSIValue(simulation); will(returnValue(0.2));
+ oneOf(modifier1).getUnitGroup(); will(returnValue(UnitGroup.UNITS_LENGTH));
+ oneOf(modifier2).getCurrentSIValue(simulation); will(returnValue(0.3));
+ oneOf(modifier2).getUnitGroup(); will(returnValue(UnitGroup.UNITS_LENGTH));
+ oneOf(listener).evaluated(point, new Value[] {
+ new Value(0.2, UnitGroup.UNITS_LENGTH.getDefaultUnit()),
+ new Value(0.3, UnitGroup.UNITS_LENGTH.getDefaultUnit())
+ }, dref, pvalueValue, gvalue);
+ }});
+ // @formatter:on
+
+ RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
+ parameter, goal, domain, modifier1, modifier2) {
+ @Override
+ Simulation newSimulationInstance(Simulation sim) {
+ return sim;
+ }
+ };
+ function.addRocketOptimizationListener(listener);
+
+ double value = function.evaluate(point);
+ assertEquals(gvalue, value, 0);
+ }
+
+ @Test
+ public void testNaNValue() throws InterruptedException, OptimizationException {
+ final Rocket rocket = new Rocket();
+ final Simulation simulation = new Simulation(rocket);
+
+ final double p1 = 0.4;
+ final double p2 = 0.7;
+ final double ddist = -0.43;
+ final Value dref = new Value(0.33, Unit.NOUNIT2);
+ final double pvalue = 9.81;
+
+ // @formatter:off
+ context.checking(new Expectations() {{
+ oneOf(modifier1).modify(simulation, p1);
+ oneOf(modifier2).modify(simulation, p2);
+ oneOf(domain).getDistanceToDomain(simulation); will(returnValue(new Pair<Double,Value>(ddist, dref)));
+ oneOf(parameter).computeValue(simulation); will(returnValue(pvalue));
+ oneOf(parameter).getUnitGroup(); will(returnValue(UnitGroup.UNITS_NONE));
+ oneOf(goal).getMinimizationParameter(pvalue); will(returnValue(Double.NaN));
+ }});
+ // @formatter:on
+
+
+ RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
+ parameter, goal, domain, modifier1, modifier2) {
+ @Override
+ Simulation newSimulationInstance(Simulation sim) {
+ return sim;
+ }
+ };
+
+
+ double value = function.evaluate(new Point(p1, p2));
+ assertEquals(Double.MAX_VALUE, value, 0);
+ }
+
+
+ @Test
+ public void testOutsideDomain() throws InterruptedException, OptimizationException {
+ final Rocket rocket = new Rocket();
+ final Simulation simulation = new Simulation(rocket);
+
+ final double p1 = 0.4;
+ final double p2 = 0.7;
+ final double ddist = 0.98;
+ final Value dref = new Value(ddist, Unit.NOUNIT2);
+ final Point point = new Point(p1, p2);
+
+ // @formatter:off
+ context.checking(new Expectations() {{
+ oneOf(modifier1).modify(simulation, p1);
+ oneOf(modifier2).modify(simulation, p2);
+ oneOf(domain).getDistanceToDomain(simulation); will(returnValue(new Pair<Double,Value>(ddist, dref)));
+ oneOf(modifier1).getCurrentSIValue(simulation); will(returnValue(0.2));
+ oneOf(modifier1).getUnitGroup(); will(returnValue(UnitGroup.UNITS_LENGTH));
+ oneOf(modifier2).getCurrentSIValue(simulation); will(returnValue(0.3));
+ oneOf(modifier2).getUnitGroup(); will(returnValue(UnitGroup.UNITS_LENGTH));
+ oneOf(listener).evaluated(point, new Value[] {
+ new Value(0.2, UnitGroup.UNITS_LENGTH.getDefaultUnit()),
+ new Value(0.3, UnitGroup.UNITS_LENGTH.getDefaultUnit())
+ }, dref, null, 1.98E200);
+ }});
+ // @formatter:on
+
+
+ RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
+ parameter, goal, domain, modifier1, modifier2) {
+ @Override
+ Simulation newSimulationInstance(Simulation sim) {
+ return sim;
+ }
+ };
+ function.addRocketOptimizationListener(listener);
+
+ double value = function.evaluate(new Point(p1, p2));
+ assertTrue(value > 1e100);
+ }
+
+ @Test
+ public void testOutsideDomain2() throws InterruptedException, OptimizationException {
+ final Rocket rocket = new Rocket();
+ final Simulation simulation = new Simulation(rocket);
+
+ final double p1 = 0.4;
+ final double p2 = 0.7;
+ final double ddist = Double.NaN;
+ final Value dref = new Value(0.33, Unit.NOUNIT2);
+
+ // @formatter:off
+ context.checking(new Expectations() {{
+ oneOf(modifier1).modify(simulation, p1);
+ oneOf(modifier2).modify(simulation, p2);
+ oneOf(domain).getDistanceToDomain(simulation); will(returnValue(new Pair<Double,Value>(ddist, dref)));
+ }});
+ // @formatter:on
+
+
+ RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
+ parameter, goal, domain, modifier1, modifier2) {
+ @Override
+ Simulation newSimulationInstance(Simulation sim) {
+ return sim;
+ }
+ };
+
+ double value = function.evaluate(new Point(p1, p2));
+ assertEquals(Double.MAX_VALUE, value, 0);
+ }
+
+
+ @Test
+ public void testNewSimulationInstance() {
+ final Rocket rocket = new Rocket();
+ rocket.setName("Foobar");
+ final Simulation simulation = new Simulation(rocket);
+ simulation.setName("MySim");
+
+ RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
+ parameter, goal, domain, modifier1, modifier2);
+
+ Simulation sim = function.newSimulationInstance(simulation);
+ assertFalse(simulation == sim);
+ assertEquals("MySim", sim.getName());
+ assertFalse(rocket == sim.getRocket());
+ assertEquals("Foobar", sim.getRocket().getName());
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.optimization.rocketoptimization.modifiers;
+
+import static net.sf.openrocket.util.MathUtil.EPSILON;
+import static org.junit.Assert.assertEquals;
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.optimization.general.OptimizationException;
+import net.sf.openrocket.rocketcomponent.Rocket;
+import net.sf.openrocket.unit.UnitGroup;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestGenericModifier {
+
+ private TestValue value;
+ private GenericModifier<TestValue> gm;
+ private Simulation sim;
+
+ @Before
+ public void setup() {
+ value = new TestValue();
+ sim = new Simulation(new Rocket());
+
+ Object related = new Object();
+
+ gm = new GenericModifier<TestGenericModifier.TestValue>("Test modifier", "Description", related,
+ UnitGroup.UNITS_NONE, 2.0, TestValue.class, "value") {
+ @Override
+ protected TestValue getModifiedObject(Simulation simulation) {
+ Assert.assertTrue(simulation == sim);
+ return value;
+ }
+ };
+
+ gm.setMinValue(0.5);
+ gm.setMaxValue(5.5);
+ }
+
+ @Test
+ public void testGetCurrentValue() throws OptimizationException {
+ value.d = 1.0;
+ assertEquals(2.0, gm.getCurrentSIValue(sim), EPSILON);
+ value.d = 2.0;
+ assertEquals(4.0, gm.getCurrentSIValue(sim), EPSILON);
+ }
+
+ @Test
+ public void testGetCurrentScaledValue() throws OptimizationException {
+ value.d = 0.0;
+ assertEquals(-0.1, gm.getCurrentScaledValue(sim), EPSILON);
+ value.d = 1.0;
+ assertEquals(0.3, gm.getCurrentScaledValue(sim), EPSILON);
+ value.d = 2.0;
+ assertEquals(0.7, gm.getCurrentScaledValue(sim), EPSILON);
+ value.d = 3.0;
+ assertEquals(1.1, gm.getCurrentScaledValue(sim), EPSILON);
+ }
+
+ @Test
+ public void testModify() throws OptimizationException {
+ value.d = 0.0;
+ gm.modify(sim, -0.5);
+ assertEquals(-1.0, value.d, EPSILON);
+
+ gm.modify(sim, 0.0);
+ assertEquals(0.25, value.d, EPSILON);
+
+ gm.modify(sim, 0.5);
+ assertEquals(1.5, value.d, EPSILON);
+
+ gm.modify(sim, 1.0);
+ assertEquals(2.75, value.d, EPSILON);
+
+ gm.modify(sim, 1.5);
+ assertEquals(4.0, value.d, EPSILON);
+ }
+
+ public void testSingularRange() throws OptimizationException {
+ gm.setMinValue(1.0);
+ gm.setMaxValue(1.0);
+ value.d = 0.5;
+ assertEquals(0.0, gm.getCurrentScaledValue(sim), EPSILON);
+ value.d = 1.0;
+ assertEquals(0.5, gm.getCurrentScaledValue(sim), EPSILON);
+ value.d = 1.00001;
+ assertEquals(1.0, gm.getCurrentScaledValue(sim), EPSILON);
+ }
+
+ public class TestValue {
+ private double d;
+
+ public double getValue() {
+ return d;
+ }
+
+ public void setValue(double value) {
+ this.d = value;
+ }
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.rocketcomponent;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.regex.Pattern;
+
+import net.sf.openrocket.util.BugException;
+
+public class ComponentCompare {
+
+ private static final Pattern GETTER_PATTERN = Pattern.compile("^(is|get)[A-Z].*+");
+
+ private static final String[] IGNORED_METHODS = {
+ "getClass", "getChildCount", "getChildren", "getNextComponent", "getID",
+ "getPreviousComponent", "getParent", "getRocket", "getRoot", "getStage",
+ "getStageNumber", "getComponentName",
+ // Rocket specific methods:
+ "getModID", "getMassModID", "getAerodynamicModID", "getTreeModID", "getFunctionalModID",
+ "getMotorConfigurationIDs", "getDefaultConfiguration"
+ };
+
+
+ /**
+ * Check whether the two components are <em>equal</em>. Two components are considered
+ * equal if they are of the same type and all of their getXXX() and isXXX() methods
+ * return equal values.
+ *
+ * @param c1 the first component to compare.
+ * @param c2 the second component to compare.
+ */
+ public static void assertEquality(RocketComponent c1, RocketComponent c2) {
+ assertEquals(c1.getClass(), c2.getClass());
+
+ // Same class + similar == equal
+ assertSimilarity(c1, c2);
+ }
+
+
+
+ public static void assertDeepEquality(RocketComponent c1, RocketComponent c2) {
+ assertEquality(c1, c2);
+
+ Iterator<RocketComponent> i1 = c1.getChildren().iterator();
+ Iterator<RocketComponent> i2 = c2.getChildren().iterator();
+ while (i1.hasNext()) {
+ assertTrue("iterator continues", i2.hasNext());
+ RocketComponent comp1 = i1.next();
+ RocketComponent comp2 = i2.next();
+ assertDeepEquality(comp1, comp2);
+ }
+ assertFalse("iterator end", i2.hasNext());
+ }
+
+
+
+ public static void assertDeepSimilarity(RocketComponent c1, RocketComponent c2,
+ boolean allowNameDifference) {
+ assertSimilarity(c1, c2, allowNameDifference);
+
+ Iterator<RocketComponent> i1 = c1.getChildren().iterator();
+ Iterator<RocketComponent> i2 = c2.getChildren().iterator();
+ while (i1.hasNext()) {
+ assertTrue("iterator continues", i2.hasNext());
+ RocketComponent comp1 = i1.next();
+ RocketComponent comp2 = i2.next();
+ assertDeepSimilarity(comp1, comp2, allowNameDifference);
+ }
+ assertFalse("iterator end", i2.hasNext());
+ }
+
+
+
+ /**
+ * Check whether the two components are <em>similar</em>. Two components are similar
+ * if each of the getXXX and isXXX methods that both object types have return
+ * equal values. This does not check whether the two components are of the same type.
+ *
+ * @param c1 the first component.
+ * @param c2 the second component.
+ */
+ public static void assertSimilarity(RocketComponent c1, RocketComponent c2) {
+ assertSimilarity(c1, c2, false);
+ }
+
+ /**
+ * Check whether the two components are <em>similar</em>, allowing a name difference.
+ *
+ * @param c1 the first component.
+ * @param c2 the second component.
+ * @param allowNameDifference whether to allow the components to have different names.
+ */
+ public static void assertSimilarity(RocketComponent c1, RocketComponent c2,
+ boolean allowNameDifference) {
+ Class<? extends RocketComponent> class1 = c1.getClass();
+ Class<? extends RocketComponent> class2 = c2.getClass();
+
+ mainloop: for (Method m1 : class1.getMethods()) {
+ // Check for getter method
+ String name = m1.getName();
+ if (!GETTER_PATTERN.matcher(name).matches())
+ continue;
+
+ // Ignore methods that take parameters
+ if (m1.getParameterTypes().length != 0)
+ continue;
+
+ // Ignore specific getters
+ for (String ignore : IGNORED_METHODS) {
+ if (name.equals(ignore))
+ continue mainloop;
+ }
+ if (allowNameDifference && name.equals("getName"))
+ continue;
+
+
+ // Check for method in other class
+ Method m2;
+ try {
+ m2 = class2.getMethod(name);
+ } catch (NoSuchMethodException e) {
+ continue;
+ }
+
+ // System.out.println("Testing results of method " + name);
+
+ // Run the methods
+ Object result1, result2;
+ try {
+ result1 = m1.invoke(c1);
+ result2 = m2.invoke(c2);
+ } catch (Exception e) {
+ throw new BugException("Error executing method " + name, e);
+ }
+
+ if (result1 != null && result2 != null &&
+ result1.getClass().isArray() && result2.getClass().isArray()) {
+ assertArrayEquals("Comparing result of method " + name,
+ (Object[]) result1, (Object[]) result2);
+ } else {
+ assertEquals("Comparing result of method " + name, result1, result2);
+ }
+ }
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.rocketcomponent;
+
+import static org.junit.Assert.*;
+
+import java.awt.Color;
+import java.util.Iterator;
+
+import net.sf.openrocket.gui.util.ColorConversion;
+import net.sf.openrocket.util.Coordinate;
+
+import org.junit.Test;
+
+public class ComponentCompareTest {
+
+ @Test
+ public void testComponentEquality() {
+
+ System.out.println("TEST CLASSPATH: " + System.getProperty("java.class.path"));
+
+ Rocket r1 = net.sf.openrocket.util.TestRockets.makeBigBlue();
+ Rocket r2 = net.sf.openrocket.util.TestRockets.makeBigBlue();
+
+ Iterator<RocketComponent> i1 = r1.iterator(true);
+ Iterator<RocketComponent> i2 = r2.iterator(true);
+ while (i1.hasNext()) {
+ assertTrue(i2.hasNext());
+
+ RocketComponent c1 = i1.next();
+ RocketComponent c2 = i2.next();
+
+ ComponentCompare.assertEquality(c1, c2);
+ ComponentCompare.assertSimilarity(c1, c2);
+ }
+ assertFalse(i2.hasNext());
+
+
+ ComponentCompare.assertDeepEquality(r1, r2);
+ ComponentCompare.assertDeepSimilarity(r1, r2, false);
+
+
+ r1.setColor(ColorConversion.fromAwtColor(Color.YELLOW));
+ try {
+ ComponentCompare.assertEquality(r1, r2);
+ fail();
+ } catch (AssertionError e) {
+ // Correct behavior
+ }
+
+
+ i1 = r1.iterator(true);
+ i2 = r2.iterator(true);
+ boolean finsetfound = false;
+ while (i1.hasNext()) {
+ RocketComponent c1 = i1.next();
+ RocketComponent c2 = i2.next();
+
+ if (c1 instanceof FinSet) {
+ finsetfound = true;
+ FinSet f1 = (FinSet)c1;
+ f1.setTabHeight(0.001);
+
+ try {
+ ComponentCompare.assertEquality(c1, c2);
+ fail();
+ } catch (AssertionError e) {
+ // Correct behavior
+ }
+ }
+ }
+ assertTrue(finsetfound);
+ }
+
+
+ @Test
+ public void testComponentSimilarity() throws IllegalFinPointException {
+ FinSet trap = new TrapezoidFinSet(
+ 5, // fins
+ 5.0, // root
+ 3.0, // tip
+ 0.0, // sweep
+ 2.0); // height
+ FinSet free = new FreeformFinSet(new Coordinate[] {
+ new Coordinate(0,0),
+ new Coordinate(0,2),
+ new Coordinate(3,2),
+ new Coordinate(5,0)
+ });
+ free.setFinCount(5);
+
+ ComponentCompare.assertSimilarity(trap, free, true);
+
+ try {
+ ComponentCompare.assertSimilarity(trap, free);
+ fail();
+ } catch (AssertionError e) {
+ // Correct behavior
+ }
+
+ free.setName(trap.getName());
+ ComponentCompare.assertSimilarity(trap, free);
+
+ try {
+ ComponentCompare.assertEquality(trap, free);
+ fail();
+ } catch (AssertionError e) {
+ // Correct behavior
+ }
+
+
+ BodyTube t1 = new BodyTube();
+ BodyTube t2 = new BodyTube();
+ t1.addChild(free);
+ t2.addChild(trap);
+
+ ComponentCompare.assertDeepSimilarity(t1, t2, false);
+
+ try {
+ ComponentCompare.assertDeepEquality(t1, t2);
+ fail();
+ } catch (AssertionError e) {
+ // Correct behavior
+ }
+
+ t1.addChild(new TrapezoidFinSet());
+
+ try {
+ ComponentCompare.assertDeepSimilarity(t1, t2, true);
+ fail();
+ } catch (AssertionError e) {
+ // Correct behavior
+ }
+
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.rocketcomponent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.Color;
+
+import net.sf.openrocket.gui.util.ColorConversion;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.material.Material.Type;
+import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
+import net.sf.openrocket.rocketcomponent.FinSet.CrossSection;
+import net.sf.openrocket.rocketcomponent.FinSet.TabRelativePosition;
+import net.sf.openrocket.rocketcomponent.RocketComponent.Position;
+import net.sf.openrocket.util.LineStyle;
+import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
+
+import org.junit.Test;
+
+public class FinSetTest extends BaseTestCase {
+
+
+ @Test
+ public void testFreeformConvert() {
+ testFreeformConvert(new TrapezoidFinSet());
+ testFreeformConvert(new EllipticalFinSet());
+ testFreeformConvert(new FreeformFinSet());
+ }
+
+
+ private void testFreeformConvert(FinSet fin) {
+ FreeformFinSet converted;
+ Material mat = Material.newMaterial(Type.BULK, "foo", 0.1, true);
+
+ fin.setBaseRotation(1.1);
+ fin.setCantAngle(0.001);
+ fin.setCGOverridden(true);
+ fin.setColor(ColorConversion.fromAwtColor(Color.YELLOW));
+ fin.setComment("cmt");
+ fin.setCrossSection(CrossSection.ROUNDED);
+ fin.setFinCount(5);
+ fin.setFinish(Finish.ROUGH);
+ fin.setLineStyle(LineStyle.DASHDOT);
+ fin.setMassOverridden(true);
+ fin.setMaterial(mat);
+ fin.setOverrideCGX(0.012);
+ fin.setOverrideMass(0.0123);
+ fin.setOverrideSubcomponents(true);
+ fin.setPositionValue(0.1);
+ fin.setRelativePosition(Position.ABSOLUTE);
+ fin.setTabHeight(0.01);
+ fin.setTabLength(0.02);
+ fin.setTabRelativePosition(TabRelativePosition.END);
+ fin.setTabShift(0.015);
+ fin.setThickness(0.005);
+
+
+ converted = FreeformFinSet.convertFinSet((FinSet) fin.copy());
+
+ ComponentCompare.assertSimilarity(fin, converted, true);
+
+ assertEquals(converted.getComponentName(), converted.getName());
+
+
+ // Create test rocket
+ Rocket rocket = new Rocket();
+ Stage stage = new Stage();
+ BodyTube body = new BodyTube();
+
+ rocket.addChild(stage);
+ stage.addChild(body);
+ body.addChild(fin);
+
+ Listener l1 = new Listener("l1");
+ rocket.addComponentChangeListener(l1);
+
+ fin.setName("Custom name");
+ assertTrue(l1.changed);
+ assertEquals(ComponentChangeEvent.NONFUNCTIONAL_CHANGE, l1.changetype);
+
+
+ // Create copy
+ RocketComponent rocketcopy = rocket.copy();
+
+ Listener l2 = new Listener("l2");
+ rocketcopy.addComponentChangeListener(l2);
+
+ FinSet fincopy = (FinSet) rocketcopy.getChild(0).getChild(0).getChild(0);
+ FreeformFinSet.convertFinSet(fincopy);
+
+ assertTrue(l2.changed);
+ assertEquals(ComponentChangeEvent.TREE_CHANGE,
+ l2.changetype & ComponentChangeEvent.TREE_CHANGE);
+
+ }
+
+
+ private static class Listener implements ComponentChangeListener {
+ private boolean changed = false;
+ private int changetype = 0;
+ private final String name;
+
+ public Listener(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void componentChanged(ComponentChangeEvent e) {
+ assertFalse("Ensuring listener " + name + " has not been called.", changed);
+ changed = true;
+ changetype = e.getType();
+ }
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.rocketcomponent;
+
+import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
+
+import org.junit.Test;
+
+public class RocketTest extends BaseTestCase {
+
+ @Test
+ public void testCopyFrom() {
+ Rocket r1 = net.sf.openrocket.util.TestRockets.makeIsoHaisu();
+ Rocket r2 = net.sf.openrocket.util.TestRockets.makeBigBlue();
+
+ Rocket copy = (Rocket) r2.copy();
+
+ ComponentCompare.assertDeepEquality(r2, copy);
+
+ r1.copyFrom(copy);
+
+ ComponentCompare.assertDeepEquality(r1, r2);
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.unit;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class ValueTest {
+
+ @Test
+ public void testValues() {
+ Value v1, v2;
+
+ v1 = new Value(273.15, UnitGroup.UNITS_TEMPERATURE.findApproximate("F"));
+ v2 = new Value(283.15, UnitGroup.UNITS_TEMPERATURE.findApproximate("C"));
+
+ assertTrue(v1.compareTo(v2) > 0);
+ assertTrue(v2.compareTo(v1) < 0);
+ assertTrue(v1.compareTo(v1) == 0);
+ assertTrue(v2.compareTo(v2) == 0);
+
+ v2 = new Value(283.15, UnitGroup.UNITS_TEMPERATURE.findApproximate("K"));
+ assertTrue(v1.compareTo(v2) > 0);
+ assertTrue(v2.compareTo(v1) < 0);
+ assertEquals("283 K", v2.toString());
+
+ v2 = new Value(283.15, UnitGroup.UNITS_TEMPERATURE.findApproximate("F"));
+ assertTrue(v1.compareTo(v2) < 0);
+ assertTrue(v2.compareTo(v1) > 0);
+
+
+ v1 = new Value(Double.NaN, UnitGroup.UNITS_TEMPERATURE.findApproximate("F"));
+ assertTrue(v1.compareTo(v2) > 0);
+ assertTrue(v2.compareTo(v1) < 0);
+
+ v2 = new Value(Double.NaN, UnitGroup.UNITS_TEMPERATURE.findApproximate("F"));
+ assertTrue(v1.compareTo(v2) == 0);
+ assertTrue(v1.compareTo(v2) == 0);
+ assertEquals("N/A", v1.toString());
+ assertEquals("N/A", v2.toString());
+
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util.BaseTestCase;\r
+\r
+import net.sf.openrocket.gui.util.SwingPreferences;\r
+import net.sf.openrocket.startup.Application;\r
+\r
+import org.junit.BeforeClass;\r
+\r
+public class BaseTestCase {\r
+\r
+ @BeforeClass\r
+ public static void setUpApplication () {\r
+ \r
+ Application.setPreferences( new SwingPreferences() );\r
+ \r
+ }\r
+}\r
--- /dev/null
+package net.sf.openrocket.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class CoordinateTest {
+
+ private static final double EPS = 0.0000000001;
+
+ @Test
+ public void coordinateTest() {
+
+ Coordinate x = new Coordinate(1,1,1,1);
+ Coordinate y = new Coordinate(1,2,3,4);
+
+ assertCoordinateEquals(new Coordinate(2,1,1,1), x.setX(2));
+ assertCoordinateEquals(new Coordinate(1,2,1,1), x.setY(2));
+ assertCoordinateEquals(new Coordinate(1,1,2,1), x.setZ(2));
+ assertCoordinateEquals(new Coordinate(1,1,1,2), x.setWeight(2));
+ assertCoordinateEquals(new Coordinate(2,3,4,1), x.setXYZ(y).add(1,1,1));
+
+ assertFalse(x.isNaN());
+ assertTrue(x.setX(Double.NaN).isNaN());
+ assertTrue(Coordinate.NaN.isNaN());
+
+ assertTrue(x.isWeighted());
+ assertFalse(x.setWeight(0).isWeighted());
+
+
+ assertCoordinateEquals(x, x.add(Coordinate.NUL));
+ assertCoordinateEquals(new Coordinate(2,3,4,5), x.add(y));
+ assertCoordinateEquals(new Coordinate(2,3,4,1), x.add(1,2,3));
+ assertCoordinateEquals(new Coordinate(2,3,4,5), x.add(1,2,3,4));
+
+ assertCoordinateEquals(new Coordinate(0,-1,-2,1), x.sub(y));
+ assertCoordinateEquals(new Coordinate(0,-1,-2,1), x.sub(1,2,3));
+
+ assertCoordinateEquals(new Coordinate(2,4,6,8), y.multiply(2));
+
+ assertEquals(1+2+3, y.dot(x), EPS);
+ assertEquals(1+2+3, x.dot(y), EPS);
+ assertEquals(1+2+3, Coordinate.dot(x,y), EPS);
+ assertEquals(x.dot(x), x.length2(), EPS);
+ assertEquals(y.dot(y), y.length2(), EPS);
+ assertEquals(Math.sqrt(1+4+9), y.length(), EPS);
+ assertEquals(1, y.normalize().length(), EPS);
+
+ assertCoordinateEquals(new Coordinate(1.75,1.75,1.75,4),
+ new Coordinate(1,1,1,1).average(new Coordinate(2,2,2,3)));
+ assertCoordinateEquals(new Coordinate(1,1,1,1),
+ new Coordinate(1,1,1,1).average(new Coordinate(2,2,2,0)));
+ assertCoordinateEquals(new Coordinate(1.5,1.5,1.5,0),
+ new Coordinate(1,1,1,0).average(new Coordinate(2,2,2,0)));
+
+ }
+
+
+ private void assertCoordinateEquals(Coordinate a, Coordinate b) {
+ assertEquals(a, b);
+ assertEquals(a.weight, b.weight, EPS);
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class GeodeticComputationStrategyTest {
+
+ @Test
+ public void testSpericalAddCoordinate() {
+
+ double arcmin = (1.0 / 60.0);
+ double arcsec = (1.0 / (60.0 * 60.0));
+
+ double lat1 = 50.0 + 3 * arcmin + 59 * arcsec;
+ double lon1 = -1.0 * (5 + 42 * arcmin + 53 * arcsec); //W
+
+ double lat2 = 58 + 38 * arcmin + 38 * arcsec;
+ double lon2 = -1.0 * (3 + 4 * arcmin + 12 * arcsec);
+
+ double range = 968.9 * 1000.0;
+ double bearing = (9.0 + 7 * arcmin + 11 * arcsec) * (Math.PI / 180.0);
+
+ Coordinate coord = new Coordinate(range * Math.sin(bearing), range * Math.cos(bearing), 1000.0);
+ WorldCoordinate wc = new WorldCoordinate(lat1, lon1, 0.0);
+ wc = GeodeticComputationStrategy.SPHERICAL.addCoordinate(wc, coord);
+
+ System.out.println(wc.getLatitudeDeg());
+ System.out.println(lat2);
+
+ System.out.println(wc.getLongitudeDeg());
+ System.out.println(lon2);
+
+ assertEquals(lat2, wc.getLatitudeDeg(), 0.001);
+ assertEquals(lon2, wc.getLongitudeDeg(), 0.001);
+ assertEquals(1000.0, wc.getAltitude(), 0.0);
+ }
+
+
+ @Test
+ public void testAddCoordinates() {
+
+ double min = 1 / 60.0;
+ double sec = 1 / 3600.0;
+
+
+ // Test zero movement
+ System.out.println("\nTesting zero movement");
+ testAddCoordinate(50.0, 20.0, 0, 123, 50.0, 20.0, false);
+
+
+ /*
+ * These example values have been computed using the calculator at
+ * http://www.movable-type.co.uk/scripts/latlong.html
+ */
+
+ // Long distance NE over England, crosses Greenwich meridian
+ // 50 03N 005 42W to 58 38N 003 04E is 1109km at 027 16'07"
+ System.out.println("\nTesting 1109km NE over England");
+ testAddCoordinate(50 + 3 * min, -5 - 42 * min, 1109000, 27 + 16 * min + 7 * sec, 58 + 38 * min, 3 + 4 * min, false);
+
+ // SW over Brazil
+ // -10N -60E to -11N -61E is 155.9km at 224 25'34"
+ System.out.println("\nTesting 155km SW over Brazil");
+ testAddCoordinate(-10, -60, 155900, 224 + 25 * min + 34 * sec, -11, -61, true);
+
+ // NW over the 180 meridian
+ // 63N -179E to 63 01N 179E is 100.9km at 271 56'34"
+ System.out.println("\nTesting 100km NW over 180 meridian");
+ testAddCoordinate(63, -179, 100900, 271 + 56 * min + 34 * sec, 63 + 1 * min, 179, true);
+
+ // NE near the north pole
+ // 89 50N 0E to 89 45N 175E is 46.29 km at 003 00'01"
+ System.out.println("\nTesting 46km NE near north pole");
+ testAddCoordinate(89 + 50 * min, 0, 46290, 3 + 0 * min + 1 * sec, 89 + 45 * min, 175, false);
+
+ // S directly over south pole
+ // -89 50N 12E to -89 45N 192E is 46.33km at 180 00'00"
+ System.out.println("\nTesting 46km directly over south pole ");
+ testAddCoordinate(-89 - 50 * min, 12, 46330, 180, -89 - 45 * min, -168, false);
+
+ }
+
+ private void testAddCoordinate(double initialLatitude, double initialLongitude, double distance, double bearing,
+ double finalLatitude, double finalLongitude, boolean testFlat) {
+
+ double tolerance;
+
+ bearing = Math.toRadians(bearing);
+
+ // positive X is EAST, positive Y is NORTH
+ double deltaX = distance * Math.sin(bearing);
+ double deltaY = distance * Math.cos(bearing);
+
+ Coordinate coord = new Coordinate(deltaX, deltaY, 1000.0);
+ WorldCoordinate wc = new WorldCoordinate(initialLatitude, initialLongitude, 0.0);
+
+ // Test SPHERICAL
+ tolerance = 0.0015 * distance / 111325;
+ System.out.println("\nSpherical tolerance: " + tolerance);
+ WorldCoordinate result = GeodeticComputationStrategy.SPHERICAL.addCoordinate(wc, coord);
+
+ System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
+ System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
+ assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
+ assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
+ assertEquals(1000.0, result.getAltitude(), 0.0);
+
+
+ // Test WGS84
+ /*
+ * Note: Since the example values are computed using a spherical earth approximation,
+ * the WGS84 method will have significantly larger errors. A tolerance of 1% accommodates
+ * all cases except the NE flight near the north pole, where the ellipsoidal effect is
+ * the greatest.
+ */
+ tolerance = 0.04 * distance / 111325;
+ System.out.println("\nWGS84 tolerance: " + tolerance);
+ result = GeodeticComputationStrategy.WGS84.addCoordinate(wc, coord);
+
+ System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
+ System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
+ assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
+ assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
+ assertEquals(1000.0, result.getAltitude(), 0.0);
+
+
+ // Test FLAT
+ if (testFlat) {
+ tolerance = 0.02 * distance / 111325;
+ System.out.println("\nFlat tolerance: " + tolerance);
+ result = GeodeticComputationStrategy.FLAT.addCoordinate(wc, coord);
+
+ System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
+ System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
+ assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
+ assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
+ assertEquals(1000.0, result.getAltitude(), 0.0);
+
+ }
+
+ }
+
+
+
+ @Test
+ public void testSpericalGetCoriolisAcceleration() {
+
+ // For positive latitude and rotational velocity, a movement due east results in an acceleration due south
+ Coordinate velocity = new Coordinate(-1000, 0, 0);
+ WorldCoordinate wc = new WorldCoordinate(45, 0, 0);
+ double north_accel = GeodeticComputationStrategy.SPHERICAL.getCoriolisAcceleration(wc, velocity).y;
+ System.out.println("North accel " + north_accel);
+ assertTrue(north_accel < 0.0);
+
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util;
+
+import static java.lang.Double.NaN;
+import static java.lang.Math.PI;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+public class MathUtilTest {
+
+ public static final double EPS = 0.00000000001;
+
+ @Test
+ public void miscMathTest() {
+
+ assertEquals(PI * PI, MathUtil.pow2(PI), EPS);
+ assertEquals(PI * PI * PI, MathUtil.pow3(PI), EPS);
+ assertEquals(PI * PI * PI * PI, MathUtil.pow4(PI), EPS);
+
+ assertEquals(1.0, MathUtil.clamp(0.9999, 1.0, 2.0), 0);
+ assertEquals(1.23, MathUtil.clamp(1.23, 1.0, 2.0), 0);
+ assertEquals(2.0, MathUtil.clamp(2 + EPS / 100, 1.0, 2.0), 0);
+
+ assertEquals(1.0f, MathUtil.clamp(0.9999f, 1.0f, 2.0f), 0);
+ assertEquals(1.23f, MathUtil.clamp(1.23f, 1.0f, 2.0f), 0);
+ assertEquals(2.0f, MathUtil.clamp(2.0001f, 1.0f, 2.0f), 0);
+
+ assertEquals(1, MathUtil.clamp(-3, 1, 5));
+ assertEquals(3, MathUtil.clamp(3, 1, 5));
+ assertEquals(5, MathUtil.clamp(6, 1, 5));
+
+ assertEquals(-1.0, MathUtil.sign(Double.NEGATIVE_INFINITY), EPS);
+ assertEquals(-1.0, MathUtil.sign(-100), EPS);
+ assertEquals(-1.0, MathUtil.sign(Math.nextAfter(0.0, -1.0)), EPS);
+ assertEquals(1.0, MathUtil.sign(Math.nextUp(0.0)), EPS);
+ assertEquals(1.0, MathUtil.sign(100), EPS);
+ assertEquals(1.0, MathUtil.sign(Double.POSITIVE_INFINITY), EPS);
+ }
+
+ @Test
+ public void hypotTest() {
+
+ for (int i = 0; i < 10000; i++) {
+ double x = Math.random() * 100 - 50;
+ double y = Math.random() * i - i / 2;
+ double z = Math.hypot(x, y);
+ assertEquals(z, MathUtil.hypot(x, y), EPS);
+ }
+
+ }
+
+ @Test
+ public void reduceTest() {
+
+ for (int i = -1000; i < 1000; i++) {
+ double angle = Math.random() * 2 * PI;
+ double shift = angle + i * 2 * PI;
+ assertEquals(angle, MathUtil.reduce360(shift), EPS);
+ }
+
+ for (int i = -1000; i < 1000; i++) {
+ double angle = Math.random() * 2 * PI - PI;
+ double shift = angle + i * 2 * PI;
+ assertEquals(angle, MathUtil.reduce180(shift), EPS);
+ }
+
+ }
+
+ @Test
+ public void minmaxTest() {
+ assertEquals(1.0, MathUtil.min(1.0, Math.nextUp(1.0)), 0);
+ assertEquals(1.0, MathUtil.min(1.0, Double.POSITIVE_INFINITY), 0);
+ assertEquals(1.0, MathUtil.min(NaN, 1.0), 0);
+ assertEquals(1.0, MathUtil.min(1.0, NaN), 0);
+ assertEquals(NaN, MathUtil.min(NaN, NaN), 0);
+
+ assertEquals(Math.nextUp(1.0), MathUtil.max(1.0, Math.nextUp(1.0)), 0);
+ assertEquals(Double.POSITIVE_INFINITY, MathUtil.max(1.0, Double.POSITIVE_INFINITY), 0);
+ assertEquals(1.0, MathUtil.max(NaN, 1.0), 0);
+ assertEquals(1.0, MathUtil.max(1.0, NaN), 0);
+ assertEquals(NaN, MathUtil.max(NaN, NaN), 0);
+
+ assertEquals(1.0, MathUtil.min(1.0, 2.0, 3.0), 0);
+ assertEquals(1.0, MathUtil.min(1.0, NaN, NaN), 0);
+ assertEquals(1.0, MathUtil.min(NaN, 1.0, NaN), 0);
+ assertEquals(1.0, MathUtil.min(NaN, NaN, 1.0), 0);
+ assertEquals(1.0, MathUtil.min(2.0, NaN, 1.0), 0);
+ assertEquals(1.0, MathUtil.min(1.0, 2.0, NaN), 0);
+ assertEquals(1.0, MathUtil.min(NaN, 2.0, 1.0), 0);
+
+ assertEquals(3.0, MathUtil.max(1.0, 3.0, 2.0), 0);
+ assertEquals(1.0, MathUtil.max(1.0, NaN, NaN), 0);
+ assertEquals(1.0, MathUtil.max(NaN, 1.0, NaN), 0);
+ assertEquals(1.0, MathUtil.max(NaN, NaN, 1.0), 0);
+ assertEquals(2.0, MathUtil.max(2.0, NaN, 1.0), 0);
+ assertEquals(2.0, MathUtil.max(1.0, 2.0, NaN), 0);
+ assertEquals(2.0, MathUtil.max(NaN, 2.0, 1.0), 0);
+
+ assertEquals(1.0, MathUtil.min(1.0, 2.0, 3.0, 4.0), 0);
+ assertEquals(1.0, MathUtil.min(1.0, NaN, NaN, NaN), 0);
+ assertEquals(1.0, MathUtil.min(NaN, 1.0, NaN, NaN), 0);
+ assertEquals(1.0, MathUtil.min(NaN, NaN, 1.0, NaN), 0);
+ assertEquals(1.0, MathUtil.min(2.0, NaN, 1.0, NaN), 0);
+ assertEquals(1.0, MathUtil.min(2.0, NaN, NaN, 1.0), 0);
+ assertEquals(1.0, MathUtil.min(1.0, 2.0, NaN, 3.0), 0);
+ assertEquals(1.0, MathUtil.min(NaN, 2.0, 3.0, 1.0), 0);
+
+ }
+
+ @Test
+ public void mapTest() {
+ assertEquals(1.0, MathUtil.map(1.0, 0.0, 5.0, -1.0, 9.0), EPS);
+ assertEquals(7.0, MathUtil.map(1.0, 5.0, 0.0, -1.0, 9.0), EPS);
+ assertEquals(7.0, MathUtil.map(1.0, 0.0, 5.0, 9.0, -1.0), EPS);
+ assertEquals(6.0, MathUtil.map(6.0, 0.0, 5.0, Math.nextUp(6.0), 6.0), EPS);
+ assertEquals(6.0, MathUtil.map(6.0, 0.0, 0.0, Math.nextUp(6.0), 6.0), EPS);
+ try {
+ MathUtil.map(6.0, 1.0, Math.nextUp(1.0), 1.0, 2.0);
+ fail("Should not be reached.");
+ } catch (IllegalArgumentException normal) {
+ }
+
+ assertEquals(7.0, MathUtil.map(Math.nextUp(1.0), 0.0, 5.0, 9.0, -1.0), EPS);
+ }
+
+
+ @Test
+ public void mapCoordinateTest() {
+ assertEquals(new Coordinate(0.8, 2.0, 1.6, 4.0),
+ MathUtil.map(1.0, 0.0, 5.0, new Coordinate(0, 1, 2, 3), new Coordinate(4, 6, 0, 8)));
+ }
+
+
+ @Test
+ public void equalsTest() {
+ assertTrue(MathUtil.equals(1.0, 1.0 + MathUtil.EPSILON / 3));
+ assertFalse(MathUtil.equals(1.0, 1.0 + MathUtil.EPSILON * 2));
+ assertTrue(MathUtil.equals(-1.0, -1.0 + MathUtil.EPSILON / 3));
+ assertFalse(MathUtil.equals(-1.0, -1.0 + MathUtil.EPSILON * 2));
+
+ for (double zero : new double[] { 0.0, MathUtil.EPSILON / 10, -MathUtil.EPSILON / 10 }) {
+
+ assertTrue(MathUtil.equals(zero, MathUtil.EPSILON / 3));
+ assertTrue(MathUtil.equals(zero, -MathUtil.EPSILON / 3));
+ assertFalse(MathUtil.equals(zero, MathUtil.EPSILON * 2));
+ assertFalse(MathUtil.equals(zero, -MathUtil.EPSILON * 2));
+
+ assertTrue(MathUtil.equals(MathUtil.EPSILON / 3, zero));
+ assertTrue(MathUtil.equals(-MathUtil.EPSILON / 3, zero));
+ assertFalse(MathUtil.equals(MathUtil.EPSILON * 2, zero));
+ assertFalse(MathUtil.equals(-MathUtil.EPSILON * 2, zero));
+
+ }
+
+ for (double value : new double[] { PI * 1e20, -PI * 1e20 }) {
+ assertTrue("value=" + value, MathUtil.equals(value, value + 1));
+ assertTrue("value=" + value, MathUtil.equals(value, Math.nextUp(value)));
+ assertTrue("value=" + value, MathUtil.equals(value, value * (1 + MathUtil.EPSILON)));
+ }
+
+ assertFalse(MathUtil.equals(NaN, 0.0));
+ assertFalse(MathUtil.equals(0.0, NaN));
+ assertFalse(MathUtil.equals(NaN, NaN));
+ }
+
+ @Test
+ public void testAverageStddev() {
+ List<Integer> ints = new ArrayList<Integer>();
+ List<Double> doubles = new ArrayList<Double>();
+
+ ints.add(3);
+ ints.add(4);
+ ints.add(7);
+ ints.add(5);
+
+ doubles.add(3.4);
+ doubles.add(2.9);
+ doubles.add(7.5);
+ doubles.add(5.43);
+ doubles.add(2.8);
+ doubles.add(6.6);
+
+ assertEquals(4.75, MathUtil.average(ints), EPS);
+ assertEquals(1.707825127659933, MathUtil.stddev(ints), EPS);
+ assertEquals(4.771666666666667, MathUtil.average(doubles), EPS);
+ assertEquals(2.024454659078999, MathUtil.stddev(doubles), EPS);
+ }
+
+ @Test
+ public void testMedian() {
+ List<Integer> ints = new ArrayList<Integer>();
+ List<Double> doubles = new ArrayList<Double>();
+
+ ints.add(3);
+ ints.add(4);
+ ints.add(7);
+ ints.add(5);
+
+ doubles.add(3.4);
+ doubles.add(2.9);
+ doubles.add(7.5);
+ doubles.add(5.43);
+ doubles.add(2.8);
+ doubles.add(6.6);
+
+ assertEquals(4.5, MathUtil.median(ints), EPS);
+ assertEquals(4.415, MathUtil.median(doubles), EPS);
+
+ ints.add(9);
+ doubles.add(10.0);
+
+ assertEquals(5, MathUtil.median(ints), EPS);
+ assertEquals(5.43, MathUtil.median(doubles), EPS);
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util;
+
+import static org.junit.Assert.*;
+import net.sf.openrocket.logging.TraceException;
+
+import org.junit.Test;
+
+public class MutableTest {
+
+ @Test
+ public void testMutable() {
+ Mutable m = new Mutable();
+ Throwable t = null;
+
+ m.check();
+ m.check();
+ assertTrue(m.isMutable());
+
+ m.immute();
+
+ try {
+ m.check();
+ fail();
+ } catch (IllegalStateException e) {
+ // Success
+ t = e.getCause();
+ assertTrue(t instanceof TraceException);
+ }
+
+ m.immute();
+
+ try {
+ m.check();
+ fail();
+ } catch (IllegalStateException e) {
+ // Success
+ assertTrue(e.getCause() == t);
+ }
+ }
+
+
+ @Test
+ public void testClone() {
+ Mutable m1 = new Mutable();
+ Mutable m2 = m1.clone();
+
+ assertTrue(m1.isMutable());
+ assertTrue(m2.isMutable());
+
+ m1.immute();
+
+ assertFalse(m1.isMutable());
+ assertTrue(m2.isMutable());
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Test;
+
+public class ReflectionTest {
+
+ @Test
+ public void textHandleInvocationTargetException() {
+ Throwable cause = null;
+
+ try {
+ cause = new InvocationTargetException(null);
+ Reflection.handleWrappedException((InvocationTargetException)cause);
+ fail();
+ } catch (BugException e) {
+ assertTrue(cause == e.getCause());
+ }
+
+ try {
+ cause = new IllegalStateException("Test");
+ Reflection.handleWrappedException(new InvocationTargetException(cause));
+ fail();
+ } catch (IllegalStateException e) {
+ assertTrue(cause == e);
+ }
+
+ try {
+ cause = new AbstractMethodError();
+ Reflection.handleWrappedException(new InvocationTargetException(cause));
+ fail();
+ } catch (AbstractMethodError e) {
+ assertTrue(cause == e);
+ }
+
+ try {
+ cause = new IOException();
+ Reflection.handleWrappedException(new InvocationTargetException(cause));
+ fail();
+ } catch (BugException e) {
+ assertTrue(cause == e.getCause());
+ }
+
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class Rotation2DTest {
+
+ @Test
+ public void rotationTest() {
+
+ double rot60 = 0.5;
+ double rot30 = Math.sqrt(3)/2;
+
+ Coordinate x = new Coordinate(1,1,0);
+ Coordinate y = new Coordinate(0,1,1);
+
+ Rotation2D rot = new Rotation2D(Math.PI/3); // 60 deg
+
+ assertEquals(new Coordinate(rot60, 1, -rot30), rot.rotateY(x));
+ assertEquals(new Coordinate(rot60, 1, rot30), rot.invRotateY(x));
+
+ assertEquals(new Coordinate(1, rot60, rot30), rot.rotateX(x));
+ assertEquals(new Coordinate(1, rot60, -rot30), rot.invRotateX(x));
+
+ assertEquals(new Coordinate(-rot30, rot60, 1), rot.rotateZ(y));
+ assertEquals(new Coordinate(rot30, rot60, 1), rot.invRotateZ(y));
+
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestMutex {
+
+ @Before
+ public void setup() {
+ System.setProperty("openrocket.debug.safetycheck", "true");
+ }
+
+ @Test
+ public void testSingleLocking() {
+ SafetyMutex.ConcreteSafetyMutex m = new SafetyMutex.ConcreteSafetyMutex();
+
+ // Test single locking
+ assertNull(m.lockingThread);
+ m.verify();
+ m.lock("here");
+ assertNotNull(m.lockingThread);
+ assertTrue(m.unlock("here"));
+
+ }
+
+ @Test
+ public void testDoubleLocking() {
+ SafetyMutex.ConcreteSafetyMutex m = new SafetyMutex.ConcreteSafetyMutex();
+
+ // Test double locking
+ m.verify();
+ m.lock("foobar");
+ m.verify();
+ m.lock("bazqux");
+ m.verify();
+ assertTrue(m.unlock("bazqux"));
+ m.verify();
+ assertTrue(m.unlock("foobar"));
+ m.verify();
+ }
+
+ @Test
+ public void testDoubleUnlocking() {
+ SafetyMutex.ConcreteSafetyMutex m = new SafetyMutex.ConcreteSafetyMutex();
+ // Mark error reported to not init exception handler
+ SafetyMutex.ConcreteSafetyMutex.errorReported = true;
+
+ m.lock("here");
+ assertTrue(m.unlock("here"));
+ assertFalse(m.unlock("here"));
+ }
+
+
+
+ private volatile int testState = 0;
+ private volatile String failure = null;
+
+ @Test(timeout = 1000)
+ public void testThreadingErrors() {
+ final SafetyMutex.ConcreteSafetyMutex m = new SafetyMutex.ConcreteSafetyMutex();
+
+ // Initialize and start the thread
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ try {
+
+ // Test locking a locked mutex
+ waitFor(1);
+ try {
+ m.lock("in thread one");
+ failure = "Succeeded in locking a mutex locked by a different thread";
+ return;
+ } catch (ConcurrencyException e) {
+ // OK
+ }
+
+ // Test unlocking a mutex locked by a different thread
+ if (m.unlock("in thread two")) {
+ failure = "Succeeded in unlocking a mutex locked by a different thread";
+ return;
+ }
+
+ // Test verifying a locked mutex that already has an error
+ try {
+ m.verify();
+ failure = "Succeeded in verifying a mutex locked by a different thread";
+ return;
+ } catch (ConcurrencyException e) {
+ // OK
+ }
+
+ // Test locking a mutex after it's been unlocked
+ testState = 2;
+ waitFor(3);
+ m.lock("in thread three");
+ m.verify();
+
+ // Wait for other side to test
+ testState = 4;
+ waitFor(5);
+
+ // Exit code
+ testState = 6;
+
+ } catch (Exception e) {
+ failure = "Exception occurred in thread: " + e;
+ return;
+ }
+
+ }
+ };
+ thread.setDaemon(true);
+ thread.start();
+
+ m.lock("one");
+ testState = 1;
+
+ waitFor(2);
+ assertNull("Thread error: " + failure, failure);
+
+ m.verify();
+ m.unlock("one");
+ testState = 3;
+
+ waitFor(4);
+ assertNull("Thread error: " + failure, failure);
+
+ try {
+ m.lock("two");
+ fail("Succeeded in locking a locked mutex in main thread");
+ } catch (ConcurrencyException e) {
+ // OK
+ }
+
+ // Test unlocking a mutex locked by a different thread
+ assertFalse(m.unlock("here"));
+
+ try {
+ m.verify();
+ fail("Succeeded in verifying a locked mutex in main thread");
+ } catch (ConcurrencyException e) {
+ // OK
+ }
+
+ testState = 5;
+ waitFor(6);
+ assertNull("Thread error: " + failure, failure);
+ }
+
+ private void waitFor(int state) {
+ while (testState != state && failure == null) {
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+
+ public void testBogusMutex() {
+ SafetyMutex m = new SafetyMutex.BogusSafetyMutex();
+ m.lock("foo");
+ m.lock("bar");
+ m.lock("baz");
+ m.verify();
+ m.unlock("a");
+ m.unlock(null);
+ m.unlock("");
+ m.unlock("c");
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util;
+
+import static java.lang.Math.PI;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Random;
+
+import org.junit.Test;
+
+public class TextUtilTest {
+
+ @Test
+ public void testHexString() {
+ assertEquals("", TextUtil.hexString(new byte[0]));
+ assertEquals("00", TextUtil.hexString(new byte[] { 0x00 }));
+ assertEquals("ff", TextUtil.hexString(new byte[] { (byte) 0xff }));
+
+ for (int i = 0; i <= 0xff; i++) {
+ assertEquals(String.format("%02x", i), TextUtil.hexString(new byte[] { (byte) i }));
+ }
+
+ assertEquals("0f1e2d3c4b5a6978", TextUtil.hexString(new byte[] {
+ 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78
+ }));
+
+ Random rnd = new Random();
+ for (int count = 0; count < 10; count++) {
+ int n = rnd.nextInt(100);
+ byte[] bytes = new byte[n];
+ rnd.nextBytes(bytes);
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ sb.append(String.format("%02x", b & 0xFF));
+ }
+ assertEquals(sb.toString(), TextUtil.hexString(bytes));
+ }
+ }
+
+ @Test
+ public void specialCaseTest() {
+ assertEquals("NaN", TextUtil.doubleToString(Double.NaN));
+ assertEquals("Inf", TextUtil.doubleToString(Double.POSITIVE_INFINITY));
+ assertEquals("-Inf", TextUtil.doubleToString(Double.NEGATIVE_INFINITY));
+ assertEquals("0", TextUtil.doubleToString(0.0));
+ assertEquals("0", TextUtil.doubleToString(MathUtil.EPSILON / 3));
+ assertEquals("0", TextUtil.doubleToString(-MathUtil.EPSILON / 3));
+ }
+
+ @Test
+ public void longTest() {
+
+ assertEquals("3.1416e-5", TextUtil.doubleToString(PI * 1e-5));
+ assertEquals("3.1416e-4", TextUtil.doubleToString(PI * 1e-4));
+ assertEquals("0.0031416", TextUtil.doubleToString(PI * 1e-3));
+ assertEquals("0.031416", TextUtil.doubleToString(PI * 1e-2));
+ assertEquals("0.31416", TextUtil.doubleToString(PI * 1e-1));
+ assertEquals("3.1416", TextUtil.doubleToString(PI));
+ assertEquals("31.416", TextUtil.doubleToString(PI * 1e1));
+ assertEquals("314.16", TextUtil.doubleToString(PI * 1e2));
+ assertEquals("3141.6", TextUtil.doubleToString(PI * 1e3));
+ assertEquals("31416", TextUtil.doubleToString(PI * 1e4));
+ assertEquals("314159", TextUtil.doubleToString(PI * 1e5));
+ assertEquals("3141593", TextUtil.doubleToString(PI * 1e6));
+ assertEquals("31415927", TextUtil.doubleToString(PI * 1e7));
+ assertEquals("3.1416e8", TextUtil.doubleToString(PI * 1e8));
+ assertEquals("3.1416e9", TextUtil.doubleToString(PI * 1e9));
+ assertEquals("3.1416e10", TextUtil.doubleToString(PI * 1e10));
+
+ assertEquals("-3.1416e-5", TextUtil.doubleToString(-PI * 1e-5));
+ assertEquals("-3.1416e-4", TextUtil.doubleToString(-PI * 1e-4));
+ assertEquals("-0.0031416", TextUtil.doubleToString(-PI * 1e-3));
+ assertEquals("-0.031416", TextUtil.doubleToString(-PI * 1e-2));
+ assertEquals("-0.31416", TextUtil.doubleToString(-PI * 1e-1));
+ assertEquals("-3.1416", TextUtil.doubleToString(-PI));
+ assertEquals("-31.416", TextUtil.doubleToString(-PI * 1e1));
+ assertEquals("-314.16", TextUtil.doubleToString(-PI * 1e2));
+ assertEquals("-3141.6", TextUtil.doubleToString(-PI * 1e3));
+ assertEquals("-31416", TextUtil.doubleToString(-PI * 1e4));
+ assertEquals("-314159", TextUtil.doubleToString(-PI * 1e5));
+ assertEquals("-3141593", TextUtil.doubleToString(-PI * 1e6));
+ assertEquals("-31415927", TextUtil.doubleToString(-PI * 1e7));
+ assertEquals("-3.1416e8", TextUtil.doubleToString(-PI * 1e8));
+ assertEquals("-3.1416e9", TextUtil.doubleToString(-PI * 1e9));
+ assertEquals("-3.1416e10", TextUtil.doubleToString(-PI * 1e10));
+
+ }
+
+ @Test
+ public void shortTest() {
+ double p = 3.1;
+ assertEquals("3.1e-5", TextUtil.doubleToString(p * 1e-5));
+ assertEquals("3.1e-4", TextUtil.doubleToString(p * 1e-4));
+ assertEquals("0.0031", TextUtil.doubleToString(p * 1e-3));
+ assertEquals("0.031", TextUtil.doubleToString(p * 1e-2));
+ assertEquals("0.31", TextUtil.doubleToString(p * 1e-1));
+ assertEquals("3.1", TextUtil.doubleToString(p));
+ assertEquals("31", TextUtil.doubleToString(p * 1e1));
+ assertEquals("310", TextUtil.doubleToString(p * 1e2));
+ assertEquals("3100", TextUtil.doubleToString(p * 1e3));
+ assertEquals("31000", TextUtil.doubleToString(p * 1e4));
+ assertEquals("3.1e5", TextUtil.doubleToString(p * 1e5));
+ assertEquals("3.1e6", TextUtil.doubleToString(p * 1e6));
+ assertEquals("3.1e7", TextUtil.doubleToString(p * 1e7));
+ assertEquals("3.1e8", TextUtil.doubleToString(p * 1e8));
+ assertEquals("3.1e9", TextUtil.doubleToString(p * 1e9));
+ assertEquals("3.1e10", TextUtil.doubleToString(p * 1e10));
+
+ assertEquals("-3.1e-5", TextUtil.doubleToString(-p * 1e-5));
+ assertEquals("-3.1e-4", TextUtil.doubleToString(-p * 1e-4));
+ assertEquals("-0.0031", TextUtil.doubleToString(-p * 1e-3));
+ assertEquals("-0.031", TextUtil.doubleToString(-p * 1e-2));
+ assertEquals("-0.31", TextUtil.doubleToString(-p * 1e-1));
+ assertEquals("-3.1", TextUtil.doubleToString(-p));
+ assertEquals("-31", TextUtil.doubleToString(-p * 1e1));
+ assertEquals("-310", TextUtil.doubleToString(-p * 1e2));
+ assertEquals("-3100", TextUtil.doubleToString(-p * 1e3));
+ assertEquals("-31000", TextUtil.doubleToString(-p * 1e4));
+ assertEquals("-3.1e5", TextUtil.doubleToString(-p * 1e5));
+ assertEquals("-3.1e6", TextUtil.doubleToString(-p * 1e6));
+ assertEquals("-3.1e7", TextUtil.doubleToString(-p * 1e7));
+ assertEquals("-3.1e8", TextUtil.doubleToString(-p * 1e8));
+ assertEquals("-3.1e9", TextUtil.doubleToString(-p * 1e9));
+ assertEquals("-3.1e10", TextUtil.doubleToString(-p * 1e10));
+
+ p = 3;
+ assertEquals("3e-5", TextUtil.doubleToString(p * 1e-5));
+ assertEquals("3e-4", TextUtil.doubleToString(p * 1e-4));
+ assertEquals("3e-3", TextUtil.doubleToString(p * 1e-3));
+ assertEquals("0.03", TextUtil.doubleToString(p * 1e-2));
+ assertEquals("0.3", TextUtil.doubleToString(p * 1e-1));
+ assertEquals("3", TextUtil.doubleToString(p));
+ assertEquals("30", TextUtil.doubleToString(p * 1e1));
+ assertEquals("300", TextUtil.doubleToString(p * 1e2));
+ assertEquals("3e3", TextUtil.doubleToString(p * 1e3));
+ assertEquals("3e4", TextUtil.doubleToString(p * 1e4));
+ assertEquals("3e5", TextUtil.doubleToString(p * 1e5));
+ assertEquals("3e6", TextUtil.doubleToString(p * 1e6));
+ assertEquals("3e7", TextUtil.doubleToString(p * 1e7));
+ assertEquals("3e8", TextUtil.doubleToString(p * 1e8));
+ assertEquals("3e9", TextUtil.doubleToString(p * 1e9));
+ assertEquals("3e10", TextUtil.doubleToString(p * 1e10));
+
+ assertEquals("-3e-5", TextUtil.doubleToString(-p * 1e-5));
+ assertEquals("-3e-4", TextUtil.doubleToString(-p * 1e-4));
+ assertEquals("-3e-3", TextUtil.doubleToString(-p * 1e-3));
+ assertEquals("-0.03", TextUtil.doubleToString(-p * 1e-2));
+ assertEquals("-0.3", TextUtil.doubleToString(-p * 1e-1));
+ assertEquals("-3", TextUtil.doubleToString(-p));
+ assertEquals("-30", TextUtil.doubleToString(-p * 1e1));
+ assertEquals("-300", TextUtil.doubleToString(-p * 1e2));
+ assertEquals("-3e3", TextUtil.doubleToString(-p * 1e3));
+ assertEquals("-3e4", TextUtil.doubleToString(-p * 1e4));
+ assertEquals("-3e5", TextUtil.doubleToString(-p * 1e5));
+ assertEquals("-3e6", TextUtil.doubleToString(-p * 1e6));
+ assertEquals("-3e7", TextUtil.doubleToString(-p * 1e7));
+ assertEquals("-3e8", TextUtil.doubleToString(-p * 1e8));
+ assertEquals("-3e9", TextUtil.doubleToString(-p * 1e9));
+ assertEquals("-3e10", TextUtil.doubleToString(-p * 1e10));
+
+ }
+
+ @Test
+ public void roundingTest() {
+
+ assertEquals("1.001", TextUtil.doubleToString(1.00096));
+
+
+ /*
+ * Not testing with 1.00015 because it might be changed during number formatting
+ * calculations. Its rounding is basically arbitrary anyway.
+ */
+
+ assertEquals("1.0002e-5", TextUtil.doubleToString(1.0001500001e-5));
+ assertEquals("1.0001e-5", TextUtil.doubleToString(1.0001499999e-5));
+ assertEquals("1.0002e-4", TextUtil.doubleToString(1.0001500001e-4));
+ assertEquals("1.0001e-4", TextUtil.doubleToString(1.0001499999e-4));
+ assertEquals("0.0010002", TextUtil.doubleToString(1.0001500001e-3));
+ assertEquals("0.0010001", TextUtil.doubleToString(1.0001499999e-3));
+ assertEquals("0.010002", TextUtil.doubleToString(1.0001500001e-2));
+ assertEquals("0.010001", TextUtil.doubleToString(1.0001499999e-2));
+ assertEquals("0.10002", TextUtil.doubleToString(1.0001500001e-1));
+ assertEquals("0.10001", TextUtil.doubleToString(1.0001499999e-1));
+ assertEquals("1.0002", TextUtil.doubleToString(1.0001500001));
+ assertEquals("1.0001", TextUtil.doubleToString(1.0001499999));
+ assertEquals("10.002", TextUtil.doubleToString(1.0001500001e1));
+ assertEquals("10.001", TextUtil.doubleToString(1.0001499999e1));
+ assertEquals("100.02", TextUtil.doubleToString(1.0001500001e2));
+ assertEquals("100.01", TextUtil.doubleToString(1.0001499999e2));
+ assertEquals("1000.2", TextUtil.doubleToString(1.0001500001e3));
+ assertEquals("1000.1", TextUtil.doubleToString(1.0001499999e3));
+ assertEquals("10002", TextUtil.doubleToString(1.0001500001e4));
+ assertEquals("10001", TextUtil.doubleToString(1.0001499999e4));
+ assertEquals("100012", TextUtil.doubleToString(1.00011500001e5));
+ assertEquals("100011", TextUtil.doubleToString(1.00011499999e5));
+ assertEquals("1000112", TextUtil.doubleToString(1.000111500001e6));
+ assertEquals("1000111", TextUtil.doubleToString(1.000111499999e6));
+ assertEquals("10001112", TextUtil.doubleToString(1.0001111500001e7));
+ assertEquals("10001111", TextUtil.doubleToString(1.0001111499999e7));
+ assertEquals("1.0002e8", TextUtil.doubleToString(1.0001500001e8));
+ assertEquals("1.0001e8", TextUtil.doubleToString(1.0001499999e8));
+ assertEquals("1.0002e9", TextUtil.doubleToString(1.0001500001e9));
+ assertEquals("1.0001e9", TextUtil.doubleToString(1.0001499999e9));
+ assertEquals("1.0002e10", TextUtil.doubleToString(1.0001500001e10));
+ assertEquals("1.0001e10", TextUtil.doubleToString(1.0001499999e10));
+
+
+ assertEquals("-1.0002e-5", TextUtil.doubleToString(-1.0001500001e-5));
+ assertEquals("-1.0001e-5", TextUtil.doubleToString(-1.0001499999e-5));
+ assertEquals("-1.0002e-4", TextUtil.doubleToString(-1.0001500001e-4));
+ assertEquals("-1.0001e-4", TextUtil.doubleToString(-1.0001499999e-4));
+ assertEquals("-0.0010002", TextUtil.doubleToString(-1.0001500001e-3));
+ assertEquals("-0.0010001", TextUtil.doubleToString(-1.0001499999e-3));
+ assertEquals("-0.010002", TextUtil.doubleToString(-1.0001500001e-2));
+ assertEquals("-0.010001", TextUtil.doubleToString(-1.0001499999e-2));
+ assertEquals("-0.10002", TextUtil.doubleToString(-1.0001500001e-1));
+ assertEquals("-0.10001", TextUtil.doubleToString(-1.0001499999e-1));
+ assertEquals("-1.0002", TextUtil.doubleToString(-1.0001500001));
+ assertEquals("-1.0001", TextUtil.doubleToString(-1.0001499999));
+ assertEquals("-10.002", TextUtil.doubleToString(-1.0001500001e1));
+ assertEquals("-10.001", TextUtil.doubleToString(-1.0001499999e1));
+ assertEquals("-100.02", TextUtil.doubleToString(-1.0001500001e2));
+ assertEquals("-100.01", TextUtil.doubleToString(-1.0001499999e2));
+ assertEquals("-1000.2", TextUtil.doubleToString(-1.0001500001e3));
+ assertEquals("-1000.1", TextUtil.doubleToString(-1.0001499999e3));
+ assertEquals("-10002", TextUtil.doubleToString(-1.0001500001e4));
+ assertEquals("-10001", TextUtil.doubleToString(-1.0001499999e4));
+ assertEquals("-100012", TextUtil.doubleToString(-1.00011500001e5));
+ assertEquals("-100011", TextUtil.doubleToString(-1.00011499999e5));
+ assertEquals("-1000112", TextUtil.doubleToString(-1.000111500001e6));
+ assertEquals("-1000111", TextUtil.doubleToString(-1.000111499999e6));
+ assertEquals("-10001112", TextUtil.doubleToString(-1.0001111500001e7));
+ assertEquals("-10001111", TextUtil.doubleToString(-1.0001111499999e7));
+ assertEquals("-1.0002e8", TextUtil.doubleToString(-1.0001500001e8));
+ assertEquals("-1.0001e8", TextUtil.doubleToString(-1.0001499999e8));
+ assertEquals("-1.0002e9", TextUtil.doubleToString(-1.0001500001e9));
+ assertEquals("-1.0001e9", TextUtil.doubleToString(-1.0001499999e9));
+ assertEquals("-1.0002e10", TextUtil.doubleToString(-1.0001500001e10));
+ assertEquals("-1.0001e10", TextUtil.doubleToString(-1.0001499999e10));
+
+ }
+
+
+ @Test
+ public void randomTest() {
+ for (int i = 0; i < 10000; i++) {
+ double orig = Math.random();
+ double result;
+ double expected = Math.rint(orig * 100000) / 100000.0;
+
+ if (orig < 0.1)
+ continue;
+ String s = TextUtil.doubleToString(orig);
+ result = Double.parseDouble(s);
+ assertEquals(expected, result, 0.00000001);
+ }
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class UniqueIDTest {
+
+ @Test
+ public void integerTest() {
+
+ int n = UniqueID.next();
+ assertTrue(n > 0);
+ assertEquals(n+1, UniqueID.next());
+ assertEquals(n+2, UniqueID.next());
+ assertEquals(n+3, UniqueID.next());
+
+ }
+
+
+ @Test
+ public void stringTest() {
+ String id = UniqueID.uuid();
+ assertNotNull(id);
+ assertNotSame(id, UniqueID.uuid());
+ assertNotSame(id, UniqueID.uuid());
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class WorldCoordinateTest {
+
+ private static final double EPS = 1e-10;
+
+ @Test
+ public void testConstructor() {
+ WorldCoordinate wc;
+
+ wc = new WorldCoordinate(10, 15, 130);
+ assertEquals(10, wc.getLatitudeDeg(), EPS);
+ assertEquals(15, wc.getLongitudeDeg(), EPS);
+ assertEquals(130, wc.getAltitude(), 0);
+
+ wc = new WorldCoordinate(100, 190, 13000);
+ assertEquals(90, wc.getLatitudeDeg(), EPS);
+ assertEquals(-170, wc.getLongitudeDeg(), EPS);
+ assertEquals(13000, wc.getAltitude(), 0);
+
+ wc = new WorldCoordinate(-100, -200, -13000);
+ assertEquals(-90, wc.getLatitudeDeg(), EPS);
+ assertEquals(160, wc.getLongitudeDeg(), EPS);
+ assertEquals(-13000, wc.getAltitude(), 0);
+ }
+
+ @Test
+ public void testGetLatitude() {
+ WorldCoordinate wc;
+ wc = new WorldCoordinate(10, 15, 130);
+ assertEquals(10, wc.getLatitudeDeg(), EPS);
+ assertEquals(Math.toRadians(10), wc.getLatitudeRad(), EPS);
+ }
+
+ @Test
+ public void testGetLongitude() {
+ WorldCoordinate wc;
+ wc = new WorldCoordinate(10, 15, 130);
+ assertEquals(15, wc.getLongitudeDeg(), EPS);
+ assertEquals(Math.toRadians(15), wc.getLongitudeRad(), EPS);
+ }
+
+}
+++ /dev/null
-<engine-database>\r
- <engine-list>\r
-<engine FDiv="10" FFix="1" FStep="-1." Isp="71.7" Itot="2.32" Type="single-use" auto-calc-cg="1" auto-calc-mass="1" avgThrust="3.178" burn-time="0.73" cgDiv="10" cgFix="1" cgStep="-1." code="A8" delays="3,5" dia="18." exitDia="0." initWt="16.35" len="70." mDiv="10" mFix="1" mStep="-1." massFrac="20.18" mfg="Estes" peakThrust="9.73" propWt="3.3" tDiv="10" tFix="1" tStep="-1." throatDia="0.">\r
-<comments>Estes A8 RASP.ENG file made from NAR published data\r
-File produced October 3, 2000\r
-The total impulse, peak thrust, average thrust and burn time are\r
-the same as the averaged static test data on the NAR web site in\r
-the certification file. The curve drawn with these data points is as\r
-close to the certification curve as can be with such a limited\r
-number of points (32) allowed with wRASP up to v1.6.\r
-</comments>\r
-<data>\r
-<eng-data cg="35." f="0." m="3.3" t="0."/>\r
-<eng-data cg="35." f="0.512" m="3.28507" t="0.041"/>\r
-<eng-data cg="35." f="2.115" m="3.20474" t="0.084"/>\r
-<eng-data cg="35." f="4.358" m="3.0068" t="0.127"/>\r
-<eng-data cg="35." f="6.794" m="2.6975" t="0.166"/>\r
-<eng-data cg="35." f="8.588" m="2.41309" t="0.192"/>\r
-<eng-data cg="35." f="9.294" m="2.23506" t="0.206"/>\r
-<eng-data cg="35." f="9.73" m="1.96448" t="0.226"/>\r
-<eng-data cg="35." f="8.845" m="1.83238" t="0.236"/>\r
-<eng-data cg="35." f="7.179" m="1.70703" t="0.247"/>\r
-<eng-data cg="35." f="5.063" m="1.58515" t="0.261"/>\r
-<eng-data cg="35." f="3.717" m="1.48525" t="0.277"/>\r
-<eng-data cg="35." f="3.205" m="1.3425" t="0.306"/>\r
-<eng-data cg="35." f="2.884" m="1.14764" t="0.351"/>\r
-<eng-data cg="35." f="2.499" m="0.94092" t="0.405"/>\r
-<eng-data cg="35." f="2.371" m="0.726196" t="0.467"/>\r
-<eng-data cg="35." f="2.307" m="0.509957" t="0.532"/>\r
-<eng-data cg="35." f="2.371" m="0.320333" t="0.589"/>\r
-<eng-data cg="35." f="2.371" m="0.175326" t="0.632"/>\r
-<eng-data cg="35." f="2.243" m="0.109701" t="0.652"/>\r
-<eng-data cg="35." f="1.794" m="0.0637665" t="0.668"/>\r
-<eng-data cg="35." f="1.153" m="0.0302344" t="0.684"/>\r
-<eng-data cg="35." f="0.448" m="0.00860204" t="0.703"/>\r
-<eng-data cg="35." f="0." m="0." t="0.73"/>\r
-</data>\r
-</engine>\r
- </engine-list>\r
-</engine-database>\r
+++ /dev/null
-package net.sf.openrocket;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.awt.event.ActionEvent;
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.swing.Action;
-
-import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
-import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
-import net.sf.openrocket.aerodynamics.FlightConditions;
-import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
-import net.sf.openrocket.document.OpenRocketDocument;
-import net.sf.openrocket.document.Simulation;
-import net.sf.openrocket.file.GeneralRocketLoader;
-import net.sf.openrocket.file.RocketLoadException;
-import net.sf.openrocket.file.motor.GeneralMotorLoader;
-import net.sf.openrocket.gui.main.UndoRedoAction;
-import net.sf.openrocket.l10n.ResourceBundleTranslator;
-import net.sf.openrocket.masscalc.BasicMassCalculator;
-import net.sf.openrocket.masscalc.MassCalculator;
-import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
-import net.sf.openrocket.motor.Motor;
-import net.sf.openrocket.motor.ThrustCurveMotor;
-import net.sf.openrocket.rocketcomponent.Configuration;
-import net.sf.openrocket.rocketcomponent.EngineBlock;
-import net.sf.openrocket.rocketcomponent.MassComponent;
-import net.sf.openrocket.rocketcomponent.NoseCone;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
-import net.sf.openrocket.simulation.FlightDataType;
-import net.sf.openrocket.simulation.exception.SimulationException;
-import net.sf.openrocket.startup.Application;
-import net.sf.openrocket.util.Coordinate;
-import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * This class contains various integration tests that simulate user actions that
- * might be performed.
- */
-public class IntegrationTest extends BaseTestCase {
-
- private OpenRocketDocument document;
- private Action undoAction, redoAction;
-
- private AerodynamicCalculator aeroCalc = new BarrowmanCalculator();
- private MassCalculator massCalc = new BasicMassCalculator();
- private Configuration config;
- private FlightConditions conditions;
-
-
- @BeforeClass
- public static void initialize() {
- ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {
- @Override
- protected void loadMotors() {
- GeneralMotorLoader loader = new GeneralMotorLoader();
- InputStream is = this.getClass().getResourceAsStream("Estes_A8.rse");
- assertNotNull("Problem in unit test, cannot find Estes_A8.rse", is);
- try {
- for (Motor m : loader.load(is, "Estes_A8.rse")) {
- addMotor((ThrustCurveMotor) m);
- }
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- fail("IOException: " + e);
- }
- }
- };
- db.startLoading();
- assertEquals(1, db.getMotorSets().size());
- Application.setMotorSetDatabase(db);
- Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
- }
-
- /**
- * Tests loading a rocket design, modifying it, simulating it and the undo/redo
- * mechanism in various combinations.
- */
- @Test
- public void test1() throws RocketLoadException, IOException, SimulationException {
- System.setProperty("openrocket.unittest", "true");
-
- // Load the rocket
- GeneralRocketLoader loader = new GeneralRocketLoader();
- InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
- assertNotNull("Problem in unit test, cannot find simplerocket.ork", is);
- document = loader.load(is);
- is.close();
-
- undoAction = UndoRedoAction.newUndoAction(document );
- redoAction = UndoRedoAction.newRedoAction(document);
- config = document.getSimulation(0).getConfiguration();
- conditions = new FlightConditions(config);
-
-
- // Test undo state
- checkUndoState(null, null);
-
-
- // Compute cg+cp + altitude
- checkCgCp(0.248, 0.0645, 0.320, 12.0);
- checkAlt(48.2);
-
-
- // Mass modification
- document.addUndoPosition("Modify mass");
- checkUndoState(null, null);
- massComponent().setComponentMass(0.01);
- checkUndoState("Modify mass", null);
-
-
- // Check cg+cp + altitude
- checkCgCp(0.230, 0.0745, 0.320, 12.0);
- checkAlt(37.2);
-
-
- // Non-change
- document.addUndoPosition("No change");
- checkUndoState("Modify mass", null);
-
-
- // Non-funcitonal change
- document.addUndoPosition("Name change");
- checkUndoState("Modify mass", null);
- massComponent().setName("Foobar component");
- checkUndoState("Name change", null);
-
-
- // Check cg+cp
- checkCgCp(0.230, 0.0745, 0.320, 12.0);
-
-
- // Aerodynamic modification
- document.addUndoPosition("Remove component");
- checkUndoState("Name change", null);
- document.getRocket().getChild(0).removeChild(0);
- checkUndoState("Remove component", null);
-
-
- // Check cg+cp + altitude
- checkCgCp(0.163, 0.0613, 0.275, 9.95);
- checkAlt(45.0);
-
-
- // Undo "Remove component" change
- undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
- assertTrue(document.getRocket().getChild(0).getChild(0) instanceof NoseCone);
- checkUndoState("Name change", "Remove component");
-
-
- // Check cg+cp + altitude
- checkCgCp(0.230, 0.0745, 0.320, 12.0);
- checkAlt(37.2);
-
-
- // Undo "Name change" change
- undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
- assertEquals("Extra mass", massComponent().getName());
- checkUndoState("Modify mass", "Name change");
-
-
- // Check cg+cp
- checkCgCp(0.230, 0.0745, 0.320, 12.0);
-
-
- // Undo "Modify mass" change
- undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
- assertEquals(0, massComponent().getComponentMass(), 0);
- checkUndoState(null, "Modify mass");
-
-
- // Check cg+cp + altitude
- checkCgCp(0.248, 0.0645, 0.320, 12.0);
- checkAlt(48.2);
-
-
- // Redo "Modify mass" change
- redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
- assertEquals(0.010, massComponent().getComponentMass(), 0.00001);
- checkUndoState("Modify mass", "Name change");
-
-
- // Check cg+cp + altitude
- checkCgCp(0.230, 0.0745, 0.320, 12.0);
- checkAlt(37.2);
-
-
- // Mass modification
- document.addUndoPosition("Modify mass2");
- checkUndoState("Modify mass", "Name change");
- massComponent().setComponentMass(0.015);
- checkUndoState("Modify mass2", null);
-
-
- // Check cg+cp + altitude
- checkCgCp(0.223, 0.0795, 0.320, 12.0);
- checkAlt(32.7);
-
-
- // Perform component movement
- document.startUndo("Move component");
- document.getRocket().freeze();
- RocketComponent bodytube = document.getRocket().getChild(0).getChild(1);
- RocketComponent innertube = bodytube.getChild(2);
- RocketComponent engineblock = innertube.getChild(0);
- assertTrue(innertube.removeChild(engineblock));
- bodytube.addChild(engineblock, 0);
- checkUndoState("Modify mass2", null);
- document.getRocket().thaw();
- checkUndoState("Move component", null);
- document.stopUndo();
-
-
- // Check cg+cp + altitude
- checkCgCp(0.221, 0.0797, 0.320, 12.0);
- checkAlt(32.7);
-
-
- // Modify mass without setting undo description
- massComponent().setComponentMass(0.020);
- checkUndoState("Modify mass2", null);
-
-
- // Check cg+cp + altitude
- checkCgCp(0.215, 0.0847, 0.320, 12.0);
- checkAlt(29.0);
-
-
- // Undo "Modify mass2" change
- undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
- assertEquals(0.015, massComponent().getComponentMass(), 0.0000001);
- checkUndoState("Move component", "Modify mass2");
-
-
- // Check cg+cp + altitude
- checkCgCp(0.221, 0.0797, 0.320, 12.0);
- checkAlt(32.7);
-
-
- // Undo "Move component" change
- undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
- assertTrue(document.getRocket().getChild(0).getChild(1).getChild(2).getChild(0) instanceof EngineBlock);
- checkUndoState("Modify mass2", "Move component");
-
-
- // Check cg+cp + altitude
- checkCgCp(0.223, 0.0795, 0.320, 12.0);
- checkAlt(32.7);
-
-
- // Redo "Move component" change
- redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
- assertTrue(document.getRocket().getChild(0).getChild(1).getChild(0) instanceof EngineBlock);
- checkUndoState("Move component", "Modify mass2");
-
-
- // Check cg+cp + altitude
- checkCgCp(0.221, 0.0797, 0.320, 12.0);
- checkAlt(32.7);
-
-
- }
-
- private String massComponentID = null;
-
- private MassComponent massComponent() {
- if (massComponentID == null) {
- massComponentID = document.getRocket().getChild(0).getChild(1).getChild(0).getID();
- }
- return (MassComponent) document.getRocket().findComponent(massComponentID);
- }
-
-
- private void checkUndoState(String undoDesc, String redoDesc) {
- if (undoDesc == null) {
- assertEquals("Undo", undoAction.getValue(Action.NAME));
- assertFalse(undoAction.isEnabled());
- } else {
- assertEquals("Undo (" + undoDesc + ")", undoAction.getValue(Action.NAME));
- assertTrue(undoAction.isEnabled());
- }
- if (redoDesc == null) {
- assertEquals("Redo", redoAction.getValue(Action.NAME));
- assertFalse(redoAction.isEnabled());
- } else {
- assertEquals("Redo (" + redoDesc + ")", redoAction.getValue(Action.NAME));
- assertTrue(redoAction.isEnabled());
- }
- }
-
-
- private void checkCgCp(double cgx, double mass, double cpx, double cna) {
- Coordinate cg, cp;
-
- cg = massCalc.getCG(config, MassCalcType.LAUNCH_MASS);
- assertEquals(cgx, cg.x, 0.001);
- assertEquals(mass, cg.weight, 0.0005);
-
- cp = aeroCalc.getWorstCP(config, conditions, null);
- assertEquals(cpx, cp.x, 0.001);
- assertEquals(cna, cp.weight, 0.1);
- }
-
-
- private void checkAlt(double expected) throws SimulationException {
- Simulation simulation = document.getSimulation(0);
- double actual;
-
- // Simulate + check altitude
- simulation.simulate();
- actual = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
- assertEquals(expected, actual, 0.5);
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.arch;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-
-import org.junit.Test;
-
-/*
- * Note: These tests have not been tested on Windows, they might fail there
- * due to a different directory separator character.
- */
-public class TestSystemInfo {
-
- private String osname;
- private String userhome;
-
-
- public void setup() {
- this.osname = System.getProperty("os.name");
- this.userhome = System.getProperty("user.home");
- }
-
- public void tearDown() {
- System.setProperty("os.name", this.osname);
- System.setProperty("user.home", this.userhome);
- }
-
- @Test
- public void testWindows() {
- setup();
-
- System.setProperty("os.name", "Windows Me");
- System.setProperty("user.home", "C:/Users/my user");
- assertEquals(SystemInfo.Platform.WINDOWS, SystemInfo.getPlatform());
- if (System.getenv("APPDATA") != null) {
- assertEquals(new File(System.getenv("APPDATA") + "/OpenRocket/"), SystemInfo.getUserApplicationDirectory());
- } else {
- assertEquals(new File("C:/Users/my user/OpenRocket/"), SystemInfo.getUserApplicationDirectory());
- }
-
- tearDown();
- }
-
- @Test
- public void testMacOS() {
- setup();
-
- System.setProperty("os.name", "Mac OS X");
- System.setProperty("user.home", "/Users/My User");
- assertEquals(SystemInfo.Platform.MAC_OS, SystemInfo.getPlatform());
- assertEquals(new File("/Users/My User/Library/Application Support/OpenRocket/"),
- SystemInfo.getUserApplicationDirectory());
-
- tearDown();
- }
-
- @Test
- public void testUnix() {
- setup();
-
- System.setProperty("user.home", "/home/myuser");
- for (String os : new String[] { "Linux", "Solaris", "Foobar" }) {
- System.setProperty("os.name", os);
-
- assertEquals(SystemInfo.Platform.UNIX, SystemInfo.getPlatform());
- assertEquals(new File("/home/myuser/.openrocket"), SystemInfo.getUserApplicationDirectory());
- }
-
- tearDown();
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.communication;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-
-import net.sf.openrocket.util.BuildProperties;
-
-import org.junit.Test;
-
-
-public class BugReportTest {
-
- private HttpURLConnectionMock setup() {
- HttpURLConnectionMock connection = new HttpURLConnectionMock();
- Communicator.setConnectionSource(new ConnectionSourceStub(connection));
-
- connection.setUseCaches(true);
- return connection;
- }
-
- private void check(HttpURLConnectionMock connection) {
- assertEquals(Communicator.BUG_REPORT_URL, connection.getTrueUrl());
- assertTrue(connection.getConnectTimeout() > 0);
- assertEquals(BuildProperties.getVersion(), connection.getRequestProperty("X-OpenRocket-Version"));
- assertTrue(connection.getInstanceFollowRedirects());
- assertEquals("POST", connection.getRequestMethod());
- assertFalse(connection.getUseCaches());
- }
-
-
- @Test
- public void testBugReportSuccess() throws IOException {
- HttpURLConnectionMock connection = setup();
- connection.setResponseCode(Communicator.BUG_REPORT_RESPONSE_CODE);
-
- String message =
- "MyMessage\n"+
- "is important\n"+
- "h\u00e4h?";
-
- BugReporter.sendBugReport(message);
-
- check(connection);
-
- String msg = connection.getOutputStreamString();
- assertTrue(msg.indexOf("version=" + BuildProperties.getVersion()) >= 0);
- assertTrue(msg.indexOf(Communicator.encode(message)) >= 0);
- }
-
-
- @Test
- public void testBugReportFailure() throws IOException {
- HttpURLConnectionMock connection = setup();
- connection.setResponseCode(200);
-
- String message =
- "MyMessage\n"+
- "is important\n"+
- "h\u00e4h?";
-
- try {
- BugReporter.sendBugReport(message);
- fail("Exception did not occur");
- } catch (IOException e) {
- // Success
- }
-
- check(connection);
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.communication;
-
-import java.io.IOException;
-import java.net.HttpURLConnection;
-
-public class ConnectionSourceStub implements ConnectionSource {
-
- private final HttpURLConnection connection;
-
- public ConnectionSourceStub(HttpURLConnection connection) {
- this.connection = connection;
- }
-
- @Override
- public HttpURLConnection getConnection(String url) throws IOException {
- if (connection instanceof HttpURLConnectionMock) {
- ((HttpURLConnectionMock)connection).setTrueUrl(url);
- }
- return connection;
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.communication;
-
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.ProtocolException;
-import java.net.URL;
-import java.security.Permission;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import net.sf.openrocket.util.BugException;
-
-public class HttpURLConnectionMock extends HttpURLConnection {
-
- private static final URL MOCK_URL;
- static {
- try {
- MOCK_URL = new URL("http://localhost/");
- } catch (MalformedURLException e) {
- throw new BugException(e);
- }
- }
-
- private volatile boolean instanceFollowRedirects = false;
- private volatile String requestMethod = "";
- private volatile int responseCode;
- private Map<String, String> requestProperties = new HashMap<String, String>();
- private volatile int connectTimeout = -1;
- private volatile String contentEncoding = "";
-
- private volatile boolean doInput = false;
- private volatile boolean doOutput = false;
-
- private volatile byte[] content = null;
- private volatile String contentType = null;
- private volatile boolean useCaches = false;
-
-
- private volatile InputStream inputStream = null;
- private volatile ByteArrayOutputStream outputStream = null;
-
- private volatile String trueUrl = null;
-
-
- private volatile boolean connected = false;
- private volatile int connectionDelay = 0;
-
- private volatile boolean failed = false;
-
-
-
-
- public HttpURLConnectionMock() {
- super(MOCK_URL);
- }
-
- public HttpURLConnectionMock(URL u) {
- super(u);
- }
-
-
-
- public String getTrueUrl() {
- return trueUrl;
- }
-
- public void setTrueUrl(String url) {
- assertNull(this.trueUrl);
- this.trueUrl = url;
- }
-
-
- public boolean hasFailed() {
- return failed;
- }
-
-
- public void setConnectionDelay(int delay) {
- this.connectionDelay = delay;
- }
-
-
-
- @Override
- public void connect() {
- if (!connected) {
- try {
- Thread.sleep(connectionDelay);
- } catch (InterruptedException e) {
- }
- connected = true;
- }
- }
-
- @Override
- public void disconnect() {
-
- }
-
- @Override
- public boolean usingProxy() {
- return false;
- }
-
-
-
-
- @Override
- public boolean getInstanceFollowRedirects() {
- return this.instanceFollowRedirects;
- }
-
- @Override
- public void setInstanceFollowRedirects(boolean followRedirects) {
- assertFalse(connected);
- this.instanceFollowRedirects = followRedirects;
- }
-
- @Override
- public String getRequestMethod() {
- return this.requestMethod;
- }
-
- @Override
- public void setRequestMethod(String method) throws ProtocolException {
- assertFalse(connected);
- this.requestMethod = method;
- }
-
- @Override
- public int getResponseCode() throws IOException {
- connect();
- return this.responseCode;
- }
-
- public void setResponseCode(int code) {
- this.responseCode = code;
- }
-
-
- @Override
- public void addRequestProperty(String key, String value) {
- assertFalse(connected);
- assertFalse(this.requestProperties.containsKey(key.toLowerCase()));
- this.requestProperties.put(key.toLowerCase(), value);
- }
-
-
- @Override
- public void setRequestProperty(String key, String value) {
- assertFalse(connected);
- this.requestProperties.put(key.toLowerCase(), value);
- }
-
-
- @Override
- public String getRequestProperty(String key) {
- return this.requestProperties.get(key.toLowerCase());
- }
-
-
- @Override
- public int getConnectTimeout() {
- return this.connectTimeout;
- }
-
- @Override
- public void setConnectTimeout(int timeout) {
- assertFalse(connected);
- this.connectTimeout = timeout;
- }
-
-
-
- @Override
- public String getContentEncoding() {
- connect();
- return this.contentEncoding;
- }
-
- public void setContentEncoding(String encoding) {
- this.contentEncoding = encoding;
- }
-
-
-
- @Override
- public int getContentLength() {
- connect();
- if (content == null)
- return 0;
- return content.length;
- }
-
- public void setContent(byte[] content) {
- this.content = content;
- }
-
- public void setContent(String content) {
- try {
- this.content = content.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- fail("UTF-8");
- }
- }
-
-
- @Override
- public String getContentType() {
- connect();
- return this.contentType;
- }
-
- public void setContentType(String type) {
- this.contentType = type;
- }
-
-
-
- @Override
- public boolean getDoInput() {
- return this.doInput;
- }
-
-
- @Override
- public void setDoInput(boolean doinput) {
- assertFalse(connected);
- this.doInput = doinput;
- }
-
-
- @Override
- public boolean getDoOutput() {
- return this.doOutput;
- }
-
-
- @Override
- public void setDoOutput(boolean dooutput) {
- assertFalse(connected);
- this.doOutput = dooutput;
- }
-
-
- @Override
- public InputStream getInputStream() throws IOException {
- assertTrue(doInput);
- assertNull(inputStream);
- assertNotNull(content);
-
- connect();
- inputStream = new ByteArrayInputStream(content);
- return inputStream;
- }
-
-
- @Override
- public OutputStream getOutputStream() throws IOException {
- assertTrue(doOutput);
- assertNull(outputStream);
- outputStream = new ByteArrayOutputStream();
- return outputStream;
- }
-
- public byte[] getOutputStreamData() {
- return outputStream.toByteArray();
- }
-
- public String getOutputStreamString() {
- try {
- return outputStream.toString("UTF-8");
- } catch (UnsupportedEncodingException e) {
- fail("UTF-8");
- return null;
- }
- }
-
-
-
- @Override
- public void setUseCaches(boolean usecaches) {
- assertFalse(connected);
- this.useCaches = usecaches;
- }
-
-
-
- @Override
- public boolean getUseCaches() {
- return this.useCaches;
- }
-
-
-
-
-
-
-
-
- private void assertNull(Object o) {
- try {
- org.junit.Assert.assertNull(o);
- } catch (AssertionError e) {
- failed = true;
- throw e;
- }
- }
-
- private void assertNotNull(Object o) {
- try {
- org.junit.Assert.assertNotNull(o);
- } catch (AssertionError e) {
- failed = true;
- throw e;
- }
- }
-
- private void assertTrue(boolean o) {
- try {
- org.junit.Assert.assertTrue(o);
- } catch (AssertionError e) {
- failed = true;
- throw e;
- }
- }
-
- private void assertFalse(boolean o) {
- try {
- org.junit.Assert.assertFalse(o);
- } catch (AssertionError e) {
- failed = true;
- throw e;
- }
- }
-
- private void fail(String msg) {
- failed = true;
- org.junit.Assert.fail(msg);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- @Override
- public InputStream getErrorStream() {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public String getHeaderField(int n) {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public long getHeaderFieldDate(String name, long Default) {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public String getHeaderFieldKey(int n) {
- throw new UnsupportedOperationException();
- }
-
-
- @Override
- public Permission getPermission() throws IOException {
- throw new UnsupportedOperationException();
- }
-
-
- @Override
- public String getResponseMessage() throws IOException {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public void setChunkedStreamingMode(int chunklen) {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public void setFixedLengthStreamingMode(int contentLength) {
- throw new UnsupportedOperationException();
- }
-
-
-
-
-
- @Override
- public boolean getAllowUserInteraction() {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public Object getContent() throws IOException {
- throw new UnsupportedOperationException();
- }
-
-
-
- @SuppressWarnings("unchecked")
- @Override
- public Object getContent(Class[] classes) throws IOException {
- throw new UnsupportedOperationException();
- }
-
-
- @Override
- public long getDate() {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public boolean getDefaultUseCaches() {
- throw new UnsupportedOperationException();
- }
-
-
- @Override
- public long getExpiration() {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public String getHeaderField(String name) {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public int getHeaderFieldInt(String name, int Default) {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public Map<String, List<String>> getHeaderFields() {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public long getIfModifiedSince() {
- throw new UnsupportedOperationException();
- }
-
-
- @Override
- public long getLastModified() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getReadTimeout() {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public Map<String, List<String>> getRequestProperties() {
- throw new UnsupportedOperationException();
- }
-
-
- @Override
- public URL getURL() {
- throw new UnsupportedOperationException();
- }
-
-
-
- @Override
- public void setAllowUserInteraction(boolean allowuserinteraction) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setDefaultUseCaches(boolean defaultusecaches) {
- throw new UnsupportedOperationException();
- }
-
-
- @Override
- public void setIfModifiedSince(long ifmodifiedsince) {
- throw new UnsupportedOperationException();
- }
-
-
- @Override
- public void setReadTimeout(int timeout) {
- throw new UnsupportedOperationException();
- }
-
-
-
-
-
- @Override
- public String toString() {
- throw new UnsupportedOperationException();
- }
-
-
-
-
-}
+++ /dev/null
-package net.sf.openrocket.communication;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Random;
-
-import net.sf.openrocket.util.BuildProperties;
-import net.sf.openrocket.util.ComparablePair;
-import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
-
-import org.junit.Test;
-
-public class UpdateInfoTest extends BaseTestCase {
-
- /** The connection delay */
- private static final int DELAY = 100;
-
- /** How much long does the test allow it to take */
- private static final int ALLOWANCE = 2000;
-
-
- private HttpURLConnectionMock setup() {
- HttpURLConnectionMock connection = new HttpURLConnectionMock();
- Communicator.setConnectionSource(new ConnectionSourceStub(connection));
-
- connection.setConnectionDelay(DELAY);
- connection.setUseCaches(true);
- connection.setContentType("text/plain");
- return connection;
- }
-
- private void check(HttpURLConnectionMock connection) {
- assertEquals(Communicator.UPDATE_INFO_URL + "?version=" + BuildProperties.getVersion(),
- connection.getTrueUrl());
- assertTrue(connection.getConnectTimeout() > 0);
- assertEquals(BuildProperties.getVersion() + "+" + BuildProperties.getBuildSource(),
- connection.getRequestProperty("X-OpenRocket-Version"));
- assertNotNull(connection.getRequestProperty("X-OpenRocket-Country"));
- assertNotNull(connection.getRequestProperty("X-OpenRocket-ID"));
- assertNotNull(connection.getRequestProperty("X-OpenRocket-OS"));
- assertNotNull(connection.getRequestProperty("X-OpenRocket-Java"));
- assertTrue(connection.getInstanceFollowRedirects());
- assertEquals("GET", connection.getRequestMethod());
- assertFalse(connection.getUseCaches());
- }
-
-
- @Test
- public void testUpdateAvailable() throws IOException {
- HttpURLConnectionMock connection = setup();
- connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
-
- String content =
- "Version: 6.6.6pre A \n" +
- "Extra: information\n" +
- "100:hundred\n" +
- "50: m\u00e4 \n\n" +
- "1: one\n" +
- "-2: none";
- connection.setContent(content);
-
- UpdateInfoRetriever retriever = new UpdateInfoRetriever();
- retriever.start();
-
- // Info is null while processing
- assertNull(retriever.getUpdateInfo());
-
- waitfor(retriever);
- assertFalse(connection.hasFailed());
-
- UpdateInfo info = retriever.getUpdateInfo();
- assertNotNull(info);
-
- check(connection);
-
- assertEquals("6.6.6pre A", info.getLatestVersion());
-
- List<ComparablePair<Integer, String>> updates = info.getUpdates();
- assertEquals(3, updates.size());
- Collections.sort(updates);
- assertEquals(1, (int)updates.get(0).getU());
- assertEquals("one", updates.get(0).getV());
- assertEquals(50, (int)updates.get(1).getU());
- assertEquals("m\u00e4", updates.get(1).getV());
- assertEquals(100, (int)updates.get(2).getU());
- assertEquals("hundred", updates.get(2).getV());
- }
-
-
-
-
- @Test
- public void testUpdateNotAvailable() throws IOException {
- HttpURLConnectionMock connection = setup();
- connection.setResponseCode(Communicator.UPDATE_INFO_NO_UPDATE_CODE);
-
- String content =
- "Version: 6.6.6pre A \n" +
- "Extra: information\n" +
- "100:hundred\n" +
- "50: m\u00e4 \n\n" +
- "1: one\n" +
- "-2: none";
- connection.setContent(content);
-
- UpdateInfoRetriever retriever = new UpdateInfoRetriever();
- retriever.start();
-
- // Info is null while processing
- assertNull(retriever.getUpdateInfo());
-
- waitfor(retriever);
- assertFalse(connection.hasFailed());
-
- UpdateInfo info = retriever.getUpdateInfo();
- assertNotNull(info);
-
- check(connection);
-
- assertEquals(BuildProperties.getVersion(), info.getLatestVersion());
- assertEquals(0, info.getUpdates().size());
- }
-
-
-
- @Test
- public void testInvalidResponses() {
- HttpURLConnectionMock connection = setup();
- connection.setResponseCode(404);
- connection.setContent("Version: 1.2.3");
-
- UpdateInfoRetriever retriever = new UpdateInfoRetriever();
- retriever.start();
- assertNull(retriever.getUpdateInfo());
- waitfor(retriever);
- assertFalse(connection.hasFailed());
- assertNull(retriever.getUpdateInfo());
- check(connection);
-
-
- connection = setup();
- connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
- connection.setContentType("text/xml");
-
- retriever = new UpdateInfoRetriever();
- retriever.start();
- assertNull(retriever.getUpdateInfo());
- waitfor(retriever);
- assertFalse(connection.hasFailed());
- assertNull(retriever.getUpdateInfo());
- check(connection);
-
-
-
- connection = setup();
- connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
- String content =
- "100:hundred\n" +
- "50: m\u00e4 \n\n" +
- "1: one\n";
- connection.setContent(content);
-
- retriever = new UpdateInfoRetriever();
- retriever.start();
- assertNull(retriever.getUpdateInfo());
- waitfor(retriever);
- assertFalse(connection.hasFailed());
- assertNull(retriever.getUpdateInfo());
- check(connection);
-
-
- connection = setup();
- connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
- connection.setContent(new byte[0]);
-
- retriever = new UpdateInfoRetriever();
- retriever.start();
- assertNull(retriever.getUpdateInfo());
- waitfor(retriever);
- assertFalse(connection.hasFailed());
- assertNull(retriever.getUpdateInfo());
- check(connection);
-
- }
-
- @Test
- public void testRandomInputData() {
-
- Random rnd = new Random();
- for (int i=0; i<10; i++) {
- int size = (int) ((1 + 0.3 * rnd.nextGaussian()) * Math.pow(i, 6));
- byte[] buf = new byte[size];
- rnd.nextBytes(buf);
-
- HttpURLConnectionMock connection = setup();
- connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
- connection.setContent(buf);
-
- UpdateInfoRetriever retriever = new UpdateInfoRetriever();
- retriever.start();
- assertNull(retriever.getUpdateInfo());
- waitfor(retriever);
- assertFalse(connection.hasFailed());
- assertNull(retriever.getUpdateInfo());
- check(connection);
- }
-
- }
-
-
-
- private void waitfor(UpdateInfoRetriever retriever) {
- long t = System.currentTimeMillis();
-
- while (retriever.isRunning()) {
- if (System.currentTimeMillis() >= t+ALLOWANCE) {
- fail("retriever took too long to respond");
- }
-
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) { }
- }
-
- System.out.println("Waiting took " + (System.currentTimeMillis()-t) + " ms");
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.database;
-
-import static org.junit.Assert.*;
-
-import java.util.List;
-
-import net.sf.openrocket.motor.Manufacturer;
-import net.sf.openrocket.motor.Motor;
-import net.sf.openrocket.motor.ThrustCurveMotor;
-import net.sf.openrocket.util.Coordinate;
-
-import org.junit.Test;
-
-
-public class MotorSetDatabaseTest {
-
- @Test
- public void testMotorLoading() {
-
- ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(true) {
- @Override
- protected void loadMotors() {
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- this.addMotor(new ThrustCurveMotor(Manufacturer.getManufacturer("A"),
- "Foo", "Desc", Motor.Type.SINGLE, new double[] { 0 },
- 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
- new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}));
- this.addMotor(new ThrustCurveMotor(Manufacturer.getManufacturer("A"),
- "Bar", "Desc", Motor.Type.SINGLE, new double[] { 0 },
- 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
- new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}));
- this.addMotor(new ThrustCurveMotor(Manufacturer.getManufacturer("A"),
- "Foo", "Desc", Motor.Type.UNKNOWN, new double[] { 0 },
- 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
- new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}));
- }
- };
-
- assertFalse(db.isLoaded());
- db.startLoading();
- assertFalse(db.isLoaded());
- List<ThrustCurveMotorSet> list = db.getMotorSets();
- assertTrue(db.isLoaded());
-
- assertEquals(2, list.size());
- assertEquals(1, list.get(0).getMotors().size());
- assertEquals(1, list.get(1).getMotors().size());
- assertEquals("Bar", list.get(0).getMotors().get(0).getDesignation());
- assertEquals("Foo", list.get(1).getMotors().get(0).getDesignation());
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.database;
-
-import static org.junit.Assert.*;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import net.sf.openrocket.motor.Manufacturer;
-import net.sf.openrocket.motor.Motor;
-import net.sf.openrocket.motor.ThrustCurveMotor;
-import net.sf.openrocket.util.Coordinate;
-
-import org.junit.Test;
-
-public class ThrustCurveMotorSetTest {
-
-
- private static final ThrustCurveMotor motor1 = new ThrustCurveMotor(
- Manufacturer.getManufacturer("A"),
- "F12X", "Desc", Motor.Type.UNKNOWN, new double[] { },
- 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
- new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL});
-
- private static final ThrustCurveMotor motor2 = new ThrustCurveMotor(
- Manufacturer.getManufacturer("A"),
- "F12H", "Desc", Motor.Type.SINGLE, new double[] { 5 },
- 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0},
- new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL});
-
- private static final ThrustCurveMotor motor3 = new ThrustCurveMotor(
- Manufacturer.getManufacturer("A"),
- "F12", "Desc", Motor.Type.UNKNOWN, new double[] { 0, Motor.PLUGGED },
- 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 2, 0},
- new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL});
-
- private static final ThrustCurveMotor motor4 = new ThrustCurveMotor(
- Manufacturer.getManufacturer("A"),
- "F12", "Desc", Motor.Type.HYBRID, new double[] { 0 },
- 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 2, 0},
- new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL});
-
-
- @Test
- public void testSimplifyDesignation() {
- assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("J115"));
- assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation(" J115 "));
- assertEquals("H115", ThrustCurveMotorSet.simplifyDesignation("241H115-KS"));
- assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("384 J115"));
- assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("384-J115"));
- assertEquals("A2", ThrustCurveMotorSet.simplifyDesignation("A2T"));
- assertEquals("1/2A2T", ThrustCurveMotorSet.simplifyDesignation("1/2A2T"));
- assertEquals("Micro Maxx II", ThrustCurveMotorSet.simplifyDesignation("Micro Maxx II"));
- }
-
- @Test
- public void testAdding() {
- ThrustCurveMotorSet set = new ThrustCurveMotorSet();
-
- // Test empty set
- assertNull(set.getManufacturer());
- assertEquals(0, set.getMotors().size());
-
- // Add motor1
- assertTrue(set.matches(motor1));
- set.addMotor(motor1);
- assertEquals(motor1.getManufacturer(), set.getManufacturer());
- assertEquals(motor1.getDesignation(), set.getDesignation());
- assertEquals(Motor.Type.UNKNOWN, set.getType());
- assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
- assertEquals(motor1.getLength(), set.getLength(), 0.00001);
- assertEquals(1, set.getMotors().size());
- assertEquals(motor1, set.getMotors().get(0));
- assertEquals(Collections.emptyList(), set.getDelays());
-
- // Add motor1 again
- assertTrue(set.matches(motor1));
- set.addMotor(motor1);
- assertEquals(motor1.getManufacturer(), set.getManufacturer());
- assertEquals(motor1.getDesignation(), set.getDesignation());
- assertEquals(Motor.Type.UNKNOWN, set.getType());
- assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
- assertEquals(motor1.getLength(), set.getLength(), 0.00001);
- assertEquals(1, set.getMotors().size());
- assertEquals(motor1, set.getMotors().get(0));
- assertEquals(Collections.emptyList(), set.getDelays());
-
- // Add motor2
- assertTrue(set.matches(motor2));
- set.addMotor(motor2);
- assertEquals(motor1.getManufacturer(), set.getManufacturer());
- assertEquals(motor3.getDesignation(), set.getDesignation());
- assertEquals(Motor.Type.SINGLE, set.getType());
- assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
- assertEquals(motor1.getLength(), set.getLength(), 0.00001);
- assertEquals(2, set.getMotors().size());
- assertEquals(motor2, set.getMotors().get(0));
- assertEquals(motor1, set.getMotors().get(1));
- assertEquals(Arrays.asList(5.0), set.getDelays());
-
- // Add motor3
- assertTrue(set.matches(motor3));
- set.addMotor(motor3);
- assertEquals(motor1.getManufacturer(), set.getManufacturer());
- assertEquals(motor3.getDesignation(), set.getDesignation());
- assertEquals(Motor.Type.SINGLE, set.getType());
- assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
- assertEquals(motor1.getLength(), set.getLength(), 0.00001);
- assertEquals(3, set.getMotors().size());
- assertEquals(motor3, set.getMotors().get(0));
- assertEquals(motor2, set.getMotors().get(1));
- assertEquals(motor1, set.getMotors().get(2));
- assertEquals(Arrays.asList(0.0, 5.0, Motor.PLUGGED), set.getDelays());
-
- // Test that adding motor4 fails
- assertFalse(set.matches(motor4));
- try {
- set.addMotor(motor4);
- fail("Did not throw exception");
- } catch (IllegalArgumentException e) {
- }
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.file.iterator;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.IOException;
-
-import org.junit.Test;
-
-public class TestDirectoryIterator {
-
- @Test
- public void testDirectoryIterator() throws IOException {
- DirectoryIterator iterator = new DirectoryIterator(new File("test/net/sf/openrocket/file"), new FileFilter() {
- @Override
- public boolean accept(File pathname) {
- return pathname.getName().matches("^Test(Directory|File)Iterator.java");
- }
- }, true);
-
- while (iterator.hasNext()) {
- System.out.println("" + iterator.next());
- }
-
- }
-}
+++ /dev/null
-package net.sf.openrocket.file.iterator;
-
-import static org.junit.Assert.*;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-import net.sf.openrocket.util.Pair;
-
-import org.junit.Test;
-
-public class TestFileIterator {
-
- @Test
- public void testFileIterator() {
- final Pair<String, InputStream> one = new Pair<String, InputStream>("one", new ByteArrayInputStream(new byte[] { 1 }));
- final Pair<String, InputStream> two = new Pair<String, InputStream>("two", new ByteArrayInputStream(new byte[] { 2 }));
-
- FileIterator iterator = new FileIterator() {
- private int count = 0;
-
- @Override
- protected Pair<String, InputStream> findNext() {
- count++;
- switch (count) {
- case 1:
- return one;
- case 2:
- return two;
- default:
- return null;
- }
- }
- };
-
- assertTrue(iterator.hasNext());
- assertEquals(one, iterator.next());
- assertEquals(two, iterator.next());
- assertFalse(iterator.hasNext());
- }
-}
+++ /dev/null
-package net.sf.openrocket.file.motor;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.List;
-
-import net.sf.openrocket.motor.Motor;
-import net.sf.openrocket.motor.MotorDigest;
-import net.sf.openrocket.motor.ThrustCurveMotor;
-
-import org.junit.Test;
-
-public class TestMotorLoader {
-
- @Test
- public void testGeneralMotorLoader() throws IOException {
- MotorLoader loader = new GeneralMotorLoader();
-
- test(loader, "test1.eng", "c056cf25df6751f7bb8a94bc4f64750f");
- test(loader, "test2.rse", "b2fe203ee319ae28b9ccdad26a8f21de");
- test(loader, "test.zip", "b2fe203ee319ae28b9ccdad26a8f21de", "c056cf25df6751f7bb8a94bc4f64750f");
-
- }
-
- @Test
- public void testRASPMotorLoader() throws IOException {
- test(new RASPMotorLoader(), "test1.eng", "c056cf25df6751f7bb8a94bc4f64750f");
- }
-
- @Test
- public void testRocksimMotorLoader() throws IOException {
- test(new RockSimMotorLoader(), "test2.rse", "b2fe203ee319ae28b9ccdad26a8f21de");
- }
-
- @Test
- public void testZipMotorLoader() throws IOException {
- test(new ZipFileMotorLoader(), "test.zip", "b2fe203ee319ae28b9ccdad26a8f21de", "c056cf25df6751f7bb8a94bc4f64750f");
- }
-
-
- private void test(MotorLoader loader, String file, String... digests) throws IOException {
- List<Motor> motors;
-
- InputStream is = this.getClass().getResourceAsStream(file);
- assertNotNull("File " + file + " not found", is);
- motors = loader.load(is, file);
- is.close();
- assertEquals(digests.length, motors.size());
-
- String[] d = new String[digests.length];
- for (int i = 0; i < motors.size(); i++) {
- d[i] = MotorDigest.digestMotor((ThrustCurveMotor) motors.get(i));
- }
-
- Arrays.sort(digests);
- Arrays.sort(d);
- assertTrue(Arrays.equals(d, digests));
- }
-
-}
+++ /dev/null
-D10 18 70 7 0.009800000000000001 0.0259 AT\r
- 0.0070 23.0\r
- 0.018 25.0\r
- 0.027 20.25\r
- 0.066 20.25\r
- 0.073 18.5\r
- 0.094 20.25\r
- 0.112 20.75\r
- 0.137 19.75\r
- 0.163 21.5\r
- 0.202 20.75\r
- 0.231 20.75\r
- 0.254 22.75\r
- 0.27 20.75\r
- 0.504 20.0\r
- 0.536 18.25\r
- 0.607 17.0\r
- 0.687 14.75\r
- 0.751 14.25\r
- 0.84 11.25\r
- 0.998 8.25\r
- 1.024 8.25\r
- 1.248 2.5\r
- 1.385 0.0\r
+++ /dev/null
-<engine-database>\r
- <engine-list>\r
- <engine mfg="Cesaroni Technology Inc." code="G115-13A" Type="reloadable" dia="38."\r
-len="127." initWt="195." propWt="61.8" delays="13" auto-calc-mass="1"\r
-auto-calc-cg="1" avgThrust="113.512" peakThrust="131.895" throatDia="0."\r
-exitDia="0." Itot="140.755" burn-time="1.24" massFrac="31.69" Isp="232.25"\r
-tDiv="10" tStep="-1." tFix="1" FDiv="10" FStep="-1." FFix="1" mDiv="10"\r
-mStep="-1." mFix="1" cgDiv="10" cgStep="-1." cgFix="1">\r
- <data>\r
- <eng-data t="0." f="0." m="61.8" cg="63.5"/>\r
- <eng-data t="0.00787402" f="10.3447" m="61.7821" cg="63.5"/>\r
- <eng-data t="0.0183727" f="117.671" m="61.4871" cg="63.5"/>\r
- <eng-data t="0.0209974" f="128.447" m="61.3453" cg="63.5"/>\r
- <eng-data t="0.0446194" f="131.895" m="59.9952" cg="63.5"/>\r
- <eng-data t="0.0577428" f="125.861" m="59.2526" cg="63.5"/>\r
- <eng-data t="0.0629921" f="119.395" m="58.97" cg="63.5"/>\r
- <eng-data t="0.0787402" f="113.792" m="58.1638" cg="63.5"/>\r
- <eng-data t="0.107612" f="115.947" m="56.7077" cg="63.5"/>\r
- <eng-data t="0.149606" f="118.964" m="54.542" cg="63.5"/>\r
- <eng-data t="0.188976" f="119.395" m="52.4819" cg="63.5"/>\r
- <eng-data t="0.233596" f="121.981" m="50.1176" cg="63.5"/>\r
- <eng-data t="0.278215" f="122.412" m="47.7237" cg="63.5"/>\r
- <eng-data t="0.322835" f="122.843" m="45.3213" cg="63.5"/>\r
- <eng-data t="0.380577" f="123.274" m="42.2014" cg="63.5"/>\r
- <eng-data t="0.440945" f="122.843" m="38.9398" cg="63.5"/>\r
- <eng-data t="0.480315" f="123.274" m="36.8126" cg="63.5"/>\r
- <eng-data t="0.540682" f="122.843" m="33.5509" cg="63.5"/>\r
- <eng-data t="0.590551" f="122.412" m="30.866" cg="63.5"/>\r
- <eng-data t="0.622047" f="120.688" m="29.1851" cg="63.5"/>\r
- <eng-data t="0.67979" f="120.257" m="26.1308" cg="63.5"/>\r
- <eng-data t="0.734908" f="119.395" m="23.231" cg="63.5"/>\r
- <eng-data t="0.790026" f="117.671" m="20.3625" cg="63.5"/>\r
- <eng-data t="0.845144" f="116.809" m="17.5253" cg="63.5"/>\r
- <eng-data t="0.88189" f="116.378" m="15.6442" cg="63.5"/>\r
- <eng-data t="0.929134" f="113.361" m="13.2615" cg="63.5"/>\r
- <eng-data t="0.979003" f="113.361" m="10.7794" cg="63.5"/>\r
- <eng-data t="1.0315" f="111.206" m="8.19152" cg="63.5"/>\r
- <eng-data t="1.07087" f="108.188" m="6.29532" cg="63.5"/>\r
- <eng-data t="1.11286" f="108.188" m="4.30052" cg="63.5"/>\r
- <eng-data t="1.16535" f="106.033" m="1.83186" cg="63.5"/>\r
- <eng-data t="1.18373" f="112.499" m="0.95044" cg="63.5"/>\r
- <eng-data t="1.18635" f="96.5506" m="0.829987" cg="63.5"/>\r
- <eng-data t="1.19685" f="81.0335" m="0.420696" cg="63.5"/>\r
- <eng-data t="1.2021" f="51.7235" m="0.267708" cg="63.5"/>\r
- <eng-data t="1.2126" f="30.172" m="0.0789575" cg="63.5"/>\r
- <eng-data t="1.21522" f="16.8101" m="0.0518866" cg="63.5"/>\r
- <eng-data t="1.21785" f="7.75853" m="0.0377303" cg="63.5"/>\r
- <eng-data t="1.24" f="0." m="0." cg="63.5"/>\r
- </data>\r
- </engine>\r
-</engine-list>\r
-</engine-database>\r
+++ /dev/null
-package net.sf.openrocket.file.rocksim.export;
-
-import net.sf.openrocket.document.OpenRocketDocument;
-import net.sf.openrocket.file.rocksim.importt.RocksimLoader;
-import net.sf.openrocket.file.rocksim.importt.RocksimLoaderTest;
-import net.sf.openrocket.file.rocksim.importt.RocksimTestBase;
-import org.junit.Assert;
-import org.junit.Test;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.Marshaller;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.StringWriter;
-
-/**
- */
-public class RocksimDocumentDTOTest extends RocksimTestBase {
-
- @Test
- public void testDTO() throws Exception {
- JAXBContext binder = JAXBContext.newInstance(RocksimDocumentDTO.class);
- Marshaller marshaller = binder.createMarshaller();
- marshaller.setProperty("jaxb.fragment", Boolean.TRUE);
-
- NoseConeDTO noseCone = new NoseConeDTO();
- noseCone.setBaseDia(10d);
- noseCone.setCalcCG(1.3d);
-
- StageDTO stage1 = new StageDTO();
- stage1.addExternalPart(noseCone);
-
- RocketDesignDTO design2 = new RocketDesignDTO();
- design2.setName("Test");
- design2.setStage3(stage1);
-
- RocksimDesignDTO design = new RocksimDesignDTO();
- design.setDesign(design2);
- RocksimDocumentDTO message = new RocksimDocumentDTO();
- message.setDesign(design);
-
-
- StringWriter stringWriter = new StringWriter();
- marshaller.marshal(message, stringWriter);
-
- String response = stringWriter.toString();
-
- System.err.println(response);
- }
-
- @Test
- public void testRoundTrip() throws Exception {
- OpenRocketDocument ord = RocksimLoaderTest.loadRocksimRocket3(new RocksimLoader());
-
- Assert.assertNotNull(ord);
- String result = new RocksimSaver().marshalToRocksim(ord);
-
-// System.err.println(result);
-
- File output = new File("rt.rkt");
- FileWriter fw = new FileWriter(output);
- fw.write(result);
- fw.flush();
- fw.close();
- }
-}
+++ /dev/null
-/*
- * BodyTubeHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.ExternalComponent;
-import net.sf.openrocket.rocketcomponent.Stage;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.HashMap;
-
-/**
- * BodyTubeHandler Tester.
- *
- */
-public class BodyTubeHandlerTest extends RocksimTestBase {
-
- /**
- * Method: constructor
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testConstructor() throws Exception {
-
- try {
- new BodyTubeHandler(null, new WarningSet());
- Assert.fail("Should have thrown IllegalArgumentException");
- }
- catch (IllegalArgumentException iae) {
- //success
- }
-
- Stage stage = new Stage();
- BodyTubeHandler handler = new BodyTubeHandler(stage, new WarningSet());
- BodyTube component = (BodyTube) getField(handler, "bodyTube");
- assertContains(component, stage.getChildren());
- }
-
- /**
- * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testOpenElement() throws Exception {
- Assert.assertEquals(PlainTextHandler.INSTANCE, new BodyTubeHandler(new Stage(), new WarningSet()).openElement(null, null, null));
- Assert.assertNotNull(new BodyTubeHandler(new Stage(), new WarningSet()).openElement("AttachedParts", null, null));
- }
-
- /**
- *
- * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testCloseElement() throws Exception {
- Stage stage = new Stage();
- BodyTubeHandler handler = new BodyTubeHandler(stage, new WarningSet());
- BodyTube component = (BodyTube) getField(handler, "bodyTube");
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("OD", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("OD", attributes, "0", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("OD", attributes, "75", warnings);
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
- handler.closeElement("OD", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("ID", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "0", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "75", warnings);
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Len", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("IsMotorMount", attributes, "1", warnings);
- Assert.assertTrue(component.isMotorMount());
- handler.closeElement("IsMotorMount", attributes, "0", warnings);
- Assert.assertFalse(component.isMotorMount());
- handler.closeElement("IsMotorMount", attributes, "foo", warnings);
- Assert.assertFalse(component.isMotorMount());
-
- handler.closeElement("EngineOverhang", attributes, "-1", warnings);
- Assert.assertEquals(-1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
- handler.closeElement("EngineOverhang", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
- handler.closeElement("EngineOverhang", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
- handler.closeElement("EngineOverhang", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("FinishCode", attributes, "-1", warnings);
- Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
- handler.closeElement("FinishCode", attributes, "100", warnings);
- Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
- handler.closeElement("FinishCode", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Name", attributes, "Test Name", warnings);
- Assert.assertEquals("Test Name", component.getName());
- }
-
- /**
- * Method: getComponent()
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testGetComponent() throws Exception {
- Assert.assertTrue(new BodyTubeHandler(new Stage(), new WarningSet()).getComponent() instanceof BodyTube);
- }
-
- /**
- * Method: getMaterialType()
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testGetMaterialType() throws Exception {
- Assert.assertEquals(Material.Type.BULK, new BodyTubeHandler(new Stage(), new WarningSet()).getMaterialType());
- }
-
-}
+++ /dev/null
-/*
- * FinSetHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import junit.framework.TestCase;
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
-import net.sf.openrocket.rocketcomponent.FinSet;
-import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
-import net.sf.openrocket.util.Coordinate;
-
-import java.lang.reflect.Method;
-import java.util.HashMap;
-
-/**
- * FinSetHandler Tester.
- *
- */
-public class FinSetHandlerTest extends TestCase {
-
- /**
- * Method: asOpenRocket(WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testAsOpenRocket() throws Exception {
-
- FinSetHandler dto = new FinSetHandler(new BodyTube());
-
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- dto.closeElement("Name", attributes, "The name", warnings);
- dto.closeElement("ShapeCode", attributes, "0", warnings);
- dto.closeElement("Xb", attributes, "2", warnings);
- dto.closeElement("FinCount", attributes, "4", warnings);
- dto.closeElement("RootChord", attributes, "10", warnings);
- dto.closeElement("TipChord", attributes, "11", warnings);
- dto.closeElement("SemiSpan", attributes, "12", warnings);
- dto.closeElement("MidChordLen", attributes, "13", warnings);
- dto.closeElement("SweepDistance", attributes, "14", warnings);
- dto.closeElement("Thickness", attributes, "200", warnings);
- dto.closeElement("TipShapeCode", attributes, "1", warnings);
- dto.closeElement("TabLength", attributes, "400", warnings);
- dto.closeElement("TabDepth", attributes, "500", warnings);
- dto.closeElement("TabOffset", attributes, "30", warnings);
- dto.closeElement("RadialAngle", attributes, ".123", warnings);
- dto.closeElement("PointList", attributes, "20,0|2,2|0,0", warnings);
- dto.closeElement("LocationMode", attributes, "0", warnings);
-
- WarningSet set = new WarningSet();
- FinSet fins = dto.asOpenRocket(set);
- assertNotNull(fins);
- assertEquals(0, set.size());
-
- assertEquals("The name", fins.getName());
- assertTrue(fins instanceof TrapezoidFinSet);
- assertEquals(4, fins.getFinCount());
-
- assertEquals(0.012d, ((TrapezoidFinSet) fins).getHeight());
- assertEquals(0.012d, fins.getSpan());
-
- assertEquals(0.2d, fins.getThickness());
- assertEquals(0.4d, fins.getTabLength());
- assertEquals(0.5d, fins.getTabHeight());
- assertEquals(0.03d, fins.getTabShift());
- assertEquals(.123d, fins.getBaseRotation());
-
- dto.closeElement("ShapeCode", attributes, "1", warnings);
- fins = dto.asOpenRocket(set);
- assertNotNull(fins);
- assertEquals(0, set.size());
-
- assertEquals("The name", fins.getName());
- assertTrue(fins instanceof EllipticalFinSet);
- assertEquals(4, fins.getFinCount());
-
- assertEquals(0.2d, fins.getThickness());
- assertEquals(0.4d, fins.getTabLength());
- assertEquals(0.5d, fins.getTabHeight());
- assertEquals(0.03d, fins.getTabShift());
- assertEquals(.123d, fins.getBaseRotation());
- }
-
-
- /**
- * Method: toCoordinates(String pointList)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testToCoordinates() throws Exception {
- FinSetHandler holder = new FinSetHandler(new BodyTube());
- Method method = FinSetHandler.class.getDeclaredMethod("toCoordinates", String.class, WarningSet.class);
- method.setAccessible(true);
-
- WarningSet warnings = new WarningSet();
- //Null finlist
- String finlist = null;
- Coordinate[] result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(0 == result.length);
-
- //Empty string finlist
- finlist = "";
- result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(0 == result.length);
-
- //Invalid finlist (only x coordinate)
- finlist = "10.0";
- result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(0 == result.length);
- assertEquals(1, warnings.size());
- warnings.clear();
-
- //Invalid finlist (non-numeric character)
- finlist = "10.0,asdf";
- result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(0 == result.length);
- assertEquals(1, warnings.size());
- warnings.clear();
-
- //Invalid finlist (all delimiters)
- finlist = "||||||";
- result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(0 == result.length);
- assertEquals(0, warnings.size());
- warnings.clear();
-
- //One point finlist - from a parsing view it's valid; from a practical view it may not be, but that's outside
- //the scope of this test case
- finlist = "10.0,5.0";
- result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(1 == result.length);
- assertEquals(0, warnings.size());
- warnings.clear();
-
- //Two point finlist - from a parsing view it's valid; from a practical view it may not be, but that's outside
- //the scope of this test case
- finlist = "10.0,5.0|3.3,4.4";
- result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(2 == result.length);
- assertEquals(0, warnings.size());
- warnings.clear();
-
- //Normal four point finlist.
- finlist = "518.16,0|517.494,37.2145|1.31261,6.77283|0,0|";
- result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(4 == result.length);
- assertEquals(new Coordinate(0,0), result[0]);
- assertEquals(0, warnings.size());
- warnings.clear();
-
- //Normal four point finlist with spaces.
- finlist = "518.16 , 0 | 517.494 , 37.2145 | 1.31261,6.77283|0,0|";
- result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(4 == result.length);
- assertEquals(new Coordinate(0,0), result[0]);
- assertEquals(new Coordinate(.51816,0), result[3]);
- assertEquals(0, warnings.size());
- warnings.clear();
-
- //Reversed Normal four point finlist.
- finlist = "0,0|1.31261,6.77283|517.494,37.2145|518.16,0|";
- result = (Coordinate[])method.invoke(holder, finlist, warnings);
- assertNotNull(result);
- assertTrue(4 == result.length);
- assertEquals(new Coordinate(0,0), result[0]);
- assertEquals(new Coordinate(.51816,0), result[3]);
- assertEquals(0, warnings.size());
- warnings.clear();
-
- }
-}
+++ /dev/null
-/*
- * InnerBodyTubeHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.InnerTube;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
-import org.junit.Assert;
-
-import java.util.HashMap;
-
-/**
- * InnerBodyTubeHandler Tester.
- *
- */
-public class InnerBodyTubeHandlerTest extends RocksimTestBase {
-
- /**
- * Method: constructor
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testConstructor() throws Exception {
-
- try {
- new InnerBodyTubeHandler(null, new WarningSet());
- Assert.fail("Should have thrown IllegalArgumentException");
- }
- catch (IllegalArgumentException iae) {
- //success
- }
-
- BodyTube tube = new BodyTube();
- InnerBodyTubeHandler handler = new InnerBodyTubeHandler(tube, new WarningSet());
- InnerTube component = (InnerTube) getField(handler, "bodyTube");
- assertContains(component, tube.getChildren());
- }
-
- /**
- * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testOpenElement() throws Exception {
- Assert.assertEquals(PlainTextHandler.INSTANCE, new InnerBodyTubeHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
- Assert.assertNotNull(new InnerBodyTubeHandler(new BodyTube(), new WarningSet()).openElement("AttachedParts", null, null));
- }
-
- /**
- *
- * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testCloseElement() throws Exception {
- BodyTube tube = new BodyTube();
- InnerBodyTubeHandler handler = new InnerBodyTubeHandler(tube, new WarningSet());
- InnerTube component = (InnerTube) getField(handler, "bodyTube");
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("OD", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("OD", attributes, "0", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("OD", attributes, "75", warnings);
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
- handler.closeElement("OD", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("ID", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "0", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "75", warnings);
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Len", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("IsMotorMount", attributes, "1", warnings);
- Assert.assertTrue(component.isMotorMount());
- handler.closeElement("IsMotorMount", attributes, "0", warnings);
- Assert.assertFalse(component.isMotorMount());
- handler.closeElement("IsMotorMount", attributes, "foo", warnings);
- Assert.assertFalse(component.isMotorMount());
-
- handler.closeElement("EngineOverhang", attributes, "-1", warnings);
- Assert.assertEquals(-1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
- handler.closeElement("EngineOverhang", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
- handler.closeElement("EngineOverhang", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getMotorOverhang(), 0.001);
- handler.closeElement("EngineOverhang", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Name", attributes, "Test Name", warnings);
- Assert.assertEquals("Test Name", component.getName());
- }
-
- /**
- * Method: setRelativePosition(RocketComponent.Position position)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testSetRelativePosition() throws Exception {
- BodyTube tube = new BodyTube();
- InnerBodyTubeHandler handler = new InnerBodyTubeHandler(tube, new WarningSet());
- InnerTube component = (InnerTube) getField(handler, "bodyTube");
- handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
- Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
- }
-
- /**
- * Method: getComponent()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetComponent() throws Exception {
- Assert.assertTrue(new InnerBodyTubeHandler(new BodyTube(), new WarningSet()).getComponent() instanceof InnerTube);
- }
-
- /**
- * Method: getMaterialType()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetMaterialType() throws Exception {
- Assert.assertEquals(Material.Type.BULK, new InnerBodyTubeHandler(new BodyTube(), new WarningSet()).getMaterialType());
- }
-
-}
+++ /dev/null
-/*
- * LaunchLugHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.ExternalComponent;
-import net.sf.openrocket.rocketcomponent.LaunchLug;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
-import org.junit.Assert;
-
-import java.util.HashMap;
-
-/**
- * LaunchLugHandler Tester.
- *
- */
-public class LaunchLugHandlerTest extends RocksimTestBase {
-
- /**
- * Method: constructor
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testConstructor() throws Exception {
-
- try {
- new LaunchLugHandler(null, new WarningSet());
- Assert.fail("Should have thrown IllegalArgumentException");
- }
- catch (IllegalArgumentException iae) {
- //success
- }
-
- BodyTube tube = new BodyTube();
- LaunchLugHandler handler = new LaunchLugHandler(tube, new WarningSet());
- LaunchLug component = (LaunchLug) getField(handler, "lug");
- assertContains(component, tube.getChildren());
- }
-
- /**
- * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testOpenElement() throws Exception {
- Assert.assertEquals(PlainTextHandler.INSTANCE, new LaunchLugHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
- }
-
- /**
- *
- * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testCloseElement() throws Exception {
- BodyTube tube = new BodyTube();
- LaunchLugHandler handler = new LaunchLugHandler(tube, new WarningSet());
- LaunchLug component = (LaunchLug) getField(handler, "lug");
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("OD", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getOuterRadius(), 0.001);
- handler.closeElement("OD", attributes, "0", warnings);
- Assert.assertEquals(0d, component.getOuterRadius(), 0.001);
- handler.closeElement("OD", attributes, "75", warnings);
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getOuterRadius(), 0.001);
- handler.closeElement("OD", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("ID", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "0", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "75", warnings);
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Len", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("FinishCode", attributes, "-1", warnings);
- Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
- handler.closeElement("FinishCode", attributes, "100", warnings);
- Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
- handler.closeElement("FinishCode", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Name", attributes, "Test Name", warnings);
- Assert.assertEquals("Test Name", component.getName());
- }
-
- /**
- * Method: setRelativePosition(RocketComponent.Position position)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testSetRelativePosition() throws Exception {
- BodyTube tube = new BodyTube();
- LaunchLugHandler handler = new LaunchLugHandler(tube, new WarningSet());
- LaunchLug component = (LaunchLug) getField(handler, "lug");
- handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
- Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
- }
-
- /**
- * Method: getComponent()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetComponent() throws Exception {
- Assert.assertTrue(new LaunchLugHandler(new BodyTube(), new WarningSet()).getComponent() instanceof LaunchLug);
- }
-
- /**
- * Method: getMaterialType()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetMaterialType() throws Exception {
- Assert.assertEquals(Material.Type.BULK, new LaunchLugHandler(new BodyTube(), new WarningSet()).getMaterialType());
- }
-
-
-}
+++ /dev/null
-/*
- * MassObjectHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.MassComponent;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
-import org.junit.Assert;
-
-import java.util.HashMap;
-
-/**
- * MassObjectHandler Tester.
- *
- */
-public class MassObjectHandlerTest extends RocksimTestBase {
-
- /**
- * Method: constructor
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testConstructor() throws Exception {
-
- try {
- new MassObjectHandler(null, new WarningSet());
- Assert.fail("Should have thrown IllegalArgumentException");
- }
- catch (IllegalArgumentException iae) {
- //success
- }
-
- BodyTube tube = new BodyTube();
- MassObjectHandler handler = new MassObjectHandler(tube, new WarningSet());
- MassComponent component = (MassComponent) getField(handler, "mass");
- assertContains(component, tube.getChildren());
- }
-
- /**
- * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testOpenElement() throws Exception {
- Assert.assertEquals(PlainTextHandler.INSTANCE, new MassObjectHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
- }
-
- /**
- *
- * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testCloseElement() throws Exception {
- BodyTube tube = new BodyTube();
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- MassObjectHandler handler = new MassObjectHandler(tube, new WarningSet());
- MassComponent component = (MassComponent) getField(handler, "mass");
-
- handler.closeElement("Len", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10", warnings);
- Assert.assertEquals(10d / (MassObjectHandler.MASS_LEN_FUDGE_FACTOR * RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH)
- , component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10.0", warnings);
- Assert.assertEquals(10d / (MassObjectHandler.MASS_LEN_FUDGE_FACTOR * RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH)
- , component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("KnownMass", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getComponentMass(), 0.001);
- handler.closeElement("KnownMass", attributes, "100", warnings);
- Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_MASS, component.getComponentMass(), 0.001);
- handler.closeElement("KnownMass", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- }
-
- /**
- * Method: setRelativePosition(RocketComponent.Position position)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testSetRelativePosition() throws Exception {
- BodyTube tube = new BodyTube();
- MassObjectHandler handler = new MassObjectHandler(tube, new WarningSet());
- MassComponent component = (MassComponent) getField(handler, "mass");
- handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
- Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
- }
-
- /**
- * Method: getComponent()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetComponent() throws Exception {
- Assert.assertTrue(new MassObjectHandler(new BodyTube(), new WarningSet()).getComponent() instanceof MassComponent);
- }
-
- /**
- * Method: getMaterialType()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetMaterialType() throws Exception {
- Assert.assertEquals(Material.Type.BULK, new MassObjectHandler(new BodyTube(), new WarningSet()).getMaterialType());
- }
-}
+++ /dev/null
-/*
- * NoseConeHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.ExternalComponent;
-import net.sf.openrocket.rocketcomponent.NoseCone;
-import net.sf.openrocket.rocketcomponent.Stage;
-import net.sf.openrocket.rocketcomponent.Transition;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.HashMap;
-
-/**
- * NoseConeHandler Tester.
- *
- */
-public class NoseConeHandlerTest extends RocksimTestBase {
-
- /**
- * Method: constructor
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testConstructor() throws Exception {
-
- try {
- new NoseConeHandler(null, new WarningSet());
- Assert.fail("Should have thrown IllegalArgumentException");
- }
- catch (IllegalArgumentException iae) {
- //success
- }
-
- Stage stage = new Stage();
- NoseConeHandler handler = new NoseConeHandler(stage, new WarningSet());
- NoseCone component = (NoseCone) getField(handler, "noseCone");
- assertContains(component, stage.getChildren());
- }
-
- /**
- * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testOpenElement() throws Exception {
- Assert.assertEquals(PlainTextHandler.INSTANCE, new NoseConeHandler(new Stage(), new WarningSet()).openElement(null, null, null));
- Assert.assertNotNull(new NoseConeHandler(new Stage(), new WarningSet()).openElement("AttachedParts", null, null));
- }
-
- /**
- *
- * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testCloseElement() throws Exception {
-
- Stage stage = new Stage();
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- NoseConeHandler handler = new NoseConeHandler(stage, warnings);
- NoseCone component = (NoseCone) getField(handler, "noseCone");
-
- handler.closeElement("ShapeCode", attributes, "0", warnings);
- Assert.assertEquals(Transition.Shape.CONICAL, component.getType());
- handler.closeElement("ShapeCode", attributes, "1", warnings);
- Assert.assertEquals(Transition.Shape.OGIVE, component.getType());
- handler.closeElement("ShapeCode", attributes, "17", warnings);
- Assert.assertEquals(RocksimNoseConeCode.PARABOLIC.asOpenRocket(), component.getType()); //test of default
- handler.closeElement("ShapeCode", attributes, "foo", warnings);
- Assert.assertNotNull(component.getType());
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Len", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("BaseDia", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getAftRadius(), 0.001);
- handler.closeElement("BaseDia", attributes, "100", warnings);
- Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getAftRadius(), 0.001);
- handler.closeElement("BaseDia", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
-
- final double aft = 100d;
- component.setAftRadius(aft);
-
- handler.closeElement("ConstructionType", attributes, "0", warnings);
- component.setAftShoulderRadius(1.1d);
- handler.closeElement("WallThickness", attributes, "-1", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(component.getAftRadius(), component.getThickness(), 0.001);
- Assert.assertEquals(component.getAftShoulderThickness(), component.getAftShoulderThickness(), 0.001);
- handler.closeElement("WallThickness", attributes, "100", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(aft, component.getThickness(), 0.001);
- handler.closeElement("WallThickness", attributes, "foo", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("ConstructionType", attributes, "1", warnings);
- component.setAftShoulderRadius(1.1d);
- handler.closeElement("WallThickness", attributes, "-1", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(0d, component.getThickness(), 0.001);
- Assert.assertEquals(0d, component.getAftShoulderThickness(), 0.001);
- handler.closeElement("WallThickness", attributes, "1.1", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getThickness(), 0.001);
- Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderThickness(), 0.001);
-
- handler.closeElement("ShoulderLen", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getAftShoulderLength(), 0.001);
- handler.closeElement("ShoulderLen", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderLength(), 0.001);
- handler.closeElement("ShoulderLen", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderLength(), 0.001);
- handler.closeElement("ShoulderLen", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("ShoulderOD", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getAftShoulderRadius(), 0.001);
- handler.closeElement("ShoulderOD", attributes, "100", warnings);
- Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getAftShoulderRadius(), 0.001);
- handler.closeElement("ShoulderOD", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- component.setType(Transition.Shape.HAACK);
- handler.closeElement("ShapeParameter", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getShapeParameter(), 0.001);
- handler.closeElement("ShapeParameter", attributes, "100", warnings);
- Assert.assertEquals(Transition.Shape.HAACK.maxParameter(), component.getShapeParameter(), 0.001);
- handler.closeElement("ShapeParameter", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- Assert.assertEquals("Could not convert ShapeParameter value of foo. It is expected to be a number.",
- warnings.iterator().next().toString());
-
- warnings.clear();
-
- component.setType(Transition.Shape.CONICAL);
- component.setShapeParameter(0d);
- handler.closeElement("ShapeParameter", attributes, "100", warnings);
- Assert.assertEquals(0d, component.getShapeParameter(), 0.001);
-
- handler.closeElement("FinishCode", attributes, "-1", warnings);
- Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
- handler.closeElement("FinishCode", attributes, "100", warnings);
- Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
- handler.closeElement("FinishCode", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Name", attributes, "Test Name", warnings);
- Assert.assertEquals("Test Name", component.getName());
-
- handler.closeElement("Material", attributes, "Some Material", warnings);
- handler.endHandler("NoseCone", attributes, null, warnings);
- Assert.assertTrue(component.getMaterial().getName().contains("Some Material"));
- }
-
- /**
- * Method: getComponent()
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testGetComponent() throws Exception {
- Assert.assertTrue(new NoseConeHandler(new Stage(), new WarningSet()).getComponent() instanceof NoseCone);
- }
-
- /**
- * Method: getMaterialType()
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testGetMaterialType() throws Exception {
- Assert.assertEquals(Material.Type.BULK, new NoseConeHandler(new Stage(), new WarningSet()).getMaterialType());
- }
-}
+++ /dev/null
-/*
- * ParachuteHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.Parachute;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
-import org.junit.Assert;
-
-import java.util.HashMap;
-
-/**
- * ParachuteHandler Tester.
- */
-public class ParachuteHandlerTest extends RocksimTestBase {
-
- /**
- * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testOpenElement() throws Exception {
- Assert.assertEquals(PlainTextHandler.INSTANCE, new ParachuteHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
- }
-
- /**
- * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testCloseElement() throws Exception {
-
- BodyTube tube = new BodyTube();
- ParachuteHandler handler = new ParachuteHandler(tube, new WarningSet());
- Parachute component = (Parachute) getField(handler, "chute");
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("Name", attributes, "Test Name", warnings);
- Assert.assertEquals("Test Name", component.getName());
-
- handler.closeElement("DragCoefficient", attributes, "0.94", warnings);
- Assert.assertEquals(0.94d, component.getCD(), 0.001);
- handler.closeElement("DragCoefficient", attributes, "-0.94", warnings);
- Assert.assertEquals(-0.94d, component.getCD(), 0.001);
- handler.closeElement("DragCoefficient", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Dia", attributes, "-1", warnings);
- Assert.assertEquals(-1d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getDiameter(), 0.001);
- handler.closeElement("Dia", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getDiameter(), 0.001);
- handler.closeElement("Dia", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("ShroudLineCount", attributes, "-1", warnings);
- Assert.assertEquals(0, component.getLineCount());
- handler.closeElement("ShroudLineCount", attributes, "10", warnings);
- Assert.assertEquals(10, component.getLineCount());
- handler.closeElement("ShroudLineCount", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("ShroudLineLen", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getLineLength(), 0.001);
- handler.closeElement("ShroudLineLen", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLineLength(), 0.001);
- handler.closeElement("ShroudLineLen", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- }
-
- /**
- * Method: constructor
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testConstructor() throws Exception {
-
- try {
- new ParachuteHandler(null, new WarningSet());
- Assert.fail("Should have thrown IllegalArgumentException");
- }
- catch (IllegalArgumentException iae) {
- //success
- }
-
- BodyTube tube = new BodyTube();
- ParachuteHandler handler = new ParachuteHandler(tube, new WarningSet());
- Parachute component = (Parachute) getField(handler, "chute");
- assertContains(component, tube.getChildren());
- }
-
- /**
- * Method: setRelativePosition(RocketComponent.Position position)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testSetRelativePosition() throws Exception {
- BodyTube tube = new BodyTube();
- ParachuteHandler handler = new ParachuteHandler(tube, new WarningSet());
- Parachute component = (Parachute) getField(handler, "chute");
- handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
- Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
- }
-
- /**
- * Method: getComponent()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetComponent() throws Exception {
- Assert.assertTrue(new ParachuteHandler(new BodyTube(), new WarningSet()).getComponent() instanceof Parachute);
- }
-
- /**
- * Method: getMaterialType()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetMaterialType() throws Exception {
- Assert.assertEquals(Material.Type.SURFACE, new ParachuteHandler(new BodyTube(), new WarningSet()).getMaterialType());
- }
-
- /**
- * Method: endHandler()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testEndHandler() throws Exception {
- BodyTube tube = new BodyTube();
- ParachuteHandler handler = new ParachuteHandler(tube, new WarningSet());
- Parachute component = (Parachute) getField(handler, "chute");
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("Xb", attributes, "-10", warnings);
- handler.closeElement("LocationMode", attributes, "1", warnings);
- handler.endHandler("Parachute", attributes, null, warnings);
- Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
- Assert.assertEquals(component.getPositionValue(), -10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, 0.001);
-
- handler.closeElement("Xb", attributes, "-10", warnings);
- handler.closeElement("LocationMode", attributes, "2", warnings);
- handler.endHandler("Parachute", attributes, null, warnings);
- Assert.assertEquals(RocketComponent.Position.BOTTOM, component.getRelativePosition());
- Assert.assertEquals(component.getPositionValue(), 10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, 0.001);
- }
-}
+++ /dev/null
-<RockSimDocument>
- <FileVersion>4</FileVersion>
- <DesignInformation>
- <RocketDesign>
- <CalculateCD>1</CalculateCD>
- <ProCalculateCD>1</ProCalculateCD>
- <ProCalculateCN>1</ProCalculateCN>
- <FixedCd>0.75</FixedCd>
- <FixedCd2>0.8</FixedCd2>
- <FixedCd3>0.81</FixedCd3>
- <FixedCd2Alone>0.95</FixedCd2Alone>
- <FixedCd3Alone>0.95</FixedCd3Alone>
- <StageCount>1</StageCount>
- <Stage3Mass>0.</Stage3Mass>
- <Stage2Mass>0.</Stage2Mass>
- <Stage1Mass>0.</Stage1Mass>
- <Stage321CG>0.</Stage321CG>
- <Stage32CG>0.</Stage32CG>
- <Stage3CG>0.</Stage3CG>
- <Stage2CGAlone>0.</Stage2CGAlone>
- <Stage1CGAlone>0.</Stage1CGAlone>
- <CPCalcFlags>1</CPCalcFlags>
- <LaunchGuideLength>914.4</LaunchGuideLength>
- <UseKnownMass>0</UseKnownMass>
- <DefaultFinish>0</DefaultFinish>
- <FinishMedium>0</FinishMedium>
- <FinishCoatCount>1</FinishCoatCount>
- <GlueType>0</GlueType>
- <CPSimFlags>1</CPSimFlags>
- <LastSerialNumber>7</LastSerialNumber>
- <DisplayFlags>1</DisplayFlags>
- <MetricsFlags>0</MetricsFlags>
- <BarromanXN>0,567.719,0,0</BarromanXN>
- <BarrowmanCNa>0,19.2193,0,0</BarrowmanCNa>
- <RockSimXN>0,571.25,0,0</RockSimXN>
- <RockSimCNa>0,28.2677,0,0</RockSimCNa>
- <RockSimCNa90>0,0,0,0</RockSimCNa90>
- <RockSimXN90>0,0,0,0</RockSimXN90>
- <ViewType>0</ViewType>
- <ViewStageCount>1</ViewStageCount>
- <ViewTypeEdit>0</ViewTypeEdit>
- <ViewStageCountEdit>1</ViewStageCountEdit>
- <ZoomFactor>0.</ZoomFactor>
- <ZoomFactorEdit>0.</ZoomFactorEdit>
- <ScrollPosX>0</ScrollPosX>
- <ScrollPosY>0</ScrollPosY>
- <ScrollPosXEdit>0</ScrollPosXEdit>
- <ScrollPosYEdit>0</ScrollPosYEdit>
- <ThreeDFlags>0</ThreeDFlags>
- <ThreeDFlagsEdit>0</ThreeDFlagsEdit>
- <UseModelSprite>0</UseModelSprite>
- <StaticMarginRef>0</StaticMarginRef>
- <UserRefDiameter>0.</UserRefDiameter>
- <SideMarkerHeight>10.</SideMarkerHeight>
- <SideDimensionHeight>10.</SideDimensionHeight>
- <BaseMarkerHeight>10.</BaseMarkerHeight>
- <BaseDimensionHeight>10.</BaseDimensionHeight>
- <ShowGlideCP>0</ShowGlideCP>
- <ShowGridTypeSide>0</ShowGridTypeSide>
- <ShowGridTypeBase>0</ShowGridTypeBase>
- <GridSpacing>10.</GridSpacing>
- <GridOpacity>0.15</GridOpacity>
- <GridColor>black</GridColor>
- <MaxDiaWithFins>259.588</MaxDiaWithFins>
- <MaxDiaWithoutFins>56.388</MaxDiaWithoutFins>
- <MaxLenWithFins>717.499</MaxLenWithFins>
- <MaxLenWithoutFins>717.499</MaxLenWithoutFins>
- <MinXExtent>0.</MinXExtent>
- <MaxXExtent>717.499</MaxXExtent>
- <CalculatedMaxStageDia>0,56.388,0,0</CalculatedMaxStageDia>
- <CalculatedStageLen>0,717.499,0,0</CalculatedStageLen>
- <Cd3>
- <PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
- <X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
- <A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
- <B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
- <C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
- </PolyData>
- </Cd3>
- <Cd32>
- <PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
- <X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
- <A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
- <B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
- <C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
- </PolyData>
- </Cd32>
- <Cd321>
- <PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
- <X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
- <A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
- <B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
- <C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
- </PolyData>
-</Cd321>
-<Cb3>
- <PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
- <X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
- <A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
- <B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
- <C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb3>
-<Cb32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb32>
-<Cb321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb321>
-<CNa3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa3>
-<CNa32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa32>
-<CNa321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa321>
-<CP3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP3>
-<CP32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP32>
-<CP321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP321>
-<SimulationEventList>
-</SimulationEventList>
-<Stage3Parts>
-<NoseCone>
-<PartMfg>Apogee</PartMfg>
-<KnownMass>24.0999</KnownMass>
-<Density>1049.21</Density>
-<Material>Polystyrene PS</Material>
-<Name>Nose cone</Name>
-<KnownCG>65.3999</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>94.7384</CalcMass>
-<CalcCG>208.434</CalcCG>
-<WettedSurface>0.0323955</WettedSurface>
-<PaintedSurface>0.0323955</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>19470</PartNo>
-<PartDesc>PNC-70A</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>1</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>2.</BarrowmanCNa>
-<BarrowmanXN>0.126958</BarrowmanXN>
-<RockSimCNa>2.</RockSimCNa>
-<RockSimXN>0.126958</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>0.</Station>
-<Len>272.999</Len>
-<BaseDia>56.2991</BaseDia>
-<FinishCode>0</FinishCode>
-<ShapeCode>1</ShapeCode>
-<ConstructionType>1</ConstructionType>
-<ShoulderLen>58.3997</ShoulderLen>
-<WallThickness>2.159</WallThickness>
-<ShapeParameter>0.</ShapeParameter>
-<ShoulderOD>53.1012</ShoulderOD>
-<BaseExtensionLen>0.</BaseExtensionLen>
-<CoreDia>0.</CoreDia>
-<CoreLen>0.</CoreLen>
-<AttachedParts>
-</AttachedParts>
-</NoseCone>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>44.4492</CalcMass>
-<CalcCG>222.25</CalcCG>
-<WettedSurface>0.0787423</WettedSurface>
-<PaintedSurface>0.0787423</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>Estes</PartNo>
-<PartDesc>BT-70</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>2</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>272.999</Station>
-<OD>56.388</OD>
-<ID>55.372</ID>
-<Len>444.5</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<FinSet>
-<PartMfg>Public Missiles</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1905.24</Density>
-<Material>G10 fiberglass</Material>
-<Name>Fin set</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>273.05</Xb>
-<CalcMass>75.5033</CalcMass>
-<CalcCG>110.067</CalcCG>
-<WettedSurface>0.0167742</WettedSurface>
-<PaintedSurface>0.0503225</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>FIN-A-04</PartNo>
-<PartDesc>Fins</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>4</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>16.5474</BarrowmanCNa>
-<BarrowmanXN>0.628599</BarrowmanXN>
-<RockSimCNa>23.7789</RockSimCNa>
-<RockSimXN>0.628599</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>546.049</Station>
-<FinCount>3</FinCount>
-<RootChord>165.1</RootChord>
-<TipChord>0.</TipChord>
-<SemiSpan>101.6</SemiSpan>
-<MidChordLen>130.909</MidChordLen>
-<SweepDistance>165.1</SweepDistance>
-<Thickness>1.5748</Thickness>
-<ShapeCode>0</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>1</TipShapeCode>
-<TabLength>0.</TabLength>
-<TabDepth>0.</TabDepth>
-<TabOffset>0.</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>1.02001</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>62.0607</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>13.7288</RockSimCNaPerFin>
-<TaperRatio>0.</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AttachedParts>
-</AttachedParts>
-</FinSet>
-<BodyTube>
-<PartMfg>Apogee</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>107.95</Xb>
-<CalcMass>1.7435</CalcMass>
-<CalcCG>55.5625</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>10062</PartNo>
-<PartDesc>13 mm</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>5</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>380.949</Station>
-<OD>13.8176</OD>
-<ID>13.1572</ID>
-<Len>111.125</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>13.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<FinSet>
-<PartMfg>Public Missiles</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1905.24</Density>
-<Material>G10 fiberglass</Material>
-<Name>Fin set</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>5.53666</CalcMass>
-<CalcCG>44.5707</CalcCG>
-<WettedSurface>0.00365927</WettedSurface>
-<PaintedSurface>0.00365927</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>FIN-A-06</PartNo>
-<PartDesc>Fins</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>7</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.671866</BarrowmanCNa>
-<BarrowmanXN>0.380349</BarrowmanXN>
-<RockSimCNa>2.4888</RockSimCNa>
-<RockSimXN>0.380349</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>349.199</Station>
-<FinCount>1</FinCount>
-<RootChord>66.675</RootChord>
-<TipChord>38.1</TipChord>
-<SemiSpan>34.925</SemiSpan>
-<MidChordLen>42.7843</MidChordLen>
-<SweepDistance>39.0017</SweepDistance>
-<Thickness>1.5875</Thickness>
-<ShapeCode>0</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>0</TipShapeCode>
-<TabLength>0.</TabLength>
-<TabDepth>0.</TabDepth>
-<TabOffset>0.</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.366519</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>44.069</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>2.87382</RockSimCNaPerFin>
-<TaperRatio>0.571429</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AttachedParts>
-</AttachedParts>
-</FinSet>
-</AttachedParts>
-</BodyTube>
-<ExternalPod>
-<PartMfg>Custom</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>0.</Density>
-<Name>Pod</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>76.2</Xb>
-<CalcMass>0.</CalcMass>
-<CalcCG>0.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>28.194</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>6</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>349.199</Station>
-<Detachable>1</Detachable>
-<AutoCalcRadialDistance>1</AutoCalcRadialDistance>
-<AutoCalcRadialAngle>1</AutoCalcRadialAngle>
-<AttachedParts>
-<FinSet>
-<PartMfg>Public Missiles</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1905.24</Density>
-<Material>G10 fiberglass</Material>
-<Name>Fin set</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>5.53666</CalcMass>
-<CalcCG>44.5707</CalcCG>
-<WettedSurface>0.00365927</WettedSurface>
-<PaintedSurface>0.00365927</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>FIN-A-06</PartNo>
-<PartDesc>Fins</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>7</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.671866</BarrowmanCNa>
-<BarrowmanXN>0.380349</BarrowmanXN>
-<RockSimCNa>2.4888</RockSimCNa>
-<RockSimXN>0.380349</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>349.199</Station>
-<FinCount>1</FinCount>
-<RootChord>66.675</RootChord>
-<TipChord>38.1</TipChord>
-<SemiSpan>34.925</SemiSpan>
-<MidChordLen>42.7843</MidChordLen>
-<SweepDistance>39.0017</SweepDistance>
-<Thickness>1.5875</Thickness>
-<ShapeCode>0</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>0</TipShapeCode>
-<TabLength>0.</TabLength>
-<TabDepth>0.</TabDepth>
-<TabOffset>0.</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.366519</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>44.069</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>2.87382</RockSimCNaPerFin>
-<TaperRatio>0.571429</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AttachedParts>
-</AttachedParts>
-</FinSet>
-</AttachedParts>
-</ExternalPod>
-</AttachedParts>
-</BodyTube>
-</Stage3Parts>
-<Stage2Parts>
-</Stage2Parts>
-<Stage1Parts>
-</Stage1Parts>
-<SideViewDims>
-</SideViewDims>
-<BaseViewDims>
-</BaseViewDims>
-<VertViewDims>
-</VertViewDims>
-</RocketDesign>
-</DesignInformation>
-<SimulationResultsList>
-</SimulationResultsList>
-</RockSimDocument>
+++ /dev/null
-/*
- * RingHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.Bulkhead;
-import net.sf.openrocket.rocketcomponent.CenteringRing;
-import net.sf.openrocket.rocketcomponent.EngineBlock;
-import net.sf.openrocket.rocketcomponent.RingComponent;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
-import net.sf.openrocket.rocketcomponent.TubeCoupler;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.HashMap;
-
-/**
- * RingHandler Tester.
- */
-public class RingHandlerTest extends RocksimTestBase {
-
- /**
- * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testOpenElement() throws Exception {
- Assert.assertEquals(PlainTextHandler.INSTANCE, new RingHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
- }
-
- /**
- * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testCloseElement() throws Exception {
-
- BodyTube tube = new BodyTube();
- RingHandler handler = new RingHandler(tube, new WarningSet());
- CenteringRing component = (CenteringRing) getField(handler, "ring");
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("OD", attributes, "0", warnings);
- Assert.assertEquals(0d, component.getOuterRadius(), 0.001);
- handler.closeElement("OD", attributes, "75", warnings);
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getOuterRadius(), 0.001);
- handler.closeElement("OD", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("ID", attributes, "0", warnings);
- Assert.assertEquals(0d, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "75", warnings);
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getInnerRadius(), 0.001);
- handler.closeElement("ID", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Len", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Name", attributes, "Test Name", warnings);
- Assert.assertEquals("Test Name", component.getName());
- }
-
- /**
- * Test a bulkhead.
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testBulkhead() throws Exception {
- BodyTube tube = new BodyTube();
- RingHandler handler = new RingHandler(tube, new WarningSet());
- CenteringRing component = (CenteringRing) getField(handler, "ring");
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("OD", attributes, "75", warnings);
- handler.closeElement("ID", attributes, "0", warnings);
- handler.closeElement("Len", attributes, "10", warnings);
- handler.closeElement("Name", attributes, "Test Name", warnings);
- handler.closeElement("KnownMass", attributes, "109.9", warnings);
- handler.closeElement("UsageCode", attributes, "1", warnings);
- handler.closeElement("UseKnownCG", attributes, "1", warnings);
- handler.endHandler("", attributes, "", warnings);
-
- Assert.assertEquals(1, tube.getChildren().size());
- RingComponent child = (RingComponent)tube.getChild(0);
-
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getOuterRadius(), 0.001);
- Assert.assertEquals(0d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getInnerRadius(), 0.001);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getLength(), 0.001);
- Assert.assertEquals("Test Name", child.getName());
- Assert.assertEquals(109.9/1000, child.getMass(), 0.001);
- Assert.assertEquals(0, child.getPositionValue(), 0.0);
- Assert.assertEquals(RocketComponent.Position.TOP, child.getRelativePosition());
- Assert.assertTrue(child instanceof Bulkhead);
-
- }
-
- /**
- * Test a tube coupler.
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testTubeCoupler() throws Exception {
- BodyTube tube = new BodyTube();
- RingHandler handler = new RingHandler(tube, new WarningSet());
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("OD", attributes, "75", warnings);
- handler.closeElement("ID", attributes, "70", warnings);
- handler.closeElement("Len", attributes, "10", warnings);
- handler.closeElement("Name", attributes, "Test Name", warnings);
- handler.closeElement("KnownMass", attributes, "109.9", warnings);
- handler.closeElement("UsageCode", attributes, "4", warnings);
- handler.closeElement("UseKnownCG", attributes, "1", warnings);
- handler.endHandler("", attributes, "", warnings);
-
- Assert.assertEquals(1, tube.getChildren().size());
- RingComponent child = (RingComponent)tube.getChild(0);
- Assert.assertTrue(child instanceof TubeCoupler);
-
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getOuterRadius(), 0.001);
- Assert.assertEquals(70d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getInnerRadius(), 0.001);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getLength(), 0.001);
- Assert.assertEquals("Test Name", child.getName());
- Assert.assertEquals(109.9/1000, child.getMass(), 0.001);
- Assert.assertEquals(0, child.getPositionValue(), 0.0);
- Assert.assertEquals(RocketComponent.Position.TOP, child.getRelativePosition());
- }
-
- /**
- * Test a engine block.
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testEngineBlock() throws Exception {
- BodyTube tube = new BodyTube();
- RingHandler handler = new RingHandler(tube, new WarningSet());
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("OD", attributes, "75", warnings);
- handler.closeElement("ID", attributes, "70", warnings);
- handler.closeElement("Len", attributes, "10", warnings);
- handler.closeElement("Name", attributes, "Test Name", warnings);
- handler.closeElement("KnownMass", attributes, "109.9", warnings);
- handler.closeElement("UsageCode", attributes, "2", warnings);
- handler.closeElement("KnownCG", attributes, "4", warnings);
- handler.closeElement("UseKnownCG", attributes, "1", warnings);
- handler.endHandler("", attributes, "", warnings);
-
- Assert.assertEquals(1, tube.getChildren().size());
- RingComponent child = (RingComponent)tube.getChild(0);
- Assert.assertTrue(child instanceof EngineBlock);
-
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getOuterRadius(), 0.001);
- Assert.assertEquals(70d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getInnerRadius(), 0.001);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getLength(), 0.001);
- Assert.assertEquals("Test Name", child.getName());
- Assert.assertEquals(109.9/1000, child.getMass(), 0.001);
- Assert.assertEquals(0, child.getPositionValue(), 0.0);
- Assert.assertEquals(RocketComponent.Position.TOP, child.getRelativePosition());
- Assert.assertEquals(4d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getCG().x, 0.000001);
-
- }
-
- /**
- * Test a centering ring
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testRing() throws Exception {
- BodyTube tube = new BodyTube();
- RingHandler handler = new RingHandler(tube, new WarningSet());
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("OD", attributes, "75", warnings);
- handler.closeElement("ID", attributes, "0", warnings);
- handler.closeElement("Len", attributes, "10", warnings);
- handler.closeElement("Name", attributes, "Test Name", warnings);
- handler.closeElement("KnownMass", attributes, "109.9", warnings);
- handler.closeElement("UsageCode", attributes, "0", warnings);
- handler.closeElement("UseKnownCG", attributes, "1", warnings);
- handler.endHandler("", attributes, "", warnings);
-
- Assert.assertEquals(1, tube.getChildren().size());
- RingComponent child = (RingComponent)tube.getChild(0);
-
- Assert.assertEquals(75d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getOuterRadius(), 0.001);
- Assert.assertEquals(0d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, child.getInnerRadius(), 0.001);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, child.getLength(), 0.001);
- Assert.assertEquals("Test Name", child.getName());
- Assert.assertEquals(109.9/1000, child.getMass(), 0.001);
- Assert.assertEquals(0, child.getPositionValue(), 0.0);
- Assert.assertEquals(RocketComponent.Position.TOP, child.getRelativePosition());
- Assert.assertTrue(child instanceof CenteringRing);
- }
-
- /**
- * Method: constructor
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testConstructor() throws Exception {
-
- try {
- new RingHandler(null, new WarningSet());
- Assert.fail("Should have thrown IllegalArgumentException");
- }
- catch (IllegalArgumentException iae) {
- //success
- }
-
- BodyTube tube = new BodyTube();
- RingHandler handler = new RingHandler(tube, new WarningSet());
- CenteringRing component = (CenteringRing) getField(handler, "ring");
- }
-
- /**
- * Method: setRelativePosition(RocketComponent.Position position)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testSetRelativePosition() throws Exception {
- BodyTube tube = new BodyTube();
- RingHandler handler = new RingHandler(tube, new WarningSet());
- CenteringRing component = (CenteringRing) getField(handler, "ring");
- handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
- Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
- }
-
-
- /**
- * Method: getComponent()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetComponent() throws Exception {
- Assert.assertTrue(new RingHandler(new BodyTube(), new WarningSet()).getComponent() instanceof CenteringRing);
- }
-
- /**
- * Method: getMaterialType()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetMaterialType() throws Exception {
- Assert.assertEquals(Material.Type.BULK, new RingHandler(new BodyTube(), new WarningSet()).getMaterialType());
- }
-
-
-}
+++ /dev/null
-/*
- * RocksimContentHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import org.junit.Assert;
-
-/**
- * RocksimContentHandler Tester.
- *
- */
-public class RocksimContentHandlerTest {
-
- /**
- *
- * Method: getDocument()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetDocument() throws Exception {
- RocksimContentHandler handler = new RocksimContentHandler();
- Assert.assertNotNull(handler.getDocument());
- }
-
-}
+++ /dev/null
-/*
- * RocksimLoaderTest.java
- *
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.document.OpenRocketDocument;
-import net.sf.openrocket.file.RocketLoadException;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.LaunchLug;
-import net.sf.openrocket.rocketcomponent.Rocket;
-import net.sf.openrocket.rocketcomponent.Stage;
-import org.junit.Assert;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * RocksimLoader Tester.
- */
-public class RocksimLoaderTest {
-
- /**
- * Test a bug reported via automated bug report. I have been unable to reproduce this bug
- * (hanging finset off of an inner body tube) when creating a Rocksim file using Rocksim. The bug
- * is reproducible when manually modifying the Rocksim file, which is what is tested here.
- */
- @org.junit.Test
- public void testFinsOnInnerTube() throws Exception {
- RocksimLoader loader = new RocksimLoader();
- InputStream stream = this.getClass().getResourceAsStream("PodFins.rkt");
- Assert.assertNotNull("Could not open PodFins.rkt", stream);
- try {
- OpenRocketDocument doc = loader.loadFromStream(new BufferedInputStream(stream));
- Assert.assertNotNull(doc);
- Rocket rocket = doc.getRocket();
- Assert.assertNotNull(rocket);
- } catch (IllegalStateException ise) {
- Assert.fail(ise.getMessage());
- }
- Assert.assertTrue(loader.getWarnings().size() == 2);
- }
-
- /**
- * Method: loadFromStream(InputStream source)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testLoadFromStream() throws Exception {
- RocksimLoader loader = new RocksimLoader();
- //Stupid single stage rocket
- OpenRocketDocument doc = loadRocksimRocket(loader);
- InputStream stream;
-
- Assert.assertNotNull(doc);
- Rocket rocket = doc.getRocket();
- Assert.assertNotNull(rocket);
- Assert.assertEquals("FooBar Test", doc.getRocket().getName());
- Assert.assertTrue(loader.getWarnings().isEmpty());
-
- stream = this.getClass().getResourceAsStream("rocksimTestRocket2.rkt");
- Assert.assertNotNull("Could not open rocksimTestRocket2.rkt", stream);
- doc = loader.loadFromStream(new BufferedInputStream(stream));
-
- Assert.assertNotNull(doc);
- rocket = doc.getRocket();
- Assert.assertNotNull(rocket);
-
- //Do some simple asserts; the important thing here is just validating that the mass and cg were
- //not overridden for each stage.
- Assert.assertEquals("Three Stage Everything Included Rocket", doc.getRocket().getName());
- Assert.assertEquals(1, loader.getWarnings().size());
- Assert.assertEquals(3, rocket.getStageCount());
- Stage stage1 = (Stage) rocket.getChild(0);
- Assert.assertFalse(stage1.isMassOverridden());
- Assert.assertFalse(stage1.isCGOverridden());
- Stage stage2 = (Stage) rocket.getChild(1);
- Assert.assertFalse(stage2.isMassOverridden());
- Assert.assertFalse(stage2.isCGOverridden());
- Stage stage3 = (Stage) rocket.getChild(2);
- Assert.assertFalse(stage3.isMassOverridden());
- Assert.assertFalse(stage3.isCGOverridden());
-
- stream = this.getClass().getResourceAsStream("rocksimTestRocket3.rkt");
- Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
- doc = loader.loadFromStream(new BufferedInputStream(stream));
-
- Assert.assertNotNull(doc);
- rocket = doc.getRocket();
- Assert.assertNotNull(rocket);
- Assert.assertEquals("Three Stage Everything Included Rocket - Override Total Mass/CG", doc.getRocket().getName());
- Assert.assertEquals(3, rocket.getStageCount());
- stage1 = (Stage) rocket.getChild(0);
- stage2 = (Stage) rocket.getChild(1);
- stage3 = (Stage) rocket.getChild(2);
-
- //Do some 1st level and simple asserts; the idea here is to not do a deep validation as that
- //should have been covered elsewhere. Assert that the stage overrides are correct.
- Assert.assertEquals(2, stage1.getChildCount());
- Assert.assertEquals("Nose cone", stage1.getChild(0).getName());
- Assert.assertEquals("Body tube", stage1.getChild(1).getName());
- Assert.assertTrue(stage1.isMassOverridden());
- Assert.assertEquals(0.185d, stage1.getOverrideMass(), 0.001);
- Assert.assertTrue(stage1.isCGOverridden());
- Assert.assertEquals(0.3d, stage1.getOverrideCG().x, 0.001);
- Assert.assertEquals(4, loader.getWarnings().size());
-
- Assert.assertEquals(1, stage2.getChildCount());
- Assert.assertEquals("2nd Stage Tube", stage2.getChild(0).getName());
- Assert.assertTrue(stage2.isMassOverridden());
- Assert.assertEquals(0.21d, stage2.getOverrideMass(), 0.001);
- Assert.assertTrue(stage2.isCGOverridden());
- Assert.assertEquals(0.4d, stage2.getOverrideCG().x, 0.001);
-
- BodyTube bt = (BodyTube) stage2.getChild(0);
- LaunchLug ll = (LaunchLug) bt.getChild(6);
- Assert.assertEquals(1.22d, ll.getRadialDirection(), 0.001);
-
- Assert.assertEquals(2, stage3.getChildCount());
- Assert.assertEquals("Transition", stage3.getChild(0).getName());
- Assert.assertEquals("Body tube", stage3.getChild(1).getName());
- Assert.assertTrue(stage2.isMassOverridden());
- Assert.assertEquals(0.33d, stage3.getOverrideMass(), 0.001);
- Assert.assertTrue(stage2.isCGOverridden());
- Assert.assertEquals(0.5d, stage3.getOverrideCG().x, 0.001);
- }
-
- public static OpenRocketDocument loadRocksimRocket(RocksimLoader theLoader) throws IOException, RocketLoadException {
- InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket1.rkt");
- try {
- Assert.assertNotNull("Could not open rocksimTestRocket1.rkt", stream);
- return theLoader.loadFromStream(new BufferedInputStream(stream));
- } finally {
- stream.close();
- }
- }
-
- public static OpenRocketDocument loadRocksimRocket3(RocksimLoader theLoader) throws IOException, RocketLoadException {
- InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket3.rkt");
- try {
- Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
- return theLoader.loadFromStream(new BufferedInputStream(stream));
- } finally {
- stream.close();
- }
- }
-
-}
+++ /dev/null
-/*
- * BaseRocksimTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.gui.util.SwingPreferences;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
-import net.sf.openrocket.startup.Application;
-import org.junit.Assert;
-import org.junit.Before;
-
-import java.lang.reflect.Field;
-import java.util.List;
-
-/**
- * A base class for the Rocksim tests. Includes code from the junitx.addons project.
- */
-public abstract class RocksimTestBase {
-
- /* (non-Javadoc)
- * @see junit.framework.TestCase#setUp()
- */
- @Before
- public void setUp() throws Exception {
- Application.setPreferences( new SwingPreferences() );
- }
-
-
- public void assertContains(RocketComponent child, List<RocketComponent> components) {
- Assert.assertTrue("Components did not contain child", components.contains(child));
- }
-
- /**
- * Returns the value of the field on the specified object. The name
- * parameter is a <code>String</code> specifying the simple name of the
- * desired field.<p>
- *
- * The object is first searched for any matching field. If no matching
- * field is found, the superclasses are recursively searched.
- *
- * @exception NoSuchFieldException if a field with the specified name is
- * not found.
- */
- public static Object getField(Object object,
- String name)
- throws NoSuchFieldException {
- if (object == null) {
- throw new IllegalArgumentException("Invalid null object argument");
- }
- for (Class cls = object.getClass(); cls != null; cls = cls.getSuperclass()) {
- try {
- Field field = cls.getDeclaredField(name);
- field.setAccessible(true);
- return field.get(object);
- } catch (Exception ex) {
- /* in case of an exception, we will throw a new
- * NoSuchFieldException object */
- ;
- }
- }
- throw new NoSuchFieldException("Could get value for field " +
- object.getClass().getName() + "." + name);
- }
-
- /**
- * Returns the value of the field on the specified class. The name
- * parameter is a <code>String</code> specifying the simple name of the
- * desired field.<p>
- *
- * The class is first searched for any matching field. If no matching
- * field is found, the superclasses are recursively searched.
- *
- * @exception NoSuchFieldException if a field with the specified name is
- * not found.
- */
- public static Object getField(Class cls,
- String name)
- throws NoSuchFieldException {
- if (cls == null) {
- throw new IllegalArgumentException("Invalid null cls argument");
- }
- Class base = cls;
- while (base != null) {
- try {
- Field field = base.getDeclaredField(name);
- field.setAccessible(true);
- return field.get(base);
- } catch (Exception ex) {
- /* in case of an exception, we will throw a new
- * NoSuchFieldException object */
- ;
- }
- base = base.getSuperclass();
- }
- throw new NoSuchFieldException("Could get value for static field " +
- cls.getName() + "." + name);
- }
-
-
-}
+++ /dev/null
-/*
- * StreamerHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
-import net.sf.openrocket.rocketcomponent.Streamer;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.HashMap;
-
-/**
- * StreamerHandler Tester.
- */
-public class StreamerHandlerTest extends RocksimTestBase {
-
- /**
- * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testOpenElement() throws Exception {
- Assert.assertEquals(PlainTextHandler.INSTANCE, new StreamerHandler(new BodyTube(), new WarningSet()).openElement(null, null, null));
- }
-
- /**
- * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testCloseElement() throws Exception {
-
- BodyTube tube = new BodyTube();
- StreamerHandler handler = new StreamerHandler(tube, new WarningSet());
- Streamer component = (Streamer) getField(handler, "streamer");
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("Width", attributes, "0", warnings);
- Assert.assertEquals(0d/ RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getStripWidth(), 0.001);
- handler.closeElement("Width", attributes, "10", warnings);
- Assert.assertEquals(10d/ RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getStripWidth(), 0.001);
- handler.closeElement("Width", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Len", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getStripLength(), 0.001);
- handler.closeElement("Len", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getStripLength(), 0.001);
- handler.closeElement("Len", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getStripLength(), 0.001);
- handler.closeElement("Len", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Name", attributes, "Test Name", warnings);
- Assert.assertEquals("Test Name", component.getName());
-
- handler.closeElement("DragCoefficient", attributes, "0.94", warnings);
- Assert.assertEquals(0.94d, component.getCD(), 0.001);
- handler.closeElement("DragCoefficient", attributes, "-0.94", warnings);
- Assert.assertEquals(-0.94d, component.getCD(), 0.001);
- handler.closeElement("DragCoefficient", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- }
-
- /**
- * Method: constructor
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testConstructor() throws Exception {
-
- try {
- new StreamerHandler(null, new WarningSet());
- Assert.fail("Should have thrown IllegalArgumentException");
- }
- catch (IllegalArgumentException iae) {
- //success
- }
-
- BodyTube tube = new BodyTube();
- StreamerHandler handler = new StreamerHandler(tube, new WarningSet());
- Streamer component = (Streamer) getField(handler, "streamer");
- assertContains(component, tube.getChildren());
- }
-
- /**
- * Method: setRelativePosition(RocketComponent.Position position)
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testSetRelativePosition() throws Exception {
- BodyTube tube = new BodyTube();
- StreamerHandler handler = new StreamerHandler(tube, new WarningSet());
- Streamer component = (Streamer) getField(handler, "streamer");
- handler.setRelativePosition(RocketComponent.Position.ABSOLUTE);
- Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
- }
-
- /**
- * Method: getComponent()
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testGetComponent() throws Exception {
- Assert.assertTrue(new StreamerHandler(new BodyTube(), new WarningSet()).getComponent() instanceof Streamer);
- }
-
- /**
- * Method: getMaterialType()
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testGetMaterialType() throws Exception {
- Assert.assertEquals(Material.Type.SURFACE, new StreamerHandler(new BodyTube(), new WarningSet()).getMaterialType());
- }
-
- /**
- * Method: endHandler()
- *
- * @throws Exception thrown if something goes awry
- */
- @Test
- public void testEndHandler() throws Exception {
- BodyTube tube = new BodyTube();
- StreamerHandler handler = new StreamerHandler(tube, new WarningSet());
- Streamer component = (Streamer) getField(handler, "streamer");
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- handler.closeElement("Xb", attributes, "-10", warnings);
- handler.closeElement("LocationMode", attributes, "1", warnings);
- handler.endHandler("Streamer", attributes, null, warnings);
- Assert.assertEquals(RocketComponent.Position.ABSOLUTE, component.getRelativePosition());
- Assert.assertEquals(component.getPositionValue(), -10d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, 0.001);
-
- handler.closeElement("Xb", attributes, "-10", warnings);
- handler.closeElement("LocationMode", attributes, "2", warnings);
- handler.endHandler("Streamer", attributes, null, warnings);
- Assert.assertEquals(RocketComponent.Position.BOTTOM, component.getRelativePosition());
- Assert.assertEquals(component.getPositionValue(), 10d/ RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, 0.001);
-
- handler.closeElement("Thickness", attributes, "0.02", warnings);
- Assert.assertEquals(0.01848, handler.computeDensity(RocksimDensityType.ROCKSIM_BULK, 924d), 0.001);
-
- //Test Density Type 0 (Bulk)
- handler.closeElement("Density", attributes, "924.0", warnings);
- handler.closeElement("DensityType", attributes, "0", warnings);
- handler.endHandler("Streamer", attributes, null, warnings);
- Assert.assertEquals(0.01848d, component.getMaterial().getDensity(), 0.001);
-
- //Test Density Type 1 (Surface)
- handler.closeElement("Density", attributes, "0.006685", warnings);
- handler.closeElement("DensityType", attributes, "1", warnings);
- handler.endHandler("Streamer", attributes, null, warnings);
- Assert.assertTrue(Math.abs(0.06685d - component.getMaterial().getDensity()) < 0.00001);
-
- //Test Density Type 2 (Line)
- handler.closeElement("Density", attributes, "0.223225", warnings);
- handler.closeElement("DensityType", attributes, "2", warnings);
- handler.closeElement("Len", attributes, "3810.", warnings);
- handler.closeElement("Width", attributes, "203.2", warnings);
- handler.endHandler("Streamer", attributes, null, warnings);
-
- Assert.assertEquals(1.728190092, component.getMass(), 0.001);
-
- }
-
-}
+++ /dev/null
-/*
- * TransitionHandlerTest.java
- */
-package net.sf.openrocket.file.rocksim.importt;
-
-import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.ExternalComponent;
-import net.sf.openrocket.rocketcomponent.Stage;
-import net.sf.openrocket.rocketcomponent.Transition;
-import org.junit.Assert;
-
-import java.util.HashMap;
-
-/**
- * TransitionHandler Tester.
- */
-public class TransitionHandlerTest extends RocksimTestBase {
-
- /**
- * Method: constructor
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testConstructor() throws Exception {
-
- try {
- new TransitionHandler(null, new WarningSet());
- Assert.fail("Should have thrown IllegalArgumentException");
- }
- catch (IllegalArgumentException iae) {
- //success
- }
-
- Stage stage = new Stage();
- TransitionHandler handler = new TransitionHandler(stage, new WarningSet());
- Transition component = (Transition) getField(handler, "transition");
- assertContains(component, stage.getChildren());
- }
-
- /**
- * Method: openElement(String element, HashMap<String, String> attributes, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testOpenElement() throws Exception {
- Assert.assertEquals(PlainTextHandler.INSTANCE, new TransitionHandler(new Stage(), new WarningSet()).openElement(null, null, null));
- }
-
- /**
- * Method: closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testCloseElement() throws Exception {
-
- Stage stage = new Stage();
- HashMap<String, String> attributes = new HashMap<String, String>();
- WarningSet warnings = new WarningSet();
-
- TransitionHandler handler = new TransitionHandler(stage, new WarningSet());
- Transition component = (Transition) getField(handler, "transition");
-
- handler.closeElement("ShapeCode", attributes, "0", warnings);
- Assert.assertEquals(Transition.Shape.CONICAL, component.getType());
- handler.closeElement("ShapeCode", attributes, "1", warnings);
- Assert.assertEquals(Transition.Shape.OGIVE, component.getType());
- handler.closeElement("ShapeCode", attributes, "17", warnings);
- Assert.assertEquals(RocksimNoseConeCode.PARABOLIC.asOpenRocket(), component.getType()); //test of default
- handler.closeElement("ShapeCode", attributes, "foo", warnings);
- Assert.assertNotNull(component.getType());
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Len", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getLength(), 0.001);
- handler.closeElement("Len", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("FrontDia", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getForeRadius(), 0.001);
- handler.closeElement("FrontDia", attributes, "100", warnings);
- Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getForeRadius(), 0.001);
- handler.closeElement("FrontDia", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("RearDia", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getAftRadius(), 0.001);
- handler.closeElement("RearDia", attributes, "100", warnings);
- Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getAftRadius(), 0.001);
- handler.closeElement("RearDia", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- final double aft = 100d;
- component.setAftRadius(aft);
-
- handler.closeElement("ConstructionType", attributes, "0", warnings);
- component.setAftShoulderRadius(1.1d);
- component.setForeShoulderRadius(1.1d);
- handler.closeElement("WallThickness", attributes, "-1", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(component.getAftRadius(), component.getThickness(), 0.001);
- Assert.assertEquals(component.getAftShoulderThickness(), component.getAftShoulderThickness(), 0.001);
- Assert.assertEquals(component.getForeShoulderThickness(), component.getForeShoulderThickness(), 0.001);
- handler.closeElement("WallThickness", attributes, "100", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(aft, component.getThickness(), 0.001);
- handler.closeElement("WallThickness", attributes, "foo", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("ConstructionType", attributes, "1", warnings);
- component.setAftShoulderRadius(1.1d);
- component.setForeShoulderRadius(1.1d);
- handler.closeElement("WallThickness", attributes, "-1", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(0d, component.getThickness(), 0.001);
- Assert.assertEquals(0d, component.getAftShoulderThickness(), 0.001);
- Assert.assertEquals(0d, component.getForeShoulderThickness(), 0.001);
- handler.closeElement("WallThickness", attributes, "1.1", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getThickness(), 0.001);
- Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderThickness(), 0.001);
- Assert.assertEquals(1.1d/RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getForeShoulderThickness(), 0.001);
-
-
- handler.closeElement("FrontShoulderLen", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getForeShoulderLength(), 0.001);
- handler.closeElement("FrontShoulderLen", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getForeShoulderLength(), 0.001);
- handler.closeElement("FrontShoulderLen", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getForeShoulderLength(), 0.001);
- handler.closeElement("FrontShoulderLen", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("RearShoulderLen", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getAftShoulderLength(), 0.001);
- handler.closeElement("RearShoulderLen", attributes, "10", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderLength(), 0.001);
- handler.closeElement("RearShoulderLen", attributes, "10.0", warnings);
- Assert.assertEquals(10d / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH, component.getAftShoulderLength(), 0.001);
- handler.closeElement("RearShoulderLen", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("FrontShoulderDia", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getForeShoulderRadius(), 0.001);
- handler.closeElement("FrontShoulderDia", attributes, "100", warnings);
- Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getForeShoulderRadius(), 0.001);
- handler.closeElement("FrontShoulderDia", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("RearShoulderDia", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getAftShoulderRadius(), 0.001);
- handler.closeElement("RearShoulderDia", attributes, "100", warnings);
- Assert.assertEquals(100d / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS, component.getAftShoulderRadius(), 0.001);
- handler.closeElement("RearShoulderDia", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- component.setType(Transition.Shape.HAACK);
- handler.closeElement("ShapeParameter", attributes, "-1", warnings);
- Assert.assertEquals(0d, component.getShapeParameter(), 0.001);
- handler.closeElement("ShapeParameter", attributes, "100", warnings);
- Assert.assertEquals(Transition.Shape.HAACK.maxParameter(), component.getShapeParameter(), 0.001);
- handler.closeElement("ShapeParameter", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- Assert.assertEquals("Could not convert ShapeParameter value of foo. It is expected to be a number.",
- warnings.iterator().next().toString());
-
- warnings.clear();
-
- component.setType(Transition.Shape.CONICAL);
- component.setShapeParameter(0d);
- handler.closeElement("ShapeParameter", attributes, "100", warnings);
- Assert.assertEquals(0d, component.getShapeParameter(), 0.001);
-
- handler.closeElement("FinishCode", attributes, "-1", warnings);
- Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
- handler.closeElement("FinishCode", attributes, "100", warnings);
- Assert.assertEquals(ExternalComponent.Finish.NORMAL, component.getFinish());
- handler.closeElement("FinishCode", attributes, "foo", warnings);
- Assert.assertEquals(1, warnings.size());
- warnings.clear();
-
- handler.closeElement("Name", attributes, "Test Name", warnings);
- Assert.assertEquals("Test Name", component.getName());
-
- handler.closeElement("Material", attributes, "Some Material", warnings);
- handler.endHandler("Transition", attributes, null, warnings);
- Assert.assertTrue(component.getMaterial().getName().contains("Some Material"));
- }
-
- /**
- * Method: getComponent()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetComponent() throws Exception {
- Assert.assertTrue(new TransitionHandler(new Stage(), new WarningSet()).getComponent() instanceof Transition);
- }
-
- /**
- * Method: getMaterialType()
- *
- * @throws Exception thrown if something goes awry
- */
- @org.junit.Test
- public void testGetMaterialType() throws Exception {
- Assert.assertEquals(Material.Type.BULK, new TransitionHandler(new Stage(), new WarningSet()).getMaterialType());
- }
-
-
-}
+++ /dev/null
-<RockSimDocument>
-<FileVersion>3</FileVersion>
-<DesignInformation>
-<RocketDesign>
- <Name>FooBar Test</Name>
-<CalculateCD>1</CalculateCD>
-<ProCalculateCD>1</ProCalculateCD>
-<ProCalculateCN>1</ProCalculateCN>
-<FixedCd>0.75</FixedCd>
-<FixedCd2>0.8</FixedCd2>
-<FixedCd3>0.81</FixedCd3>
-<FixedCd2Alone>0.95</FixedCd2Alone>
-<FixedCd3Alone>0.95</FixedCd3Alone>
-<StageCount>1</StageCount>
-<Stage3Mass>0.</Stage3Mass>
-<Stage2Mass>0.</Stage2Mass>
-<Stage1Mass>0.</Stage1Mass>
-<Stage321CG>0.</Stage321CG>
-<Stage32CG>0.</Stage32CG>
-<Stage3CG>0.</Stage3CG>
-<Stage2CGAlone>0.</Stage2CGAlone>
-<Stage1CGAlone>0.</Stage1CGAlone>
-<CPCalcFlags>1</CPCalcFlags>
-<LaunchGuideLength>914.4</LaunchGuideLength>
-<UseKnownMass>0</UseKnownMass>
-<DefaultFinish>0</DefaultFinish>
-<FinishMedium>0</FinishMedium>
-<FinishCoatCount>1</FinishCoatCount>
-<GlueType>0</GlueType>
-<CPSimFlags>1</CPSimFlags>
-<LastSerialNumber>11</LastSerialNumber>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<BarromanXN>0,1215.49,0,0</BarromanXN>
-<BarrowmanCNa>0,35.9506,0,0</BarrowmanCNa>
-<RockSimXN>0,1226.38,0,0</RockSimXN>
-<RockSimCNa>0,47.5027,0,0</RockSimCNa>
-<RockSimCNa90>0,0,0,0</RockSimCNa90>
-<RockSimXN90>0,0,0,0</RockSimXN90>
-<ViewType>0</ViewType>
-<ViewStageCount>1</ViewStageCount>
-<ViewTypeEdit>0</ViewTypeEdit>
-<ViewStageCountEdit>1</ViewStageCountEdit>
-<ZoomFactor>0.</ZoomFactor>
-<ZoomFactorEdit>0.</ZoomFactorEdit>
-<ScrollPosX>0</ScrollPosX>
-<ScrollPosY>0</ScrollPosY>
-<ScrollPosXEdit>0</ScrollPosXEdit>
-<ScrollPosYEdit>0</ScrollPosYEdit>
-<ThreeDFlags>0</ThreeDFlags>
-<ThreeDFlagsEdit>0</ThreeDFlagsEdit>
-<UseModelSprite>0</UseModelSprite>
-<StaticMarginRef>0</StaticMarginRef>
-<UserRefDiameter>0.</UserRefDiameter>
-<SideMarkerHeight>10.</SideMarkerHeight>
-<SideDimensionHeight>10.</SideDimensionHeight>
-<BaseMarkerHeight>10.</BaseMarkerHeight>
-<BaseDimensionHeight>10.</BaseDimensionHeight>
-<ShowGlideCP>0</ShowGlideCP>
-<ShowGridTypeSide>0</ShowGridTypeSide>
-<ShowGridTypeBase>0</ShowGridTypeBase>
-<GridSpacing>10.</GridSpacing>
-<GridOpacity>0.15</GridOpacity>
-<GridColor>black</GridColor>
-<MaxDiaWithFins>424.688</MaxDiaWithFins>
-<MaxDiaWithoutFins>66.04</MaxDiaWithoutFins>
-<MaxLenWithFins>1417.95</MaxLenWithFins>
-<MaxLenWithoutFins>1332.23</MaxLenWithoutFins>
-<MinXExtent>0.</MinXExtent>
-<MaxXExtent>1417.95</MaxXExtent>
-<CalculatedMaxStageDia>0,66.04,0,0</CalculatedMaxStageDia>
-<CalculatedStageLen>0,1332.23,0,0</CalculatedStageLen>
-<Cd3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cd3>
-<Cd32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cd32>
-<Cd321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cd321>
-<Cb3>
-<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb3>
-<Cb32>
-<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb32>
-<Cb321>
-<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb321>
-<CNa3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa3>
-<CNa32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa32>
-<CNa321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa321>
-<CP3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP3>
-<CP32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP32>
-<CP321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP321>
-<SimulationEventList>
-</SimulationEventList>
-<Stage3Parts>
-<NoseCone>
-<PartMfg>Apogee</PartMfg>
-<KnownMass>24.1</KnownMass>
-<Density>1049.21</Density>
-<Material>Polystyrene PS</Material>
-<Name>Nose cone</Name>
-<KnownCG>65.3999</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>126.438</CalcMass>
-<CalcCG>348.443</CalcCG>
-<WettedSurface>0.0356487</WettedSurface>
-<PaintedSurface>0.0356487</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>19470</PartNo>
-<PartDesc>PNC-70A</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>2</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>2.</BarrowmanCNa>
-<BarrowmanXN>0.264319</BarrowmanXN>
-<RockSimCNa>2.</RockSimCNa>
-<RockSimXN>0.264319</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>0.</Station>
-<Len>396.875</Len>
-<BaseDia>57.15</BaseDia>
-<FinishCode>0</FinishCode>
-<ShapeCode>0</ShapeCode>
-<ConstructionType>1</ConstructionType>
-<ShoulderLen>58.3997</ShoulderLen>
-<WallThickness>2.159</WallThickness>
-<ShapeParameter>0.</ShapeParameter>
-<ShoulderOD>53.1012</ShoulderOD>
-<BaseExtensionLen>66.675</BaseExtensionLen>
-<CoreDia>0.</CoreDia>
-<CoreLen>0.</CoreLen>
-<AttachedParts>
-</AttachedParts>
-</NoseCone>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>10.636</CalcMass>
-<CalcCG>180.34</CalcCG>
-<WettedSurface>0.0748306</WettedSurface>
-<PaintedSurface>0.0748306</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>EST 3090</PartNo>
-<PartDesc>BT-80</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>3</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>463.55</Station>
-<OD>66.04</OD>
-<ID>65.786</ID>
-<Len>360.68</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-</AttachedParts>
-</BodyTube>
-<Transition>
-<PartMfg>BalsaMachining.com</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>128.148</Density>
-<Material>Balsa</Material>
-<Name>Transition</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>39.355</CalcMass>
-<CalcCG>37.0332</CalcCG>
-<WettedSurface>0.0096001</WettedSurface>
-<PaintedSurface>0.0096001</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>TA7080</PartNo>
-<PartDesc>Transition T70 to T80 2 in long</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>7</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>-0.92852</BarrowmanCNa>
-<BarrowmanXN>0.848729</BarrowmanXN>
-<RockSimCNa>-0.92852</RockSimCNa>
-<RockSimXN>0.848729</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>824.23</Station>
-<FrontDia>66.04</FrontDia>
-<RearDia>53.34</RearDia>
-<Len>50.8</Len>
-<FinishCode>0</FinishCode>
-<FrontShoulderLen>35.56</FrontShoulderLen>
-<RearShoulderLen>35.56</RearShoulderLen>
-<ConstructionType>0</ConstructionType>
-<WallThickness>0.</WallThickness>
-<FrontShoulderDia>55.118</FrontShoulderDia>
-<RearShoulderDia>53.34</RearShoulderDia>
-<CoreDia>0.</CoreDia>
-<ShapeCode>0</ShapeCode>
-<ShapeParameter>0.</ShapeParameter>
-<EquivNoseLen>264.12</EquivNoseLen>
-<EquivNoseOffset>213.32</EquivNoseOffset>
-<AttachedParts>
-</AttachedParts>
-</Transition>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>44.449</CalcMass>
-<CalcCG>222.25</CalcCG>
-<WettedSurface>0.0787423</WettedSurface>
-<PaintedSurface>0.0787423</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>Estes</PartNo>
-<PartDesc>BT-70</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>8</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>875.03</Station>
-<OD>56.388</OD>
-<ID>55.372</ID>
-<Len>444.5</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<FinSet>
-<PartMfg>Public Missiles</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1905.24</Density>
-<Material>G10 fiberglass</Material>
-<Name>Fin set</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>260.35</Xb>
-<CalcMass>153.85</CalcMass>
-<CalcCG>155.575</CalcCG>
-<WettedSurface>0.0339112</WettedSurface>
-<PaintedSurface>0.101734</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>FIN-A-01</PartNo>
-<PartDesc>Fins</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>9</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>34.8792</BarrowmanCNa>
-<BarrowmanXN>1.26026</BarrowmanXN>
-<RockSimCNa>46.4312</RockSimCNa>
-<RockSimXN>1.26026</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>1135.38</Station>
-<FinCount>3</FinCount>
-<RootChord>184.15</RootChord>
-<TipChord>0.</TipChord>
-<SemiSpan>184.15</SemiSpan>
-<MidChordLen>264.956</MidChordLen>
-<SweepDistance>282.575</SweepDistance>
-<Thickness>1.5875</Thickness>
-<ShapeCode>0</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>0</TipShapeCode>
-<TabLength>0.</TabLength>
-<TabDepth>0.</TabDepth>
-<TabOffset>0.</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.990003</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>89.5773</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>26.8071</RockSimCNaPerFin>
-<TaperRatio>0.</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AttachedParts>
-</AttachedParts>
-</FinSet>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>13.008</CalcMass>
-<CalcCG>228.6</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>EST 3086</PartNo>
-<PartDesc>BT-50</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>11</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>875.03</Station>
-<OD>24.7904</OD>
-<ID>24.13</ID>
-<Len>457.2</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>1</IsMotorMount>
-<MotorDia>24.</MotorDia>
-<EngineOverhang>12.7</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-</AttachedParts>
-</BodyTube>
-</AttachedParts>
-</BodyTube>
-</Stage3Parts>
-<Stage2Parts>
-</Stage2Parts>
-<Stage1Parts>
-</Stage1Parts>
-<SideViewDims>
-</SideViewDims>
-<BaseViewDims>
-</BaseViewDims>
-<VertViewDims>
-</VertViewDims>
-</RocketDesign>
-</DesignInformation>
-<SimulationResultsList>
-<SimulationResults>
-<MaxAltitude>445.129</MaxAltitude>
-<MaxVelocity>68.7587</MaxVelocity>
-<MaxAcceleration>76.6476</MaxAcceleration>
-<TimeToApogee>10.8263</TimeToApogee>
-<OptimalDelay>4.765</OptimalDelay>
-<MultiDelayCount>1</MultiDelayCount>
-<VelocityAtDeplyment>33.4284</VelocityAtDeplyment>
-<AltitudeAtDeployment>405.535</AltitudeAtDeployment>
-<DelayTime>2</DelayTime>
-<EjectTime>8.06125</EjectTime>
-<FinalState>4</FinalState>
-<TimeToBurnout>6.06125</TimeToBurnout>
-<TimeToLanding>22.4787</TimeToLanding>
-<TimeToEject>8.06125</TimeToEject>
-<MinLaunchGuideLen>1.35915</MinLaunchGuideLen>
-<MaxVertVelocity>65.9349</MaxVertVelocity>
-<MaxHorzVelocity>1.0686</MaxHorzVelocity>
-<MaxVertAcceleration>76.5426</MaxVertAcceleration>
-<MaxHorzAcceleration>4.01173</MaxHorzAcceleration>
-<MaxRange>172.076</MaxRange>
-<LaunchStartVelocity>0.</LaunchStartVelocity>
-<LaunchStartRollRate>0.</LaunchStartRollRate>
-<LaunchGuideType>0</LaunchGuideType>
-<LaunchGuideLen>1828.8</LaunchGuideLen>
-<LaunchWindDirection>0</LaunchWindDirection>
-<LaunchWindSpeed>0.</LaunchWindSpeed>
-<LaunchDirection>0</LaunchDirection>
-<LaunchAngle>0.0523599</LaunchAngle>
-<LaunchGuideAzimuth>0.</LaunchGuideAzimuth>
-<LaunchGuideElevation>0.</LaunchGuideElevation>
-<LaunchBarometer>770.314</LaunchBarometer>
-<LaunchLatitude>43.</LaunchLatitude>
-<LaunchLongitude>0.</LaunchLongitude>
-<LaunchHumidity>70.</LaunchHumidity>
-<LaunchTemperature>7.22222</LaunchTemperature>
-<LaunchAltitude>304.8</LaunchAltitude>
-<LaunchLandingAltitude>0.</LaunchLandingAltitude>
-<CompStateMask>0</CompStateMask>
-<LaunchWindPreset>3</LaunchWindPreset>
-<LaunchWindLowSpeed>1.34112</LaunchWindLowSpeed>
-<LaunchWindHighSpeed>3.53162</LaunchWindHighSpeed>
-<LaunchWindTurbulencePreset>2</LaunchWindTurbulencePreset>
-<LaunchWindFrequency>0.01</LaunchWindFrequency>
-<LaunchWindDeltaFrequency>0.02</LaunchWindDeltaFrequency>
-<LaunchUseRandomConditions>0</LaunchUseRandomConditions>
-<LaunchCloudCoverPreset>5</LaunchCloudCoverPreset>
-<LaunchCCLow>0.</LaunchCCLow>
-<LaunchCCHigh>0.1</LaunchCCHigh>
-<LaunchThermalPosPreset>1</LaunchThermalPosPreset>
-<LaunchThermalPos>0.</LaunchThermalPos>
-<LaunchMultipleThermals>0</LaunchMultipleThermals>
-<LaunchMaxThermals>3</LaunchMaxThermals>
-<LaunchThermalDia>300.</LaunchThermalDia>
-<LaunchThermalHeight>2000.</LaunchThermalHeight>
-<LaunchThermalSpeedPreset>1</LaunchThermalSpeedPreset>
-<LaunchThermalSpeed>5.99999</LaunchThermalSpeed>
-<LaunchWindTableSize>0</LaunchWindTableSize>
-<LaunchWindAltTable>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</LaunchWindAltTable>
-<LaunchWindSpeedTable>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</LaunchWindSpeedTable>
-<LaunchWindDirectionTable>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</LaunchWindDirectionTable>
-<LaunchLossPreset>2</LaunchLossPreset>
-<LaunchLossPercent>0.99</LaunchLossPercent>
-<LaunchSiteDia>2000.</LaunchSiteDia>
-<LaunchDriftRangeToLoss>1500.</LaunchDriftRangeToLoss>
-<LaunchPayloadDamagePreset>2</LaunchPayloadDamagePreset>
-<LaunchPayloadDamagePercent>0.98</LaunchPayloadDamagePercent>
-<LaunchEngineMisfirePreset>1</LaunchEngineMisfirePreset>
-<LaunchEngineMisfirePercent>0.</LaunchEngineMisfirePercent>
-<LaunchVariableIgnitionDelay>0</LaunchVariableIgnitionDelay>
-<LaunchVariableIgnitionDelaySec>0.08</LaunchVariableIgnitionDelaySec>
-<LaunchRecDeviceFailurePreset>1</LaunchRecDeviceFailurePreset>
-<LaunchRecDeviceFailurePercent>0.</LaunchRecDeviceFailurePercent>
-<LaunchAriframeFailurePreset>1</LaunchAriframeFailurePreset>
-<LaunchAirframeFailurePercent>0.</LaunchAirframeFailurePercent>
-<LaunchTrackLossPreset>1</LaunchTrackLossPreset>
-<LaunchTeckLossPercent>0.</LaunchTeckLossPercent>
-<CNaMultiplier>1.</CNaMultiplier>
-<CdMultiplier>1.</CdMultiplier>
-<CPOffset>0.</CPOffset>
-<SaveSimAsText>0</SaveSimAsText>
-<OutputAtMaxRes>0</OutputAtMaxRes>
-<MaxSimTim>3600.</MaxSimTim>
-<MassUncertainty>0.</MassUncertainty>
-<MOIUncertainty>0.</MOIUncertainty>
-<CGUncertainty>0.</CGUncertainty>
-<CdUncertainty>0.</CdUncertainty>
-<CnaUncertainty>0.</CnaUncertainty>
-<CPUncertainty>0.</CPUncertainty>
-<FinCantUncertainty>0.</FinCantUncertainty>
-<TotImpulseUncertainty>0.</TotImpulseUncertainty>
-<PropellantUncertainty>0.</PropellantUncertainty>
-<ThrustAxisUncertainty>0.</ThrustAxisUncertainty>
-<WindDirectionUncertainty>0.</WindDirectionUncertainty>
-<WindVelocityUncertainty>0.</WindVelocityUncertainty>
-<LaunchGuideAzimuthUncertainty>0.</LaunchGuideAzimuthUncertainty>
-<LaunchGuideElevationUncertainty>0.</LaunchGuideElevationUncertainty>
-<IgnitionUncertainty>0.</IgnitionUncertainty>
-<CATOUncertainty>0.</CATOUncertainty>
-<DeploymentUncertainty>0.</DeploymentUncertainty>
-<RecoveryDeviceUncertainty>0.</RecoveryDeviceUncertainty>
-<SimulationName>[E6-2] </SimulationName>
-<VelocityAtLaunchGuideEnd>15.4098</VelocityAtLaunchGuideEnd>
-<WindStartAltitude>0.</WindStartAltitude>
-<TimeToWindShear>0.</TimeToWindShear>
-<TimeToFreeFlight>0.25875</TimeToFreeFlight>
-<TimeToMaxVelocity>5.69125</TimeToMaxVelocity>
-<TimeToMaxAcceleration>0.11125</TimeToMaxAcceleration>
-<Nsims>10</Nsims>
-<CalcResolution>1</CalcResolution>
-<SamplesPerSecond>800.</SamplesPerSecond>
-<SimulationType>0</SimulationType>
-<LocationDataServerName>Earth</LocationDataServerName>
-<LocationDataServerDisplayName>Standard earth condistions.</LocationDataServerDisplayName>
-<ExecutionTime>4.078</ExecutionTime>
-<RangeAtLanding>-172.076</RangeAtLanding>
-<DirectionAtLanding>0.</DirectionAtLanding>
-<VelocityAtLanding>56.537</VelocityAtLanding>
-<XVelcoityAtLanding>-3.38254</XVelcoityAtLanding>
-<YVelocityAtLanding>-56.4357</YVelocityAtLanding>
-<ZVelocityAtLanding>0.</ZVelocityAtLanding>
-<StageSeparationTime>0,0,8.06125,0,0</StageSeparationTime>
-<StageEjectTime>-1,-1,-1,-1,-1</StageEjectTime>
-<TimeToDeployment>0,0,0,0,0</TimeToDeployment>
-<DeploymentType>32,32,32,32,32</DeploymentType>
-<SamplesPerSecondDescent>1.</SamplesPerSecondDescent>
-<CalculationFlags>1</CalculationFlags>
-<Mass0>0.233111</Mass0>
-<CG0>0.739954</CG0>
-<LaterialMOI0>0.0208295</LaterialMOI0>
-<RadialMOI0>0.000194272</RadialMOI0>
-<GUID>{b33e529e-1ada-4524-9885-7382d7cf4d64}</GUID>
-<Booster1Staging>
-<SimulationEvent>
-<PartSerialNo>0</PartSerialNo>
-<Type>0</Type>
-<DeployAltitude>0.</DeployAltitude>
-<DeplyTime>0.</DeplyTime>
-<HasDeployed>0</HasDeployed>
-<DeployedAt_Altitude>0.</DeployedAt_Altitude>
-<DeployedAt_Velocity>0.</DeployedAt_Velocity>
-<DeployedAt_Range>0.</DeployedAt_Range>
-<DeployedAt_Time>0.</DeployedAt_Time>
-<DeviceID>-1</DeviceID>
-<TestType>0,0,0</TestType>
-<TestCondition>0,0,0</TestCondition>
-<TestValueAltitude>0,0,0</TestValueAltitude>
-<TestValueDegrees>0,0,0</TestValueDegrees>
-<TestValuePressure>0,0,0</TestValuePressure>
-<TestValueMach>0,0,0</TestValueMach>
-<TestValueTime>0,0,0</TestValueTime>
-<TestValueQ>0,0,0</TestValueQ>
-</SimulationEvent>
-</Booster1Staging>
-<Booster2Staging>
-<SimulationEvent>
-<PartSerialNo>0</PartSerialNo>
-<Type>0</Type>
-<DeployAltitude>0.</DeployAltitude>
-<DeplyTime>0.</DeplyTime>
-<HasDeployed>0</HasDeployed>
-<DeployedAt_Altitude>0.</DeployedAt_Altitude>
-<DeployedAt_Velocity>0.</DeployedAt_Velocity>
-<DeployedAt_Range>0.</DeployedAt_Range>
-<DeployedAt_Time>0.</DeployedAt_Time>
-<DeviceID>-1</DeviceID>
-<TestType>0,0,0</TestType>
-<TestCondition>0,0,0</TestCondition>
-<TestValueAltitude>0,0,0</TestValueAltitude>
-<TestValueDegrees>0,0,0</TestValueDegrees>
-<TestValuePressure>0,0,0</TestValuePressure>
-<TestValueMach>0,0,0</TestValueMach>
-<TestValueTime>0,0,0</TestValueTime>
-<TestValueQ>0,0,0</TestValueQ>
-</SimulationEvent>
-</Booster2Staging>
-<SimulationEvents>
-</SimulationEvents>
-<Stage1Engines>
-</Stage1Engines>
-<Stage2Engines>
-</Stage2Engines>
-<Stage3Engines>
-<EngineSet>
-<EngineCount>1</EngineCount>
-<EngineCode>E6</EngineCode>
-<IgnitionDelay>0.</IgnitionDelay>
-<EngineMfg>Apogee</EngineMfg>
-<EngineOverhang>0.50038</EngineOverhang>
-<CasingCG>0.</CasingCG>
-<MountSerialNo>5</MountSerialNo>
-<EjectionDelay>2.</EjectionDelay>
-<RotateXaboutY>0.</RotateXaboutY>
-<RotateEngineAxisAboutX>0.</RotateEngineAxisAboutX>
-</EngineSet>
-</Stage3Engines>
-<DropItems>
-</DropItems>
-</SimulationResults>
-</SimulationResultsList>
-</RockSimDocument>
+++ /dev/null
-<RockSimDocument>
-<FileVersion>3</FileVersion>
-<DesignInformation>
-<RocketDesign>
-<Name>Three Stage Everything Included Rocket</Name>
-<CalculateCD>1</CalculateCD>
-<ProCalculateCD>1</ProCalculateCD>
-<ProCalculateCN>1</ProCalculateCN>
-<FixedCd>0.75</FixedCd>
-<FixedCd2>0.8</FixedCd2>
-<FixedCd3>0.81</FixedCd3>
-<FixedCd2Alone>0.95</FixedCd2Alone>
-<FixedCd3Alone>0.95</FixedCd3Alone>
-<StageCount>3</StageCount>
-<Stage3Mass>0.</Stage3Mass>
-<Stage2Mass>0.</Stage2Mass>
-<Stage1Mass>0.</Stage1Mass>
-<Stage321CG>0.</Stage321CG>
-<Stage32CG>0.</Stage32CG>
-<Stage3CG>0.</Stage3CG>
-<Stage2CGAlone>0.</Stage2CGAlone>
-<Stage1CGAlone>0.</Stage1CGAlone>
-<CPCalcFlags>1</CPCalcFlags>
-<LaunchGuideLength>914.4</LaunchGuideLength>
-<UseKnownMass>0</UseKnownMass>
-<DefaultFinish>0</DefaultFinish>
-<FinishMedium>0</FinishMedium>
-<FinishCoatCount>1</FinishCoatCount>
-<GlueType>0</GlueType>
-<CPSimFlags>1</CPSimFlags>
-<LastSerialNumber>25</LastSerialNumber>
-<DisplayFlags>7</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<BarromanXN>0,29.6333,326.159,887.03</BarromanXN>
-<BarrowmanCNa>0,2,4.93008,33.0782</BarrowmanCNa>
-<RockSimXN>0,29.6333,384.174,883.929</RockSimXN>
-<RockSimCNa>0,2,6.91103,47.1184</RockSimCNa>
-<RockSimCNa90>0,0,0,0</RockSimCNa90>
-<RockSimXN90>0,0,0,0</RockSimXN90>
-<ViewType>0</ViewType>
-<ViewStageCount>3</ViewStageCount>
-<ViewTypeEdit>0</ViewTypeEdit>
-<ViewStageCountEdit>3</ViewStageCountEdit>
-<ZoomFactor>0.</ZoomFactor>
-<ZoomFactorEdit>0.</ZoomFactorEdit>
-<ScrollPosX>0</ScrollPosX>
-<ScrollPosY>0</ScrollPosY>
-<ScrollPosXEdit>0</ScrollPosXEdit>
-<ScrollPosYEdit>0</ScrollPosYEdit>
-<ThreeDFlags>0</ThreeDFlags>
-<ThreeDFlagsEdit>0</ThreeDFlagsEdit>
-<UseModelSprite>0</UseModelSprite>
-<StaticMarginRef>0</StaticMarginRef>
-<UserRefDiameter>0.</UserRefDiameter>
-<SideMarkerHeight>10.</SideMarkerHeight>
-<SideDimensionHeight>10.</SideDimensionHeight>
-<BaseMarkerHeight>10.</BaseMarkerHeight>
-<BaseDimensionHeight>10.</BaseDimensionHeight>
-<ShowGlideCP>0</ShowGlideCP>
-<ShowGridTypeSide>0</ShowGridTypeSide>
-<ShowGridTypeBase>0</ShowGridTypeBase>
-<GridSpacing>10.</GridSpacing>
-<GridOpacity>0.15</GridOpacity>
-<GridColor>black</GridColor>
-<MaxDiaWithFins>339.43</MaxDiaWithFins>
-<MaxDiaWithoutFins>66.3</MaxDiaWithoutFins>
-<MaxLenWithFins>2104.53</MaxLenWithFins>
-<MaxLenWithoutFins>2104.53</MaxLenWithoutFins>
-<MinXExtent>0.</MinXExtent>
-<MaxXExtent>1150.33</MaxXExtent>
-<CalculatedMaxStageDia>0,66.3,66.3,66.3</CalculatedMaxStageDia>
-<CalculatedStageLen>0,296.8,954.2,2104.53</CalculatedStageLen>
-<Cd3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cd3>
-<Cd32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cd32>
-<Cd321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cd321>
-<Cb3>
-<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb3>
-<Cb32>
-<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb32>
-<Cb321>
-<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb321>
-<CNa3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa3>
-<CNa32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa32>
-<CNa321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa321>
-<CP3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP3>
-<CP32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP32>
-<CP321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP321>
-<SimulationEventList>
-</SimulationEventList>
-<Stage3Parts>
-<NoseCone>
-<PartMfg>Aerospace Speciality Products</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>128.148</Density>
-<Material>Balsa</Material>
-<Name>Nose cone</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>42.0747</CalcMass>
-<CalcCG>75.3029</CalcCG>
-<WettedSurface>0.0152945</WettedSurface>
-<PaintedSurface>0.0152945</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>BNC80S</PartNo>
-<PartDesc><![CDATA[T-80H Balsa Nose Cone "S"]]></PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>1</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>2.</BarrowmanCNa>
-<BarrowmanXN>0.0296333</BarrowmanXN>
-<RockSimCNa>2.</RockSimCNa>
-<RockSimXN>0.0296333</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>0.</Station>
-<Len>88.9</Len>
-<BaseDia>66.3</BaseDia>
-<FinishCode>0</FinishCode>
-<ShapeCode>3</ShapeCode>
-<ConstructionType>0</ConstructionType>
-<ShoulderLen>38.1</ShoulderLen>
-<WallThickness>0.</WallThickness>
-<ShapeParameter>0.</ShapeParameter>
-<ShoulderOD>64.3</ShoulderOD>
-<BaseExtensionLen>0.</BaseExtensionLen>
-<CoreDia>0.</CoreDia>
-<CoreLen>0.</CoreLen>
-<AttachedParts>
-<MassObject>
-<PartMfg>Custom</PartMfg>
-<KnownMass>20.</KnownMass>
-<Density>0.</Density>
-<Material>Custom</Material>
-<Name>Clay</Name>
-<KnownCG>17.8</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>17.8</Xb>
-<CalcMass>0.</CalcMass>
-<CalcCG>0.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>2</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>17.8</Station>
-<TypeCode>0</TypeCode>
-<Len>0.</Len>
-<AttachedParts>
-</AttachedParts>
-</MassObject>
-<BodyTube>
-<PartMfg>Apogee</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Attachment Rod</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>6.1</Xb>
-<CalcMass>2.47301</CalcMass>
-<CalcCG>78.85</CalcCG>
-<WettedSurface>0.00684683</WettedSurface>
-<PaintedSurface>0.00684683</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>10062</PartNo>
-<PartDesc>13 mm</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>3</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>6.1</Station>
-<OD>13.82</OD>
-<ID>13.16</ID>
-<Len>157.7</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Plate</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>78.9</Xb>
-<CalcMass>7.86272</CalcMass>
-<CalcCG>1.585</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-(2)0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>4</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>85.</Station>
-<OD>66.</OD>
-<ID>13.82</ID>
-<Len>3.17</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Ring>
-<PartMfg>Custom</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1400.</Density>
-<Material>Carbon Fiber</Material>
-<Name>Sleeve </Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>17.5527</CalcMass>
-<CalcCG>13.85</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>5</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>2</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>136.1</Station>
-<OD>27.7</OD>
-<ID>13.82</ID>
-<Len>27.7</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>3</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Parachute>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>170.</KnownMass>
-<Density>0.006685</Density>
-<Material>Rip stop nylon</Material>
-<Name>Nose Cone Parachute</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>142.6</Xb>
-<CalcMass>15.8812</CalcMass>
-<CalcCG>34.5417</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>1</DensityType>
-<PartNo>LP-50</PartNo>
-<PartDesc>50 In. 16 lines</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>6</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>148.7</Station>
-<Dia>414.5</Dia>
-<SpillHoleDia>0.</SpillHoleDia>
-<SideCount>15</SideCount>
-<ShroudLineCount>16</ShroudLineCount>
-<Thickness>0.05</Thickness>
-<ShroudLineLen>1350.</ShroudLineLen>
-<ChuteCount>1</ChuteCount>
-<ShroudLineMassPerMM>0.00032972</ShroudLineMassPerMM>
-<ShroudLineMaterial>Carpet String (Apogee 29500)</ShroudLineMaterial>
-<DragCoefficient>0.95</DragCoefficient>
-<AttachedParts>
-</AttachedParts>
-</Parachute>
-</AttachedParts>
-</BodyTube>
-</AttachedParts>
-</NoseCone>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>15.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>100.</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>5.80486</CalcMass>
-<CalcCG>100.</CalcCG>
-<WettedSurface>0.0414942</WettedSurface>
-<PaintedSurface>0.0414942</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>EST 3090</PartNo>
-<PartDesc>BT-80</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>7</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(54,250,21)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>88.9</Station>
-<OD>66.04</OD>
-<ID>65.79</ID>
-<Len>200.</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>190.2</Xb>
-<CalcMass>7.65502</CalcMass>
-<CalcCG>1.59</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>8</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>279.1</Station>
-<OD>65.02</OD>
-<ID>25.4</ID>
-<Len>3.18</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>165.</Xb>
-<CalcMass>7.62626</CalcMass>
-<CalcCG>1.585</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-(2)0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>9</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>253.9</Station>
-<OD>65.</OD>
-<ID>25.4</ID>
-<Len>3.17</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<BodyTube>
-<PartMfg>Public Missiles Ltd.</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>958.705</Density>
-<Material>Kraft phenolic</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>137.9</Xb>
-<CalcMass>9.8818</CalcMass>
-<CalcCG>35.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>KS-1.1</PartNo>
-<PartDesc>KwikSwitch MMT 29mm</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>-1.58371</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>10</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>226.8</Station>
-<OD>32.26</OD>
-<ID>29.21</ID>
-<Len>70.</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>1</IsMotorMount>
-<MotorDia>29.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-</AttachedParts>
-</BodyTube>
-</AttachedParts>
-</BodyTube>
-</Stage3Parts>
-<Stage2Parts>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>2nd Stage Tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>10.4685</CalcMass>
-<CalcCG>180.34</CalcCG>
-<WettedSurface>0.0748306</WettedSurface>
-<PaintedSurface>0.0748306</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>EST 3090</PartNo>
-<PartDesc>BT-80</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>11</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(54,250,21)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>288.9</Station>
-<OD>66.04</OD>
-<ID>65.79</ID>
-<Len>360.68</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>15.025</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Tube coupler</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>-10.</Xb>
-<CalcMass>20.465</CalcMass>
-<CalcCG>35.45</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>TC-2.56</PartNo>
-<PartDesc>Tube Coupler</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>12</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>278.9</Station>
-<OD>65.79</OD>
-<ID>63.25</ID>
-<Len>70.9</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>4</UsageCode>
-<AutoSize>1</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<MassObject>
-<PartMfg>Custom</PartMfg>
-<KnownMass>40.</KnownMass>
-<Density>0.</Density>
-<Material>Custom</Material>
-<Name>Electronics</Name>
-<KnownCG>138.3</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>138.3</Xb>
-<CalcMass>0.</CalcMass>
-<CalcCG>0.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>13</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>427.2</Station>
-<TypeCode>0</TypeCode>
-<Len>0.</Len>
-<AttachedParts>
-</AttachedParts>
-</MassObject>
-<FinSet>
-<PartMfg>Quest</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>128.148</Density>
-<Material>Balsa</Material>
-<Name>Fin set</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>228.6</Xb>
-<CalcMass>1.32269</CalcMass>
-<CalcCG>19.05</CalcCG>
-<WettedSurface>0.0028791</WettedSurface>
-<PaintedSurface>0.0086373</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>Payloader One</PartNo>
-<PartDesc>Fin</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.0830777</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>14</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>2.93008</BarrowmanCNa>
-<BarrowmanXN>0.52856</BarrowmanXN>
-<RockSimCNa>5.49629</RockSimCNa>
-<RockSimXN>0.52856</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>517.5</Station>
-<FinCount>3</FinCount>
-<RootChord>38.1</RootChord>
-<TipChord>24.9</TipChord>
-<SemiSpan>45.7</SemiSpan>
-<MidChordLen>45.7</MidChordLen>
-<SweepDistance>6.6</SweepDistance>
-<Thickness>2.39</Thickness>
-<ShapeCode>0</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>2</TipShapeCode>
-<TabLength>0.</TabLength>
-<TabDepth>0.</TabDepth>
-<TabOffset>0.</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.139993</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>54.2741</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>2.83538</RockSimCNaPerFin>
-<TaperRatio>0.653543</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AttachedParts>
-</AttachedParts>
-</FinSet>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>302.</Xb>
-<CalcMass>7.65502</CalcMass>
-<CalcCG>1.59</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>15</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>590.9</Station>
-<OD>65.02</OD>
-<ID>25.4</ID>
-<Len>3.18</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>335.5</Xb>
-<CalcMass>7.62626</CalcMass>
-<CalcCG>1.585</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-(2)0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>16</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>624.4</Station>
-<OD>65.</OD>
-<ID>25.4</ID>
-<Len>3.17</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<BodyTube>
-<PartMfg>Public Missiles Ltd.</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>958.705</Density>
-<Material>Kraft phenolic</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>587.4</Xb>
-<CalcMass>9.8818</CalcMass>
-<CalcCG>35.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>KS-1.1</PartNo>
-<PartDesc>KwikSwitch MMT 29mm</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>-1.58371</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>17</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>1</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>587.4</Station>
-<OD>32.26</OD>
-<ID>29.21</ID>
-<Len>70.</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>1</IsMotorMount>
-<MotorDia>29.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<Ring>
-<PartMfg>Semroc</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Engine block</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>2.69315</CalcMass>
-<CalcCG>2.39</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>TB-7</PartNo>
-<PartDesc>Thrust Block</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>18</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>587.4</Station>
-<OD>29.21</OD>
-<ID>14.61</ID>
-<Len>4.78</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>2</UsageCode>
-<AutoSize>1</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-</AttachedParts>
-</BodyTube>
-</AttachedParts>
-</BodyTube>
-</Stage2Parts>
-<Stage1Parts>
-<Transition>
-<PartMfg>BalsaMachining.com</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>128.148</Density>
-<Material>Balsa</Material>
-<Name>Transition</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>8.62096</CalcMass>
-<CalcCG>25.1578</CalcCG>
-<WettedSurface>0.00986655</WettedSurface>
-<PaintedSurface>0.00986655</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>TA6080</PartNo>
-<PartDesc>Transition T60 to T80 2.25 in long</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>19</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>-1.20451</BarrowmanCNa>
-<BarrowmanXN>0.675971</BarrowmanXN>
-<RockSimCNa>-1.20451</RockSimCNa>
-<RockSimXN>0.675971</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>649.58</Station>
-<FrontDia>66.04</FrontDia>
-<RearDia>41.4</RearDia>
-<Len>57.15</Len>
-<FinishCode>0</FinishCode>
-<FrontShoulderLen>20.</FrontShoulderLen>
-<RearShoulderLen>38.1</RearShoulderLen>
-<ConstructionType>1</ConstructionType>
-<WallThickness>3.</WallThickness>
-<FrontShoulderDia>64.77</FrontShoulderDia>
-<RearShoulderDia>41.38</RearShoulderDia>
-<CoreDia>0.</CoreDia>
-<ShapeCode>0</ShapeCode>
-<ShapeParameter>0.</ShapeParameter>
-<EquivNoseLen>153.172</EquivNoseLen>
-<EquivNoseOffset>96.022</EquivNoseOffset>
-<AttachedParts>
-</AttachedParts>
-</Transition>
-<BodyTube>
-<PartMfg>LOC/Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>33.5306</CalcMass>
-<CalcCG>209.2</CalcCG>
-<WettedSurface>0.0604643</WettedSurface>
-<PaintedSurface>0.0604643</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC BT-2.14</PartNo>
-<PartDesc>Airframe tube</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>20</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(54,250,21)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>706.73</Station>
-<OD>46.</OD>
-<ID>45.</ID>
-<Len>418.4</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<FinSet>
-<PartMfg>Quest</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Elliptical Fins</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>69.7</Xb>
-<CalcMass>36.2048</CalcMass>
-<CalcCG>46.</CalcCG>
-<WettedSurface>0.00676907</WettedSurface>
-<PaintedSurface>0.0203072</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>-0.519061</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>21</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>3.64017</BarrowmanCNa>
-<BarrowmanXN>0.802926</BarrowmanXN>
-<RockSimCNa>6.19583</RockSimCNa>
-<RockSimXN>0.802926</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>776.43</Station>
-<FinCount>3</FinCount>
-<RootChord>92.</RootChord>
-<TipChord>46.</TipChord>
-<SemiSpan>46.9</SemiSpan>
-<MidChordLen>46.9</MidChordLen>
-<SweepDistance>33.49</SweepDistance>
-<Thickness>3.18</Thickness>
-<ShapeCode>1</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>0</TipShapeCode>
-<TabLength>0.</TabLength>
-<TabDepth>0.</TabDepth>
-<TabOffset>0.</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.349066</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>43.8444</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>3.30201</RockSimCNaPerFin>
-<TaperRatio>0.5</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AttachedParts>
-</AttachedParts>
-</FinSet>
-<CustomFinSet>
-<PartMfg>Public Missiles</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1905.24</Density>
-<Material>G10 fiberglass</Material>
-<Name>Custom Fins</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>241.7</Xb>
-<CalcMass>256.292</CalcMass>
-<CalcCG>78.9922</CalcCG>
-<WettedSurface>0.0355266</WettedSurface>
-<PaintedSurface>0.10658</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>FIN-C-02</PartNo>
-<PartDesc>Fins</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.357967</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>22</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>25.7124</BarrowmanCNa>
-<BarrowmanXN>0.996591</BarrowmanXN>
-<RockSimCNa>34.6308</RockSimCNa>
-<RockSimXN>0.996926</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>948.43</Station>
-<FinCount>3</FinCount>
-<RootChord>152.4</RootChord>
-<TipChord>83.83</TipChord>
-<SemiSpan>146.72</SemiSpan>
-<MidChordLen>146.81</MidChordLen>
-<SweepDistance>39.42</SweepDistance>
-<Thickness>2.38</Thickness>
-<ShapeCode>2</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>2</TipShapeCode>
-<TabLength>101.6</TabLength>
-<TabDepth>10.6</TabDepth>
-<TabOffset>35.6</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>89.2598</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>19.9941</RockSimCNaPerFin>
-<TaperRatio>0.550066</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AverageChord>121.07</AverageChord>
-<EffectiveTipChord>83.8257</EffectiveTipChord>
-<PointList>152.4,0|126.202,146.715|36.455,146.715|0,0|</PointList>
-<AutoCalcGridStepX>0,0,0,0,0,0,0</AutoCalcGridStepX>
-<GridStepCountX>10,10,10,10,10,10,10</GridStepCountX>
-<UseAbsoluteGridStepsX>0,0,0,0,0,0,0</UseAbsoluteGridStepsX>
-<GridStepSizeX>0.5,10,0.5,0.5,0.00018939,0.001,1</GridStepSizeX>
-<SnapToSizeX>0.25,5,0.1,0.1,0.00018939,0.001,1</SnapToSizeX>
-<AutoCalcGridStepY>0,0,0,0,0,0,0</AutoCalcGridStepY>
-<GridStepCountY>10,10,10,10,10,10,10</GridStepCountY>
-<UseAbsoluteGridStepsY>0,0,0,0,0,0,0</UseAbsoluteGridStepsY>
-<GridStepSizeY>0.5,10,0.5,0.5,0.00018939,0.001,1</GridStepSizeY>
-<SnapToSizeY>0.25,5,0.1,0.1,0.00018939,0.001,1</SnapToSizeY>
-<AttachedParts>
-</AttachedParts>
-</CustomFinSet>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>379.5</Xb>
-<CalcMass>2.55395</CalcMass>
-<CalcCG>1.59</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC FCR-1.52-1.14</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>23</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>1086.23</Station>
-<OD>45.</OD>
-<ID>24.79</ID>
-<Len>3.18</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>1</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>272.</Xb>
-<CalcMass>2.55395</CalcMass>
-<CalcCG>1.59</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC FCR-1.52-1.14</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>24</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>978.73</Station>
-<OD>45.</OD>
-<ID>24.79</ID>
-<Len>3.18</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>1</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>259.7</Xb>
-<CalcMass>5.22902</CalcMass>
-<CalcCG>91.95</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>EST 3086</PartNo>
-<PartDesc>BT-50</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>25</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>966.43</Station>
-<OD>24.79</OD>
-<ID>24.13</ID>
-<Len>183.9</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>1</IsMotorMount>
-<MotorDia>24.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-</AttachedParts>
-</BodyTube>
-</AttachedParts>
-</BodyTube>
-</Stage1Parts>
-<SideViewDims>
-</SideViewDims>
-<BaseViewDims>
-</BaseViewDims>
-<VertViewDims>
-</VertViewDims>
-</RocketDesign>
-</DesignInformation>
-<SimulationResultsList>
-</SimulationResultsList>
-</RockSimDocument>
+++ /dev/null
-<RockSimDocument>
-<FileVersion>3</FileVersion>
-<DesignInformation>
-<RocketDesign>
-<Name>Three Stage Everything Included Rocket - Override Total Mass/CG</Name>
-<CalculateCD>1</CalculateCD>
-<ProCalculateCD>1</ProCalculateCD>
-<ProCalculateCN>1</ProCalculateCN>
-<FixedCd>0.75</FixedCd>
-<FixedCd2>0.8</FixedCd2>
-<FixedCd3>0.81</FixedCd3>
-<FixedCd2Alone>0.95</FixedCd2Alone>
-<FixedCd3Alone>0.95</FixedCd3Alone>
-<StageCount>3</StageCount>
-<Stage3Mass>185.</Stage3Mass>
-<Stage2Mass>210.</Stage2Mass>
-<Stage1Mass>330.</Stage1Mass>
-<Stage321CG>0.</Stage321CG>
-<Stage32CG>0.</Stage32CG>
-<Stage3CG>300.</Stage3CG>
-<Stage2CGAlone>400.</Stage2CGAlone>
-<Stage1CGAlone>500.</Stage1CGAlone>
-<CPCalcFlags>1</CPCalcFlags>
-<LaunchGuideLength>914.4</LaunchGuideLength>
-<UseKnownMass>0</UseKnownMass>
-<DefaultFinish>0</DefaultFinish>
-<FinishMedium>0</FinishMedium>
-<FinishCoatCount>1</FinishCoatCount>
-<GlueType>0</GlueType>
-<CPSimFlags>1</CPSimFlags>
-<LastSerialNumber>32</LastSerialNumber>
-<DisplayFlags>7</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<BarromanXN>0,29.6333,327.236,966.855</BarromanXN>
-<BarrowmanCNa>0,2,4.95647,83.562</BarrowmanCNa>
-<RockSimXN>0,29.6333,385.082,953.76</RockSimXN>
-<RockSimCNa>0,2,6.95476,97.0629</RockSimCNa>
-<RockSimCNa90>0,0,0,0</RockSimCNa90>
-<RockSimXN90>0,0,0,0</RockSimXN90>
-<ViewType>0</ViewType>
-<ViewStageCount>3</ViewStageCount>
-<ViewTypeEdit>0</ViewTypeEdit>
-<ViewStageCountEdit>3</ViewStageCountEdit>
-<ZoomFactor>0.</ZoomFactor>
-<ZoomFactorEdit>0.</ZoomFactorEdit>
-<ScrollPosX>0</ScrollPosX>
-<ScrollPosY>0</ScrollPosY>
-<ScrollPosXEdit>0</ScrollPosXEdit>
-<ScrollPosYEdit>0</ScrollPosYEdit>
-<ThreeDFlags>0</ThreeDFlags>
-<ThreeDFlagsEdit>0</ThreeDFlagsEdit>
-<UseModelSprite>0</UseModelSprite>
-<StaticMarginRef>0</StaticMarginRef>
-<UserRefDiameter>0.</UserRefDiameter>
-<SideMarkerHeight>10.</SideMarkerHeight>
-<SideDimensionHeight>10.</SideDimensionHeight>
-<BaseMarkerHeight>10.</BaseMarkerHeight>
-<BaseDimensionHeight>10.</BaseDimensionHeight>
-<ShowGlideCP>0</ShowGlideCP>
-<ShowGridTypeSide>0</ShowGridTypeSide>
-<ShowGridTypeBase>0</ShowGridTypeBase>
-<GridSpacing>10.</GridSpacing>
-<GridOpacity>0.15</GridOpacity>
-<GridColor>black</GridColor>
-<MaxDiaWithFins>334.83</MaxDiaWithFins>
-<MaxDiaWithoutFins>66.</MaxDiaWithoutFins>
-<MaxLenWithFins>2155.23</MaxLenWithFins>
-<MaxLenWithoutFins>2155.23</MaxLenWithoutFins>
-<MinXExtent>0.</MinXExtent>
-<MaxXExtent>1150.33</MaxXExtent>
-<CalculatedMaxStageDia>0,66,66,66</CalculatedMaxStageDia>
-<CalculatedStageLen>0,347.5,1004.9,2155.23</CalculatedStageLen>
-<Cd3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cd3>
-<Cd32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cd32>
-<Cd321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cd321>
-<Cb3>
-<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb3>
-<Cb32>
-<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb32>
-<Cb321>
-<PolyData useXYOnly="1" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</Cb321>
-<CNa3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa3>
-<CNa32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa32>
-<CNa321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CNa321>
-<CP3>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP3>
-<CP32>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP32>
-<CP321>
-<PolyData useXYOnly="0" useSmoothCurveEvaluation="0" count="0">
-<X-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</X-data>
-<A-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</A-data>
-<B-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</B-data>
-<C-data>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</C-data>
-</PolyData>
-</CP321>
-<SimulationEventList>
-</SimulationEventList>
-<Stage3Parts>
-<NoseCone>
-<PartMfg>Aerospace Speciality Products</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>128.148</Density>
-<Material>Balsa</Material>
-<Name>Nose cone</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>42.6368</CalcMass>
-<CalcCG>76.0242</CalcCG>
-<WettedSurface>0.0152192</WettedSurface>
-<PaintedSurface>0.0152192</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>BNC80S</PartNo>
-<PartDesc><![CDATA[T-80H Balsa Nose Cone "S"]]></PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>1</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>2.</BarrowmanCNa>
-<BarrowmanXN>0.0296333</BarrowmanXN>
-<RockSimCNa>2.</RockSimCNa>
-<RockSimXN>0.0296333</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>0.</Station>
-<Len>88.9</Len>
-<BaseDia>66.</BaseDia>
-<FinishCode>0</FinishCode>
-<ShapeCode>3</ShapeCode>
-<ConstructionType>0</ConstructionType>
-<ShoulderLen>38.1</ShoulderLen>
-<WallThickness>0.</WallThickness>
-<ShapeParameter>0.</ShapeParameter>
-<ShoulderOD>65.9</ShoulderOD>
-<BaseExtensionLen>0.</BaseExtensionLen>
-<CoreDia>0.</CoreDia>
-<CoreLen>0.</CoreLen>
-<AttachedParts>
-<MassObject>
-<PartMfg>Custom</PartMfg>
-<KnownMass>20.</KnownMass>
-<Density>0.</Density>
-<Material>Custom</Material>
-<Name>Clay</Name>
-<KnownCG>17.8</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>17.8</Xb>
-<CalcMass>0.</CalcMass>
-<CalcCG>0.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>2</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>17.8</Station>
-<TypeCode>0</TypeCode>
-<Len>0.</Len>
-<AttachedParts>
-</AttachedParts>
-</MassObject>
-<BodyTube>
-<PartMfg>Apogee</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Attachment Rod</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>6.1</Xb>
-<CalcMass>2.47301</CalcMass>
-<CalcCG>78.85</CalcCG>
-<WettedSurface>0.00684683</WettedSurface>
-<PaintedSurface>0.00684683</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>10062</PartNo>
-<PartDesc>13 mm</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>3</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>6.1</Station>
-<OD>13.82</OD>
-<ID>13.16</ID>
-<Len>157.7</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Plate</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>78.9</Xb>
-<CalcMass>7.86272</CalcMass>
-<CalcCG>1.585</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-(2)0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>4</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>85.</Station>
-<OD>66.</OD>
-<ID>13.82</ID>
-<Len>3.17</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Ring>
-<PartMfg>Custom</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1400.</Density>
-<Material>Carbon Fiber</Material>
-<Name>Sleeve </Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>17.5527</CalcMass>
-<CalcCG>13.85</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>5</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>2</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>136.1</Station>
-<OD>27.7</OD>
-<ID>13.82</ID>
-<Len>27.7</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>3</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Parachute>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>170.</KnownMass>
-<Density>0.006685</Density>
-<Material>Rip stop nylon</Material>
-<Name>Nose Cone Parachute</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>142.6</Xb>
-<CalcMass>15.8812</CalcMass>
-<CalcCG>34.5417</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>1</DensityType>
-<PartNo>LP-50</PartNo>
-<PartDesc>50 In. 16 lines</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>6</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>148.7</Station>
-<Dia>414.5</Dia>
-<SpillHoleDia>0.</SpillHoleDia>
-<SideCount>15</SideCount>
-<ShroudLineCount>16</ShroudLineCount>
-<Thickness>0.05</Thickness>
-<ShroudLineLen>1350.</ShroudLineLen>
-<ChuteCount>1</ChuteCount>
-<ShroudLineMassPerMM>0.00032972</ShroudLineMassPerMM>
-<ShroudLineMaterial>Carpet String (Apogee 29500)</ShroudLineMaterial>
-<DragCoefficient>0.95</DragCoefficient>
-<AttachedParts>
-</AttachedParts>
-</Parachute>
-</AttachedParts>
-</BodyTube>
-</AttachedParts>
-</NoseCone>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>15.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>100.</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>5.805</CalcMass>
-<CalcCG>100.</CalcCG>
-<WettedSurface>0.0414942</WettedSurface>
-<PaintedSurface>0.0414942</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>EST 3090</PartNo>
-<PartDesc>BT-80</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>7</SerialNo>
-<DisplayFlags>1</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(54,250,21)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>88.9</Station>
-<OD>66.</OD>
-<ID>65.79</ID>
-<Len>200.</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>190.2</Xb>
-<CalcMass>7.65502</CalcMass>
-<CalcCG>1.59</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>8</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>279.1</Station>
-<OD>65.02</OD>
-<ID>25.4</ID>
-<Len>3.18</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>165.</Xb>
-<CalcMass>7.62626</CalcMass>
-<CalcCG>1.585</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-(2)0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>9</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>253.9</Station>
-<OD>65.</OD>
-<ID>25.4</ID>
-<Len>3.17</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<BodyTube>
-<PartMfg>Public Missiles Ltd.</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>958.705</Density>
-<Material>Kraft phenolic</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>137.9</Xb>
-<CalcMass>9.8818</CalcMass>
-<CalcCG>35.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>KS-1.1</PartNo>
-<PartDesc>KwikSwitch MMT 29mm</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>-1.58371</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>10</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>226.8</Station>
-<OD>32.26</OD>
-<ID>29.21</ID>
-<Len>70.</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>1</IsMotorMount>
-<MotorDia>29.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-</AttachedParts>
-</BodyTube>
-<LaunchLug>
-<PartMfg>Apogee</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Launch lug</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>77.2</Xb>
-<CalcMass>1.11942</CalcMass>
-<CalcCG>38.1</CalcCG>
-<WettedSurface>0.00374518</WettedSurface>
-<PaintedSurface>0.00199411</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>13056</PartNo>
-<PartDesc><![CDATA[1/4" X 3]]></PartDesc>
-<RadialLoc>37.185</RadialLoc>
-<RadialAngle>3.14</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>26</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>166.1</Station>
-<OD>8.33</OD>
-<ID>7.26</ID>
-<Len>76.2</Len>
-<FinishCode>0</FinishCode>
-<AttachedParts>
-</AttachedParts>
-</LaunchLug>
-<ExternalPod>
-<PartMfg>Custom</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>0.</Density>
-<Name>Pod</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>200.</Xb>
-<CalcMass>0.</CalcMass>
-<CalcCG>0.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>36.175</RadialLoc>
-<RadialAngle>-1.50735</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>29</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>288.9</Station>
-<Detachable>1</Detachable>
-<AutoCalcRadialDistance>1</AutoCalcRadialDistance>
-<AutoCalcRadialAngle>1</AutoCalcRadialAngle>
-<AttachedParts>
-<BodyTube>
-<PartMfg>Apogee</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>958.705</Density>
-<Material>Kraft phenolic</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>0.400397</CalcMass>
-<CalcCG>29.3</CalcCG>
-<WettedSurface>0.00116902</WettedSurface>
-<PaintedSurface>0.00116902</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>9601</PartNo>
-<PartDesc>6 mm</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>30</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(54,250,21)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>288.9</Station>
-<OD>6.35</OD>
-<ID>5.59</ID>
-<Len>58.6</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-</AttachedParts>
-</BodyTube>
-</AttachedParts>
-</ExternalPod>
-</AttachedParts>
-</BodyTube>
-</Stage3Parts>
-<Stage2Parts>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>2nd Stage Tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>10.468</CalcMass>
-<CalcCG>180.34</CalcCG>
-<WettedSurface>0.0748306</WettedSurface>
-<PaintedSurface>0.0748306</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>EST 3090</PartNo>
-<PartDesc>BT-80</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>11</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(54,250,21)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>288.9</Station>
-<OD>66.</OD>
-<ID>65.79</ID>
-<Len>360.68</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>15.025</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Tube coupler</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>-10.</Xb>
-<CalcMass>20.465</CalcMass>
-<CalcCG>35.45</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>TC-2.56</PartNo>
-<PartDesc>Tube Coupler</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>12</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>278.9</Station>
-<OD>65.79</OD>
-<ID>63.25</ID>
-<Len>70.9</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>4</UsageCode>
-<AutoSize>1</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<MassObject>
-<PartMfg>Custom</PartMfg>
-<KnownMass>40.</KnownMass>
-<Density>0.</Density>
-<Material>Custom</Material>
-<Name>Electronics</Name>
-<KnownCG>138.3</KnownCG>
-<UseKnownCG>1</UseKnownCG>
-<Xb>138.3</Xb>
-<CalcMass>0.</CalcMass>
-<CalcCG>0.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>13</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>427.2</Station>
-<TypeCode>0</TypeCode>
-<Len>0.</Len>
-<AttachedParts>
-</AttachedParts>
-</MassObject>
-<FinSet>
-<PartMfg>Quest</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>128.148</Density>
-<Material>Balsa</Material>
-<Name>Fin set</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>228.6</Xb>
-<CalcMass>1.32269</CalcMass>
-<CalcCG>19.05</CalcCG>
-<WettedSurface>0.0028791</WettedSurface>
-<PaintedSurface>0.0086373</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>Payloader One</PartNo>
-<PartDesc>Fin</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.0830777</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>14</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>2.95647</BarrowmanCNa>
-<BarrowmanXN>0.52856</BarrowmanXN>
-<RockSimCNa>5.54523</RockSimCNa>
-<RockSimXN>0.52856</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>517.5</Station>
-<FinCount>3</FinCount>
-<RootChord>38.1</RootChord>
-<TipChord>24.9</TipChord>
-<SemiSpan>45.7</SemiSpan>
-<MidChordLen>45.7</MidChordLen>
-<SweepDistance>6.6</SweepDistance>
-<Thickness>2.39</Thickness>
-<ShapeCode>0</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>2</TipShapeCode>
-<TabLength>0.</TabLength>
-<TabDepth>0.</TabDepth>
-<TabOffset>0.</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.139993</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>54.2541</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>2.86063</RockSimCNaPerFin>
-<TaperRatio>0.653543</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AttachedParts>
-</AttachedParts>
-</FinSet>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>302.</Xb>
-<CalcMass>7.65502</CalcMass>
-<CalcCG>1.59</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>15</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>590.9</Station>
-<OD>65.02</OD>
-<ID>25.4</ID>
-<Len>3.18</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>335.5</Xb>
-<CalcMass>7.62626</CalcMass>
-<CalcCG>1.585</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC CR-2.56-(2)0.95</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>16</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>624.4</Station>
-<OD>65.</OD>
-<ID>25.4</ID>
-<Len>3.17</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>0</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<BodyTube>
-<PartMfg>Public Missiles Ltd.</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>958.705</Density>
-<Material>Kraft phenolic</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>587.4</Xb>
-<CalcMass>9.8818</CalcMass>
-<CalcCG>35.</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>KS-1.1</PartNo>
-<PartDesc>KwikSwitch MMT 29mm</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>-1.58371</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>17</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>1</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>587.4</Station>
-<OD>32.26</OD>
-<ID>29.21</ID>
-<Len>70.</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>1</IsMotorMount>
-<MotorDia>29.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<Ring>
-<PartMfg>Semroc</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Engine block</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>2.69315</CalcMass>
-<CalcCG>2.39</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>TB-7</PartNo>
-<PartDesc>Thrust Block</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>18</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>587.4</Station>
-<OD>29.21</OD>
-<ID>14.61</ID>
-<Len>4.78</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>2</UsageCode>
-<AutoSize>1</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-</AttachedParts>
-</BodyTube>
-<LaunchLug>
-<PartMfg>Apogee</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Launch lug</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>265.8</Xb>
-<CalcMass>1.11942</CalcMass>
-<CalcCG>38.1</CalcCG>
-<WettedSurface>0.00374518</WettedSurface>
-<PaintedSurface>0.00199411</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>13056</PartNo>
-<PartDesc><![CDATA[1/4" X 3]]></PartDesc>
-<RadialLoc>37.185</RadialLoc>
-<RadialAngle>1.22</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>27</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>554.7</Station>
-<OD>8.33</OD>
-<ID>7.26</ID>
-<Len>76.2</Len>
-<FinishCode>0</FinishCode>
-<AttachedParts>
-</AttachedParts>
-</LaunchLug>
-</AttachedParts>
-</BodyTube>
-</Stage2Parts>
-<Stage1Parts>
-<Transition>
-<PartMfg>BalsaMachining.com</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>128.148</Density>
-<Material>Balsa</Material>
-<Name>Transition</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>8.61936</CalcMass>
-<CalcCG>25.1551</CalcCG>
-<WettedSurface>0.0098623</WettedSurface>
-<PaintedSurface>0.0098623</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>TA6080</PartNo>
-<PartDesc>Transition T60 to T80 2.25 in long</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>19</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>-1.213</BarrowmanCNa>
-<BarrowmanXN>0.675973</BarrowmanXN>
-<RockSimCNa>-1.213</RockSimCNa>
-<RockSimXN>0.675973</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>649.58</Station>
-<FrontDia>66.</FrontDia>
-<RearDia>41.4</RearDia>
-<Len>57.15</Len>
-<FinishCode>0</FinishCode>
-<FrontShoulderLen>20.</FrontShoulderLen>
-<RearShoulderLen>38.1</RearShoulderLen>
-<ConstructionType>1</ConstructionType>
-<WallThickness>3.</WallThickness>
-<FrontShoulderDia>64.77</FrontShoulderDia>
-<RearShoulderDia>41.38</RearShoulderDia>
-<CoreDia>0.</CoreDia>
-<ShapeCode>0</ShapeCode>
-<ShapeParameter>0.</ShapeParameter>
-<EquivNoseLen>153.339</EquivNoseLen>
-<EquivNoseOffset>96.1895</EquivNoseOffset>
-<AttachedParts>
-</AttachedParts>
-</Transition>
-<BodyTube>
-<PartMfg>LOC/Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>0.</CalcMass>
-<CalcCG>nan.</CalcCG>
-<WettedSurface>0.0544179</WettedSurface>
-<PaintedSurface>0.0544179</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC BT-2.14</PartNo>
-<PartDesc>Airframe tube</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>20</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(54,250,21)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>706.73</Station>
-<OD>41.4</OD>
-<ID>41.</ID>
-<Len>418.4</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>0</IsMotorMount>
-<MotorDia>0.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>0</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-<FinSet>
-<PartMfg>Quest</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Elliptical Fins</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>69.7</Xb>
-<CalcMass>36.2048</CalcMass>
-<CalcCG>46.</CalcCG>
-<WettedSurface>0.00676907</WettedSurface>
-<PaintedSurface>0.0203072</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>-0.519061</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>21</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>3.61024</BarrowmanCNa>
-<BarrowmanXN>0.802926</BarrowmanXN>
-<RockSimCNa>6.03948</RockSimCNa>
-<RockSimXN>0.802926</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>776.43</Station>
-<FinCount>3</FinCount>
-<RootChord>92.</RootChord>
-<TipChord>46.</TipChord>
-<SemiSpan>46.9</SemiSpan>
-<MidChordLen>46.9</MidChordLen>
-<SweepDistance>33.49</SweepDistance>
-<Thickness>3.18</Thickness>
-<ShapeCode>1</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>0</TipShapeCode>
-<TabLength>0.</TabLength>
-<TabDepth>0.</TabDepth>
-<TabOffset>0.</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.349066</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>41.5444</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>3.21868</RockSimCNaPerFin>
-<TaperRatio>0.5</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AttachedParts>
-</AttachedParts>
-</FinSet>
-<CustomFinSet>
-<PartMfg>Public Missiles</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1905.24</Density>
-<Material>G10 fiberglass</Material>
-<Name>Custom Fins</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>241.7</Xb>
-<CalcMass>256.292</CalcMass>
-<CalcCG>78.9922</CalcCG>
-<WettedSurface>0.0355266</WettedSurface>
-<PaintedSurface>0.10658</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>FIN-C-02</PartNo>
-<PartDesc>Fins</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.357967</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>22</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>25.7037</BarrowmanCNa>
-<BarrowmanXN>0.996526</BarrowmanXN>
-<RockSimCNa>34.1865</RockSimCNa>
-<RockSimXN>0.996822</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>948.43</Station>
-<FinCount>3</FinCount>
-<RootChord>152.4</RootChord>
-<TipChord>84.53</TipChord>
-<SemiSpan>146.72</SemiSpan>
-<MidChordLen>146.81</MidChordLen>
-<SweepDistance>39.07</SweepDistance>
-<Thickness>2.38</Thickness>
-<ShapeCode>2</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>2</TipShapeCode>
-<TabLength>101.6</TabLength>
-<TabDepth>10.6</TabDepth>
-<TabOffset>35.6</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>87.0529</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>19.7376</RockSimCNaPerFin>
-<TaperRatio>0.554659</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<AverageChord>121.39</AverageChord>
-<EffectiveTipChord>84.5261</EffectiveTipChord>
-<PointList>152.4,0|126.202,146.715|36.455,146.715|0,0|</PointList>
-<AutoCalcGridStepX>0,0,0,0,0,0,0</AutoCalcGridStepX>
-<GridStepCountX>10,10,10,10,10,10,10</GridStepCountX>
-<UseAbsoluteGridStepsX>0,0,0,0,0,0,0</UseAbsoluteGridStepsX>
-<GridStepSizeX>0.5,10,0.5,0.5,0.00018939,0.001,1</GridStepSizeX>
-<SnapToSizeX>0.25,5,0.1,0.1,0.00018939,0.001,1</SnapToSizeX>
-<AutoCalcGridStepY>0,0,0,0,0,0,0</AutoCalcGridStepY>
-<GridStepCountY>10,10,10,10,10,10,10</GridStepCountY>
-<UseAbsoluteGridStepsY>0,0,0,0,0,0,0</UseAbsoluteGridStepsY>
-<GridStepSizeY>0.5,10,0.5,0.5,0.00018939,0.001,1</GridStepSizeY>
-<SnapToSizeY>0.25,5,0.1,0.1,0.00018939,0.001,1</SnapToSizeY>
-<AttachedParts>
-</AttachedParts>
-</CustomFinSet>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>379.5</Xb>
-<CalcMass>1.99074</CalcMass>
-<CalcCG>1.59</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC FCR-1.52-1.14</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>23</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>1086.23</Station>
-<OD>41.4</OD>
-<ID>24.79</ID>
-<Len>3.18</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>1</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<Ring>
-<PartMfg>LOC Precision</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>724.996</Density>
-<Material>Aircraft plywood (LOC)</Material>
-<Name>Centering ring</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>272.</Xb>
-<CalcMass>1.99074</CalcMass>
-<CalcCG>1.59</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>LOC FCR-1.52-1.14</PartNo>
-<PartDesc>Centering Ring</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>24</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>978.73</Station>
-<OD>41.4</OD>
-<ID>24.79</ID>
-<Len>3.18</Len>
-<FinishCode>0</FinishCode>
-<UsageCode>0</UsageCode>
-<AutoSize>1</AutoSize>
-<AttachedParts>
-</AttachedParts>
-</Ring>
-<BodyTube>
-<PartMfg>Estes</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Body tube</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>259.7</Xb>
-<CalcMass>5.22902</CalcMass>
-<CalcCG>91.95</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>EST 3086</PartNo>
-<PartDesc>BT-50</PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>rgb(0,0,250)</AbientColor>
-<DiffuseColor>rgb(0,0,250)</DiffuseColor>
-<SpecularColor>rgb(255,255,255)</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>25</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>rgb(0,0,250)</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>966.43</Station>
-<OD>24.79</OD>
-<ID>24.13</ID>
-<Len>183.9</Len>
-<FinishCode>0</FinishCode>
-<IsMotorMount>1</IsMotorMount>
-<MotorDia>24.</MotorDia>
-<EngineOverhang>0.5</EngineOverhang>
-<FrontExtension>0.</FrontExtension>
-<RearExtension>0.</RearExtension>
-<IsInsideTube>1</IsInsideTube>
-<isStrapOnTube>0</isStrapOnTube>
-<AttachedParts>
-</AttachedParts>
-</BodyTube>
-<TubeFinSet>
-<PartMfg>Custom</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1121.29</Density>
-<Material>Paper</Material>
-<Name>Tube fins</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>12.6878</CalcMass>
-<CalcCG>24.79</CalcCG>
-<WettedSurface>0.0688063</WettedSurface>
-<PaintedSurface>0.0688063</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>35.395</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>28</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>10.866</BarrowmanCNa>
-<BarrowmanXN>0.707815</BarrowmanXN>
-<RockSimCNa>10.866</RockSimCNa>
-<RockSimXN>0.707815</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>706.73</Station>
-<OD>24.79</OD>
-<ID>24.13</ID>
-<Len>49.58</Len>
-<FinishCode>0</FinishCode>
-<TubeCount>9</TubeCount>
-<MinTubeAngle>0.715549</MinTubeAngle>
-<MaxTubesAllowed>9</MaxTubesAllowed>
-<AttachedParts>
-</AttachedParts>
-</TubeFinSet>
-<RingTail>
-<PartMfg>Custom</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>688.794</Density>
-<Material>Cardboard</Material>
-<Name>Ringtail</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>0.</Xb>
-<CalcMass>2.93707</CalcMass>
-<CalcCG>10.</CalcCG>
-<WettedSurface>0.00474229</WettedSurface>
-<PaintedSurface>0.00444249</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>31</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>2</LocationMode>
-<Color>rgb(255,9,18)</Color>
-<BarrowmanCNa>39.6386</BarrowmanCNa>
-<BarrowmanXN>1.10463</BarrowmanXN>
-<RockSimCNa>39.6386</RockSimCNa>
-<RockSimXN>1.10463</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>1105.13</Station>
-<FinCount>3</FinCount>
-<RootChord>20.</RootChord>
-<TipChord>20.</TipChord>
-<SemiSpan>7.495</SemiSpan>
-<MidChordLen>7.495</MidChordLen>
-<SweepDistance>0.</SweepDistance>
-<Thickness>3.</Thickness>
-<ShapeCode>0</ShapeCode>
-<FinishCode>0</FinishCode>
-<TipShapeCode>0</TipShapeCode>
-<TabLength>0.</TabLength>
-<TabDepth>0.</TabDepth>
-<TabOffset>0.</TabOffset>
-<SweepMode>1</SweepMode>
-<SweepAngle>0.</SweepAngle>
-<RockSimXNPerFin>0.</RockSimXNPerFin>
-<RockSimRadialXNPerFin>0.</RockSimRadialXNPerFin>
-<RockSimCNaPerFin>0.</RockSimCNaPerFin>
-<TaperRatio>0.</TaperRatio>
-<CantAngle>0.</CantAngle>
-<CantPivotPoint>0.</CantPivotPoint>
-<OD>56.39</OD>
-<ID>55.37</ID>
-<Len>20.</Len>
-<TubeDensity>1121.29</TubeDensity>
-<TubeDensityType>0</TubeDensityType>
-<TubeMaterial>Paper</TubeMaterial>
-<AttachedParts>
-</AttachedParts>
-</RingTail>
-<Streamer>
-<PartMfg>Apogee</PartMfg>
-<KnownMass>0.</KnownMass>
-<Density>1309.</Density>
-<Material>Mylar</Material>
-<Name>Streamer</Name>
-<KnownCG>0.</KnownCG>
-<UseKnownCG>0</UseKnownCG>
-<Xb>149.4</Xb>
-<CalcMass>5.67514</CalcMass>
-<CalcCG>50.8</CalcCG>
-<WettedSurface>0.</WettedSurface>
-<PaintedSurface>0.</PaintedSurface>
-<GlueJointLength>0.</GlueJointLength>
-<DensityType>0</DensityType>
-<PartNo>29006</PartNo>
-<PartDesc><![CDATA[4" Wide Mylar]]></PartDesc>
-<RadialLoc>0.</RadialLoc>
-<RadialAngle>0.</RadialAngle>
-<Texture>file=()|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)</Texture>
-<Opacity>1.</Opacity>
-<Specular>0.</Specular>
-<SpecularPower>1.</SpecularPower>
-<Ambient>0.</Ambient>
-<Diffuse>1.</Diffuse>
-<AbientColor>blue</AbientColor>
-<DiffuseColor>blue</DiffuseColor>
-<SpecularColor>white</SpecularColor>
-<UseSingleColor>1</UseSingleColor>
-<SerialNo>32</SerialNo>
-<DisplayFlags>0</DisplayFlags>
-<MetricsFlags>0</MetricsFlags>
-<LocationMode>0</LocationMode>
-<Color>blue</Color>
-<BarrowmanCNa>0.</BarrowmanCNa>
-<BarrowmanXN>0.</BarrowmanXN>
-<RockSimCNa>0.</RockSimCNa>
-<RockSimXN>0.</RockSimXN>
-<SimpleColorModel>1</SimpleColorModel>
-<ProduceTemplate>0</ProduceTemplate>
-<TemplateUnits>8</TemplateUnits>
-<Removed>0</Removed>
-<Station>856.13</Station>
-<Len>1422.4</Len>
-<Width>101.6</Width>
-<Thickness>0.03</Thickness>
-<StreamerCount>1</StreamerCount>
-<DragCoefficient>0.127</DragCoefficient>
-<IsFolded>0</IsFolded>
-<AutoCalcCd>1</AutoCalcCd>
-<AttachedParts>
-</AttachedParts>
-</Streamer>
-</AttachedParts>
-</BodyTube>
-</Stage1Parts>
-<SideViewDims>
-</SideViewDims>
-<BaseViewDims>
-</BaseViewDims>
-<VertViewDims>
-</VertViewDims>
-</RocketDesign>
-</DesignInformation>
-<SimulationResultsList>
-</SimulationResultsList>
-</RockSimDocument>
+++ /dev/null
-package net.sf.openrocket.gui;
-
-import org.junit.Test;
-
-public class TestGUI {
-
- @Test
- public void test() {
- // No-op
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.gui.configdialog;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-import net.sf.openrocket.gui.adaptors.DoubleModel;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.CenteringRing;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
-import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class FinSetConfigTest extends BaseTestCase {
-
- static Method method;
-
- @BeforeClass
- public static void classSetup() throws Exception {
- method = FinSetConfig.class.getDeclaredMethod("computeFinTabLength", List.class, Double.class, Double.class, DoubleModel.class, RocketComponent.class);
- Assert.assertNotNull(method);
- method.setAccessible(true);
- }
-
- /**
- * Test no centering rings.
- *
- * @throws Exception
- */
- @Test
- public void testComputeFinTabLength() throws Exception {
- DoubleModel dm = new DoubleModel(1d);
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- RocketComponent parent = new BodyTube();
-
- Double result = (Double)method.invoke(null, rings, 10d, 11d, dm, parent);
- Assert.assertEquals(0.0001, 11d, result.doubleValue());
- result = (Double)method.invoke(null, null, 10d, 11d, dm, parent);
- Assert.assertEquals(11d, result.doubleValue(), 0.0001);
- }
-
- /**
- * Test 2 rings both ahead of the fin.
- */
- @Test
- public void testCompute2LeadingRings() throws Exception {
- DoubleModel dm = new DoubleModel(1d);
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- RocketComponent parent = new BodyTube();
-
- CenteringRing ring1 = new CenteringRing();
- ring1.setLength(0.004);
- ring1.setRelativePosition(RocketComponent.Position.TOP);
- ring1.setPositionValue(0.43);
- CenteringRing ring2 = new CenteringRing();
- ring2.setLength(0.004);
- ring2.setRelativePosition(RocketComponent.Position.TOP);
- ring2.setPositionValue(0.45);
- rings.add(ring1);
- rings.add(ring2);
- parent.addChild(ring1);
- parent.addChild(ring2);
-
- Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
- Assert.assertEquals(0.01, result.doubleValue(), 0.0001);
-
- }
-
- /**
- * Test one ring, ahead of the fin.
- */
- @Test
- public void testCompute1Ring() throws Exception {
- DoubleModel dm = new DoubleModel(1d);
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- CenteringRing ring1 = new CenteringRing();
- ring1.setLength(0.004);
- ring1.setRelativePosition(RocketComponent.Position.TOP);
- ring1.setPositionValue(0.43);
- rings.add(ring1);
-
- RocketComponent parent = new BodyTube();
- parent.addChild(ring1);
-
- Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
- Assert.assertEquals(0.01, result.doubleValue(), 0.0001);
- }
-
- /**
- * Test one ring ahead of the fin, one ring within the root chord.
- */
- @Test
- public void testComputeOneLeadingOneRingWithinRoot() throws Exception {
- DoubleModel dm = new DoubleModel(1d);
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- CenteringRing ring1 = new CenteringRing();
- ring1.setRelativePosition(RocketComponent.Position.TOP);
- ring1.setLength(0.004);
- ring1.setPositionValue(0.43);
- CenteringRing ring2 = new CenteringRing();
- ring2.setRelativePosition(RocketComponent.Position.TOP);
- ring2.setLength(0.004);
- ring2.setPositionValue(0.45);
- rings.add(ring1);
- rings.add(ring2);
-
- RocketComponent parent = new BodyTube(1d, 0.01);
- parent.addChild(ring1);
- parent.addChild(ring2);
-
- Double result = (Double)method.invoke(null, rings, 0.45d, 0.01, dm, parent);
- Assert.assertEquals(0.01 - 0.004, result.doubleValue(), 0.0001);
- }
-
- /**
- * Test one ring ahead of the fin, one ring beyond the root chord.
- */
- @Test
- public void testComputeOneLeadingOneTrailingRing() throws Exception {
- DoubleModel dm = new DoubleModel(1d);
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- CenteringRing ring1 = new CenteringRing();
- ring1.setRelativePosition(RocketComponent.Position.TOP);
- ring1.setLength(0.004);
- ring1.setPositionValue(0.43);
- CenteringRing ring2 = new CenteringRing();
- ring2.setRelativePosition(RocketComponent.Position.TOP);
- ring2.setLength(0.004);
- ring2.setPositionValue(0.48);
- rings.add(ring1);
- rings.add(ring2);
-
- RocketComponent parent = new BodyTube();
- Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, ring1);
- Assert.assertEquals(0.01, result.doubleValue(), 0.0001);
- }
-
- /**
- * Test one ring within the root chord, another ring beyond the root chord.
- */
- @Test
- public void testComputeOneWithinRootOneTrailingRing() throws Exception {
- DoubleModel dm = new DoubleModel(1d);
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- CenteringRing ring1 = new CenteringRing();
- ring1.setRelativePosition(RocketComponent.Position.TOP);
- ring1.setLength(0.004);
- ring1.setPositionValue(0.4701);
- CenteringRing ring2 = new CenteringRing();
- ring2.setLength(0.004);
- ring2.setRelativePosition(RocketComponent.Position.TOP);
- ring2.setPositionValue(0.48);
- rings.add(ring1);
- rings.add(ring2);
- RocketComponent parent = new BodyTube(1.0d, 0.1d);
- parent.addChild(ring1);
- parent.addChild(ring2);
- Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
- Assert.assertEquals(0.0059, result.doubleValue(), 0.0001);
- }
-
- /**
- * Test both rings within the root chord.
- */
- @Test
- public void testBothRingsWithinRootChord() throws Exception {
- DoubleModel dm = new DoubleModel(1d);
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- RocketComponent parent = new BodyTube(1.0000d, 0.1d);
- CenteringRing ring1 = new CenteringRing();
- ring1.setRelativePosition(RocketComponent.Position.TOP);
- ring1.setLength(0.004);
- ring1.setPositionValue(0.4701);
- parent.addChild(ring1);
- CenteringRing ring2 = new CenteringRing();
- ring2.setLength(0.004);
- ring2.setRelativePosition(RocketComponent.Position.TOP);
- ring2.setPositionValue(0.4750);
- parent.addChild(ring2);
- rings.add(ring1);
- rings.add(ring2);
-
- Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
- Assert.assertEquals(0.0009, result.doubleValue(), 0.0002);
- }
-
-
- /**
- * Test both rings beyond the root chord.
- */
- @Test
- public void testBothRingsBeyondRootChord() throws Exception {
- DoubleModel dm = new DoubleModel(1d);
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- CenteringRing ring1 = new CenteringRing();
- ring1.setRelativePosition(RocketComponent.Position.TOP);
- ring1.setLength(0.004);
- ring1.setPositionValue(0.48);
- CenteringRing ring2 = new CenteringRing();
- ring2.setRelativePosition(RocketComponent.Position.TOP);
- ring2.setLength(0.004);
- ring2.setPositionValue(0.49);
- rings.add(ring1);
- rings.add(ring2);
- RocketComponent parent = new BodyTube(1.0d, 0.1d);
- parent.addChild(ring1);
- parent.addChild(ring2);
-
- Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
- Assert.assertEquals(0.0, result.doubleValue(), 0.0001);
- }
-
- /**
- * Test both rings within the root chord - the top ring has an adjacent ring (so 3 rings total).
- */
- @Test
- public void test3RingsWithinRootChord() throws Exception {
- DoubleModel dm = new DoubleModel(1d);
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- CenteringRing ring1 = new CenteringRing();
- ring1.setRelativePosition(RocketComponent.Position.ABSOLUTE);
- ring1.setLength(0.004);
- ring1.setPositionValue(0.47);
- CenteringRing ring2 = new CenteringRing();
- ring2.setRelativePosition(RocketComponent.Position.ABSOLUTE);
- ring2.setLength(0.004);
- ring2.setPositionValue(0.4702);
- CenteringRing ring3 = new CenteringRing();
- ring3.setRelativePosition(RocketComponent.Position.ABSOLUTE);
- ring3.setLength(0.004);
- ring3.setPositionValue(0.4770);
- rings.add(ring1);
- rings.add(ring2);
- rings.add(ring3);
- BodyTube parent = new BodyTube(1.0d, 0.1d);
- parent.setPositionValue(0);
- parent.addChild(ring1);
- parent.addChild(ring2);
- parent.addChild(ring3);
-
- Double result = (Double)method.invoke(null, rings, 0.47d, 0.01, dm, parent);
- Assert.assertEquals(0.0028, result.doubleValue(), 0.0001);
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.gui.print;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class TestPaperSize {
-
- @Test
- public void testGetDefaultForCountry() {
- assertEquals(PaperSize.LETTER, PaperSize.getDefaultForCountry("US"));
- assertEquals(PaperSize.LETTER, PaperSize.getDefaultForCountry("cA"));
- assertEquals(PaperSize.LETTER, PaperSize.getDefaultForCountry("mx"));
-
- assertEquals(PaperSize.A4, PaperSize.getDefaultForCountry("FI"));
- assertEquals(PaperSize.A4, PaperSize.getDefaultForCountry("xy"));
-
- assertNull(PaperSize.getDefaultForCountry("FIN"));
- assertNull(PaperSize.getDefaultForCountry("a"));
- assertNull(PaperSize.getDefaultForCountry("A4"));
- assertNull(PaperSize.getDefaultForCountry(null));
- }
-
- @Test
- public void testGetSizeFromString() {
- assertEquals(PaperSize.LETTER, PaperSize.getSizeFromString("Letter"));
- assertEquals(PaperSize.LEGAL, PaperSize.getSizeFromString(" legal\t"));
- assertEquals(PaperSize.A4, PaperSize.getSizeFromString(" A4\n"));
- assertEquals(PaperSize.A3, PaperSize.getSizeFromString("A3"));
-
- assertNull(PaperSize.getSizeFromString("#A4"));
- assertNull(PaperSize.getSizeFromString(""));
- assertNull(PaperSize.getSizeFromString(null));
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.l10n;
-
-import static org.junit.Assert.*;
-
-import java.util.MissingResourceException;
-
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-import org.jmock.auto.Mock;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-
-@RunWith(JMock.class)
-public class TestClassBasedTranslator {
- Mockery context = new JUnit4Mockery();
-
- @Mock
- Translator translator;
-
- @Test
- public void testClassName() {
- ClassBasedTranslator cbt = new ClassBasedTranslator(null, 0);
- assertEquals("TestClassBasedTranslator", cbt.getClassName());
-
- cbt = new ClassBasedTranslator(null, "foobar");
- assertEquals("foobar", cbt.getClassName());
- }
-
- @Test
- public void testGetWithClassName() {
- ClassBasedTranslator cbt = new ClassBasedTranslator(translator, 0);
-
- // @formatter:off
- context.checking(new Expectations() {{
- oneOf(translator).get("TestClassBasedTranslator.fake.key"); will(returnValue("foobar"));
- }});
- // @formatter:on
-
- assertEquals("foobar", cbt.get("fake.key"));
- }
-
-
- @Test
- public void testGetWithoutClassName() {
- ClassBasedTranslator cbt = new ClassBasedTranslator(translator, 0);
-
- // @formatter:off
- context.checking(new Expectations() {{
- oneOf(translator).get("TestClassBasedTranslator.fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
- oneOf(translator).get("fake.key"); will(returnValue("barbaz"));
- }});
- // @formatter:on
-
- assertEquals("barbaz", cbt.get("fake.key"));
- }
-
-
- @Test
- public void testMissing() {
- ClassBasedTranslator cbt = new ClassBasedTranslator(translator, 0);
-
- // @formatter:off
- context.checking(new Expectations() {{
- oneOf(translator).get("TestClassBasedTranslator.fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
- oneOf(translator).get("fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
- }});
- // @formatter:on
-
- try {
- fail("Returned: " + cbt.get("fake.key"));
- } catch (MissingResourceException e) {
- assertEquals("Neither key 'TestClassBasedTranslator.fake.key' nor 'fake.key' could be found", e.getMessage());
- }
-
- }
-}
+++ /dev/null
-package net.sf.openrocket.l10n;
-
-import static org.junit.Assert.*;
-
-import java.util.MissingResourceException;
-
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-import org.jmock.auto.Mock;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(JMock.class)
-public class TestExceptionSuppressingTranslator {
- Mockery context = new JUnit4Mockery();
-
- @Mock
- Translator translator;
-
- @Test
- public void testSuccessful() {
- ExceptionSuppressingTranslator est = new ExceptionSuppressingTranslator(translator);
-
- // @formatter:off
- context.checking(new Expectations() {{
- oneOf(translator).get("fake.key"); will(returnValue("foobar"));
- }});
- // @formatter:on
-
- assertEquals("foobar", est.get("fake.key"));
- }
-
-
- @Test
- public void testFailure() {
- ExceptionSuppressingTranslator est = new ExceptionSuppressingTranslator(translator);
-
- assertFalse("Prerequisite failed", ExceptionSuppressingTranslator.errorReported);
-
- // @formatter:off
- context.checking(new Expectations() {{
- oneOf(translator).get("fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
- oneOf(translator).get("fake.key"); will(throwException(new MissingResourceException("a", "b", "c")));
- oneOf(translator).get("fake.key2"); will(throwException(new MissingResourceException("a", "b", "c")));
- }});
- // @formatter:on
-
- // Test first failure
- assertEquals("fake.key", est.get("fake.key"));
- assertTrue(ExceptionSuppressingTranslator.errorReported);
-
- // Test second failure
- assertEquals("fake.key", est.get("fake.key"));
- assertTrue(ExceptionSuppressingTranslator.errorReported);
-
- // Test failure with other key
- assertEquals("fake.key2", est.get("fake.key2"));
- assertTrue(ExceptionSuppressingTranslator.errorReported);
- }
-
-
-}
+++ /dev/null
-package net.sf.openrocket.l10n;
-
-import static org.junit.Assert.*;
-
-import java.util.Locale;
-import java.util.MissingResourceException;
-
-import org.junit.Test;
-
-public class TestResourceBundleTranslator {
-
- @Test
- public void testSuccessfulUS() {
- ResourceBundleTranslator trans = new ResourceBundleTranslator("l10n.messages", Locale.US);
- assertEquals("messages.properties", trans.get("debug.currentFile"));
- }
-
- @Test
- public void testSuccessfulFR() {
- ResourceBundleTranslator trans = new ResourceBundleTranslator("l10n.messages", Locale.FRENCH);
- assertEquals("messages_fr.properties", trans.get("debug.currentFile"));
- }
-
- @Test
- public void testFailure() {
- ResourceBundleTranslator trans = new ResourceBundleTranslator("l10n.messages", Locale.US);
- try {
- fail("Returned: " + trans.get("missing"));
- } catch (MissingResourceException e) {
- // Expected
- }
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.logging;
-
-import static org.junit.Assert.*;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Random;
-
-import org.junit.Test;
-
-
-public class CyclicBufferTest {
-
- @Test
- public void testBasic() {
- CyclicBuffer<Integer> buffer = new CyclicBuffer<Integer>(5);
- LinkedList<Integer> correct = new LinkedList<Integer>();
-
- Random rnd = new Random();
- for (int i=0; i<50; i++) {
- int n = rnd.nextInt();
- buffer.add(n);
- correct.add(n);
- if (correct.size() > 5)
- correct.remove();
- assertEquals(correct, buffer.asList());
- }
- }
-
- @Test
- public void testComplex() {
- CyclicBuffer<Integer> buffer = new CyclicBuffer<Integer>(5);
-
- testContents(buffer);
- assertEquals(0, buffer.getOverwriteCount());
-
- buffer.offer(1);
- testContents(buffer, 1);
- assertEquals(0, buffer.getOverwriteCount());
-
- buffer.add(2);
- testContents(buffer, 1, 2);
- assertEquals(0, buffer.getOverwriteCount());
-
- buffer.add(3);
- testContents(buffer, 1, 2, 3);
- assertEquals(0, buffer.getOverwriteCount());
-
- assertEquals(1, (int)buffer.remove());
- testContents(buffer, 2, 3);
- assertEquals(0, buffer.getOverwriteCount());
-
- assertEquals(2, (int)buffer.peek());
- testContents(buffer, 2, 3);
- assertEquals(0, buffer.getOverwriteCount());
-
- buffer.offer(-2);
- testContents(buffer, 2, 3, -2);
- assertEquals(0, buffer.getOverwriteCount());
-
- buffer.offer(-3);
- testContents(buffer, 2, 3, -2, -3);
- assertEquals(0, buffer.getOverwriteCount());
-
- buffer.offer(-4);
- testContents(buffer, 2, 3, -2, -3, -4);
- assertEquals(0, buffer.getOverwriteCount());
-
- buffer.offer(5);
- testContents(buffer, 3, -2, -3, -4, 5);
- assertEquals(1, buffer.getOverwriteCount());
-
- buffer.offer(6);
- testContents(buffer, -2, -3, -4, 5, 6);
- assertEquals(2, buffer.getOverwriteCount());
-
- assertEquals(-2, (int)buffer.peek());
- testContents(buffer, -2, -3, -4, 5, 6);
- assertEquals(2, buffer.getOverwriteCount());
-
- assertEquals(-2, (int)buffer.remove());
- testContents(buffer, -3, -4, 5, 6);
- assertEquals(2, buffer.getOverwriteCount());
-
- assertEquals(-3, (int)buffer.remove());
- testContents(buffer, -4, 5, 6);
- assertEquals(2, buffer.getOverwriteCount());
-
- assertEquals(-4, (int)buffer.poll());
- testContents(buffer, 5, 6);
- assertEquals(2, buffer.getOverwriteCount());
-
- assertEquals(5, (int)buffer.remove());
- testContents(buffer, 6);
- assertEquals(2, buffer.getOverwriteCount());
-
- assertEquals(6, (int)buffer.poll());
- testContents(buffer);
- assertEquals(2, buffer.getOverwriteCount());
-
- assertNull(buffer.peek());
- assertNull(buffer.poll());
- testContents(buffer);
- assertEquals(2, buffer.getOverwriteCount());
- }
-
-
- @Test
- public void testRandom() {
- CyclicBuffer<Integer> buffer = new CyclicBuffer<Integer>(4);
- LinkedList<Integer> correct = new LinkedList<Integer>();
-
- Random rnd = new Random();
- for (int i=0; i<500; i++) {
-
- if (rnd.nextBoolean()) {
- int n = rnd.nextInt();
- buffer.add(n);
- correct.add(n);
- if (correct.size() > 4)
- correct.remove();
- } else {
- Integer n = buffer.poll();
- if (correct.size() > 0) {
- assertEquals(correct.remove(), n);
- } else {
- assertNull(n);
- }
- }
-
- assertEquals(correct, buffer.asList());
- }
- }
-
-
- private void testContents(CyclicBuffer<Integer> buffer, int ... values) {
-
- // Test using iterator
- Iterator<Integer> iterator = buffer.iterator();
- for (int v: values) {
- assertTrue(iterator.hasNext());
- assertEquals(v, (int)iterator.next());
- }
- assertFalse(iterator.hasNext());
- try {
- iterator.next();
- fail();
- } catch (NoSuchElementException ignore) { }
-
- // Test using list
- List<Integer> list = buffer.asList();
- assertEquals("List: " + list, values.length, list.size());
- for (int i=0; i<values.length; i++) {
- assertEquals(values[i], (int)list.get(i));
- }
-
- }
-
-
-}
+++ /dev/null
-package net.sf.openrocket.logging;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.List;
-
-import org.junit.Test;
-
-public class LogLevelBufferLoggerTest {
-
- @Test
- public void testLogger() {
- LogLevelBufferLogger logger = new LogLevelBufferLogger(4);
-
- logger.debug("debug 1");
- logger.debug("debug 2");
- logger.user("user 1");
- logger.info("info 1");
- logger.info("info 2");
- logger.warn("warn 1");
- logger.debug("debug 3");
- logger.debug("debug 4");
- logger.user("user 2");
- logger.info("info 3");
- logger.error("error 1");
- logger.debug("debug 5");
- logger.warn("warn 2");
- logger.debug("debug 6");
- logger.user("user 3");
- logger.info("info 4");
- logger.debug("debug 7");
- logger.info("info 5");
- logger.debug("debug 8");
- logger.info("info 6");
-
- List<LogLine> list = logger.getLogs();
- assertEquals(16, list.size());
-
- assertEquals("user 1", list.get(0).getMessage());
- assertEquals("warn 1", list.get(1).getMessage());
- assertEquals("user 2", list.get(2).getMessage());
- assertEquals("===== 2 INFO lines removed =====", list.get(3).getMessage());
- assertEquals("info 3", list.get(4).getMessage());
- assertEquals("error 1", list.get(5).getMessage());
- assertEquals("===== 4 DEBUG lines removed =====", list.get(6).getMessage());
- assertEquals("debug 5", list.get(7).getMessage());
- assertEquals("warn 2", list.get(8).getMessage());
- assertEquals("debug 6", list.get(9).getMessage());
- assertEquals("user 3", list.get(10).getMessage());
- assertEquals("info 4", list.get(11).getMessage());
- assertEquals("debug 7", list.get(12).getMessage());
- assertEquals("info 5", list.get(13).getMessage());
- assertEquals("debug 8", list.get(14).getMessage());
- assertEquals("info 6", list.get(15).getMessage());
-
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.logging;
-
-import static net.sf.openrocket.logging.LogLevel.*;
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class LogLevelTest {
-
- @Test
- public void testLevels() {
- assertTrue(DEBUG.atLeast(DEBUG));
- assertFalse(DEBUG.atLeast(INFO));
- assertTrue(ERROR.atLeast(WARN));
-
- assertTrue(ERROR.moreThan(WARN));
- assertFalse(ERROR.moreThan(ERROR));
-
- assertEquals(5, LENGTH);
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.logging;
-
-import static org.junit.Assert.*;
-
-import java.util.List;
-
-import org.junit.Test;
-
-public class LoggingTest {
-
- @Test
- public void testLoggers() {
- // Ensure a sane stack trace
- actualTest();
- }
-
- private void actualTest() {
- BufferLogger log3 = new BufferLogger(3);
- BufferLogger log4 = new BufferLogger(4);
-
- DelegatorLogger delegator = new DelegatorLogger();
- delegator.addLogger(log3);
- delegator.addLogger(log4);
-
- delegator.debug("one");
- delegator.debug("two");
- delegator.info("three");
- delegator.warn(1, "four");
- delegator.error("five");
-
- List<LogLine> logs = log4.getLogs();
- assertEquals(4, logs.size());
- assertTrue(logs.get(0).toString(), logs.get(0).toString().matches(
- " *[0-9]+ +[0-9]+\\.[0-9]+ +DEBUG \\(-\\) two"));
- assertTrue(logs.get(1).toString(), logs.get(1).toString().matches(
- " *[0-9]+ +[0-9]+\\.[0-9]+ +INFO \\(LoggingTest.java:[0-9]+\\) three"));
- assertTrue(logs.get(2).toString(), logs.get(2).toString().matches(
- " *[0-9]+ +[0-9]+\\.[0-9]+ +WARN \\(LoggingTest.java:[0-9]+ LoggingTest.java:[0-9]+\\) four"));
- assertTrue(logs.get(3).toString(), logs.get(3).toString().matches(
- " *[0-9]+ +[0-9]+\\.[0-9]+ +ERROR \\(LoggingTest.java:[0-9]+\\) five"));
-
- logs = log3.getLogs();
- assertEquals(3, logs.size());
- assertTrue(logs.get(0).toString(), logs.get(0).toString().matches(
- " *[0-9]+ +[0-9]+\\.[0-9]+ +INFO \\(LoggingTest.java:[0-9]+\\) three"));
- assertTrue(logs.get(1).toString(), logs.get(1).toString().matches(
- " *[0-9]+ +[0-9]+\\.[0-9]+ +WARN \\(LoggingTest.java:[0-9]+ LoggingTest.java:[0-9]+\\) four"));
- assertTrue(logs.get(2).toString(), logs.get(2).toString().matches(
- " *[0-9]+ +[0-9]+\\.[0-9]+ +ERROR \\(LoggingTest.java:[0-9]+\\) five"));
-
- }
-
- public static void main(String[] args) {
- PrintStreamLogger logger = new PrintStreamLogger();
-
- logger.debug("a debug message");
- logger.info("an info message");
- logger.warn("a warning message");
- logger.error("an error message");
-
- logger.debug(4, "Debugging");
- }
-}
+++ /dev/null
-package net.sf.openrocket.logging;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class TraceExceptionTest {
-
- private TraceException getViaAccess() {
-
- /*
- * The SubClass test bases on the fact that getViaAccess method is defined on a row number < 20
- * and the return statement is on a row number > 20.
- *
- * The JRE sometimes adds an additional "access$NNN" method call between the calls with the
- * row number equal to the method definition line.
- *
- *
- *
- *
- *
- *
- *
- */
-
- return new TraceException(0, 1);
- }
-
-
- @Test
- public void testBasic() {
- TraceException trace = new TraceException();
- assertMatch("\\(TraceExceptionTest.java:[2-9][0-9]\\)", trace);
- }
-
-
- @Test
- public void testOneLevelUp() {
- // @formatter:off - these need to be on the same line number
- TraceException trace = getOneLevelUp(); TraceException ref = new TraceException();
- // @formatter:on
- assertEquals(ref.getMessage(), trace.getMessage());
- }
-
- private TraceException getOneLevelUp() {
- return new TraceException(1);
- }
-
-
- @Test
- public void testTwoLevels() {
- TraceException trace = getTwoLevels();
- assertMatch("\\(TraceExceptionTest.java:[2-9][0-9] TraceExceptionTest.java:[2-9][0-9]\\)", trace);
- }
-
- private TraceException getTwoLevels() {
- return new TraceException(0, 1);
- }
-
-
- @Test
- public void testViaSubclass() {
- /*
- * This tests that TraceException.getMessage ignores the synthetic "access$0" method calls.
- */
-
- TraceException trace = new SubClass().getTrace();
- assertMatch("\\(TraceExceptionTest.java:[2-9][0-9] TraceExceptionTest.java:[2-9][0-9]\\)", trace);
- }
-
- private class SubClass {
- private TraceException getTrace() {
- return getViaAccess();
- }
- }
-
-
-
-
-
- private void assertMatch(String regex, TraceException trace) {
- boolean match = trace.getMessage().matches(regex);
- if (!match) {
- trace.printStackTrace();
- assertTrue("Was: " + trace.getMessage(), match);
- }
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.models.gravity;
-
-import static org.junit.Assert.assertEquals;
-import net.sf.openrocket.util.WorldCoordinate;
-
-import org.junit.Test;
-
-
-public class WGSGravityModelTest {
-
- private WGSGravityModel model = new WGSGravityModel();
-
- @Test
- public void testSurfaceGravity() {
- // Equator
- test(0, 0, 0, 9.780);
- // Mid-latitude
- test(45, 0, 0, 9.806);
- // Mid-latitude
- test(45, 99, 0, 9.806);
- // South pole
- test(-90, 0, 0, 9.832);
- }
-
- @Test
- public void testAltitudeEffect() {
- test(45, 0, -100, 9.806);
- test(45, 0, 0, 9.806);
- test(45, 0, 10, 9.806);
- test(45, 0, 100, 9.806);
- test(45, 0, 1000, 9.803);
- test(45, 0, 10000, 9.775);
- test(45, 0, 100000, 9.505);
- }
-
- private void test(double lat, double lon, double alt, double g) {
- WorldCoordinate wc = new WorldCoordinate(lat, lon, alt);
- assertEquals(g, model.getGravity(wc), 0.001);
- assertEquals(g, model.getGravity(wc), 0.001);
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.motor;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class ManufacturerTest {
-
- @Test
- public void testExisting() {
-
- Manufacturer m1, m2, m3, m4, m5;
-
- m1 = Manufacturer.getManufacturer("aerotech");
- m2 = Manufacturer.getManufacturer("a ");
- m3 = Manufacturer.getManufacturer("-isp-");
- m4 = Manufacturer.getManufacturer("at/rcs");
- m5 = Manufacturer.getManufacturer("e");
-
- assertTrue(m1 == m2);
- assertTrue(m1 == m3);
- assertTrue(m1 == m4);
- assertFalse(m1 == m5);
-
- }
-
- @Test
- public void testNew() {
-
- Manufacturer m1, m2, m3;
-
- m1 = Manufacturer.getManufacturer("Unknown");
- m2 = Manufacturer.getManufacturer(" Unknown/ ");
- m3 = Manufacturer.getManufacturer("Unknown/a");
-
- assertEquals(m1.getDisplayName(), "Unknown");
- assertEquals(m2.getDisplayName(), "Unknown");
- assertTrue(m1 == m2);
-
- assertEquals(m3.getDisplayName(), "Unknown/a");
- assertFalse(m1 == m3);
-
- }
-
- @Test
- public void testSimpleName() {
-
- Manufacturer m1, m2, m3, m4;
-
- m1 = Manufacturer.getManufacturer("cs");
- m2 = Manufacturer.getManufacturer("Cesaroni Technology");
- m3 = Manufacturer.getManufacturer("Cesaroni Technology Inc");
- m4 = Manufacturer.getManufacturer("Cesaroni Technology Inc.");
-
- assertEquals(m1.getDisplayName(), "Cesaroni Technology Inc.");
- assertEquals(m1.toString(), "Cesaroni Technology Inc.");
- assertEquals(m1.getSimpleName(), "Cesaroni Technology");
-
- assertTrue(m1 == m2);
- assertTrue(m1 == m3);
- assertTrue(m1 == m4);
-
- }
-
- @Test
- public void testMatches() {
-
- Manufacturer m1;
-
- m1 = Manufacturer.getManufacturer("aerotech");
-
- assertTrue(m1.matches("a"));
- assertTrue(m1.matches("a/"));
- assertTrue(m1.matches("a/rcs"));
- assertTrue(m1.matches("a/rms"));
- assertTrue(m1.matches("aerotech ...-/%#_!"));
- assertTrue(m1.matches(" .isp/"));
-
- assertFalse(m1.matches("aero/tech"));
- assertFalse(m1.matches("aero.tech"));
- assertFalse(m1.matches("aero_tech"));
- assertFalse(m1.matches("aero tech"));
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.motor;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import net.sf.openrocket.motor.MotorDigest.DataType;
-import net.sf.openrocket.util.TextUtil;
-
-import org.junit.Test;
-
-
-public class MotorDigestTest {
-
- private static final double[] timeArray = {
- 0.0, 0.123456789, 0.4115, Math.nextAfter(Math.nextAfter(1.4445, 0), 0)
- };
-
- private static final double[] massArray = {
- 0.54321, 0.43211
- };
-
- private static final double[] thrustArray = {
- 0.0, 0.2345678, 9999.3335, 0.0
- };
-
- private static final int[] intData = {
- // Time (ms)
- 0, 4, 0, 123, 412, 1445,
- // Mass specific (0.1g)
- 1, 2, 5432, 4321,
- // Thrust (mN)
- 5, 4, 0, 235, 9999334, 0
- };
-
-
- @Test
- public void testMotorDigest() throws NoSuchAlgorithmException {
-
- MessageDigest correct = MessageDigest.getInstance("MD5");
- for (int value: intData) {
- correct.update((byte) ((value >>> 24) & 0xFF));
- correct.update((byte) ((value >>> 16) & 0xFF));
- correct.update((byte) ((value >>> 8) & 0xFF));
- correct.update((byte) (value & 0xFF));
- }
-
- MotorDigest motor = new MotorDigest();
- motor.update(DataType.TIME_ARRAY, timeArray);
- motor.update(DataType.MASS_SPECIFIC, massArray);
- motor.update(DataType.FORCE_PER_TIME, thrustArray);
-
-
- assertEquals(TextUtil.hexString(correct.digest()), motor.getDigest());
- }
-
-
- @Test
- public void testCommentDigest() throws NoSuchAlgorithmException, UnsupportedEncodingException {
-
- assertEquals(md5("Hello world!"), MotorDigest.digestComment("Hello world! "));
- assertEquals(md5("Hello world!"), MotorDigest.digestComment("\nHello\tworld!\n\r"));
- assertEquals(md5("Hello world!"), MotorDigest.digestComment("Hello\r\r\r\nworld!"));
- assertEquals(md5("Hello\u00e4 world!"), MotorDigest.digestComment("Hello\u00e4\r\r\nworld!"));
-
- }
-
-
- private static String md5(String source)
- throws NoSuchAlgorithmException, UnsupportedEncodingException {
- MessageDigest digest = MessageDigest.getInstance("MD5");
- return TextUtil.hexString(digest.digest(source.getBytes("UTF-8")));
- }
-}
+++ /dev/null
-package net.sf.openrocket.motor;
-
-import static org.junit.Assert.assertEquals;
-import net.sf.openrocket.util.Coordinate;
-import net.sf.openrocket.util.Inertia;
-
-import org.junit.Test;
-
-public class ThrustCurveMotorTest {
-
- private final double EPS = 0.000001;
-
- private final double radius = 0.025;
- private final double length = 0.10;
- private final double longitudinal = Inertia.filledCylinderLongitudinal(radius, length);
- private final double rotational = Inertia.filledCylinderRotational(radius);
-
- private final ThrustCurveMotor motor =
- new ThrustCurveMotor(Manufacturer.getManufacturer("foo"),
- "X6", "Description of X6", Motor.Type.RELOAD,
- new double[] {0, 2, Motor.PLUGGED}, radius*2, length,
- new double[] {0, 1, 3, 4}, // time
- new double[] {0, 2, 3, 0}, // thrust
- new Coordinate[] {
- new Coordinate(0.02,0,0,0.05),
- new Coordinate(0.02,0,0,0.05),
- new Coordinate(0.02,0,0,0.05),
- new Coordinate(0.03,0,0,0.03)
- });
-
- @Test
- public void testMotorData() {
-
- assertEquals("X6", motor.getDesignation());
- assertEquals("X6-5", motor.getDesignation(5.0));
- assertEquals("Description of X6", motor.getDescription());
- assertEquals(Motor.Type.RELOAD, motor.getMotorType());
-
- }
-
- @Test
- public void testInstance() {
- MotorInstance instance = motor.getInstance();
-
- verify(instance, 0, 0.05, 0.02);
- instance.step(0.0, 0, null);
- verify(instance, 0, 0.05, 0.02);
- instance.step(0.5, 0, null);
- verify(instance, 0.5, 0.05, 0.02);
- instance.step(1.5, 0, null);
- verify(instance, (1.5 + 2.125)/2, 0.05, 0.02);
- instance.step(2.5, 0, null);
- verify(instance, (2.125 + 2.875)/2, 0.05, 0.02);
- instance.step(3.0, 0, null);
- verify(instance, (2+3.0/4 + 3)/2, 0.05, 0.02);
- instance.step(3.5, 0, null);
- verify(instance, (1.5 + 3)/2, 0.045, 0.0225);
- instance.step(4.5, 0, null);
- // mass and cg is simply average of the end points
- verify(instance, 1.5/4, 0.035, 0.0275);
- instance.step(5.0, 0, null);
- verify(instance, 0, 0.03, 0.03);
- }
-
- private void verify(MotorInstance instance, double thrust, double mass, double cgx) {
- assertEquals("Testing thrust", thrust, instance.getThrust(), EPS);
- assertEquals("Testing mass", mass, instance.getCG().weight, EPS);
- assertEquals("Testing cg x", cgx, instance.getCG().x, EPS);
- assertEquals("Testing longitudinal inertia", mass*longitudinal, instance.getLongitudinalInertia(), EPS);
- assertEquals("Testing rotational inertia", mass*rotational, instance.getRotationalInertia(), EPS);
- }
-
-
-}
+++ /dev/null
-package net.sf.openrocket.optimization;
-
-import static org.junit.Assert.*;
-
-import java.util.List;
-
-import net.sf.openrocket.optimization.general.Point;
-import net.sf.openrocket.optimization.general.multidim.SearchPattern;
-
-import org.junit.Test;
-
-public class TestSearchPattern {
-
- @Test
- public void testRegularSimplex() {
- for (int dim = 1; dim < 20; dim++) {
- List<Point> points = SearchPattern.regularSimplex(dim);
- assertEquals(dim, points.size());
-
- for (int i = 0; i < dim; i++) {
- // Test dot product
- for (int j = i + 1; j < dim; j++) {
- double[] x = points.get(i).asArray();
- double[] y = points.get(j).asArray();
- double dot = 0;
- for (int k = 0; k < dim; k++) {
- dot += x[k] * y[k];
- }
- assertEquals(0.5, dot, 0.000000001);
- }
-
- // Test positive coordinates
- for (int j = 0; j < dim; j++) {
- assertTrue(points.get(i).get(j) >= 0);
- }
-
- // Test length
- assertEquals(1.0, points.get(i).length(), 0.000000001);
- }
- }
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.optimization.rocketoptimization;
-
-import static org.junit.Assert.*;
-import net.sf.openrocket.document.Simulation;
-import net.sf.openrocket.optimization.general.OptimizationException;
-import net.sf.openrocket.optimization.general.Point;
-import net.sf.openrocket.rocketcomponent.Rocket;
-import net.sf.openrocket.unit.Unit;
-import net.sf.openrocket.unit.UnitGroup;
-import net.sf.openrocket.unit.Value;
-import net.sf.openrocket.util.Pair;
-
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-import org.jmock.auto.Mock;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-
-@RunWith(JMock.class)
-public class TestRocketOptimizationFunction {
- Mockery context = new JUnit4Mockery();
-
- @Mock
- OptimizableParameter parameter;
- @Mock
- OptimizationGoal goal;
- @Mock
- SimulationDomain domain;
- @Mock
- SimulationModifier modifier1;
- @Mock
- SimulationModifier modifier2;
- @Mock
- RocketOptimizationListener listener;
-
- @Test
- public void testNormalEvaluation() throws InterruptedException, OptimizationException {
- final Rocket rocket = new Rocket();
- final Simulation simulation = new Simulation(rocket);
-
- final double p1 = 0.4;
- final double p2 = 0.7;
- final double ddist = -0.43;
- final Value dref = new Value(ddist, Unit.NOUNIT2);
- final double pvalue = 9.81;
- final Value pvalueValue = new Value(9.81, Unit.NOUNIT2);
- final double gvalue = 8.81;
- final Point point = new Point(p1, p2);
-
- // @formatter:off
- context.checking(new Expectations() {{
- oneOf(modifier1).modify(simulation, p1);
- oneOf(modifier2).modify(simulation, p2);
- oneOf(domain).getDistanceToDomain(simulation); will(returnValue(new Pair<Double,Value>(ddist, dref)));
- oneOf(parameter).computeValue(simulation); will(returnValue(pvalue));
- oneOf(parameter).getUnitGroup(); will(returnValue(UnitGroup.UNITS_NONE));
- oneOf(goal).getMinimizationParameter(pvalue); will(returnValue(gvalue));
- oneOf(modifier1).getCurrentSIValue(simulation); will(returnValue(0.2));
- oneOf(modifier1).getUnitGroup(); will(returnValue(UnitGroup.UNITS_LENGTH));
- oneOf(modifier2).getCurrentSIValue(simulation); will(returnValue(0.3));
- oneOf(modifier2).getUnitGroup(); will(returnValue(UnitGroup.UNITS_LENGTH));
- oneOf(listener).evaluated(point, new Value[] {
- new Value(0.2, UnitGroup.UNITS_LENGTH.getDefaultUnit()),
- new Value(0.3, UnitGroup.UNITS_LENGTH.getDefaultUnit())
- }, dref, pvalueValue, gvalue);
- }});
- // @formatter:on
-
- RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
- parameter, goal, domain, modifier1, modifier2) {
- @Override
- Simulation newSimulationInstance(Simulation sim) {
- return sim;
- }
- };
- function.addRocketOptimizationListener(listener);
-
- double value = function.evaluate(point);
- assertEquals(gvalue, value, 0);
- }
-
- @Test
- public void testNaNValue() throws InterruptedException, OptimizationException {
- final Rocket rocket = new Rocket();
- final Simulation simulation = new Simulation(rocket);
-
- final double p1 = 0.4;
- final double p2 = 0.7;
- final double ddist = -0.43;
- final Value dref = new Value(0.33, Unit.NOUNIT2);
- final double pvalue = 9.81;
-
- // @formatter:off
- context.checking(new Expectations() {{
- oneOf(modifier1).modify(simulation, p1);
- oneOf(modifier2).modify(simulation, p2);
- oneOf(domain).getDistanceToDomain(simulation); will(returnValue(new Pair<Double,Value>(ddist, dref)));
- oneOf(parameter).computeValue(simulation); will(returnValue(pvalue));
- oneOf(parameter).getUnitGroup(); will(returnValue(UnitGroup.UNITS_NONE));
- oneOf(goal).getMinimizationParameter(pvalue); will(returnValue(Double.NaN));
- }});
- // @formatter:on
-
-
- RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
- parameter, goal, domain, modifier1, modifier2) {
- @Override
- Simulation newSimulationInstance(Simulation sim) {
- return sim;
- }
- };
-
-
- double value = function.evaluate(new Point(p1, p2));
- assertEquals(Double.MAX_VALUE, value, 0);
- }
-
-
- @Test
- public void testOutsideDomain() throws InterruptedException, OptimizationException {
- final Rocket rocket = new Rocket();
- final Simulation simulation = new Simulation(rocket);
-
- final double p1 = 0.4;
- final double p2 = 0.7;
- final double ddist = 0.98;
- final Value dref = new Value(ddist, Unit.NOUNIT2);
- final Point point = new Point(p1, p2);
-
- // @formatter:off
- context.checking(new Expectations() {{
- oneOf(modifier1).modify(simulation, p1);
- oneOf(modifier2).modify(simulation, p2);
- oneOf(domain).getDistanceToDomain(simulation); will(returnValue(new Pair<Double,Value>(ddist, dref)));
- oneOf(modifier1).getCurrentSIValue(simulation); will(returnValue(0.2));
- oneOf(modifier1).getUnitGroup(); will(returnValue(UnitGroup.UNITS_LENGTH));
- oneOf(modifier2).getCurrentSIValue(simulation); will(returnValue(0.3));
- oneOf(modifier2).getUnitGroup(); will(returnValue(UnitGroup.UNITS_LENGTH));
- oneOf(listener).evaluated(point, new Value[] {
- new Value(0.2, UnitGroup.UNITS_LENGTH.getDefaultUnit()),
- new Value(0.3, UnitGroup.UNITS_LENGTH.getDefaultUnit())
- }, dref, null, 1.98E200);
- }});
- // @formatter:on
-
-
- RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
- parameter, goal, domain, modifier1, modifier2) {
- @Override
- Simulation newSimulationInstance(Simulation sim) {
- return sim;
- }
- };
- function.addRocketOptimizationListener(listener);
-
- double value = function.evaluate(new Point(p1, p2));
- assertTrue(value > 1e100);
- }
-
- @Test
- public void testOutsideDomain2() throws InterruptedException, OptimizationException {
- final Rocket rocket = new Rocket();
- final Simulation simulation = new Simulation(rocket);
-
- final double p1 = 0.4;
- final double p2 = 0.7;
- final double ddist = Double.NaN;
- final Value dref = new Value(0.33, Unit.NOUNIT2);
-
- // @formatter:off
- context.checking(new Expectations() {{
- oneOf(modifier1).modify(simulation, p1);
- oneOf(modifier2).modify(simulation, p2);
- oneOf(domain).getDistanceToDomain(simulation); will(returnValue(new Pair<Double,Value>(ddist, dref)));
- }});
- // @formatter:on
-
-
- RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
- parameter, goal, domain, modifier1, modifier2) {
- @Override
- Simulation newSimulationInstance(Simulation sim) {
- return sim;
- }
- };
-
- double value = function.evaluate(new Point(p1, p2));
- assertEquals(Double.MAX_VALUE, value, 0);
- }
-
-
- @Test
- public void testNewSimulationInstance() {
- final Rocket rocket = new Rocket();
- rocket.setName("Foobar");
- final Simulation simulation = new Simulation(rocket);
- simulation.setName("MySim");
-
- RocketOptimizationFunction function = new RocketOptimizationFunction(simulation,
- parameter, goal, domain, modifier1, modifier2);
-
- Simulation sim = function.newSimulationInstance(simulation);
- assertFalse(simulation == sim);
- assertEquals("MySim", sim.getName());
- assertFalse(rocket == sim.getRocket());
- assertEquals("Foobar", sim.getRocket().getName());
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.optimization.rocketoptimization.modifiers;
-
-import static net.sf.openrocket.util.MathUtil.EPSILON;
-import static org.junit.Assert.assertEquals;
-import net.sf.openrocket.document.Simulation;
-import net.sf.openrocket.optimization.general.OptimizationException;
-import net.sf.openrocket.rocketcomponent.Rocket;
-import net.sf.openrocket.unit.UnitGroup;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestGenericModifier {
-
- private TestValue value;
- private GenericModifier<TestValue> gm;
- private Simulation sim;
-
- @Before
- public void setup() {
- value = new TestValue();
- sim = new Simulation(new Rocket());
-
- Object related = new Object();
-
- gm = new GenericModifier<TestGenericModifier.TestValue>("Test modifier", "Description", related,
- UnitGroup.UNITS_NONE, 2.0, TestValue.class, "value") {
- @Override
- protected TestValue getModifiedObject(Simulation simulation) {
- Assert.assertTrue(simulation == sim);
- return value;
- }
- };
-
- gm.setMinValue(0.5);
- gm.setMaxValue(5.5);
- }
-
- @Test
- public void testGetCurrentValue() throws OptimizationException {
- value.d = 1.0;
- assertEquals(2.0, gm.getCurrentSIValue(sim), EPSILON);
- value.d = 2.0;
- assertEquals(4.0, gm.getCurrentSIValue(sim), EPSILON);
- }
-
- @Test
- public void testGetCurrentScaledValue() throws OptimizationException {
- value.d = 0.0;
- assertEquals(-0.1, gm.getCurrentScaledValue(sim), EPSILON);
- value.d = 1.0;
- assertEquals(0.3, gm.getCurrentScaledValue(sim), EPSILON);
- value.d = 2.0;
- assertEquals(0.7, gm.getCurrentScaledValue(sim), EPSILON);
- value.d = 3.0;
- assertEquals(1.1, gm.getCurrentScaledValue(sim), EPSILON);
- }
-
- @Test
- public void testModify() throws OptimizationException {
- value.d = 0.0;
- gm.modify(sim, -0.5);
- assertEquals(-1.0, value.d, EPSILON);
-
- gm.modify(sim, 0.0);
- assertEquals(0.25, value.d, EPSILON);
-
- gm.modify(sim, 0.5);
- assertEquals(1.5, value.d, EPSILON);
-
- gm.modify(sim, 1.0);
- assertEquals(2.75, value.d, EPSILON);
-
- gm.modify(sim, 1.5);
- assertEquals(4.0, value.d, EPSILON);
- }
-
- public void testSingularRange() throws OptimizationException {
- gm.setMinValue(1.0);
- gm.setMaxValue(1.0);
- value.d = 0.5;
- assertEquals(0.0, gm.getCurrentScaledValue(sim), EPSILON);
- value.d = 1.0;
- assertEquals(0.5, gm.getCurrentScaledValue(sim), EPSILON);
- value.d = 1.00001;
- assertEquals(1.0, gm.getCurrentScaledValue(sim), EPSILON);
- }
-
- public class TestValue {
- private double d;
-
- public double getValue() {
- return d;
- }
-
- public void setValue(double value) {
- this.d = value;
- }
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.rocketcomponent;
-
-import static org.junit.Assert.*;
-
-import java.lang.reflect.Method;
-import java.util.Iterator;
-import java.util.regex.Pattern;
-
-import net.sf.openrocket.util.BugException;
-
-public class ComponentCompare {
-
- private static final Pattern GETTER_PATTERN = Pattern.compile("^(is|get)[A-Z].*+");
-
- private static final String[] IGNORED_METHODS = {
- "getClass", "getChildCount", "getChildren", "getNextComponent", "getID",
- "getPreviousComponent", "getParent", "getRocket", "getRoot", "getStage",
- "getStageNumber", "getComponentName",
- // Rocket specific methods:
- "getModID", "getMassModID", "getAerodynamicModID", "getTreeModID", "getFunctionalModID",
- "getMotorConfigurationIDs", "getDefaultConfiguration"
- };
-
-
- /**
- * Check whether the two components are <em>equal</em>. Two components are considered
- * equal if they are of the same type and all of their getXXX() and isXXX() methods
- * return equal values.
- *
- * @param c1 the first component to compare.
- * @param c2 the second component to compare.
- */
- public static void assertEquality(RocketComponent c1, RocketComponent c2) {
- assertEquals(c1.getClass(), c2.getClass());
-
- // Same class + similar == equal
- assertSimilarity(c1, c2);
- }
-
-
-
- public static void assertDeepEquality(RocketComponent c1, RocketComponent c2) {
- assertEquality(c1, c2);
-
- Iterator<RocketComponent> i1 = c1.getChildren().iterator();
- Iterator<RocketComponent> i2 = c2.getChildren().iterator();
- while (i1.hasNext()) {
- assertTrue("iterator continues", i2.hasNext());
- RocketComponent comp1 = i1.next();
- RocketComponent comp2 = i2.next();
- assertDeepEquality(comp1, comp2);
- }
- assertFalse("iterator end", i2.hasNext());
- }
-
-
-
- public static void assertDeepSimilarity(RocketComponent c1, RocketComponent c2,
- boolean allowNameDifference) {
- assertSimilarity(c1, c2, allowNameDifference);
-
- Iterator<RocketComponent> i1 = c1.getChildren().iterator();
- Iterator<RocketComponent> i2 = c2.getChildren().iterator();
- while (i1.hasNext()) {
- assertTrue("iterator continues", i2.hasNext());
- RocketComponent comp1 = i1.next();
- RocketComponent comp2 = i2.next();
- assertDeepSimilarity(comp1, comp2, allowNameDifference);
- }
- assertFalse("iterator end", i2.hasNext());
- }
-
-
-
- /**
- * Check whether the two components are <em>similar</em>. Two components are similar
- * if each of the getXXX and isXXX methods that both object types have return
- * equal values. This does not check whether the two components are of the same type.
- *
- * @param c1 the first component.
- * @param c2 the second component.
- */
- public static void assertSimilarity(RocketComponent c1, RocketComponent c2) {
- assertSimilarity(c1, c2, false);
- }
-
- /**
- * Check whether the two components are <em>similar</em>, allowing a name difference.
- *
- * @param c1 the first component.
- * @param c2 the second component.
- * @param allowNameDifference whether to allow the components to have different names.
- */
- public static void assertSimilarity(RocketComponent c1, RocketComponent c2,
- boolean allowNameDifference) {
- Class<? extends RocketComponent> class1 = c1.getClass();
- Class<? extends RocketComponent> class2 = c2.getClass();
-
- mainloop: for (Method m1 : class1.getMethods()) {
- // Check for getter method
- String name = m1.getName();
- if (!GETTER_PATTERN.matcher(name).matches())
- continue;
-
- // Ignore methods that take parameters
- if (m1.getParameterTypes().length != 0)
- continue;
-
- // Ignore specific getters
- for (String ignore : IGNORED_METHODS) {
- if (name.equals(ignore))
- continue mainloop;
- }
- if (allowNameDifference && name.equals("getName"))
- continue;
-
-
- // Check for method in other class
- Method m2;
- try {
- m2 = class2.getMethod(name);
- } catch (NoSuchMethodException e) {
- continue;
- }
-
- // System.out.println("Testing results of method " + name);
-
- // Run the methods
- Object result1, result2;
- try {
- result1 = m1.invoke(c1);
- result2 = m2.invoke(c2);
- } catch (Exception e) {
- throw new BugException("Error executing method " + name, e);
- }
-
- if (result1 != null && result2 != null &&
- result1.getClass().isArray() && result2.getClass().isArray()) {
- assertArrayEquals("Comparing result of method " + name,
- (Object[]) result1, (Object[]) result2);
- } else {
- assertEquals("Comparing result of method " + name, result1, result2);
- }
- }
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.rocketcomponent;
-
-import static org.junit.Assert.*;
-
-import java.awt.Color;
-import java.util.Iterator;
-
-import net.sf.openrocket.gui.util.ColorConversion;
-import net.sf.openrocket.util.Coordinate;
-
-import org.junit.Test;
-
-public class ComponentCompareTest {
-
- @Test
- public void testComponentEquality() {
-
- System.out.println("TEST CLASSPATH: " + System.getProperty("java.class.path"));
-
- Rocket r1 = net.sf.openrocket.util.TestRockets.makeBigBlue();
- Rocket r2 = net.sf.openrocket.util.TestRockets.makeBigBlue();
-
- Iterator<RocketComponent> i1 = r1.iterator(true);
- Iterator<RocketComponent> i2 = r2.iterator(true);
- while (i1.hasNext()) {
- assertTrue(i2.hasNext());
-
- RocketComponent c1 = i1.next();
- RocketComponent c2 = i2.next();
-
- ComponentCompare.assertEquality(c1, c2);
- ComponentCompare.assertSimilarity(c1, c2);
- }
- assertFalse(i2.hasNext());
-
-
- ComponentCompare.assertDeepEquality(r1, r2);
- ComponentCompare.assertDeepSimilarity(r1, r2, false);
-
-
- r1.setColor(ColorConversion.fromAwtColor(Color.YELLOW));
- try {
- ComponentCompare.assertEquality(r1, r2);
- fail();
- } catch (AssertionError e) {
- // Correct behavior
- }
-
-
- i1 = r1.iterator(true);
- i2 = r2.iterator(true);
- boolean finsetfound = false;
- while (i1.hasNext()) {
- RocketComponent c1 = i1.next();
- RocketComponent c2 = i2.next();
-
- if (c1 instanceof FinSet) {
- finsetfound = true;
- FinSet f1 = (FinSet)c1;
- f1.setTabHeight(0.001);
-
- try {
- ComponentCompare.assertEquality(c1, c2);
- fail();
- } catch (AssertionError e) {
- // Correct behavior
- }
- }
- }
- assertTrue(finsetfound);
- }
-
-
- @Test
- public void testComponentSimilarity() throws IllegalFinPointException {
- FinSet trap = new TrapezoidFinSet(
- 5, // fins
- 5.0, // root
- 3.0, // tip
- 0.0, // sweep
- 2.0); // height
- FinSet free = new FreeformFinSet(new Coordinate[] {
- new Coordinate(0,0),
- new Coordinate(0,2),
- new Coordinate(3,2),
- new Coordinate(5,0)
- });
- free.setFinCount(5);
-
- ComponentCompare.assertSimilarity(trap, free, true);
-
- try {
- ComponentCompare.assertSimilarity(trap, free);
- fail();
- } catch (AssertionError e) {
- // Correct behavior
- }
-
- free.setName(trap.getName());
- ComponentCompare.assertSimilarity(trap, free);
-
- try {
- ComponentCompare.assertEquality(trap, free);
- fail();
- } catch (AssertionError e) {
- // Correct behavior
- }
-
-
- BodyTube t1 = new BodyTube();
- BodyTube t2 = new BodyTube();
- t1.addChild(free);
- t2.addChild(trap);
-
- ComponentCompare.assertDeepSimilarity(t1, t2, false);
-
- try {
- ComponentCompare.assertDeepEquality(t1, t2);
- fail();
- } catch (AssertionError e) {
- // Correct behavior
- }
-
- t1.addChild(new TrapezoidFinSet());
-
- try {
- ComponentCompare.assertDeepSimilarity(t1, t2, true);
- fail();
- } catch (AssertionError e) {
- // Correct behavior
- }
-
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.rocketcomponent;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.awt.Color;
-
-import net.sf.openrocket.gui.util.ColorConversion;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.material.Material.Type;
-import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
-import net.sf.openrocket.rocketcomponent.FinSet.CrossSection;
-import net.sf.openrocket.rocketcomponent.FinSet.TabRelativePosition;
-import net.sf.openrocket.rocketcomponent.RocketComponent.Position;
-import net.sf.openrocket.util.LineStyle;
-import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
-
-import org.junit.Test;
-
-public class FinSetTest extends BaseTestCase {
-
-
- @Test
- public void testFreeformConvert() {
- testFreeformConvert(new TrapezoidFinSet());
- testFreeformConvert(new EllipticalFinSet());
- testFreeformConvert(new FreeformFinSet());
- }
-
-
- private void testFreeformConvert(FinSet fin) {
- FreeformFinSet converted;
- Material mat = Material.newMaterial(Type.BULK, "foo", 0.1, true);
-
- fin.setBaseRotation(1.1);
- fin.setCantAngle(0.001);
- fin.setCGOverridden(true);
- fin.setColor(ColorConversion.fromAwtColor(Color.YELLOW));
- fin.setComment("cmt");
- fin.setCrossSection(CrossSection.ROUNDED);
- fin.setFinCount(5);
- fin.setFinish(Finish.ROUGH);
- fin.setLineStyle(LineStyle.DASHDOT);
- fin.setMassOverridden(true);
- fin.setMaterial(mat);
- fin.setOverrideCGX(0.012);
- fin.setOverrideMass(0.0123);
- fin.setOverrideSubcomponents(true);
- fin.setPositionValue(0.1);
- fin.setRelativePosition(Position.ABSOLUTE);
- fin.setTabHeight(0.01);
- fin.setTabLength(0.02);
- fin.setTabRelativePosition(TabRelativePosition.END);
- fin.setTabShift(0.015);
- fin.setThickness(0.005);
-
-
- converted = FreeformFinSet.convertFinSet((FinSet) fin.copy());
-
- ComponentCompare.assertSimilarity(fin, converted, true);
-
- assertEquals(converted.getComponentName(), converted.getName());
-
-
- // Create test rocket
- Rocket rocket = new Rocket();
- Stage stage = new Stage();
- BodyTube body = new BodyTube();
-
- rocket.addChild(stage);
- stage.addChild(body);
- body.addChild(fin);
-
- Listener l1 = new Listener("l1");
- rocket.addComponentChangeListener(l1);
-
- fin.setName("Custom name");
- assertTrue(l1.changed);
- assertEquals(ComponentChangeEvent.NONFUNCTIONAL_CHANGE, l1.changetype);
-
-
- // Create copy
- RocketComponent rocketcopy = rocket.copy();
-
- Listener l2 = new Listener("l2");
- rocketcopy.addComponentChangeListener(l2);
-
- FinSet fincopy = (FinSet) rocketcopy.getChild(0).getChild(0).getChild(0);
- FreeformFinSet.convertFinSet(fincopy);
-
- assertTrue(l2.changed);
- assertEquals(ComponentChangeEvent.TREE_CHANGE,
- l2.changetype & ComponentChangeEvent.TREE_CHANGE);
-
- }
-
-
- private static class Listener implements ComponentChangeListener {
- private boolean changed = false;
- private int changetype = 0;
- private final String name;
-
- public Listener(String name) {
- this.name = name;
- }
-
- @Override
- public void componentChanged(ComponentChangeEvent e) {
- assertFalse("Ensuring listener " + name + " has not been called.", changed);
- changed = true;
- changetype = e.getType();
- }
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.rocketcomponent;
-
-import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
-
-import org.junit.Test;
-
-public class RocketTest extends BaseTestCase {
-
- @Test
- public void testCopyFrom() {
- Rocket r1 = net.sf.openrocket.util.TestRockets.makeIsoHaisu();
- Rocket r2 = net.sf.openrocket.util.TestRockets.makeBigBlue();
-
- Rocket copy = (Rocket) r2.copy();
-
- ComponentCompare.assertDeepEquality(r2, copy);
-
- r1.copyFrom(copy);
-
- ComponentCompare.assertDeepEquality(r1, r2);
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.unit;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class ValueTest {
-
- @Test
- public void testValues() {
- Value v1, v2;
-
- v1 = new Value(273.15, UnitGroup.UNITS_TEMPERATURE.findApproximate("F"));
- v2 = new Value(283.15, UnitGroup.UNITS_TEMPERATURE.findApproximate("C"));
-
- assertTrue(v1.compareTo(v2) > 0);
- assertTrue(v2.compareTo(v1) < 0);
- assertTrue(v1.compareTo(v1) == 0);
- assertTrue(v2.compareTo(v2) == 0);
-
- v2 = new Value(283.15, UnitGroup.UNITS_TEMPERATURE.findApproximate("K"));
- assertTrue(v1.compareTo(v2) > 0);
- assertTrue(v2.compareTo(v1) < 0);
- assertEquals("283 K", v2.toString());
-
- v2 = new Value(283.15, UnitGroup.UNITS_TEMPERATURE.findApproximate("F"));
- assertTrue(v1.compareTo(v2) < 0);
- assertTrue(v2.compareTo(v1) > 0);
-
-
- v1 = new Value(Double.NaN, UnitGroup.UNITS_TEMPERATURE.findApproximate("F"));
- assertTrue(v1.compareTo(v2) > 0);
- assertTrue(v2.compareTo(v1) < 0);
-
- v2 = new Value(Double.NaN, UnitGroup.UNITS_TEMPERATURE.findApproximate("F"));
- assertTrue(v1.compareTo(v2) == 0);
- assertTrue(v1.compareTo(v2) == 0);
- assertEquals("N/A", v1.toString());
- assertEquals("N/A", v2.toString());
-
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util.BaseTestCase;\r
-\r
-import net.sf.openrocket.gui.util.SwingPreferences;\r
-import net.sf.openrocket.startup.Application;\r
-\r
-import org.junit.BeforeClass;\r
-\r
-public class BaseTestCase {\r
-\r
- @BeforeClass\r
- public static void setUpApplication () {\r
- \r
- Application.setPreferences( new SwingPreferences() );\r
- \r
- }\r
-}\r
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class CoordinateTest {
-
- private static final double EPS = 0.0000000001;
-
- @Test
- public void coordinateTest() {
-
- Coordinate x = new Coordinate(1,1,1,1);
- Coordinate y = new Coordinate(1,2,3,4);
-
- assertCoordinateEquals(new Coordinate(2,1,1,1), x.setX(2));
- assertCoordinateEquals(new Coordinate(1,2,1,1), x.setY(2));
- assertCoordinateEquals(new Coordinate(1,1,2,1), x.setZ(2));
- assertCoordinateEquals(new Coordinate(1,1,1,2), x.setWeight(2));
- assertCoordinateEquals(new Coordinate(2,3,4,1), x.setXYZ(y).add(1,1,1));
-
- assertFalse(x.isNaN());
- assertTrue(x.setX(Double.NaN).isNaN());
- assertTrue(Coordinate.NaN.isNaN());
-
- assertTrue(x.isWeighted());
- assertFalse(x.setWeight(0).isWeighted());
-
-
- assertCoordinateEquals(x, x.add(Coordinate.NUL));
- assertCoordinateEquals(new Coordinate(2,3,4,5), x.add(y));
- assertCoordinateEquals(new Coordinate(2,3,4,1), x.add(1,2,3));
- assertCoordinateEquals(new Coordinate(2,3,4,5), x.add(1,2,3,4));
-
- assertCoordinateEquals(new Coordinate(0,-1,-2,1), x.sub(y));
- assertCoordinateEquals(new Coordinate(0,-1,-2,1), x.sub(1,2,3));
-
- assertCoordinateEquals(new Coordinate(2,4,6,8), y.multiply(2));
-
- assertEquals(1+2+3, y.dot(x), EPS);
- assertEquals(1+2+3, x.dot(y), EPS);
- assertEquals(1+2+3, Coordinate.dot(x,y), EPS);
- assertEquals(x.dot(x), x.length2(), EPS);
- assertEquals(y.dot(y), y.length2(), EPS);
- assertEquals(Math.sqrt(1+4+9), y.length(), EPS);
- assertEquals(1, y.normalize().length(), EPS);
-
- assertCoordinateEquals(new Coordinate(1.75,1.75,1.75,4),
- new Coordinate(1,1,1,1).average(new Coordinate(2,2,2,3)));
- assertCoordinateEquals(new Coordinate(1,1,1,1),
- new Coordinate(1,1,1,1).average(new Coordinate(2,2,2,0)));
- assertCoordinateEquals(new Coordinate(1.5,1.5,1.5,0),
- new Coordinate(1,1,1,0).average(new Coordinate(2,2,2,0)));
-
- }
-
-
- private void assertCoordinateEquals(Coordinate a, Coordinate b) {
- assertEquals(a, b);
- assertEquals(a.weight, b.weight, EPS);
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class GeodeticComputationStrategyTest {
-
- @Test
- public void testSpericalAddCoordinate() {
-
- double arcmin = (1.0 / 60.0);
- double arcsec = (1.0 / (60.0 * 60.0));
-
- double lat1 = 50.0 + 3 * arcmin + 59 * arcsec;
- double lon1 = -1.0 * (5 + 42 * arcmin + 53 * arcsec); //W
-
- double lat2 = 58 + 38 * arcmin + 38 * arcsec;
- double lon2 = -1.0 * (3 + 4 * arcmin + 12 * arcsec);
-
- double range = 968.9 * 1000.0;
- double bearing = (9.0 + 7 * arcmin + 11 * arcsec) * (Math.PI / 180.0);
-
- Coordinate coord = new Coordinate(range * Math.sin(bearing), range * Math.cos(bearing), 1000.0);
- WorldCoordinate wc = new WorldCoordinate(lat1, lon1, 0.0);
- wc = GeodeticComputationStrategy.SPHERICAL.addCoordinate(wc, coord);
-
- System.out.println(wc.getLatitudeDeg());
- System.out.println(lat2);
-
- System.out.println(wc.getLongitudeDeg());
- System.out.println(lon2);
-
- assertEquals(lat2, wc.getLatitudeDeg(), 0.001);
- assertEquals(lon2, wc.getLongitudeDeg(), 0.001);
- assertEquals(1000.0, wc.getAltitude(), 0.0);
- }
-
-
- @Test
- public void testAddCoordinates() {
-
- double min = 1 / 60.0;
- double sec = 1 / 3600.0;
-
-
- // Test zero movement
- System.out.println("\nTesting zero movement");
- testAddCoordinate(50.0, 20.0, 0, 123, 50.0, 20.0, false);
-
-
- /*
- * These example values have been computed using the calculator at
- * http://www.movable-type.co.uk/scripts/latlong.html
- */
-
- // Long distance NE over England, crosses Greenwich meridian
- // 50 03N 005 42W to 58 38N 003 04E is 1109km at 027 16'07"
- System.out.println("\nTesting 1109km NE over England");
- testAddCoordinate(50 + 3 * min, -5 - 42 * min, 1109000, 27 + 16 * min + 7 * sec, 58 + 38 * min, 3 + 4 * min, false);
-
- // SW over Brazil
- // -10N -60E to -11N -61E is 155.9km at 224 25'34"
- System.out.println("\nTesting 155km SW over Brazil");
- testAddCoordinate(-10, -60, 155900, 224 + 25 * min + 34 * sec, -11, -61, true);
-
- // NW over the 180 meridian
- // 63N -179E to 63 01N 179E is 100.9km at 271 56'34"
- System.out.println("\nTesting 100km NW over 180 meridian");
- testAddCoordinate(63, -179, 100900, 271 + 56 * min + 34 * sec, 63 + 1 * min, 179, true);
-
- // NE near the north pole
- // 89 50N 0E to 89 45N 175E is 46.29 km at 003 00'01"
- System.out.println("\nTesting 46km NE near north pole");
- testAddCoordinate(89 + 50 * min, 0, 46290, 3 + 0 * min + 1 * sec, 89 + 45 * min, 175, false);
-
- // S directly over south pole
- // -89 50N 12E to -89 45N 192E is 46.33km at 180 00'00"
- System.out.println("\nTesting 46km directly over south pole ");
- testAddCoordinate(-89 - 50 * min, 12, 46330, 180, -89 - 45 * min, -168, false);
-
- }
-
- private void testAddCoordinate(double initialLatitude, double initialLongitude, double distance, double bearing,
- double finalLatitude, double finalLongitude, boolean testFlat) {
-
- double tolerance;
-
- bearing = Math.toRadians(bearing);
-
- // positive X is EAST, positive Y is NORTH
- double deltaX = distance * Math.sin(bearing);
- double deltaY = distance * Math.cos(bearing);
-
- Coordinate coord = new Coordinate(deltaX, deltaY, 1000.0);
- WorldCoordinate wc = new WorldCoordinate(initialLatitude, initialLongitude, 0.0);
-
- // Test SPHERICAL
- tolerance = 0.0015 * distance / 111325;
- System.out.println("\nSpherical tolerance: " + tolerance);
- WorldCoordinate result = GeodeticComputationStrategy.SPHERICAL.addCoordinate(wc, coord);
-
- System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
- System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
- assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
- assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
- assertEquals(1000.0, result.getAltitude(), 0.0);
-
-
- // Test WGS84
- /*
- * Note: Since the example values are computed using a spherical earth approximation,
- * the WGS84 method will have significantly larger errors. A tolerance of 1% accommodates
- * all cases except the NE flight near the north pole, where the ellipsoidal effect is
- * the greatest.
- */
- tolerance = 0.04 * distance / 111325;
- System.out.println("\nWGS84 tolerance: " + tolerance);
- result = GeodeticComputationStrategy.WGS84.addCoordinate(wc, coord);
-
- System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
- System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
- assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
- assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
- assertEquals(1000.0, result.getAltitude(), 0.0);
-
-
- // Test FLAT
- if (testFlat) {
- tolerance = 0.02 * distance / 111325;
- System.out.println("\nFlat tolerance: " + tolerance);
- result = GeodeticComputationStrategy.FLAT.addCoordinate(wc, coord);
-
- System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
- System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
- assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
- assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
- assertEquals(1000.0, result.getAltitude(), 0.0);
-
- }
-
- }
-
-
-
- @Test
- public void testSpericalGetCoriolisAcceleration() {
-
- // For positive latitude and rotational velocity, a movement due east results in an acceleration due south
- Coordinate velocity = new Coordinate(-1000, 0, 0);
- WorldCoordinate wc = new WorldCoordinate(45, 0, 0);
- double north_accel = GeodeticComputationStrategy.SPHERICAL.getCoriolisAcceleration(wc, velocity).y;
- System.out.println("North accel " + north_accel);
- assertTrue(north_accel < 0.0);
-
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static java.lang.Double.NaN;
-import static java.lang.Math.PI;
-import static org.junit.Assert.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
-
-public class MathUtilTest {
-
- public static final double EPS = 0.00000000001;
-
- @Test
- public void miscMathTest() {
-
- assertEquals(PI * PI, MathUtil.pow2(PI), EPS);
- assertEquals(PI * PI * PI, MathUtil.pow3(PI), EPS);
- assertEquals(PI * PI * PI * PI, MathUtil.pow4(PI), EPS);
-
- assertEquals(1.0, MathUtil.clamp(0.9999, 1.0, 2.0), 0);
- assertEquals(1.23, MathUtil.clamp(1.23, 1.0, 2.0), 0);
- assertEquals(2.0, MathUtil.clamp(2 + EPS / 100, 1.0, 2.0), 0);
-
- assertEquals(1.0f, MathUtil.clamp(0.9999f, 1.0f, 2.0f), 0);
- assertEquals(1.23f, MathUtil.clamp(1.23f, 1.0f, 2.0f), 0);
- assertEquals(2.0f, MathUtil.clamp(2.0001f, 1.0f, 2.0f), 0);
-
- assertEquals(1, MathUtil.clamp(-3, 1, 5));
- assertEquals(3, MathUtil.clamp(3, 1, 5));
- assertEquals(5, MathUtil.clamp(6, 1, 5));
-
- assertEquals(-1.0, MathUtil.sign(Double.NEGATIVE_INFINITY), EPS);
- assertEquals(-1.0, MathUtil.sign(-100), EPS);
- assertEquals(-1.0, MathUtil.sign(Math.nextAfter(0.0, -1.0)), EPS);
- assertEquals(1.0, MathUtil.sign(Math.nextUp(0.0)), EPS);
- assertEquals(1.0, MathUtil.sign(100), EPS);
- assertEquals(1.0, MathUtil.sign(Double.POSITIVE_INFINITY), EPS);
- }
-
- @Test
- public void hypotTest() {
-
- for (int i = 0; i < 10000; i++) {
- double x = Math.random() * 100 - 50;
- double y = Math.random() * i - i / 2;
- double z = Math.hypot(x, y);
- assertEquals(z, MathUtil.hypot(x, y), EPS);
- }
-
- }
-
- @Test
- public void reduceTest() {
-
- for (int i = -1000; i < 1000; i++) {
- double angle = Math.random() * 2 * PI;
- double shift = angle + i * 2 * PI;
- assertEquals(angle, MathUtil.reduce360(shift), EPS);
- }
-
- for (int i = -1000; i < 1000; i++) {
- double angle = Math.random() * 2 * PI - PI;
- double shift = angle + i * 2 * PI;
- assertEquals(angle, MathUtil.reduce180(shift), EPS);
- }
-
- }
-
- @Test
- public void minmaxTest() {
- assertEquals(1.0, MathUtil.min(1.0, Math.nextUp(1.0)), 0);
- assertEquals(1.0, MathUtil.min(1.0, Double.POSITIVE_INFINITY), 0);
- assertEquals(1.0, MathUtil.min(NaN, 1.0), 0);
- assertEquals(1.0, MathUtil.min(1.0, NaN), 0);
- assertEquals(NaN, MathUtil.min(NaN, NaN), 0);
-
- assertEquals(Math.nextUp(1.0), MathUtil.max(1.0, Math.nextUp(1.0)), 0);
- assertEquals(Double.POSITIVE_INFINITY, MathUtil.max(1.0, Double.POSITIVE_INFINITY), 0);
- assertEquals(1.0, MathUtil.max(NaN, 1.0), 0);
- assertEquals(1.0, MathUtil.max(1.0, NaN), 0);
- assertEquals(NaN, MathUtil.max(NaN, NaN), 0);
-
- assertEquals(1.0, MathUtil.min(1.0, 2.0, 3.0), 0);
- assertEquals(1.0, MathUtil.min(1.0, NaN, NaN), 0);
- assertEquals(1.0, MathUtil.min(NaN, 1.0, NaN), 0);
- assertEquals(1.0, MathUtil.min(NaN, NaN, 1.0), 0);
- assertEquals(1.0, MathUtil.min(2.0, NaN, 1.0), 0);
- assertEquals(1.0, MathUtil.min(1.0, 2.0, NaN), 0);
- assertEquals(1.0, MathUtil.min(NaN, 2.0, 1.0), 0);
-
- assertEquals(3.0, MathUtil.max(1.0, 3.0, 2.0), 0);
- assertEquals(1.0, MathUtil.max(1.0, NaN, NaN), 0);
- assertEquals(1.0, MathUtil.max(NaN, 1.0, NaN), 0);
- assertEquals(1.0, MathUtil.max(NaN, NaN, 1.0), 0);
- assertEquals(2.0, MathUtil.max(2.0, NaN, 1.0), 0);
- assertEquals(2.0, MathUtil.max(1.0, 2.0, NaN), 0);
- assertEquals(2.0, MathUtil.max(NaN, 2.0, 1.0), 0);
-
- assertEquals(1.0, MathUtil.min(1.0, 2.0, 3.0, 4.0), 0);
- assertEquals(1.0, MathUtil.min(1.0, NaN, NaN, NaN), 0);
- assertEquals(1.0, MathUtil.min(NaN, 1.0, NaN, NaN), 0);
- assertEquals(1.0, MathUtil.min(NaN, NaN, 1.0, NaN), 0);
- assertEquals(1.0, MathUtil.min(2.0, NaN, 1.0, NaN), 0);
- assertEquals(1.0, MathUtil.min(2.0, NaN, NaN, 1.0), 0);
- assertEquals(1.0, MathUtil.min(1.0, 2.0, NaN, 3.0), 0);
- assertEquals(1.0, MathUtil.min(NaN, 2.0, 3.0, 1.0), 0);
-
- }
-
- @Test
- public void mapTest() {
- assertEquals(1.0, MathUtil.map(1.0, 0.0, 5.0, -1.0, 9.0), EPS);
- assertEquals(7.0, MathUtil.map(1.0, 5.0, 0.0, -1.0, 9.0), EPS);
- assertEquals(7.0, MathUtil.map(1.0, 0.0, 5.0, 9.0, -1.0), EPS);
- assertEquals(6.0, MathUtil.map(6.0, 0.0, 5.0, Math.nextUp(6.0), 6.0), EPS);
- assertEquals(6.0, MathUtil.map(6.0, 0.0, 0.0, Math.nextUp(6.0), 6.0), EPS);
- try {
- MathUtil.map(6.0, 1.0, Math.nextUp(1.0), 1.0, 2.0);
- fail("Should not be reached.");
- } catch (IllegalArgumentException normal) {
- }
-
- assertEquals(7.0, MathUtil.map(Math.nextUp(1.0), 0.0, 5.0, 9.0, -1.0), EPS);
- }
-
-
- @Test
- public void mapCoordinateTest() {
- assertEquals(new Coordinate(0.8, 2.0, 1.6, 4.0),
- MathUtil.map(1.0, 0.0, 5.0, new Coordinate(0, 1, 2, 3), new Coordinate(4, 6, 0, 8)));
- }
-
-
- @Test
- public void equalsTest() {
- assertTrue(MathUtil.equals(1.0, 1.0 + MathUtil.EPSILON / 3));
- assertFalse(MathUtil.equals(1.0, 1.0 + MathUtil.EPSILON * 2));
- assertTrue(MathUtil.equals(-1.0, -1.0 + MathUtil.EPSILON / 3));
- assertFalse(MathUtil.equals(-1.0, -1.0 + MathUtil.EPSILON * 2));
-
- for (double zero : new double[] { 0.0, MathUtil.EPSILON / 10, -MathUtil.EPSILON / 10 }) {
-
- assertTrue(MathUtil.equals(zero, MathUtil.EPSILON / 3));
- assertTrue(MathUtil.equals(zero, -MathUtil.EPSILON / 3));
- assertFalse(MathUtil.equals(zero, MathUtil.EPSILON * 2));
- assertFalse(MathUtil.equals(zero, -MathUtil.EPSILON * 2));
-
- assertTrue(MathUtil.equals(MathUtil.EPSILON / 3, zero));
- assertTrue(MathUtil.equals(-MathUtil.EPSILON / 3, zero));
- assertFalse(MathUtil.equals(MathUtil.EPSILON * 2, zero));
- assertFalse(MathUtil.equals(-MathUtil.EPSILON * 2, zero));
-
- }
-
- for (double value : new double[] { PI * 1e20, -PI * 1e20 }) {
- assertTrue("value=" + value, MathUtil.equals(value, value + 1));
- assertTrue("value=" + value, MathUtil.equals(value, Math.nextUp(value)));
- assertTrue("value=" + value, MathUtil.equals(value, value * (1 + MathUtil.EPSILON)));
- }
-
- assertFalse(MathUtil.equals(NaN, 0.0));
- assertFalse(MathUtil.equals(0.0, NaN));
- assertFalse(MathUtil.equals(NaN, NaN));
- }
-
- @Test
- public void testAverageStddev() {
- List<Integer> ints = new ArrayList<Integer>();
- List<Double> doubles = new ArrayList<Double>();
-
- ints.add(3);
- ints.add(4);
- ints.add(7);
- ints.add(5);
-
- doubles.add(3.4);
- doubles.add(2.9);
- doubles.add(7.5);
- doubles.add(5.43);
- doubles.add(2.8);
- doubles.add(6.6);
-
- assertEquals(4.75, MathUtil.average(ints), EPS);
- assertEquals(1.707825127659933, MathUtil.stddev(ints), EPS);
- assertEquals(4.771666666666667, MathUtil.average(doubles), EPS);
- assertEquals(2.024454659078999, MathUtil.stddev(doubles), EPS);
- }
-
- @Test
- public void testMedian() {
- List<Integer> ints = new ArrayList<Integer>();
- List<Double> doubles = new ArrayList<Double>();
-
- ints.add(3);
- ints.add(4);
- ints.add(7);
- ints.add(5);
-
- doubles.add(3.4);
- doubles.add(2.9);
- doubles.add(7.5);
- doubles.add(5.43);
- doubles.add(2.8);
- doubles.add(6.6);
-
- assertEquals(4.5, MathUtil.median(ints), EPS);
- assertEquals(4.415, MathUtil.median(doubles), EPS);
-
- ints.add(9);
- doubles.add(10.0);
-
- assertEquals(5, MathUtil.median(ints), EPS);
- assertEquals(5.43, MathUtil.median(doubles), EPS);
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static org.junit.Assert.*;
-import net.sf.openrocket.logging.TraceException;
-
-import org.junit.Test;
-
-public class MutableTest {
-
- @Test
- public void testMutable() {
- Mutable m = new Mutable();
- Throwable t = null;
-
- m.check();
- m.check();
- assertTrue(m.isMutable());
-
- m.immute();
-
- try {
- m.check();
- fail();
- } catch (IllegalStateException e) {
- // Success
- t = e.getCause();
- assertTrue(t instanceof TraceException);
- }
-
- m.immute();
-
- try {
- m.check();
- fail();
- } catch (IllegalStateException e) {
- // Success
- assertTrue(e.getCause() == t);
- }
- }
-
-
- @Test
- public void testClone() {
- Mutable m1 = new Mutable();
- Mutable m2 = m1.clone();
-
- assertTrue(m1.isMutable());
- assertTrue(m2.isMutable());
-
- m1.immute();
-
- assertFalse(m1.isMutable());
- assertTrue(m2.isMutable());
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-
-import org.junit.Test;
-
-public class ReflectionTest {
-
- @Test
- public void textHandleInvocationTargetException() {
- Throwable cause = null;
-
- try {
- cause = new InvocationTargetException(null);
- Reflection.handleWrappedException((InvocationTargetException)cause);
- fail();
- } catch (BugException e) {
- assertTrue(cause == e.getCause());
- }
-
- try {
- cause = new IllegalStateException("Test");
- Reflection.handleWrappedException(new InvocationTargetException(cause));
- fail();
- } catch (IllegalStateException e) {
- assertTrue(cause == e);
- }
-
- try {
- cause = new AbstractMethodError();
- Reflection.handleWrappedException(new InvocationTargetException(cause));
- fail();
- } catch (AbstractMethodError e) {
- assertTrue(cause == e);
- }
-
- try {
- cause = new IOException();
- Reflection.handleWrappedException(new InvocationTargetException(cause));
- fail();
- } catch (BugException e) {
- assertTrue(cause == e.getCause());
- }
-
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-public class Rotation2DTest {
-
- @Test
- public void rotationTest() {
-
- double rot60 = 0.5;
- double rot30 = Math.sqrt(3)/2;
-
- Coordinate x = new Coordinate(1,1,0);
- Coordinate y = new Coordinate(0,1,1);
-
- Rotation2D rot = new Rotation2D(Math.PI/3); // 60 deg
-
- assertEquals(new Coordinate(rot60, 1, -rot30), rot.rotateY(x));
- assertEquals(new Coordinate(rot60, 1, rot30), rot.invRotateY(x));
-
- assertEquals(new Coordinate(1, rot60, rot30), rot.rotateX(x));
- assertEquals(new Coordinate(1, rot60, -rot30), rot.invRotateX(x));
-
- assertEquals(new Coordinate(-rot30, rot60, 1), rot.rotateZ(y));
- assertEquals(new Coordinate(rot30, rot60, 1), rot.invRotateZ(y));
-
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestMutex {
-
- @Before
- public void setup() {
- System.setProperty("openrocket.debug.safetycheck", "true");
- }
-
- @Test
- public void testSingleLocking() {
- SafetyMutex.ConcreteSafetyMutex m = new SafetyMutex.ConcreteSafetyMutex();
-
- // Test single locking
- assertNull(m.lockingThread);
- m.verify();
- m.lock("here");
- assertNotNull(m.lockingThread);
- assertTrue(m.unlock("here"));
-
- }
-
- @Test
- public void testDoubleLocking() {
- SafetyMutex.ConcreteSafetyMutex m = new SafetyMutex.ConcreteSafetyMutex();
-
- // Test double locking
- m.verify();
- m.lock("foobar");
- m.verify();
- m.lock("bazqux");
- m.verify();
- assertTrue(m.unlock("bazqux"));
- m.verify();
- assertTrue(m.unlock("foobar"));
- m.verify();
- }
-
- @Test
- public void testDoubleUnlocking() {
- SafetyMutex.ConcreteSafetyMutex m = new SafetyMutex.ConcreteSafetyMutex();
- // Mark error reported to not init exception handler
- SafetyMutex.ConcreteSafetyMutex.errorReported = true;
-
- m.lock("here");
- assertTrue(m.unlock("here"));
- assertFalse(m.unlock("here"));
- }
-
-
-
- private volatile int testState = 0;
- private volatile String failure = null;
-
- @Test(timeout = 1000)
- public void testThreadingErrors() {
- final SafetyMutex.ConcreteSafetyMutex m = new SafetyMutex.ConcreteSafetyMutex();
-
- // Initialize and start the thread
- Thread thread = new Thread() {
- @Override
- public void run() {
- try {
-
- // Test locking a locked mutex
- waitFor(1);
- try {
- m.lock("in thread one");
- failure = "Succeeded in locking a mutex locked by a different thread";
- return;
- } catch (ConcurrencyException e) {
- // OK
- }
-
- // Test unlocking a mutex locked by a different thread
- if (m.unlock("in thread two")) {
- failure = "Succeeded in unlocking a mutex locked by a different thread";
- return;
- }
-
- // Test verifying a locked mutex that already has an error
- try {
- m.verify();
- failure = "Succeeded in verifying a mutex locked by a different thread";
- return;
- } catch (ConcurrencyException e) {
- // OK
- }
-
- // Test locking a mutex after it's been unlocked
- testState = 2;
- waitFor(3);
- m.lock("in thread three");
- m.verify();
-
- // Wait for other side to test
- testState = 4;
- waitFor(5);
-
- // Exit code
- testState = 6;
-
- } catch (Exception e) {
- failure = "Exception occurred in thread: " + e;
- return;
- }
-
- }
- };
- thread.setDaemon(true);
- thread.start();
-
- m.lock("one");
- testState = 1;
-
- waitFor(2);
- assertNull("Thread error: " + failure, failure);
-
- m.verify();
- m.unlock("one");
- testState = 3;
-
- waitFor(4);
- assertNull("Thread error: " + failure, failure);
-
- try {
- m.lock("two");
- fail("Succeeded in locking a locked mutex in main thread");
- } catch (ConcurrencyException e) {
- // OK
- }
-
- // Test unlocking a mutex locked by a different thread
- assertFalse(m.unlock("here"));
-
- try {
- m.verify();
- fail("Succeeded in verifying a locked mutex in main thread");
- } catch (ConcurrencyException e) {
- // OK
- }
-
- testState = 5;
- waitFor(6);
- assertNull("Thread error: " + failure, failure);
- }
-
- private void waitFor(int state) {
- while (testState != state && failure == null) {
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- }
- }
- }
-
-
- public void testBogusMutex() {
- SafetyMutex m = new SafetyMutex.BogusSafetyMutex();
- m.lock("foo");
- m.lock("bar");
- m.lock("baz");
- m.verify();
- m.unlock("a");
- m.unlock(null);
- m.unlock("");
- m.unlock("c");
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static java.lang.Math.PI;
-import static org.junit.Assert.assertEquals;
-
-import java.util.Random;
-
-import org.junit.Test;
-
-public class TextUtilTest {
-
- @Test
- public void testHexString() {
- assertEquals("", TextUtil.hexString(new byte[0]));
- assertEquals("00", TextUtil.hexString(new byte[] { 0x00 }));
- assertEquals("ff", TextUtil.hexString(new byte[] { (byte) 0xff }));
-
- for (int i = 0; i <= 0xff; i++) {
- assertEquals(String.format("%02x", i), TextUtil.hexString(new byte[] { (byte) i }));
- }
-
- assertEquals("0f1e2d3c4b5a6978", TextUtil.hexString(new byte[] {
- 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78
- }));
-
- Random rnd = new Random();
- for (int count = 0; count < 10; count++) {
- int n = rnd.nextInt(100);
- byte[] bytes = new byte[n];
- rnd.nextBytes(bytes);
- StringBuilder sb = new StringBuilder();
- for (byte b : bytes) {
- sb.append(String.format("%02x", b & 0xFF));
- }
- assertEquals(sb.toString(), TextUtil.hexString(bytes));
- }
- }
-
- @Test
- public void specialCaseTest() {
- assertEquals("NaN", TextUtil.doubleToString(Double.NaN));
- assertEquals("Inf", TextUtil.doubleToString(Double.POSITIVE_INFINITY));
- assertEquals("-Inf", TextUtil.doubleToString(Double.NEGATIVE_INFINITY));
- assertEquals("0", TextUtil.doubleToString(0.0));
- assertEquals("0", TextUtil.doubleToString(MathUtil.EPSILON / 3));
- assertEquals("0", TextUtil.doubleToString(-MathUtil.EPSILON / 3));
- }
-
- @Test
- public void longTest() {
-
- assertEquals("3.1416e-5", TextUtil.doubleToString(PI * 1e-5));
- assertEquals("3.1416e-4", TextUtil.doubleToString(PI * 1e-4));
- assertEquals("0.0031416", TextUtil.doubleToString(PI * 1e-3));
- assertEquals("0.031416", TextUtil.doubleToString(PI * 1e-2));
- assertEquals("0.31416", TextUtil.doubleToString(PI * 1e-1));
- assertEquals("3.1416", TextUtil.doubleToString(PI));
- assertEquals("31.416", TextUtil.doubleToString(PI * 1e1));
- assertEquals("314.16", TextUtil.doubleToString(PI * 1e2));
- assertEquals("3141.6", TextUtil.doubleToString(PI * 1e3));
- assertEquals("31416", TextUtil.doubleToString(PI * 1e4));
- assertEquals("314159", TextUtil.doubleToString(PI * 1e5));
- assertEquals("3141593", TextUtil.doubleToString(PI * 1e6));
- assertEquals("31415927", TextUtil.doubleToString(PI * 1e7));
- assertEquals("3.1416e8", TextUtil.doubleToString(PI * 1e8));
- assertEquals("3.1416e9", TextUtil.doubleToString(PI * 1e9));
- assertEquals("3.1416e10", TextUtil.doubleToString(PI * 1e10));
-
- assertEquals("-3.1416e-5", TextUtil.doubleToString(-PI * 1e-5));
- assertEquals("-3.1416e-4", TextUtil.doubleToString(-PI * 1e-4));
- assertEquals("-0.0031416", TextUtil.doubleToString(-PI * 1e-3));
- assertEquals("-0.031416", TextUtil.doubleToString(-PI * 1e-2));
- assertEquals("-0.31416", TextUtil.doubleToString(-PI * 1e-1));
- assertEquals("-3.1416", TextUtil.doubleToString(-PI));
- assertEquals("-31.416", TextUtil.doubleToString(-PI * 1e1));
- assertEquals("-314.16", TextUtil.doubleToString(-PI * 1e2));
- assertEquals("-3141.6", TextUtil.doubleToString(-PI * 1e3));
- assertEquals("-31416", TextUtil.doubleToString(-PI * 1e4));
- assertEquals("-314159", TextUtil.doubleToString(-PI * 1e5));
- assertEquals("-3141593", TextUtil.doubleToString(-PI * 1e6));
- assertEquals("-31415927", TextUtil.doubleToString(-PI * 1e7));
- assertEquals("-3.1416e8", TextUtil.doubleToString(-PI * 1e8));
- assertEquals("-3.1416e9", TextUtil.doubleToString(-PI * 1e9));
- assertEquals("-3.1416e10", TextUtil.doubleToString(-PI * 1e10));
-
- }
-
- @Test
- public void shortTest() {
- double p = 3.1;
- assertEquals("3.1e-5", TextUtil.doubleToString(p * 1e-5));
- assertEquals("3.1e-4", TextUtil.doubleToString(p * 1e-4));
- assertEquals("0.0031", TextUtil.doubleToString(p * 1e-3));
- assertEquals("0.031", TextUtil.doubleToString(p * 1e-2));
- assertEquals("0.31", TextUtil.doubleToString(p * 1e-1));
- assertEquals("3.1", TextUtil.doubleToString(p));
- assertEquals("31", TextUtil.doubleToString(p * 1e1));
- assertEquals("310", TextUtil.doubleToString(p * 1e2));
- assertEquals("3100", TextUtil.doubleToString(p * 1e3));
- assertEquals("31000", TextUtil.doubleToString(p * 1e4));
- assertEquals("3.1e5", TextUtil.doubleToString(p * 1e5));
- assertEquals("3.1e6", TextUtil.doubleToString(p * 1e6));
- assertEquals("3.1e7", TextUtil.doubleToString(p * 1e7));
- assertEquals("3.1e8", TextUtil.doubleToString(p * 1e8));
- assertEquals("3.1e9", TextUtil.doubleToString(p * 1e9));
- assertEquals("3.1e10", TextUtil.doubleToString(p * 1e10));
-
- assertEquals("-3.1e-5", TextUtil.doubleToString(-p * 1e-5));
- assertEquals("-3.1e-4", TextUtil.doubleToString(-p * 1e-4));
- assertEquals("-0.0031", TextUtil.doubleToString(-p * 1e-3));
- assertEquals("-0.031", TextUtil.doubleToString(-p * 1e-2));
- assertEquals("-0.31", TextUtil.doubleToString(-p * 1e-1));
- assertEquals("-3.1", TextUtil.doubleToString(-p));
- assertEquals("-31", TextUtil.doubleToString(-p * 1e1));
- assertEquals("-310", TextUtil.doubleToString(-p * 1e2));
- assertEquals("-3100", TextUtil.doubleToString(-p * 1e3));
- assertEquals("-31000", TextUtil.doubleToString(-p * 1e4));
- assertEquals("-3.1e5", TextUtil.doubleToString(-p * 1e5));
- assertEquals("-3.1e6", TextUtil.doubleToString(-p * 1e6));
- assertEquals("-3.1e7", TextUtil.doubleToString(-p * 1e7));
- assertEquals("-3.1e8", TextUtil.doubleToString(-p * 1e8));
- assertEquals("-3.1e9", TextUtil.doubleToString(-p * 1e9));
- assertEquals("-3.1e10", TextUtil.doubleToString(-p * 1e10));
-
- p = 3;
- assertEquals("3e-5", TextUtil.doubleToString(p * 1e-5));
- assertEquals("3e-4", TextUtil.doubleToString(p * 1e-4));
- assertEquals("3e-3", TextUtil.doubleToString(p * 1e-3));
- assertEquals("0.03", TextUtil.doubleToString(p * 1e-2));
- assertEquals("0.3", TextUtil.doubleToString(p * 1e-1));
- assertEquals("3", TextUtil.doubleToString(p));
- assertEquals("30", TextUtil.doubleToString(p * 1e1));
- assertEquals("300", TextUtil.doubleToString(p * 1e2));
- assertEquals("3e3", TextUtil.doubleToString(p * 1e3));
- assertEquals("3e4", TextUtil.doubleToString(p * 1e4));
- assertEquals("3e5", TextUtil.doubleToString(p * 1e5));
- assertEquals("3e6", TextUtil.doubleToString(p * 1e6));
- assertEquals("3e7", TextUtil.doubleToString(p * 1e7));
- assertEquals("3e8", TextUtil.doubleToString(p * 1e8));
- assertEquals("3e9", TextUtil.doubleToString(p * 1e9));
- assertEquals("3e10", TextUtil.doubleToString(p * 1e10));
-
- assertEquals("-3e-5", TextUtil.doubleToString(-p * 1e-5));
- assertEquals("-3e-4", TextUtil.doubleToString(-p * 1e-4));
- assertEquals("-3e-3", TextUtil.doubleToString(-p * 1e-3));
- assertEquals("-0.03", TextUtil.doubleToString(-p * 1e-2));
- assertEquals("-0.3", TextUtil.doubleToString(-p * 1e-1));
- assertEquals("-3", TextUtil.doubleToString(-p));
- assertEquals("-30", TextUtil.doubleToString(-p * 1e1));
- assertEquals("-300", TextUtil.doubleToString(-p * 1e2));
- assertEquals("-3e3", TextUtil.doubleToString(-p * 1e3));
- assertEquals("-3e4", TextUtil.doubleToString(-p * 1e4));
- assertEquals("-3e5", TextUtil.doubleToString(-p * 1e5));
- assertEquals("-3e6", TextUtil.doubleToString(-p * 1e6));
- assertEquals("-3e7", TextUtil.doubleToString(-p * 1e7));
- assertEquals("-3e8", TextUtil.doubleToString(-p * 1e8));
- assertEquals("-3e9", TextUtil.doubleToString(-p * 1e9));
- assertEquals("-3e10", TextUtil.doubleToString(-p * 1e10));
-
- }
-
- @Test
- public void roundingTest() {
-
- assertEquals("1.001", TextUtil.doubleToString(1.00096));
-
-
- /*
- * Not testing with 1.00015 because it might be changed during number formatting
- * calculations. Its rounding is basically arbitrary anyway.
- */
-
- assertEquals("1.0002e-5", TextUtil.doubleToString(1.0001500001e-5));
- assertEquals("1.0001e-5", TextUtil.doubleToString(1.0001499999e-5));
- assertEquals("1.0002e-4", TextUtil.doubleToString(1.0001500001e-4));
- assertEquals("1.0001e-4", TextUtil.doubleToString(1.0001499999e-4));
- assertEquals("0.0010002", TextUtil.doubleToString(1.0001500001e-3));
- assertEquals("0.0010001", TextUtil.doubleToString(1.0001499999e-3));
- assertEquals("0.010002", TextUtil.doubleToString(1.0001500001e-2));
- assertEquals("0.010001", TextUtil.doubleToString(1.0001499999e-2));
- assertEquals("0.10002", TextUtil.doubleToString(1.0001500001e-1));
- assertEquals("0.10001", TextUtil.doubleToString(1.0001499999e-1));
- assertEquals("1.0002", TextUtil.doubleToString(1.0001500001));
- assertEquals("1.0001", TextUtil.doubleToString(1.0001499999));
- assertEquals("10.002", TextUtil.doubleToString(1.0001500001e1));
- assertEquals("10.001", TextUtil.doubleToString(1.0001499999e1));
- assertEquals("100.02", TextUtil.doubleToString(1.0001500001e2));
- assertEquals("100.01", TextUtil.doubleToString(1.0001499999e2));
- assertEquals("1000.2", TextUtil.doubleToString(1.0001500001e3));
- assertEquals("1000.1", TextUtil.doubleToString(1.0001499999e3));
- assertEquals("10002", TextUtil.doubleToString(1.0001500001e4));
- assertEquals("10001", TextUtil.doubleToString(1.0001499999e4));
- assertEquals("100012", TextUtil.doubleToString(1.00011500001e5));
- assertEquals("100011", TextUtil.doubleToString(1.00011499999e5));
- assertEquals("1000112", TextUtil.doubleToString(1.000111500001e6));
- assertEquals("1000111", TextUtil.doubleToString(1.000111499999e6));
- assertEquals("10001112", TextUtil.doubleToString(1.0001111500001e7));
- assertEquals("10001111", TextUtil.doubleToString(1.0001111499999e7));
- assertEquals("1.0002e8", TextUtil.doubleToString(1.0001500001e8));
- assertEquals("1.0001e8", TextUtil.doubleToString(1.0001499999e8));
- assertEquals("1.0002e9", TextUtil.doubleToString(1.0001500001e9));
- assertEquals("1.0001e9", TextUtil.doubleToString(1.0001499999e9));
- assertEquals("1.0002e10", TextUtil.doubleToString(1.0001500001e10));
- assertEquals("1.0001e10", TextUtil.doubleToString(1.0001499999e10));
-
-
- assertEquals("-1.0002e-5", TextUtil.doubleToString(-1.0001500001e-5));
- assertEquals("-1.0001e-5", TextUtil.doubleToString(-1.0001499999e-5));
- assertEquals("-1.0002e-4", TextUtil.doubleToString(-1.0001500001e-4));
- assertEquals("-1.0001e-4", TextUtil.doubleToString(-1.0001499999e-4));
- assertEquals("-0.0010002", TextUtil.doubleToString(-1.0001500001e-3));
- assertEquals("-0.0010001", TextUtil.doubleToString(-1.0001499999e-3));
- assertEquals("-0.010002", TextUtil.doubleToString(-1.0001500001e-2));
- assertEquals("-0.010001", TextUtil.doubleToString(-1.0001499999e-2));
- assertEquals("-0.10002", TextUtil.doubleToString(-1.0001500001e-1));
- assertEquals("-0.10001", TextUtil.doubleToString(-1.0001499999e-1));
- assertEquals("-1.0002", TextUtil.doubleToString(-1.0001500001));
- assertEquals("-1.0001", TextUtil.doubleToString(-1.0001499999));
- assertEquals("-10.002", TextUtil.doubleToString(-1.0001500001e1));
- assertEquals("-10.001", TextUtil.doubleToString(-1.0001499999e1));
- assertEquals("-100.02", TextUtil.doubleToString(-1.0001500001e2));
- assertEquals("-100.01", TextUtil.doubleToString(-1.0001499999e2));
- assertEquals("-1000.2", TextUtil.doubleToString(-1.0001500001e3));
- assertEquals("-1000.1", TextUtil.doubleToString(-1.0001499999e3));
- assertEquals("-10002", TextUtil.doubleToString(-1.0001500001e4));
- assertEquals("-10001", TextUtil.doubleToString(-1.0001499999e4));
- assertEquals("-100012", TextUtil.doubleToString(-1.00011500001e5));
- assertEquals("-100011", TextUtil.doubleToString(-1.00011499999e5));
- assertEquals("-1000112", TextUtil.doubleToString(-1.000111500001e6));
- assertEquals("-1000111", TextUtil.doubleToString(-1.000111499999e6));
- assertEquals("-10001112", TextUtil.doubleToString(-1.0001111500001e7));
- assertEquals("-10001111", TextUtil.doubleToString(-1.0001111499999e7));
- assertEquals("-1.0002e8", TextUtil.doubleToString(-1.0001500001e8));
- assertEquals("-1.0001e8", TextUtil.doubleToString(-1.0001499999e8));
- assertEquals("-1.0002e9", TextUtil.doubleToString(-1.0001500001e9));
- assertEquals("-1.0001e9", TextUtil.doubleToString(-1.0001499999e9));
- assertEquals("-1.0002e10", TextUtil.doubleToString(-1.0001500001e10));
- assertEquals("-1.0001e10", TextUtil.doubleToString(-1.0001499999e10));
-
- }
-
-
- @Test
- public void randomTest() {
- for (int i = 0; i < 10000; i++) {
- double orig = Math.random();
- double result;
- double expected = Math.rint(orig * 100000) / 100000.0;
-
- if (orig < 0.1)
- continue;
- String s = TextUtil.doubleToString(orig);
- result = Double.parseDouble(s);
- assertEquals(expected, result, 0.00000001);
- }
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class UniqueIDTest {
-
- @Test
- public void integerTest() {
-
- int n = UniqueID.next();
- assertTrue(n > 0);
- assertEquals(n+1, UniqueID.next());
- assertEquals(n+2, UniqueID.next());
- assertEquals(n+3, UniqueID.next());
-
- }
-
-
- @Test
- public void stringTest() {
- String id = UniqueID.uuid();
- assertNotNull(id);
- assertNotSame(id, UniqueID.uuid());
- assertNotSame(id, UniqueID.uuid());
- }
-
-}
+++ /dev/null
-package net.sf.openrocket.util;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-public class WorldCoordinateTest {
-
- private static final double EPS = 1e-10;
-
- @Test
- public void testConstructor() {
- WorldCoordinate wc;
-
- wc = new WorldCoordinate(10, 15, 130);
- assertEquals(10, wc.getLatitudeDeg(), EPS);
- assertEquals(15, wc.getLongitudeDeg(), EPS);
- assertEquals(130, wc.getAltitude(), 0);
-
- wc = new WorldCoordinate(100, 190, 13000);
- assertEquals(90, wc.getLatitudeDeg(), EPS);
- assertEquals(-170, wc.getLongitudeDeg(), EPS);
- assertEquals(13000, wc.getAltitude(), 0);
-
- wc = new WorldCoordinate(-100, -200, -13000);
- assertEquals(-90, wc.getLatitudeDeg(), EPS);
- assertEquals(160, wc.getLongitudeDeg(), EPS);
- assertEquals(-13000, wc.getAltitude(), 0);
- }
-
- @Test
- public void testGetLatitude() {
- WorldCoordinate wc;
- wc = new WorldCoordinate(10, 15, 130);
- assertEquals(10, wc.getLatitudeDeg(), EPS);
- assertEquals(Math.toRadians(10), wc.getLatitudeRad(), EPS);
- }
-
- @Test
- public void testGetLongitude() {
- WorldCoordinate wc;
- wc = new WorldCoordinate(10, 15, 130);
- assertEquals(15, wc.getLongitudeDeg(), EPS);
- assertEquals(Math.toRadians(15), wc.getLongitudeRad(), EPS);
- }
-
-}