Computer Science 252
Problem Solving with Java

Fall 2014, The College of Saint Rose

Lab 2: Laundry Sorter
Due: 11:59 PM, Monday, September 15, 2014

The Scenario

Many students must wash their own clothes for the first time when they come to college. By the time some figure out how to use laundry machines, their underwear is pink and their white T-shirts are streaked with lots of interesting colors. In the hopes of helping next year's freshmen adjust more easily to college, you are to write a laundry sorting simulator.

You may work alone or with a partner on this lab. Only one submission per group is needed.

There are a number of lab questions and practice programs, and one programming assignment in this lab. Please refer to the "Submission Guidelines" on the course home page and syllabus for the requirements for each of these items.

Getting Set Up

To get your BlueJ environment set up for this week's lab assignment, start BlueJ and choose "New Project" from the "Project" menu. Navigate to your folder for this course and choose the name "Lab2" (no spaces) for the project.

Create a document where you will record your answers to the lab questions. If you use plain text, call it "lab2.txt". If it's a Word document, you can call it whatever you'd like, but when you submit, be sure you convert it to a PDF document "lab2.pdf" before you submit it.

Working solutions to all programs can be downloaded here.

Practice Questions and Programs

This lab includes a series of practice programs, each of which will help you with one or more of the aspects of the programming assignment at the end.

Dragging Compound Objects

Practice Program: Write a program CompoundDrag.java that creates a red circle with a black frame (a FilledOval with a FramedOval of the same size on top) and allows you to drag those two objects around as a pair. (4 points)

There are many ways to implement dragging - in our examples so far there are two variables: a boolean that remembers whether we are dragging an object or not, and a Location that is used to track the previous mouse position. Another option is to eliminate the boolean and track if there is currently a drag operation in place using the Location - if the Location is null, there is no drag operation in progress, if it refers to some Location, there is one.

Question 1: State an advantage and a disadvantage of this alternate approach to support dragging. (2 points)

Random Numbers and Colors

We will use Java's Random class from the java.util package to generate random numbers.

Java API Documentation: java/util/Random.html

Note that the textbook uses some Objectdraw-specific classes RandomIntGenerator and RandomDoubleGenerator. You are welcome to use those, but be sure you know how to use the standard Java Random class as well.

The ColorfulSpirograph example shows how to choose from a list of predefined colors, MoreColorfulSpirograph and CrazyColorfulSpirograph show how to generate completely random colors.

You can see a list of predefined color constants (and much more information) on the documentation page for Java's Color class.

Java API Documentation: java/awt/Color.html

Practice Program: Write a program RandomColors.java that displays two "fabric swatches" (that is, a square of some color inside a black outline). The swatches start out white. When the mouse is pressed on one of the swatches, that swatch chooses a new random color. One swatch's color is chosen randomly from among 4-6 predefined colors, while the other is chosen completely at random. (5 points)

Next, you will make a few additions to this program.

Question 2: Click a few dozen times on the completely random swatch. How many dark, color, and white swatches did you generate? (1 point)

We will consider (as a bonus) ways to get a better balance among the three color types.

Dragging to Multiple Targets

In the Basketball2 example, we saw how to drag an object to a target location, in this case a basketball to a hoop, and react based on whether the ball was dragged into the hoop or not.

Our next practice program will be to create a program that uses this idea, but with multiple targets toward which you can drag an object. The idea is that you have a set of 4 bins, labeled "A", "B", "C", and "D", representing letter grades on an assignment. The program will repeatedly generate a test score in the range 60-100, and your task is to drag that score into the bin corresponding to the grade. Grades in the 60's go to "D", 70's to "C", 80's to "B", and 90 and up to "A". If the score (represented by a Text object containing the number as a String) is dragged to the correct bin, it becomes green. If it is dragged to an incorrect bin, it becomes red, and if it is dragged outside of any bin, it becomes blue. As soon as the dragging operation is complete, a new score is randomly generated and a new Text object is constructed, ready to be dragged.

To limit the busy work and get down to the important part of this program, here is some code that will draw the bins on your canvas:

public class DragGrades extends WindowController {

    private static final int BOX_SIZE = 50;
    private static final int BOX_SPACING = BOX_SIZE/2;
    private static final int BOX_TOP_OFFSET = 100;
    private static final Location SCORE_START_POS = new Location(200, 200);

    private FramedRect aBox, bBox, cBox, dBox;

    private Random r = new Random();

