]> git.gag.com Git - debian/openrocket/commitdiff
moving to core/
authorkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Sun, 8 Jan 2012 02:25:52 +0000 (02:25 +0000)
committerkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Sun, 8 Jan 2012 02:25:52 +0000 (02:25 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@300 180e2498-e6e9-4542-8430-84ac67f01cd8

138 files changed:
core/test/net/sf/openrocket/Estes_A8.rse [new file with mode: 0644]
core/test/net/sf/openrocket/IntegrationTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/arch/TestSystemInfo.java [new file with mode: 0644]
core/test/net/sf/openrocket/communication/BugReportTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/communication/ConnectionSourceStub.java [new file with mode: 0644]
core/test/net/sf/openrocket/communication/HttpURLConnectionMock.java [new file with mode: 0644]
core/test/net/sf/openrocket/communication/UpdateInfoTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/database/MotorSetDatabaseTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/iterator/TestDirectoryIterator.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/iterator/TestFileIterator.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/motor/TestMotorLoader.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/motor/test.txt [new file with mode: 0644]
core/test/net/sf/openrocket/file/motor/test.zip [new file with mode: 0644]
core/test/net/sf/openrocket/file/motor/test1.eng [new file with mode: 0644]
core/test/net/sf/openrocket/file/motor/test2.rse [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/export/RocksimDocumentDTOTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/BodyTubeHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/FinSetHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/InnerBodyTubeHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/LaunchLugHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/MassObjectHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/NoseConeHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/ParachuteHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/PodFins.rkt [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/RingHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/RocksimContentHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/RocksimLoaderTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/RocksimTestBase.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/StreamerHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/TransitionHandlerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket1.rkt [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket2.rkt [new file with mode: 0644]
core/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket3.rkt [new file with mode: 0644]
core/test/net/sf/openrocket/gui/TestGUI.java [new file with mode: 0644]
core/test/net/sf/openrocket/gui/configdialog/FinSetConfigTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/gui/print/TestPaperSize.java [new file with mode: 0644]
core/test/net/sf/openrocket/l10n/TestClassBasedTranslator.java [new file with mode: 0644]
core/test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java [new file with mode: 0644]
core/test/net/sf/openrocket/l10n/TestResourceBundleTranslator.java [new file with mode: 0644]
core/test/net/sf/openrocket/logging/CyclicBufferTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/logging/LogLevelBufferLoggerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/logging/LogLevelTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/logging/LoggingTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/logging/TraceExceptionTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/models/gravity/WGSGravityModelTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/motor/ManufacturerTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/motor/MotorDigestTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/motor/ThrustCurveMotorTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/optimization/TestSearchPattern.java [new file with mode: 0644]
core/test/net/sf/openrocket/optimization/rocketoptimization/TestRocketOptimizationFunction.java [new file with mode: 0644]
core/test/net/sf/openrocket/optimization/rocketoptimization/modifiers/TestGenericModifier.java [new file with mode: 0644]
core/test/net/sf/openrocket/rocketcomponent/ComponentCompare.java [new file with mode: 0644]
core/test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/rocketcomponent/FinSetTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/rocketcomponent/RocketTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/simplerocket.ork [new file with mode: 0644]
core/test/net/sf/openrocket/unit/ValueTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/BaseTestCase/BaseTestCase.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/CoordinateTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/GeodeticComputationStrategyTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/MathUtilTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/MutableTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/ReflectionTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/Rotation2DTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/TestMutex.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/TextUtilTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/UniqueIDTest.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/WorldCoordinateTest.java [new file with mode: 0644]
test/net/sf/openrocket/Estes_A8.rse [deleted file]
test/net/sf/openrocket/IntegrationTest.java [deleted file]
test/net/sf/openrocket/arch/TestSystemInfo.java [deleted file]
test/net/sf/openrocket/communication/BugReportTest.java [deleted file]
test/net/sf/openrocket/communication/ConnectionSourceStub.java [deleted file]
test/net/sf/openrocket/communication/HttpURLConnectionMock.java [deleted file]
test/net/sf/openrocket/communication/UpdateInfoTest.java [deleted file]
test/net/sf/openrocket/database/MotorSetDatabaseTest.java [deleted file]
test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java [deleted file]
test/net/sf/openrocket/file/iterator/TestDirectoryIterator.java [deleted file]
test/net/sf/openrocket/file/iterator/TestFileIterator.java [deleted file]
test/net/sf/openrocket/file/motor/TestMotorLoader.java [deleted file]
test/net/sf/openrocket/file/motor/test.txt [deleted file]
test/net/sf/openrocket/file/motor/test.zip [deleted file]
test/net/sf/openrocket/file/motor/test1.eng [deleted file]
test/net/sf/openrocket/file/motor/test2.rse [deleted file]
test/net/sf/openrocket/file/rocksim/export/RocksimDocumentDTOTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/BodyTubeHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/FinSetHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/InnerBodyTubeHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/LaunchLugHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/MassObjectHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/NoseConeHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/ParachuteHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/PodFins.rkt [deleted file]
test/net/sf/openrocket/file/rocksim/importt/RingHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/RocksimContentHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/RocksimLoaderTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/RocksimTestBase.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/StreamerHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/TransitionHandlerTest.java [deleted file]
test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket1.rkt [deleted file]
test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket2.rkt [deleted file]
test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket3.rkt [deleted file]
test/net/sf/openrocket/gui/TestGUI.java [deleted file]
test/net/sf/openrocket/gui/configdialog/FinSetConfigTest.java [deleted file]
test/net/sf/openrocket/gui/print/TestPaperSize.java [deleted file]
test/net/sf/openrocket/l10n/TestClassBasedTranslator.java [deleted file]
test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java [deleted file]
test/net/sf/openrocket/l10n/TestResourceBundleTranslator.java [deleted file]
test/net/sf/openrocket/logging/CyclicBufferTest.java [deleted file]
test/net/sf/openrocket/logging/LogLevelBufferLoggerTest.java [deleted file]
test/net/sf/openrocket/logging/LogLevelTest.java [deleted file]
test/net/sf/openrocket/logging/LoggingTest.java [deleted file]
test/net/sf/openrocket/logging/TraceExceptionTest.java [deleted file]
test/net/sf/openrocket/models/gravity/WGSGravityModelTest.java [deleted file]
test/net/sf/openrocket/motor/ManufacturerTest.java [deleted file]
test/net/sf/openrocket/motor/MotorDigestTest.java [deleted file]
test/net/sf/openrocket/motor/ThrustCurveMotorTest.java [deleted file]
test/net/sf/openrocket/optimization/TestSearchPattern.java [deleted file]
test/net/sf/openrocket/optimization/rocketoptimization/TestRocketOptimizationFunction.java [deleted file]
test/net/sf/openrocket/optimization/rocketoptimization/modifiers/TestGenericModifier.java [deleted file]
test/net/sf/openrocket/rocketcomponent/ComponentCompare.java [deleted file]
test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java [deleted file]
test/net/sf/openrocket/rocketcomponent/FinSetTest.java [deleted file]
test/net/sf/openrocket/rocketcomponent/RocketTest.java [deleted file]
test/net/sf/openrocket/simplerocket.ork [deleted file]
test/net/sf/openrocket/unit/ValueTest.java [deleted file]
test/net/sf/openrocket/util/BaseTestCase/BaseTestCase.java [deleted file]
test/net/sf/openrocket/util/CoordinateTest.java [deleted file]
test/net/sf/openrocket/util/GeodeticComputationStrategyTest.java [deleted file]
test/net/sf/openrocket/util/MathUtilTest.java [deleted file]
test/net/sf/openrocket/util/MutableTest.java [deleted file]
test/net/sf/openrocket/util/ReflectionTest.java [deleted file]
test/net/sf/openrocket/util/Rotation2DTest.java [deleted file]
test/net/sf/openrocket/util/TestMutex.java [deleted file]
test/net/sf/openrocket/util/TextUtilTest.java [deleted file]
test/net/sf/openrocket/util/UniqueIDTest.java [deleted file]
test/net/sf/openrocket/util/WorldCoordinateTest.java [deleted file]

diff --git a/core/test/net/sf/openrocket/Estes_A8.rse b/core/test/net/sf/openrocket/Estes_A8.rse
new file mode 100644 (file)
index 0000000..1098ffe
--- /dev/null
@@ -0,0 +1,40 @@
+<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
diff --git a/core/test/net/sf/openrocket/IntegrationTest.java b/core/test/net/sf/openrocket/IntegrationTest.java
new file mode 100644 (file)
index 0000000..af73af3
--- /dev/null
@@ -0,0 +1,325 @@
+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);
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/arch/TestSystemInfo.java b/core/test/net/sf/openrocket/arch/TestSystemInfo.java
new file mode 100644 (file)
index 0000000..80c6558
--- /dev/null
@@ -0,0 +1,73 @@
+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();
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/communication/BugReportTest.java b/core/test/net/sf/openrocket/communication/BugReportTest.java
new file mode 100644 (file)
index 0000000..e178ec7
--- /dev/null
@@ -0,0 +1,75 @@
+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);
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/communication/ConnectionSourceStub.java b/core/test/net/sf/openrocket/communication/ConnectionSourceStub.java
new file mode 100644 (file)
index 0000000..4cd5470
--- /dev/null
@@ -0,0 +1,22 @@
+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;
+       }
+
+}
diff --git a/core/test/net/sf/openrocket/communication/HttpURLConnectionMock.java b/core/test/net/sf/openrocket/communication/HttpURLConnectionMock.java
new file mode 100644 (file)
index 0000000..ab5c48a
--- /dev/null
@@ -0,0 +1,550 @@
+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();
+       }
+
+       
+       
+       
+}
diff --git a/core/test/net/sf/openrocket/communication/UpdateInfoTest.java b/core/test/net/sf/openrocket/communication/UpdateInfoTest.java
new file mode 100644 (file)
index 0000000..d09db75
--- /dev/null
@@ -0,0 +1,236 @@
+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");
+       }
+
+}
diff --git a/core/test/net/sf/openrocket/database/MotorSetDatabaseTest.java b/core/test/net/sf/openrocket/database/MotorSetDatabaseTest.java
new file mode 100644 (file)
index 0000000..33ced0c
--- /dev/null
@@ -0,0 +1,56 @@
+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());
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java b/core/test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java
new file mode 100644 (file)
index 0000000..56e30b2
--- /dev/null
@@ -0,0 +1,123 @@
+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) {
+               }
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/file/iterator/TestDirectoryIterator.java b/core/test/net/sf/openrocket/file/iterator/TestDirectoryIterator.java
new file mode 100644 (file)
index 0000000..dce1486
--- /dev/null
@@ -0,0 +1,25 @@
+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());
+               }
+               
+       }
+}
diff --git a/core/test/net/sf/openrocket/file/iterator/TestFileIterator.java b/core/test/net/sf/openrocket/file/iterator/TestFileIterator.java
new file mode 100644 (file)
index 0000000..c3e424e
--- /dev/null
@@ -0,0 +1,41 @@
+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());
+       }
+}
diff --git a/core/test/net/sf/openrocket/file/motor/TestMotorLoader.java b/core/test/net/sf/openrocket/file/motor/TestMotorLoader.java
new file mode 100644 (file)
index 0000000..8200310
--- /dev/null
@@ -0,0 +1,63 @@
+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));
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/file/motor/test.txt b/core/test/net/sf/openrocket/file/motor/test.txt
new file mode 100644 (file)
index 0000000..4b43be8
--- /dev/null
@@ -0,0 +1 @@
+boo bah
diff --git a/core/test/net/sf/openrocket/file/motor/test.zip b/core/test/net/sf/openrocket/file/motor/test.zip
new file mode 100644 (file)
index 0000000..eeb5ef7
Binary files /dev/null and b/core/test/net/sf/openrocket/file/motor/test.zip differ
diff --git a/core/test/net/sf/openrocket/file/motor/test1.eng b/core/test/net/sf/openrocket/file/motor/test1.eng
new file mode 100644 (file)
index 0000000..06dc100
--- /dev/null
@@ -0,0 +1,24 @@
+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
diff --git a/core/test/net/sf/openrocket/file/motor/test2.rse b/core/test/net/sf/openrocket/file/motor/test2.rse
new file mode 100644 (file)
index 0000000..a77408f
--- /dev/null
@@ -0,0 +1,52 @@
+<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
diff --git a/core/test/net/sf/openrocket/file/rocksim/export/RocksimDocumentDTOTest.java b/core/test/net/sf/openrocket/file/rocksim/export/RocksimDocumentDTOTest.java
new file mode 100644 (file)
index 0000000..7feb8d2
--- /dev/null
@@ -0,0 +1,66 @@
+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();
+    }
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/BodyTubeHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/BodyTubeHandlerTest.java
new file mode 100644 (file)
index 0000000..b69a3bd
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 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());
+    }
+
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/FinSetHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/FinSetHandlerTest.java
new file mode 100644 (file)
index 0000000..503654b
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * 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();
+        
+    }
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/InnerBodyTubeHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/InnerBodyTubeHandlerTest.java
new file mode 100644 (file)
index 0000000..fa070ce
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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());
+    }
+
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/LaunchLugHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/LaunchLugHandlerTest.java
new file mode 100644 (file)
index 0000000..503ce80
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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());
+    }
+
+
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/MassObjectHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/MassObjectHandlerTest.java
new file mode 100644 (file)
index 0000000..e5360a1
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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());
+    }
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/NoseConeHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/NoseConeHandlerTest.java
new file mode 100644 (file)
index 0000000..593434c
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * 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());
+    }
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/ParachuteHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/ParachuteHandlerTest.java
new file mode 100644 (file)
index 0000000..20ab19f
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * 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);
+    }
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/PodFins.rkt b/core/test/net/sf/openrocket/file/rocksim/importt/PodFins.rkt
new file mode 100644 (file)
index 0000000..a137008
--- /dev/null
@@ -0,0 +1,605 @@
+<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>
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/RingHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/RingHandlerTest.java
new file mode 100644 (file)
index 0000000..af64a82
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * 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());
+    }
+
+
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/RocksimContentHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/RocksimContentHandlerTest.java
new file mode 100644 (file)
index 0000000..0eb1d62
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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());
+    }
+
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/RocksimLoaderTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/RocksimLoaderTest.java
new file mode 100644 (file)
index 0000000..92a0eea
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * 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();
+        }
+    }
+
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/RocksimTestBase.java b/core/test/net/sf/openrocket/file/rocksim/importt/RocksimTestBase.java
new file mode 100644 (file)
index 0000000..14b2494
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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);
+       }
+       
+
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/StreamerHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/StreamerHandlerTest.java
new file mode 100644 (file)
index 0000000..a1dea0a
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * 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);
+
+    }
+
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/TransitionHandlerTest.java b/core/test/net/sf/openrocket/file/rocksim/importt/TransitionHandlerTest.java
new file mode 100644 (file)
index 0000000..cea3a07
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * 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());
+    }
+
+
+}
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket1.rkt b/core/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket1.rkt
new file mode 100644 (file)
index 0000000..79f7b00
--- /dev/null
@@ -0,0 +1,743 @@
+<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>
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket2.rkt b/core/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket2.rkt
new file mode 100644 (file)
index 0000000..39b3411
--- /dev/null
@@ -0,0 +1,1583 @@
+<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>
diff --git a/core/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket3.rkt b/core/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket3.rkt
new file mode 100644 (file)
index 0000000..df1788c
--- /dev/null
@@ -0,0 +1,1961 @@
+<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>
diff --git a/core/test/net/sf/openrocket/gui/TestGUI.java b/core/test/net/sf/openrocket/gui/TestGUI.java
new file mode 100644 (file)
index 0000000..6e05aab
--- /dev/null
@@ -0,0 +1,12 @@
+package net.sf.openrocket.gui;
+
+import org.junit.Test;
+
+public class TestGUI {
+       
+       @Test
+       public void test() {
+               // No-op
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/gui/configdialog/FinSetConfigTest.java b/core/test/net/sf/openrocket/gui/configdialog/FinSetConfigTest.java
new file mode 100644 (file)
index 0000000..e45693b
--- /dev/null
@@ -0,0 +1,257 @@
+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);
+    }
+
+}
diff --git a/core/test/net/sf/openrocket/gui/print/TestPaperSize.java b/core/test/net/sf/openrocket/gui/print/TestPaperSize.java
new file mode 100644 (file)
index 0000000..82677cd
--- /dev/null
@@ -0,0 +1,36 @@
+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));
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/l10n/TestClassBasedTranslator.java b/core/test/net/sf/openrocket/l10n/TestClassBasedTranslator.java
new file mode 100644 (file)
index 0000000..94909b0
--- /dev/null
@@ -0,0 +1,79 @@
+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());
+               }
+               
+       }
+}
diff --git a/core/test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java b/core/test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java
new file mode 100644 (file)
index 0000000..153b921
--- /dev/null
@@ -0,0 +1,64 @@
+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);
+       }
+       
+
+}
diff --git a/core/test/net/sf/openrocket/l10n/TestResourceBundleTranslator.java b/core/test/net/sf/openrocket/l10n/TestResourceBundleTranslator.java
new file mode 100644 (file)
index 0000000..db7dbfc
--- /dev/null
@@ -0,0 +1,34 @@
+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
+               }
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/logging/CyclicBufferTest.java b/core/test/net/sf/openrocket/logging/CyclicBufferTest.java
new file mode 100644 (file)
index 0000000..c767217
--- /dev/null
@@ -0,0 +1,162 @@
+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));
+               }
+               
+       }
+        
+       
+}
diff --git a/core/test/net/sf/openrocket/logging/LogLevelBufferLoggerTest.java b/core/test/net/sf/openrocket/logging/LogLevelBufferLoggerTest.java
new file mode 100644 (file)
index 0000000..4bd9b8d
--- /dev/null
@@ -0,0 +1,58 @@
+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());
+               
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/logging/LogLevelTest.java b/core/test/net/sf/openrocket/logging/LogLevelTest.java
new file mode 100644 (file)
index 0000000..63c7701
--- /dev/null
@@ -0,0 +1,22 @@
+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);
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/logging/LoggingTest.java b/core/test/net/sf/openrocket/logging/LoggingTest.java
new file mode 100644 (file)
index 0000000..39e4777
--- /dev/null
@@ -0,0 +1,63 @@
+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");
+       }
+}
diff --git a/core/test/net/sf/openrocket/logging/TraceExceptionTest.java b/core/test/net/sf/openrocket/logging/TraceExceptionTest.java
new file mode 100644 (file)
index 0000000..72f3c13
--- /dev/null
@@ -0,0 +1,89 @@
+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);
+               }
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/models/gravity/WGSGravityModelTest.java b/core/test/net/sf/openrocket/models/gravity/WGSGravityModelTest.java
new file mode 100644 (file)
index 0000000..a0aea63
--- /dev/null
@@ -0,0 +1,42 @@
+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);
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/motor/ManufacturerTest.java b/core/test/net/sf/openrocket/motor/ManufacturerTest.java
new file mode 100644 (file)
index 0000000..6870c5f
--- /dev/null
@@ -0,0 +1,85 @@
+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"));
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/motor/MotorDigestTest.java b/core/test/net/sf/openrocket/motor/MotorDigestTest.java
new file mode 100644 (file)
index 0000000..916ab12
--- /dev/null
@@ -0,0 +1,76 @@
+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")));
+       }
+}
diff --git a/core/test/net/sf/openrocket/motor/ThrustCurveMotorTest.java b/core/test/net/sf/openrocket/motor/ThrustCurveMotorTest.java
new file mode 100644 (file)
index 0000000..7ca43d7
--- /dev/null
@@ -0,0 +1,74 @@
+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);
+       }
+                       
+       
+}
diff --git a/core/test/net/sf/openrocket/optimization/TestSearchPattern.java b/core/test/net/sf/openrocket/optimization/TestSearchPattern.java
new file mode 100644 (file)
index 0000000..fcb618b
--- /dev/null
@@ -0,0 +1,43 @@
+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);
+                       }
+               }
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/optimization/rocketoptimization/TestRocketOptimizationFunction.java b/core/test/net/sf/openrocket/optimization/rocketoptimization/TestRocketOptimizationFunction.java
new file mode 100644 (file)
index 0000000..48cc648
--- /dev/null
@@ -0,0 +1,212 @@
+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());
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/optimization/rocketoptimization/modifiers/TestGenericModifier.java b/core/test/net/sf/openrocket/optimization/rocketoptimization/modifiers/TestGenericModifier.java
new file mode 100644 (file)
index 0000000..deacacf
--- /dev/null
@@ -0,0 +1,102 @@
+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;
+               }
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/rocketcomponent/ComponentCompare.java b/core/test/net/sf/openrocket/rocketcomponent/ComponentCompare.java
new file mode 100644 (file)
index 0000000..fb231dc
--- /dev/null
@@ -0,0 +1,147 @@
+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);
+                       }
+               }
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java b/core/test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java
new file mode 100644 (file)
index 0000000..46c8f21
--- /dev/null
@@ -0,0 +1,135 @@
+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
+               }
+               
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/rocketcomponent/FinSetTest.java b/core/test/net/sf/openrocket/rocketcomponent/FinSetTest.java
new file mode 100644 (file)
index 0000000..abec65c
--- /dev/null
@@ -0,0 +1,116 @@
+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();
+               }
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java b/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java
new file mode 100644 (file)
index 0000000..16b5ca5
--- /dev/null
@@ -0,0 +1,23 @@
+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);
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/simplerocket.ork b/core/test/net/sf/openrocket/simplerocket.ork
new file mode 100644 (file)
index 0000000..453cdec
Binary files /dev/null and b/core/test/net/sf/openrocket/simplerocket.ork differ
diff --git a/core/test/net/sf/openrocket/unit/ValueTest.java b/core/test/net/sf/openrocket/unit/ValueTest.java
new file mode 100644 (file)
index 0000000..9440c4d
--- /dev/null
@@ -0,0 +1,43 @@
+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());
+               
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/util/BaseTestCase/BaseTestCase.java b/core/test/net/sf/openrocket/util/BaseTestCase/BaseTestCase.java
new file mode 100644 (file)
index 0000000..c5d1feb
--- /dev/null
@@ -0,0 +1,16 @@
+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
diff --git a/core/test/net/sf/openrocket/util/CoordinateTest.java b/core/test/net/sf/openrocket/util/CoordinateTest.java
new file mode 100644 (file)
index 0000000..0c74a3a
--- /dev/null
@@ -0,0 +1,64 @@
+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);
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/util/GeodeticComputationStrategyTest.java b/core/test/net/sf/openrocket/util/GeodeticComputationStrategyTest.java
new file mode 100644 (file)
index 0000000..29efe41
--- /dev/null
@@ -0,0 +1,158 @@
+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);
+               
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/util/MathUtilTest.java b/core/test/net/sf/openrocket/util/MathUtilTest.java
new file mode 100644 (file)
index 0000000..8b79aec
--- /dev/null
@@ -0,0 +1,219 @@
+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);
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/util/MutableTest.java b/core/test/net/sf/openrocket/util/MutableTest.java
new file mode 100644 (file)
index 0000000..dfc0220
--- /dev/null
@@ -0,0 +1,56 @@
+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());
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/util/ReflectionTest.java b/core/test/net/sf/openrocket/util/ReflectionTest.java
new file mode 100644 (file)
index 0000000..9f7c10e
--- /dev/null
@@ -0,0 +1,50 @@
+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());
+               }
+               
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/util/Rotation2DTest.java b/core/test/net/sf/openrocket/util/Rotation2DTest.java
new file mode 100644 (file)
index 0000000..6cc6d91
--- /dev/null
@@ -0,0 +1,31 @@
+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));
+               
+       }
+
+}
diff --git a/core/test/net/sf/openrocket/util/TestMutex.java b/core/test/net/sf/openrocket/util/TestMutex.java
new file mode 100644 (file)
index 0000000..94d5a9f
--- /dev/null
@@ -0,0 +1,175 @@
+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");
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/util/TextUtilTest.java b/core/test/net/sf/openrocket/util/TextUtilTest.java
new file mode 100644 (file)
index 0000000..8ac8319
--- /dev/null
@@ -0,0 +1,258 @@
+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);
+               }
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/util/UniqueIDTest.java b/core/test/net/sf/openrocket/util/UniqueIDTest.java
new file mode 100644 (file)
index 0000000..c77da32
--- /dev/null
@@ -0,0 +1,29 @@
+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());
+       }
+       
+}
diff --git a/core/test/net/sf/openrocket/util/WorldCoordinateTest.java b/core/test/net/sf/openrocket/util/WorldCoordinateTest.java
new file mode 100644 (file)
index 0000000..ce67dc1
--- /dev/null
@@ -0,0 +1,47 @@
+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);
+       }
+       
+}
diff --git a/test/net/sf/openrocket/Estes_A8.rse b/test/net/sf/openrocket/Estes_A8.rse
deleted file mode 100644 (file)
index 1098ffe..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<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
diff --git a/test/net/sf/openrocket/IntegrationTest.java b/test/net/sf/openrocket/IntegrationTest.java
deleted file mode 100644 (file)
index af73af3..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-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);
-       }
-       
-}
diff --git a/test/net/sf/openrocket/arch/TestSystemInfo.java b/test/net/sf/openrocket/arch/TestSystemInfo.java
deleted file mode 100644 (file)
index 80c6558..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-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();
-       }
-       
-}
diff --git a/test/net/sf/openrocket/communication/BugReportTest.java b/test/net/sf/openrocket/communication/BugReportTest.java
deleted file mode 100644 (file)
index e178ec7..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-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);
-       }
-       
-}
diff --git a/test/net/sf/openrocket/communication/ConnectionSourceStub.java b/test/net/sf/openrocket/communication/ConnectionSourceStub.java
deleted file mode 100644 (file)
index 4cd5470..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-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;
-       }
-
-}
diff --git a/test/net/sf/openrocket/communication/HttpURLConnectionMock.java b/test/net/sf/openrocket/communication/HttpURLConnectionMock.java
deleted file mode 100644 (file)
index ab5c48a..0000000
+++ /dev/null
@@ -1,550 +0,0 @@
-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();
-       }
-
-       
-       
-       
-}
diff --git a/test/net/sf/openrocket/communication/UpdateInfoTest.java b/test/net/sf/openrocket/communication/UpdateInfoTest.java
deleted file mode 100644 (file)
index d09db75..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-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");
-       }
-
-}
diff --git a/test/net/sf/openrocket/database/MotorSetDatabaseTest.java b/test/net/sf/openrocket/database/MotorSetDatabaseTest.java
deleted file mode 100644 (file)
index 33ced0c..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-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());
-       }
-       
-}
diff --git a/test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java b/test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java
deleted file mode 100644 (file)
index 56e30b2..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-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) {
-               }
-       }
-       
-}
diff --git a/test/net/sf/openrocket/file/iterator/TestDirectoryIterator.java b/test/net/sf/openrocket/file/iterator/TestDirectoryIterator.java
deleted file mode 100644 (file)
index dce1486..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-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());
-               }
-               
-       }
-}
diff --git a/test/net/sf/openrocket/file/iterator/TestFileIterator.java b/test/net/sf/openrocket/file/iterator/TestFileIterator.java
deleted file mode 100644 (file)
index c3e424e..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-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());
-       }
-}
diff --git a/test/net/sf/openrocket/file/motor/TestMotorLoader.java b/test/net/sf/openrocket/file/motor/TestMotorLoader.java
deleted file mode 100644 (file)
index 8200310..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-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));
-       }
-       
-}
diff --git a/test/net/sf/openrocket/file/motor/test.txt b/test/net/sf/openrocket/file/motor/test.txt
deleted file mode 100644 (file)
index 4b43be8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-boo bah
diff --git a/test/net/sf/openrocket/file/motor/test.zip b/test/net/sf/openrocket/file/motor/test.zip
deleted file mode 100644 (file)
index eeb5ef7..0000000
Binary files a/test/net/sf/openrocket/file/motor/test.zip and /dev/null differ
diff --git a/test/net/sf/openrocket/file/motor/test1.eng b/test/net/sf/openrocket/file/motor/test1.eng
deleted file mode 100644 (file)
index 06dc100..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-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
diff --git a/test/net/sf/openrocket/file/motor/test2.rse b/test/net/sf/openrocket/file/motor/test2.rse
deleted file mode 100644 (file)
index a77408f..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-<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
diff --git a/test/net/sf/openrocket/file/rocksim/export/RocksimDocumentDTOTest.java b/test/net/sf/openrocket/file/rocksim/export/RocksimDocumentDTOTest.java
deleted file mode 100644 (file)
index 7feb8d2..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-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();
-    }
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/BodyTubeHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/BodyTubeHandlerTest.java
deleted file mode 100644 (file)
index b69a3bd..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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());
-    }
-
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/FinSetHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/FinSetHandlerTest.java
deleted file mode 100644 (file)
index 503654b..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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();
-        
-    }
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/InnerBodyTubeHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/InnerBodyTubeHandlerTest.java
deleted file mode 100644 (file)
index fa070ce..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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());
-    }
-
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/LaunchLugHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/LaunchLugHandlerTest.java
deleted file mode 100644 (file)
index 503ce80..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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());
-    }
-
-
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/MassObjectHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/MassObjectHandlerTest.java
deleted file mode 100644 (file)
index e5360a1..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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());
-    }
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/NoseConeHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/NoseConeHandlerTest.java
deleted file mode 100644 (file)
index 593434c..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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());
-    }
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/ParachuteHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/ParachuteHandlerTest.java
deleted file mode 100644 (file)
index 20ab19f..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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);
-    }
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/PodFins.rkt b/test/net/sf/openrocket/file/rocksim/importt/PodFins.rkt
deleted file mode 100644 (file)
index a137008..0000000
+++ /dev/null
@@ -1,605 +0,0 @@
-<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>
diff --git a/test/net/sf/openrocket/file/rocksim/importt/RingHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/RingHandlerTest.java
deleted file mode 100644 (file)
index af64a82..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * 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());
-    }
-
-
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/RocksimContentHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/RocksimContentHandlerTest.java
deleted file mode 100644 (file)
index 0eb1d62..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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());
-    }
-
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/RocksimLoaderTest.java b/test/net/sf/openrocket/file/rocksim/importt/RocksimLoaderTest.java
deleted file mode 100644 (file)
index 92a0eea..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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();
-        }
-    }
-
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/RocksimTestBase.java b/test/net/sf/openrocket/file/rocksim/importt/RocksimTestBase.java
deleted file mode 100644 (file)
index 14b2494..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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);
-       }
-       
-
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/StreamerHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/StreamerHandlerTest.java
deleted file mode 100644 (file)
index a1dea0a..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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);
-
-    }
-
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/TransitionHandlerTest.java b/test/net/sf/openrocket/file/rocksim/importt/TransitionHandlerTest.java
deleted file mode 100644 (file)
index cea3a07..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * 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());
-    }
-
-
-}
diff --git a/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket1.rkt b/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket1.rkt
deleted file mode 100644 (file)
index 79f7b00..0000000
+++ /dev/null
@@ -1,743 +0,0 @@
-<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>
diff --git a/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket2.rkt b/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket2.rkt
deleted file mode 100644 (file)
index 39b3411..0000000
+++ /dev/null
@@ -1,1583 +0,0 @@
-<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>
diff --git a/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket3.rkt b/test/net/sf/openrocket/file/rocksim/importt/rocksimTestRocket3.rkt
deleted file mode 100644 (file)
index df1788c..0000000
+++ /dev/null
@@ -1,1961 +0,0 @@
-<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>
diff --git a/test/net/sf/openrocket/gui/TestGUI.java b/test/net/sf/openrocket/gui/TestGUI.java
deleted file mode 100644 (file)
index 6e05aab..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-package net.sf.openrocket.gui;
-
-import org.junit.Test;
-
-public class TestGUI {
-       
-       @Test
-       public void test() {
-               // No-op
-       }
-       
-}
diff --git a/test/net/sf/openrocket/gui/configdialog/FinSetConfigTest.java b/test/net/sf/openrocket/gui/configdialog/FinSetConfigTest.java
deleted file mode 100644 (file)
index e45693b..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-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);
-    }
-
-}
diff --git a/test/net/sf/openrocket/gui/print/TestPaperSize.java b/test/net/sf/openrocket/gui/print/TestPaperSize.java
deleted file mode 100644 (file)
index 82677cd..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-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));
-       }
-       
-}
diff --git a/test/net/sf/openrocket/l10n/TestClassBasedTranslator.java b/test/net/sf/openrocket/l10n/TestClassBasedTranslator.java
deleted file mode 100644 (file)
index 94909b0..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-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());
-               }
-               
-       }
-}
diff --git a/test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java b/test/net/sf/openrocket/l10n/TestExceptionSuppressingTranslator.java
deleted file mode 100644 (file)
index 153b921..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-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);
-       }
-       
-
-}
diff --git a/test/net/sf/openrocket/l10n/TestResourceBundleTranslator.java b/test/net/sf/openrocket/l10n/TestResourceBundleTranslator.java
deleted file mode 100644 (file)
index db7dbfc..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-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
-               }
-       }
-       
-}
diff --git a/test/net/sf/openrocket/logging/CyclicBufferTest.java b/test/net/sf/openrocket/logging/CyclicBufferTest.java
deleted file mode 100644 (file)
index c767217..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-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));
-               }
-               
-       }
-        
-       
-}
diff --git a/test/net/sf/openrocket/logging/LogLevelBufferLoggerTest.java b/test/net/sf/openrocket/logging/LogLevelBufferLoggerTest.java
deleted file mode 100644 (file)
index 4bd9b8d..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-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());
-               
-       }
-       
-}
diff --git a/test/net/sf/openrocket/logging/LogLevelTest.java b/test/net/sf/openrocket/logging/LogLevelTest.java
deleted file mode 100644 (file)
index 63c7701..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-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);
-       }
-       
-}
diff --git a/test/net/sf/openrocket/logging/LoggingTest.java b/test/net/sf/openrocket/logging/LoggingTest.java
deleted file mode 100644 (file)
index 39e4777..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-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");
-       }
-}
diff --git a/test/net/sf/openrocket/logging/TraceExceptionTest.java b/test/net/sf/openrocket/logging/TraceExceptionTest.java
deleted file mode 100644 (file)
index 72f3c13..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-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);
-               }
-       }
-       
-}
diff --git a/test/net/sf/openrocket/models/gravity/WGSGravityModelTest.java b/test/net/sf/openrocket/models/gravity/WGSGravityModelTest.java
deleted file mode 100644 (file)
index a0aea63..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-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);
-       }
-       
-}
diff --git a/test/net/sf/openrocket/motor/ManufacturerTest.java b/test/net/sf/openrocket/motor/ManufacturerTest.java
deleted file mode 100644 (file)
index 6870c5f..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-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"));
-       }
-       
-}
diff --git a/test/net/sf/openrocket/motor/MotorDigestTest.java b/test/net/sf/openrocket/motor/MotorDigestTest.java
deleted file mode 100644 (file)
index 916ab12..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-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")));
-       }
-}
diff --git a/test/net/sf/openrocket/motor/ThrustCurveMotorTest.java b/test/net/sf/openrocket/motor/ThrustCurveMotorTest.java
deleted file mode 100644 (file)
index 7ca43d7..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-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);
-       }
-                       
-       
-}
diff --git a/test/net/sf/openrocket/optimization/TestSearchPattern.java b/test/net/sf/openrocket/optimization/TestSearchPattern.java
deleted file mode 100644 (file)
index fcb618b..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-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);
-                       }
-               }
-       }
-       
-}
diff --git a/test/net/sf/openrocket/optimization/rocketoptimization/TestRocketOptimizationFunction.java b/test/net/sf/openrocket/optimization/rocketoptimization/TestRocketOptimizationFunction.java
deleted file mode 100644 (file)
index 48cc648..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-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());
-       }
-       
-}
diff --git a/test/net/sf/openrocket/optimization/rocketoptimization/modifiers/TestGenericModifier.java b/test/net/sf/openrocket/optimization/rocketoptimization/modifiers/TestGenericModifier.java
deleted file mode 100644 (file)
index deacacf..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-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;
-               }
-       }
-       
-}
diff --git a/test/net/sf/openrocket/rocketcomponent/ComponentCompare.java b/test/net/sf/openrocket/rocketcomponent/ComponentCompare.java
deleted file mode 100644 (file)
index fb231dc..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-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);
-                       }
-               }
-       }
-       
-}
diff --git a/test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java b/test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java
deleted file mode 100644 (file)
index 46c8f21..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-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
-               }
-               
-       }
-       
-}
diff --git a/test/net/sf/openrocket/rocketcomponent/FinSetTest.java b/test/net/sf/openrocket/rocketcomponent/FinSetTest.java
deleted file mode 100644 (file)
index abec65c..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-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();
-               }
-       }
-       
-}
diff --git a/test/net/sf/openrocket/rocketcomponent/RocketTest.java b/test/net/sf/openrocket/rocketcomponent/RocketTest.java
deleted file mode 100644 (file)
index 16b5ca5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-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);
-       }
-       
-}
diff --git a/test/net/sf/openrocket/simplerocket.ork b/test/net/sf/openrocket/simplerocket.ork
deleted file mode 100644 (file)
index 453cdec..0000000
Binary files a/test/net/sf/openrocket/simplerocket.ork and /dev/null differ
diff --git a/test/net/sf/openrocket/unit/ValueTest.java b/test/net/sf/openrocket/unit/ValueTest.java
deleted file mode 100644 (file)
index 9440c4d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-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());
-               
-       }
-       
-}
diff --git a/test/net/sf/openrocket/util/BaseTestCase/BaseTestCase.java b/test/net/sf/openrocket/util/BaseTestCase/BaseTestCase.java
deleted file mode 100644 (file)
index c5d1feb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-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
diff --git a/test/net/sf/openrocket/util/CoordinateTest.java b/test/net/sf/openrocket/util/CoordinateTest.java
deleted file mode 100644 (file)
index 0c74a3a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-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);
-       }
-       
-}
diff --git a/test/net/sf/openrocket/util/GeodeticComputationStrategyTest.java b/test/net/sf/openrocket/util/GeodeticComputationStrategyTest.java
deleted file mode 100644 (file)
index 29efe41..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-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);
-               
-       }
-       
-}
diff --git a/test/net/sf/openrocket/util/MathUtilTest.java b/test/net/sf/openrocket/util/MathUtilTest.java
deleted file mode 100644 (file)
index 8b79aec..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-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);
-       }
-       
-}
diff --git a/test/net/sf/openrocket/util/MutableTest.java b/test/net/sf/openrocket/util/MutableTest.java
deleted file mode 100644 (file)
index dfc0220..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-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());
-       }
-       
-}
diff --git a/test/net/sf/openrocket/util/ReflectionTest.java b/test/net/sf/openrocket/util/ReflectionTest.java
deleted file mode 100644 (file)
index 9f7c10e..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-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());
-               }
-               
-       }
-       
-}
diff --git a/test/net/sf/openrocket/util/Rotation2DTest.java b/test/net/sf/openrocket/util/Rotation2DTest.java
deleted file mode 100644 (file)
index 6cc6d91..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-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));
-               
-       }
-
-}
diff --git a/test/net/sf/openrocket/util/TestMutex.java b/test/net/sf/openrocket/util/TestMutex.java
deleted file mode 100644 (file)
index 94d5a9f..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-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");
-       }
-       
-}
diff --git a/test/net/sf/openrocket/util/TextUtilTest.java b/test/net/sf/openrocket/util/TextUtilTest.java
deleted file mode 100644 (file)
index 8ac8319..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-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);
-               }
-       }
-       
-}
diff --git a/test/net/sf/openrocket/util/UniqueIDTest.java b/test/net/sf/openrocket/util/UniqueIDTest.java
deleted file mode 100644 (file)
index c77da32..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-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());
-       }
-       
-}
diff --git a/test/net/sf/openrocket/util/WorldCoordinateTest.java b/test/net/sf/openrocket/util/WorldCoordinateTest.java
deleted file mode 100644 (file)
index ce67dc1..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-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);
-       }
-       
-}