+package net.sf.openrocket.optimization.rocketoptimization.parameters;
+
+import java.util.Arrays;
+
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.optimization.general.OptimizationException;
+import net.sf.openrocket.optimization.rocketoptimization.OptimizableParameter;
+import net.sf.openrocket.simulation.FlightData;
+import net.sf.openrocket.simulation.exception.MotorIgnitionException;
+import net.sf.openrocket.simulation.exception.SimulationCancelledException;
+import net.sf.openrocket.simulation.exception.SimulationException;
+import net.sf.openrocket.simulation.exception.SimulationLaunchException;
+import net.sf.openrocket.simulation.listeners.SimulationListener;
+import net.sf.openrocket.simulation.listeners.system.InterruptListener;
+import net.sf.openrocket.startup.Application;
+
+/**
+ * An abstract optimization parameter that simulates a rocket flight and obtains
+ * a value from the simulation result.
+ *
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public abstract class SimulationBasedParameter implements OptimizableParameter {
+
+ private static final LogHelper log = Application.getLogger();
+
+ @Override
+ public double computeValue(Simulation simulation) throws OptimizationException, InterruptedException {
+ try {
+ log.debug("Running simulation for " + getName());
+
+ SimulationListener[] listeners = getSimulationListeners();
+ listeners = Arrays.copyOf(listeners, listeners.length + 1);
+ listeners[listeners.length - 1] = new InterruptListener();
+ simulation.simulate(listeners);
+
+ double value = getResultValue(simulation.getSimulatedData());
+ log.debug("Parameter '" + getName() + " was " + value);
+ return value;
+ } catch (MotorIgnitionException e) {
+ // A problem with motor ignition will cause optimization to fail
+ throw new OptimizationException(e);
+ } catch (SimulationLaunchException e) {
+ // Other launch exceptions result in illegal value
+ return Double.NaN;
+ } catch (SimulationCancelledException e) {
+ // Simulation cancellation stops the optimization
+ throw (InterruptedException) new InterruptedException("Optimization was interrupted").initCause(e);
+ } catch (SimulationException e) {
+ // Other exceptions fail
+ throw new OptimizationException(e);
+ }
+ }
+
+
+ /**
+ * Return the optimization parameter from the simulation flight data.
+ *
+ * @param simulatedData the simulated data.
+ * @return the optimization parameter.
+ */
+ protected abstract double getResultValue(FlightData simulatedData);
+
+ /**
+ * Return an array of simulation listeners to provide to the simulation.
+ * This may include a listener that stops the simulation after the necessary value
+ * has been computed.
+ * <p>
+ * This array should NOT contain InterruptListener, it will be added implicitly.
+ *
+ * @return an array of simulation listeners to include.
+ */
+ protected SimulationListener[] getSimulationListeners() {
+ return new SimulationListener[0];
+ }
+
+}