
/* Simulation of console-I/O program LengthConverter2,
   using ConsoleApplet as a basis.  See the file
   ConsoleApplet.java for more information.
   
   David Eck
   eck@hws.edu
   
*/

public class LengthConverter2Console extends ConsoleApplet {

   protected String getTitle() {
      return "Sample program \"LengthConverter2\"";
   }

   protected void program() {

      /* 
         This program will convert measurements expressed in inches,
         feet, yards, or miles into each of the possible units of
         measure.  The measurement is input by the user, followed by
         the unit of measure.  For example:  "17 feet", "1 inch",
         "2.73 mi".  Several measurements can be combined on
         one line of input.  For example:  "2 miles 5 yards 1 inch".
         In this case, the measurements are combined into one total.
         Abbreviations in, ft, yd, and mi are accepted.  Negative 
         measurements are not allowed.
      
         The program will continue to read and convert measurements
         until the user enters an empty line.
      */
      
      double measurement;  // Numerical measurement, input by user.
      String units;        // The unit of measure for the input, also
                           //    specified by the user.
      
      double inches, feet, yards, miles;  // Measurement expressed in each
                                          //   possible unit of measure.
      
      console.putln("Enter measurements in inches, feet, yards, or miles.");
      console.putln("For example:  1 inch    17 feet    2.73 miles");
      console.putln("You can use abbreviations:   in   ft  yd   mi");
      console.putln("I will convert your input into the other units of measure.");
      
      while (true) {
         
         /* Get the user's input, and convert it to inches. */
         
         console.putln();
         console.putln();
         console.putln("Enter your measurement, or press return to end:");
         
         skipBlanks();  
         
         if (console.peek() == '\n')  // End if there is nothing on the line.
            break;
            
         inches = readMeasurement();  // If value is < 0, then user's input was illegal.
         
         if (inches >= 0) {
            
            /* Convert the measurement in inches to feet, yards, and miles. */
         
            feet = inches / 12;
            yards = inches / 36;
            miles = inches / (12*5280);
          
            /* Output the measurement in terms of each unit of measure. */
         
            console.putln();
            console.putln("That's equivalent to:");
            console.put(inches, 15);
            console.putln(" inches");
            console.put(feet, 15);
            console.putln(" feet");
            console.put(yards, 15);
            console.putln(" yards");
            console.put(miles, 15);
            console.putln(" miles");
            
         } // end else
         
         console.getln();  // Discard the rest of the input line before
                          // getting the next line.
      
      } // end while
      
      console.putln();
      console.putln("OK!  Bye for now.");

   }  // end program()
   
   
   void skipBlanks() {
         // Reads past any blanks and tabs in the input.
         // Postcondition:  The next character in the input is an
         //                 end-of-line or a non-blank character.
      char ch;
      ch = console.peek();
      while (ch == ' ' || ch == '\t') {
         ch = console.getAnyChar();
         ch = console.peek();
      }
   }
   
   
   double readMeasurement() {

         // Reads the user's input measurement from one line of input.
         // Preconditino:  The input line is not empty.
         // Postcondition:  If the user's input is legal, the measurement
         //                 is converted to inches and returned.  If the
         //                 input is not legal, the value -1 is returned.
         //                 The end-of-line is NOT read by this routine.

      double inches;  // Total number of inches in user's measurement.
      
      double measurement;  // One measurement, such as the 12 in "12 miles"
      String units;   // The units specified for the measurement, such as "miles"
      
      char ch;  // Used to peek at next character in the user's input.

      inches = 0;  // No inches have yet been read.

      skipBlanks();
      ch = console.peek();
      
      /* As long as there is more input on the line, read a measurement and
         add the equivalent number of inches to the variable, inches.  If an
         error is detected during the loop, end the subroutine immediately
         by returning -1. */

      while (ch != '\n') {
      
          /* Get the next measurement and the units.  Before reading
             anything, make sure that a legal value is there to read. */
      
          if ( ! Character.isDigit(ch) ) {
              console.putln("Error:  Expected to find a number, but found " + ch);
              return -1;
          }
          measurement = console.getDouble();
          skipBlanks();
          if (console.peek() == '\n') {
              console.putln("Error:  Missing unit of measure at end of line.");
              return -1;
          }
          units = console.getWord();
          units = units.toLowerCase();
          
          /* Convert the measurement to inches and add it to the total. */
          
          if (units.equals("inch") || units.equals("inches") || units.equals("in"))
              inches += measurement;
          else if (units.equals("foot") || units.equals("feet") || units.equals("ft"))
              inches += measurement * 12;
          else if (units.equals("yard") || units.equals("yards") || units.equals("yd"))
              inches += measurement * 36;
          else if (units.equals("mile") || units.equals("miles") || units.equals("mi"))
              inches += measurement * 12 * 5280;
          else {
              console.putln("Error: \"" + units + "\" is not a legal unit of measure.");
              return -1;
          }
        
          /* Look ahead to see whether the next thing on the line is the end-of-line. */
         
          skipBlanks();
          ch = console.peek();
          
      }  // end while
      
      return inches;
      
   } // end readMeasurement()
   

}  // end class LengthConverter2Console
