import java.io.*;
import java.util.*;

public class KWK
{

	/**************************************************************
	* readCh
	********
	*Reads the next input character and returns that character. The
	*next read takes place on the same line where this one left off.
	***************************************************************/
	public static char readCh()
	/**************************************************************/
	{
	   int charAsInt = -1; //To keep the compiler happy
	   try
	   {
		   charAsInt = System.in.read();
	   }
	   catch(IOException e)
	   {
		   System.out.println(e.getMessage());
		   System.out.println("Fatal error. Ending Program.");
		   System.exit(0);
	   }
	   return (char)charAsInt;
	}


	/**********************************************************
	* readLine
	**********
	*Reads a line of text and returns that line as a String value.
	*The end of a line must be indicated either by a new-line
	*character '\n' or by a carriage return '\r' followed by a
	*new-line character '\n'. (Almost all systems do this
	*automatically. So, you need not worry about this detail.)
	*Neither the '\n', nor the '\r' if present, are part of the
	*string returned. This will read the rest of a line if the
	*line is already partially read.
	*********************************************************/
	public static String readLn()
	/*******************************************************/
	{
	char nextChar;
	String result = "";
	boolean done = false;

	while (!done)
	{
		nextChar = readCh();
		if (nextChar == '\n')
		   done = true;
		else if (nextChar == '\r')
		{
		//Do nothing.
		//Next loop iteration will detect '\n'
		}
		else
		   result = result + nextChar;
	}
	result = result.trim();
	return result;
	}


	/**********************************************************
	* readLineStr
	*************
	* Reads a line of text and returns that line as a String value.
	* This will read the rest of a line if the line is already
	* partially read.
	*********************************************************/
	public static String readLineStr (String message, String dflt)
	/*******************************************************/
	{
	  char nextChar;
	  String result = "";
	  boolean done = false;

	  if (dflt.length()>0)
		System.out.print(message+" {"+dflt+"} ? ");
	  else
		System.out.print(message+" ? ");
	  result = readLn();

	  if (result.length()==0) result=dflt;
	  return result;
	}


	/**********************************************************
	*readInt
	********
	* Function: Prompted by message, return an integer between
	* min and max (inclusive), with a default of dflt if <CR>
	* is entered.   Note the dflt is specified AS A STRING, ""
	* means there is no default.
	* Precondition: The user has entered a number of type int on
	* a line by itself, except that there may be white space before
	* and/or after the number.
	* Action: Reads and returns the number as a value of type int.
	* The rest of the line is discarded. If the input is not
	* entered correctly, then in most cases, the user will be
	* asked to reenter the input. In particular, this applies to
	* incorrect number formats and blank lines.
	*********************************************************/
	public static int readInt(String message, int min, int max, String dflt)
	/*******************************************************/
	{
	String inputString = null;
	int number = -9999;//To keep the compiler happy.
			   //Designed to look like a garbage value.
	boolean done = false;

	while (! done)
	{
			if (dflt.length()>0)
				System.out.print(message+" {"+dflt+"} ? ");
		else
			System.out.print(message+" ? ");

		try
		{
		inputString = readLn();
		if (inputString.length() == 0)
			inputString=dflt;
		number = Integer.parseInt(inputString);
		done=(number>=min) & (number<=max);
		if (!done)
		  System.out.println("Value out of range ("+min+","+max+")");

		}
		catch (NumberFormatException e)
		{
		System.out.println("Incorrect Integer Format, Reenter.");
		}
	}

	return number;
	}


	/************************************************************
	*readDouble
	***********
	* Precondition: The user has entered a number of type double
	* on a line by itself, except that there may be white space
	* before and/or after the number.
	* Action: Reads and returns the number as a value of type
	* double. The rest of the line is discarded. If the input is
	* not entered correctly, then in most cases, the user will be
	* asked to reenter the input. In particular, this applies to
	* incorrect number formats and blank lines.
	*************************************************************/
	public static double readDouble(String message, double min, double max, String dflt)
	/*******************************************************/
	{
	String inputString = null;
	double number = -9999;//To keep the compiler happy.
				  //Designed to look like a garbage value.
	boolean done = false;

	while (! done)
	{
		try
		{
				if (dflt.length()>0)
				System.out.print(message+" {"+dflt+"} ? ");
				else
					System.out.print(message+" ? ");

		inputString = readLn();
		if (inputString.length() == 0)
			inputString=dflt;
		number = Double.parseDouble(inputString);
		done=(number>=min) & (number<=max);
				if (! done)
				  System.out.println("Value out of range ("+min+","+max+")");

		}
		catch (NumberFormatException e)
		{
		System.out.println("Incorrect Input Format, Reenter.");
		}
	}

	return number;
	}


