Homework Assignment 2

This homework assignment will give you additional experience with writing basic Java programs and then some initial experience with inheritance and types.
  1. Rewrite the Salary.java question from homework assignment 1 with the following modifications:

    1. Create an instance variable in the Salary class in which you place the computed value for the average salary once all the salaries have been read (as opposed to a local variable in the Salary constructor).
    2. Create a method in Person for printing the person's information and true if the person's salary is above the group average and false otherwise. Your method will need to access the parent class's average salary instance variable. Your program should call this method when printing out employee's information at the end of your program. This part of the problem is supposed to show you that instances of nested classes can access instance variables in their parent object.
    3. The input will be read from standard input. There will be one person record per line. Hence the sample input from hw1 will now look like:
      nels 105000.80 
      mary 20000.50 
      frank 18153.33 
      nancy 91868.73 
      michelle 20858
      Use a Scanner object, not a Console object, to read input because the TAs may redirect stdin in order to test your program. You may assume that the input is error free.
    4. You should output the names in the order that they appear in the input. Hence your output for the above sample input should be:
      average salary = 51,176.27 
      nels            105,000.80 true
      mary             20,000.50 false
      frank            18,153.33 false
      nancy            91,868.73 true
      michelle         20,858.00 false
    5. You can either use your list code from question 7 to handle the variable-length input or you can use an ArrayList to handle the variable length-input.
    You must use my program design. I understand it might not be either the way you would like to organize your program or even the best way to design the program. However, I want to give you experience with using nested classes and with calling methods.

  2. The following problem will give you experience with Java's Map collection classes, Java's file I/O classes, and Java's Scanner class. You may thank the redoubtable Professor Plank for this problem, as he is the one who composed it and wrote it.

    In the game of golf, players can rank themselves with a handicap. This is a number that basically tells you how good you are at the game. The lower your handicap, the better you are.

    The US Golf Association has a very lengthy description of how you calculate a handicap. It may be found at http://www.usga.org/Handicapping.aspx?id=7792 if you're interested. I'm going to simplify it a bit. Here is how you calculate a handicap for a golfer:

    For example, suppose I have played 20 rounds of golf from the white tees at Three Ridges golf course, whose rating is 69.3 and whose slope is 119. On ten of the rounds, I shot 88 and on the other ten, I shot 85. Then I would compute my handicap as follows: Your Strategy

    Your strategy for solving this problem should be as follows:

    1. Use a class to store the golfer's last name, their scores, and their computed handicap.
    2. Use a Map (i.e., either a Java TreeMap or HashMap) to store the golfer objects indexed by last names so that you can read lines from a score file and find the appropriate golfer to associate it with.
    3. For each golfer, use one of the following two approaches to store a golfer's score:

      1. use a tree to store a golfer's scores by date so that you can easily find the twenty most recent scores. The key should be the date and the value should be the score differential.
      2. use an ArrayList to store a golfer's scores.

      Use Java's GregorianCalendar class (java.util.GregorianCalendar) to store dates. They support the compareTo method, so they can be the key you use in the tree. Here are a couple things you should know about the Gregorian Calendar class:

      1. The class is inconsistent about its months and days. Months are numbered from 0 and days are numbered from 1. Hence if you want to create the date February 3, 1964, you should write:
        GregorianCalendar date = new GregorianCalendar(1964, 1, 3);
        This numbering scheme can cause you grief if you're not careful. For example, if you try to enter Dec. 15, 1999 as
        date = new GregorianCalendar(1999, 12, 15);
        Java will convert it to January 15, 2000, thinking that you meant to "roll over" to a new year with the 12. Hence when you parse the score files, make sure you subtract 1 from the month when you create a date object.

      2. It's not that easy to print a nicely formatted date. Here's the best code I've seen thus far:
                import java.util.GregorianCalendar;
                import java.text.SimpleDateFormat;
                GregorianCalendar date = new GregorianCalendar(1964, 1, 3);
                SimpleDateFormat dateFormatter = new SimpleDateFormat("MM-dd-yyyy");
                String printableDate = dateFormatter.format(date.getTime());
        This outputs 02-03-1964, which you might find useful if you are trying to print dates to help you debug your program. Note the MM for months. You would think that mm would work but it doesn't (try for yourself).
    4. Use a HashMap to store the courses. Do not use a HashTable, since it is designed for threaded applications, and you are not using a threaded application. You will need a class to store the information associated with each course.
    5. Your golfer class should have a method that when called, sets the golfer's computed handicap by iterating through the golfer's most recent 20 scores. If you used a TreeMap to store each golfer's score, then you should be able to do this by using an iterator to iterate through the TreeMap and stopping when your count reaches 20. You will need to use the DescendingMap() method to get a NavigableMap object that contains the tree entries in descending order, since the dates will be stored in ascending order. You can then iterate through the NavigableMap object using its values() method (use a counter to count to 20 and break when the counter reaches 20). If you used an ArrayList to store each golfer's score, then you will need to use the Collections sort algorithm to sort the ArrayList in descending order by date and use the first 20 entries in the sorted ArrayList.
    6. Once you've read the score file and associated all the scores with the appropriate golfer, compute each golfer's handicap by calling your computeHandicap method. Rather than creating a second TreeMap, I want you to add the golfers to a List, and then sort the list using a comparator based on the golfers' handicap. You can then traverse this tree to print the golfer's by handicap in ascending order.

    Your Job

    Your job is to write the program handicap.java. It should take two command line arguments:

    java jar handicap.jar score-file course-file
    The score-file is a file that contains scores. Each line of this file is in the following format:
    Month Day Year Name Score Course
    Month is a number between 1 and 12. Day is a number between 1 and 31. You do not have to error check for legal month/day combinations (i.e. don't worry about 2/30). Year is the year (i.e. 1999, 2000). Name is a one-word name of a golfer, and Score is an integer score. Course is the name of a course, and may contain any number of words separated by white space. Although course is the last part of the line, you cannot assume that there will be only one space between each of the names in the course. Hence you will need to iterate through each of the names and concatenate them together, each separated by a space. The scores can be in any order, and there can be any number of golfers in the score file.

    There are example score files in /home/bvz/courses/302/labs/lab3:

    The course-file is a file that contains golf courses plus their ratings and slopes. This file has a looser structure than the score file. It contains three kinds of lines:
    1. Course Lines: These start with the word ``Course'' and then contain the name of the golf course. Again, the name is words separated by white space.
    2. Rating/Slope Lines: These have the word ``Rating'' then the rating (which is a floating point number), then the word ``Slope'' and then the slope (which you should also treat as a floating point number). When you encounter this line, it is the rating and slope for the course named on the most recently encountered ``Course'' line.
    3. All Other Lines: All other lines should be ignored.
    My suggestion for reading a course file is to use a BufferedReader to read one line at a time using the readLine method. Stuff the string this method returns into a Scanner object and use the Scanner's next method to examine the first word of the line. There will be three cases:

    1. The line starts with Course: Store the string returned by BufferedReader's readLine method into a course variable.
    2. The line starts with Rating: Use the Scanner object's next and nextDouble methods to read the information you need from this line.
    3. The line starts with anything else. Discard the line and move on.
    An example (good to use for testing) is in courses. Look at the first four lines:

    Course Three Ridges -- White Tees
    Rating 69.3 Slope 119
    Par     72

    This says that there is a course that's called ``Three Ridges -- White Tees'' with a rating of 69.3 and a slope of 119. You ignore the ``Par'' line, and the blank line after the ``Par'' line.

    In both files (scores and courses) you should create a string for a course that is composed of each word separated by a space. For example, the following course specifications should be equivalent:

    Course Three Ridges -- White Tees
    Course      Three          Ridges          -- White            Tees

    Now, your program must read in both of these files. You may assume that they contain no errors and that they contain at least 20 scores for each golfer. Then print out the golfers and their handicaps, ordered by handicap (lowest first). Print out the handicap first (padded to 5 characters and two decimal places), and then the golfer's name.

    For example:

    UNIX> java -jar handicap.jar score1 courses
    14.31 Jim
    UNIX> java -jar handicap.jar score2 courses
     3.70 Phil
    14.31 Jim
    UNIX> java -jar handicap.jar score3 courses
     3.70 Phil
    14.31 Jim
    UNIX> java -jar handicap.jar bigscore courses
     2.58 Tiger
     8.26 Phil
     8.31 Sergio
     9.63 David
     9.77 Anika
    10.12 Jose
    18.12 Ernie
    18.21 Colin
    18.50 John
    18.88 Se-Ri
    39.55 Karrie
    A working executable is available at ~bvz/cs302/labs/lab3/handicap (it's a C++ implementation, not a Java implementation). If you set the environment variable PRINTDIFFS to be "yes", then the program will also print out each golfer's differential and date number (defined in step 4 below) or each score. You can use this to test yourself in case your computations do not seem to match those here. Note, you do not have to implement this feature. It is just included it so that you can help test your own code.
    UNIX> setenv PRINTDIFFS yes
    UNIX> handicap score1 courses
      Dnum: 743660   Differential: 17.76
      Dnum: 743661   Differential: 17.76
      Dnum: 743691   Differential: 14.91
      Dnum: 743693   Differential: 14.91
      Dnum: 743722   Differential: 17.76
      Dnum: 743725   Differential: 17.76
      Dnum: 743753   Differential: 14.91
      Dnum: 743757   Differential: 14.91
      Dnum: 743784   Differential: 17.76
      Dnum: 743789   Differential: 17.76
      Dnum: 743815   Differential: 14.91
      Dnum: 743821   Differential: 14.91
      Dnum: 743846   Differential: 17.76
      Dnum: 743853   Differential: 17.76
      Dnum: 743877   Differential: 14.91
      Dnum: 743885   Differential: 14.91
      Dnum: 743908   Differential: 17.76
      Dnum: 743939   Differential: 14.91
      Dnum: 743970   Differential: 17.76
      Dnum: 744001   Differential: 14.91
    14.31 Jim
    UNIX> setenv PRINTDIFFS no
    UNIX> handicap score1 courses
    14.31 Jim

    What to Submit

    Please submit the following two files:

    1. A jar file named salary.jar that we can execute to test problem 1. Please include your source code in salary.jar.
    2. A jar file named handicap.jar that we can execute to test problem 2. Please include your source code in handicap.jar.