Overview: Work in pairs, both together and separately

In this lab we'll write a non-trivial sized program in Java, but it will be written following the procedural programming paradigm — not the way one normally programs in Java. However, we'll get familiar with how Java language features, run-time features and conventions enable and even encourage collaboration. We'll also git a little familiarity with a tool that makes collaboration better still — the "git" version control system.

You'll work in pairs on a program to do "Mad Libs". Sometimes you'll be working together at a single computer, sometimes separately on different parts of the same project. At all times, you'll be constantly testing and debugging as you go. When you're done, you should be well-positioned to start learning the core of this class (starting Monday!): Objected-Oriented Programming.

Find a partner now! One of you will be partner "Blue", the other will be "Gold". Decide now who is who!

Step 0: Setting up your git repository

The Gold partner will create a project repository named "lab02ic211"on their github account. So, only the gold partner will do the following:
  1. login to your github account
  2. click on the "repositories" tab (top left-ish) and click on the green "New" button (top right-ish) and fill in with:
    • Repository name: lab03ic211
    • Select "Private" (lock icon)
    • Check the "Add a README file" checkbox
    Then click on the "Create Repository" button. Voila: you have now created a project!
  3. Click on "Settings", then click on "Collaborators". [Note: you will be prompted to enter your password again.] Click on the "Add People" button, and enter either the username or the email address the Blue partner (i.e. the other one!) used for their github account, click on their identity and click the "Add name to this repository" button.
  4. Blue partner: go to your email and accept this invitation.

Both Partners: On your separate lab machines pull up a shell and go to your home directory, i.e. cd ~. You must not be in the ic210 or ic211 directory! give the command:

git clone git@github.com:GoldPartnerGithubUsername/lab03ic211.git
This should create a directory lab03ic211. Please cd into it and ls. You should see a file README.md.

Step 1: Translating C++ to Java

Note: Do this with both partners at the Gold Partner's computer, and make sure you work in the lab03ic211 directory.
Below is a simple C++ program that defines structs/functions for handling linked lists of strings, along with a "main" that tests these features.

$ g++ -o ltest main.cpp stringlist.cpp
$ ./ltest
Testing stringlist functions ...
[expecting 3 : hickory dickory dock]
3 : hickory dickory dock   
Your job ...
Your job is to translate this program to Java (retaining its procedural programming approach). Specifically, you should have files StringNode.java and StringList.java that work like this:
$ javac StringNode.java StringList.java
$ java StringList
Testing stringlist functions ...
[expecting 3 : hickory dickory dock]
3 : hickory dickory dock   

Note1: the point of this is not to produce the output which, after all is just there for testing. The point is to port the addtofront, length and listtoarray to Java for you to use in the next part of the lab!
Note2: Your code should be commented, and you must include both of your names and alphas at the top of both Java files!
Note3: creating a singular class Object is "new Foo()" as opposed to creating an array which is "new Foo[n]". [This goes back to that distinction between, builtin types,a array Object types and class Object types.]

Step 2: Share your new code using git

Step 3: Go your own way

Gold Partner
You will create a class WordRead defining a function
public static String[] get(String fname) { ... }
that takes a filename fname and reads all the strings in that file, returning them (in order) in an array. Since you don't know how many strings are in the file, you're going to have to use a linked list (good thing you have one!) to read and store, then copy into an array. Unfortunately, you really need to have things stored in order!

Of course you'll have to thoroughly test this by writing a "main" for your WordRead class. Copy file nouns.txt and have your "main" call get("nouns.txt") and print the resulting array, which should show the words in nouns.txt, one per line, in the same order they appear in the file.

$ java WordRead
booger
cat
tennis-racket
souffle
apartment-building
doorknob
whoopee-cushion
iPad
dork
ninja-turtle  

One thing you'll need to be able to do is create a Scanner that reads from a file. Without understanding what's going on, here's how to do that:

Scanner sc = null;
try { sc = new Scanner(new FileReader(fname)); } 
catch(IOException e) { e.printStackTrace(); System.exit(1); }
You'll need a "import java.io.*;" for that. I also suggest you take a look at the Scanner class's hasNext() (see the Scanner API documentation). The gist is that sc.hasNext() returns true if there's a "next" string to be read, and false otherwise. This will tell you when to stop reading from the input file.

