Perfect Home
Perfect Home
Perfect Home
In this task, you MUST use the csv and the json modules to read and manipulate other files being
provided to you. We are going to create some more dictionaries for each of the following files:
1. melbourne_schools.csv contains a CSV formatted list of schools in the city of Melbourne. This
file contains many fields but we are only concerned about the following:
school_no , which contains the school number,
location ; which contains the latitude and longitude of the service in a particular format.
You should read the file (either manually or through code) to figure out how to read and
process the latitude and longitude.
3. sport_facilities.csv contains a CSV formatted list of sport facilities in Melbourne. This file
contains a few fields but we are only concerned about the following:
facility_id ; which contains the ID of the sports facility,
Your task is to complete the functionality of the two functions given to you:
1. process_schools(file_name: str) -> dict : this function should read the file passed as
file_name and return a dictionary that contains all the schools read from the file where the key
is a string version of the school_no and the value is a dictionary containing five keys (and their
appropriate value data types) ( school_no <str> , school_name <str> , school_type <str> ,
school_lat <float> and school_lon <float> ).
2. process_medicals(file_name: str) -> dict : this function should read the file passed as
file_name and return a dictionary that contains all the GPs read from the file where the key is
the gp_code and the value is a dictionary containing four keys (and their appropriate value data
types) ( gp_code <str> , gp_name <str> , gp_lat <float> , gp_lon <float> ).
3. process_sport(file_name: str) -> dict : this function should read the file passed as
file_name and return a dictionary that contains all the sport facilities read from the file where
the key is the facility_id and the value is a dictionary containing five keys (and their
appropriate value data types) ( facility_id <str> , facility_name <str> , sport_lat
<float> , sport_lon <float> , sport_played <str> ).
Sample files have been provided to you in this task and can be used to test your code.
You will notice that there are some rows where the location or latitude or longitude is empty, or
marked 'NA'. In these cases, you are supposed to ignore those rows and move on to the next row.
Sometimes you will see some junk characters being read such as '\ufeff' in your file. If this is the case, when
you use the appropriate function from the csv module, make sure to mention the encoding as 'utf-8-sig'
and that should get rid of the junk characters.
You have also been given some code in the main block which should run if you have completed the three
functions properly.
Task 4 - Making Classes Using OOP
We have had our fun with dictionaries, but we must bid them adieu. Now that you know about a
much more robust form of data storage, we will convert all that we have worked with so far into
classes and objects.
Some boilerplate code has been provided for you in various files, so open up the file explorer to see
what you have. You have to read the instructions in the docstrings of the methods, create the classes,
and define the methods.
You have to choose if these should be class or instance variables, and which class they should be
defined in. Make sure that the data type of these variables also match what you did in Task 1. The
only exception is the coordinates, which is now a tuple of floats (latitude, longitude).
You should define getters and setters for these variables. There are exceptions for these, namely:
prop_id , full_address , prop_type , coordinates and suburb are static fields and hence do not
need setters, only getters. These values for a property cannot change as that would change the
property itself. The rest of the attributes can change (think renovation)
Getters and setters help us implement an important aspect of OOP called Encapsulation. You can read more
about it here.
For example for the variable bedrooms , one of your classes should have the method:
get_bedrooms(self) -> int that returns the number of bedrooms that exist in the property and
also a method set_bedrooms(self, num_bedrooms: int) -> None that sets the value
num_bedrooms to the bedrooms variable in the class.
You will have some methods as abstract methods in the Property class. When overriding the method, if that
particular method should not have an implementation in one of the child classes, make it return None .
Completing this section should pass the tests from 4.1 to 4.20.
Please DO NOT add any additional parameters to ANY of the given functions.
Again, there are exceptions for these getters and setters , namely: amenity code , amenity type
and amenity coords are static fields and hence do not need setters, only getters.
Completing this part should pass the tests from 4.21 to 4.22.
You do not need to change this file or this function. As long as you have created the four classes
properly (Property, House, Apartment, Amenity) then this function should run properly and produce
some output for you.
Please remember to always use the getter and setter methods to access the class and instance
variables where appropriate. Using the instance variables directly where a getter or a setter should have
been used will result in a loss of marks.
Some code has already been given to you in the file at the end, and if your classes and the main() method
have been successfully set up, it should print out some legible output.
� YOU MUST NOT CHANGE any of the following elements of the skeleton.
Class names.
Class method names, parameters, or return types.
all other aspects of the skeleton required to produce a functional well-structured solution to the
assignment.
You need to copy and paste the code for these classes from Task 4 into the appropriate files given in
this slide's scaffold and then add these methods.
You should try and use the methods that have been defined in the classes rather than calling the variables
themselves. Doing so will result in a loss of marks.
Completing this part should pass the tests from 5.1 to 5.4.
Please note that if the subtype is Pri/Sec for a school, then that school should appear in both Primary and
Secondary searches.
If a amenity_subtype is not provided, then it should consider all amenities of that type and return the closest
one.
You may want to copy the haversine function to this class but ensure to make it a private function of this
class rather than a global function in the file as this will fail test cases.
Completing this part should pass the tests 5.5 and 5.6
Once you add the three new methods, and if all works well then you should see an output similar to
the following:
The nearest station to 3 Antrim Place Langwarrin VIC 3910 is Baxter Railway Station (Baxter) and it is
The property at G01/7 Rugby Road Hughesdale VIC 3166 has the following features: ['dishwasher', 'air co
We are going to add 'tennis court' as a feature to this property
Now the property at G01/7 Rugby Road Hughesdale VIC 3166 has the following features: ['dishwasher', 'ai
Task 6 - Producing Suitability Score
You've done extremely well to get to this stage! Pat yourself on the back! �
We will now use the information that you have ingested and apply that to a real-world scenario. We
will import a request from the user to provide a suitability score for each property and then provide a
list of properties that fit the user's criteria.
{
"request": {
"house_importance": {
"suburb": "Clayton",
"prop_type": "Apartment",
"bedrooms": 3,
"bathrooms": 2,
"parking_spaces": 1,
"price": 900000,
"property_features":"air conditioning"
},
"amenities_accessibility": {
"train_station": "walk",
"school": {
"school_type": "Primary",
"accessibility": "cycle"
},
"medical_centre": "drive",
"sport_facility": {
"sport_played": "Cricket",
"accessibility": "optional"
}
}
}
}
Please note that some or all fields in the house_importance may or may not exist in the request. The valid
fields are the variables that you created in the Property family. Similarly, in the amenities school and
sport_facility, the school_type and sport_played may or may not exist. If they don't exist then you should
consider all amenities in that category. Similar to the previous task, if a user asks for a Primary or a Secondary
school then the Pri/Sec schools should be considered in both categories.
Your task is to write the appropriate code in the function read_request which returns two
dictionaries; house_importance and amenity_accessibility based on the JSON request being
read.
Part 2 - Collect Properties that Match the Given Criteria in the JSON
Request
You will now use the dictionary house_importance obtained from the previous part as well as the list
of all properties that has been ingested for you in the variable props and return a list of matching
properties based on the user's request. The return value should be a list that contains objects of the
Property Family (i.e., House/Apartment/Property). This will be done in the
find_matching_properties function.
There are certain constraints for selecting a property based on the request:
1. For property type and suburb, consider only a full match; i.e. if the request is for a house, filter
out apartments.
2. For property features; consider a full match in the list. If the feature is mentioned in the request
and is not present in the property, that property should be filtered out.
3. For floor area, land area, bedrooms, bathrooms and parking_spaces, you should treat the given
values as the baseline. Anything higher than or equal to the value should be accepted.
4. For the floor number and price, treat the given value as the ceiling. Anything less than or equal
to the value should be accepted.
For item 2 above, please assume that the request will only contain one property feature.
While filtering properties, any field that is missing in the request should not be considered as a filtering criteria.
For example, if the request does not contain a value for bedrooms, you should keep all possible values of
bedrooms. This applies to all fields.
Completing this part should pass the test cases 6.2 and 6.3.
After this step is complete, you will have a dictionary in the variable called prop_scored that
contains the star_score as the key and the property object as the value. An example of the format of
the prop_scored dictionary is as below:
prop_scored = {
"3.5" : <Property_Object_1>,
"2.3" : <Property_Object_2>,
"1.3" : <Property_Object_3>
}
{
"properties": [
{
"property_id": "P1001",
"star_score": 4.2
},
{
"property_id": "P1002",
"star_score": 3.8
},
{
"property_id": "P1003",
"star_score": 3.5
}
]
}
Once you create this dictionary, you should return it from the function.
Completing this part should pass the test cases 6.4, 6.5 and 6.6
respond(response_dict: dict) -> None : This function reads the return value from the function
produce_star_scores and writes the file called response.json . While writing the response files,
sort the scores in descending order by star_score and if there is a tie then ascending order of
prop_id. Unfortunately due to the limitations of Ed, simply pressing the 'Run' button will not create
your response file, you need to open the terminal and manually execute the task6.py file. Then, you
should be able to see the response.json file in your scaffold.
It is YOUR RESPONSIBILITY to validate your JSON file. You can do so by copying the content of your
response.json file and checking its validity on a website such as JSONFormatter.
There are no tests for this task, your file will be manually checked by a tutor.
Additional Important Information About Task 6
You must copy and paste the code for all four classes from Task 5 into the appropriate files
given in the scaffold.
You have been given a couple of functions and their arguments in the scaffold that you need to
use, however, you are STRONGLY RECOMMENDED to define other functions that are called
within the given functions. Please do not edit the arguments or the return value types that our
functions require.
Once you have completed your code in task6.py , you should be able to run the code given in
the if __name__ == '__main__' block and produce the response.json file while printing the
success or the failure of your code.
# returned dictionary should look like:
returned_dict = {
"unit_no" : 'G101',
"street_no" : "7",
"street_name": "Rugby",
"street_type": "Rd",
"suburb": "Hughesdale",
"state": "VIC",
"postcode": "3166"
}
Example 2
Example 3
address_str = "Floor 10/45 The Avenue St Toorak VIC-3142"