Computer Science 120
Introduction to Programming

Spring 2012, Siena College

Lab 2: Advanced Laundry Sorter
Due: the start of your next lab session

This week's lab assignment involves an exercise to show you how to run programs that do not use any graphics (specifically, not the objectdraw library) in BlueJ, and a larger task to improve upon your laundry sorter from last week.

You may work alone or with a partner on this lab.

A GPA Calculator

For the first part of this lab we will be writing some traditional Java code that is a simple GPA Calculator. Your program will compute a GPA for four classes. For this "simple" calculator you may assume that each class you take is 3 credits. The formula for computing a GPA is:

GPA = total of all class grade points/total number of classes

You will prompt the user for each of their letter grades. Your program should convert the letter grades to their corresponding values based on the table below:

A

= 4.0
A- = 3.7
B+ = 3.3
B = 3.0
B- = 2.7
C+ = 2.3
C = 2.0
C- = 1.7
D+ = 1.3
D = 1.0
D- = 0.7
F = 0.0

In your BlueJ project create a class named GPACalculator. Do not remove the constructor that BlueJ provides: you'll want that later. But you can remove the example instance variable and the sample method.

You will only need one import statement at the top of your program for this class:

import java.util.*;

This will import the java package that we need in order to prompt the user for their grades.

Since we are not using objectdraw in this class you will not need to import the objectdraw package or "extend" your class statement. It should be left as public class GPACalculator.

Your first step is to add the method called main that traditional Java runs first, which is the analog of the begin() method in our objectdraw classes. At the bottom of your GPACalculator class (but inside the final closing curly brace) add the code:

public static void main(String args[]){

}

What does all that mean?

Before getting started with the main functionality of this program, let's add a printout and make sure you have everything set up correctly so far. In your main method, add the statement:

  System.out.println("Welcome to the CSIS 120 GPA calculator.");

And then compile and run your program. Compiling is the same as before, but to run a program with a main method, you will choose the void main(String[]) menu item. This will bring up a dialog where you can specify command-line parameters to your program. For today, we will not be using any, so you can just click "OK" to start up your program.

If all goes well, you should see a big white window appear. This is the BlueJ "terminal window" and should contain the text from your println above. Note that while a println is the only way this program will produce output for you, it is also a useful tool in your objectdraw programs. Any program that executes a println will cause BlueJ to bring up this terminal window.

Creating an instance of our class