Blue Partner
You'll create a class named Formatter and define in it a function
public static void writeInColumns(String[] sta, int cols) { .. }
that takes an array sta of strings and a positive int cols and prints the strings from sta out, in order, separated by spaces, but never using more than cols characters (including spaces!) in a line. So you have to periodically insert newlines as you go.

Of course you'll have to thoroughly test this by writing a "main" for your Formatter class that has a hardcoded array with values "these","are","the","times","that","try","men's","souls.", then calls writeInColumns to print the array in 20, then 10, then 21 columns.

$ java Formatter
cols = 20
These are the times
that try men's
souls.

cols = 10
These are
the times
that try
men's
souls.

cols = 21
These are the times
that try men's souls.
Just to clarify in these examples, when cols=20, we can't fit "that try men's souls." into a single line, because that would take 21 characters:

Since "souls." has no spaces in it, it acts like a single word and the whole thing gets moved to the 3rd line.
Note: there should be a newline after the final word. There should not be spaces after the last word on a line.

Step 4: Combining your work in your git repo

We need both partners to push their local changes to the repo, and pull their partners changes into their local repo.
  1. Gold Partner
    git add WordRead.java nouns.txt
    git commit -m "WordRead class added"
    git push
  2. Blue Partner
    git pull
    git add Formatter.java
    git commit -m "Formatter class added"
    git push
  3. Gold Partner
    git pull
At this point both partners should have the same stuff in their lab03ic211 directory.

Step 5: Combining your work

At this point, make sure you've both pushed and pulled so that both have the up-to-date repository. Continue development on the Gold partner's computer by creating a class MidLibs defining a program that takes a filename (as a command line argument) and prints the words in that file within 35 columns. If there isn't a filename on the command line (i.e. args has length 0), you should print the usage message shown below and exit (System.exit(0) will do this for you). Download the files madin01.txt and madin02.txt so you have something to run on.
~/$ java MidLibs
usage: java MidLibs <filename>
~/$ java MidLibs madin01.txt
One of my @nounp came to see me in
my office. He was @adjective with
his @nounp . He asked if there were
any optional assignments he could
do to @verb things. I told him that
I don't believe in @nounp , but
that I was happy to help him @verb
for the final.
~/$ java MidLibs madin02.txt
A group of @nounp ran into the
@adjective room. I tried to @verb
under the @noun but it was too hard
to @verb. So I gave them my
@adjective @noun asking only that
they @verb somewhere else.
Note: The beautiful thing is that as you start this Step, you have all of the functions (aka methods) from StringList, WordRead and Formatter, thoroughly tested, battle-hardened and ready for you to use!

Important! Any file you have created or modified during this step should be committed to the local repository, >pushed the github, and pulled into the other partner's local copy of the repository. Assuming that the only file you've added/modified in this step is: MidLibs.java, you would do this

Gold partner:
git add MidLibs.java	      
git commit -m "Did Step 5"
git push
Note: If you had to go back and fix a bug or something in one of the other .java files, you would add that to the "git add" line. So if, for example, you fixed a bug in Formatter.java while working on this step, you would do:
git add MidLibs.java Formatter.java
Blue partner:
git pull

Step 6: [Going Further] MidLibs

The last step is to write a program MidLibsFull.java that extends the previous MidLibs by replacing each @noun, @verb, @adjective and @nounp (plural noun) with a randomly selected word. You read the candidate words in from the files nouns.txt, nounps.txt, verbs.txt, adjectives.txt.

Note: The == sign cannot be used to test for equality between String objects. It tests for equal references, not strings. Instead, if A and B are Strings, you test for equality with A.equals(B) ... which returns true if the strings are equal, and false otherwise.

Important! Both partners will submit, and both are expected to keep their repositories sync'd so they commit the same thing! This means you need to follow the same steps as shown in the previous Step to sync your two repositories, but adapt them to the particular files you added/modified in this Step.

Submit

Both partners need to submit code but remember, through the magic of git, you should both have exactly the same thing! If not, sync your repositories and resubmit!
submit -c=IC211 -p=lab02 *.java