CSCI 2300 Data Structures and Algorithms Spring 2000
Lab 7: Program Design
 

In this lab we will explore some aspects of  program design using project1 . Since all of you have already submitted your solutions to this project, this lab will review the elements of good class design, which can greatly simplify the complexity of the code. The main data structure used in this project is the Linked-List, which everyone understands. The difficulty of the code comes from the complex interactions among the different objects in the program, which include Animals, Cages, the scheduled and waiting list, and the List of Cages. Careful design, by paying attention to the functionality to be coded within each object, is crucial in successfully solving this project. This also happened to be the problem that most of you faced, i.e., how to untangle the links among the various objects.

Let's see what a good program design can do for the simplicity and understandibility of your code.
Work through the following steps, in order:

  1. Copy the following lab files: create a workspace and then a project that incorporates these files.
    Study each of these files carefully along with the functionality implemented within each class. The Animal class has fields for the animal name, weight, start date, duration of stay and the cage number (if scheduled). The Cage class has fields for min and max weight. It also has two arrays of 365 days -- a bool array indicating if a day is filled and an array of Animals indicating which animal occupies the given day. The Cage::Schedule routine checks if the cage is empty for a given start date and duration, and if it is then it adds the animal on the schedule.  Similarly the Cage::Cancel routine clears the bool array for the given animal. The main functionality is implemented within the Scheduler class. It maintains a vector of cages, a list of scheduled animals, and a list of waiting animals. There is one routine for each of the major commands like Schedule, Cancel, Revise and Print. The main() routine first reads the cages from the input file and adds it in the scheduler m_and_m, and then for each command it calls the appropriate routines from the Scheduler class.
     
  1. Schedule Command: Let's start with the Schedule command. The main() routine asks for an animal name and checks if it is already present in the scheduled or waiting animals. If yes, we print out an error. Otherwise it calls Scheduler::Schedule():
  2. Now write the code for the Scheduler::Schedule routine. A skeleton of the code is provided for you. You must iterate over each cage and first check if the animal is within the weight requirements for that cage. If yes,  set in_weight_range to true, and try to schedule the animal in that cage. If the animal is scheduled then also set in_schedule to true. You should not have to write extensive code for this; use the routines already provided for you in the different classes.
    (note: remember to call animal.AssignCage( CAGE NUM) to store the cage number where the animal is scheduled for a successful insertion)

    After we exit the iteration, we check if in_scheduled is true and push the animal in the scheduled list. Otherwise, we check if in_weigth_range is true, and push the animal in the waiting list (in this case the animal is within range but no cage has required dates free). Finally, if both the flags are false, it means that the animal did not fit into any cage. Note the power of modular objects. In the Schedule function we need to worry only about how we can use the functionality provided by the different classes, without having to worry how they are implemented. The greatly simplifies the coding, especially for large projects.

    After writing the code test your program on the  cages.txt  file, with the sample input file  input.txt. Ignore the cancel command when you test.
     

  3. Cancel Command: We now look at the Cancel command. In main() we first check if the animal to be canceled exists in our system. If it does, we call the Scheduler::Cancel routine. This code iterates over the cages looking for the animal (note that at this point it is known that the animal is either in the schedule or in a waiting list). If found we cancel the appointment for that animal in the cage. We then call TryFromWaitList passing the cage that was modified (was_in_cage). If the animal is not in the scheduled list then it must be in the waiting list, and we delete it from the list.

  4.  
    Now write code for the TryFromWaitList routine. The arguments consist of the cage that has been modified (so that some other animal may now be scheduled in the empty slot), and an added list that keeps track of the animals that move from the waiting list to the scheduled list. What you need to do is to iterate through the entire waiting list, trying to schedule each animal in the given
    cage. If it is scheduled then also add the animal to added, and delete the animal from the waiting list. Once again use the routines already provided for you in the class interfaces.

    After writing the code test your program on the  cages.txt  file, with the sample input file  input.txt.
     

  5. Revise Command: Study carefully the code for the Scheduler::Change routine. We first look for the animal in the scheduled list. If found, we have to check if the new dates can be scheduled. To do this we have to store the old values of the animal and cage in temporary variables. We then delete the animal from the scheduled list, and try to schedule the new dates for the animal in any of cages. If the new dates can be accommodated in any cage we set in_schedule to true and update the cage number of the animal.
  6. After trying each cage, we check if the in_schedule flag is true. If yes, it means that the revision was successful, and some dates may now be free. So we have to try to see if other animals can be scheduled from the waiting list. On the other hand if in_schedule is false, it means that the revision was not successful, and we have to restore the old status. We reschedule the old animal in old cage (using the temporary values stored earlier). Now write the code that accomplishes both these tasks. i.e., try from waiting list if any of the dates previously occupied by the animal are now free or put the old animal back in its cage if revision was not successful.

    After writing the code test your program on the  cages.txt  file, with the sample input file
    input2.txt .
     

  7. Hash Tables: Now that you are familiar with the public interfaces of each of the classes, we will try to explore a different implementation of some of the details. The fact that we are using good object-oriented coding should make this transparent to the code that uses the class routines.
  8. Delete the following files from your project

    Include the following file in your project The new Scheduler class implements the scheduled_ and waiting_ lists as Hash Table of Animal.

    Carefully study the file Hash.h and its public interface.

    Next look at the new Scheduler::Schedule routine which has been suitably modified to use the public interface of HashTable. Note that HashTable doesn't provide a push_back function, but instead provides an Insert that takes the Key (animal name) and the ElementType (animal) as its arguments.

    Next look at how we have modified the Scheduler::InSchedule routine. It uses the Find function of HashTable instead of the list find from STL. The HashTable::Find returns a pointer to a <Key, ElementType> pair. This is typedef as entry_ptr in Hash.h. In our case entry_ptr for scheduled_ and waiting_ lists points to <string, Animal> pair. If ep is of type entry_ptr, then ep->second returns the second element of the pair, i.e., the Animal. We use this to get to the Animal returned by the Find routine.

    Finally study the new Scheduler::TryFromWaitList routine. Notice how instead of directly using the STL iterator class to iterate through all the animals in the waiting_ list, we use the function HashTable::ToVector to get a vector of all the animals in the waiting list. We then iterate over this vector of exported_type. Make sure you understand what's going on here.
     

  9. Code Modification Using HashTable: You are now ready to do some modifications on your own using the HashTable implementation of the scheduled_ and waiting_ lists.
  10. Uncomment the code within the Scheduler::Cancel routine. Make appropriate changes so that the code uses the HashTable interface. Test your program on the input  input.txt
     
     Next uncomment the code within the Scheduler::Change routine. Make appropriate changes so that the code uses the HashTable interface. Test your program on the input  input2.txt
     


At the conclusion of this lab, take a moment to review the following: