Update Exploring Near Earth Objects project and add Meme Generator project

This commit is contained in:
2026-01-03 21:55:24 -08:00
parent 9a4c3f7854
commit 155f0c9c6d
36 changed files with 754 additions and 65 deletions

View File

@@ -17,7 +17,10 @@ quirks of the data set, such as missing names and unknown diameters.
You'll edit this file in Task 1.
"""
from helpers import cd_to_datetime, datetime_to_str
import math
from datetime import datetime
class NearEarthObject:
@@ -32,22 +35,20 @@ class NearEarthObject:
initialized to an empty collection, but eventually populated in the
`NEODatabase` constructor.
"""
# TODO: How can you, and should you, change the arguments to this constructor?
# If you make changes, be sure to update the comments in this file.
def __init__(self, **info):
"""Create a new `NearEarthObject`.
:param info: A dictionary of excess keyword arguments supplied to the constructor.
"""
# TODO: Assign information from the arguments passed to the constructor
# onto attributes named `designation`, `name`, `diameter`, and `hazardous`.
# You should coerce these values to their appropriate data type and
# handle any edge cases, such as a empty name being represented by `None`
# and a missing diameter being represented by `float('nan')`.
self.designation = ''
self.name = None
self.diameter = float('nan')
self.hazardous = False
self.designation = info.get("designation")
self.name = None if info.get("name") == "" else info.get("name")
self.diameter = (
float("nan")
if info.get("diameter") in (None, "")
else float(info.get("diameter"))
)
self.hazardous = info.get("hazardous", "N") == "Y"
# Create an empty initial collection of linked approaches.
self.approaches = []
@@ -55,20 +56,36 @@ class NearEarthObject:
@property
def fullname(self):
"""Return a representation of the full name of this NEO."""
# TODO: Use self.designation and self.name to build a fullname for this object.
return ''
if self.name:
return f"{self.designation} {self.name}"
return f"{self.designation}"
def __str__(self):
"""Return `str(self)`."""
# TODO: Use this object's attributes to return a human-readable string representation.
# The project instructions include one possibility. Peek at the __repr__
# method for examples of advanced string formatting.
return f"A NearEarthObject ..."
hazardous_str = (
"is potentially hazardous"
if self.hazardous
else "is not potentially hazardous"
)
if not math.isnan(self.diameter):
return f"NEO {self.fullname} has a diameter of {self.diameter:.3f} and {hazardous_str}."
return f"NEO {self.fullname} has an unknown diameter and {hazardous_str}."
def __repr__(self):
"""Return `repr(self)`, a computer-readable string representation of this object."""
return f"NearEarthObject(designation={self.designation!r}, name={self.name!r}, " \
f"diameter={self.diameter:.3f}, hazardous={self.hazardous!r})"
return (
f"NearEarthObject(designation={self.designation!r}, name={self.name!r}, "
f"diameter={self.diameter:.3f}, hazardous={self.hazardous!r})"
)
def serialize(self):
"""Serialize this `NearEarthObject` into a dictionary."""
return {
"designation": self.designation,
"name": self.name,
"diameter_km": self.diameter,
"potentially_hazardous": self.hazardous,
}
class CloseApproach:
@@ -84,21 +101,20 @@ class CloseApproach:
private attribute, but the referenced NEO is eventually replaced in the
`NEODatabase` constructor.
"""
# TODO: How can you, and should you, change the arguments to this constructor?
# If you make changes, be sure to update the comments in this file.
def __init__(self, **info):
"""Create a new `CloseApproach`.
:param info: A dictionary of excess keyword arguments supplied to the constructor.
"""
# TODO: Assign information from the arguments passed to the constructor
# onto attributes named `_designation`, `time`, `distance`, and `velocity`.
# You should coerce these values to their appropriate data type and handle any edge cases.
# The `cd_to_datetime` function will be useful.
self._designation = ''
self.time = None # TODO: Use the cd_to_datetime function for this attribute.
self.distance = 0.0
self.velocity = 0.0
self._designation = info.get("designation")
self.time = info.get("time")
if self.time:
self.time = cd_to_datetime(info.get("time"))
self.distance = info.get("distance", float("nan"))
self.velocity = info.get("velocity", float("nan"))
# Create an attribute for the referenced NEO, originally None.
self.neo = None
@@ -116,19 +132,23 @@ class CloseApproach:
formatted string that can be used in human-readable representations and
in serialization to CSV and JSON files.
"""
# TODO: Use this object's `.time` attribute and the `datetime_to_str` function to
# build a formatted representation of the approach time.
# TODO: Use self.designation and self.name to build a fullname for this object.
return ''
return f"{datetime_to_str(self.time)}"
def __str__(self):
"""Return `str(self)`."""
# TODO: Use this object's attributes to return a human-readable string representation.
# The project instructions include one possibility. Peek at the __repr__
# method for examples of advanced string formatting.
return f"A CloseApproach ..."
return f"On {self.time_str}, {self.neo.fullname} approaches Earth at a distance of {self.distance:.2f} au and a velocity of {self.velocity:.2f} km/s."
def __repr__(self):
"""Return `repr(self)`, a computer-readable string representation of this object."""
return f"CloseApproach(time={self.time_str!r}, distance={self.distance:.2f}, " \
f"velocity={self.velocity:.2f}, neo={self.neo!r})"
return (
f"CloseApproach(time={self.time_str!r}, distance={self.distance:.2f}, "
f"velocity={self.velocity:.2f}, neo={self.neo!r})"
)
def serialize(self):
"""Serialize this `CloseApproach` into a dictionary."""
return {
"datetime_utc": self.time_str,
"distance_au": self.distance,
"velocity_km_s": self.velocity,
}