/*

**FreqHist.java**

Counts letters in a specified file outputting the
distribution to a text file

Version 1.4

Copyright Tom Kennaugh 2001

*/

import java.io.*;
import java.lang.Math;

public class FreqHist {

  //Declare Variables
  private static int chars = 0;
  private static int lines = 0;
  private static int letters = 0;
  private static int pcl = 0;
  private static float count[] = new float[26];  //Float used since less accuracy + few calculations required

  private static String getFilename(String use,boolean exist) {
    // Filename Reader
    String file;
    try {
      BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
      System.out.println(); 
      System.out.print("Enter filename for " + use + "?");     // Prompt User
      file = input.readLine();
        if (exist) {
          if (!checkFile(file)) {
            System.out.println("File does not exist!");
            throw new FileNotFoundException();           
          }
       }
    }
    catch (Exception e) {
      System.out.println("Please type a correct filename.");  // On error ask user again (recurcive method)
      file = getFilename(use,exist);  
    }
    return file;
  } 
  
  private static boolean checkFile(String fname) {
    File tempFile = new File(fname);
    return tempFile.exists();
  }


  private static void doCount(String ipf) throws IOException {
    System.out.print("Processing Please Wait ..... ");  // Show the program is processing
    BufferedReader in = new BufferedReader(new FileReader(ipf));
    int c = 0;
    
    while ((c = in.read()) != -1) {
      chars++;
      if ((c<91) && (c>64)) {     // Count Upper Case
        c -= 65;
        count[c]++;
        letters++;
      }
      else {
        if ((c<123) && (c>96)) {  // Count Lower Case
          c -= 97;
          count[c]++;
          letters++;
        }
        else {
          if (c == '\n') {        // Count Lines (Not required but included)
            lines++;
          }
        }
      }
    }  
    if(chars != 0) lines++; //Fix line count (ie count last line)
    in.close(); // close input file
    System.out.print("\rProcessing Finished             "); // remove processing message (cr) and signal finished
  }

  private static void normalise() {
    int i;
    float max = 0;   
    for (i=0;i<26;i++) { if (count[i]>max) max = count[i]; }  // Get maximum
    for (i=0;i<26;i++) 
      count[i] = (float)(Math.rint(1000*count[i]/max)/1000);  // Divide by max and round for each value
    pcl = (int)(100*(float)(letters)/(float)(chars)+0.5);     // Calculate Percentage Letters (extra)
  }

  private static void writeFile(String opf,String ipf) {
    int i;
    String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";  // used to print lables
    try {
      PrintWriter pw = new PrintWriter(
                          new BufferedWriter(
                             new FileWriter(opf)), true); // Set up PrintWriter
                             
      // Write formatted data
      pw.println("** Frequency Distribution of Letters in '" + ipf + "' **");
      pw.println();
      for (i=0;i<26;i++) {
        pw.println(alphabet.charAt(i) + "\t" + count[i]); // prints letter + frequency. Tab separated for import compatibility
      }
      //Print stats to end of file
      pw.println();
      pw.println("Total number of characters is " + chars);
      pw.println("Total number of letters is    " + letters);
      pw.println("Percentage of letters is      " + pcl + "%");
      pw.println("Total number of lines is      " + lines);
      pw.close();  // Close file after writing
      
      System.out.println();
      System.out.println("Output written to " + opf);  // Signal completion of writing
    }
    catch (Exception e) {
      System.out.println();
      System.out.println("WARNING: Error writing output to file " + opf);  // on error writing file (unexpected unless user gives a bad file name)
      System.out.println("File not written");                              // tell user
    }
  }
  
  public static void main(String[] args) { 

    //Declare Variables
    int i;
    String inputfile;
    String outputfile;

    //Title
    System.out.println("*---------------------------------*");
    System.out.println("|Frequency distribution of letters|");
    System.out.println("*---------------------------------*");
    System.out.println();

    //Get filenames
    if (args.length != 0) {      // Get filename from command line if it exists
      if (checkFile(args[0])) {  //check file exists
        inputfile = args[0];
      }
      else {                     // Else prompt user
        System.out.println("Specified input file \'" + args[0] + "\' does not exist!");
        System.out.println("Usage: java FreqHist <inputfile> <outputfile>\n");
        inputfile = getFilename("input file",true);
      }
    }
    else {
    inputfile = getFilename("input file",true);
    }
    if (args.length == 2) { // Get filename from command name if it exists
      outputfile = args[1];
    }
    else {                  // Else prompt user
      outputfile = getFilename("output file",false);
    }

    //Print Filenames
    System.out.println("Input Filename = " + inputfile);
    System.out.println("Output Filename = " + outputfile);
    System.out.println();    

    //Process Input File and Perform Count
    try {
      doCount(inputfile);
    }
    catch (Exception e) {  // Exceptions are unexpected. Halt program
      System.out.println();
      System.out.println("**FATAL ERROR DURING PROCESSING**");
      System.out.println("**" + e.getMessage() + "**");
      System.exit(1);  // errorlevel 1 exit
    }
    
    // Normalise Distribution
    normalise();
    
    //Write Output File
    writeFile(outputfile,inputfile); 

    //Print Stats
    System.out.println();
    System.out.println("Total Characters = " + chars);
    System.out.println("Total Letters = " + letters);
    System.out.println("Percentage Letters = " + pcl + "%");
    System.out.println("Total Lines = " + lines);
  }
}

/*
STUDENT DECLARATION
1. I confirm that I am aware of the University's Regulation governing
   Cheating in a University Test (Regulation 12) and of the guidance 
   issued by the School of Engineering concerning plagiarism and proper
   academic practice, and that the assessed work now submitted is in 
   accordance with this regulation and guidance.
2. I understand that, unless already agreed with the School of
   Engineering, assessed work may not be submitted that has previously
   been submitted, either in whole or in part, for any qualification
   other than the one for which I am currently registered, at this
   or any other institution.
3. I recognise that should evidence emerge that my work fails to
   comply with either of the above declarations, then I may be liable
   to proceedings under Regulation 12.
Student name:	Tom Kennaugh 	Date:	03/04/01

*/
