Programming and Algorithms II Degree in Bioinformatics Fall 2018 ***************************************************************** *** Lab 5: *** *** Classes, objects, and inheritance, 1. The Hospital *** ***************************************************************** Part 1: Create a class patient. A patient has the following attributes: - id: an identifier, a string that uniquely identifies that person. - name: another string - sex: a string, assumed to be "M", "F", or "X" (you don't have to check that no other patient object with the same id has been created. Just assume this is so). Make a creator operation which takes values for the three attributes. To simplify, assume that id and name can be accessed as attributes- (it is unlikely that they are implemented in any way other than attributes). For sex, we want to control that it can only take any of the three mentioned values; or that they are not set in lowercase, to avoid inconsistencies. So implement a @property called sex (to get the value of the attribute) and a corresponding setter method that checks that its parameter is one of "M", "F", "X", and if not prints an error value and sets it to the default "F". You can start with the skeleton given in patient.py. Create the property and setter for sex and make sure that sex is accessed property. Test your class with a few trials. Create patient variables with various parameters, then print their attributes. Check that you can't assign weird values to sex. Part 2: Create a class paying_patient. Some patients are covered by the social security, so they do not pay. Paying_patients are covered by some private insurer, and the hospital must send a bill to their insurance company They have additional attributes: - insurance: a string encoding the insurance company that pays for the patient - bill: a nonnegative float encoding the value of the bill for this patient. Again, assume that they can both be accessed as attributes. The creator will have (besides id, name, and sex) a parameter insurance. The bill is not in the creator, as the cost of the stay is usually not known when the patient is created. Put your class in patient.py as well. Test the new class with a few trials. Part 3: Create a class hospital similar to the one in the explanation given in theory. It should have the following methods: - __init__(f,n): creates a hospital with f*n empty rooms, n < 100 f denotes the number of floors; n denotes the number of rooms per floor. Room number 1356 is number 56 of floor 13. Room number 56 is in floor 0. - admit(p): admits patient p and puts it in some free room. It returns the number of the room. It returns -1 if the patient was not admitted because there was no room. It returns -2 if a patient with the same identifier as p was already in the hospital. - release(s): releases the patient with identifier s. It returns True if ok, False if no patient with identifier s is in the hospital. - transfer(s,r): transfers the patient with identifier s to room r. It returns -1 if room r was not free. It returns -2 if no patient with identifier s is currently in the hospital. Add also the three following @properties, without setters because they should not be changeable from the outside: - nrooms: returns the total number of rooms in the hospital. - nfloors: retuns the number of floors in the hospital. - nfree: returns the number of free rooms in the hospital. You can start with the skeleton hospital.py provided. Test your class with the help of the class menu.py provided with this lab. Please take some time to understand menu.py. Note the two lines at the end which create a menu and execute it. In general, try to make all operations except perhaps __init__ work in O(1) time (meaning: constant independent of n and f). DO NOT LOOK YET AT PART 4 WHEN DECIDING THE IMPLEMENTATION OF hospital! Part 4: After your teammates try your class, they miss a couple of operations: - find_room(s): it happens often that friends and family arrive to the hospital to see someone. They know the person's name, but not his/her identifier (do you know the DNI of your friends?). find_room returns a list with the rooms where there is currently someone with name s. Note that while identifiers are assumed to be unique, it happens often that different people have the same name. If the list is empty, nobody with that name is in the hospital. - close(f): assuming that there is no patient in floor f, it closes the floor (for example, because there is some maintenance, or because there is a serious infection there). It returns True if the operation succeeds, or False if it could not be completed because some patient is still there (the manager should first transfer or release all those patients). Closing a floor means that until it is open again, no patients can be admitted to the floor. - open(f): it reopens the floor. It does nothing if it was already open. - list_patients(r1,r2): prints to terminals the state of all rooms between r1 and r2: for each valid room number r in [r1,r2], it prints either: r: free or r: id name sex (of the patient that occupies room r) - total_bills(): returns the sum of the bills of all the paying_patients currently in the hospital. Patients that are not paying_patients do not count. Create a class hospital2 that inherits from hospital and implements these operations. Depending on how you implemented hospital, these operations may be easier or harder to implement. You may have to add additional attributes in hospital2 to make these operations fast. Perhaps, you may even want to override some of the methods of hospital to use a totally new implementation in order to have faster operations. In general, try to make all operations except perhaps __init__ work in O(1) time. An exception is find_room, which cannot in general run in O(1) time. This is because we cannot exclude the surrealistic situation in which the hospital is full with n*f people, all with the same name. The list to be returned will have length n*f, so it can't be O(1) time. Another exception is list_patients, which should take time O(r2-r1) or so. Test the new class. You will need to change the menu.py class in order to test the new operations.