    public void begin() {
        // draw the boxes
        double nextX = BOX_SPACING;

        aBox = new FramedRect(nextX, BOX_TOP_OFFSET, BOX_SIZE, BOX_SIZE, canvas);
        new Text("A", nextX, BOX_TOP_OFFSET, canvas).setFontSize(BOX_SIZE);

        nextX += BOX_SPACING + BOX_SIZE;
        bBox = new FramedRect(nextX, BOX_TOP_OFFSET, BOX_SIZE, BOX_SIZE, canvas);
        new Text("B", nextX, BOX_TOP_OFFSET, canvas).setFontSize(BOX_SIZE);

        nextX += BOX_SPACING + BOX_SIZE;
        cBox = new FramedRect(nextX, BOX_TOP_OFFSET, BOX_SIZE, BOX_SIZE, canvas);
        new Text("C", nextX, BOX_TOP_OFFSET, canvas).setFontSize(BOX_SIZE);

        nextX += BOX_SPACING + BOX_SIZE;
        dBox = new FramedRect(nextX, BOX_TOP_OFFSET, BOX_SIZE, BOX_SIZE, canvas);
        new Text("D", nextX, BOX_TOP_OFFSET, canvas).setFontSize(BOX_SIZE);
    }
}

Your task is to add the remaining functionality. The dragging of a Text object is no different than dragging the other kinds of items we have seen. The main challenge here is deciding what color to make the Text object when it is finished being dragged. There are three cases: it was dragged to the correct bin, it was dragged to an incorrect bin, or it was dragged outside of any bin. Consider the following logic, presented in pseudocode, that would occur when the object's drag operation is complete:

  if (the grade is 90-100 AND aBox contains the point OR
      the grade is 80-89 AND bBox contains the point OR
      the grade is 70-79 AND cBox contains the point OR
      the grade is 60-69 AND dBox contains the point)
    make it green
  else if (aBox contains the point OR bBox contains the point OR
           cBox contains the point OR dBox contains the point)
    make it red
  else
    make it blue

You could certainly code this, but consider this alternate approach. When the random score is generated (in the begin method for the first number, right after the code corresponding to the above for all subsequent numbers), figure out which bin is the correct bin, and give that one a second name. If we had another instance variable of type FramedRect called correctBox, and we decided that the "D" bin is the correct bin, we would set correctBox as follows:

   correctBox = dBox;

We can think about what the memory looks like for a situation like this:

There are still 4 FramedRect objects in existence, but there are 5 names. Both dBox and correctBox refer to the same object. Later, if the score generated was one where the correct bin is the "A" box, the correctBox variable would be updated to refer to the same FramedRect as aBox.

What does this do for us? It allows us to separate out the complex logic above into two parts. When we choose a new score, we immediately check to see which bin is correct and update correctBox accordingly. Then, when the drag operation completes, we can simplify the logic making use of this fact:

  if (correctBox contains the point)
    make it green
  else if (aBox contains the point OR bBox contains the point OR
           cBox contains the point OR dBox contains the point)
    make it red
  else
    make it blue

Practice Program: Complete the DragGrades.java program. (10 points)

The Laundry Sorter

Your final task is to complete the following programming assignment. Recall that programming assignments are graded on design, documentation, style, and efficiency, in addition to correctness.

Each of the practice programs gave you practice with some technique that you will need in the laundry sorter. Now, you put it all together.

Requirements

The simulator should begin with three wash baskets on the screen and the item to be sorted, or the "swatch" (a sample piece of fabric). For our purposes, the baskets will simply be squares, and they will be labeled "whites", "darks", and "colors."

A working solution will appear below. Click inside the applet to interact with it.



When the program starts, a color swatch will appear on the screen. The user ("laundry trainee") should then drag the swatch to the basket corresponding to the color of the swatch. If the drags the swatch into the correct basket, the program should randomly select a new color for the next item and display it on the screen. If the user drags to an incorrect basket or drops it outside of any basket, the item remains of the same color but is returned to its initial position for another try. Have your program generate a completely random color (as you did in the "RandomColors" practice program) and use the same criteria for determining whether the color should be considered a white, color, or dark item.

Because your program only uses one laundry item at a time, you can (and should!) reuse the same rectangle for each new laundry item by simply changing its color rather than creating a new rectangle. In general, it is a good strategy to reuse objects when possible rather than creating new ones because it uses less memory and makes the code more clear.

For simplicity, you may always make the first item have a fixed color (the demo uses black). The item should actually consist of two rectangles, a FilledRect which is the appropriate color and a FramedRect which is the same size, but lays on top of the filled rectangle to form a border. (Otherwise it can be difficult to see a very light colored item!)