In traditional Java, the first step is to create an instance of the class you are running. This is done in our main method since it is the first method to get executed. Creating this instance looks just like all of our other calls to constructors (like "new FilledRect(...) or new RandomIntGenerator(1,3)). In your main method, add the line:

GPACalculator gpaCalc = new GPACalculator();

This will call our constructor that was automatically added to our class by BlueJ when we created a new class:

public GPACalculator(){
//initialize instance variables
}

This constructor is where we initialize our instance variables. You will add the initializations here as you create any needed instance variables. For now, it can stay empty but does need to be defined.

Now that we have an instance of our class, gpaCalc, we can call our methods that we create just as we have called the provided methods on the objects we have been using. For example, if we have a FilledOval named bob, and we want to set its color to red, we could write:

  bob.setColor(Color.red);

In general, the format of a method call on a constructed object is

objectVarName.methodName(inputs);

where our objectVarName is gpaCalc and our methodName and inputs will be defined and created next.

We will need to start by creating two methods that we will call from our main method using the syntax above. Your objectVarName will be gpaCalc, methodName will be whatever you name each of your methods, and inputs will be the parameters you need to pass to that method (if any).

Method One: Prompt the user for input

Your first method will be responsible for reading the four letter grades from the keyboard and storing those grades in instance variables.

This method does not "return" any value, so it should look like this:

  public void enterGrades() {

    // do stuff in here to prompt for and read in 4 grades into
    //instance variables
  }

assuming you name your method enterGrades. This should be defined within your class but outside of any other method. A good place for it might be between your constructor and your main method. The void here means that it does not return a value back to the caller - it just executes the sequence of statements within the method body.

In order to get input from the keyboard, we need to learn about and use a new Java class: the Scanner.

Here is the link to its official Java documentation: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.html

The Scanner class provides a lot of functionality, some of which we will see later in the semester. For now, you only need to do two things with the Scanner: construct it, and use it to read lines of input that were typed in.

In this first method you will create an instance of the Scanner class:

Scanner scInput = new Scanner(System.in);

This is the way to ask Java to provide a mechanism to "scan" input from a given source. In this case, we use System.in, which indicates that the source is the "standard input" - just a fancy name for the keyboard input.

Then utilize the nextLine() method of the Scanner class to read in each grade from the user:

   scInput.nextLine();

This will return to you the line of input from they keyboard as a String, hopefully one of A, A-, B+ etc. You will convert it to its point value later, but for now, you should save each of the String values returned by nextLine() into an instance variable of type String.

Here is the documentation for the String class to help you: http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html

The Scanner class will read the user input from the terminal window. The same place where we saw that the output of System.out.println appears. Use println to print out nice prompts for the user each time you read in an input grade.

Recall the format of a println:

System.out.println("String to appear in the terminal window");

In the end, this first method should read in each of the four grades from the user and save them in instance variables of type String.

Call it from your main method with the statement:

  gpaCalc.enterGrades();

This is really no different than our method calls on our graphical objects except that here, you are not just the caller of the method, you are also the author!

Method Two: Compute your GPA

This method will also be called from your main method. It will calculate your GPA and return that value to the main method. You will need to convert each grade, represented as a String in an instance variable, to the appropriate double value listed above, then compute the average of those values.

If you were to choose the name computeGPA for your method, it would look like this:

  public double computeGPA() {
     double answer;  // a place to store the GPA we compute
 
     // compute the GPA

     return answer;   // send the computed answer back to the caller
  }

And in your main method, when you call this, you will need to "capture" the return value in a variable so you can later print it out:

   double gpa = gpaCalc.computeGPA();

As you write this method, you may find yourself repeating blocks of if statements (such as in the conversion of your String letter grades to their numeric values), you should move those blocks to its own method and then simply call the method as needed.

For example, if we were writing a program that allowed a user to enter the names of the states in New England by their two-letter postal abbreviations, and wish to convert those abbreviations to full state names at several points in our programs, we may find that we are writing code such as the following, over and over:

   // a String variable abbrev contains a 2-letter abbreviation
   String fullName;  // we will place the full name in this String
   if (abbrev.equalsIgnoreCase("MA")) {
      fullName = "Massachusetts";
   }
   else if (abbrev.equalsIgnoreCase("VT")) {
      fullName = "Vermont";
   }
   else if (abbrev.equalsIgnoreCase("NH")) {
      fullName = "New Hampshire";
   }
   else if (abbrev.equalsIgnoreCase("ME")) {
      fullName = "Maine";
   }
   else if (abbrev.equalsIgnoreCase("RI")) {
      fullName = "Rhode Island";
   }
   else if (abbrev.equalsIgnoreCase("CT")) {
      fullName = "Connecticut";
   }
   else {
      fullName = "Invalid State!";
   }
   // use fullName as needed here

(Side note: the equalsIgnoreCase method allows us to compare two Strings for equality with a case-insensitive comparison. You may wish to do the same when comparing your grade Strings to allow your users to type in either capital or lowercase letters when entering their grades.)

If we only need to do this in one place in our code, it's not too bad. But suppose we allow someone to enter three state abbreviations as responses to trivia questions about New England states. Those abbreviations are in three String variables ans1, ans2, and ans3. Now, we want to print out the responses, using the full names for the states. We could write something like:

   String fullAns1;
   // ... many lines of code like the above to set fullAns1 from ans1
   System.out.println("Question 1 response: " + fullAns1);

   String fullAns2;
   // ... many lines of code like the above to set fullAns2 from ans2
   System.out.println("Question 2 response: " + fullAns2);

   String fullAns3;
   // ... many lines of code like the above to set fullAns3 from ans3
   System.out.println("Question 3 response: " + fullAns3);

This is tedious at best, and is an error-prone way to write code. A better approach here is to write a helper method:

  public String fullStateName(String abbrev) {

    String fullName;  // we will place the full name in this String
    if (abbrev.equalsIgnoreCase("MA")) {
       fullName = "Massachusetts";
    }
    else if (abbrev.equalsIgnoreCase("VT")) {
       fullName = "Vermont";
    }
    else if (abbrev.equalsIgnoreCase("NH")) {
       fullName = "New Hampshire";
    }
    else if (abbrev.equalsIgnoreCase("ME")) {
       fullName = "Maine";
    }
    else if (abbrev.equalsIgnoreCase("RI")) {
       fullName = "Rhode Island";
    }
    else if (abbrev.equalsIgnoreCase("CT")) {
       fullName = "Connecticut";
    }
    else {
       fullName = "Invalid State!";
    }
    return fullName;
  }

We can then write our three println statements from above using calls to this helper method:

   System.out.println("Question 1 response: " + fullStateName(fullAns1));
   System.out.println("Question 2 response: " + fullStateName(fullAns2));
   System.out.println("Question 3 response: " + fullStateName(fullAns3));

Note that this is a bit different from the way we call most of our methods: it does not have an object name before the method name. By omitting the object before a method name, we are asking Java to call another method in the same class in which we are currently executing.

Finishing Up

The computed GPA will be printed from the main method. Make sure to include a nice string before the GPA.

Don't forget to demonstrate your working program to your instructor.

Advanced Laundry Sorter

Your main task this week is to improve upon the laundry simulator from last week's lab, using some of the techniques we have since learned.

Listed below are the extensions you are to make. Note that it will be much easier to do each of these separately. That is, design, implement, and thoroughly test your code for each extension before moving on to the next.

  1. Add counters (Text items) at the bottom of the picture showing the number of correct and incorrect placements. This makes it clearer when the student succeeds in placing the item correctly. They should read something like "Correct = nn", "Incorrect = mm". The value in the first Text item will be formed by concatenating the string "Correct = " with an integer instance variable which keeps track of the number of correct answers. The other Text item is similar. (You can also have both counters interspersed in the text of one text string.) If the user presses the mouse button down outside the laundry item, it should not increase the correct or the incorrect counter.
  2. Users should drag the items to the correct laundry basket rather than just clicking on the basket. Recall from the example in class that you will need an instance variable to label the last mouse position before the drag so you can determine how far to drag the item. If the user drops their laundry outside of all baskets, it will count as an incorrect sorting.
  3. Assign the item a randomly generated color by randomly choosing integers redNum, greenNum, and blueNum between 0 and 255 for each of the red, blue, and green components of the color. Colors are created from those components by writing new Color(redNum, greenNum, blueNum).

    Now define criteria for determining where each color should go. The simplest criterion is based on the sum of the three color components. If the sum of the component numbers is less than 230, then it goes in the darks basket, if it is greater than 675, then it goes in the whites basket. Otherwise it goes in the colors basket. To aid in your program development and testing, and to help us to grade your submission, add a Text item that displays the RGB code of the color you choose.

The details of how to add these features are left mostly to you, but you should not hesitate to ask for help if you get stuck. Note that to drag the item, you should drop the onMouseClick method in favor of using the three methods:

A working solution for the advanced laundry sorter will appear below. Click inside the applet to interact with it.



Optional Extensions

You should always focus first on getting the required components of the lab working, writing good comments, and using good style in your programming. But if you have done all that and would like to do more, here are some extra credit opportunities.

  1. As described above, if the user drops their laundry outside of all baskets, it will count as an incorrect sorting. For extra credit, you can be nicer to the user. If the user misses all the baskets, let the user try again without increasing either the correct or incorrect counters.
  2. In real laundry sorting, there is no precise threshold between whites and colors or between colors and darks. Enhance your program so there is some leeway for borderline cases: if the color is reasonably close to the threshold, allow a correct guess for either basket.

You should also feel free to extend or embellish your programs further, but always be sure to have the basic assignment working properly beforehand. Other enhancements are not eligible for extra credit, however.

Submitting Your Work

Before the start of your next lab session, submit your Java programs for grading. There are three things you need to do to complete the submission: (i) place a copy of your Java programs into your csis120/hw folder under hw4, (ii) print a copy of each of your programs and hand it to your lab instructor, and (iii) demonstrate the execution of your programs for your instructor.

Don't forget to check your programs for compliance with the Style Guide for CSIS 120 Programs

Grading

This assignment is worth 100 points, which are distributed as follows:

> FeatureValueScore
"GPA" Style, Design, and Efficiency (10%)
Appropriate comments 2
Good variable names 2
Good use of constants 2
Appropriate formatting 1
Good overall design and methods 3
"GPA" Correctness (20%)
main method 2
Constructor 2
Prompt for and read input grades 4
Conversion of input grade strings to numeric equivalents 4
Compute GPA from stored input grades 5
Print out computed GPA 3
"Laundry" Style, Design, and Efficiency (25%)
Appropriate comments 5
Good variable names 4
Good use of constants 5
Appropriate formatting 2
Does not generate new objects unnecessarily 3
Good overall design 4
"Laundry" Correctness (35%)
Generate new color for swatch only on correct placement of previous 4
Generate new random color 5
RGB code of color displayed correctly 3
Swatch displayed in the correct initial position 4
Swatch returns to original location after dropping in a basket 4
Updates # correct and # incorrect appropriately 5
Drags swatch properly 6
Appropriate behavior for unexpected usage (e.g., start drag outside swatch) 4
Extra Credit
No penalty for dragging outside any basket 2
Two baskets allowed as correct for colors near thresholds 4
Total 100