/////////////////////////////////////////////////////////////////////
 //
 // File: depend.java
 //
 // Purpose: (proj2) Depend (Dependencies) class.
 //
 // Authors: txe  Travis Emmitt 
 // 
 // Modifications:
 //   18-SEP-1998  txe  Initial creation
 //   19-SEP-1998  txe  Incorporated changes in specs, added comments.
 //   21-SEP-1998  txe  Added comments.
 //
 /////////////////////////////////////////////////////////////////////
 
 import java.applet.*;
 import java.awt.*;
 
 public class depend extends Applet {
 
     // Dependency-related data //
 
     private static final int MIN_SIZE = 1;
     private static final int MAX_SIZE = 2 << (4 - 1);  // 16
     private int size;
     private int init_mode;
     private int time;
     private boolean parameters[];
     private boolean dependencies[][];
     private boolean new_parameters[];
 
     // Widgets //
 
     private TextField    w_status;
     private Choice    w_size;
     private Choice        w_init_mode;
     private Button        w_go;
     private TextField w_time;
     private TextField w_parameters;
     private TextArea  w_dependencies;
     private TextArea  w_help;
     
     //////////////////////////////////////////////////////////////////////
     // This sets up the applet interface; it places all the widgets on the
     // screen and sets them to their initial values.  I use Panels in order
     // to better control the layout of the widgets.
     //////////////////////////////////////////////////////////////////////
     
     public void init () {
 
         // The Status field is used to print status and error messages.
 
         Panel p = new Panel ();
         p.add (new Label ("Status:"));
         p.add (w_status = new TextField ("Welcome, read Instructions at bottom.", 60));
         w_status.setEditable (false);
         add (p);
         
         // The Size    field lets the user specify the number of parameters.
         
         p = new Panel ();
         p.add (new Label ("Size:"));
         w_size = new Choice ();                                                    // good for small numbers
         for (int i = MIN_SIZE; i &lt;= MAX_SIZE; i++) {
             w_size.addItem ("" + i);
         }
         w_size.select (4);
         p.add (w_size);
         add (p);
 
         // The Initialization Mode fields determines how we setup the Dependencies
 
         p = new Panel ();
         p.add (new Label ("Initialization Mode:"));
         w_init_mode = new Choice ();
         w_init_mode.addItem ("False Everywhere");
         w_init_mode.addItem ("True Everywhere");                    
         w_init_mode.addItem ("True On Diagonal");                    
         w_init_mode.addItem ("True On or Above Diagonal");
         w_init_mode.addItem ("True in Block Diagonal");            
         w_init_mode.addItem ("Random");                            
         w_init_mode.select (5); // default to random
         p.add (w_init_mode);
         add (p);
 
         // The Go button and Time field deal with progression through the execution
 
         p = new Panel ();
         p.add (w_go = new Button ("Start"));
         p.add (new Label ("Time:"));
         p.add (w_time = new TextField ("" + time, 5));
         w_time.setEditable (false);
         add (p);
 
       // The Parameters field lets the user view and edit parameters
         
         p = new Panel ();
         p.add (new Label ("      Parameters:"));
         p.add (w_parameters = new TextField ("", 40));
         add (p);
 
       // The Dependencies field lets the user view and edit parameters
 
         p = new Panel ();
         p.add (new Label ("Dependencies:"));
         p.add (w_dependencies = new TextArea ("", 16, 40));
         add (p);
 
         // The Instructions field displays instructions on how to run the program
 
         p = new Panel ();
         p.add (new Label ("Instructions:"));
         p.add (w_help = new TextArea (
               "Manipulate Size or Initialize Mode to start a new execution.\n"
             + "Edit Parameters and Dependencies (0=false, 1=true, be careful\n"
             + &quot;to maintain the same format) and then hit the Start button.&quot;, 3, 50));
         w_help.setEditable (false);
         add (p);
 
         InitializeArrays ();
     }
 
 
     ///////////////////////////////////////////////////////////////////////////
     // This is called each time repaint() is called.  It updates the Time field.
     ///////////////////////////////////////////////////////////////////////////
 
     public void paint (Graphics g) {
         w_time.setText ("" + time);
     }
 
     
     ///////////////////////////////////////////////////////////////////////////
     // This is a shortcut routine, sets the status field to the specified value.
     ///////////////////////////////////////////////////////////////////////////
 
     private void Println (String string) {
         w_status.setText (string);
     }
 
     
     ///////////////////////////////////////////////////////////////////////////
     // Whenever the user manipulates a widget, we handle it in this routine.
     ///////////////////////////////////////////////////////////////////////////
 
     public boolean action (Event e, Object arg) {
         // Whenever the size or initialization mode is manipulated, we
         // immediately resize the Parameters[] and Dependencies[][]
         // arrays, update the corresponding text fields, and enter the
         // Ready state.
 
         if (e.target.equals (w_size) || e.target.equals (w_init_mode)) {
             InitializeArrays ();
         }
 
         // The user steps through the main while loop by repeatedly
         // hitting the Go button.  This button is labeled "Start"
         // when in the ready state (time = 0), and is labeled "Next"
         // during execution (time > 0).  When the execution stops,
         // the Go button reads "Done" and is greyed out.
         
         else if (e.target.equals (w_go)) {
             RunUntilAllFalse ();
         }
 
         return true;
     }
 
 
     ///////////////////////////////////////////////////////////////////////
     // This initializes the Parameters[] and Dependencies[][] arrays
     // according to the currently specified Size and Initialization Mode.
     // It automatically updates the appropriate text fields on the screen,
     // and puts the program in the Ready state (time = 0).  We start with
     // Parameters[] set to all true, but the user can edit this before
     // hitting "Start".
     ///////////////////////////////////////////////////////////////////////
 
     private void InitializeArrays () {
         size      = w_size.getSelectedIndex () + 1;
         init_mode = w_init_mode.getSelectedIndex ();
         
         parameters     = new boolean[size];                // let java garbage collect
         dependencies   = new boolean[size][size];
         new_parameters = new boolean[size];
 
         for (int index = 0; index < size; index++) {
             parameters[index] = true;                        // start true; user can edit this
 
             for (int dep = 0; dep < size; dep++) {
                 dependencies[index][dep] = (
                       (init_mode == 1)                           // true everywhere
                  || (init_mode == 2 && dep == index)                      // on diagonal
                  || (init_mode == 3 && dep >= index)           // on or above diagonal
                  || (init_mode == 4 && (dep + index) % 2 == 0) // in block diagonal pattern
                  || (init_mode == 5 && Math.random () < .5)    // random - 50% chance
                 );
             }
         }
 
         UpdateArrayFields ();                              // update appropriate text fields
         IndicateReady ();                                  // get ready to run (time = 0)
     }
 
     
     /////////////////////////////////////////////////////////////////////
     // This indicates that the program is ready to execute, but hasn't
     // yet started to execute.  It does this by enabling the Go button
     // (which reads "Start") and by allowing the user to edit the text
     // areas representing Parameters[] and Dependencies[][].  It also
     // resets the clock.
   /////////////////////////////////////////////////////////////////////
 
     private void IndicateReady () {
         w_go.setLabel ("Start");
         w_go.enable ();
         w_go.requestFocus ();
         w_parameters.setEditable (true);
         w_dependencies.setEditable (true);
         time = 0;
         repaint ();
     }
 
     
     /////////////////////////////////////////////////////////////////////
     // This updates the text fields on the screen that are responsible
     // for displaying the Parameters[] and Dependencies[][] arrays.
     // A "1" means true, a "0" means false.
     /////////////////////////////////////////////////////////////////////
 
     private void UpdateArrayFields () {
         String string1 = "", string2 = "";
         
         for (int index = 0; index < size; index++) {
             string1 += (parameters[index] ? "1 " : "0 ");    
         
             for (int dep = 0; dep < size; dep++) {
                 string2 += (dependencies[index][dep] ? "1 " : "0 ");
             }
             string2 += "\n";
         }
 
         w_parameters.setText (string1);
         w_dependencies.setText (string2);
     }
 
 
     /////////////////////////////////////////////////////////////////////
     // This examines the contents of the text fields on the screen and
     // updates the contents of Parameters[] and Dependencies[][]
     // accordingly.  The user needs to be careful to maintain the same
     // format; exact whitespace needs to be maintained.  I put a note to
     // that effect on the applet itself.
     /////////////////////////////////////////////////////////////////////
     
     private void ReadArrayFields () {
         char str1[] = w_parameters.getText()   . toCharArray ();
         char str2[] = w_dependencies.getText() . toCharArray ();
 
         for (int index = 0; index < size; index++) {
             parameters[index] = (str1[index*2] == '1');
             for (int dep = 0; dep < size; dep++) {
                 dependencies[index][dep] = (str2[dep*2 + index*(size*2+1)] == '1');
             }
         }
     }
 
     
     //////////////////////////////////////////////////////////////////////
     // This is called each time the user hits the (enabled) Go button
     // (either labeled "Start" of "Next").  It handles one step through
     // the main while loop.
   //////////////////////////////////////////////////////////////////////
          
     private void RunUntilAllFalse () {
     
         // If we are at the start of execution, read in the values
         // of the text fields for Parameters[] and Dependencies[][]
         // and then disable the editability of the text fields during
         // execution.
 
         if (time == 0) {
             ReadArrayFields ();
             w_go.setLabel ("Next");
             w_parameters.setEditable (false);  
             w_dependencies.setEditable (false);
         }
 
         // While any element of Parameters is true do the following: //
 
         if (AnyParametersTrue ()) {
             int index;
 
       // Initialize all elements of NewParameters to false //
 
             for (index = 0; index < size; index++) {
                 new_parameters[index] = false;
             }
 
             // For all integer index in the range 1..Size                         //
             //   If Parameter[index] is true then                                 //
       //     For all integers dep such that Dependencies[index,dep] is true //
       //       with a 50% chance, NewParameter[dep] BECOMES true            //
 
           for (index = 0; index < size; index++) {        // indexes minus 1
                 if (parameters[index]) {
                     for (int dep = 0; dep < size; dep++) {
                         if (dependencies[index][dep] && Math.random() < .50) {
                             new_parameters[dep] = true;
                          }
                     }
                 }
             }
 
       // Overwrite the value of Parameters with the value of NewParameters //
 
             for (index = 0; index < size; index++) {
                 parameters[index] = new_parameters[index];
             }
 
             // Increment Time [End of While loop] //
 
             time++;
 
             UpdateArrayFields ();
             repaint ();
       }
         
         // Output Time. //
 
         // We re-test whether or not any parameters are true, because we want to
         // be able to "freeze" by disabling the Go button and printing the end
         // time.
         
         if (!AnyParametersTrue ()) {
             Println ("End time = " + time);
             w_go.setLabel ("Done");
             w_go.disable ();
           w_size.requestFocus ();
         }
     }
 
 
     ///////////////////////////////////////////////////////////////////////////////
     // This returns whether or not any parameters are still true.
   ///////////////////////////////////////////////////////////////////////////////
     
     private boolean AnyParametersTrue () {
         for (int index = 0; index < size; index++) {
             if (parameters[index]) {
                 return true;
             }
         }
         return false;
     }
 }
 
 /////////////////////////////////////////////////////////////////////////////////