bug fixes
[debian/openrocket] / src / net / sf / openrocket / gui / main / SimulationRunDialog.java
index 238ca3225e9ebc5ec5e21414c2a54ab563baa9ec..c37ceef22d6b8ba9c05182a1e35b5a858ad515bf 100644 (file)
@@ -10,7 +10,6 @@ import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.io.CharArrayWriter;
 import java.io.PrintWriter;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
@@ -26,16 +25,18 @@ import javax.swing.JProgressBar;
 import net.miginfocom.swing.MigLayout;
 import net.sf.openrocket.document.Simulation;
 import net.sf.openrocket.gui.dialogs.DetailDialog;
+import net.sf.openrocket.logging.LogHelper;
 import net.sf.openrocket.rocketcomponent.Configuration;
 import net.sf.openrocket.rocketcomponent.MotorMount;
 import net.sf.openrocket.rocketcomponent.MotorMount.IgnitionEvent;
 import net.sf.openrocket.simulation.FlightEvent;
-import net.sf.openrocket.simulation.SimulationListener;
 import net.sf.openrocket.simulation.SimulationStatus;
 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.AbstractSimulationListener;
+import net.sf.openrocket.simulation.listeners.SimulationListener;
+import net.sf.openrocket.startup.Application;
 import net.sf.openrocket.unit.Unit;
 import net.sf.openrocket.unit.UnitGroup;
 import net.sf.openrocket.util.GUIUtil;
