mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(curriculum): add email simulator workshop (#62100)
Co-authored-by: Ilenia <26656284+ilenia-magoni@users.noreply.github.com> Co-authored-by: Ilenia M <nethleen@gmail.com>
This commit is contained in:
@@ -4590,6 +4590,12 @@
|
||||
"In this workshop, you will learn about classes, objects, and methods in Python by building a simple musical instrument inventory."
|
||||
]
|
||||
},
|
||||
"workshop-email-simulator": {
|
||||
"title": "Build an Email Simulator",
|
||||
"intro": [
|
||||
"In this workshop you will implement classes and objects by building an email simulator that simulates sending, receiving, and managing emails between different users."
|
||||
]
|
||||
},
|
||||
"lab-budget-app": {
|
||||
"title": "Build a Budget App",
|
||||
"intro": [
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Introduction to the Build an Email Simulator
|
||||
block: workshop-email-simulator
|
||||
superBlock: full-stack-developer
|
||||
---
|
||||
|
||||
## Introduction to the Build an Email Simulator
|
||||
|
||||
In this workshop you will implement classes and objects by building an email simulator that simulates sending, receiving, and managing emails between different users.
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
---
|
||||
id: 6852ea0c3cadb54e897acdac
|
||||
title: Step 1
|
||||
challengeType: 20
|
||||
dashedName: step-1
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In this workshop, you are going to build an *Email Simulator* that simulates sending, receiving, and managing emails between different users. You'll learn about classes, objects, and how to organize code in an object-oriented way.
|
||||
|
||||
Begin by creating a class named `Email` using the `class` keyword.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create a class named `Email`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`(_Node(_code).has_class("Email"))`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
---
|
||||
id: 6852ef95ccc27660275692cd
|
||||
title: Step 2
|
||||
challengeType: 20
|
||||
dashedName: step-2
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Your `Email` class needs to store information about each email when it's created.
|
||||
|
||||
Inside your `Email` class, remove the existing `pass` keyword and create the `__init__` method that takes `self`, `sender`, `receiver`, `subject`, and `body` as parameters.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define an `__init__` method inside the `Email` class.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Email").has_function("__init__")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
Your `__init__` method should have parameters: `self`, `sender`, `receiver`, `subject`, and `body`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__init__").has_args("self, sender, receiver, subject, body")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Email:
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
---
|
||||
id: 6852f01116912861c7d1b0e6
|
||||
title: Step 3
|
||||
challengeType: 20
|
||||
dashedName: step-3
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the `__init__` method, you need to assign the parameter values to the object's attributes so each email can store its information.
|
||||
|
||||
Inside your `__init__` method, remove the `pass` keyword and assign the parameters to `self.sender`, `self.receiver`, `self.subject`, and `self.body`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should assign the `sender` parameter to `self.sender`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__init__").find_variable("self.sender").is_equivalent("self.sender = sender")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should assign the `receiver` parameter to `self.receiver`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__init__").find_variable("self.receiver").is_equivalent("self.receiver = receiver")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should assign the `subject` parameter to `self.subject`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__init__").find_variable("self.subject").is_equivalent("self.subject = subject")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should assign the `body` parameter to `self.body`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__init__").find_variable("self.body").is_equivalent("self.body = body")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
---
|
||||
id: 6852f06fdde1b4634a263f03
|
||||
title: Step 4
|
||||
challengeType: 20
|
||||
dashedName: step-4
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now let's test the `Email` class by creating an email object and checking that it stores information correctly. You'll print a couple of attributes to verify everything works.
|
||||
|
||||
Create an email object named `email_obj` with `alice@example.com` as the sender, `bob@example.com` as the receiver, `Hello` as the subject, and `Hi Bob!` as the body. Then print the `sender` and `subject` attributes as separate print statements to verify they are stored correctly.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create an email object named `email_obj` with the specified parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_variable("email_obj").is_equivalent("email_obj = Email('alice@example.com', 'bob@example.com', 'Hello', 'Hi Bob!')")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should print `email_obj.sender`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).has_call("print(email_obj.sender)")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should print `email_obj.subject`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).has_call("print(email_obj.subject)")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
---
|
||||
id: 6852f0c3fcedb964ab959921
|
||||
title: Step 6
|
||||
challengeType: 20
|
||||
dashedName: step-6
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now let's test that the `read` attribute was added correctly to your `Email` class. Since you already have an email object from the previous steps, print the `read` attribute to see that it's now `False` by default.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should print `email_obj.read` to test the read attribute.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).has_call("print(email_obj.read)")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
--fcc-editable-region--
|
||||
email_obj = Email('alice@example.com', 'bob@example.com', 'Hello', 'Hi Bob!')
|
||||
print(email_obj.sender)
|
||||
print(email_obj.subject)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
---
|
||||
id: 6852f11d412c29665985a915
|
||||
title: Step 12
|
||||
challengeType: 20
|
||||
dashedName: step-12
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now that users can send emails, they need a way to store emails they receive. Each user should have an inbox to collect their emails.
|
||||
|
||||
Add an `inbox` attribute to the `User` class `__init__` method and initialize it as an empty list `[]`. This will store all emails that the user receives.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should add `self.inbox = []` to the `User` class `__init__` method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("__init__").find_variable("self.inbox").is_equivalent("self.inbox = []")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
--fcc-editable-region--
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
```
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
---
|
||||
id: 6853f2da9b8ed891e9fdc5fc
|
||||
title: Step 23
|
||||
challengeType: 20
|
||||
dashedName: step-23
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now let's display the sender and receiver information. To show who sent and received the email, add two print statements to the `display_full_email` method in this format:
|
||||
|
||||
- `From: sender` where `sender` is replaced with the sender's name
|
||||
- `To: receiver` where `receiver` is replaced with the receiver's name
|
||||
|
||||
# --hints--
|
||||
|
||||
You should use f-strings to print the sender's name using `From: {self.sender.name}`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("display_full_email").has_call("print(f'From: {self.sender.name}')")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should use f-strings to print the receiver's name using `To: {self.receiver.name}`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("display_full_email").has_call("print(f'To: {self.receiver.name}')")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
```
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
---
|
||||
id: 6853f34ff93594934f6636d9
|
||||
title: Step 27
|
||||
challengeType: 20
|
||||
dashedName: step-27
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Let's add a string representation to our `Email` class so we can display brief email summaries.
|
||||
|
||||
Add a `__str__` method to the `Email` class that takes `self` as a parameter.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a `__str__` method in the `Email` class.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").has_function("__str__")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
```
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
---
|
||||
id: 6853f4584f508e95cc7a9f4d
|
||||
title: Step 30
|
||||
challengeType: 20
|
||||
dashedName: step-30
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you'll create a method to list all emails in the inbox. This method should handle the case where the inbox is empty and display a numbered list of emails when there are emails present.
|
||||
|
||||
Add a method called `list_emails` to your `Inbox` class that takes `self` as a parameter. First, create an `if` statement to check if the inbox is empty by testing the `emails` list. If it's empty, print the message `Your inbox is empty.\n`. Add a `return` statement to exit the method.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a method named `list_emails` in the `Inbox` class that takes `self` as a parameter.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("list_emails").has_args("self")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should check if `self.emails` is empty using `if not self.emails`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("list_emails").find_ifs()[0].find_conditions()[0].is_equivalent("not self.emails")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should print the message `Your inbox is empty.\n` if there are no emails.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("list_emails").find_ifs()[0].find_body()[0].is_equivalent("print('Your inbox is empty.\\\\n')")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should have a `return` statement at the end of the `if` statement.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("list_emails").find_ifs()[0].find_body()[1].is_equivalent("return")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
---
|
||||
id: 6853f4ded9f84896ff182dd8
|
||||
title: Step 31
|
||||
challengeType: 20
|
||||
dashedName: step-31
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
After the empty inbox check, print the message `\nYour Emails:`. After that, iterate over all emails in the inbox using a `for` loop with enumeration. This is the syntax for enumeration with a starting number: `enumerate(iterable, start=start_number)`.
|
||||
|
||||
Use enumeration to number the emails starting from `1`. Use `i` (the index) and `email` (the email object) as the iteration variables.
|
||||
|
||||
Inside the loop, print an f-string with the iteration index followed by a `.`, then a space and the string representation of the email object in this format:
|
||||
|
||||
```md
|
||||
i. string_representation
|
||||
```
|
||||
|
||||
Where `i` is the index and `string_representation` is the representation of the email object.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should print the header `\nYour Emails:` outside the `if` statement.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("list_emails").find_body()[1].is_equivalent("print('\\\\nYour Emails:')")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should have a `for` loop that iterates over `enumerate(self.emails, start=1)`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
runPython(`
|
||||
_iter = _Node(_code).find_class("Inbox").find_function("list_emails").find_for_loops()[0].find_for_iter()
|
||||
assert _iter.is_equivalent("enumerate(self.emails, start=1)") or _iter.is_equivalent("enumerate(self.emails, 1)")
|
||||
`)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Your `for` loop should use `i` and `email` to iterate over `enumerate(self.emails, start=1)`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("list_emails").find_for_loops()[0].find_for_vars().is_equivalent("i, email")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Inside the loop, you should print each email summary with a numbered prefix followed by the formatted string from the `__str__` method. Don't forget to add a `.` after the number.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`
|
||||
cond = _Node(_code).find_class("Inbox").find_function("list_emails").find_for_loops()[0].find_body()
|
||||
cond.is_equivalent("print(f'{i}. {str(email)}')") or cond.is_equivalent("print(f'{i}. {email}')")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
--fcc-editable-region--
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
---
|
||||
id: 6853f553d90a2f9874ff9d0e
|
||||
title: Step 39
|
||||
challengeType: 20
|
||||
dashedName: step-39
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now we're ready to add timestamps to our emails to track when they were sent and received.
|
||||
|
||||
First, import the `datetime` module at the top of your file.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should import the datetime module at the top of the file using `import datetime`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).has_import("import datetime")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
```
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
---
|
||||
id: 6853f68dd3affa9adb2e6d99
|
||||
title: Step 41
|
||||
challengeType: 20
|
||||
dashedName: step-41
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Great! Now that you've practiced datetime formatting, remove the `current_time` variable and the print statement from the bottom of your code. We'll integrate timestamps into the `Email` class in the next step.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should not have the the statement `current_time = datetime.datetime.now()")` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_stmt("current_time = datetime.datetime.now()")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should not have the practice print statement with `strftime()` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_call("print(current_time.strftime('%H:%M:%S'))")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
--fcc-editable-region--
|
||||
current_time = datetime.datetime.now()
|
||||
print(current_time.strftime('%H:%M:%S'))
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
---
|
||||
id: 6853f70470f45d9c280af659
|
||||
title: Step 43
|
||||
challengeType: 20
|
||||
dashedName: step-43
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now let's show the timestamp when displaying the full email.
|
||||
|
||||
Below the subject, print the received timestamp using `strftime` to format it as `'%Y-%m-%d %H:%M'`. Use the following format:
|
||||
|
||||
```py
|
||||
Received: date
|
||||
```
|
||||
|
||||
Where `date` is formatted as `'%Y-%m-%d %H:%M'`.
|
||||
|
||||
|
||||
# --hints--
|
||||
|
||||
You should print the formatted timestamp using `self.timestamp.strftime('%Y-%m-%d %H:%M')`. Add `Received:` followed by a space before it.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("display_full_email").has_call('print(f"Received: {self.timestamp.strftime(\\'%Y-%m-%d %H:%M\\')}")')`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
--fcc-editable-region--
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
```
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
---
|
||||
id: 6853f90fd03acc9fd75ff860
|
||||
title: Step 46
|
||||
challengeType: 20
|
||||
dashedName: step-46
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Users should be able to check their inbox, read emails, and delete emails directly through their User object.
|
||||
|
||||
For checking the inbox, add a method called `check_inbox` to the `User` class. This method should print a personalized header with the user's name and then display all their emails.
|
||||
|
||||
The header should be formatted as: `\nName's Inbox:`, where `Name` is replaced with the name of the user.
|
||||
|
||||
After printing the header, call the `list_emails()` method on the user's inbox.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a method named `check_inbox` in the `User` class that takes `self` as a parameter.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("check_inbox").has_args("self")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
Within `check_inbox`, you should print a header that includes the user's name in the format `\n[user]'s Inbox:`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("check_inbox").find_body()[0].is_equivalent('print(f"\\\\n{self.name}\\\'s Inbox:")')`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Within `check_inbox`, you should call `self.inbox.list_emails()` to display the emails.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("check_inbox").find_body()[1].is_equivalent("self.inbox.list_emails()")`))
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f"Received: {self.timestamp.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject} | Time: {self.timestamp.strftime('%Y-%m-%d %H:%M')}"
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
print(f'Email sent from {self.name} to {receiver.name}!\n')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
```
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
---
|
||||
id: 6853f996671e63a0b4fbf143
|
||||
title: Step 47
|
||||
challengeType: 20
|
||||
dashedName: step-47
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
For reading and deleting emails, add two methods to your `User` class: `read_email` and `delete_email`. Both should take an `index` parameter and call the corresponding method on `self.inbox`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a method named `read_email` in the `User` class that takes `self` and `index` as parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("read_email").has_args("self, index")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `read_email` method should call `self.inbox.read_email(index)`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("read_email").has_call("self.inbox.read_email(index)")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should define a method named `delete_email` in the `User` class that takes `self` and `index` as parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("delete_email").has_args("self, index")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `delete_email` method should call `self.inbox.delete_email(index)`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("delete_email").has_call("self.inbox.delete_email(index)")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f"Received: {self.timestamp.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject} | Time: {self.timestamp.strftime('%Y-%m-%d %H:%M')}"
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
print(f'Email sent from {self.name} to {receiver.name}!\n')
|
||||
|
||||
def check_inbox(self):
|
||||
print(f'\n{self.name}\'s Inbox:')
|
||||
self.inbox.list_emails()
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
```
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
---
|
||||
id: 685409f3f6c765aa4cd44a26
|
||||
title: Step 49
|
||||
challengeType: 20
|
||||
dashedName: step-49
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Before sending the emails, add the standard Python idiom `if __name__ == '__main__':` followed by a call to `main()`. This ensures that the main function only runs when the script is executed directly, not when it's imported as a module.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should add the `if __name__ == '__main__':` check outside the `main` function.
|
||||
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_ifs()[0].find_conditions()[0].is_equivalent("__name__ == '__main__'")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should call `main()` inside the `if __name__ == '__main__':` block.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_ifs()[0].find_body().is_equivalent("main()")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f"Received: {self.timestamp.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject} | Time: {self.timestamp.strftime('%Y-%m-%d %H:%M')}"
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
print(f'Email sent from {self.name} to {receiver.name}!\n')
|
||||
|
||||
def check_inbox(self):
|
||||
print(f"\n{self.name}'s Inbox:")
|
||||
self.inbox.list_emails()
|
||||
|
||||
def read_email(self, index):
|
||||
self.inbox.read_email(index)
|
||||
|
||||
def delete_email(self, index):
|
||||
self.inbox.delete_email(index)
|
||||
|
||||
def main():
|
||||
tory = User('Tory')
|
||||
ramy = User('Ramy')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
---
|
||||
id: 68540a534c56aeabae6afd58
|
||||
title: Step 50
|
||||
challengeType: 20
|
||||
dashedName: step-50
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you'll simulate sending some emails between the users.
|
||||
|
||||
In your `main` function, after creating the users, use the `send_email` method to:
|
||||
|
||||
- Have Tory send an email to the `ramy` user object with subject `Hello` and body `Hi Ramy, just saying hello!`.
|
||||
- Have Ramy send an email to the `tory` user object with subject `Re: Hello` and body `Hi Tory, hope you are fine.`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have Tory send an email to `ramy`, subject `Hello`, and body `Hi Ramy, just saying hello!`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("main").find_body()[2].is_equivalent("tory.send_email(ramy, 'Hello', 'Hi Ramy, just saying hello!')")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should have Ramy send an email to `tory`, subject `Re: Hello`, and body `Hi Tory, hope you are fine.`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("main").find_body()[3].is_equivalent("ramy.send_email(tory, 'Re: Hello', 'Hi Tory, hope you are fine.')")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f"Received: {self.timestamp.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject} | Time: {self.timestamp.strftime('%Y-%m-%d %H:%M')}"
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
print(f'Email sent from {self.name} to {receiver.name}!\n')
|
||||
|
||||
def check_inbox(self):
|
||||
print(f"\n{self.name}'s Inbox:")
|
||||
self.inbox.list_emails()
|
||||
|
||||
def read_email(self, index):
|
||||
self.inbox.read_email(index)
|
||||
|
||||
def delete_email(self, index):
|
||||
self.inbox.delete_email(index)
|
||||
|
||||
--fcc-editable-region--
|
||||
def main():
|
||||
tory = User('Tory')
|
||||
ramy = User('Ramy')
|
||||
|
||||
--fcc-editable-region--
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
```
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
---
|
||||
id: 68540aa7dfd449ad074c285c
|
||||
title: Step 51
|
||||
challengeType: 20
|
||||
dashedName: step-51
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you'll demonstrate the inbox functionality. Ramy will check his inbox, read the first email, delete the second email, and then check his inbox again to see the changes.
|
||||
|
||||
In your `main` function, after sending the emails, add code to:
|
||||
|
||||
- Have Ramy check his inbox using the `check_inbox` method.
|
||||
- Have Ramy read the first email.
|
||||
- Have Ramy delete the first email.
|
||||
- Have Ramy check his inbox again.
|
||||
|
||||
With this, you have completed the email simulator!
|
||||
|
||||
# --hints--
|
||||
|
||||
You should call `ramy.check_inbox()` to show Ramy's emails.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("main").find_body().has_stmt("ramy.check_inbox()")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should call `ramy.read_email(1)` to read the first email.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("main").find_body().has_stmt("ramy.read_email(1)")`))
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You should call `ramy.delete_email(1)` to delete the first email.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("main").find_body().has_stmt("ramy.delete_email(1)")`))
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You should call `ramy.check_inbox()` again to show the updated inbox.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("main").find_body().is_ordered("ramy.delete_email(1)", "ramy.check_inbox()")`))
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f"Received: {self.timestamp.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject} | Time: {self.timestamp.strftime('%Y-%m-%d %H:%M')}"
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
print(f'Email sent from {self.name} to {receiver.name}!\n')
|
||||
|
||||
def check_inbox(self):
|
||||
print(f"\n{self.name}'s Inbox:")
|
||||
self.inbox.list_emails()
|
||||
|
||||
def read_email(self, index):
|
||||
self.inbox.read_email(index)
|
||||
|
||||
def delete_email(self, index):
|
||||
self.inbox.delete_email(index)
|
||||
|
||||
--fcc-editable-region--
|
||||
def main():
|
||||
tory = User('Tory')
|
||||
ramy = User('Ramy')
|
||||
|
||||
tory.send_email(ramy, 'Hello', 'Hi Ramy, just saying hello!')
|
||||
ramy.send_email(tory, 'Re: Hello', 'Hi Tory, hope you are fine.')
|
||||
|
||||
|
||||
--fcc-editable-region--
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f"Received: {self.timestamp.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject} | Time: {self.timestamp.strftime('%Y-%m-%d %H:%M')}"
|
||||
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
print(f'Email sent from {self.name} to {receiver.name}!\n')
|
||||
|
||||
def check_inbox(self):
|
||||
print(f"\n{self.name}'s Inbox:")
|
||||
self.inbox.list_emails()
|
||||
|
||||
def read_email(self, index):
|
||||
self.inbox.read_email(index)
|
||||
|
||||
def delete_email(self, index):
|
||||
self.inbox.delete_email(index)
|
||||
|
||||
|
||||
def main():
|
||||
# Create users
|
||||
tory = User('Tory')
|
||||
ramy = User('Ramy')
|
||||
|
||||
# Send emails
|
||||
tory.send_email(ramy, 'Hello', 'Hi Ramy, just saying hello!')
|
||||
ramy.send_email(tory, 'Re: Hello', 'Hi Tory, hope you are fine.')
|
||||
|
||||
# Ramy checks inbox
|
||||
ramy.check_inbox()
|
||||
|
||||
# Ramy reads first email (now uses 1-based indexing)
|
||||
ramy.read_email(1)
|
||||
|
||||
# Ramy deletes first email (now uses 1-based indexing)
|
||||
ramy.delete_email(1)
|
||||
|
||||
# Ramy checks inbox again
|
||||
ramy.check_inbox()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
```
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
---
|
||||
id: 68593ea22eac7e228ed585ce
|
||||
title: Step 5
|
||||
challengeType: 20
|
||||
dashedName: step-5
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Emails should track whether they've been read or not. Add a `read` attribute to the `__init__` method and set it to `False` by default, since new emails start as unread.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should assign `False` to ``self.read` in the `__init__` method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
assert _Node(_code).find_class("Email").find_function("__init__").find_variable("self.read").is_equivalent("self.read = False")
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
|
||||
--fcc-editable-region--
|
||||
email_obj = Email('alice@example.com', 'bob@example.com', 'Hello', 'Hi Bob!')
|
||||
print(email_obj.sender)
|
||||
print(email_obj.subject)
|
||||
```
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
---
|
||||
id: 6859400f8f7f872e50e1238c
|
||||
title: Step 11
|
||||
challengeType: 20
|
||||
dashedName: step-11
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The `User` class needs a method to send emails to other users. When sending an email, you'll create a new `Email` object and add it to the receiver's inbox.
|
||||
|
||||
Create a method called `send_email` in your `User` class. This method should take parameters for `receiver`, `subject`, and `body`.
|
||||
|
||||
Inside the method, create a new `Email` object with the following parameter values and assign it to a variable named `email`:
|
||||
|
||||
- `sender`: `self` (the current user)
|
||||
- `receiver`: `receiver` (the user receiving the email)
|
||||
- `subject`: `subject` (the subject of the email)
|
||||
- `body`: `body` (the body of the email)
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a `send_email` method in the `User` class.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("User").has_function("send_email")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
The `send_email` method should have parameters: `self`, `receiver`, `subject`, and `body`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("send_email").has_args("self, receiver, subject, body")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
The method should create an `Email` object named `email` with the correct parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`
|
||||
cond = _Node(_code).find_class("User").find_function("send_email").find_body()[0]
|
||||
cond.is_equivalent("email = Email(sender=self, receiver=receiver, subject=subject, body=body)") or cond.is_equivalent("email = Email(self, receiver, subject, body)")
|
||||
`));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
---
|
||||
id: 685941422c30cd3dc41b1d0a
|
||||
title: Step 22
|
||||
challengeType: 20
|
||||
dashedName: step-22
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now let's add a header to the email display. In the `display_full_email` method, after calling `mark_as_read()`, print `\n--- Email ---` to start the email display with a clear header.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should print the header `\n--- Email ---` in the `display_full_email` method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("display_full_email").has_call("print('\\\\n--- Email ---')")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
```
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
---
|
||||
id: 68594df7779a164e6a61e8ae
|
||||
title: Step 32
|
||||
challengeType: 20
|
||||
dashedName: step-32
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The inbox needs a method to read a specific email. When a user wants to read an email, they'll specify which email number (starting from index 0) they want to see, and the method will display the full email content.
|
||||
|
||||
Add a method called `read_email` to your `Inbox` class that takes an `index` parameter. First, check if the inbox is empty and print the message `Inbox is empty.\n` if it is. Add a `return` statement after that to exit the method.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a method named `read_email` in the `Inbox` class that takes `self` and `index` as parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("read_email").has_args("self, index")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should check if `self.emails` is empty using `if not self.emails`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("read_email").find_ifs()[0].find_conditions()[0].is_equivalent("not self.emails")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should print `Inbox is empty.\n` if there are no emails and return.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("read_email").find_ifs()[0].find_body()[0].is_equivalent("print('Inbox is empty.\\\\n')")`));
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("read_email").find_ifs()[0].find_body()[1].is_equivalent("return")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
---
|
||||
id: 6859523c793377706e19e9a0
|
||||
title: Step 42
|
||||
challengeType: 20
|
||||
dashedName: step-42
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now let's add timestamps to our emails. In the Email class `__init__` method, create a `timestamp` attribute and assign the current time to it to automatically set a timestamp for when the email was created.
|
||||
|
||||
This is helpful for tracking when messages were sent and received.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `self.timestamp` in the Email `__init__` method and assign `datetime.datetime.now()` to it.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__init__").has_stmt("self.timestamp = datetime.datetime.now()")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
--fcc-editable-region--
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
```
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
---
|
||||
id: 685a82a54950823ef954276a
|
||||
title: Step 48
|
||||
challengeType: 20
|
||||
dashedName: step-48
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you'll create the main function that demonstrates your email simulator.
|
||||
|
||||
Create the `main` function and inside it, using the `User` class, create two users: `Tory` and `Ramy` and assign them to variables `tory` and `ramy`, respectively.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a function named `main`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).has_function("main")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should create a user named `Tory` and assign it to a variable called `tory`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("main").find_variable("tory").is_equivalent("tory = User('Tory')")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should create a user named `Ramy` and assign it to a variable called `ramy`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("main").find_variable("ramy").is_equivalent("ramy = User('Ramy')")`))
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f"Received: {self.timestamp.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject} | Time: {self.timestamp.strftime('%Y-%m-%d %H:%M')}"
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
print(f'Email sent from {self.name} to {receiver.name}!\n')
|
||||
|
||||
def check_inbox(self):
|
||||
print(f"\n{self.name}'s Inbox:")
|
||||
self.inbox.list_emails()
|
||||
|
||||
def read_email(self, index):
|
||||
self.inbox.read_email(index)
|
||||
|
||||
def delete_email(self, index):
|
||||
self.inbox.delete_email(index)
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
---
|
||||
id: 685c1e32254e5993a5c8823e
|
||||
title: Step 10
|
||||
challengeType: 20
|
||||
dashedName: step-10
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now that you have an initial setup of the `Email` class, it's time to create users who can send and receive emails. Each user will have a name and will be able to perform email operations.
|
||||
|
||||
Create a `User` class with an `__init__` method that takes `self` and `name` as parameters. Within the class, assign the `name` parameter to `self.name`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create a `User` class.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).has_class("User")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
The `User` class should have an `__init__` method that takes `self` and `name` as parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("__init__").has_args("self, name")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should assign the `name` parameter to `self.name`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("__init__").find_variable("self.name").is_equivalent("self.name = name")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
---
|
||||
id: 685c1eba966c6396850736ea
|
||||
title: Step 13
|
||||
challengeType: 20
|
||||
dashedName: step-13
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
While users can send emails and have inboxes, we need a dedicated class to manage inbox operations efficiently.
|
||||
|
||||
The `Inbox` class will store a list of emails and provide methods to add new emails, list all emails, and manage them.
|
||||
|
||||
Create a new class called `Inbox` with an `__init__` method that initializes an empty list called `emails`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create an `Inbox` class.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).has_class("Inbox")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `Inbox` class should have an `__init__` method that takes `self` as a parameter.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("__init__").has_args("self")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should initialize `self.emails = []` in the `Inbox` class `__init__` method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("__init__").find_variable("self.emails").is_equivalent("self.emails = []")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = []
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
---
|
||||
id: 685cdabd4cded3b340193f72
|
||||
title: Step 24
|
||||
challengeType: 20
|
||||
dashedName: step-24
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now add the subject line to the email display. In the `display_full_email` method, add a print statement to show the email's subject in this format:
|
||||
|
||||
- `Subject: subject` where `subject` is replaced with the subject of the email
|
||||
|
||||
# --hints--
|
||||
|
||||
You should use f-strings to print the subject using `Subject: {self.subject}`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("display_full_email").has_call("print(f'Subject: {self.subject}')")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
```
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
---
|
||||
id: 685cdfd1932d8ac6ad986813
|
||||
title: Step 28
|
||||
challengeType: 20
|
||||
dashedName: step-28
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Within the `__str__` method, you'll show whether an email has been read or not.
|
||||
|
||||
Conditional expressions allow you to assign a value based on a condition in a single line.
|
||||
|
||||
Here is an example:
|
||||
|
||||
```py
|
||||
x = 10
|
||||
y = 'Even' if x % 2 == 0 else 'Odd' # y will be even
|
||||
```
|
||||
|
||||
Within the method, before, use conditional expression to assign the string `Read` to a variable `status` if the email is read and `Unread` if it is not.
|
||||
|
||||
# --hints--
|
||||
|
||||
The `__str__` method should create a `status` variable that uses a conditional expression.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__str__").has_stmt("status = 'Read' if self.read else 'Unread'")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `__str__` method should return the email information with the status included.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__str__").has_variable("status")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
--fcc-editable-region--
|
||||
def __str__(self):
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
```
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
---
|
||||
id: 685d2fd1f309b9191f257c55
|
||||
title: Step 40
|
||||
challengeType: 20
|
||||
dashedName: step-40
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Before integrating timestamps into our email system, let's practice working with datetime formatting. The `datetime.datetime.now()` function gives us the current date and time, and we can use the `strftime()` method to format it in different ways.
|
||||
|
||||
Here's how `strftime()` works with format codes:
|
||||
|
||||
```python
|
||||
now = datetime.datetime.now()
|
||||
print(now.strftime("%Y-%m-%d")) # Output: 2024-03-15 (year-month-day with - separator)
|
||||
```
|
||||
|
||||
The format codes like `%Y` (year), `%m` (month), `%d` (day) tell `strftime()` what to include, and you can add separators like `-` between them.
|
||||
|
||||
At the bottom of your code, create a variable called `current_time` and assign it `datetime.datetime.now()`. Then use `strftime()` to print the time in hours:minutes:seconds format using `:` as the separator.
|
||||
|
||||
Use these format codes: `%H` for hours (24-hour format), `%M` for minutes, and `%S` for seconds.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create a variable called `current_time` and assign it `datetime.datetime.now()`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).has_stmt("current_time = datetime.datetime.now()")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should use `strftime()` to print the time in `%H:%M:%S` format.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).has_call("print(current_time.strftime('%H:%M:%S'))")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
---
|
||||
id: 685d53b5e4f5784562a12d1b
|
||||
title: Step 45
|
||||
challengeType: 20
|
||||
dashedName: step-45
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Users should get confirmation when they successfully send an email. Let's improve the user experience by adding feedback to the `send_email` method.
|
||||
|
||||
In the `send_email` method of the `User` class, add a print statement after the email is sent that shows confirmation. The message should include both the sender's name and the receiver's name in this format: `Email sent from [sender_name] to [receiver_name]!\n`
|
||||
|
||||
# --hints--
|
||||
|
||||
You should add a print statement in the `send_email` method that confirms the email was sent.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("send_email").has_call("print(f'Email sent from {self.name} to {receiver.name}!\\\\n')")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f"Received: {self.timestamp.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject} | Time: {self.timestamp.strftime('%Y-%m-%d %H:%M')}"
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
--fcc-editable-region--
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
```
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
---
|
||||
id: 685d53ec88a16a4643c2437b
|
||||
title: Step 44
|
||||
challengeType: 20
|
||||
dashedName: step-44
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now let's also show timestamps in the email listing. Update the `__str__` method in the `Email` class to include the timestamp after the subject.
|
||||
|
||||
Modify the return statement to include the timestamp formatted as `'%Y-%m-%d %H:%M'` at the end, separated by ` | Time: `.
|
||||
|
||||
The complete format should be:
|
||||
|
||||
```py
|
||||
[status] From: sender | Subject: subject | Time: time
|
||||
```
|
||||
|
||||
Where `status` is the status of the email, `sender` is the sender's name, `subject` is the subject of the email, and `time` is in the format `'%Y-%m-%d %H:%M'`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should update the `__str__` method to include the formatted timestamp.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__str__").has_stmt("return f\\"[{status}] From: {self.sender.name} | Subject: {self.subject} | Time: {self.timestamp.strftime('%Y-%m-%d %H:%M')}\\"")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import datetime
|
||||
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.timestamp = datetime.datetime.now()
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f"Received: {self.timestamp.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
--fcc-editable-region--
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
del self.emails[actual_index]
|
||||
print('Email deleted.\n')
|
||||
```
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
---
|
||||
id: 688754d6d59578df1313cb3c
|
||||
title: Step 14
|
||||
challengeType: 20
|
||||
dashedName: step-14
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now it's time to connect the User and Inbox classes so that emails can actually be delivered!
|
||||
|
||||
Users need to have proper Inbox objects instead of simple lists, and the `send_email` method should deliver emails to the receiver's inbox.
|
||||
|
||||
Update the `User` class `__init__` in a way that each user gets an actual Inbox object instead of an empty list created earlier.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should update the User class to initialize `self.inbox = Inbox()`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("__init__").find_variable("self.inbox").is_equivalent("self.inbox = Inbox()")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = []
|
||||
--fcc-editable-region--
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
```
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
---
|
||||
id: 688754f3494b17e0b352d67d
|
||||
title: Step 17
|
||||
challengeType: 20
|
||||
dashedName: step-17
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now it's time to test our complete email system! Let's create some users and see the email functionality in action.
|
||||
|
||||
Create two User objects: `alice` with name `"Alice"` and `bob` with name `"Bob"`. This will demonstrate how users can be created and interact with each other.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create a User object named `alice` with name `"Alice"`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_variable("alice").is_equivalent('alice = User("Alice")')`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should create a User object named `bob` with name `"Bob"`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_variable("bob").is_equivalent('bob = User("Bob")')`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
---
|
||||
id: 6887550fe36f64e27074475a
|
||||
title: Step 18
|
||||
challengeType: 20
|
||||
dashedName: step-18
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Have Alice send an email to Bob to see if the email delivery works correctly.
|
||||
|
||||
Use Alice's `send_email` method to send Bob an email with subject `"Hello"` and body `"Hi Bob, how are you?"`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should call `alice.send_email()` with the correct parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).has_call('alice.send_email(bob, "Hello", "Hi Bob, how are you?")')`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
--fcc-editable-region--
|
||||
alice = User("Alice")
|
||||
bob = User("Bob")
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
---
|
||||
id: 68875521efc1a4e3f0c570e3
|
||||
title: Step 19
|
||||
challengeType: 20
|
||||
dashedName: step-19
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now let's verify that the email was delivered successfully by printing the length of Bob's inbox emails.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should print the length of Bob's inbox emails using `len(bob.inbox.emails)`
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).has_call("print(len(bob.inbox.emails))")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
--fcc-editable-region--
|
||||
alice = User("Alice")
|
||||
bob = User("Bob")
|
||||
|
||||
alice.send_email(bob, "Hello", "Hi Bob, how are you?")
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
---
|
||||
id: 68875554c6c32de788afc64e
|
||||
title: Step 21
|
||||
challengeType: 20
|
||||
dashedName: step-21
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Users need a way to read their emails properly.
|
||||
|
||||
Add a `display_full_email` method to the `Email` class that takes only `self` as a parameter. Inside this method, call `mark_as_read()` method to mark the email as read when someone views it.
|
||||
|
||||
This method would be used to display the email's full content in a nicely formatted way.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a `display_full_email` method in the `Email` class.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").has_function("display_full_email")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `display_full_email` method should take only `self` as a parameter.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("display_full_email").has_args("self")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The method should call `self.mark_as_read()` to mark the email as read.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("display_full_email").has_call("self.mark_as_read()")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
```
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
---
|
||||
id: 688798fccea91f522d1f245e
|
||||
title: Step 33
|
||||
challengeType: 20
|
||||
dashedName: step-33
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
When the inbox is not empty, you'll try to access the email at the given index and display it.
|
||||
|
||||
Remember in the `list_emails` method, you displayed email numbers starting from 1, but list indices in Python start from 0. So, you'll need to convert the 1-based index to a 0-based index by subtracting 1.
|
||||
|
||||
Within the `read_email` method, subtract 1 from the `index` parameter and store it in a variable called `actual_index`.
|
||||
|
||||
|
||||
# --hints--
|
||||
|
||||
You should subtract 1 from the `index` parameter and store it in a variable called `actual_index`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("read_email").find_body().find_variable("actual_index").is_equivalent("actual_index = index - 1")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
--fcc-editable-region--
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
---
|
||||
id: 68879d0a2aeb368e26559635
|
||||
title: Step 26
|
||||
challengeType: 20
|
||||
dashedName: step-26
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Finally, let's add a footer to complete the email display format. Add a final print statement: `print('------------\n')` to close off the email display with a nice separator line.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should print the footer `------------\n` at the end of the `display_full_email` method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("display_full_email").has_call("print('------------\\\\n')")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
```
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
---
|
||||
id: 68879d6de6398893be8c4b7b
|
||||
title: Step 25
|
||||
challengeType: 20
|
||||
dashedName: step-25
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now add the email body to complete the main content. In the `display_full_email` method, add another print statement in the format `Body: body` (where `body` is the content of the email) to show the email's content.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should print the email body using `f'Body: {self.body}'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("display_full_email").has_call("print(f'Body: {self.body}')")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
```
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
---
|
||||
id: 68b930ee0e7b8fb81895e59a
|
||||
title: Step 7
|
||||
challengeType: 20
|
||||
dashedName: step-7
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you'll add a method to mark an email as read. When someone opens an email, you want to change its status from unread to read. This method will be simple - it just needs to set the `read` attribute to `True`.
|
||||
|
||||
Add a method called `mark_as_read` to your `Email` class. This method should take only `self` as a parameter and set the `read` attribute to `True`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a method named `mark_as_read` in the `Email` class.
|
||||
that should only take `self` as a parameter.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("mark_as_read").has_args("self")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
The method should set `self.read` to `True`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("mark_as_read").find_variable("self.read").is_equivalent("self.read = True")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
--fcc-editable-region--
|
||||
email_obj = Email('alice@example.com', 'bob@example.com', 'Hello', 'Hi Bob!')
|
||||
print(email_obj.sender)
|
||||
print(email_obj.subject)
|
||||
print(email_obj.read)
|
||||
```
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
---
|
||||
id: 68b9350183ff05bd106c79e4
|
||||
title: Step 8
|
||||
challengeType: 20
|
||||
dashedName: step-8
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, test the `mark_as_read` method you created in the `Email` class. Use the method on the existing `Email` object `email_obj` to change the status. After marking the email as read, print the `read` attribute of `email_obj` to confirm the change.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should call the `mark_as_read` method on the `email_obj` to mark the email as read.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).has_call("email_obj.mark_as_read()")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should print the `read` attribute of the `email_obj` after calling the `mark_as_read` method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).is_ordered("email_obj.mark_as_read()", "print(email_obj.read)")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
email_obj = Email('alice@example.com', 'bob@example.com', 'Hello', 'Hi Bob!')
|
||||
print(email_obj.sender)
|
||||
print(email_obj.subject)
|
||||
print(email_obj.read)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
---
|
||||
id: 68b9366fae8b13c1278761b1
|
||||
title: Step 15
|
||||
challengeType: 20
|
||||
dashedName: step-15
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Your inbox needs a way to receive new emails. When someone sends an email to a user, it should be added to their inbox.
|
||||
|
||||
Add a method called `receive_email` to your `Inbox` class. that takes `self` and an email object `email` as a parameter. Within the method body, add the `email` to the `emails` list using the `append` method.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a method named `receive_email` in the `Inbox` class that takes `self` and `email` as parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("receive_email").has_args("self, email")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should append the `email` to `self.emails`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("receive_email").has_stmt("self.emails.append(email)")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
|
||||
--fcc-editable-region--
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
---
|
||||
id: 68b936bf4f47d6c29a669f99
|
||||
title: Step 16
|
||||
challengeType: 20
|
||||
dashedName: step-16
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Modify the `send_email` method to add the email to the receiver's inbox by calling the `receive_email` method of the `Inbox` class.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should add `receiver.inbox.receive_email(email)` to the `send_email` method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("User").find_function("send_email").has_stmt("receiver.inbox.receive_email(email)")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
--fcc-editable-region--
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
```
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
---
|
||||
id: 68b96d6a290d52d5e57a7485
|
||||
title: Step 9
|
||||
challengeType: 20
|
||||
dashedName: step-9
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Remove the `email_obj` and the following print statements.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should not have the `email_obj` creation line in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_stmt("email_obj = Email('alice@example.com', 'bob@example.com', 'Hello', 'Hi Bob!')")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should not have `print(email_obj.sender)` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_call("print(email_obj.sender)")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should not have `print(email_obj.subject)` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_call("print(email_obj.subject)")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should not have `print(email_obj.read)` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_call("print(email_obj.read)")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should not have `email_obj.mark_as_read()` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_call("email_obj.mark_as_read()")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
--fcc-editable-region--
|
||||
email_obj = Email('alice@example.com', 'bob@example.com', 'Hello', 'Hi Bob!')
|
||||
print(email_obj.sender)
|
||||
print(email_obj.subject)
|
||||
print(email_obj.read)
|
||||
email_obj.mark_as_read()
|
||||
print(email_obj.read)
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
---
|
||||
id: 68b9a011daf902ff1eba40a8
|
||||
title: Step 20
|
||||
challengeType: 20
|
||||
dashedName: step-20
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now that the email has been received, remove object creations, method calls, and print statements.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should not have `alice = User("Alice")` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_stmt("alice = User(\\"Alice\\")")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should not have `bob = User("Bob")` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_stmt("bob = User(\\"Bob\\")")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should not have `alice.send_email(bob, "Hello", "Hi Bob, how are you?")` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_call("alice.send_email(bob, \\"Hello\\", \\"Hi Bob, how are you?\\")")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should not have `print(len(bob.inbox.emails))` in your code.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(!runPython(`_Node(_code).has_call("print(len(bob.inbox.emails))")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
--fcc-editable-region--
|
||||
alice = User("Alice")
|
||||
bob = User("Bob")
|
||||
|
||||
alice.send_email(bob, "Hello", "Hi Bob, how are you?")
|
||||
|
||||
print(len(bob.inbox.emails))
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
---
|
||||
id: 68be6a4447e61c4395ef2359
|
||||
title: Step 36
|
||||
challengeType: 20
|
||||
dashedName: step-36
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Your inbox also needs a way to delete emails.
|
||||
|
||||
Python's `del` keyword can be used to delete items from a list by their index.
|
||||
|
||||
Add a method called `delete_email` to your `Inbox` class. Like `read_email`, it should:
|
||||
|
||||
- Take an `index` parameter, check for an empty inbox, and print the message `Inbox is empty.\n` if it is. Use `return` to exit the method.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a method named `delete_email` in the `Inbox` class that takes `self` and `index` as parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("delete_email").has_args("self,index")`))
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You should check if the inbox is empty first using `if not self.emails:`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("delete_email").find_ifs()[0].find_conditions()[0].is_equivalent("not self.emails")`))
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
If inbox is empty, you should print the message `Inbox is empty.\n` and use `return` to exit the method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("delete_email").find_ifs()[0].find_body().is_equivalent("print('Inbox is empty.\\\\n')\\nreturn")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
---
|
||||
id: 68be6af1f43cc44541debe41
|
||||
title: Step 37
|
||||
challengeType: 20
|
||||
dashedName: step-37
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
You should handle the case where the user tries to delete an email using an invalid index just like you did in the `read_email` method.
|
||||
|
||||
Within the `delete_email` method:
|
||||
|
||||
- Convert the 1-based `index` parameter to a 0-based index by subtracting 1 and storing it in a variable called `actual_index`.
|
||||
- Create an if statement to check if the `actual_index` is less than 0 or greater than or equal to the length of the `self.emails` list. If it is, print the message `Invalid email number.\n` and use `return` to exit the method.
|
||||
|
||||
# --hints--
|
||||
|
||||
|
||||
You should subtract 1 from the `index` parameter and store it in a variable called `actual_index`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("delete_email").find_body().find_variable("actual_index").is_equivalent("actual_index = index - 1")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should create an if statement to check if the `actual_index` is less than 0 or greater than or equal to the length of the `self.emails` list.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("delete_email").find_ifs()[1].find_conditions()[0].is_equivalent("actual_index < 0 or actual_index >= len(self.emails)")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Within the `if` statememt, you should print the message `Invalid email number.\n` and use `return` to exit the method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("delete_email").find_ifs()[1].find_body()[0].is_equivalent("print('Invalid email number.\\\\n')")`))
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("delete_email").find_ifs()[1].find_body()[1].is_equivalent("return")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
--fcc-editable-region--
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
---
|
||||
id: 68bf0f09b7ec33be465c0c35
|
||||
title: Step 29
|
||||
challengeType: 20
|
||||
dashedName: step-29
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
At the end of the `__str__` method, return the email summary in this format:
|
||||
|
||||
```py
|
||||
[status] From: sender | Subject: subject.
|
||||
```
|
||||
|
||||
Where `status` is the status of the email, `sender` is the sender's name and `subject` is the subject of the email.
|
||||
|
||||
# --hints--
|
||||
|
||||
The `__str__` method should return `f"[{status}] From: {self.sender.name} | Subject: {self.subject}"`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`_Node(_code).find_class("Email").find_function("__str__").has_return("f\\"[{status}] From: {self.sender.name} | Subject: {self.subject}\\"")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
--fcc-editable-region--
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
--fcc-editable-region--
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
```
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
---
|
||||
id: 68dfc5082ea4b4cdcf09dd58
|
||||
title: Step 34
|
||||
challengeType: 20
|
||||
dashedName: step-34
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
After getting the actual index, create an if statement to check if the `actual_index` is less than 0 or greater than or equal to the length of the `self.emails` list. If it is, print the message `Invalid email number.\n` and use `return` to exit the method.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create an if statement to check if the `actual_index` is less than 0 or greater than or equal to the length of the `self.emails` list.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("read_email").find_ifs()[1].find_conditions()[0].is_equivalent("actual_index < 0 or actual_index >= len(self.emails)")`))
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
If the index is invalid, you should print the message `Invalid email number.\n` and use `return` to exit the method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("read_email").find_ifs()[1].find_body()[0].is_equivalent("print('Invalid email number.\\\\n')")`))
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("read_email").find_ifs()[1].find_body()[1].is_equivalent("return")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
--fcc-editable-region--
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
---
|
||||
id: 68dfc5f71dc2a6d65091a39c
|
||||
title: Step 35
|
||||
challengeType: 20
|
||||
dashedName: step-35
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
When the email index is valid, access the email at `actual_index`, call its `display_full_email` method to show the email content.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should access the email at `actual_index` in the `self.emails` list and call its `display_full_email` method.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("read_email").find_body().has_stmt("self.emails[actual_index].display_full_email()")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
--fcc-editable-region--
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
---
|
||||
id: 68dfc80941fa2ef744c64cd6
|
||||
title: Step 38
|
||||
challengeType: 20
|
||||
dashedName: step-38
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
When the inbox is not empty, and the email index is valid, delete the email at the given index using the `del` keyword and print a confirmation message `Email deleted.\n`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should use the `del` keyword to delete the email at `actual_index` in the `self.emails` list.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("delete_email").find_body().has_stmt("del self.emails[actual_index]")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should print the message `Email deleted.\n` after deleting the email.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_class("Inbox").find_function("delete_email").find_body().has_call("print('Email deleted.\\\\n')")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Email:
|
||||
def __init__(self, sender, receiver, subject, body):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.subject = subject
|
||||
self.body = body
|
||||
self.read = False
|
||||
|
||||
def mark_as_read(self):
|
||||
self.read = True
|
||||
|
||||
def display_full_email(self):
|
||||
self.mark_as_read()
|
||||
print('\n--- Email ---')
|
||||
print(f'From: {self.sender.name}')
|
||||
print(f'To: {self.receiver.name}')
|
||||
print(f'Subject: {self.subject}')
|
||||
print(f'Body: {self.body}')
|
||||
print('------------\n')
|
||||
|
||||
def __str__(self):
|
||||
status = 'Read' if self.read else 'Unread'
|
||||
return f"[{status}] From: {self.sender.name} | Subject: {self.subject}"
|
||||
|
||||
class User:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.inbox = Inbox()
|
||||
|
||||
def send_email(self, receiver, subject, body):
|
||||
email = Email(sender=self, receiver=receiver, subject=subject, body=body)
|
||||
receiver.inbox.receive_email(email)
|
||||
|
||||
class Inbox:
|
||||
def __init__(self):
|
||||
self.emails = []
|
||||
|
||||
def receive_email(self, email):
|
||||
self.emails.append(email)
|
||||
|
||||
def list_emails(self):
|
||||
if not self.emails:
|
||||
print('Your inbox is empty.\n')
|
||||
return
|
||||
print('\nYour Emails:')
|
||||
for i, email in enumerate(self.emails, start=1):
|
||||
print(f'{i}. {email}')
|
||||
|
||||
def read_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
self.emails[actual_index].display_full_email()
|
||||
|
||||
--fcc-editable-region--
|
||||
def delete_email(self, index):
|
||||
if not self.emails:
|
||||
print('Inbox is empty.\n')
|
||||
return
|
||||
actual_index = index - 1
|
||||
if actual_index < 0 or actual_index >= len(self.emails):
|
||||
print('Invalid email number.\n')
|
||||
return
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"name": "Build an Email Simulator",
|
||||
"isUpcomingChange": true,
|
||||
"dashedName": "workshop-email-simulator",
|
||||
"helpCategory": "Python",
|
||||
"blockLayout": "challenge-grid",
|
||||
"blockType": "workshop",
|
||||
"challengeOrder": [
|
||||
{ "id": "6852ea0c3cadb54e897acdac", "title": "Step 1" },
|
||||
{ "id": "6852ef95ccc27660275692cd", "title": "Step 2" },
|
||||
{ "id": "6852f01116912861c7d1b0e6", "title": "Step 3" },
|
||||
{ "id": "6852f06fdde1b4634a263f03", "title": "Step 4" },
|
||||
{ "id": "68593ea22eac7e228ed585ce", "title": "Step 5" },
|
||||
{ "id": "6852f0c3fcedb964ab959921", "title": "Step 6" },
|
||||
{ "id": "68b930ee0e7b8fb81895e59a", "title": "Step 7" },
|
||||
{ "id": "68b9350183ff05bd106c79e4", "title": "Step 8" },
|
||||
{ "id": "68b96d6a290d52d5e57a7485", "title": "Step 9" },
|
||||
{ "id": "685c1e32254e5993a5c8823e", "title": "Step 10" },
|
||||
{ "id": "6859400f8f7f872e50e1238c", "title": "Step 11" },
|
||||
{ "id": "6852f11d412c29665985a915", "title": "Step 12" },
|
||||
{ "id": "685c1eba966c6396850736ea", "title": "Step 13" },
|
||||
{ "id": "688754d6d59578df1313cb3c", "title": "Step 14" },
|
||||
{ "id": "68b9366fae8b13c1278761b1", "title": "Step 15" },
|
||||
{ "id": "68b936bf4f47d6c29a669f99", "title": "Step 16" },
|
||||
{ "id": "688754f3494b17e0b352d67d", "title": "Step 17" },
|
||||
{ "id": "6887550fe36f64e27074475a", "title": "Step 18" },
|
||||
{ "id": "68875521efc1a4e3f0c570e3", "title": "Step 19" },
|
||||
{ "id": "68b9a011daf902ff1eba40a8", "title": "Step 20" },
|
||||
{ "id": "68875554c6c32de788afc64e", "title": "Step 21" },
|
||||
{ "id": "685941422c30cd3dc41b1d0a", "title": "Step 22" },
|
||||
{ "id": "6853f2da9b8ed891e9fdc5fc", "title": "Step 23" },
|
||||
{ "id": "685cdabd4cded3b340193f72", "title": "Step 24" },
|
||||
{ "id": "68879d6de6398893be8c4b7b", "title": "Step 25" },
|
||||
{ "id": "68879d0a2aeb368e26559635", "title": "Step 26" },
|
||||
{ "id": "6853f34ff93594934f6636d9", "title": "Step 27" },
|
||||
{ "id": "685cdfd1932d8ac6ad986813", "title": "Step 28" },
|
||||
{ "id": "68bf0f09b7ec33be465c0c35", "title": "Step 29" },
|
||||
{ "id": "6853f4584f508e95cc7a9f4d", "title": "Step 30" },
|
||||
{ "id": "6853f4ded9f84896ff182dd8", "title": "Step 31" },
|
||||
{ "id": "68594df7779a164e6a61e8ae", "title": "Step 32" },
|
||||
{ "id": "688798fccea91f522d1f245e", "title": "Step 33" },
|
||||
{ "id": "68dfc5082ea4b4cdcf09dd58", "title": "Step 34" },
|
||||
{ "id": "68dfc5f71dc2a6d65091a39c", "title": "Step 35" },
|
||||
{ "id": "68be6a4447e61c4395ef2359", "title": "Step 36" },
|
||||
{ "id": "68be6af1f43cc44541debe41", "title": "Step 37" },
|
||||
{ "id": "68dfc80941fa2ef744c64cd6", "title": "Step 38" },
|
||||
{ "id": "6853f553d90a2f9874ff9d0e", "title": "Step 39" },
|
||||
{ "id": "685d2fd1f309b9191f257c55", "title": "Step 40" },
|
||||
{ "id": "6853f68dd3affa9adb2e6d99", "title": "Step 41" },
|
||||
{ "id": "6859523c793377706e19e9a0", "title": "Step 42" },
|
||||
{ "id": "6853f70470f45d9c280af659", "title": "Step 43" },
|
||||
{ "id": "685d53ec88a16a4643c2437b", "title": "Step 44" },
|
||||
{ "id": "685d53b5e4f5784562a12d1b", "title": "Step 45" },
|
||||
{ "id": "6853f90fd03acc9fd75ff860", "title": "Step 46" },
|
||||
{ "id": "6853f996671e63a0b4fbf143", "title": "Step 47" },
|
||||
{ "id": "685a82a54950823ef954276a", "title": "Step 48" },
|
||||
{ "id": "685409f3f6c765aa4cd44a26", "title": "Step 49" },
|
||||
{ "id": "68540a534c56aeabae6afd58", "title": "Step 50" },
|
||||
{ "id": "68540aa7dfd449ad074c285c", "title": "Step 51" }
|
||||
],
|
||||
"usesMultifileEditor": true,
|
||||
"hasEditableBoundaries": true
|
||||
}
|
||||
@@ -718,6 +718,7 @@
|
||||
"blocks": [
|
||||
"lecture-classes-and-objects",
|
||||
"workshop-musical-instrument-inventory",
|
||||
"workshop-email-simulator",
|
||||
"lab-budget-app",
|
||||
"review-classes-and-objects",
|
||||
"quiz-classes-and-objects"
|
||||
|
||||
Reference in New Issue
Block a user