	/*********************************************************
	* readChar
	**********
	*Reads the first nonwhite character on a line and returns
	*that character. The rest of the line is discarded. If the
	*line contains only white space, then the user is asked to
	*reenter the line.
	*********************************************************/
	public static char readChar(String message, char dflt)
	/*******************************************************/
	{
	boolean done = false;
	String inputString = null;
	char nonWhite = ' ';//To keep the compiler happy.


	while (! done)
	{
			if (dflt==' ')
			System.out.print(message+" {"+dflt+"} ? ");
			else
				System.out.print(message+" ? ");

		inputString = readLn();
		if (inputString.length() == 0)
		nonWhite=dflt;
		else
		nonWhite = (inputString.charAt(0));
		done = true;
	}

	return nonWhite;
	}


	/********************************************************
	* readBool
	**********
	* Input should consist of a single word on a line, possibly
	* surrounded by white space. The line is read and discarded.
	* If the input word is "y", "yes", "true" or "t", then true
	* is returned.  If the input word is "n" "no", "false" or "f",
	* then false is returned.
	* Uppercase and lowercase letters are considered equal. If the
	* user enters anything else (e.g., multiple words or different
	* words), then the user is asked to reenter the input.
	********************************************************/
	public static boolean readBool(String message, String dflt)
	/*******************************************************/
	{
	boolean done = false;
	String inputString = null;
	boolean result = false;//To keep the compiler happy.

	if (dflt.length()>0)
	{
		if (dflt.equalsIgnoreCase("t")) dflt="Y";
		else if (dflt.equalsIgnoreCase("f")) dflt="N";
		System.out.print(message+" {"+dflt+"} ? ");
		}
		else
			System.out.print(message+" ? ");

	while (! done)
	{
		inputString = readLn();
		inputString = inputString.trim();
		if (inputString.length() == 0)
		inputString=dflt;
		if (inputString.equalsIgnoreCase("true")
		   || inputString.equalsIgnoreCase("t")
		   || inputString.equalsIgnoreCase("yes")
		   || inputString.equalsIgnoreCase("y"))
		{
		result = true;
		done = true;
		}
		else if (inputString.equalsIgnoreCase("false")
			|| inputString.equalsIgnoreCase("f")
			|| inputString.equalsIgnoreCase("no")
			|| inputString.equalsIgnoreCase("n"))
		{
		  result = false;
		  done = true;
		}
		else
		{
		  System.out.print("Incorrect Input Format; Enter T, F, Y, N ? ");
		}
	 }

	return result;
	}


	/*******************************************************************
	* readChoice
	************
	* print message and read one character which must be in choices list}
	* alpha characters in choices must be upper case, default char=dflt}
	********************************************************************/
	public static char readChoice (String message, String choices, String dflt)
	/*******************************************************************/
	{
	boolean ok=true;
	String inputString;
	char reply=' ';

		do
		{
			if (dflt.length()==0)
				System.out.print(message+" ? ");
		else
			System.out.print(message+" {"+dflt+"} ? ");

		inputString=readLn();
		if (inputString.length()==0)
		inputString=dflt;
		inputString=inputString.toUpperCase();
		ok=false;
		if (inputString.length()>0)
		{
				reply=inputString.charAt(0);
			if (choices.indexOf(reply)>=0)
				ok=true;
			}
		if (! ok)
			System.out.println("Invalid Choice");
		} while (! ok);
		return reply;
	}


	/*************************************************************
	* rStr
	******
	* Converts double val to right justifed, rounded string
	* in a field wid long and with dec decimals
	* will expand string length if need to keep significant digits
	*************************************************************/
	public static String rStr ( double val, int width, int dec)
	/************************************************************/
	{
		PrintfFormat fmtItem=new PrintfFormat("%"+width+"."+dec+"f");
		return fmtItem.sprintf(val);
	}


