Instructions
Objective
Write a Python assignment to implement encapsulation.
Requirements and Specifications
The advantage of encapsulating the properties of a date in an object rather than a string is flexibility. It is flexible in a sense that we can manipulate it in different ways. We have to consider sometimes that dates can be represented in different formats and styles. Depending on the country, some dates are represented differently. Although they are represented differently, they still mean the same since date and time are absolute. Besides date representation, we can further customize our object to have additional functionalities such as being able to compare whether dates are equal, greater than, and even less than. Date comparison is useful in many ways such as when in need for sorting. Other functionalities include being able to increment/decrement for a number of days, months, and years.
All the above-mentioned advantages cannot be done on a date that is represented as a string. The advantage of having a date as string is its simplicity. If we don’t need to do date operations then we can simply store it as a string. Creating a date class along with its attributes and operation is a complex task and not a good idea to use it if the program will just use it to store data.
Source Code
import csv
class Date:
def __init__(self, year, month, day):
"""
Create a date
"""
self.__year = year
self.__month = month
self.__day = day
def __str__(self):
"""
Return a string representation of a date
"""
month_names = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
return month_names[self.__month] + " " + str(self.__day) + ", " + str(self.__year)
def __repr__(self):
"""
Return a representation of a date for debugging
"""
return self.__str__()
def __gt__(self, other):
"""
Check if this date is greater than the other date
"""
if not isinstance(other, Date):
False
if self.__year > other.__year:
return True
elif self.__year < other.__year:
return False
if self.__month > other.__month:
return True
elif self.__month < other.__month:
return False
return self.__day > other.__day
def __lt__(self, other):
"""
Check if this date is lesser than the other date
"""
if not isinstance(other, Date):
False
if self.__year < other.__year:
return True
elif self.__year > other.__year:
return False
if self.__month < other.__month:
return True
elif self.__month > other.__month:
return False
return self.__day < other.__day
class Infection:
def __init__(self, date, num_infected):
"""
Initialize the information about the infection status at a
given date for a given country
"""
self.__date = date
self.__num_infected = num_infected
self.__num_tested = 0
self.__num_hospitalized = 0
self.__num_respirators_needed = 0
self.__num_dead = 0
def get_num_infected(self):
"""
Return the number of infected
"""
return self.__num_infected
def get_date(self):
"""
Return the date
"""
return self.__date
class Country:
def __init__(self, name, code):
"""
Create a country
"""
self.__name = name
self.__code = code
self.__registrations = {}
def log_data(self, infection):
"""
Add a new infection data to the country
"""
self.__registrations[infection.get_date()] = infection
def remove_zero_infections(self):
"""
Remove the infections before the earliest date that was
found to have an infection
"""
dates = self.get_sorted_dates()
# Find which date has a non-zero infection
earliest_index = None
for i in range(len(dates)):
if self.__registrations[dates[i]].get_num_infected() > 0:
earliest_index = i
break
# Delete everything before the earliest index
for i in range(earliest_index):
del self.__registrations[dates[i]]
def get_data(self):
"""
Get the list of infections
"""
return list(self.__registrations.values())
def get_csv_data_by_date(self, date):
"""
Return the infection data for a specific date
"""
if date not in self.__registrations.keys():
return None
return self.__name + "," + self.__code + ",\"" + str(date) + "\"," + str(self.__registrations[date].get_num_infected()) + "\n"
def get_csv_data(self):
"""
Return the data of infection as a CSV
"""
dates = self.get_sorted_dates()
csv_data = ""
for date in dates:
csv_data += self.__name + "," + self.__code + ",\"" + str(date) + "\"," + str(self.__registrations[date].get_num_infected()) + "\n"
return csv_data
def get_sorted_dates(self):
"""
Return the dates but sorted by date in ascending
"""
dates = list(self.__registrations.keys())
# Sort the dates in ascending order
for i in range(len(dates) - 1):
for j in range(i + 1, len(dates)):
if dates[i] > dates[j]:
temp = dates[i]
dates[i] = dates[j]
dates[j] = temp
return dates
class Region:
def __init__(self, name, code, countries):
"""
Create a region containing a list of countries
"""
self.__name = name
self.__code = code
self.__countries = countries
def get_infections_by_date(self):
"""
Accumulate all infections grouped by date
"""
infections_by_date = {}
for country in self.__countries:
for infection in country.get_data():
date = infection.get_date()
if date not in infections_by_date.keys():
infections_by_date[date] = 0
infections_by_date[date] += infection.get_num_infected()
return infections_by_date
def parse_date(str_date):
"""
Given a date in the form of MMM DD, YYYY
we parse it to a date object
"""
# Split the MMM DD and YYYY
tokens = str_date.split(",")
if len(tokens) != 2:
return None
mmm_dd = tokens[0]
yyyy = tokens[1]
# Validate that the year is a positive integer value
try:
yyyy = int(yyyy)
except:
return None
# Corona virus just started being officially recorded this 2020
# Date is invalid if it was before 2020
if yyyy < 2020:
return None
# Split the MMM and DD
tokens = mmm_dd.split()
if len(tokens) != 2:
return None
mmm = tokens[0]
dd = tokens[1]
# Find the numeric value of a month
months = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
if mmm not in months:
return None
month_number = months.index(mmm)
# Next is to validate the day, it should be a positive day
try:
dd = int(dd)
except:
return None
if month_number in [1, 3, 5, 7, 8, 10, 12]:
# 31 days for months that fall in the given list
max_day_in_month = 31
elif month_number == 2:
# Month of February is 29 days if leap year, otherwise 28
if (yyyy % 400 == 0) or ((yyyy % 4 == 0) and (yyyy % 100 != 0)):
max_day_in_month = 29
else:
max_day_in_month = 28
else:
# 30 days for the other months
max_day_in_month = 30
if dd < 1 or dd > max_day_in_month:
return None
return Date(yyyy, month_number, dd)
def load_data():
"""
Load the data from file, this returns a dictionary of
countries and dates. Each country object contains
their respective infection data
"""
countries = {}
dates = {}
in_file = open("data.txt", "r")
csv_reader = csv.reader(in_file, delimiter=",")
for row in csv_reader:
country_name = row[0]
country_code = row[1]
infection_date = row[2]
num_infected = row[3]
# We're only going to create only 1 instance of each date
# If the instance does not exist yet, then create one
if infection_date not in dates.keys():
date = parse_date(infection_date)
if date is None:
# Reject this record if the date can't be parsed
continue
dates[infection_date] = date
# Get the object version, not the string version
infection_date = dates[infection_date]
# Validate the number of infections
try:
num_infected = int(num_infected)
except:
# Reject this record if the number of infections is invalid
continue
if num_infected < 0:
# Reject this record if the number of infections is invalid
continue
# Create the country if it does not exist yet
if country_name not in countries.keys():
country = Country(country_name, country_code)
countries[country_name] = country
# Get the country and record the infection
country = countries[country_name]
country.log_data(Infection(infection_date, num_infected))
in_file.close()
return countries, dates
def option_c(countries):
"""
write infection data for a given country
"""
country_name = input("Enter name of country: ")
if country_name not in countries.keys():
print("Country does not exist.")
return
print(countries[country_name].get_csv_data())
def option_d(countries, dates):
"""
Write infection data of all countries for a specific date
"""
date = input("Enter a date (mmm dd, yyyy): ")
if date is None:
print("Invalid date.")
return
# Check if the date is known for infection
if date not in dates.keys():
print("No countries are infected on the given date.")
return
# Convert the date as an object
date = dates[date]
# Find all countries that has infection on the given date
csv_data = ""
for country_name in countries.keys():
csv_line = countries[country_name].get_csv_data_by_date(date)
if csv_line is not None:
csv_data += csv_line + "\n"
print(csv_data)
def option_g(countries, regions):
"""
Create a region that contains a list of countries
"""
region_name = input("Enter region name: ")
if region_name in regions.keys():
print("Region name already exists")
return
region_code = input("Enter region code: ")
# Set the countries to be added to the region
region_countries = []
while True:
country_name = input("Enter a country name to be added to the region: ")
if country_name in countries.keys():
country = countries[country_name]
if country in region_countries:
print("Country has been previously added.")
else:
region_countries.append(country)
print("Country included in region.")
if len(region_countries) > 0:
option = input("Would you like to add another country? (y/n): ")
if option != "y":
break
regions[region_name] = Region(region_name, region_code, region_countries)
print("Region created.")
def option_m(regions):
"""
Find which date the infection spread the most in a given region
"""
region_name = input("Enter a region name: ")
if region_name not in regions.keys():
print("Region does note exist.")
return
region = regions[region_name]
infections_by_date = region.get_infections_by_date()
max_date = None
for date in infections_by_date.keys():
if max_date is None or infections_by_date[date] > infections_by_date[max_date]:
max_date = date
if max_date is None:
print("There is no date that has the most infected in the region")
else:
print("\"" + str(max_date) + "\"," + str(infections_by_date[max_date]))
def option_n(countries, dates):
"""
Create a new entry for a country
"""
country_name = input("Enter country name: ")
if country_name not in countries.keys():
country_code = input("Enter country code: ")
countries[country_name] = Country(country_name, country_code)
print("New country created.")
date = input("Enter infection date (mmm dd, yyyy): ")
if date not in dates.keys():
date_object = parse_date(date)
if date_object is None:
print("Invalid date.")
return
dates[date] = date_object
try:
num_infections = input("Enter the number of infected: ")
except:
print("Invalid number of infected.")
return
if num_infections < 0:
print("Invalid number of infected.")
return
country = countries[country_name]
country.log_data(Infection(date_object, num_infections))
print("New entry added.")
def option_r(countries):
"""
Removes all objects of Infection with a number of infected equal to 0,
which comes earlier than the first day of detected spread
"""
for country in countries.values():
country.remove_zero_infections()
print("Ok, done.")
def option_w(countries):
"""
Write all infections to file
"""
filename = input("Enter output filename: ")
out_file = open(filename, "w")
for country in countries.values():
out_file.write(country.get_csv_data())
out_file.close()
print("Ok, done.")
def main():
"""
Main procedure that will load data from file, create the data structures
needed and the corresponding of infected people
"""
countries, dates = load_data()
regions = {}
while True:
print("Menu")
print("c-(country) write infection data for a given country")
print("d-(date) write infection data for all countries at a given date")
print('g-(group) create a region with infection data for a group of countries')
print("m-(max) find which date the infection spread the most in a given region")
print('n-(new) add a new information to the data structure')
print("q-(quit) terminate the program")
print("r-(remove) remove all data with 0 infections earlier than the first day of detected spread")
print("w-(write) save information to file")
option = input("Option: ")
print()
if option == "c":
option_c(countries)
elif option == "d":
option_d(countries, dates)
elif option == "g":
option_g(countries, regions)
elif option == "m":
option_m(regions)
elif option == "n":
option_n(countries, dates)
elif option == "r":
option_r(countries)
elif option == "w":
option_w(countries)
elif option == "q":
break
print()
if __name__ == '__main__':
main()
Similar Sample
Explore our Python assignment sample to see how we tackle complex problems with clear, efficient code. Our expert solutions not only solve the given tasks but also illustrate best practices in Python programming. Dive into our sample to understand the quality and approach we bring to every assignment, ensuring you get the best help possible.
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python
Python