01: HamSpam

Estimated reading time: 25 minutes
Estimated time to complete: 90 minutes (plus debugging time, if needed)
Starter code: hamspam-student.zip
Collaboration: not permitted

Computer science is the study of the theory of computation and its applications. In this course, we will weight the scales toward application. Two important parts of applying the theory of computation are knowing how to make a computer do what you want (programming) and checking that it’s doing what you want (testing). This assignment consists of a textual description of a “toy problem”, provides starter code to solve that problem, and asks you to solve the problem (and test that your solution is correct).

Overview

In this assignment, you’ll download and install the latest version of the Java8 SE SDK and the latest version of the Eclipse IDE for Java development.

Then, you’ll learn to download and set up starter code that we provide, a skill which you’ll need for almost every future programming assignment in this course. You’ll use that code to complete an implementation of the Ham and Spam counting game. Along the way, you’ll start to learn about unit testing, a repeatable, automatable way to detect bugs (and not incidentally, a way for us to test your submissions). Finally, you’ll learn to export and submit an entire Eclipse project to the autograder.

Goals

  • Install a working Java8 SE SDK.
  • Install a working Eclipse IDE.
  • (optional but recommended) Set up and use cloud-based storage and/or regular backups of your COMPSCI 186 work.
  • Import an Eclipse project into the Eclipse IDE.
  • Execute code within Eclipse.
  • Run tests within Eclipse.
  • Write code within Eclipse.
  • Export a project from Eclipse and submit it to the autograder.

Some reminders

  1. Start this (and future) assignment(s) early. It is your responsibility to start early enough that you can get help if you have trouble!

  2. This is the first programming assignment. Programming assignments generally do not permit collaboration. At the top of each assignment, the collaboration policy is clearly stated.

    When collaboration is not permitted, copying partial or whole solutions, obtained from other students or elsewhere, is academic dishonesty, as is showing your code to other students or looking at other students’ code.

    Remember, you can use the course Piazza site to quickly (and anonymously, if you like) get help from both the course staff and your classmates. When using Piazza, don’t copy/paste large chunks of code into your question. Instead, do the same thing you should do if asking a classmate for help: ask your question by describing the problem you’re having, or use a small synthetic example that illustrates your difficulty. If you must include a large chunk of your code to ask your question on Piazza, mark it as a “private” question, and only the course staff will be able to see it.

  3. Do not expect partial credit if you submit a program that does not compile or contains an infinite loop. Errors of these sorts in your project will cause the autograder to fail, and you will receive a zero for your submission.

  4. This is a new, experimental course. We do our best to exhaustively check the assignments and autograder. But, if you think something is wrong with the autograder or assignment (as opposed to your submission), contact the course staff immediately. Capture a screenshot of the error, and export a copy of your assignment in the state that triggers the error. Providing these to us will help us immensely in narrowing down the problem.

  5. Late submissions will not be accepted. Excuses with documentation may permit you to submit an assignment late on a case-by-case basis, consistent with the University’s Academic Regulations and otherwise at my discretion.

Downloading the SDK

