HW 3: Trees and Objects
- Due: Wed, Oct 11 2023 at 9:00 PM EST
- Released: Wed, Oct 4 2023
The goals of this assignment are:
- to get practice with designing and developing programs that operate on on tree-shaped data; and
- to get practice implementing methods on Python classes.
The material from class on Wednesday, October 4th covers the first goal (Part 1 below), and class on Friday, October 6th covers the second goal (Part 2).
Setup
In order to setup hw3, make a new VSCode Project and name it hw3. The functions you need to complete will be outlined later, but for now make sure you copy the following files:
In addition, create the following empty files:
tree_test.py
messagecenter_test.py
Make sure you copy the stencil code from the links above for tree.py
and
messagecenter.py
. Also, since you will be working with HTMLTrees in tree.py
,
copy the code from the link above for htmltree.py
. This contains the structure
of the HTMLTree, which is imported into tree.py
.
Helpful Things
Documentation
Staff Assistance
Your friendly TAs and Professor are here to help with this assignment! You can find our schedule for office hours here.
The Assignment
Part 1: For the love of Newton
Whimsical Framing
Tim has been invited to give a talk at Woolsthorpe Manor, the famous location where Isaac Newton reportedly came up with the law of gravity. While touring the estate, you pass by the apple tree. Tim thinks that inspiration could be found at the top of the tree, but would perhaps be wiser not to make the attempt. Exactly how far is it from the top of the tree to the bottom? You’ll help by showing Tim a simulation of this idea on HTML trees.
Summary
We’d like you to write the following functions on HTMLTree
s in the tree.py
file.
tree_height
tree_height computes the maximum distance from the root to any leaf. This
function should take an HTMLTree
and return an integer. The height of a tree
with only the root and no children is 1; the height of a tree with children is the maximum height of any of its children plus 1.
has_strong_grandchildren
has_strong_grandchildren should return True
if any of the grandchildren of
the node at the root of the tree (i.e., children of its children) have the
"strong"
tag. Note that it doesn’t matter whether the root of the tree or any
of its children are strong
, we only care about the grandchildren. has_strong_grandchildren
should take an
HTMLTree
and return a boolean.
Part 2: Getting the message
Whimsical Framing
In homework two, Tim set up a social network to connect students with similar interests. Now, he wants to grow the platform by allowing users to interact with each other through messaging.
Summary
For this part, you’ll implement a messaging application–think WhatsApp. Your
application will track messages (as a list of Message
objects, defined above)
and groups, which are sets of users. Users can send messages either to other
users or to a group; sending a message to a group results in it being sent to
every user in the group. Your messaging application will be implemented as a
class called MessageCenter
.
You should write code for this part in messagecenter.py
. The stencil file,
linked above, contains code implementing the Message
class, as well as the
method definitions for the MessageCenter
class.
Implement the methods below in the MessageCenter
class. Remember that all of
your methods need to take self
as their first argument! We list the other
arguments below.
__init__
The __init__ method doesn’t need to take any arguments besides self
. It
should add messages
and groups
fields to the object; these should be an
empty list responsible for keeping track of the messages and an empty dictionary
in charge of the different groups present in the message center, respectively.
add_user_to_group
This method should take (in addition to self
) the name of a group (a string)
and the name of a user (also a string). It should add a group with the given
name if it doesn’t exist, and then add the named user to the group if it’s not
already in the group.
add_direct_message
add_direct_message should take (in addition to self
) two users and a
message body. It should create a message with the given users and body and store
it in the messages
list.
add_group_message
add_group_message should take (in addition to self
) a user, a group, and a
message body. If the given group exists, it should add messages with the given
body from the given user to every member of the group.
next_message
next_message should take (in addition to self
) a user and return the first
unread message in the messages list addressed to that user. Before returning
the message, it should mark the message as read using the mark_read
method.
message_history
message_history should take (in addition to self
) two users and return all
of the messages (read or unread) between those two users–messages from the
first user to the second user and vice versa.
Part 3: Privacy
We have received feedback from our users expressing a desire for their messages to be encrypted to ensure their privacy. However, we currently analyze the content of users’ messages to screen for potentially harmful content. To get a deeper understanding of the issue read this article on WhatsApp end to end encryption and then, in your README, reflect on the following:
NOTE: You should be able to access the mentioned articles without requiring any subscription. You should sign in through google using your brown .edu email.
- Describe situations where encryption might be a lifeline versus when it could harbor malicious activities. Does your stance on the balance between individual privacy and collective security change based on these contexts? (5-6 sentences)
After reviewing various solutions, Tim has concluded that a good compromise between privacy and security would be to incorporate end-to-end encryption for the content of messages while retaining metadata about the context behind those messages for the sake of moderation. While delving into the details of encryption is beyond the scope of this course, we will be adding metadata to our messages.
__init__
Modify the __init__
field in the Message class so that, in addition to keeping track of the sender and recipient, we keep track of the timestamp and length of a message in self.timestamp and self.length respectively. To get the date and time of a message, use the datetime python library. You can read the documentation for the datetime library here: datetime (use the .now() function).
After implementing metadata answer the following two questions in your README:
-
What other metadata can you think of that might be useful for better understanding the context surrounding an encrypted message?
-
If we stopped keeping track of the sender and recipient(s) of a message, how could you use the metadata we implemented, and the metadata you came up with in your last response to identify the sender and recipient(s) of a message? (Hint: if you are stuck, read Using Metadata to find Paul Revere).
While encryption plays a pivotal role in ensuring security and privacy from intermediaries like the company relaying messages, hackers, and third parties, it only addresses concerns about unauthorized access. Privacy, however, is not only about external threats; it also deals with the control individuals have over their data, even when it is in the hands of authorized recipients. This is where European Privacy Laws under the GDPR (General Data Protection Regulation) come into play. One of the key principles of GDPR is the “right to be forgotten,” which means that individuals can request the deletion of their data. In compliance with this principle, we will implement a function that allows users to delete their account and all messages sent from it.
delete_account
delete_account
should take (in addition to self) a user. This function should remove all messages in the Message Center that have been sent by this user and remove the user from all groups.
In your README, answer the following:
- What are some of the negative implications of giving users more agency over their data, particularly in scenarios where past messages may have legal, historical, or societal importance? (3-4 sentences)
Testing
Please make sure you write tests for your functions in the tree_test.py and messagecenter_test.py files. You don’t have to test for a case where no tree is present (null/None).
Handin
You may submit as many times as you want. Only your latest submission will be graded. This means that if you submit after the deadline, you will be using a late day – so do NOT submit after the deadline unless you plan on using late days.
Please follow the design and clarity guide–part of your grade will be for code style and clarity. After completing the homework, you will submit:
README.txt
tree.py
tree_test.py
messagecenter.py
messagecenter_test.py
Please make sure your files are named properly.
If you are using late days, make sure to make a note of that in your README. Remember, you may only use a maximum of 3 late days per assignment. If the assignment is late (and you do NOT have anymore late days) no credit will be given.
Please don’t put your name anywhere in any of the handin files–we grade assigments anonymously!
Hand in your work on Gradescope. Use the Gradescope account associated with your anonymous ID which you set up during HW0. The guide for setting that up and enrolling in gradescope can be found in the Setup guide here.