	/***************************************************************
	* iStr
	******
	* Converts int val to right justifed string of length wid
	* will expand string length if needed to keep significant digits
	***************************************************************/
	public static String iStr ( int val, int width)
	/**************************************************************/
	{
		PrintfFormat fmtItem=new PrintfFormat("%"+width+"i");
		return fmtItem.sprintf(val);
	}


	/**************************************************************************
	* writeFile - open a file for steam text output
	***********
	* The writeFile method prompts the user for the name of a file to write.
	* Unless the path is specified, the file will be in the default directory.
	* If the file exists, the method verifies it is ok to replace the file.
	* The method then opens the file for writing
	* To use this method, you must import Java.io.* in the calling procedure.
	* You must also declare an object of the type PrintWriter then assign
	* the method to the declared object, e.g.
	*
	* import java.io.*;
	* ...
	* PrintWriter streamOut=null;
	* ...
	* streamOut=writeFile("Listing File Name","list.txt");
	* ...
	* streamOut.println("Use print and println as usual on streamOut");
	*
	* streamOut.close()  //once writing is complete
	**************************************************************************/
	public static PrintWriter writeFile(String message, String defaultFileName)
	/*************************************************************************/
	{
		PrintWriter stream=null;
		File fileObject=null;
		boolean quit=false;

		do
		{
			fileObject=new File(readLineStr(message,defaultFileName));
			// get file name

			if (fileObject.exists())
			//if the file to be written exists
			{
				quit=false;
				if (readBool("  File Exists, OK to Replace","T"))
				   //check to see if OK to delete
				   //fileObject.delete deletes file
				   quit=! fileObject.delete();
				   //get a new file name only if file delete fails
				else
					quit=true;
					//get a new file name if user says don't delete
			}
		} while (quit);  //get a new name if quit true

		try
		{
			stream = new PrintWriter(new FileOutputStream(fileObject));
			System.out.println("  Opening: "+fileObject.getPath());
		}
		catch(FileNotFoundException e)
		{
			//this should not happen under ordinary circumstances
			System.out.println("  Fatal Error opening the file"+fileObject.getPath());
			System.exit(0);
		}
		catch(IOException e)
		{
			System.out.println("IO Exception On "+fileObject.getPath());
			System.exit(0);
		}
		return stream;
	}


	/**********************************************************************
	* readFile - open a file for steam text input
	**********
	* The readFile method prompts the user for the name of a file to read.
	* Unless the path is specified, the file will be in the default directory.
	* The method checks to be sure the file exists then opens it for writing
	* To use this method, you must import Java.io.* in the calling procedure.
	* Also, in the calling procedure declare an object of the
	* type BufferedReader then assign the method to the declared object, e.g.
	*
	* import java.io.*;
	*
	* BufferedReader streamIn=null;
	* ...
	* streamIn=readFile("Input Data File Name","data.txt");
	*
	* also, any read from the file and the close of the file (and associated code)
	* should occur within the scope of an IOException trap, e.g. to print a
	* file to the screen the follwing is an example of the read and the close
	* the file
	*
	*	try
	*	{
	*		String s;
	*		do
	*		{
	*			s=inStream.readLine();
	*			if (s!=null)
	*				System.out.println(s);
	*		} while (s!=null);
	*		inStream.close();
	*	}
	*	catch(IOException e)
	*	{
	*		System.out.println("Error reading from Input File");
	*		System.exit(0);
	*	}
	****************************************************************************/
	public static BufferedReader readFile(String message, String defaultFileName)
	/***************************************************************************/
	{
		BufferedReader stream=null;
		File fileObject=null;
		boolean quit=false;

		do
		{
			fileObject=new File(KWK.readLineStr(message,defaultFileName));
			// get file name
		} while ((! fileObject.exists())||(!fileObject.canRead()));
		try
		{
			stream = new BufferedReader(new FileReader(fileObject));
			System.out.println("  Reading: "+fileObject.getPath());
		}
		catch(FileNotFoundException e)
		{
			//this should not happen under ordinary circumstances
			System.out.println("  Fatal Error opening the file"+fileObject.getPath());
			System.exit(0);
		}
		catch(IOException e)
		{
			System.out.println("Error reading from"+fileObject.getPath());
			System.exit(0);
		}
		return stream;
	}

	/***************************
	* double
	********
	* squares a value
	***************************/
	public static double sqr(double v)
	{
	  return (v*v);
	}


