import java.io.*;

/**
 * Drill on heaps --- including Enter/Heapify
<pre>
   Keyboard dialog (random data)
      1.    size desired
      2...  Multiple ENTERs as successive enqueues are done
      3.    Pause --- end of multiple enters
      4...  Multiple ENTERs as unsorted vector undergoes Heapify
      5.    Pause --- end of heap generation
      6...  Multiple ENTERs as the queue is emptied.
</pre>
  @author   Timothy Rolfe
*/
public class HeapDrill
{
// For drill purposes.
   static int player[] = null, nPlayers, current = -2;

   public static void main ( String[] args )
   {  MinHeap2 jobQ = new MinHeap2();
      JobEntry job = null;
      String   lineIn = "";
      boolean  minOne, multiPlayer;
      int      size, k, data[] = null;

      System.out.print ("Number of players (0 or 1 for solo):  ");
      if (args.length < 1)
         lineIn = getLine();
      else
      {  lineIn = args[0]; System.out.println (lineIn);  }
      nPlayers = atoi(lineIn);
      multiPlayer = nPlayers > 1;
   // First call initializes the player information.
      if ( multiPlayer )
         playerUp();

      System.out.print ("Heap size:  ");
      if (args.length < 2)
         lineIn = getLine();
      else
      {  lineIn = args[1]; System.out.println (lineIn);  }

      size = atoi(lineIn);
      if ( size < 1 )
      {  System.out.println ("Illegal size.  Abort.");  System.exit(-1);  }

      data = new int[size];
      if ( data == null )
      {  System.out.println ("Insufficient memory.  Abort."); System.exit(-1);}

      System.out.print ("Min heap (Y/N) --- else max heap: ");
      lineIn = getLine();

      minOne = lineIn.length() > 0
               && Character.toUpperCase(lineIn.charAt(0)) == 'Y';

      for (k = 0; k < size; k++)
         data[k] = k+1;

      shuffleArray(data, size);

      System.out.println ("Building the heap with successive enqueues:\n"
           + "Press ENTER at each stage to see the result\n");

      for ( k = 0; k < size; k++ )
      {  int current = data[k];
         lineIn = ( current < 10 ? " " : "" )
                  + current;
         if (minOne)
            job = new JobEntry( current, lineIn );
         else
            job = new JobEntry( size-current, lineIn );
         jobQ.enqueue(job);
         if ( multiPlayer )
            playerUp();
         System.out.print ("Entering \'" + lineIn + "\': ");
         lineIn = getLine();
         jobQ.display();
      }

      System.out.println ("\nFinished with successive enqueues.\n"
           + "Press ENTER to begin enter/heapify section\n"
           + "(Note that the root is stored in subscript 1):\n");
      lineIn = getLine();

   // First, empty out the present queue.
      for ( k = 0; k < size; k++ )
      {  job = jobQ.dequeue(); }

   // Bare entry of values via jobQ.enter
      for ( k = 0; k < size; k++ )
      {  int current = data[k];
         lineIn = ( current < 10 ? " " : "" )
                  + current;
         if (minOne)
            job = new JobEntry( current, lineIn );
         else
            job = new JobEntry( size-current, lineIn );
         jobQ.enter(job);
      }

   // NOTE:  heapify is set to do the pauses.
      System.out.println (
         "Press ENTER after each step of heapify to see next.\n");

      jobQ.heapify(multiPlayer);

      System.out.println ("Emptying out the resulting queue:\n"
           + "Press ENTER at each stage to see the result.");

      for ( k = 0; k < size; k++ )
      {  job = jobQ.dequeue();
         if ( multiPlayer )
            playerUp();
         System.out.println ("Delete gives \'" + job.otherInfo + "\'"
              + "  Press ENTER to see remaining queue. ");
         lineIn = getLine();
         jobQ.display();
         System.out.println();
      }
      System.out.print ("Press ENTER to exit: ");
      lineIn = getLine();
   }

   static public void playerUp ()
   {
      if ( player == null )
      {
         player = new int[nPlayers];
         for ( current = 0; current < nPlayers; current++ )
            player[current] = current+1;
         shuffleArray (player, nPlayers);
         current = -1;  // Will increment before use
         return;        // Initialization call does not prompt
      }
      if ( ++current >= nPlayers )
      {
         System.out.println ("New sequence of players.");
         for ( current = 0; current < nPlayers; current++ )
            player[current] = current+1;
         shuffleArray (player, nPlayers);
         current = 0;   // Note that increment has happened.
      }
      System.out.print ("Player #" + player[current] + ":  ");
   }

// Code for reading console from "Java in a Nutshell", p. 166
   static BufferedReader console = new BufferedReader
                                  (new InputStreamReader(System.in));
// UTILITY FUNCTIONS:
// Pull a line of text from the console.
   static String getLine ()
   {  String text = "";
      try
      {  text = console.readLine();  }
      catch (IOException e)
      {  /* let it pass */  }
      return text;
   } // end getLine()

// replacement for parseInt that acts like the C function atoi
   static int atoi(String number)
   {  int rtnVal = 0;   // on invalid string, return a zero

      try
      {  rtnVal = Integer.parseInt(number);  }
      catch (NumberFormatException e)
      { /* Let it pass! */  }

      return rtnVal;
   } // end atoi

/**
 * Shuffle the entire array, using the class scope generator
 */
   static void shuffleArray ( int [] x, int lim )
   {//Accept the default initialization of the random generator
      java.util.Random generator = new java.util.Random();

      while ( lim > 1 )
      {  int item,
             save = x[lim-1];
         item = generator.nextInt(lim);
         x[--lim] = x[item];                // Note predecrement on lim
         x[item] = save;
      } // end while
   } // end shuffleArray()

} // end class HeapDrill
