CSCI142: Computer Science 2
Lab 6 - Woolie Wipeout

Introduction

The viewership at Woolie TV (WTV) has been in decline for years. Their program manager, Woolma, has come up with an idea for a new show that she thinks is going to be a slam dunk for the station. On recent holiday in Japan, Woolma became obsessed with watching their television shows. In particular, she found their versions of game shows to be irresistibly hilarious. Woolma plans to bring a translated version of the Japanese game show, Takeshi's Castle, to Woolieville. It will be called "Woolie Wipeout".

The idea behind the show is to make the normal citizens of Woolieville the stars of the show. They will be competing against one another to complete an obstacle course. The location for the show is in the iconic Cliffs of Winona. The two giant cliffs are separated below by the raging rapids of the Wailuku river. The construction crew has built a collection of giant rolling logs that spans across the two side of the cliff. Unfortunately, it is quite fragile and can only support a certain number of Woolies on it before it will collapse.

In the show, the Woolies race from the starting area to the obstacle course. The Woolies begin crossing the course based on their time of arrival. If they are next in line, and the maximum occupancy for the obstacle course has not been exceeded, they are allowed to cross. Because the show casts Woolies of all ages and physical conditions, they will take a different amount of time to cross the course.

While the Woolies cross the course, some will undoubtedly fall. In the event this happens, the fallen Woolies must make their way from the water, to the shore, and eventually to the back of the line of Woolies waiting to cross. As soon as a Woolie falls, the logs stop rolling. The Woolies currently crossing are "air lifted" by The Kraken's many arms and inserted into the back of the waiting line, with their crossing time reset.

The shows producer thought it would be more riveting if the Woolies that fell into the river had nothing but their wits and courage to safely make it to shore. The legal department thought otherwise and mandated that all Woolies crossing the course be equipped with life preservers to prevent lawsuits from the family members of Woolies who drown to death.

The request for life preservers threw the production company into the red. They already had spent a large portion of their budget sewing up a deal with a memorable face to host their show - the infamous octopus from the West Sea - The Kraken. Because of this, they had to cut corners on the quality of the life preservers they would use in the show. For one, the air capacity of the preservers is varied (by volume). Even worse is how badly the preservers hold air. Once blown up to full capacity, the preservers would slowly lose air over time - eventually resulting in a useless piece of plastic.

These life preserver problems threatened to ruin the concept of the show unless it was handled properly. Due to a loophole in the fine print of The Kraken's contract, the producer forced The Kraken to handle the life preserver situation. The Kraken must keep the life preservers distributed to the Woolies in "good shape". This means that no Woolie would ever be given a preserver that wouldn't last the time it takes for them to cross the course, or fall into the river and make it to shore.

And so, the Woolie Wipeout game show became a reality. It was a huge hit with the audience and brought WTV back to the number one spot in the ratings. Your job in this lab is to recreate the game show as a simulation that documents the struggle of the Woolies on the obstacle course. To achieve this, you will tap into your new found knowledge of multi-threaded programming.

Design

This is a visual diagram of the design of the lab:

There are five classes in the design. A brief description of each class and its documentation follows.

Implementation

Starter Code

If you did not already get the GitHub link for this assignment please see your instructor.

First Run

You should be able to run the provided code to completion. The Woolies are not implemented yet so they do nothing. The main program is run with two arguments:

  1. numWoolies: the number of Woolies in the simulation
  2. maxOnCourse: the maximum number of Woolies allowed on the course at once

If you run the program as follows:

    java WoolieWipeout 0 0

The simulation should run and you should see the following output. Here, SIM refers to messages that correspond to the main class, and KRAKEN refers to messages from the host. The host also displays the state of the OBSTACLE_COURSE while running.

What To Do

You will be focusing on implementing the Woolie thread class and the portion of code that the Woolies need to interact with in the ObstacleCourse class.

