home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / solaris2 / book / applets / nuclearp / nuclearp.jav < prev    next >
Encoding:
Text File  |  1995-09-15  |  46.8 KB  |  1,294 lines

  1.  
  2. import java.awt.Image;
  3. import java.awt.Graphics;
  4. import java.awt.Color;
  5. import java.awt.Button;
  6. import java.awt.Dimension;
  7. import java.awt.Container;
  8. import java.awt.Window;
  9. import java.awt.Panel;
  10. import java.awt.BorderLayout;
  11. import java.awt.FlowLayout;
  12. import java.awt.Event;
  13.  
  14. import java.net.URL;
  15. import java.io.DataInputStream;
  16. import java.io.DataOutputStream;
  17. import java.util.StringTokenizer;
  18.  
  19. /* Copyright (C) 1995 Link=F6ping University, Link=F6ping, Sweden. */
  20.  
  21. /**
  22.  * The class NuclearPlant is an applet that lets you run a nuclear power plant
  23.  *
  24.  * @version 1.0f
  25.  * @author Henrik Eriksson
  26.  */
  27.           public class NuclearPlant extends java.applet.Applet implements Runnable {
  28.  
  29.               /** The thread that updates the display (for animation) */
  30.               protected Thread kicker = null;
  31.  
  32.               /** The amount of time too sleep between display updates (ms?) */
  33.               protected int kickerDelay;
  34.  
  35.               /** The offscreen image */
  36.               protected Image im;
  37.  
  38.               /** The offscreen graphics context */
  39.               protected Graphics offscreen;
  40.  
  41.               /** The static background image */
  42.               protected Image background;
  43.  
  44.               /** The directory that contains the images. This
  45.                   directory is the location for GIFS for the
  46.                   background, plant components, and display
  47.                   animation. */
  48.               static String imageDir = "images/";
  49.  
  50.               /** The reactor object */
  51.               Reactor reactor;
  52.  
  53.               /** Valve object */
  54.               Valve valve_1, valve_2, valve_3, valve_4;
  55.  
  56.               /** Pump object */
  57.               Pump pump_1, pump_2, pump_3;
  58.  
  59.               /** The turbine */
  60.               Turbine turbine;
  61.  
  62.               /** The condenser */
  63.               Condenser condenser;
  64.  
  65.               /** The generator */
  66.               Generator generator;
  67.  
  68.               /** The nuclear power plant simulator */
  69.               Simulator simulator;
  70.  
  71.               /** The window for the sequence control buttons */
  72.               Panel controlPanel;
  73.  
  74.               /** Flag that is true iff a simulation is running */
  75.               boolean isRunningSimulation = false;
  76.  
  77.               /** The status message that is display in the applet area */
  78.               String message = "";
  79.  
  80.               /** Initialize the applet. Sets the applet size, creates
  81.                   the plant components, and creates the simulator. */
  82.               public void init() {
  83.                   //resize(680, 473);       // java.applet.Applet size
  84.                   im = createImage(680,473);
  85.                   offscreen = im.getGraphics();
  86.                   offscreen.setColor(Color.black);
  87.  
  88.                   background = getImage(getCodeBase(), imageDir + "BACKGROUND.GIF");
  89.  
  90.                   Component.plant = this;
  91.                   reactor = new Reactor();
  92.                   valve_1 = new Valve("SV1", 360, 59);
  93.                   valve_2 = new Valve("SV2", 360, 178);
  94.                   valve_3 = new Valve("WV1", 385, 382);
  95.                   valve_4 = new Valve("WV2", 385, 420);
  96.                   pump_1 = new Pump("Pump 1", 406, 389, 1400);
  97.                   pump_2 = new Pump("Pump 2", 406, 427, 1400);
  98.                   pump_3 = new Pump("Pump 3", 619, 421, 1285);
  99.                   turbine = new Turbine();
  100.                   condenser = new Condenser();
  101.                   generator = new Generator();
  102.  
  103.           setLayout(new BorderLayout());
  104.  
  105.           controlPanel = new Panel();
  106.           controlPanel.setLayout(new FlowLayout());
  107.                   controlPanel.add(new Seq_1_Button(this, "Sequence 1"));
  108.                   controlPanel.add(new Seq_2_Button(this, "Sequence 2"));
  109.                   controlPanel.add(new Seq_3_Button(this, "Sequence 3"));
  110.                   controlPanel.add(new Rand_Button(this, "Randomize"));
  111.           add("North", controlPanel);
  112.           simulator = new LocalSimulator(this);
  113.               }
  114.  
  115.  
  116.               /** Update the plant display
  117.                 * @param g Graphics context to paint in */
  118.               public void paint(Graphics g) {
  119.           if (reactor == null) {
  120.               return;
  121.           }
  122.                   if (!reactor.overheated) {
  123.             Dimension d = size();
  124.             offscreen.setColor(getBackground());
  125.             offscreen.fillRect(0, 0, d.width, d.height);
  126.  
  127.                     offscreen.drawImage(background,0,50, this);
  128.                     reactor.paint(offscreen);
  129.                     valve_1.paint(offscreen);
  130.                     valve_2.paint(offscreen);
  131.                     valve_3.paint(offscreen);
  132.                     valve_4.paint(offscreen);
  133.                     pump_1.paint(offscreen);
  134.                     pump_2.paint(offscreen);
  135.                     pump_3.paint(offscreen);
  136.                     turbine.paint(offscreen);
  137.                     condenser.paint(offscreen);
  138.                     generator.paint(offscreen);
  139.                     offscreen.drawString(message, 150, 440);
  140.                   } else reactor.paintMeltdown(offscreen);
  141.                   //controlPanel.move(g.originX+20, g.originY+330);
  142.                   g.drawImage(im,0,0, this);
  143.               }
  144.  
  145.               /** Update without erasing background
  146.                 * @param g Graphics context to update in */
  147.               public void update(Graphics g) {
  148.                 paint(g);
  149.               }
  150.  
  151.               /** Handle mouseDown events. This method distributes the
  152.                   message by calling the mouseDown methods for the
  153.                   appropriate plant components
  154.                 * @param x The X coordinate
  155.                 * @param y The Y coordinate */
  156.               public boolean mouseDown(Event evt, int x, int y) {
  157. getAppletContext().showStatus("mouseDown " + x + " " + y);
  158.                 pump_1.mouseDown(evt, x, y);
  159.                 pump_2.mouseDown(evt, x, y);
  160.                 pump_3.mouseDown(evt, x, y);
  161.                 valve_1.mouseDown(evt, x, y);
  162.                 valve_2.mouseDown(evt, x, y);
  163.                 valve_3.mouseDown(evt, x, y);
  164.                 valve_4.mouseDown(evt, x, y);
  165.                 reactor.mouseDown(evt, x, y);
  166.         return true;
  167.               }
  168.  
  169.  
  170.               /** Handle mouseDrag events. This method distributes the
  171.                   message by calling the mouseDrag methods for the
  172.                   appropriate plant components
  173.                 * @param x The X coordinate
  174.                 * @param y The Y coordinate */
  175.               public boolean mouseDrag(Event evt, int x, int y) {
  176.                 return reactor.mouseDrag(evt, x, y);
  177.               }
  178.  
  179.               /** Handle mouseUp events. This method distributes the
  180.                   message by calling the mouseUp methods for the
  181.                   appropriate plant components
  182.                 * @param x The X coordinate
  183.                 * @param y The Y coordinate */
  184.               public boolean mouseUp(Event evt, int x, int y) {
  185.                 return reactor.mouseUp(evt, x, y);
  186.               }
  187.  
  188.               /** Rotate the pumps one step. (Only pumps with rpm > 0
  189.                   are rotated.) */
  190.               protected void rotatePumps() {
  191.                 pump_1.rotate();
  192.                 pump_2.rotate();
  193.                 pump_3.rotate();
  194.               }
  195.  
  196.               /** Move the waves on the water surfaces in the tanks */
  197.               protected void waterWave() {
  198.                 reactor.waterWave();
  199.                 condenser.waterWave();
  200.               }
  201.  
  202.               /** Start the simulation */
  203.               public void startReactor() {
  204.                   getAppletContext().showStatus("The simulation is running...");
  205.                   simulator.start();
  206.               }
  207.  
  208.               /** Run the simulation n steps. Uses the crurrent
  209.                 * simulator to calculate the next states
  210.                 * @param n The number of steps */
  211.               public void timeStep(int n) {
  212.                   simulator.timeStep(n);
  213.               }
  214.  
  215.               /** Blow up a device.
  216.                 * @param device The device to blow (e.g., a turbine object) */
  217.               public void blow(Component device) {
  218.                   simulator.blow(device);
  219.               }
  220.  
  221.               /** Stop the simulation */
  222.               public void stopReactor() {
  223.                   getAppletContext().showStatus("The simulation has stopped");
  224.                   simulator.stop();
  225.               }
  226.  
  227.               /** Play a crash sound. This method is called when plant
  228.                   components blow up.
  229.                 * @param n Duration */
  230.               public void crashSound(int n) {
  231.                 play(getCodeBase(), "audio/crash.au");
  232.               }
  233.  
  234.  
  235.               /** Run the animation thread. This method is called when
  236.                   the animation thread is started. */
  237.               public void run() {
  238.                 Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
  239.                 while (kicker != null) {
  240.                   rotatePumps();
  241.                   waterWave();
  242.                   repaint();
  243. try {Thread.sleep(kickerDelay);} catch (InterruptedException e){}
  244.                 }
  245.               }
  246.  
  247.               /** Start the applet. Creates the animation thread and
  248.                   opens the window for the sequence control buttons */
  249.               public void start() {
  250.                 if (kicker == null) {
  251.                   kicker = new Thread(this);
  252.                   kickerDelay = 60;
  253.                   kicker.start();
  254.                 }
  255.               }
  256.  
  257.               /** Stop the applet. Stops the animation thread and
  258.                   closes the window for the sequence control buttons */
  259.               public void stop() {
  260.                 if (kicker != null) {
  261.                   kicker.stop();
  262.                   kicker = null;
  263.                 }
  264.               }
  265.           }
  266.  
  267.  
  268. /**
  269.  * The class SeqButton is an abstract class for buttons that control
  270.  * simulation sequences.
  271.  *
  272.  * @version 1.0f
  273.  * @author Henrik Eriksson
  274.  */
  275.           abstract class SeqButton extends Button implements Runnable {
  276.               /** Backpointer to the NuclearPlant applet */
  277.               protected NuclearPlant plant;
  278.  
  279.               /** Construct a button and initialize it.
  280.                 * @param p The plant
  281.                 * @param name The button label
  282.                 * @param x The X coordinate
  283.                 * @param y The Y coordinate */
  284.               public SeqButton(NuclearPlant p, String name) {
  285.                 super(name);
  286.                 plant = p;
  287.               }
  288.  
  289.               /** Perform a sequence when the button is selected. This
  290.                   method is called automatically when the button is
  291.                   selected by the user. The method runs the sequence
  292.                   in a separate thread.
  293.                 * @param c the awt.Component selected
  294.                 * @param pos undefined */
  295.               public boolean action(Event evt, Object arg) {
  296.                 new Thread(this).start();
  297.         return true;
  298.               }
  299.           }
  300.  
  301.  
  302. /**
  303.  * Class for the Sequence 1 button.
  304.  *
  305.  * @version 1.0f
  306.  * @author Henrik Eriksson
  307.  */
  308.           class Seq_1_Button extends SeqButton {
  309.               /** Construct a button and initialize it.
  310.                 * @param p The plant
  311.                 * @param name The button label
  312.                 * @param x The X coordinate
  313.                 * @param y The Y coordinate */
  314.               public Seq_1_Button(NuclearPlant p, String name) {
  315.                 super(p, name);
  316.               }
  317.  
  318.               /** Run the sequence. This method is called in a
  319.                   separate thread when the button is selected by the
  320.                   user. Modify this method to change the sequence in
  321.                   question. */
  322.               public void run() {
  323.         plant.controlPanel.hide();
  324.         plant.isRunningSimulation = true;
  325.                 plant.startReactor();
  326.                 plant.message = "Sequence 1 running...";
  327.                 plant.timeStep(25);
  328.                 plant.blow(plant.turbine);
  329.                 plant.timeStep(200);
  330.                 plant.stopReactor();
  331.                 plant.message = "";
  332.         plant.isRunningSimulation = false;
  333.         plant.controlPanel.show();
  334.               }
  335.  
  336.           }
  337.  
  338.  
  339. /**
  340.  * Class for the Sequence 2 button.
  341.  *
  342.  * @version 1.0f
  343.  * @author Henrik Eriksson
  344.  */
  345.           class Seq_2_Button extends SeqButton {
  346.               /** Construct a button and initialize it.
  347.                 * @param p The plant
  348.                 * @param name The button label
  349.                 * @param x The X coordinate
  350.                 * @param y The Y coordinate */
  351.               public Seq_2_Button(NuclearPlant p, String name) {
  352.                 super(p, name);
  353.               }
  354.  
  355.               /** Run the sequence. This method is called in a
  356.                   separate thread when the button is selected by the
  357.                   user. Modify this method to change the sequence in
  358.                   question. */
  359.               public void run() {
  360.         plant.controlPanel.hide();
  361.                 plant.startReactor();
  362.         plant.isRunningSimulation = true;
  363.                 plant.message = "Sequence 2 running...";
  364.                 plant.timeStep(25);
  365.                 plant.blow(plant.pump_1);
  366.                 plant.timeStep(140);
  367.                 plant.stopReactor();
  368.                 plant.message = "";
  369.         plant.isRunningSimulation = false;
  370.         plant.controlPanel.show();
  371.               }
  372.           }
  373.  
  374.  
  375. /**
  376.  * Class for the Sequence 3 button.
  377.  *
  378.  * @version 1.0f
  379.  * @author Henrik Eriksson
  380.  */
  381.           class Seq_3_Button extends SeqButton {
  382.               /** Construct a button and initialize it.
  383.                 * @param p The plant
  384.                 * @param name The button label
  385.                 * @param x The X coordinate
  386.                 * @param y The Y coordinate */
  387.               public Seq_3_Button(NuclearPlant p, String name) {
  388.                 super(p, name);
  389.               }
  390.  
  391.               /** Run the sequence. This method is called in a
  392.                   separate thread when the button is selected by the
  393.                   user. Modify this method to change the sequence in
  394.                   question. */
  395.               public void run() {
  396.         plant.controlPanel.hide();
  397.                 plant.startReactor();
  398.         plant.isRunningSimulation = true;
  399.                 plant.message = "Sequence 3 running...";
  400.                 plant.timeStep(25);
  401.                 plant.blow(plant.pump_3);
  402.                 plant.timeStep(140);
  403.                 plant.stopReactor();
  404.                 plant.message = "";
  405.         plant.isRunningSimulation = false;
  406.         plant.controlPanel.show();
  407.               }
  408.           }
  409.  
  410.  
  411. /**
  412.  * Class for the random sequence button.
  413.  *
  414.  * @version 1.0f
  415.  * @author Henrik Eriksson
  416.  */
  417.           class Rand_Button extends SeqButton {
  418.               /** Construct a button and initialize it.
  419.                 * @param p The plant
  420.                 * @param name The button label
  421.                 * @param x The X coordinate
  422.                 * @param y The Y coordinate */
  423.               public Rand_Button(NuclearPlant p, String name) {
  424.                 super(p, name);
  425.               }
  426.  
  427.               /** Run the sequence. This method is called in a
  428.                   separate thread when the button is selected by the
  429.                   user. Modify this method to change the sequence in
  430.                   question. */
  431.               public void run() {
  432.         plant.controlPanel.hide();
  433.                 plant.startReactor();
  434.         plant.isRunningSimulation = true;
  435.                 plant.message = "Random sequence running...";
  436.                 plant.timeStep(25);
  437.                 switch ((int)(Math.random()*5)) {
  438.                   case 0: plant.blow(plant.turbine); break;
  439.                   case 1: plant.blow(plant.pump_1); break;
  440.                   case 2: plant.blow(plant.pump_3); break;
  441.                   case 3: plant.blow(plant.condenser); break;
  442.                   case 4: plant.blow(plant.reactor); break;
  443.                 }
  444.                 plant.timeStep(25);
  445.                 switch ((int)(Math.random()*5)) {
  446.                   case 0: plant.blow(plant.turbine); break;
  447.                   case 1: plant.blow(plant.pump_1); break;
  448.                   case 2: plant.blow(plant.pump_3); break;
  449.                   case 3: plant.blow(plant.condenser); break;
  450.                   case 4: plant.blow(plant.reactor); break;
  451.                 }
  452.                 plant.timeStep(140);
  453.                 plant.stopReactor();
  454.                 plant.message = "";
  455.         plant.isRunningSimulation = false;
  456.         plant.controlPanel.show();
  457.               }
  458.           }
  459.  
  460.  
  461. /**
  462.  * Class for components of the nuclear power plant
  463.  *
  464.  * @version 1.0f
  465.  * @author Henrik Eriksson
  466.  */
  467.           class Component {
  468.               /** Backpointer to the plant */
  469.               protected static NuclearPlant plant;
  470.  
  471.               /** Component location */
  472.               protected int x, y;
  473.  
  474.               /** Component label (if any) */
  475.               protected String label;
  476.  
  477.               /** True iff component broken */
  478.               boolean blown = false;
  479.  
  480.               /** Returns an image given its name
  481.                 * @param name The image name 
  482.                 * @return The image */
  483.               private Image getImage(URL url, String name) {
  484.                 return plant.getImage(url, plant.imageDir + name);
  485.               }
  486.  
  487.               /** Returns an image given its name
  488.                 * @param name The image name
  489.                 * @param cache A cached image
  490.                 * @return The image */
  491.               protected Image getImage(URL url, String name, Image cache) {
  492.                 return (cache == null) ? getImage(url, name) : cache;
  493.               }
  494.  
  495.               /** No-op at this level */
  496.               void blow() {}
  497.  
  498.               /** Set the value of a slot (no-op at this level)
  499.                 * @param slot The slot name
  500.                 * @param val The value */
  501.               void setIntValue(String slot, int val) { }
  502.  
  503.               /** Set the value of a slot (no-op at this level)
  504.                 * @param slot The slot name
  505.                 * @param val The value */
  506.               void setValue(String slot, float val) { }
  507.  
  508.               /** Set the value of a slot (no-op at this level)
  509.                 * @param slot The slot name
  510.                 * @param val The value */
  511.               void setValue(String slot, String val) { }
  512.  
  513.               /** Set the value of a slot
  514.                 * @param slot The slot name
  515.                 * @param val The value */
  516.               void setValue(String slot, boolean val) {
  517.                 if (slot.equals("blown")) blown = val;
  518.               }
  519.  
  520.               /** Random number generator (pseudo)
  521.                 * @param min The lower bound
  522.                 * @param max The upper bound
  523.                 * @return A random number (between min and max) */
  524.               protected int rand(int min, int max) {
  525.                 return (int)(Math.random()*(max-min) + min);
  526.               }
  527.  
  528.           }
  529.  
  530. /**
  531.  * A generic tank component for the nuclear power plant
  532.  *
  533.  * @version 1.0f
  534.  * @author Henrik Eriksson
  535.  */
  536.           class Tank extends Component {
  537.  
  538.               /** The tank pressure (in bar) */
  539.               float pressure;
  540.  
  541.               /** The tank waterlevel (in mm) */
  542.               float waterLevel;
  543.  
  544.               /** The number of the water image shown */
  545.               protected int imageState = 0;
  546.  
  547.               /** Water (surface) images for animation */
  548.               protected static Image vatten_bm[];
  549.  
  550.               /** Blow up the tank */
  551.               void blow() {
  552.                 plant.crashSound(15000);
  553.                 plant.getAppletContext().showStatus("The " + label + " blow up");
  554.                 blown = true;
  555.               }
  556.  
  557.               /** Set the value of a slot
  558.                 * @param slot The slot name
  559.                 * @param val The value */
  560.               void setValue(String slot, float val) {
  561.                 if (slot.equals("pressure")) pressure = val;
  562.                 else if (slot.equals("waterLevel")) waterLevel = val;
  563.                 else super.setValue(slot, val);
  564.               }
  565.  
  566.               /** Array of bubble depths */
  567.               private int bubble_depth[] = new int[100];
  568.  
  569.               /** Array of bubble X positions */
  570.               private int bubble_x[] = new int[100];
  571.  
  572.               /** Paint animated bubbles in a region
  573.                 * @param g The graphics context
  574.                 * @param x The X position for the bubble region
  575.                 * @param y The Y position for the bubble region
  576.                 * @param size().width The size().width of the bubble region
  577.                 * @param size().height The size().height of the bubble region
  578.                 * @param noOfBubbles The bubble frequency */
  579.               protected void paintBubbles(Graphics g, int x, int y, int width,
  580.                                           int depth, int noOfBubbles) {
  581.                   Color oldForeground = g.getColor();
  582.                   g.setColor(Color.white);
  583.                   if (noOfBubbles > bubble_depth.length)
  584.                     noOfBubbles = bubble_depth.length;
  585.                   for (int i=0; i < noOfBubbles; i++) {
  586.                     if (bubble_depth[i] == 0) {     // Create a new bubble
  587.                       bubble_depth[i] = rand(1, depth);
  588.                       bubble_x[i] = rand(x, width);
  589.                     }
  590.                     g.fillRect(bubble_x[i], y+bubble_depth[i]--, 1, 1);
  591. Thread.yield();
  592.                   }
  593.                   g.setColor(oldForeground);
  594.               }
  595.           }
  596.  
  597.  
  598. /**
  599.  * A reactor tank component for the nuclear power plant
  600.  *
  601.  * @version 1.0f
  602.  * @author Henrik Eriksson
  603.  */
  604.           class Reactor extends Tank {
  605.  
  606.               /** The moderator rod level (in percent) */
  607.               int moderatorPercent = 50;
  608.  
  609.               /** True iff the reactor is overheated */
  610.               boolean overheated;
  611.  
  612.               /** The state of a meltdown */
  613.               private int meltStage;
  614.  
  615.               /** Water (surface) images for animation */
  616.               protected static Image vatten_bm[] = new Image[3];
  617.  
  618.               /** Image for a blown reactor tank */
  619.               protected static Image crashed_reactor_bm;
  620.  
  621.               /** Radiation sign (image) */
  622.               protected static Image radiak_bm;
  623.  
  624.               Reactor() {
  625.                   vatten_bm[0] = getImage(plant.getCodeBase(), "R_VATTEN_A_BM.GIF", vatten_bm[0]);
  626.                   vatten_bm[1] = getImage(plant.getCodeBase(), "R_VATTEN_B_BM.GIF", vatten_bm[1]);
  627.                   vatten_bm[2] = getImage(plant.getCodeBase(), "R_VATTEN_C_BM.GIF", vatten_bm[2]);
  628.                   radiak_bm = getImage(plant.getCodeBase(), "RADIAK_BM.GIF", radiak_bm);
  629.                   label = "reactor";
  630.                   waterLevel = 1800;
  631.               }
  632.  
  633.               /** Set the value of a slot
  634.                 * @param slot The slot name
  635.                 * @param val The value */
  636.               void setIntValue(String slot, int val) {
  637.                 if (slot.equals("moderatorPercent")) moderatorPercent = val;
  638.                 else super.setIntValue(slot, val);
  639.               }
  640.  
  641.               /** Set the value of a slot
  642.                 * @param slot The slot name
  643.                 * @param val The value */
  644.               void setValue(String slot, boolean val) {
  645.                 if (slot.equals("overheated")) {
  646.                   overheated = val;
  647.                   if (val) meltdown();
  648.                 } else super.setValue(slot, val);
  649.               }
  650.  
  651.               /** Advance the water-surface animation one step */
  652.               void waterWave () {
  653.                 if (++imageState >= vatten_bm.length) imageState = 0;
  654.               }
  655.  
  656.               /** Perform the meltdown animation. Called when the reactor
  657.                   core is overheated */
  658.               public void meltdown() {
  659.                 overheated = true;
  660.                 plant.kickerDelay = 40;
  661.                 meltStage = 5;
  662.                 plant.getAppletContext().showStatus("The " + label + " is overheated");
  663.               }
  664.  
  665.               /** Paint operation for the meltdown animation
  666.                 * @param g The graphics context */
  667.               public void paintMeltdown(Graphics g) {
  668.  
  669.                 //im = new Image(item.parent);
  670.                 //offscreen = new Graphics(im);
  671.  
  672. //                int x0 = 10, y0 = 150;
  673.                 int x0 = -60, y0 = 110;
  674.                 if (meltStage == 5) g.drawImage(radiak_bm, 170, 150, plant);
  675.                 if (meltStage < 1500) {
  676.                   int d = meltStage;
  677.                   int x = Math.max(x0 - (d - 100), 0) +
  678.                           rand(0, Math.min(d, plant.size().width));
  679.                   int y = Math.max(y0 - (d - 100), 0) +
  680.                           rand(0, Math.min(d, plant.size().height));
  681.                   // BITBLT
  682.                   g.copyArea(x, y,
  683.                            rand(10, 100),
  684.                            rand(10, 100),
  685.                            ((d < 250) ? rand(-3, 3) : rand(-2, 2)),
  686.                            ((d < 250) ? rand(-3, 3) : rand(-2, 2)));
  687.                   meltStage++;
  688.                 }
  689.               }
  690.  
  691.  
  692.               /** The color of overheated fuel rods */
  693.               private static Color overheatedColor = new Color(200,0,0);
  694.  
  695.               /** The color of water */
  696.               private static Color waterColor = new Color(127,193,255);
  697.  
  698.  
  699.               /** Paint operation for the reactor tank
  700.                 * @param g The graphics context */
  701.               public void paint(Graphics g) {
  702.                   if (pressure > 500) g.setColor(Color.red);
  703.                   g.drawString((int)pressure+" bar", 55, 70);
  704.                   int surfaceY = 175-(int)waterLevel/50;
  705.                   g.setColor(waterColor);
  706.                   g.fillRect(3, surfaceY+1, 135, 279-surfaceY);
  707.                   g.setColor(Color.black);
  708.                   g.drawImage(vatten_bm[imageState], 3, surfaceY, plant);
  709.                   g.drawString("Level:", 160, 110);
  710.                   if (waterLevel < 0) g.setColor(Color.red);
  711.                   g.drawString((int)waterLevel+" mm", 160, 125);
  712.                   g.setColor(Color.gray);
  713.                   for (int i = 0; i < 7; i++)
  714.                       g.fillRect(33 + i*12, 102+moderatorPercent*3/4, 3, 80);
  715.                   if (moderatorOutlinePos > 0) {
  716.                     g.setColor(Color.yellow);
  717.                     for (int i = 0; i < 7; i++)
  718.                       g.drawRect(33 + i*12, moderatorOutlinePos, 2, 80);
  719.                   }
  720.                   if (waterLevel < 0) {
  721.                     Color hotColor =
  722.                             new Color(Math.min(-(int)waterLevel/10,150),0,0);
  723.                     g.setColor(hotColor);
  724.                   } else g.setColor(Color.black);
  725.                   for (int i = 0; i < 8; i++)
  726.                       g.fillRect(25 + i*12, 177, 7, 80);
  727.                   if (waterLevel < 0) {
  728.                     g.setColor(overheatedColor);
  729.                     for (int i = 0; i < 8; i++)
  730.                         g.fillRect(25 + i*12, 177, 7,
  731.                              Math.max(-(int)waterLevel/50-1, 0));
  732.                   }
  733.                   g.setColor(Color.black);
  734.                   paintBubbles(g, 3, surfaceY, 137, 40, 50);
  735.                   if (blown) {
  736.                     crashed_reactor_bm =
  737.                         getImage(plant.getCodeBase(), "CRASHED_REACTOR_BM.GIF",crashed_reactor_bm);
  738.                     g.drawImage(crashed_reactor_bm, 30, 3, plant);
  739.                     g.drawImage(radiak_bm, 170, 150, plant);
  740.                   }
  741.               }
  742.  
  743.               /** Initial Y position for dragged moderator rods */
  744.               private int y0 = 0;
  745.  
  746.               /** The distance of the drag */
  747.               protected int dragDelta = 0;
  748.  
  749.               /** The position of the outline of the dragged moderator rods */
  750.               protected int moderatorOutlinePos = 0;
  751.  
  752.               /** Checks if a certain position is inside the area of
  753.                   the moderator rods
  754.                 * @param x The X coordinate
  755.                 * @param y The Y coordinate
  756.                 * @return True iff the position is inside the moderator-rod
  757.                           area, otherwise false */
  758.               private boolean isInsideModerator(int x, int y) {
  759.                 return x > 25 && x < 120 && y > 102+moderatorPercent*3/4 &&
  760.                        y < 102+moderatorPercent*3/4 + 80;
  761.               }
  762.  
  763.               /** Handle mouseDown events (i.e., clicks on moderator rods).
  764.                 * @param x The X coordinate
  765.                 * @param y The Y coordinate */
  766.               public boolean mouseDown(Event evt, int x, int y) {
  767.                 if (isInsideModerator(x, y)) {
  768.                   y0 = y;
  769.                 }
  770.         return true;
  771.               }
  772.  
  773.               /** Handle mouseDrag events. This method allows the user to
  774.                   drag moderator rods
  775.                 * @param x The X coordinate
  776.                 * @param y The Y coordinate */
  777.               public boolean mouseDrag(Event evt, int x, int y) {
  778.                 if (y0 > 0) {
  779.                   moderatorOutlinePos = 102+moderatorPercent*3/4 - (y0 - y);
  780.                   if (moderatorOutlinePos < 97) moderatorOutlinePos = 97;
  781.                   if (moderatorOutlinePos > 177) moderatorOutlinePos = 177;
  782.                 }
  783.         return true;
  784.               }
  785.  
  786.               /** Handle mouseUp events. This method sets the moderatorPercent
  787.                 * @param x The X coordinate
  788.                 * @param y The Y coordinate */
  789.               public boolean mouseUp(Event evt, int x, int y) {
  790.                 if (y0 > 0) {
  791.                   moderatorPercent = (moderatorOutlinePos - 97) * 5/4;
  792.                 }
  793.                 moderatorOutlinePos = 0;
  794.                 y0 = 0;
  795.         return true;
  796.               }
  797.  
  798.  
  799.           }
  800.  
  801.  
  802. /**
  803.  * A valve component for the nuclear power plant
  804.  *
  805.  * @version 1.0f
  806.  * @author Henrik Eriksson
  807.  */
  808.           class Valve extends Component {
  809.  
  810.               /** True iff the valve is open */
  811.               boolean status = false;
  812.  
  813.               /** Valve image */
  814.               protected static Image ventil_o_bm, ventil_s_bm;
  815.  
  816.               /** Construct a valve and initialize it.
  817.                 * @param l The valve label
  818.                 * @param xPos The X coordinate
  819.                 * @param yPos The Y coordinate */
  820.               Valve(String l, int xPos, int yPos) {
  821.                   x = xPos;
  822.                   y = yPos;
  823.                   label = l;
  824.                   ventil_o_bm = getImage(plant.getCodeBase(), "VENTIL.O_BM.GIF", ventil_o_bm);
  825.                   ventil_s_bm = getImage(plant.getCodeBase(), "VENTIL.S_BM.GIF", ventil_s_bm);
  826.               }
  827.  
  828.               /** Set the value of a slot
  829.                 * @param slot The slot name
  830.                 * @param val The value */
  831.               void setValue(String slot, boolean val) {
  832.                 if (slot.equals("status")) status = val;
  833.                 else super.setValue(slot, val);
  834.               }
  835.  
  836.               /** Paint operation for valve
  837.                 * @param g The graphics context */
  838.               public void paint(Graphics g) {
  839.                   if (status)
  840.                      g.drawImage(ventil_o_bm, x, y, plant);
  841.                   else
  842.                      g.drawImage(ventil_s_bm, x, y+6, plant);
  843.                   g.drawString(label, x, y+40);
  844.               }
  845.  
  846.               /** Handle mouseDown events (i.e., clicks on the valve).
  847.                 * @param mx The X coordinate
  848.                 * @param my The Y coordinate */
  849.               public boolean mouseDown(Event evt, int mx, int my) {
  850.                 if (mx > x && mx < x+20 && my > y && my < y+40)
  851.                   status = !status;
  852.         return true;
  853.               }
  854.  
  855.           }
  856.  
  857.  
  858. /**
  859.  * A pump component for the nuclear power plant
  860.  *
  861.  * @version 1.0f
  862.  * @author Henrik Eriksson
  863.  */
  864.           class Pump extends Component {
  865.  
  866.               /** The state of the pump (0=crashed) */
  867.               int status = 1;
  868.  
  869.               /** The pump rpm */
  870.               int rpm;
  871.  
  872.               /** Maximum pump rpm */
  873.               int full_rpm;
  874.  
  875.               /** Pump images for amimation */
  876.               protected static Image pump_bm[] = new Image[6];
  877.  
  878.               /** Crashed pump image */
  879.               protected static Image pump_crash_bm;
  880.  
  881.  
  882.               /** Construct a pump and initialize it.
  883.                 * @param l The pump label
  884.                 * @param xPos The X coordinate
  885.                 * @param yPos The Y coordinate
  886.                 * @param maxRpm The maximum pump rpm */
  887.               Pump(String l, int xPos, int yPos, int maxRpm) {
  888.                   x = xPos;
  889.                   y = yPos;
  890.                   label = l;
  891.                   full_rpm = maxRpm;
  892.                   pump_bm[0] = getImage(plant.getCodeBase(), "PUMP.A_BM.GIF", pump_bm[0]);
  893.                   pump_bm[1] = getImage(plant.getCodeBase(), "PUMP.B_BM.GIF", pump_bm[1]);
  894.                   pump_bm[2] = getImage(plant.getCodeBase(), "PUMP.C_BM.GIF", pump_bm[2]);
  895.                   pump_bm[3] = getImage(plant.getCodeBase(), "PUMP.D_BM.GIF", pump_bm[3]);
  896.                   pump_bm[4] = getImage(plant.getCodeBase(), "PUMP.E_BM.GIF", pump_bm[4]);
  897.                   pump_bm[5] = getImage(plant.getCodeBase(), "PUMP.F_BM.GIF", pump_bm[5]);
  898.                   pump_crash_bm = getImage(plant.getCodeBase(), "PUMP.CRASH_BM.GIF", pump_crash_bm);
  899.               }
  900.  
  901.  
  902.               /** Set the value of a slot
  903.                 * @param slot The slot name
  904.                 * @param val The value */
  905.               void setIntValue(String slot, int val) {
  906.                 if (slot.equals("status")) status = val;
  907.                 else if (slot.equals("rpm")) rpm = val;
  908.                 else super.setIntValue(slot, val);
  909.               }
  910.  
  911.               /** Blow up the pump */
  912.               void blow() {
  913.                 plant.crashSound(800);
  914.                 plant.getAppletContext().showStatus(label + " crashed");
  915.                 status = 0;
  916.                 rpm = 0;
  917.               }
  918.  
  919.               /** Rotate the pump one step. (Only pumps with rpm > 0
  920.                   are rotated.) */
  921.               public void rotate() {
  922.                 if (rpm > 0 && status != 0) status++;
  923.                 if (status > 6) status = 1;
  924.               }
  925.  
  926.               /** Paint operation for pump
  927.                 * @param g The graphics context */
  928.               public void paint(Graphics g) {
  929.                   if (status == 0) g.drawImage(pump_crash_bm, x, y, plant);
  930.                   else g.drawImage(pump_bm[status-1], x, y, plant);
  931.                   g.drawString(rpm+" rpm", x+4, y-2);
  932.               }
  933.  
  934.               /** Handle mouseDown events (i.e., clicks on the pump).
  935.                 * @param mx The X coordinate
  936.                 * @param my The Y coordinate */
  937.               public boolean mouseDown(Event evt, int mx, int my) {
  938.                 if (mx > x && mx < x+30 && my > y && my < y+30)
  939.                   if (status != 0)
  940.                     if (rpm == 0) rpm = full_rpm; else rpm = 0;
  941.         return true;
  942.               }
  943.  
  944.           }
  945.  
  946.  
  947.  
  948. /**
  949.  * Turbine component for the nuclear power plant
  950.  *
  951.  * @version 1.0f
  952.  * @author Henrik Eriksson
  953.  */
  954.           class Turbine extends Component {
  955.  
  956.               /** Image of crash turbine */
  957.               protected static Image crashed_turbine_bm;
  958.  
  959.               /** Blow up the turbine */
  960.               void blow() {
  961.                   blown = true;
  962.               }
  963.  
  964.               /** Count down for blow up animation */
  965.               private byte blow_countdown = -1;
  966.  
  967.               /** Paint operation for turbine
  968.                 * @param g The graphics context */
  969.               public void paint(Graphics g) {
  970.                   if (blown && blow_countdown < 0) {
  971.                     blow_countdown = 20;
  972.                   } else if (blown && blow_countdown < 10) {
  973.                     crashed_turbine_bm =
  974.                         getImage(plant.getCodeBase(), "CRASHED_TURBIN_BM.GIF",crashed_turbine_bm);
  975.                     g.drawImage(crashed_turbine_bm, 403, 73, plant);
  976.                     if (blow_countdown == 8) {
  977.                       plant.getAppletContext().showStatus("The turbine crashed");
  978.                       plant.crashSound(8000);
  979.                     }
  980.                   } 
  981.                   if (blown && blow_countdown > 0) {
  982.                     blow_countdown--;
  983.                     g.copyArea(403, 95, 145, 65,
  984.                                403+rand(-2,2), 95+rand(-4,2));
  985.                   } else if (!blown) blow_countdown = -1;
  986.               }
  987.           }
  988.  
  989.  
  990. /**
  991.  * Condenser component for the nuclear power plant
  992.  *
  993.  * @version 1.0f
  994.  * @author Henrik Eriksson
  995.  */
  996.           class Condenser extends Tank {
  997.  
  998.               /** Water (surface) images for animation */
  999.               protected static Image vatten_bm[] = new Image[3];
  1000.  
  1001.               /** Image of cooling pipe */
  1002.               protected static Image kylror_bm;
  1003.  
  1004.               /** Image of crashed condenser */
  1005.               protected static Image crashed_kondensor_bm;
  1006.  
  1007.               /** Construct a condenser and initialize it. */
  1008.               Condenser() {
  1009.                   vatten_bm[0] = getImage(plant.getCodeBase(), "K_VATTEN_A_BM.GIF", vatten_bm[0]);
  1010.                   vatten_bm[1] = getImage(plant.getCodeBase(), "K_VATTEN_B_BM.GIF", vatten_bm[1]);
  1011.                   vatten_bm[2] = getImage(plant.getCodeBase(), "K_VATTEN_C_BM.GIF", vatten_bm[2]);
  1012.                   kylror_bm = getImage(plant.getCodeBase(), "KYLROR_BM.GIF", kylror_bm);
  1013.                   label = "condenser";
  1014.                   waterLevel = 6000;
  1015.               }
  1016.  
  1017.               /** Advance the water-surface animation one step */
  1018.               void waterWave () {
  1019.                 if (++imageState >= vatten_bm.length) imageState = 0;
  1020.               }
  1021.  
  1022.               /** The color of water */
  1023.               private static Color waterColor = new Color(127,193,255);
  1024.  
  1025.               /** Paint operation for condenser
  1026.                 * @param g The graphics context */
  1027.               public void paint(Graphics g) {
  1028.                   if (pressure > 200) g.setColor(Color.red);
  1029.                   g.drawString((int)pressure+" bar", 520, 250);
  1030.                   g.setColor(waterColor);
  1031.                   int surfaceY = 440 - (int)waterLevel / 50;
  1032.                   g.fillRect(483, surfaceY+1, 108, 449-surfaceY);
  1033.                   g.drawImage(kylror_bm, 500, 349, plant);
  1034.                   g.setColor(Color.black);
  1035.                   g.drawImage(vatten_bm[imageState], 483, surfaceY, plant);
  1036.                   paintBubbles(g, 483, surfaceY, 590, 15, 10);
  1037.                   g.drawString("Level:", 615, 290);
  1038.                   g.drawString((int)waterLevel+" mm", 615, 305);
  1039.                   if (blown) {
  1040.                     crashed_kondensor_bm =
  1041.                      getImage(plant.getCodeBase(), "CRASHED_KONDENSOR_BM.GIF",crashed_kondensor_bm);
  1042.                     g.drawImage(crashed_kondensor_bm, 570, 214, plant);
  1043.                   }
  1044.               }
  1045.           }
  1046.  
  1047.  
  1048. /**
  1049.  * Generator component for the nuclear power plant
  1050.  *
  1051.  * @version 1.0f
  1052.  * @author Henrik Eriksson
  1053.  */
  1054.           class Generator extends Component {
  1055.  
  1056.               /** Output generator power (in MW) */
  1057.               int power;
  1058.  
  1059.               /** Set the value of a slot
  1060.                 * @param slot The slot name
  1061.                 * @param val The value */
  1062.               void setIntValue(String slot, int val) {
  1063.                 if (slot.equals("power")) power = val;
  1064.                 else super.setIntValue(slot, val);
  1065.               }
  1066.  
  1067.               /** Paint operation for generator
  1068.                 * @param g The graphics context */
  1069.               public void paint(Graphics g) {
  1070.                   g.drawString(power+" MW", 570, 95);
  1071.               }
  1072.           }
  1073.  
  1074.  
  1075.  
  1076. /**
  1077.  * The class Simulator is an abstact class for power-plant
  1078.  * simulators. The actual simulators are sumclasses of this class.
  1079.  *
  1080.  * @see NuclearPlant
  1081.  * @version 1.0f
  1082.  * @author Henrik Eriksson
  1083.  */
  1084.           abstract class Simulator {
  1085.               /** The plant */
  1086.               protected NuclearPlant plant;
  1087.               abstract void start();
  1088.               abstract void timeStep(int n);
  1089.               abstract void blow(Component device);
  1090.               abstract void stop();
  1091.           }
  1092.  
  1093. /**
  1094.  * The class LocalSimulatorServer is a test class that simulates the
  1095.  * behavior of the simulator server. It is used for testing the
  1096.  * java client applet and its user interface.
  1097.  *
  1098.  * @see TestSimulatorServer
  1099.  * @see ClipsSimulatorServer
  1100.  * @version 1.0f
  1101.  * @author Henrik Eriksson
  1102.  */
  1103.          class LocalSimulator extends Simulator {
  1104.               /** The reactor and its components */
  1105.               protected Reactor reactor;    
  1106.  
  1107.               /** Valve object */
  1108.               protected Valve valve_1, valve_2, valve_3, valve_4;
  1109.  
  1110.               /** Pump object */
  1111.               protected Pump pump_1, pump_2, pump_3;
  1112.  
  1113.               /** The turbine */
  1114.               protected Turbine turbine;
  1115.  
  1116.               /** The condenser */
  1117.               protected Condenser condenser;
  1118.  
  1119.               /** The generator */
  1120.               protected Generator generator;
  1121.  
  1122.  
  1123.               /** Constructor for LocalSimulator. Wires objects based on the
  1124.                 * NuclearPlant components.
  1125.                 * @param p The current NuclearPlant object */
  1126.               public LocalSimulator(NuclearPlant p) {
  1127.                 plant = p;
  1128.                 reactor = p.reactor;
  1129.                 valve_1 = p.valve_1;
  1130.                 valve_2 = p.valve_2;
  1131.                 valve_3 = p.valve_3;
  1132.                 valve_4 = p.valve_4;
  1133.                 pump_1 = p.pump_1;
  1134.                 pump_2 = p.pump_2;
  1135.                 pump_3 = p.pump_3;
  1136.                 turbine = p.turbine;
  1137.                 condenser = p.condenser;
  1138.                 generator = p.generator;
  1139.               }
  1140.  
  1141.               /** Starts the local simulator. This method initializes
  1142.                 * the simulation variables (i.e., the plant is reset
  1143.                 * to steady state). */
  1144.               public void start() {
  1145.                 reactor.pressure = 288;
  1146.                 reactor.moderatorPercent = 50;
  1147.                 reactor.waterLevel = 1800;
  1148.                 reactor.blown = false;
  1149.                 reactor.overheated = false;
  1150.                 turbine.blown = false;
  1151.                 condenser.pressure = 40;
  1152.                 condenser.waterLevel = 6000;
  1153.                 condenser.blown = false;
  1154.                 generator.power = 622;
  1155.                 pump_1.status = 1;
  1156.                 pump_1.rpm = 1400;
  1157.                 pump_2.status = 1;
  1158.                 pump_2.rpm = 0;
  1159.                 pump_3.status = 1;
  1160.                 pump_3.rpm = 1285;
  1161.                 pump_1.blown = false;
  1162.                 pump_2.blown = false;
  1163.                 pump_3.blown = false;
  1164.                 valve_1.status = true;
  1165.                 valve_2.status = false;
  1166.                 valve_3.status = true;
  1167.                 valve_4.status = false;
  1168.               }
  1169.  
  1170.  
  1171.               /** Calculates the next state of the simulation. This
  1172.                 * calculation is perfomed locally in java.
  1173.                 * @param n The number of steps to calculate before returning */
  1174.               public void timeStep(int n) {
  1175.                 float v1, v2, v3, v4;
  1176.  
  1177.                 for (int i = 0; i < n; i++) {
  1178.                   if (!reactor.overheated) {
  1179.                     // Compute the flow through valve_1...
  1180.                     if (valve_1.status)
  1181.                       v1 = (reactor.pressure-condenser.pressure) / 10;
  1182.                     else v1 = 0;
  1183.                     // Compute the flow through valve_2...
  1184.                     if (valve_2.status)
  1185.                       v2 = (reactor.pressure-condenser.pressure) / 2.5f;
  1186.                     else v2 = 0;
  1187.  
  1188.                     // Compute the flow through valve_3 and pump_1...
  1189.                     if (valve_3.status)
  1190.                       if (pump_1.rpm > 0)
  1191.                         if (condenser.waterLevel > 0)
  1192.                           v3 = pump_1.rpm * 0.07f;
  1193.                         else v3 = 0;
  1194.                       else v3 = -30;
  1195.                     else v3 = 0;
  1196.  
  1197.                     // Compute the flow through valve_4 and pump_2...
  1198.                     if (valve_4.status)
  1199.                       if (pump_2.rpm > 0)
  1200.                         if (condenser.waterLevel > 0)
  1201.                           v4 = pump_2.rpm * 0.07f;
  1202.                         else v4 = 0;
  1203.                       else v4 = -30;
  1204.                     else v4 = 0;
  1205.  
  1206.                     // Scale the flow levels to allow frequent time steps
  1207.                     // (smother animation)
  1208.                     float factor = 0.5f;
  1209.                     v1 *= factor;
  1210.                     v2 *= factor;
  1211.                     v3 *= factor;
  1212.                     v4 *= factor;
  1213.  
  1214.                     // Compute new values for pressure and water levels...
  1215.                     float boiledRW = (100 - reactor.moderatorPercent)*2*(900 - reactor.pressure)/620;
  1216.                     boiledRW *= factor;
  1217.  
  1218.                     float cooledKP = (float)(pump_3.rpm * Math.sqrt(condenser.pressure) * 0.003f);
  1219.                     cooledKP *= factor;
  1220.  
  1221.                     float newRP = reactor.pressure - v1 - v2 + boiledRW/4;
  1222.  
  1223.                     // The steam flow to the condenser stops if the
  1224.                     // turbine is blown...
  1225.                     if (turbine.blown) v1 = 0;
  1226.  
  1227.                     // Compute new values for pressure and water levels...
  1228.                     float newKP = condenser.pressure + v1 + v2 - cooledKP;
  1229.                     float newRW = reactor.waterLevel + v3 + v4 - boiledRW;
  1230.                     float newKW = condenser.waterLevel - v3 - v4 + 4*cooledKP;
  1231.  
  1232.                     // Make adjustments for blown tanks...
  1233.                     if (reactor.blown) newRP = 0.15f * newRP;
  1234.                     if (condenser.blown) newKP = 0.2f * newKP;
  1235.                     // Check the computed values for illegal values...
  1236.                     if (newKW < 0) newKW = 0;
  1237.                     if (newKW > 9900) newKW = 9900;
  1238.                     if (newRW > 6000) newRW = 6000;
  1239.                     if (newKP < 0) newKP = 0;
  1240.                     if (newKP > 300) newKP = 300;
  1241.                     if (newRP > 800) newRP = 800;
  1242.  
  1243.                     // Adjust the generator power...
  1244.                     float newEffect;
  1245.                     if (valve_1.status && !turbine.blown)
  1246.                       newEffect = (newRP - newKP) * 2.5f;
  1247.                     else newEffect = 0;
  1248.  
  1249.                     // Assign the computed values...
  1250.                     generator.power = (int)newEffect;
  1251.                     condenser.pressure = newKP;
  1252.                     condenser.waterLevel = newKW;
  1253.                     reactor.pressure = newRP;
  1254.                     reactor.waterLevel = newRW;
  1255.  
  1256.                     // Rules for the plant...
  1257.                     if (pump_1.blown) pump_1.rpm = 0;
  1258.                     if (pump_2.blown) pump_2.rpm = 0;
  1259.                     if (pump_3.blown) pump_3.rpm = 0;
  1260.                     if (reactor.waterLevel < -1500) reactor.meltdown();
  1261.                     if (reactor.pressure >= 610) reactor.blow();
  1262.                     if (condenser.pressure >= 225) condenser.blow();
  1263.  
  1264.                     // R1 (safety rule for blown turbine)...
  1265. /* Disabled for now
  1266.                     if (turbine.blown) {
  1267.                       valve_1.status = false;
  1268.                       valve_2.status = true;
  1269.                       reactor.moderatorPercent = 100;
  1270.                       pump_1.rpm = 0;
  1271.                       valve_3.status = false;
  1272.                     }
  1273. */
  1274.  
  1275.                   } // if
  1276.  
  1277. try {Thread.sleep(200); } catch (InterruptedException e){}
  1278.  
  1279.                 }  // for
  1280.  
  1281.               }
  1282.  
  1283.               /** Blow up a device. 
  1284.                 * @param device The device to blow (e.g., a turbine object) */
  1285.               public void blow(Component device) {
  1286.                 device.blow();
  1287.               }
  1288.  
  1289.               /** Stop the simulation */
  1290.               public void stop() {
  1291.               }
  1292.  
  1293.           }
  1294.