HW 3: Trees and Objects

The goals of this assignment are:

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:

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 HTMLTrees 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.

  1. 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:

  1. What other metadata can you think of that might be useful for better understanding the context surrounding an encrypted message?

  2. 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:

  1. 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:

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.