Keep in mind there is a separate thread class, Kraken, that you are not allowed to change. You must cooperate with it and follow the rules of the game in order to prevent a deadlock scenario from occurring. Additionally, you will be interacting with the Preserver class, which you should not change. And finally, the main class WoolieWipeout should not be modified.

Simulation Overview

This is a high level overview of how the simulation flows for the main class and run methods for Kraken and Woolie.

WoolieWipeout

  1. The Kraken, the obstacle course, and the entire collection of Woolies are created.
  2. The Kraken thread is started.
  3. The Woolie threads are all started.
  4. All the Woolie threads are joined on.
  5. The obstacle course is closed.
  6. The Kraken thread is joined on.
  7. The results of the simulation are displayed, e.g. the final state of the Woolies, the Woolies that fell the most, and the state of the life preservers.

Kraken

  1. The obstacle course is turned on.
  2. While the course is open, The Kraken does the following:
    1. The course is checked to see if a Woolie fell. If so:
      1. The course is turned off.
      2. While the course has Woolies on it, The Kraken waits.
      3. Once all Woolies have left the course, it is turned back on.
    2. The Kraken temporarily sleeps
  3. When the course closes, The Kraken turns off the course.

Woolie

  1. The Woolie requests entrance to the course. They are not granted it until the course is running, there is room on the course, and they are at the front of the waiting line. Once access is granted, they get a preserver from The Kraken.
  2. The Woolie enters a loop to cross, for each unit of time, until they have completely crossed.
    1. If the course isn't running, it means another Woolie just fell. The Woolie should reset their crossing time, return the preserver to The Kraken, and then leave and re-enter the course.
    2. Otherwise, the Woolie should cross for one unit of time:
      1. The preserver is used.
      2. The Woolie rolls the dice and sees if they fall or not.
      3. If the Woolie falls off, the following things happen:
        1. A message about falling is printed (see javadoc for the run method).
        2. The Woolie indicates to the course that they fell off.
        3. The Woolie increases its fall count.
        4. The crossing time is reset.
        5. The Woolie exits the course, returns the preserver to The Kraken, and re-enters at the back of the line.
      4. If the Woolie does not fall, the following happens:
        1. A message about crossing is printed (see javadoc for run method).
        2. The crossing time is reduced.
        3. The Woolie goes to sleep temporarily.
  3. The Woolie indicates to the obstacle course that they are leaving and the other Woolie's waiting are signaled to wake up and check if they can now cross. They also return their preserver to The Kraken.

Avoiding Deadlock

When a Woolie falls off the course, they indicate it to the ObstacleCourse class. The Kraken will periodically wake up and check to see if anyone has fallen. If they have, The Kraken turns off the course. This is the signal to any Woolies currently crossing that they must back up off the course, reset their crossing time, and enter the back of the queue.

