Instructions
Requirements and Specifications
Source Code
AIRLINE SERVICE
import typing
from typing import List
from typing import Set
from datetime import datetime
from airline import AirlineError, CabinClass
from airline import Airline
from airline import Aircraft
from airline import Flight
class AirlineService:
def __init__(self):
self.airlines = []
self.aircrafts = {}
self.flights = []
def add_airline(self, airline):
if airline in self.airlines:
raise DuplicateAirlineCodeError
self.airlines.append(airline)
self.aircrafts[airline] = []
def get_airline_by_code(self, iata_code: str):
airline = None
for a in self.airlines:
if a.get_code() == iata_code:
airline = a
break
return airline
def get_aircraft_by_code_name(self, iata_code: str, name: str):
airline = None
for a in self.airlines:
if a.get_code() == iata_code:
airline = a
break
if airline is None:
return None
aircraft = None
for a in self.aircrafts[airline]:
if a.get_name() == name:
aircraft = a
break
return aircraft
def add_aircraft(self, aircraft: Aircraft):
airline = aircraft.get_airline()
if airline not in self.airlines:
raise AirlineDoesNotExistError
for ac in self.aircrafts[airline]:
if ac.get_name() == aircraft.get_name():
raise DuplicateAircraftNameError
self.aircrafts[airline].append(aircraft)
def add_flight(self, flight: Flight):
airline = flight.get_airline()
if airline not in self.airlines:
raise AirlineDoesNotExistError
if flight.get_aircraft() not in self.aircrafts[airline]:
raise AircraftDoesNotExistError
self.flights.append(flight)
def reset(self):
self.airlines.clear()
self.aircrafts.clear()
self.flights.clear()
def find_routes(self, origin: str, destination: str, dep_time: datetime, cabin_class: CabinClass, num_passengers: int):
visited = set()
start_flights = self.find_start_flights(origin, dep_time)
if len(start_flights) == 0:
return None
result = []
for f in start_flights:
visited = set()
visited.add(origin)
visited.add(f.get_dest_airport())
self.find_dfs(f.get_dest_airport(), destination, [f], result, visited)
return result
def find_dfs(self, curr_airport: str, dest_airport: str, curr_flights: List[Flight], result: List[List[Flight]], visited: Set[str]):
if curr_airport == dest_airport:
copy = list(curr_flights)
result.append(copy)
return
last_flight = curr_flights[-1]
for f in self.flights:
if last_flight.get_dest_airport() != f.get_origin_airport():
continue
fdt = f.get_dep_time()
shift = fdt - last_flight.get_arr_time()
if shift.total_seconds() <= 0:
continue
curr = f.get_dest_airport()
if curr in visited:
continue
visited.add(curr)
curr_flights.append(f)
self.find_dfs(curr, dest_airport, curr_flights, result, visited)
del curr_flights[-1]
visited.remove(curr)
def find_start_flights(self, origin, dep_time):
result = []
for f in self.flights:
if f.get_origin_airport() != origin:
continue
fdt = f.get_dep_time()
shift = dep_time - fdt
if shift.days > 1 or shift.days < -1:
continue
result.append(f)
return result
class DuplicateAirlineCodeError(AirlineError):
def __init__(self):
super().__init__("ERROR: airline with such code already exists")
class AirlineDoesNotExistError(AirlineError):
def __init__(self):
super().__init__("ERROR: airline with given code does not exist")
class DuplicateAircraftNameError(AirlineError):
def __init__(self):
super().__init__("ERROR: aircraft with such name already exists in the airline")
class AircraftDoesNotExistError(AirlineError):
def __init__(self):
super().__init__("ERROR: aircraft with given name does not exist")
AIRLINE
import typing
from typing import Dict
from typing import List
from enum import Enum
from datetime import datetime, timedelta
class AirlineError(Exception):
pass
class Airline:
def __init__(self, name: str, code: str):
if name is None or len(name) == 0:
raise AirlineEmptyNameError
self.name = name
if code is None or len(code) == 0:
raise AirlineEmptyCodeError
self.code = code
def get_name(self) -> str:
return self.name
def get_code(self) -> str:
return self.code
def __hash__(self):
return hash(self.code)
def __eq__(self, other):
if not isinstance(other, Airline):
return False
return self.code == other.get_code()
class AirlineEmptyNameError(AirlineError):
def __init__(self):
super().__init__("ERROR: empty airline name")
class AirlineEmptyCodeError:
def __init__(self):
super().__init__("ERROR: empty airline code")
class CabinClass(Enum):
F = 1,
J = 2,
Y = 3,
W = 4
class RowStructure:
def __init__(self, sections: List[int]):
if len(sections) == 0:
raise InvalidRowStructureError
self.sections = list(sections)
n = 0
for i in self.sections:
if i <= 0:
raise InvalidRowStructureError
n += i
self.seat_num = n
def get_seat_num(self) -> int:
return self.seat_num
class InvalidRowStructureError(AirlineError):
def __init__(self):
super().__init__("ERROR: cabin row structure is invalid")
class Cabin:
def __init__(self, cc: CabinClass, rs: RowStructure, row_num_from: int, row_num_to: int):
if cc is None:
raise EmptyCabinClassError
self.cabin_class = cc
if rs is None:
raise EmptyCabinClassError
self.row_structure = rs
if row_num_from <= 0 or row_num_to < row_num_from:
raise InvalidRowNumberError
self.row_start = row_num_from
self.row_end = row_num_to
def get_row_start(self):
return self.row_start
def get_row_end(self):
return self.row_end
class EmptyCabinClassError(AirlineError):
def __init__(self):
super().__init__("ERROR: no cabin class specified for cabin")
class EmptyRowStructureError(AirlineError):
def __init__(self):
super().__init__("ERROR: no cabin row structure specified for cabin")
class InvalidRowNumberError(AirlineError):
def __init__(self):
super().__init__("ERROR: cabin row numbers are invalid")
class Aircraft:
def __init__(self, airline: Airline, name: str, cabins: List[Cabin]):
if airline is None:
raise AircraftEmptyAirlineError
self.airline = airline
if name is None or len(name) == 0:
raise AircraftEmptyNameError
self.name = name
if cabins is None or len(cabins) == 0:
raise AircraftEmptyCabinsError
for i in range(len(cabins)):
c1 = cabins[i]
for j in range(i-1):
c2 = cabins[j]
if (c1.get_row_start() * c2.get_row_start()) * (c1.get_row_end() * c2.get_row_start()) <= 0:
raise CabinRowIntersectionError
if (c1.get_row_start() * c2.get_row_end()) * (c1.get_row_end() * c2.get_row_end()) <= 0:
raise CabinRowIntersectionError
self.cabins = list(cabins)
def get_airline(self) -> Airline:
return self.airline
def get_name(self) -> str:
return self.name
def __hash__(self):
return hash(self.get_airline().get_code() + '_' + self.get_name())
def __eq__(self, other):
if not isinstance(other, Aircraft):
return False
return self.airline == other.get_airline() and self.name == other.get_name()
class AircraftEmptyAirlineError(AirlineError):
def __init__(self):
super().__init__("ERROR: no airline specified for the aircraft")
class AircraftEmptyNameError(AirlineError):
def __init__(self):
super().__init__("ERROR: empty aircraft name")
class AircraftEmptyCabinsError(AirlineError):
def __init__(self):
super().__init__("ERROR: no cabin specified for the aircraft")
class CabinRowIntersectionError(AirlineError):
def __init__(self):
super().__init__("ERROR: row numbers for different cabins do intersect")
class Flight:
def __init__(self, airline: Airline, aircraft: Aircraft, ofn: int, rfn: int, origin_airport_code: str, dest_airport_code: str, dep_time: datetime, flight_hours: int, flight_mins: int, stopover_hours: int, cabin_class_prices: Dict[CabinClass, int]):
self.airline = airline
self.aircraft = aircraft
self.out_flight_number = ofn
self.return_flight_number = rfn
self.origin_airport = origin_airport_code
self.dest_airport = dest_airport_code
self.dep_time = dep_time
self.arr_time = dep_time + timedelta(hours=(flight_hours + stopover_hours), minutes=flight_mins)
self.cabin_class_prices = dict(cabin_class_prices)
def get_airline(self):
return self.airline
def get_aircraft(self):
return self.aircraft
def get_origin_airport(self) -> str:
return self.origin_airport
def get_dest_airport(self) -> str:
return self.dest_airport
def get_dep_time(self) -> datetime:
return self.dep_time
def get_arr_time(self) -> datetime:
return self.arr_time
def get_cabin_price(self, cabin_class) -> int:
if cabin_class in self.cabin_class_prices:
return self.cabin_class_prices[cabin_class]
return -1
def __str__(self):
return self.airline.get_code() + str(self.out_flight_number) + ", " + self.origin_airport + " to " + self.dest_airport + ", Depart " + self.dep_time.strftime('%d %b %y %I:%M %p') + ", Arrive " + self.arr_time.strftime('%d %b %y %I:%M %p')
PYFLIGHTS
from airline_service import AirlineService, AirlineDoesNotExistError, AircraftDoesNotExistError
from airline import *
def load_data_from_file(service: AirlineService):
filename = input("Please, enter filename to load data from: ")
f = None
airlines = []
aircrafts = []
flights = []
try:
f = open(filename, "r")
n_airlines = int(f.readline()[:-1])
if n_airlines < 0:
raise ValueError
for i in range(n_airlines):
airline_parts = f.readline()[:-1].split(",")
if len(airline_parts) != 2:
raise ValueError
airlines.append(Airline(airline_parts[1].strip(), airline_parts[0].strip()))
line = f.readline()
if len(line.strip()) > 0:
raise ValueError
n_aircrafts = int(f.readline()[:-1])
if n_aircrafts < 0:
raise ValueError
for i in range(n_aircrafts):
aircraft_parts = f.readline().split(",")
if len(aircraft_parts) != 3:
raise ValueError
line = f.readline()[:-1]
cabins = []
while len(line.strip()) > 0:
cabin_parts = line.split(",")
if len(cabin_parts) != 4:
raise ValueError
cabin_class = CabinClass[cabin_parts[0].strip()]
sections = []
rows_structure_parts = cabin_parts[1].split("-")
for s in rows_structure_parts:
sections.append(int(s))
cabins.append(Cabin(cabin_class, RowStructure(sections), int(cabin_parts[2]), int(cabin_parts[3])))
line = f.readline()[:-1]
airline = None
for a in airlines:
if a.get_code() == aircraft_parts[0].strip():
airline = a
break
if airline is None:
raise AirlineDoesNotExistError
aircrafts.append(Aircraft(airline, aircraft_parts[1].strip(), cabins))
n_flights = int(f.readline()[:-1])
if n_flights < 0:
raise ValueError
for i in range(n_flights):
flight_parts = f.readline()[:-1].split(",")
if len(flight_parts) != 9:
raise ValueError
line = f.readline()[:-1]
cabins = {}
while len(line.strip()) > 0:
cabin_parts = line.split(",")
if len(cabin_parts) != 2:
raise ValueError
cabin_class = CabinClass[cabin_parts[0].strip()]
cabins[cabin_class] = int(cabin_parts[1])
line = f.readline()[:-1]
airline = None
aircraft = None
for a in aircrafts:
if a.get_airline().get_code() == flight_parts[0].strip() and a.get_name() == flight_parts[8].strip():
airline = a.get_airline()
aircraft = a
break
if aircraft is None:
raise AircraftDoesNotExistError
dep_time = datetime.strptime(flight_parts[5].strip(), '%d %b %y %I:%M %p')
flight_time_parts = flight_parts[6].strip().split(" ")
if len(flight_time_parts) != 4:
raise ValueError
stopover_parts = flight_parts[7].strip().split(" ")
if len(stopover_parts) != 2:
raise ValueError
flights.append(Flight(airline, aircraft, int(flight_parts[1]), int(flight_parts[2]), flight_parts[3].strip(), flight_parts[4].strip(), dep_time, int(flight_time_parts[0]), int(flight_time_parts[2]), int(stopover_parts[0]), cabins))
except AirlineError as e:
print(e)
return
except IOError:
print("ERROR: can not open input file " + filename)
return
except Exception:
print("ERROR: invalid input file format")
return
finally:
if f is not None:
f.close()
test = AirlineService()
try:
for a in airlines:
test.add_airline(a)
for a in aircrafts:
test.add_aircraft(a)
for f in flights:
test.add_flight(f)
except Exception as e:
print(e)
return
service.reset()
for a in airlines:
service.add_airline(a)
for a in aircrafts:
service.add_aircraft(a)
for f in flights:
service.add_flight(f)
def read_airline(service: AirlineService):
try:
airline_name = input("Please, enter new airline name: ")
iata_code = input("Please, enter new airline IATA code: ")
a = Airline(airline_name, iata_code)
service.add_airline(a)
except Exception as e:
print(e)
def read_aircraft(service: AirlineService):
try:
iata_code = input("Please, airline IATA code: ").strip()
airline = service.get_airline_by_code(iata_code)
if airline is None:
raise AirlineDoesNotExistError
aircraft_name = input("Please, enter new aircraft name: ").strip()
cabins = []
while True:
try:
line = input("Please, enter cabin class (empty line to stop): ").strip()
if len(line) == 0:
break
cabin_class = CabinClass[line]
row_str = input("Please, enter row sections (A-B-C format): ").strip().split("-")
rs = []
for s in row_str:
rs.append(int(s))
row_structure = RowStructure(rs)
start_row = int(input("Please, enter start row: ").strip())
end_row = int(input("Please, enter end row: ").strip())
cabins.append(Cabin(cabin_class, row_structure, start_row, end_row))
except Exception as e2:
print(e2)
service.add_aircraft(Aircraft(airline, aircraft_name, cabins))
except Exception as e:
print(e)
def read_flight(service: AirlineService):
try:
iata_code = input("Please, airline IATA code: ").strip()
airline = service.get_airline_by_code(iata_code)
if airline is None:
raise AirlineDoesNotExistError
aircraft_name = input("Please, enter aircraft name: ").strip()
aircraft = service.get_aircraft_by_code_name(iata_code, aircraft_name)
if aircraft is None:
raise AircraftDoesNotExistError
ofn = int(input("Please, enter outbound flight number: ").strip())
rfn = int(input("Please, enter return flight number: ").strip())
origin_airport = input("Please, enter origin airport IATA code: ").strip()
dest_airport = input("Please, enter destination airport IATA code: ").strip()
dep_time = datetime.strptime(input("Please, enter departure time (format 1 Jan 22 00:00 PM): ").strip().strip(), '%d %b %y %I:%M %p')
flight_hours = int(input("Please, enter flight time hours: ").strip())
flight_minutes = int(input("Please, enter flight time minutes: ").strip())
stopover_hours = int(input("Please, enter stopover hours: ").strip())
cabins = {}
while True:
try:
line = input("Please, enter cabin class (empty line to stop): ").strip()
if len(line) == 0:
break
cabin_class = CabinClass[line]
price = int(input("Please, enter price in $: ").strip())
cabins[cabin_class] = price
except Exception as e2:
print(e2)
service.add_flight(Flight(airline, aircraft, ofn, rfn, origin_airport, dest_airport, dep_time, flight_hours, flight_minutes, stopover_hours, cabins))
except Exception as e:
print(e)
def search_and_book(service: AirlineService):
try:
origin = input("Please, enter origin airport: ").strip()
destination = input("Please, enter destination airport: ").strip()
dep_time = datetime.strptime(input("Please, enter departure date (format 1 Jan 22): ").strip().strip(), '%d %b %y')
routes = service.find_routes(origin, destination, dep_time, None, None)
if routes is None or len(routes) == 0:
print("No results found")
else:
for i in range(len(routes)):
print("Result " + str(i+1))
for f in routes[i]:
print(str(f))
print()
except Exception as e:
print(e)
def read_menu_choice():
while True:
print("Menu:")
print("1 - Load data from file")
print("2 - Create airline")
print("3 - Create aircraft")
print("4 - Create flight")
print("5 - Search and book flight")
print("0 - Exit")
try:
choice = int(input("Enter your choice: "))
if choice < 0 or choice > 5:
raise ValueError
return choice
except Exception:
print("Invalid input")
def main():
is_over = False
service = AirlineService()
while not is_over:
choice = read_menu_choice()
if choice == 0:
is_over = True
elif choice == 1:
load_data_from_file(service)
elif choice == 2:
read_airline(service)
elif choice == 3:
read_aircraft(service)
elif choice == 4:
read_flight(service)
elif choice == 5:
search_and_book(service)
else:
raise Exception()
print()
if __name__ == '__main__':
main()