From 3a1bc46cb35e9cdc22bc1c630f21c855009340d7 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 26 Sep 2022 22:01:04 +0200 Subject: [PATCH 1/5] Refactor sim status checking to separate method --- core/src/net/sf/openrocket/document/Simulation.java | 10 +++++++++- .../net/sf/openrocket/gui/main/SimulationPanel.java | 3 +-- .../net/sf/openrocket/gui/scalefigure/RocketPanel.java | 4 ++-- .../gui/simulation/SimulationEditDialog.java | 3 +-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/core/src/net/sf/openrocket/document/Simulation.java b/core/src/net/sf/openrocket/document/Simulation.java index 3143eb83d..9a75dbbf8 100644 --- a/core/src/net/sf/openrocket/document/Simulation.java +++ b/core/src/net/sf/openrocket/document/Simulation.java @@ -308,7 +308,7 @@ public class Simulation implements ChangeSource, Cloneable { */ public Status getStatus() { mutex.verify(); - if (status == Status.UPTODATE || status == Status.LOADED) { + if (isStatusUpToDate(status)) { if (rocket.getFunctionalModID() != simulatedRocketID || !options.equals(simulatedConditions)) { status = Status.OUTDATED; } @@ -330,6 +330,14 @@ public class Simulation implements ChangeSource, Cloneable { return status; } + + /** + * Returns true is the status indicates that the simulation data is up-to-date. + * @param status status of the simulation to check for if its data is up-to-date + */ + public static boolean isStatusUpToDate(Status status) { + return status == Status.UPTODATE || status == Status.LOADED || status == Status.EXTERNAL; + } diff --git a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java index 423f23d25..29951987c 100644 --- a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java +++ b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java @@ -507,8 +507,7 @@ public class SimulationPanel extends JPanel { private void openDialog(final Simulation sim) { boolean plotMode = false; - if (sim.hasSimulationData() && (sim.getStatus() == Status.UPTODATE || sim.getStatus() == Status.LOADED - || sim.getStatus() == Status.EXTERNAL)) { + if (sim.hasSimulationData() && Simulation.isStatusUpToDate(sim.getStatus())) { plotMode = true; } openDialog(plotMode, sim); diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index 9f4f309f7..d5de4d5e3 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -853,8 +853,8 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change // Re-run the present simulation(s) List sims = new LinkedList<>(); for (Simulation sim : document.getSimulations()) { - if (sim.getStatus() == Simulation.Status.UPTODATE || sim.getStatus() == Simulation.Status.LOADED - || !document.getRocket().getFlightConfiguration(sim.getFlightConfigurationId()).hasMotors()) + if (Simulation.isStatusUpToDate(sim.getStatus()) || + !document.getRocket().getFlightConfiguration(sim.getFlightConfigurationId()).hasMotors()) continue; // Find a Simulation based on the current flight configuration diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java index 03b9ab944..7955bdae3 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java @@ -292,8 +292,7 @@ public class SimulationEditDialog extends JDialog { @Override public void actionPerformed(ActionEvent e) { // If the simulation is out of date, run the simulation. - if (simulationList[0].getStatus() != Simulation.Status.UPTODATE && - simulationList[0].getStatus() != Simulation.Status.LOADED) { + if (!Simulation.isStatusUpToDate(simulationList[0].getStatus())) { new SimulationRunDialog(SimulationEditDialog.this.parentWindow, document, simulationList[0]).setVisible(true); } From 989e80c59c308f2c5f6eaec76368627f8324b6bb Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 27 Sep 2022 16:18:23 +0200 Subject: [PATCH 2/5] Add TODO call --- swing/src/net/sf/openrocket/gui/plot/SimulationPlot.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swing/src/net/sf/openrocket/gui/plot/SimulationPlot.java b/swing/src/net/sf/openrocket/gui/plot/SimulationPlot.java index 9bcb0253f..e14cf9e5b 100644 --- a/swing/src/net/sf/openrocket/gui/plot/SimulationPlot.java +++ b/swing/src/net/sf/openrocket/gui/plot/SimulationPlot.java @@ -60,7 +60,7 @@ import org.jfree.ui.RectangleInsets; import org.jfree.ui.TextAnchor; /* - * It should be possible to simplify this code quite a bit by using a single Renderer instance for + * TODO: It should be possible to simplify this code quite a bit by using a single Renderer instance for * both datasets and the legend. But for now, the renderers are queried for the line color information * and this is held in the Legend. */ From b5e7515f63e9ca8d6ef8c97204a3ee0618c7fd11 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 28 Sep 2022 12:36:19 +0200 Subject: [PATCH 3/5] Remove unnecessary simulation listener --- .../simulation/DisableStageTest.java | 36 +++++++------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/core/test/net/sf/openrocket/simulation/DisableStageTest.java b/core/test/net/sf/openrocket/simulation/DisableStageTest.java index 1162a7ef0..bbd62d4cf 100644 --- a/core/test/net/sf/openrocket/simulation/DisableStageTest.java +++ b/core/test/net/sf/openrocket/simulation/DisableStageTest.java @@ -6,8 +6,6 @@ import net.sf.openrocket.rocketcomponent.FlightConfigurationId; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.simulation.exception.MotorIgnitionException; import net.sf.openrocket.simulation.exception.SimulationException; -import net.sf.openrocket.simulation.listeners.AbstractSimulationListener; -import net.sf.openrocket.simulation.listeners.SimulationListener; import net.sf.openrocket.util.BaseTestCase.BaseTestCase; import net.sf.openrocket.util.TestRockets; import org.junit.Assert; @@ -35,11 +33,9 @@ public class DisableStageTest extends BaseTestCase { simDisabled.getOptions().setISAAtmosphere(true); simDisabled.getOptions().setTimeStep(0.05); - SimulationListener simulationListener = new AbstractSimulationListener(); - // Since there are no stages, the simulation should throw an exception. try { - simDisabled.simulate(simulationListener); + simDisabled.simulate(); } catch (SimulationException e) { if (!(e instanceof MotorIgnitionException)) { Assert.fail("Simulation should have thrown a MotorIgnitionException"); @@ -56,7 +52,7 @@ public class DisableStageTest extends BaseTestCase { simDisabled.getActiveConfiguration().setAllStages(); // Re-enable all stages. - compareSims(simOriginal, simDisabled, simulationListener, delta); + compareSims(simOriginal, simDisabled, delta); } /** @@ -83,9 +79,7 @@ public class DisableStageTest extends BaseTestCase { simDisabled.getOptions().setISAAtmosphere(true); simDisabled.getOptions().setTimeStep(0.05); - SimulationListener simulationListener = new AbstractSimulationListener(); - - compareSims(simRemoved, simDisabled, simulationListener, delta); + compareSims(simRemoved, simDisabled, delta); //// Test re-enableing the stage. Rocket rocketOriginal = TestRockets.makeBeta(); @@ -96,7 +90,7 @@ public class DisableStageTest extends BaseTestCase { simDisabled.getActiveConfiguration().setAllStages(); - compareSims(simOriginal, simDisabled, simulationListener, delta); + compareSims(simOriginal, simDisabled, delta); } /** @@ -173,9 +167,7 @@ public class DisableStageTest extends BaseTestCase { simDisabled.getOptions().setISAAtmosphere(true); simDisabled.getOptions().setTimeStep(0.05); - SimulationListener simulationListener = new AbstractSimulationListener(); - - compareSims(simRemoved, simDisabled, simulationListener, delta); + compareSims(simRemoved, simDisabled, delta); //// Test re-enableing the stage. Rocket rocketOriginal = TestRockets.makeFalcon9Heavy(); @@ -186,7 +178,7 @@ public class DisableStageTest extends BaseTestCase { simDisabled.getActiveConfiguration().setAllStages(); - compareSims(simOriginal, simDisabled, simulationListener, delta); + compareSims(simOriginal, simDisabled, delta); } /** @@ -214,11 +206,9 @@ public class DisableStageTest extends BaseTestCase { simDisabled.getOptions().setISAAtmosphere(true); simDisabled.getOptions().setTimeStep(0.05); - SimulationListener simulationListener = new AbstractSimulationListener(); - // There should be no motors left at this point, so a no motors exception should be thrown try { - simRemoved.simulate(simulationListener); + simRemoved.simulate(); } catch (SimulationException e) { if (!(e instanceof MotorIgnitionException)) { Assert.fail("Simulation failed: " + e); @@ -226,7 +216,7 @@ public class DisableStageTest extends BaseTestCase { } try { - simDisabled.simulate(simulationListener); + simDisabled.simulate(); } catch (SimulationException e) { if (!(e instanceof MotorIgnitionException)) { Assert.fail("Simulation failed: " + e); @@ -242,7 +232,7 @@ public class DisableStageTest extends BaseTestCase { simDisabled.getActiveConfiguration().setAllStages(); - compareSims(simOriginal, simDisabled, simulationListener, delta); + compareSims(simOriginal, simDisabled, delta); } /** @@ -259,13 +249,11 @@ public class DisableStageTest extends BaseTestCase { * - groundHitVelocity * @param simExpected the expected simulation results * @param simActual the actual simulation results - * @param simulationListener the simulation listener to use for the comparison * @param delta the error margin for the comparison (e.g. 0.05 = 5 % error margin) */ - private void compareSims(Simulation simExpected, Simulation simActual, - SimulationListener simulationListener, double delta) { + private void compareSims(Simulation simExpected, Simulation simActual, double delta) { try { - simExpected.simulate(simulationListener); + simExpected.simulate(); double maxAltitudeOriginal = simExpected.getSimulatedData().getMaxAltitude(); double maxVelocityOriginal = simExpected.getSimulatedData().getMaxVelocity(); double maxMachNumberOriginal = simExpected.getSimulatedData().getMaxMachNumber(); @@ -274,7 +262,7 @@ public class DisableStageTest extends BaseTestCase { double launchRodVelocityOriginal = simExpected.getSimulatedData().getLaunchRodVelocity(); double deploymentVelocityOriginal = simExpected.getSimulatedData().getDeploymentVelocity(); - simActual.simulate(simulationListener); + simActual.simulate(); double maxAltitudeDisabled = simActual.getSimulatedData().getMaxAltitude(); double maxVelocityDisabled = simActual.getSimulatedData().getMaxVelocity(); double maxMachNumberDisabled = simActual.getSimulatedData().getMaxMachNumber(); From 7be9dc238a3b4318e58cacf6121cb8765c70f3d4 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 28 Sep 2022 13:12:57 +0200 Subject: [PATCH 4/5] Add unit tests for flight events --- .../simulation/FlightEventsTest.java | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 core/test/net/sf/openrocket/simulation/FlightEventsTest.java diff --git a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java new file mode 100644 index 000000000..6a03e8c9c --- /dev/null +++ b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java @@ -0,0 +1,115 @@ +package net.sf.openrocket.simulation; + +import net.sf.openrocket.document.Simulation; +import net.sf.openrocket.rocketcomponent.FlightConfigurationId; +import net.sf.openrocket.rocketcomponent.Rocket; +import net.sf.openrocket.simulation.exception.SimulationException; +import net.sf.openrocket.util.BaseTestCase.BaseTestCase; +import net.sf.openrocket.util.TestRockets; +import org.junit.Test; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +/** + * Tests to verify that simulations contain all the expected flight events. + */ +public class FlightEventsTest extends BaseTestCase { + /** + * Tests for a single stage design. + */ + @Test + public void testSingleStage() throws SimulationException { + Rocket rocket = TestRockets.makeEstesAlphaIII(); + Simulation sim = new Simulation(rocket); + sim.getOptions().setISAAtmosphere(true); + sim.getOptions().setTimeStep(0.05); + sim.setFlightConfigurationId(TestRockets.TEST_FCID_0); + + sim.simulate(); + + // Test branch count + int branchCount = sim.getSimulatedData().getBranchCount(); + assertEquals(" Single stage simulation invalid branch count", 1, branchCount); + + // Test event count + FlightDataBranch branch = sim.getSimulatedData().getBranch(0); + List eventList = branch.getEvents(); + List eventTypes = eventList.stream().map(FlightEvent::getType).collect(Collectors.toList()); + assertEquals(" Single stage simulation invalid number of events", 10, eventTypes.size()); + + // Test that all expected events are present, and in the right order + FlightEvent.Type[] expectedEventTypes = {FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, + FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, + FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; + for (int i = 0; i < expectedEventTypes.length; i++) { + assertSame(" Flight type " + expectedEventTypes[i] + " not found in single stage simulation", + eventTypes.get(i), expectedEventTypes[i]); + } + } + + /** + * Tests for a multi-stage design. + */ + @Test + public void testMultiStage() throws SimulationException { + Rocket rocket = TestRockets.makeFalcon9Heavy(); + Simulation sim = new Simulation(rocket); + sim.getOptions().setISAAtmosphere(true); + sim.getOptions().setTimeStep(0.05); + rocket.getSelectedConfiguration().setAllStages(); + FlightConfigurationId fcid = rocket.getSelectedConfiguration().getFlightConfigurationID(); + sim.setFlightConfigurationId(fcid); + + sim.simulate(); + + // Test branch count + int branchCount = sim.getSimulatedData().getBranchCount(); + assertEquals(" Multi-stage simulation invalid branch count", 3, branchCount); + + for (int b = 0; b < 3; b++) { + int expectedEventsCount; + FlightEvent.Type[] expectedEventTypes; + switch (b) { + // TODO: change expected values + case 0: + expectedEventsCount = 15; + expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, + FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, + FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; + break; + case 1: + expectedEventsCount = 15; + expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, + FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, + FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; + break; + case 2: + expectedEventsCount = 15; + expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, + FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, + FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; + break; + default: + throw new IllegalStateException("Invalid branch number " + b); + } + + // Test event count + FlightDataBranch branch = sim.getSimulatedData().getBranch(b); + List eventList = branch.getEvents(); + List eventTypes = eventList.stream().map(FlightEvent::getType).collect(Collectors.toList()); + assertEquals(" Multi-stage simulation, branch " + b + " invalid number of events", expectedEventsCount, eventTypes.size()); + System.out.println(eventTypes); + + // Test that all expected events are present, and in the right order + for (int i = 0; i < expectedEventTypes.length; i++) { + assertSame(" Flight type " + expectedEventTypes[i] + ", branch " + b + " not found in multi-stage simulation", + eventTypes.get(i), expectedEventTypes[i]); + } + } + } + +} From e9bc8d1dd13d1f84cd4146e8eaea78bcb62a7711 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 17 Oct 2022 17:53:21 +0200 Subject: [PATCH 5/5] Add unit tests for flight events pt.2 --- .../simulation/FlightEventsTest.java | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java index 6a03e8c9c..037290746 100644 --- a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java +++ b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java @@ -35,16 +35,17 @@ public class FlightEventsTest extends BaseTestCase { int branchCount = sim.getSimulatedData().getBranchCount(); assertEquals(" Single stage simulation invalid branch count", 1, branchCount); + FlightEvent.Type[] expectedEventTypes = {FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, + FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, + FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; + // Test event count FlightDataBranch branch = sim.getSimulatedData().getBranch(0); List eventList = branch.getEvents(); List eventTypes = eventList.stream().map(FlightEvent::getType).collect(Collectors.toList()); - assertEquals(" Single stage simulation invalid number of events", 10, eventTypes.size()); + assertEquals(" Single stage simulation invalid number of events", expectedEventTypes.length, eventTypes.size()); // Test that all expected events are present, and in the right order - FlightEvent.Type[] expectedEventTypes = {FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, - FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, - FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; for (int i = 0; i < expectedEventTypes.length; i++) { assertSame(" Flight type " + expectedEventTypes[i] + " not found in single stage simulation", eventTypes.get(i), expectedEventTypes[i]); @@ -71,27 +72,19 @@ public class FlightEventsTest extends BaseTestCase { assertEquals(" Multi-stage simulation invalid branch count", 3, branchCount); for (int b = 0; b < 3; b++) { - int expectedEventsCount; FlightEvent.Type[] expectedEventTypes; switch (b) { - // TODO: change expected values case 0: - expectedEventsCount = 15; - expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, - FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, - FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; + expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.IGNITION, + FlightEvent.Type.LIFTOFF, FlightEvent.Type.LAUNCHROD, FlightEvent.Type.APOGEE, FlightEvent.Type.BURNOUT, + FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.EJECTION_CHARGE, + FlightEvent.Type.STAGE_SEPARATION, FlightEvent.Type.STAGE_SEPARATION, FlightEvent.Type.TUMBLE, FlightEvent.Type.GROUND_HIT, + FlightEvent.Type.SIMULATION_END}; break; case 1: - expectedEventsCount = 15; - expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, - FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, - FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; - break; case 2: - expectedEventsCount = 15; - expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, - FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, - FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; + expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.TUMBLE, FlightEvent.Type.GROUND_HIT, + FlightEvent.Type.SIMULATION_END}; break; default: throw new IllegalStateException("Invalid branch number " + b); @@ -101,8 +94,7 @@ public class FlightEventsTest extends BaseTestCase { FlightDataBranch branch = sim.getSimulatedData().getBranch(b); List eventList = branch.getEvents(); List eventTypes = eventList.stream().map(FlightEvent::getType).collect(Collectors.toList()); - assertEquals(" Multi-stage simulation, branch " + b + " invalid number of events", expectedEventsCount, eventTypes.size()); - System.out.println(eventTypes); + assertEquals(" Multi-stage simulation, branch " + b + " invalid number of events", expectedEventTypes.length, eventTypes.size()); // Test that all expected events are present, and in the right order for (int i = 0; i < expectedEventTypes.length; i++) {