Preparation

In Python functions can be defined that one can call with an arbitrary number of arguments. These arguments are bundled into tuple and assigned to the parameter that is preceded by an asterisk (*) in the definition of the function. Zero or more normal arguments may occur for these variable arguments. This is illustrated in the Python session below.

>>> def sum(*terms):
...     result = 0
...     for term in terms:
...         result += term
...     return result
...
>>> sum()
0
>>> sum(1, 2, 3, 4, 5)
15

The reverse situation may also occur. Namely that arguments are already in a list or tuple but need to be unpacked before calling a function that wants them as separate positional arguments. The unpacking can be done by placing an asterisk (*) for the list or tuple that is given to the function as an argument. This is illustrated in the Python session below.

>>> terms = [1, 2, 3, 4, 5]
>>> sum(*terms)
15
>>> sum(*range(101))
5050

Look at the Python manual1 for more examples of tuple packing and tuple unpacking.

Problem

Water creates extra pressure when diving. The regulator in a tank has been specially designed to provide oxygen with the same pressure as the surrounding water pressure. That means that if a diver fills his lungs at a depth of 33 feet2 (1 foot = 0.305 metres) — where the pressure is about 2 psi (pound-force per square inch3) — he uses twice as much air as he would at the surface. A full scuba tank at 33 feet (about 10 meters) deep last half as long as it would at the surface. A bottle that would last an hour at the surface, will be empty after 20 minutes at a depth of 66 feet, where the pressure is 3 psi.

The SAC ratio (Surface Air Consumption) is an important concept among scuba divers ("SCUBA" was originally an acronym for self contained underwater breathing apparatus, but is now commonly used as a word in itself) in order to estimate how much oxygen they will use at a certain depth. The amount of air a diver breathes depends on several factors: water temperature, physical condition, manner of breathing, experience of the diver, level of effort and amount of stress. In cold conditions and low visibility, an inexperienced diver will have a significantly higher SAC ratio than an experienced diver in the same conditions.

After each dive, the amount of oxygen a diver consumes at a certain depth is normalized to his oxygen consumption at the surface. In order to do so, the following formula is used \[ \text{SAC} = \frac{33(s - f)}{t(d + 33)} \] where $$d$$ represents the depth (in feet) to which was plunged , $$s$$ is the pressure in the scuba tank (in psi) for the dive, $$f$$ is the pressure in the scuba tank (in psi) after the dive and $$t$$ is the length of the dive (in minutes). Typically, the SAC-ratio of an individual diver is leveled over multiple dives.

Assignment

Define a class Dive of which the objects have various attributes that record the data of a single dive, such as the pressure before and after the dive, the start time and end time of the dive, and the depth of the dive. Typical values ​​are an initial pressure of 3000 psi, an ultimate pressure of 700 psi, a depth of 30 to 80 feet, and a duration of 30 minutes (at 80 feet) to 60 minutes (at 30 feet). The SAC-ratio is typically between 10 and 20. The class Dive must also have a method Dive.SACratio(), which can be used to calculate the SAC ratio of that dive. The class Dive must support the following methods:

Dive.__init__(self, initialpressure, ultimatepressure, starttime, endtime, depth)

The initializaing method __init__ must ensure that objects of the class Dive are initialized with attributes that indicate the pressure at the beginning and at the end of the dive (given as floats expressed in psi), the start time and end time of the dive, and the depth of the dive (given as floats, expressed in feet). To specify data from the dive more easily, the times are given as a string of the format hh:mm. The initializing method will therefore have to use string functions in order to cut the number of hours and the number of minutes (after midnight) from the string. To determine the duration of a dive, the method must normalize time to a number of minutes since midnight based on the calculation $$uu \times 60 + mm$$. If the start and end times were converted to a number of minutes since midnight, we can subtract the two times to determine the duration of the dive (in minutes). You may assume here that there are no dives over midnight. It is also permitted to add a helper method Dive.determineDuration() to the class Dive, in which this calculation for the duration of a dive is executed.

Dive.SACratio(self)

The method SACratio prints the SAC ratio of the dive, based on the circumstances.

To represent a sequence of consecutive dives, you will also define a class Log. This log can be initialized with the data from the sequence dive, and afterwards, individual dives can also be added to the log. Based on the log, you must be able to calculated the mean SAC ratio of the diver. The class Log must support the following methods:

Log.__init__(self, *dive)

The initializing method __init__ must ensure that objects from the class Log can be initialized with a list of dives (objects from the class Dive). To add these dives as positional parameters to the initializing method, the parameter *dives, which allows parameters to be bundled in a list.

Log.newDive(self, dive)

The method newDive adds a given dive (object of the class Dive) in the back of the log.

Log.meanSACratio(self)

The method meanSACratio calculates the mean SAC ratio of a diver over all dives in his log, and print the mean result.

Example

>>> dive = Dive(3100, 1300, '11:52', '12:45', 35)
>>> dive.SACratio()
16.4816870144
>>> dive = Dive(2700, 1000, '11:16', '12:06', 40)
>>> dive.SACratio()
15.3698630137
>>> dive = Dive(2800, 1200, '11:26', '12:06', 60)
>>> dive.SACratio()
14.1935483871
>>> dive = Dive(2800, 1150, '11:54', '12:16', 95)
>>> dive.SACratio()
19.3359375

>>> log = Log(
...     Dive(3100, 1300, '11:52', '12:45', 35),
...     Dive(2700, 1000, '11:16', '12:06', 40),
...     Dive(2800, 1200, '11:26', '12:06', 60)
... )
>>> log.meanSACratio()
15.3483661384
>>> log.newDive(Dive(2800, 1150, '11:54', '12:16', 95))
>>> log.meanSACratio()
16.3452589788