Enum Classes and Data Sets
To solve this problem, two Enum Classes should be created to represent Categories and Stats of a DataSet. The DataSet to be loaded will contain information about the average amount per night for different rooms in different states. By using functions and working with Sets, Lists and Dictionaries, calculations will be made on average cost per state, maximum and minimum costs, etc.
fromenumimport Enum
# Define the Enums
classCategories(Enum):
LOCATION =1
PROPERTY_TYPE =2
classStats(Enum):
MIN =1
AVG =2
MAX =3
conversions = {
"USD": 1,
"EUR": .9,
"CAD": 1.4,
"GBP": .8,
"CHF": .95,
"NZD": 1.66,
"AUD": 1.62,
"JPY": 107.92
}
home_currency =""
classDataSet:
""" the DataSet class will present summary tables based on
information imported from a .csv file
"""
header_length =30
def__init__(self, header=""):
self._data =None
self._labels =dict()
self._active_labels =dict()
try:
self.header = header
exceptValueError:
self.header =""
@property
defheader(self):
returnself._header
@header.setter
defheader(self, new_header: str):
ifisinstance(new_header, str) and \
len(new_header) 28} {:>25}".format("Private room", "Entire home / apt"))
locations =dict()
for i inrange(len(self._labels[Categories.LOCATION])):
location =list(self._labels[Categories.LOCATION])[i]
for k inrange(len(self._labels[Categories.PROPERTY_TYPE])):
property_type =list(self._labels[Categories.PROPERTY_TYPE])[k]
ifnot location in locations:
locations[location] =dict()
ifnot property_type in locations[location]:
locations[location][property_type] =-1
minv, avgv, maxv =self._cross_table_statistics(location, property_type)
if stat == Stats.MAX:
locations[location][property_type] = maxv
elif stat == Stats.MIN:
locations[location][property_type] = minv
elif stat == Stats.AVG:
locations[location][property_type] = avgv
# Now print
#print(self._labels)
for location in locations:
priv = locations[location]["Private room"]
if priv isNone:
priv ="N/A"
entire = locations[location]["Entire home / apt"]
if entire isNone:
entire ="N/A"
print("{:15} {:20} {:1}".format(location, "$ "+str(priv), "$ "+str(entire)))
"""
for property_type in locations[location]:
if locations[location][property_type] is None:
print("{:>20}".format("$ N/A"), end="")
else:
#print(" $ " + str(locations[location][property_type]), end="")
print("{:>20}".format("$ " + str(locations[location][property_type])), end="")
print("")
"""
print("")
classEmptyDatasetError(Exception):
""" Raise when a method is asked to do calculation on the
dataset, but no data is loaded"""
pass
defprint_menu():
""" Display the main menu text. """
print("Main Menu")
print("1 - Print Average Rent by Location and Property Type")
print("2 - Print Minimum Rent by Location and Property Type")
print("3 - Print Maximum Rent by Location and Property Type")
print("4 - Print Min/Avg/Max by Location")
print("5 - Print Min/Avg/Max by Property Type")
print("6 - Adjust Location Filters")
print("7 - Adjust Property Type Filters")
print("8 - Load Data")
print("9 - Quit")
defmenu(dataset: DataSet):
""" present user with options to access the Airbnb dataset """
currency_options(home_currency)
print()
whileTrue:
print(dataset.header)
print_menu()
try:
selection =int(input("What is your choice? "))
exceptValueError:
print("Please enter a number only")
continue
dataset.load_default_data()
if selection ==1:
dataset.display_cross_table(Stats.AVG)
#print("Average rent functionality is not implemented yet")
elif selection ==2:
dataset.display_cross_table(Stats.MIN)
#print("Minimum rent functionality is not implemented yet")
elif selection ==3:
dataset.display_cross_table(Stats.MAX)
#print("Maximum rent functionality is not implemented yet")
elif selection ==4:
print("Location functionality is not implemented yet")
elif selection ==5:
print("Property type functionality is not implemented yet")
elif selection ==6:
print(
"Location filter functionality is not implemented yet")
elif selection ==7:
print("Property type functionality is not implemented yet")
elif selection ==8:
print("Load data functionality is not implemented yet")
elif selection ==9:
print("Goodbye! Thank you for using the database")
break
else:
print("Please enter a number between 1 and 9")
defcurrency_converter(quantity: float, source_curr: str,
target_curr: str):
""" Convert from one unit of currency to another.
Keyword arguments:
quantity -- a float representing the amount of currency to be
converted.
source_curr -- a three letter currency identifier string from
the conversions dictionary
target_curr -- a three letter currency identifier string from
the conversions dictionary
"""
if source_curr notin conversions or target_curr notin \
conversions or quantity <=0:
raiseValueError
in_usd = quantity / conversions[source_curr]
in_target = in_usd * conversions[target_curr]
return in_target
defcurrency_options(base_curr='EUR'):
""" Present a table of common conversions from base_curr to other
currencies.
"""
print("Options for converting from USD:")
for target in conversions:
print(f"{target:10}", end="")
print()
for i inrange(10, 100, 10):
for target in conversions:
print(f"{currency_converter(i, base_curr, target):<10.2f}",
end="")
print()
defmain():
global home_currency
air_bnb = DataSet()
print(air_bnb.header)
name =input("Please enter your name: ")
message ="Hi "+ name +", welcome to Foothill's database project."
print(message)
while home_currency notin conversions:
home_currency =input("What is your home currency?")
whileTrue:
print("Enter a header for the menu: ")
header =input()
try:
air_bnb.header = header
break
exceptValueError:
print(
f"Header must be a string less than"
f" {air_bnb.header_length} characters long")
menu(air_bnb)
defunit_test():
a = DataSet()
b = DataSet("OK Header")
c = DataSet("This header is way too long, I am quite sure")
print("Testing constructor with default parameter: ", end="")
if a.header =="":
print("Pass")
else:
print("Fail")
print("Testing constructor with valid header argument: ", end="")
if b.header =="OK Header":
print("Pass")
else:
print("Fail")
print("Testing constructor with invalid header argument: ", end="")
if c.header =="":
print("Pass")
else:
print("Fail")
print("Testing setter with valid assignment: ", end="")
c.header ="New header"
if c.header =="New header":
print("Pass")
else:
print("Fail")
print("Testing setter with invalid assignment: ", end="")
try:
c.header ="This header is way too long, I am quite sure"
exceptValueError:
if c.header =="New header":
print("Pass")
else:
print("Fail - Exception raised but value is incorrect")
else:
print("Fail - Exception not raised")
defunit_test2():
""" Test the _cross_table_statistics method """
print("Testing _cross_table_statistics")
my_set = DataSet()
print("Method Raises EmptyDataSetError: ", end="")
try:
my_set._cross_table_statistics("Bronx", "Private room")
print("Fail")
except DataSet.EmptyDatasetError:
print("Pass")
my_set.load_default_data()
statistics = my_set._cross_table_statistics("Bronx", "a")
print("Invalid Property Type Returns None Tuple: ", end="")
if statistics == (None, None, None):
print("Pass")
else:
print("Fail")
statistics = my_set._cross_table_statistics("a", "Private room")
print("Invalid Borough Return None Tuple: ", end="")
if statistics == (None, None, None):
print("Pass")
else:
print("Fail")
statistics = my_set._cross_table_statistics("Queens",
"Private room")
print("No Matching Rows Returns None Tuple: ", end="")
if statistics == (None, None, None):
print("Pass")
else:
print("Fail")
statistics = my_set._cross_table_statistics("Queens",
"Entire home / apt")
print("One Matching Row Returns Correct Tuple: ", end="")
if statistics == (350, 350, 350):
print("Pass")
else:
print("Fail")
statistics = my_set._cross_table_statistics("Brooklyn",
"Entire home / apt")
print("Multiple Matching Rows Returns Correct Tuple: ", end="")
if statistics == (150, 166.666666666666666, 200):
print("Pass")
else:
print("Fail")
if __name__ =="__main__":
unit_test2()
main()
""" SAMPLE RUN
Testing _cross_table_statistics
Method Raises EmptyDataSetError: Pass
Invalid Property Type Returns None Tuple: Pass
Invalid Borough Return None Tuple: Pass
No Matching Rows Returns None Tuple: Pass
One Matching Row Returns Correct Tuple: Pass
Multiple Matching Rows Returns Correct Tuple: Pass
Please enter your name:
"""