Problem 3

Parse the file containing the list of bonus flying miles.

Here is an example:

Michaela Meier
LX326 05.12.2016 ECONOMY
LX317 10.01.2017 ECONOMY
A3851 12.05.2017 BUSINESS
LX8 12.10.2017 FIRST 4433
.
Stefan Oliver Schmid
LX4150 19.10.2017 BUSINESS 6404
.

The list consists of blocks. Each block begins with the name of the flier. The name is then followed by the list of flights. For each flight, the flight number, the flight date (in dd.mm.yyyy), the class of the flight (“ECONOMY”, “BUSINESS”, “FIRST”) are given. If it is an inter-continental flight, the number of miles follows the class of flight.

If no miles are given, you can assume a “flat-rate” of 125 miles. The miles flown in “BUSINESS” are counted double and the miles in “FIRST” triple, respectively.

Output the number of miles per person.

For the aforementioned example:

Michaela Meier: 13799
Stefan Oliver Schmid: 12808

Classes:

ClassOfFlight(value)

Enumerate the different classes of flights.

Flight(number, date, class_of_flight, miles)

Represent an entry in the flight data.

Block(name, flights)

Represent a block of flight entries tied to the flier.

Data:

STR_TO_CLASS_OF_FLIGHT

Map literal value 🠒 enumeration.

FLIGHT_RE

Express the flight entry in the text data.

Functions:

compile_flight_re()

Compile the regular expression that expresses the flight entry in the data.

parse_block(lines)

Parse the given block of the input data given as text lines.

parse(lines)

Parse the input data given as text lines into structured blocks.

compute_totals(blocks)

Compute the total miles collected by the flier.

class ClassOfFlight(value)[source]

Enumerate the different classes of flights.

Attributes:

ECONOMY

BUSINESS

FIRST

ECONOMY = 'ECONOMY'
BUSINESS = 'BUSINESS'
FIRST = 'FIRST'
STR_TO_CLASS_OF_FLIGHT: Mapping[str, ClassOfFlight] = {'BUSINESS': ClassOfFlight.BUSINESS, 'ECONOMY': ClassOfFlight.ECONOMY, 'FIRST': ClassOfFlight.FIRST}

Map literal value 🠒 enumeration.

class Flight(number: str, date: date, class_of_flight: ClassOfFlight, miles: Optional[int])[source]

Represent an entry in the flight data.

Methods:

__init__(number, date, class_of_flight, miles)

Initialize with the given values.

__init__(number: str, date: date, class_of_flight: ClassOfFlight, miles: Optional[int]) None[source]

Initialize with the given values.

Requires
  • miles is not Nonemiles > 0

Ensures
  • miles is Noneself.miles == 125

    (If miles is not given, set to the default value.)

class Block(name: str, flights: Sequence[Flight])[source]

Represent a block of flight entries tied to the flier.

Methods:

__init__(name, flights)

Initialize with the given values.

__init__(name: str, flights: Sequence[Flight])[source]

Initialize with the given values.

compile_flight_re() Pattern[source]

Compile the regular expression that expresses the flight entry in the data.

FLIGHT_RE = re.compile('^(?P<number>[a-zA-Z0-9]+) (?P<date>[0-9]{2}.[0-9]{2}.[0-9]{4}) (?P<class_of_flight>ECONOMY|BUSINESS|FIRST)( (?P<miles>[0-9]+))?$')

Express the flight entry in the text data.

parse_block(lines: Lines) Block[source]

Parse the given block of the input data given as text lines.

Requires
  • all(FLIGHT_RE.match(line) for line in lines[1:])

  • len(lines) >= 1

Ensures
  • len(lines) == 1len(result.flights) == 0

  • result.name == lines[0]

parse(lines: Lines) List[Block][source]

Parse the input data given as text lines into structured blocks.

Ensures
  • len(lines) > 0len(result) > 0

  • len(lines) == 0len(result) == 0

compute_totals(blocks: List[Block]) MutableMapping[str, int][source]

Compute the total miles collected by the flier.

Returns

Flier name 🠒 miles collected

Ensures
  • len(blocks) != 0len(result) > 0

  • set(block.name for block in blocks) == set(result.keys())

    (All people considered)

  • all(value >= 0 for value in result.values())