XMUT103
Assignment 3: Using Collections and Recursion

days Due 20 April , 19 pm

Download zip file of necessary code and data and extract it to an Assig3 folder (eg, in a COMP103 folder in your home folder). It should contain templates for the Java programs that will be marked.

ALERT! Important note about the style of your code.

To submit

  • HospitalERCore.java
  • Patient.java
  • HospitalERCompl.java and Department.java (for the completion)
  • MineSweeper.java

ALERT! Do not rename these files.

Remember to submit all of these files. When you have submitted them, check that you can read the files listed on the submission page, and complete the submission process.

Part 1: Hospital ER (Weight: 70%)

tip The specification of this problem is quite long and detailed. Read it carefully! You cannot do this assignment just based on comments in the template code.

The HospitalER program is a tick-based simulation of patients arriving at the emergency room of a hospital. Patients arrive, wait for treatment, get treated, then are discharged.
  • For the core version, there is just one waiting room and one treatment room, and patients only need one treatment.
  • For the completion version, patients move through a series of treatments in different departments - ER, X-ray, MRI, Operating Theatre, etc. Each department has its own waiting room and treatment room. When patients have finished all their treatments, they are discharged.

A treatment room only has facilities to treat a fixed number of patients at any one time; if the treatment room is full, any new patients arrive for that treatment have to wait in the waiting room until there is a space.

Patients can have different priorities (from 1 (the highest priority) to 3), which are assigned when they arrive at the emergency room.

