Table 1 Animal Food Chart Simulate a zoo animal feeding system in Python. Assume the system maintains a stock of food and takes care of feeding for five different animals, which are an elephant, a giraffe, a horse, a zebra, and a deer. Each of these animals has different amount of food requirements. An example of food requirements per animal is shown in Table 1. For example, at least
15 kg food is required in the food stock to feed an elephant, whenever it gets hungry. Similarly, a hungry giraffe eats 9 kg food, and so on. Feeding Task: [Requirement 1]: Animals become hungry at a random order, but one animal at a time (i.e., if an animal gets hungry and consumes food from the stock, then no other animal can access the food
stock until the hungry animal releases it.) If the required amount of food (for the hungry animal) is available in the food stock, the hungry animal is fed right away, and the food stock is updated with this food consumption. Otherwise, the animal must wait for more food to be added to the stock by the food depositing task (see below). Depositing Task: [Requirement 2]: Food is deposited to the food stock at a random amount between
1 kg and 10
kg, at a time. Concurrency: [Requirement 3]: Both tasks (Feeding Task and Depositing Task) run concurrently, but in a synchronized and co-operative manner. If the required amount of food to feed a hungry animal is not available in the stock, the Feeding Task must wait for the Depositing Task that adds food to the food stock. When the Feeding Task consumes food from the stock, the food stock should be locked to the Depositing Task. Similarly, during the time the Depositing Task adds food to the stock, the stock should be locked to the Feeding Task. After each deposit, the Depositing Task should notify (all) waiting Feeding Task for possible food consumption. Processing Feeding Data: [Requirement 4]: Your simulation should keep track of total number of animals that have been fed. It should terminate both Feeding Task and Depositing Task, after feeding
n animals (
n is the total number of animals to be fed by the system, which is entered by the user). It should also keep track of (i) total number of times each animal gets hungry, irrespective of it was fed or not (i.e., waited for food), and (ii) each total amount of food consumed by each specific animal. Also, display the summary of food consumption for all animals as shown in the sample input/output below.
[Requirement 5]: Write the simulation to demonstrate thread cooperation through implementing multiple threads. Suppose that you create and launch two threads, one adds food to the food stock (i.e., Depositing Task), and the other consumes food from the same food stock (i.e., Feeding Task). Both threads run concurrently and access the critical region as per the operations mentioned above. Few assumptions: - the initial food stock is
0Kg, - the amount of food to be deposited is randomly generated, and - the selection of animal to be fed (i.e., the amount of food to be consumed) is randomly generated. To synchronize the operations, use a condition: zoo_cond. If the food stock is less than the amount to be consumed, the Feeding Task will wait for the zoo_cond condition. When the deposit task adds food to the stock, the task signals the waiting Feeding Task to try again. The interactions between the two tasks are shown in following figure.
[Requirement 6]: You must demonstrate the use of anonymous function in your development. For example, the user input can be received and processed using lambda function. [Requirement 7]: You must use at least one class (e.g., Animal class with required attributes to process food requirement) in your program. All required information regarding an animal (e.g., name, food consumption amount, hungry count, feeding detail, etc.) should be maintained in this class. Use more classes (e.g., subclass for each type of animal), if required. Use all required mutators and accessors in your class(es). [Requirement 8]: Use a separate function that creates all the animal objects, stores them in a collection and passes it along to other functions, as required. Add your first name as part of the name of this function. [Requirement 9]: Use a separate function to compute the number of times each animal got hungry and return the animal that was hungry the greatest number of times. If there are multiple winners, return all winner animals. Add your first name as part of the name of this function. [Requirement 10]: Use a separate function to find and return the animal that consumed the highest amount of food. If there are multiple winners, return all winner animals. Add your first name as part of the name of this function.
[Requirement 11]: Document your all modules e.g., classes and functions using Python Docstring to facilitate generating a standard documentation of your entire application using PyDoc. All functions and classes must be documented with their full detail e.g., functions with complete description of tasks, parameters, return types, exceptions, etc., and classes with complete description, attributes, methods, etc. Input/Output: A sample input/output for a typical run for
n=10 is shown below. [Requirement 12]: Display your information (full name and Sheridan student id) at the beginning of input/output. [Requirement 13]: Input: Enter user input for the number of animals to be fed. [Requirement 14]: Outputs of both tasks are concurrently printed as they are operated. The 'wait for food' message is generated from the feeding task every time an animal gets hungry and there is insufficient food in the stock. The 'Add food' message is generated by the depositing task every time it adds a random amount (between
1Kg to
10Kg ) of food to the food stock. 'Feed
'
message is generated from the feeding task when an animal is fed (show the name of the animal at ). In addition, feeding task also displays the running feeding count for each animal right after it was fed. Both tasks should keep displaying above messages until n animals were fed (note: if an animal got hungry, but not fed, that animal should not be counted as fed). [Requirement 15]: After n animal is fed, the concurrent feeding and depositing tasks should terminate. Display details of food consumption information for each animal and overall result of the feeding system, as shown in the sample input/output below. If multiple animals were the winners for the hungry count and the food consumption, display the names of all the winners for respective summary. [Requirement 16]: Display the __doc__ attribute of all functions and classes in the terminal. Issue the PyDoc command on the terminal to render the documentation on your localhost server using the port x, where x is the first 4 digits of your Sheridan student id. If the port is not available, user the last 4 digits of the id. If both are not available, user a random port chosen by the PyDoc command.
Sample input/output for feeding system: Zoo Animal Feeding System Developed by: Syed Tanbeer Student number: 00000000000 Enter number of animals to be fed: 10 --.---.: Feeding Begins : Wait for food: Zibra got hungry, Not enough food. Add food: 3Kg??> Stock: 3Kg Add food: 9Kg??> Stock: 12Kg Feed Zibra: 5Kg? Stock: 7Kg Zibra feed count: 1 Add food: 1Kg? Stock: 8Kg Wait for food: Elephant got hungry, Not enough food. Add food: 2Kg? Stock: 10Kg Add food: 7Kg??> Stock: 17Kg Feed Elephant: 15Kg??> Stock: 2Kg Elephant feed count: 1 Wait for food: Zibra got hungry, Not enough food. Add food: 10Kg?> Stock: 12Kg Add food: 5Kg??> Stock: 17Kg Feed Zibra: 5Kg?> Stock: 12Kg Zibra feed count: 2 Add food: 4Kg??> Stock: 16Kg Feed Giraffe: 9Kg?> Stock: 7Kg Giraffe feed count: 1
b. Your program must work if the food requirement for each animal is changed. c. You must demonstrate the use of thread co-operation, and condition. d. You must follow the development process mentioned under Development section. e. You must demonstrate code modularization. f. You must demonstrate Python code writing standard in your code.