	/**************************************************************
	* getCh
	********
	*Reads the next input character from stream and returns it. The
	*next read takes place on the same line where this one left off.
	***************************************************************/
	public static char getCh(BufferedReader stream)
	/**************************************************************/
	{
	   int charAsInt = 0; //To keep the compiler happy
	   try
	   {
		   if (stream.ready()) charAsInt=stream.read();
	   }
	   catch(IOException e)
	   {
		   System.out.println(e.getMessage());
		   System.out.println("Fatal error. Ending Program.");
		   System.exit(0);
	   }
	   return ((char)charAsInt);
	}

	/************************************************************
	 * closeBufferedReader
	 * *******************
	 * Deals with the issues asssociated with closing a file.
	 ***********************************************************/
	public static void closeBufferedReader(BufferedReader stream)
	{
	  try
	  {
		stream.close();
	  }
	  catch(IOException e)
	  {
		System.out.println(e.getMessage());
		System.out.println("Error Closing Input File.");
	  }
	}

	/* procedure skip_comment(var fvar: text);
	var c: char;
	begin
	   {skip over # to end of line or text between #'s, e.g. #site 12 #}
	   c:=^J;
	   repeat
	   if not seekeoln(fvar) then read(fvar,c);
	   until eoln(fvar) or (c='#') or (c=^J);
	end; */

	/***************************************************************
	 * skipSeparator
	 * *************
	 * reads white space characters and commas from the input stream
	 * returning the first non-whitespace character
	 * skips over blanks, tabs, commas, lf's
	 * *************************************************************/
	 public static char skipSeparator(BufferedReader stream)
	 {
	  char c;
	  String skipChars=" ,\t\n\r";
	  c=(char)0;
	  do
	  {
		c=getCh(stream);
		/* if c='#' then begin skip_comment(fvar); c:=',' end; */
	  } while (((int)c>0) && (skipChars.indexOf(c)>=0));
	  return(c);
	}

	/***************************************************
	 * getToken
	 **********
	 * Reads the next input token ignoring commas and
	 * white space from the input stream.
	 **************************************************/
	public static String getToken(BufferedReader stream)
	/**************************************************/
	/* reads an antana token */
	{
	  String reply="";
	  String skipChars=" ,\t\n\r";
	  char c;

	  c=skipSeparator(stream);
	  do
	  {
		reply=reply+c;
		c=getCh(stream);
	  } while (skipChars.indexOf(c)<0);
	  /*if c='#' then skip_comment(fvar); */
	  return(reply);
	}

	/***********************************************
	 * getInt
	 ********
	 * Reads the next integer from the input stream
	 ***********************************************/
	public static int getInt(BufferedReader stream)
	/***********************************************/
	{
		String s;
		int rslt=Integer.MIN_VALUE;
		s=getToken(stream); /* deal with eoln */
		try
		{
			rslt=Integer.parseInt(s);
		}
		catch (NumberFormatException e)
		{
			System.out.println("Error in Integer Input: "+s+"  0 used");
		}
		return (rslt);
	}

	/***********************************************
	 * getDouble
	 ***********
	 * Reads the next double from the input stream
	 ***********************************************/
	public static double getDouble(BufferedReader stream)
	/***********************************************/
	{
		String s;
		double rslt=Double.MIN_VALUE;
		s=getToken(stream); /* deal with eoln */
		try
		{
			rslt=Double.parseDouble(s);
		}
		catch (NumberFormatException e)
		{
			System.out.println("Error in Real Input: "+s+"  0 used");
		}
		return (rslt);
	}

	/********************************************************
	*Small main program that can be used to test the methods
	********************************************************/
	public static void main(String Args[]) //program for testing only
	/*******************************************************/
	{
		boolean boolVal;
		int intVal;
		double doubleVal;
		char charVal;

		do
		{
			intVal=readInt("Test readInt",1,100,"49");
			System.out.println(intVal);
			doubleVal=readDouble("Test readDouble",1,100,"49");
			System.out.println(doubleVal);
			charVal=readChar("Test readChar",'Z');
			System.out.println("\""+charVal+"\"");
			charVal=readChoice("Test readChoice","ABCDE","C");
			System.out.println("\""+charVal+"\"");
		} while(readBool("Continue","F"));
	}
}