Go to Oracle’s Technology Network website (http://java.oracle.com/), navigate to the Java section, then find the Java SE downloads section. (When I wrote this lab, the direct link was at: http://www.oracle.com/technetwork/java/javase/downloads/index.html; if this link does not work, please contact me to update it.)

You should arrive at a page that looks like the following:

SDK download landing page

Click the download button for the JDK, and you should arrive at a page listing the various downloads available:

SDK download page

Choose the correct version for your operating system. For Mac OS X, there is only one choice. For Windows on a relatively new machine, you almost certainly want the “x64” version. (For Linux, you will probably want to install your distribution’s version of the OpenJDK. Check your specific Linux distribution’s package manager for the preferred Java8 SDK on your distribution.) Accept the license agreement using the small radio button, then click the download link.

The key point here is that you are downloading the Java8 (not Java10) SE SDK (that is, the JDK) – you are not downloading Java EE or ME, and you are not downloading the “Java Runtime Environment” (“JRE”).

You should be downloading the latest version, which at the time of this writing is the Java SE Development Kit 8u181. Java10 might or might not work with future projects (notably, there are some known incompatibilities with Assignment 02), so make sure you get Java8 (also known as Java 1.8)!

Installing the SDK

Locate the downloaded file, which will be stored with in your web browser’s standard download location.

Under Windows, it’s a self-extracting executable file (.exe) that runs the installer; under OS X, it’s an installer package (.pkg) inside of a disk image (.dmg). Either way, double-click the file. (Your web browser might also have prompted you to run the downloaded file, which is fine, too.)

Once you run the installer, you should be guided through a series of dialog boxes. You should choose a default (standard) install: the JDK for all users.

Verifying the installation

If everything appears to have gone well, you should have the Java8 SE SDK installed on your system. To verify:

  • OS X: Open the “Terminal” app, which is usually located inside the “Utilities” folder in the “Applications” folder (or just type “terminal” into the Spotlight search). It should look something like:

    OS X: Terminal

    Type java -version and press return. Then type javac -version and press return. You should see something like:

    OS X: java and javac

The 1.8 part is the most important thing here.

  • Windows: Open the Windows (File) Explorer. One way to do this is to open the Start menu and type explorer, then choose the appropriate option. Navigate to where you installed the JDK (by default: in the C: drive, in the Program Files folder, in the Java folder). You should see a window that looks something like:

    Windows: JDK in Explorer

    You’re looking to see that a folder staring with jdk1.8 is in this directory. It’s OK if there’s also a JRE installed (in a folder starting with jre, as shown here), but you must also have the JDK installed.

Again, the 1.8 part is the most important thing here.

Downloading Eclipse

Go to Eclipse’s web site (http://www.eclipse.org/), and press the shiny “Download” button:

Eclipse home page

Click “Download” (or perhaps “Download 64 bit” as shown below) again:

Eclipse download page

And then once more to download the installer for Eclipse:

Eclipse final download page

Depending upon your OS, this file may be an compressed archive (.tar.gz or .zip) or a directly executable installer (.exe). If it’s an archive, open it to find the installer (Eclipse Installer).

Installing Eclipse

Run the installer. You will be prompted to choose which “flavor” of Eclipse you want:

Eclipse installer

Marvel briefly at the many options available, but make sure you select the “Eclipse IDE for Java Developers”.

The default installation directory is fine (on my Mac, this is /Users/liberato/eclipse/java-oxygen, that is, in eclipse/java-oxygen inside my home directory), or you can place it in whatever directory you choose. In either case, make sure you note where it’s going so you can find it! The installer will download and install Eclipse, and this process can take a few minutes.

Launching Eclipse

If all goes well, you should see something like this:

Eclipse installer success

Go ahead and click the “Launch” button. After a brief loading screen, you should see a window prompting you to choose a workspace:

Eclipse installer

A brief but important digression: The place you choose for the Eclipse workspace is where all of your work for this course will go. I strongly, strongly, strongly suggest you do one (or ideally both) of the following:

  • Sign up for a cloud-based storage service, sync that storage with your local computer, and place your Eclipse workspace in this synced directory.

    As a member of the UMass community, you have access to Google Drive with basically unlimited storage space through Apps at UMass. Further, you can install the Backup and Sync application (https://www.google.com/drive/download/). When this is app is running, any changes you make to files in your local Google Drive directory will be uploaded to your Google Drive (and sent to any other of your devices that are also running the application). On my Mac, this directory is /Users/liberato/Google Drive/.

    Other cloud storage providers such as Box and Dropbox provide similar functionality.

  • Enable automatic backups to an external drive, or sign up for a backup service. Make sure your Eclipse workspace is being backed up.

    OS X has Time Machine; Windows has Windows Backup, and there are myriad third-party backup utility vendors. Find one and use it. Make sure you know how to recover from a backup before you need it.

In any event, it’s 2018: storage and bandwidth are virtually free, and the University has both computer labs and loaner computers available. “My computer crashed” won’t be acceptable as an excuse in this class.

Now back to our regularly scheduled program.

Choose an appropriate directory to store your workspace and click OK. After a bit more loading, you’ll see the default Eclipse “Welcome” screen:

Eclipse installer

Eclipse has been installed.

Configuring Eclipse

Quit Eclipse using the appropriate menu item.

Now re-open it. (Do you remember where you installed it?) You should again arrive at the Welcome screen.

Open the Preferences menu item. On a Mac, this will be located in the Eclipse menu in the top-of-the-screen menubar; on Windows, it will be located under the Window menu at the top of the Eclipse window. Either way, it should look something like the following:

Eclipse preferences

Eclipse has about eleventy-hojillion configuration options, but we’re only going to look at one of them for this assignment.

Expand the “Java” item on the left by clicking the small triangle next to it, then select “Installed JREs” by clicking on it (not the triangle, but the words “Installed JREs”). Here’s what it looks like on my Mac:

Installed JREs

And here’s what it looks like on a student’s Windows 10 PC:

Installed JREs, Windows

You should see a list of one or more JREs, depending upon what’s installed on your computer. If you don’t see “Java SE 8” (on a Mac) or “jdk1.8.0_181” (or similar on Windows and Linux – “jdk” and “1.8” are the important parts), click the Search... button on the right, and it should show up (assuming you installed one earlier!). If it doesn’t, contact the TA or instructor via Piazza immediately for assistance, or check with a classmate for help. Make sure that “Java SE 8” or “jdk1.8.0_181” is selected (note the Windows screenshot doesn’t yet have the correct item selected!).

Again, the important thing here is that the “1.8” or “Java 8” or the like is selected.

Downloading and importing the starter code

Download and save (but do not decompress) the provided archive file containing the starter code. Note that in this and future labs, the starter code is linked to at the top of the assignment.

Open Eclipse. Depending upon how you left things after installing Eclipse, you might see either the welcome screen, or the standard eclipse workspace. Close the welcome screen if it’s open. Then choose “Import…” from the “File” menu. A window will come up so you can choose how to import. Select “General” and within that, “Existing Projects into Workspace” (It may seem strange, but do not choose “Projects from Folder or Archive”) Then click “Next”.

import

Choose the button for “Select archive file:” and locate the file you downloaded above. Then click “Finish”.

select file

You should see a hamspam-student Java project in the Package Explorer window on the left. Click on the triangles to reveal the content of this directory and the src, support, and test directories within it.

expanded

Finally, we’re going to make the support directory read-only. The folder contains support code that we encourage you to use (and which must be used to pass certain tests), but you must not change or add anything in this folder. (In this and future assignments, if you change or add files in this directory, you might find that your program runs fine on your machine but that the autograder will not compile it successfully.)

To help ensure that you do not change anything in support, we suggest that you set the folder to be read-only. You can do this by right-clicking on it in the Package Explorer, choosing “Properties” from the menu, choosing “Resource” from the list on the left of the pop-up “Properties” window, unchecking the “Permissions” checkbox for “Owner-Write”, and clicking the “OK” button. A dialog box will show with the title “Confirm recursive changes”, and you should click on the “Yes” button.

permissions

You should see three Java source files among the directories: HamSpam.java, HamCommander.java, and HamSpamTest.java. You can open them by double-clicking on them. Do so, and take a look through each of them. You’ll quickly note they involve a game about “Ham”, “Spam”, and numbers, and that Eclipse has detected two errors.

On Ham and Spam

“Ham and Spam” is a children’s counting game. Before it is played, the players agree on a ham number and a spam number. Both are integers greater than one, and they cannot be the same number. The players then take turns saying the hamspam value for each successive integer, starting at one. Usually, the hamspam value is just the number. But:

  • If the number they are supposed to say is divisible by the ham number and not the spam number they say “ham” instead of the number.
  • If the number they are supposed to say is divisible by the spam number and not the ham number they say “spam” instead of the number.
  • If the number they are supposed to say is divisible by both the spam number and the ham number they say “hamspam” instead of the number.

For example, if the ham number is three, and the spam number is four, then the first twelve hamspam values are:
1, 2, ham, spam, 5, ham, 7, spam, ham, 10, 11, hamspam

For this assignment, you are going to modify the HamSpam class provided to produce the correct value or values for a game of “Ham and Spam”.

Using Eclipse

Let’s walk through using Eclipse to identify and fix errors, run code, and run unit tests.

Finding and fixing compilation errors. You can see that Eclipse has noted that “The blank final field hamNumber may not have been initialized,” as displayed in the Errors list at the bottom and as shown by the red underlines in the source for HamSpam.java.

In other words, the instance variable hamNumber is declared (private final int hamNumber) but never set to a value if the class is instantiated. Your lazy instructor didn’t even provide you with code that compiles!

Fix the error by modifying the constructor of HamSpam to set the instance variable hamNumber to the appropriate argument of the constructor. (A reminder: when a local variable, such as the argument to the constructor, has the same name as an instance variable, you can disambiguate the instance variable by including the this. qualifier. In other words, you can write this.hamNumber = hamNumber; to set the instance variable to the argument passed to the constructor.)

Note that each distinct instance of HamSpam may have a different pair of ham and spam numbers; these values are tracked in these instance variables. When you open HamSpamTest.java you’ll see that more than one instance of HamSpam is created, each with its own hamspam values.

Running programs. Once you’ve eliminated errors, you can run the program. But you’ll note there’s no main method in HamSpam.java. Instead, open HamCommander.java (which does have a main method), then click the green play button in the top row of the Eclipse window (it looks like a white triangle inside of a green circle), or choose “Run” from the Run menu. A console will appear in the bottom of the Eclipse window. Follow along, pressing Enter after each number you enter, to see the (sometimes incorrect) results of the current implementation of Ham and Spam.

Running tests. Next, choose HamSpamTest.java in the Package Explorer and run it using the play button or the menu, as above. When you do, the package explorer on the left will switch to a JUnit pane, which will show the testing output. JUnit is a standard unit-testing library for Java that we’ll be using extensively in this course.

You should see a total of fourteen tests: four tests that pass (with small green checkmarks), and ten tests that fail (with small blue Xs). Familiarize yourself with the testing interface: hover over the buttons to see what they do (notably, one toggles showing only failed tests), and double-click on a test to jump to it. For example, if you select testHamAndSpamGetValue, you should see the following under Failure Trace:

org.junit.ComparisonFailure: getValue returns incorrect value
expected:<[hamspam]> but was:<[12]>
at hamspam.HamSpamTest.testHamAndSpamGetValue(HamSpamTest.java:41)

You may have to resize the JUnit pane to see the full message.

JUnit tests work by checking that the expected result of a method call equals the actual result. The failed test indicates that one (or more) methods in the starter code aren’t returning correct values. Examine the test; you can double-click on at hamspam.HamSpamTest.testHamAndSpamGetValue(HamSpamTest.java:41) (or just the test itself, as noted above) to jump to the test in the source pane. Here, you can see that the test case expects the result of hamspamThreeFour.getValue(12) to be the string "hamspam", but as the output in the Failure Trace indicates, it produced the string "12" instead.

Diagnosing and fixing problems. Go to the declaration of getValue(); you can do so by right-clicking on it and selecting “Open Declaration”, or by double-clicking on HamSpam.java in the Package Explorer and scrolling to it.

Your goal should be to correct the implementation of the getValue() method. The correct solution is not merely to make the function return “hamspam” when n == 12. Instead, you should revise the code so that the function will return the correct string for any n.

There is at least one thing to fix. The getValue() method currently checks for equality against numbers, not divisibility. You can use the modulus (remainder) operator (%) to check for divisibility. It divides one number by another and returns the remainder. For example, if you wanted to print out whether the value of a variable n was divisible by three, you could write:

1
2
3
4
5
if ((n % 3) == 0) {
  System.out.println(n + " is divisible by 3");
else {
  System.out.println(n + " is not divisible by 3");
}

Notably, the value ((n % 3) == 0) will evaluate to true if and only if n is divisible by three. You can use this fact in your implementation of getValue().

Finishing up. Next, you’ll need to write getValues(), which will allocate and return an array of String containing the correct hamspam values for the range.

When we autograde your program, we will test both getValue() and getValues() with other ham and spam numbers to make sure each works properly. Our test cases will obey the constraints described in this assignment (for example, the ham number and spam number will always be greater than one, and never be equal to one another), but are otherwise unconstrained.

In this assignment, we’ve given you all the test cases. But in future assignments, there are test cases we are going to use that you won’t be able to examine for yourself. You will have to think about the problem and make sure you’re not missing any details or corner cases if you want to pass them. (We’ll teach you to write tests soon, but there’s no magic: copy/paste and edit an existing test to get 90% of the way there.)

You can also use the HamCommander class for interactive testing. But as you’ll see, just being able to press the “Play” button and run a bunch of tests quickly and repeatedly is much more convenient, especially as programs grow more complex.

Submitting the assignment

When you have completed the changes to your code, you should export an archive file containing the entire Java project. To do this, click on the “hamspam-student” project in the package explorer. Then choose “Export…” from the “File” menu. In the window that appears, under “General” choose “Archive File”.

export archive

Then choose “Next” and enter a destination for the output file. Be sure that the “hamspam-student” project is selected, and that all Java source files in src files are included (the easiest way to do this is to click “Select All”).

save export

Save the exported file with a .zip extension (any name is fine). Then log into Gradescope, select the HamSpam assignment, and submit the file for grading, just as you did for Homework 01. You’ll see the contents of the .zip file in the upload window after you select it:

upload

If you uploaded a not-fully-correct submission, you might see something like the following:

autograded

Compilation errors will be provided by the autograder, but the exact details of the tests we run on your code are deliberately not provided. For this assignment, the tests you have locally and the tests run on Gradescope are the same, but this won’t always be the case. You must read assignments carefully – if your submission is not passing a test, it is almost certainly because your submission doesn’t match the requirements of the assignment.

Remember, you can resubmit the assignment as many times as you want, until the deadline. If it turns out you missed something and your code doesn’t pass 100% of the tests, you can keep working until it does.