(Note, this program is related to the MedicalCenter program in the lectures, but is more complex.

The Core version of the program has four classes:
  • HospitalERCore which contains
    • fields to hold collections of Patients for the waiting room and the treatment room, fields to hold the statistics, and fields with parameters for the simulation.
    • a main(...) and setupGUI() methods (completed for you).
    • a reset(...) method [incomplete] which will reset the simulation, the waiting room, the treatment room, and all the fields for the statistics.
    • the run() method [incomplete] for the simulation
    • several pre-written methods, including setupGUI() and a redraw() method that visualises the state of the simulation for you.

  • Patient [almost complete] which contains information about an individual patient. This includes the treatment plan: the sequence of treatments they need and how long each treatment will take. Note that the core version of the simulation ignores everything beyond the first treatment.
    The Patient object keeps track of the current treatment - the treatment they are currently undergoing (or are about to start) and the remaining time for that treatment.
    It has methods for accessing fields, comparing Patients [incomplete], and drawing Patients
    It has methods for moving the Patient through the simulation:
    • waitForATick(): makes patient wait for one tick.
    • advanceCurrentTreatmentByTick(): removes one time tick from the remaining time for the current treatment.
    • currentTreatmentFinished(): whether the Patient has finished their current treatment.
    • removeCurrentTreatment(): [completion] Remove the current treatment from the queue of treatments the Patient needs.
    • getCurrentDepartment(): [completion] gets the name of the department for the current (or about-to-start) treatment.
    • allTreatmentsCompleted(): [completion] whether the Patient has completed all their treatments.

  • Treatment [complete] which is a small class for describing a treatment, with the name of the department where the treatment will happen and how much longer the treatment will take. Patients contain a queue of Treatments they need to undergo.

  • PatientGenerator [complete] which can generate new random patients (with random names, priorities, and treatment plans).
    • It has a static method getNextPatient() which will return either null, if no new Patient has arrived, or a new Patient object with randomly generated values.

The Completion version of the program has five classes
  • Patient, Treatment, and PatientGenerator, just as in the core.

  • HospitalERCompl [incomplete] which contains
    • a field containing a collection of Department objects, representing the different treatment centers in the hospital.
    • The same methods as the core version, but the reset(...) and run() methods will be more complicated.

  • Department [incomplete] which contains information about one department of the hospital. It will need
    • Fields to hold
      • The Set of patients currently being treated (and the maximum size of this set)
      • The queue of patients waiting to be treated.
    • Methods to
      • Add a patient to the department.
      • Return the collection of waiting patients.
      • Return the collection of patients being treated.
      • Move patients from the waiting room to the treatment area, if there are any spaces.
      • Remove a patient from the department (because they have completed their treatment)
    • The method to draw a graphical representation of the patients in the department is already comlpeted for you.

Note that the GUI of both versions of HospitalER has four buttons for resetting, running, and pausing the simulation. It also has sliders to control some of the parameters of the simulation, such as the speed of the simulation, how often new patients arrive, and the relative frequency of the different priority patients.

Core:

Complete the HospitalERCore class and the compareTo method in the Patient class so that it simulates patients coming to the emergency room, and reports on basic statistics.

The following image shows what the hospital might be like when a new patient (N) arrives, then after the patient has been put in the waiting room, and then a bit later when patient A finishes their treatment:

HospitalER-core.png

  1. Complete the reset method to set up waitingRoom to have a queue of patients and treatmentRoom to have a set of Patients.
  2. Complete the run method. Each loop of the run() method represents one tick of time. The method should:
    • Advance the time by one "tick"
    • Find all patients in the treatment room who have finished their current treatment and discharge them (remove them from the treatment room). For debugging, it is helpful to print a message for each patient when they are discharged: UI.println(time+ ": Discharge: " + p);
    • Process one time tick for each patient currently being treated, or waiting in the waiting room.
    • Move patients from the waiting room to the treatment room if there is space.
    • Get any new patient that has arrived and adds them to the waiting room [complete].
    • Display the state of the waiting room and treatment room [complete].
  3. Add fields to record basic statistics, extend the run() method to update the statistics when a patient is discharged, and complete the reportStatistics() method to report:
    • The total number of patients treated
    • The average waiting time of the patients
  4. Make the waiting room act as a priority queue taking into account the priority of the patients.
    • Extend the reset method to use a priority queue if the argument to the method is true, and a regular queue if the argument is false.
    • Complete the compareTo method in the Patient class so that a Patient with a higher priority is ordered before a Patient with lower priority. Patients with equal priority should be ordered by their time of arrival.
    • Add fields, and modify the run() and reportStatistics methods to also report
      • The total number of priority 1 patients treated,
      • The average waiting time of the priority 1 patients

Run some tests to see whether using the priority queue improves the waiting time for priority 1 patients.

Completion:

The Core version of the simulation is not realistic, since patients often need a sequence of treatments, including Surgery, X-rays, MRI, or ultrasound, in addition to treatment in the emergency room itself. The simulation should have a collection of departments, where each department provides a different kind of treatment. When a patient finishes one treatment, they then need to move on to their next treatment, until they finally finish all the required treatments and can be discharged. When a Patient object is created, the sequence of treatments (and how long they will take) is worked out by PatientGenerator.getNextPatient.

Each department will have limited facilities so each department will have its own waiting room and treatment room. For example, the state at some time tick might be the following:

HospitalER-completion.png

Extend your program to handle the more realistic simulation.

  • Complete the Department class, (as described above). Note that the constructor has three parameters: the name of the department, the maximum number of Patients in its treatment room, and whether the waiting room is run as an ordinary queue or a priority queue.
    Note: The template for Department is pretty empty: You will need to decide what methods to define to make the class useful.

  • Copy your code from HospitalERCore.java into HospitalERCompl.java but then modify it to use a collection of Departments, instead of a single treatment room and wating room.

  • Make the run() method in your HospitalERCompl class do the following:
    • Advance the time by one "tick"
    • Run through all the departments to find all patients who have finished their current treatment:
      • remove them from their current department,
      • remove the current treatment from their treatment plan,
      • If they have completed all their treatments: discharge them
      • If not, move them to the next department according to their treatment plan.
    • Process one time tick for each patient currently being treated in each department or waiting in the waiting room.
    • For each department, move patients from the waiting room into the treatment room, if there are any spaces.
    • Get any new patient that has arrived and add them to the appropriate department for their first treatment.

Challenge:

The goal of a simulation like this is to be able to evaluate and/or design a real system. For the EmergencyRoom, we might want to find out how well it is performing (How long do patients have to wait? Are critical patients at risk because of having to wait too long? Which departments get overloaded and need more facilities? etc), or we might want to find out what kinds of situations (arrival rates, distributions of priorities, kinds of injuries) would stress the emergency room.

Add more record keeping and more reporting to the system to allow a user to evaluate how well the emergency room functions under various different situations. You will need to make the Patient class print more useful information, and possibly record more information. You will also need to complete the reportStatistics method to produce a useful report, preferably with graphical information as well as text, of the performance of the emergency room.

You may need to modify the GenerateRandomTreatments method in PatientGenerator to allow the user to vary the kinds of patients.

The challenge is essentially a Data Science task, of writing code that generates data and presents/visualises in a way that is useful to a human analyst. This is a very common purpose of simulation programs.

Part 2: Minesweeper Game (Weight: 30%)

Minesweeper is a very old video game in which the player tries to work out where the mines are hidden on a grid. Each square in the grid starts off as hidden (dark blue). The player can mark any hidden square that they think contains a mine, and can expose any hidden square that they think is safe.
  • If the player exposes a square with a mine, they lose and the game is over. In this case, all the squares are opened up so that the player can see where all the mines are.
  • If the player exposes a safe square that is next to one or more mines, then the square displays a number saying how many of the eight surrounding squares contain a mine.
  • If the player exposes a safe square that is not next to a mine, then it "spreads" to all the connected squares that are also safe, and exposes them also.

The Minesweeper class has code for most of the program, except for the key methods of
  • mark(row, col): [incomplete] The player has clicked on a square to mark it.
  • tryExpose(row, col): [incomplete] The player has clicked on a square to expose it. Check first if it is a mine, or is already marked or exposed.
  • exposeSquareAt(row, col): [incomplete] The square at (row,col) isn't a mine. If it isn't exposed already, expose it now and if it has no adjacent mines, spread the exposing to all 8 neighbouring cells (recursively).
  • hasWon(): [incomplete] Check whether the player has won the game yet : have all the squares without a mine been exposed. It doesn't matter whether the squares with a mine have been marked or not.

The Square class has code for individual squares; you need to use it, but you should not modify it.

Core and Completion:

Complete the four incomplete methods in Minesweeper in order to make the game work.

Challenge

Construct an AI helper that helps you play the game and does all the hard work for you. Of course, it should only be able to see what the player can see, rather than cheat by looking inside the game.

Write a non-cheating method that can do what a good player would:
  • It should be passed an 2D array of integers representing the visible state of the Minesweeper board. It should have -1 for each hidden square, 0 for each empty exposed square, and 1 - 8 for each exposed square that has adjacent mines.
  • It should then work out which of the hidden squares are safe to expose and which of the hidden squares should be marked.

To test your AI helper, you will need to get the grid of numbers for the visible state, and then draw the recommended actions on the board.