@@ -44,6 +45,8 @@ import net.sf.openrocket.util.Prefs;
 
 
 public class SimulationRunDialog extends JDialog {
+       private static final LogHelper log = Application.getLogger();
+       
        /** Update the dialog status every this many ms */
        private static final long UPDATE_MS = 200;
        
@@ -53,7 +56,7 @@ public class SimulationRunDialog extends JDialog {
        /** Flight progress at apogee */
        private static final double APOGEE_PROGRESS = 0.7;
        
-       
+
        /*
         * The executor service is not static since we want concurrent simulation
         * dialogs to run in parallel, ie. they both have their own executor service.
@@ -61,11 +64,11 @@ public class SimulationRunDialog extends JDialog {
        private final ExecutorService executor = Executors.newFixedThreadPool(
                        Prefs.getMaxThreadCount());
        
-       
+
        private final JLabel simLabel, timeLabel, altLabel, velLabel;
        private final JProgressBar progressBar;
        
-       
+
        private final Simulation[] simulations;
        private final SimulationWorker[] simulationWorkers;
        private final SimulationStatus[] simulationStatuses;
@@ -73,7 +76,7 @@ public class SimulationRunDialog extends JDialog {
        private final double[] simulationMaxVelocity;
        private final boolean[] simulationDone;
        
-       public SimulationRunDialog(Window window, Simulation ... simulations) {
+       public SimulationRunDialog(Window window, Simulation... simulations) {
                super(window, "Running simulations...", Dialog.ModalityType.DOCUMENT_MODAL);
                
                if (simulations.length == 0) {
@@ -81,7 +84,7 @@ public class SimulationRunDialog extends JDialog {
                }
                
                this.simulations = simulations;
-       
+               
                // Initialize the simulations
                int n = simulations.length;
                simulationWorkers = new SimulationWorker[n];
@@ -90,7 +93,7 @@ public class SimulationRunDialog extends JDialog {
                simulationMaxVelocity = new double[n];
                simulationDone = new boolean[n];
                
-               for (int i=0; i<n; i++) {
+               for (int i = 0; i < n; i++) {
                        simulationWorkers[i] = new InteractiveSimulationWorker(simulations[i], i);
                        executor.execute(simulationWorkers[i]);
                }
@@ -116,7 +119,7 @@ public class SimulationRunDialog extends JDialog {
                progressBar = new JProgressBar();
                panel.add(progressBar, "spanx, growx, wrap para");
                
-               
+
                // Add cancel button
                JButton cancel = new JButton("Cancel");
                cancel.addActionListener(new ActionListener() {
@@ -127,7 +130,7 @@ public class SimulationRunDialog extends JDialog {
                });
                panel.add(cancel, "spanx, tag cancel");
                
-               
+
                // Cancel simulations when user closes the window
                this.addWindowListener(new WindowAdapter() {
                        @Override
@@ -136,7 +139,7 @@ public class SimulationRunDialog extends JDialog {
                        }
                });
                
-               
+
                this.add(panel);
                this.setMinimumSize(new Dimension(300, 0));
                this.setLocationByPlatform(true);
@@ -144,7 +147,7 @@ public class SimulationRunDialog extends JDialog {
                this.pack();
                
                GUIUtil.setDisposableDialogOptions(this, null);
-
+               
                updateProgress();
        }
        
@@ -155,7 +158,7 @@ public class SimulationRunDialog extends JDialog {
         */
        public void cancelSimulations() {
                executor.shutdownNow();
-               for (SimulationWorker w: simulationWorkers) {
+               for (SimulationWorker w : simulationWorkers) {
                        w.cancel(true);
                }
        }
@@ -167,62 +170,60 @@ public class SimulationRunDialog extends JDialog {
         * @param parent                the parent Window of the dialog to use.
         * @param simulations   the simulations to run.
         */
-       public static void runSimulations(Window parent, Simulation ... simulations) {
+       public static void runSimulations(Window parent, Simulation... simulations) {
                new SimulationRunDialog(parent, simulations).setVisible(true);
        }
        
        
-       
-       
+
+
        private void updateProgress() {
-               System.out.println("updateProgress() called");
                int index;
-               for (index=0; index < simulations.length; index++) {
+               for (index = 0; index < simulations.length; index++) {
                        if (!simulationDone[index])
                                break;
                }
                
                if (index >= simulations.length) {
                        // Everything is done, close the dialog
-                       System.out.println("Everything done.");
+                       log.debug("Everything done.");
                        this.dispose();
                        return;
                }
-
+               
                // Update the progress bar status
                int progress = 0;
-               for (SimulationWorker s: simulationWorkers) {
+               for (SimulationWorker s : simulationWorkers) {
                        progress += s.getProgress();
                }
                progress /= simulationWorkers.length;
                progressBar.setValue(progress);
-               System.out.println("Progressbar value "+progress);
+               log.debug("Progressbar value " + progress);
                
                // Update the simulation fields
                simLabel.setText("Running " + simulations[index].getName());
                if (simulationStatuses[index] == null) {
+                       log.debug("No simulation status data available, setting empty labels");
                        timeLabel.setText("");
                        altLabel.setText("");
                        velLabel.setText("");
-                       System.out.println("Empty labels, how sad.");
                        return;
                }
                
                Unit u = UnitGroup.UNITS_FLIGHT_TIME.getDefaultUnit();
-               timeLabel.setText(u.toStringUnit(simulationStatuses[index].time));
+               timeLabel.setText(u.toStringUnit(simulationStatuses[index].getSimulationTime()));
                
                u = UnitGroup.UNITS_DISTANCE.getDefaultUnit();
-               altLabel.setText(u.toStringUnit(simulationStatuses[index].position.z) + " (max. " +
+               altLabel.setText(u.toStringUnit(simulationStatuses[index].getRocketPosition().z) + " (max. " +
                                u.toStringUnit(simulationMaxAltitude[index]) + ")");
                
                u = UnitGroup.UNITS_VELOCITY.getDefaultUnit();
-               velLabel.setText(u.toStringUnit(simulationStatuses[index].velocity.z) + " (max. " +
+               velLabel.setText(u.toStringUnit(simulationStatuses[index].getRocketVelocity().z) + " (max. " +
                                u.toStringUnit(simulationMaxVelocity[index]) + ")");
-               System.out.println("Set interesting labels.");
        }
-
        
        
+
        /**
         * A SwingWorker that performs a flight simulation.  It periodically updates the
         * simulation statuses of the parent class and calls updateProgress().
@@ -232,7 +233,7 @@ public class SimulationRunDialog extends JDialog {
         * @author Sampo Niskanen <sampo.niskanen@iki.fi>
         */
        private class InteractiveSimulationWorker extends SimulationWorker {
-
+               
                private final int index;
                private final double burnoutTimeEstimate;
                private volatile double burnoutVelocity;
@@ -251,7 +252,7 @@ public class SimulationRunDialog extends JDialog {
                public InteractiveSimulationWorker(Simulation sim, int index) {
                        super(sim);
                        this.index = index;
-
+                       
                        // Calculate estimate of motor burn time
                        double launchBurn = 0;
                        double otherBurn = 0;
@@ -261,25 +262,23 @@ public class SimulationRunDialog extends JDialog {
                        while (iterator.hasNext()) {
                                MotorMount m = iterator.next();
                                if (m.getIgnitionEvent() == IgnitionEvent.LAUNCH)
-                                       launchBurn = MathUtil.max(launchBurn, m.getMotor(id).getTotalTime());
+                                       launchBurn = MathUtil.max(launchBurn, m.getMotor(id).getBurnTimeEstimate());
                                else
-                                       otherBurn = otherBurn + m.getMotor(id).getTotalTime();
+                                       otherBurn = otherBurn + m.getMotor(id).getBurnTimeEstimate();
                        }
                        burnoutTimeEstimate = Math.max(launchBurn + otherBurn, 0.1);
                        
                }
-
-
+               
+               
                /**
                 * Return the extra listeners to use, a progress listener and cancel listener.
                 */
                @Override
                protected SimulationListener[] getExtraListeners() {
-                       return new SimulationListener[] {
-                                       new SimulationProgressListener()
-                       };
+                       return new SimulationListener[] { new SimulationProgressListener() };
                }
-
+               
                
                /**
                 * Processes simulation statuses published by the simulation listener.
@@ -289,21 +288,21 @@ public class SimulationRunDialog extends JDialog {
                protected void process(List<SimulationStatus> chunks) {
                        
                        // Update max. altitude and velocity
-                       for (SimulationStatus s: chunks) {
-                               simulationMaxAltitude[index] = Math.max(simulationMaxAltitude[index], 
-                                               s.position.z);
-                               simulationMaxVelocity[index] = Math.max(simulationMaxVelocity[index], 
-                                               s.velocity.length());
+                       for (SimulationStatus s : chunks) {
+                               simulationMaxAltitude[index] = Math.max(simulationMaxAltitude[index],
+                                               s.getRocketPosition().z);
+                               simulationMaxVelocity[index] = Math.max(simulationMaxVelocity[index],
+                                               s.getRocketVelocity().length());
                        }
-
+                       
                        // Calculate the progress
-                       SimulationStatus status = chunks.get(chunks.size()-1);
+                       SimulationStatus status = chunks.get(chunks.size() - 1);
                        simulationStatuses[index] = status;
-
+                       
                        // 1. time = 0 ... burnoutTimeEstimate
-                       if (simulationStage == -2 && status.time < burnoutTimeEstimate) {
-                               System.out.println("Method 1:  t="+status.time + "  est="+burnoutTimeEstimate);
-                               setSimulationProgress(MathUtil.map(status.time, 0, burnoutTimeEstimate, 
+                       if (simulationStage == -2 && status.getSimulationTime() < burnoutTimeEstimate) {
+                               log.debug("Method 1:  t=" + status.getSimulationTime() + "  est=" + burnoutTimeEstimate);
+                               setSimulationProgress(MathUtil.map(status.getSimulationTime(), 0, burnoutTimeEstimate,
                                                0.0, BURNOUT_PROGRESS));
                                updateProgress();
                                return;
@@ -311,29 +310,29 @@ public class SimulationRunDialog extends JDialog {
                        
                        if (simulationStage == -2) {
                                simulationStage++;
-                               burnoutVelocity = MathUtil.max(status.velocity.z, 0.1);
-                               System.out.println("CHANGING to Method 2, vel="+burnoutVelocity);
+                               burnoutVelocity = MathUtil.max(status.getRocketVelocity().z, 0.1);
+                               log.debug("CHANGING to Method 2, vel=" + burnoutVelocity);
                        }
                        
                        // 2. z-velocity from burnout velocity to zero
-                       if (simulationStage == -1 && status.velocity.z >= 0) {
-                               System.out.println("Method 2:  vel="+status.velocity.z + " burnout=" +
-                                               burnoutVelocity);
-                               setSimulationProgress(MathUtil.map(status.velocity.z, burnoutVelocity, 0,
+                       if (simulationStage == -1 && status.getRocketVelocity().z >= 0) {
+                               log.debug("Method 2:  vel=" + status.getRocketVelocity().z + " burnout=" + burnoutVelocity);
+                               setSimulationProgress(MathUtil.map(status.getRocketVelocity().z, burnoutVelocity, 0,
                                                BURNOUT_PROGRESS, APOGEE_PROGRESS));
                                updateProgress();
                                return;
                        }
                        
-                       if (simulationStage == -1 && status.velocity.z < 0) {
+                       if (simulationStage == -1 && status.getRocketVelocity().z < 0) {
                                simulationStage++;
-                               apogeeAltitude = status.position.z;
+                               apogeeAltitude = MathUtil.max(status.getRocketPosition().z, 1);
+                               log.debug("CHANGING to Method 3, apogee=" + apogeeAltitude);
                        }
                        
                        // 3. z-position from apogee to zero
                        // TODO: MEDIUM: several stages
-                       System.out.println("Method 3:  alt="+status.position.z +"  apogee="+apogeeAltitude);
-                       setSimulationProgress(MathUtil.map(status.position.z, 
+                       log.debug("Method 3:  alt=" + status.getRocketPosition().z + "  apogee=" + apogeeAltitude);
+                       setSimulationProgress(MathUtil.map(status.getRocketPosition().z,
                                        apogeeAltitude, 0, APOGEE_PROGRESS, 1.0));
                        updateProgress();
                }
@@ -344,7 +343,7 @@ public class SimulationRunDialog extends JDialog {
                @Override
                protected void simulationDone() {
                        simulationDone[index] = true;
-                       System.out.println("DONE, setting progress");
+                       log.debug("Simulation done");
                        setSimulationProgress(1.0);
                        updateProgress();
                }
@@ -359,7 +358,7 @@ public class SimulationRunDialog extends JDialog {
                        
                        if (t instanceof SimulationCancelledException) {
                                simulationDone();
-                               return;  // Ignore cancellations
+                               return; // Ignore cancellations
                        }
                        
                        // Retrieve the stack trace in a textual form
@@ -371,51 +370,54 @@ public class SimulationRunDialog extends JDialog {
                        // Analyze the exception type
                        if (t instanceof SimulationLaunchException) {
                                
-                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this, 
+                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this,
                                                new Object[] {
-                                               "Unable to simulate:",
-                                               t.getMessage()
+                                                               "Unable to simulate:",
+                                                               t.getMessage()
                                                },
                                                null, simulation.getName(), JOptionPane.ERROR_MESSAGE);
                                
                        } else if (t instanceof SimulationException) {
                                
-                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this, 
+                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this,
                                                new Object[] {
-                                               "A error occurred during the simulation:",
-                                               t.getMessage()
-                                               }, 
+                                                               "A error occurred during the simulation:",
+                                                               t.getMessage()
+                                               },
                                                stackTrace, simulation.getName(), JOptionPane.ERROR_MESSAGE);
                                
                        } else if (t instanceof Exception) {
                                
-                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this, 
+                               // TODO: MEDIUM: Check the exception handling here...
+                               t.printStackTrace();
+                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this,
                                                new Object[] {
-                                               "An exception occurred during the simulation:",
-                                               t.getMessage(),
-                                               simulation.getSimulationListeners().isEmpty() ? 
-                                               "Please report this as a bug along with the details below." : ""
-                                               }, 
+                                                               "An exception occurred during the simulation:",
+                                                               t.getMessage(),
+                                                               simulation.getSimulationListeners().isEmpty() ?
+                                                                               "Please report this as a bug along with the details below." : ""
+                                               },
                                                stackTrace, simulation.getName(), JOptionPane.ERROR_MESSAGE);
                                
                        } else if (t instanceof AssertionError) {
                                
-                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this, 
+                               t.printStackTrace();
+                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this,
                                                new Object[] {
-                                                       "A computation error occurred during the simulation.",
-                                                       "Please report this as a bug along with the details below."
-                                               }, 
+                                                               "A computation error occurred during the simulation.",
+                                                               "Please report this as a bug along with the details below."
+                                               },
                                                stackTrace, simulation.getName(), JOptionPane.ERROR_MESSAGE);
                                
                        } else {
                                
                                // Probably an Error
-                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this, 
+                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this,
                                                new Object[] {
-                                                       "An unknown error was encountered during the simulation.",
-                                                       "The program may be unstable, you should save all your designs " +
-                                                       "and restart OpenRocket now!"
-                                               }, 
+                                                               "An unknown error was encountered during the simulation.",
+                                                               "The program may be unstable, you should save all your designs " +
+                                                                               "and restart OpenRocket now!"
+                                               },
                                                stackTrace, simulation.getName(), JOptionPane.ERROR_MESSAGE);
                                
                        }
@@ -425,14 +427,13 @@ public class SimulationRunDialog extends JDialog {
                
 
                private void setSimulationProgress(double p) {
-                       progress = Math.max(progress, (int)(100*p+0.5));
-                       progress = MathUtil.clamp(progress, 0, 100);
-                       System.out.println("Setting progress to "+progress+ " (real " + 
-                                       ((int)(100*p+0.5)) + ")");
+                       int exact = Math.max(progress, (int) (100 * p + 0.5));
+                       progress = MathUtil.clamp(exact, 0, 100);
+                       log.debug("Setting progress to " + progress + " (real " + exact + ")");
                        super.setProgress(progress);
                }
-
-
+               
+               
                /**
                 * A simulation listener that regularly updates the progress property of the 
                 * SimulationWorker and publishes the simulation status for the run dialog to process.
@@ -441,39 +442,36 @@ public class SimulationRunDialog extends JDialog {
                 */
                private class SimulationProgressListener extends AbstractSimulationListener {
                        private long time = 0;
-
+                       
                        @Override
-                       public Collection<FlightEvent> handleEvent(FlightEvent event,
-                                       SimulationStatus status) {
-                               
+                       public boolean handleFlightEvent(SimulationStatus status, FlightEvent event) {
                                switch (event.getType()) {
                                case APOGEE:
                                        simulationStage = 0;
-                                       apogeeAltitude = status.position.z;
-                                       System.out.println("APOGEE, setting progress");
+                                       apogeeAltitude = status.getRocketPosition().z;
+                                       log.debug("APOGEE, setting progress");
                                        setSimulationProgress(APOGEE_PROGRESS);
                                        publish(status);
                                        break;
-                                       
+                               
                                case LAUNCH:
                                        publish(status);
                                        break;
-                                       
+                               
                                case SIMULATION_END:
-                                       System.out.println("END, setting progress");
+                                       log.debug("END, setting progress");
                                        setSimulationProgress(1.0);
                                        break;
                                }
-                               return null;
+                               return true;
                        }
-
+                       
                        @Override
-                       public Collection<FlightEvent> stepTaken(SimulationStatus status) {
+                       public void postStep(SimulationStatus status) {
                                if (System.currentTimeMillis() >= time + UPDATE_MS) {
                                        time = System.currentTimeMillis();
                                        publish(status);
                                }
-                               return null;
                        }
                }
        }