lab07 : Apartment Listing Manager

num ready? description assigned due
lab07 true Apartment Listing Manager Tue 05/21 11:59PM Tue 05/28 11:59PM

Learning Goals

In this lab, we will utilize many concepts covered in the course so far including:

Note: It is important that you try and start this lab early so you can utilize our office hours to seek assistance / ask clarifying questions during the weekdays before the deadline if needed!

Introduction

The goal for this lab is to write a program that will manage apartment listings. Each listing will have a date indicating when the apartment will become available. Listings will be organized in a MinHeap priority queue, ensuring the apartment that becomes available the soonest is listed first.

In this lab, you will develop various Apartment classes (Apartment, StudioApartment, and FamilyApartment that utilize inheritance and polymorphism), a ApartmentListing class representing a collection of apartments available on a specific date, and a ListingQueue class that organizes these apartment listings in a MinHeap based on their availability dates. This structure ensures that the apartment that becomes available the soonest is processed first, optimizing the management of apartment rentals.

You will also write pytests in testFile.py illustrating your behavior works correctly. This lab writeup will provide some test cases for clarity, but the Gradescope autograder will run different tests shown here.

Instructions

You will need to create six files:

There will be no starter code for this assignment, but rather class descriptions and required methods are defined in the specification below.

You should organize your lab work in its own directory. This way all files for a lab are located in a single folder. Also, this will be easy to import various files into your code using the import / from technique shown in lecture.

Apartment.py

The Apartment.py file will contain the definition of a Apartment base class. We will define the Apartment attributes as follows:

You should write a constructor that allows the user to construct an Apartment object by passing in values for the view. Your constructor should also create a price attribute and set it to 0.0.

Your Apartment class definition should also support the “getter” and “setter” methods for the price and view. Since this will be a base class for other Apartment types, anything we write here can be inherited by its child classes.

StudioApartment.py and FamilyApartment.py

Apartment objects can be two different types. Both of these types of apartments inherit from the Apartment class:

  1. StudioApartment that allows the customers to add additional amenities of their choice
  2. FamilyApartment that has already been pre-configured and has a fixed price based on its view

StudioApartment.py

Your StudioApartment class definition will be defined in StudioApartment.py. The StudioApartment class will contain a constructor that takes in the view of the Apartment, and should use this view to call our base class’ constructor. In addition to the view, it will initialize an amenities list represented as a Python List.

The price of a StudioApartment is defined by two things:

  1. the view of the apartment
  2. the number of amenties the apartment will have (assuming no amenities, it is an unfurnished simple apartment). StudioApartment will have the following fixed prices based on its view:

The view from the apartment also dictates the number of additional amenities will cost based on the following definition:

Since we now know that the price of an apartment should be based on the view, the StudioApartment constructor should determine the base price of the apartment and set it appropriately (remember, no need to write it in this class if we already have the method in Apartment.py).

There are two more methods this class should support:

StudioApartment without amenities example:

sa1 = StudioApartment("C")

assert sa1.get_apartment_details() == \
"""\
STUDIO APARTMENT
View: C
Amenities:
Price: $1200.00
"""

StudioApartment with a list of amenities example (note that each amenity will be indented with a tab):

sa1 = StudioApartment("L")
sa1.add_amenity("balcony/patio")
sa1.add_amenity("dishwasher")

assert sa1.get_apartment_details() == \
"""\
STUDIO APARTMENT
View: L
Amenities:
\t+ balcony/patio
\t+ dishwasher
Price: $1960.00
"""

FamilyApartment.py

A FamilyApartment class definition will exist in FamilyApartment.py. Similar to a FamilyApartment object, the class constructor will take in the view as well as the layout type of the apartment.

Also similar to the StudioApartment class, FamilyApartment will use the view to set its price appropriately. The price of a FamilyApartment is defined as follows:

Unlike studio apartments, family apartments do not have a list of amenities associated with it, but do have a unique layout that will be displayed when getting details for this apartment. This class should also have its own get_apartment_details method described below:

A sample output test for get_apartment_details():

fa1 = FamilyApartment("C", "Modern")
assert fa1.get_apartment_details() == \
"""\
FAMILY APARTMENT
View: C
Layout: Modern
Price: $2500.00
"""

ApartmentListing.py

The ApartmentListing class will be defined in ApartmentListing.py. This class will keep track of various apartments for a single listing. The ApartmentListing class will have the following attributes:

The constructor for an ApartmentListing will take in the expected date that listing should be ready:

The date format will be stored as an int in a YYYYMMDD. This format keeps the date attributes straightforward and allows for easy sorting and comparison of dates. Here’s how you would represent a few dates in this format:

In addition to the constructor, getters for the date attribute, the ability to add Apartment objects to the listing, as well as a method to construct a string representing the listing details will need to be implemented:

An example of the info() string format is given below:

sa1 = StudioApartment("L")
sa1.add_amenity("balcony/patio")
sa1.add_amenity("dishwasher")
fa1 = FamilyApartment("C", "Modern")
listing = ApartmentListing(20250101) #January 1, 2025
listing.add_apartment(sa1)
listing.add_apartment(fa1)

assert listing.info() == \
"""\
***
Date of Viewing: 20250101
STUDIO APARTMENT
View: L
Amenities:
\t+ balcony/patio
\t+ dishwasher
Price: $1960.00

----
FAMILY APARTMENT
View: C
Layout: Modern
Price: $2500.00

----
TOTAL APARTMENT LISTING PRICE: $4460.00
***
"""

ListingQueue.py

The ListingQueue class will be defined in ListingQueue.py. This priority queue is implemented as a MinHeap data structure. The ListingQueue will manage ApartmentListing objects based on their date attribute.

In addition to the construction of the MinHeap in this class, two methods are required to be implemented:

The automated tests will create various apartment listings with different date attributes. It will then call process_next_listing() one at a time and check the removed ApartmentListing is in the right priority by checking their expected info() string. You should write similar tests to confirm the MinHeap state is in the correct order.

For example:

listing1 = ApartmentListing(20240417)   #April 17,2024
sa1 = StudioApartment("P")
listing1.add_apartment(sa1)
listing2 = ApartmentListing(20240115)   #January 15,2024
sa2 = StudioApartment("L")
sa2.add_amenity("balcony/patio")
sa2.add_amenity("dishwasher")
listing2.add_apartment(sa2)
listing3 = ApartmentListing(20240415)    #April 15,2024
fa1 = FamilyApartment("L", "Modern")
listing3.add_apartment(fa1)
listing4 = ApartmentListing(20240215)    #February 15,2024
fa2 = FamilyApartment("C", "Open")
listing4.add_apartment(fa2)

listingQueue = ListingQueue()
listingQueue.add_listing(listing1)
listingQueue.add_listing(listing2)
listingQueue.add_listing(listing3)
listingQueue.add_listing(listing4)

print(listingQueue.process_next_listing())

Output:

***
Date of Viewing: 20240115
STUDIO APARTMENT
View: L
Amenities:
        + balcony/patio
        + dishwasher
Price: $1960.00

----
TOTAL APARTMENT LISTING PRICE: $1960.00
***

testFile.py

This file should test all of your classes using pytest. Think of various scenarios and edge cases when testing your code according to the given descriptions. You should test every class’ method functionality. Even though Gradescope will not use this file when running automated tests (there are separate tests defined for this), it is important to provide this file with various test cases (testing is important!!).

Of course, feel free to reach out / post questions on Piazza as they come up!

Submission

Once you’re done with writing your class definitions and tests, submit the following files to Gradescope’s Lab07 assignment:

There will be various unit tests Gradescope will run to ensure your code is working correctly based on the specifications given in this lab.

If the tests don’t pass, you may get some error message that may or may not be obvious at this point. Don’t worry - if the tests didn’t pass, take a minute to think about what may have caused the error. If your tests didn’t pass and you’re still not sure why you’re getting the error, feel free to ask your TAs or Learning Assistants.