Include a scoreboard showing the number of correct and incorrect placements. This makes it clearer when the trainee succeeds in placing the item correctly. They should read something like "Correct = nn", "Incorrect = mm". If the user drops the swatch outside of any basket, this does not count as either a correct or incorrect placement.

One picky detail: be sure your laundry swatch is always shown above all other items (so it doesn't look like your laundry is passing below the baskets or scoreboard). Given the way graphical objects are stacked in Objectdraw, you can achieve this by simply creating the swatch components last, so they are on top of the graphical stacking order.

A Sample Design

Since this is a significantly larger program than the practice programs, you should first come up with a design document which contains an outline of how you plan to solve the problem. To give you an idea about the expectations for the design document, here is a design that could have been used for the SunAndMoon example from class (plus it uses some constants that did not exist in the class examples). You would also include a simple drawing showing the initial placement of the objects in the scene, labelled with key coordinates.

public class SunAndMoon extends WindowController {

    private FilledRect field;        // lower 1/3rd of window
    private FilledRect sky;          // top 2/3rds of window
    private FilledOval heavenlyBody; // the sun or the moon

    // constants to use in scene layout
    private static final int HORIZON_Y = 260;
    private static final int ORB_DIAMETER = 80;
    private static final double RISE_OR_SET_SPEED = 1.5

    /* Create the sky, field and orb and set their colors */
    public void begin() {
        // create sky (FilledRect), field (FilledRect),
        //  heavenlyBody (FilledOval)
        // set colors to "daytime colors"
    }

    /* Make it look like night by using black, white and gray */
    public void onMousePress(Location point) {
       // set sky, field, heavenlyBody colors to "nighttime colors"
    }

    /* Make it look like a bright sunny day */
    public void onMouseRelease(Location point) {
       // set sky, field, heavenlyBody colors to "daytime colors"
    }

    /* Move the sun-like circle down a little bit */
    public void onMouseMove(Location point) {
       // move heavenlyBody down by one unit
    }

    /* Move the moon-like circle up a bit */
    public void onMouseDrag(Location point) {
       // move heavenlyBody up by one unit
    }
}

One advantage of doing this in BlueJ is that the English descriptions in your design can often become the comments in your program.

Implementation

Write your program in LaundrySorter.java. The grading breakdown for this programming assignment can be found at the end of this document.

It is usually good practice to develop programs incrementally. Start with a simplified version of the full problem. Plan, implement, and test a program for this simplified version. Then, add more functionality, a little bit at a time, until you have solved the full problem.

One note on program design: if you think carefully about how to arrange your conditionals, especially in the onMouseRelease method, you can avoid repeating code. For example, my solution code has exactly one place where a new color is picked, one place where the color of the swatch is updated, one place where it determines the new correct basket, one place where it updates the scoreboard, and one place where the swatch is moved back to its original position.

Optional Extensions

You should always focus first on getting 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, you may extend or embellish your programs for up to 5 points of extra credit. Always be sure to have the basic assignment working properly before attempting any extensions.

One extention that would be very useful would be to come up with a mechanism for generating random colors that would more evenly distribute among whites, colors, and darks. Changing the thresholds might help, but it would also become more difficult for the user to determine the correct answer. A better mechanism would just increase the chances of the especially light or dark hues.

Submitting

Before 11:59 PM, Monday, September 15, 2014, submit your lab for grading. There are three things you need to do to complete the submission: (i) Copy your file with the answers to the lab questions into your project directory. Be sure to use the correct file name. If you prepared your answers in Word, export to a PDF file and submit that. (ii) Upload a copy of your lab (a .7z or .zip file containing your project directory) using Submission Box under assignment "Lab2". (iii) Demonstrate the execution of your programs for your instructor. (2 business day grace period for demos).

Grading

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

> FeatureValueScore
Practice Questions and Programs
CompoundDrag program 4
Lab question 1 2
Basic RandomColors program 5
RandomColors displays RGB 1
RandomColors displays dark/color/white 3
RandomColors counts dark/color/white 1
Lab question 2 1
DragGrades program 10
LaundrySorter Style, Design, and Efficiency
Appropriate comments 5
Good variable names 4
Good use of constants 4
Appropriate formatting 2
Does not generate new objects unnecessarily 2
Good overall design (e.g., avoid repeated code) 2
LaundrySorter Correctness
Generate new color swatch only on correct placement of previous 5
Swatch displayed in the correct initial position 3
Swatch returns to original location after each drag 2
Updates scoreboard correctly 4
Drags swatch properly (including frame) 3
Appropriate behavior for unexpected usage (e.g., start drag outside swatch) 4
No penalty for dragging outside any basket 3
Extra Credit (up to 5 points total)

Total

70