This is a demonstration of the correct behavior for dealing with the falling scenario. In this example, there are 4 Woolies and 4 are allowed on the course.

    KRAKEN: A Woolie has fallen!  Turning off course...
    OBSTACLE_COURSE: ObstacleCourse(maxOnCourse=4, numOnCourse=4, fallenWoolie=true, running=false, open=true, wooliesWaiting=0)
    KRAKEN: A Woolie has fallen!  Waiting for Woolies to exit course...
    KRAKEN: OBSTACLE_COURSE: ObstacleCourse(maxOnCourse=4, numOnCourse=4, fallenWoolie=true, running=false, open=true, wooliesWaiting=0)
    KRAKEN: A Woolie has fallen!  Waiting for Woolies to exit course...
    KRAKEN: OBSTACLE_COURSE: ObstacleCourse(maxOnCourse=4, numOnCourse=4, fallenWoolie=true, running=false, open=true, wooliesWaiting=0)
    WOOLIE: Woolie_3(total=4, remaining=4, fallen=0, preserver=Optional[Preserver(id=3, buoyancy=7)]) leaves course
    KRAKEN: Woolie_3 returns Preserver(id=3, buoyancy=7)
    WOOLIE: Woolie_1(total=9, remaining=9, fallen=0, preserver=Optional[Preserver(id=1, buoyancy=15)]) leaves course
    KRAKEN: Woolie_1 returns Preserver(id=1, buoyancy=15)
    WOOLIE: Woolie_1(total=9, remaining=9, fallen=0, preserver=Optional.empty) enters line
    WOOLIE: Woolie_2(total=5, remaining=5, fallen=0, preserver=Optional[Preserver(id=2, buoyancy=14)]) leaves course
    KRAKEN: Woolie_2 returns Preserver(id=2, buoyancy=14)
    WOOLIE: Woolie_2(total=5, remaining=5, fallen=0, preserver=Optional.empty) enters line
    WOOLIE: Woolie_3(total=4, remaining=4, fallen=0, preserver=Optional.empty) enters line
    WOOLIE: Woolie_4(total=8, remaining=8, fallen=1, preserver=Optional[Preserver(id=4, buoyancy=7)]) leaves course
    KRAKEN: Woolie_4 returns Preserver(id=4, buoyancy=7)
    WOOLIE: Woolie_4(total=8, remaining=8, fallen=1, preserver=Optional.empty) enters line
    KRAKEN: All Woolies have exited course!  Restarting course...

It is possible that a Woolie may cross in the time between a Woolie falls, and The Kraken wakes up and turns off the course. But once the course is turned off, no Woolie's should continue to cross until they have all cleared off the course. During this time, the Woolie waiting at the front of the line should continue to wait until the course is started up again.

Life Preserver & Optional

The life preserver that the Woolie holds is wrapped in an Optional. Optional is a way to avoid having to use null and potentially run into the null pointer exception.

Instead of using null, if the Optional holds no preserver, it should be set to Optional.empty(). Otherwise it can be set using Optional.of(...), where ... is a non-null instance of a Preserver object.

To check if the Optional holds a Preserver, use the isPresent() method. It returns true if it holds a Preserver, and false if not.

To extract the Preserver from the Optional, use the get() method. It returns the Preserver stored within.

The Kraken will never give a Woolie a life preserver that does not have enough air in it for them to cross. When a Woolie returns a preserver, if it has no air left in it, it is destroyed. Otherwise it is pushed onto the front of a stack of preservers. While in the stack, the preservers continue to maintain the same amount of air they had in them when they were first added. When a Woolie requests a preserver, the Kraken first checks the top of the stack. If that preserver has enough air in it, he returns it to them. Otherwise he creates a new preserver that has at least enough air for that Woolie to cross.

Sample Runs

Several sample runs with a different number of Wolies and a maximum number on course are provided. Keep in mind that due to the execution of the threads, and the random state, that no two runs are ever guaranteed to display even remotely the same order of output.

Roadmap

This is the suggested approach for how you should implement this lab.

  1. Implement the constructor for Woolie.
  2. Add a statement to the Woolie's run() method that just prints out the Woolie. It should now run to completion with each Woolie completing the course (with no falling or life preservers used).
  3. Add a loop to the method that simulates the crossing, without interacting with ObstacleCourse yet. In the loop it should simply print the Woolie, decrement the crossing time, and sleep.
  4. Implement things so that the Woolies can cooperate and cross the course. The Woolies will never fall and they don't need to use a Preserver. Run this with a differing number of woolies and maximum on course to assure yourself things are working correctly.
  5. Add in the ability for a Woolie to fall when crossing. Again, do not worry about dealing with Preserver.
  6. Add in the ability for the Woolie to work with the preserver.

Lecture Notes

You should review the lectures notes from this week that are posted here. Also make note of the zip file that contains all the source code from lecture. In particular, the second producer consumer example shows the basics of the thread cooperation you will need to use in this lab.

Grading

The grade breakdown for this lab is as follows:

Submission

Zip your your entire src folder and name the zip file lab6.zip. Upload your zip file to the MyCourses dropbox by the deadline.