- Available: Thursday, 13 April 2023, 4:00 PM Eastern
- Due: on or before Monday, 24 April 2023, 11:59 PM Eastern
âť— No late submissions will be accepted for scoring.
The last assignment is open network, open readings, and open notes. You may refer to
code in previous lecture exercises, lab exercises, and problem sets for inspiration. See the
last_assignment_overview.pdf document for more details regarding this assignment.
The last assignment is worth 1800 points and you accumulate points by passing a series of autograder tests.
âť— Per section 5.4 of the Syllabus you must earn a
minimum 4650 points and attempt all challenges comprising the last assignment to earn a final
course grade of A.
Please abide by the following rules:
-
The last assignment that you submit must constitute your own work. You are prohibited from soliciting assistance or accepting assistance from any person or generative artificial intelligence (AI) platform, chatbot, or tool while working to complete the programming assignment. This includes but is not limited to individual classmates, study group members, tutors, ChatGPT or Github copilot.
-
âť— If you have formed or participated in an SI 506 study group please suspend all study group activities for the duration of the midterm assignment.
-
âť— If you work with a tutor please suspend contact with the tutor for the duration of the assignment.
-
-
Likewise, you are prohibited from assisting any other student who is required to complete this assignment. This includes students attempting the assignment during the regular exam period, as well as those who may attempt the assignment at another time and/or place due to scheduling conflicts or other issues.
Direct all questions regarding the assignment to the Slack SI 506 workspace #last_assignment
channel. Do not post code snippets to the #last_assignment channel. Avoid sending private direct
messages (DMs) to teaching team members about the midterm challenges. Doing so is inefficient since
it limits the response to a single team member and increases the likelihood of a delayed response.
Surfacing your question on the #last_assignment channel also helps reduce message duplication.
That said, if a personal issue arises during the assignment period please send a private DM to Anthony.
In line with the weekly lab exercises and problem sets you will be provided with a number of files:
| File | Purpose |
|---|---|
README.md |
Assignment instructions |
last_assignment.py |
Program/script including a main() function and other definitions and statements. |
five_oh_six.py |
Module containing utility functions and statements. |
data-clone_wars_episodes.csv |
Data file. |
data-nyt_star_wars_articles.json |
Data file. |
data-wookieepedia_droids.json |
Data file. |
data-wookieepedia_people.json |
Data file. |
data-wookieepedia_planets.csv |
Data file. |
data-wookieepedia_starships.csv |
Data file. |
fxt_*.json |
Collection of test fixture files that you must match with the files you produce. |
Please download the assignment files from Canvas Files as soon as they are released. This is a timed event and delays in acquiring the assignment files will shorten the time available to engage with the challenges. The clock is not your friend.
âť— DO NOT modify or remove the scaffolded code that we provide in the Python script or module files unless instructed to do so.
The template file last_assignment.py includes the following import statements:
import copy
import five_oh_six as utlThe utilities module five_oh_six.py includes the following import statements:
import csv
import json
import requests
from urllib.parse import quote, urlencode, urljoinâť— Do not comment out or remove these import statements. That said, check your
import statements periodically. If you discover that other import statements have been added to
your Python files remove them. In such cases, VS Code is attempting to assist you by inserting
additional import statements based on your keystrokes. Their presence can trigger
ModuleNotFoundError runtime exceptions when you submit your code to Gradescope.
As discussed in class, this assignment utilizes a caching workflow that eliminates
redundant HTTP GET requests made to SWAPI by storing the SWAPI responses locally. Caching is
implemented fully and all you need do is call the function get_swapi_resource() whenever you
need to retrieve a SWAPI representation of a person/droid, planet, species, or starship, either
locally from the cache or remotely from SWAPI. The cache dictionary is serialized as JSON and
written to CACHE.json every time you run last_assignment.py.
âť— Do not call the function named utl.get_resource directly. Doing so sidesteps the
cache and undercuts the caching optimization strategy.
The Star Wars saga has spawned films, animated series, books, music, artwork, toys, games, fandom websites, cosplayers, scientific names for new organisms (e.g., Trigonopterus yoda), and even a Darth Vader grotesque attached to the northwest tower of the Washington National Cathedral. Leading US news sources such as the New York Times cover the Star Wars phenomenon on a regular basis.
The last assignment adds yet another Star Wars-inspired artifact to the list. The data used in this assignment is sourced from the Star Wars API (SWAPI), Wookieepedia, Wikipedia, and the New York Times.
As you write your code take advantage of the built-in print() function, VS code's debugger, and VS
Codes file comparison feature to check your work and debug your code. See the
last_assignment_overview.pdf for additional details and instructions.
You may submit your solution to Gradescope as many times as needed before the expiration of the assignment time. Your final submission will constitute your assignment submission.
âť— You must submit your solution file to Gradescope before the expiration of exam time. Solution files submitted to the teaching team after the expiration of the assginment time will receive a score of zero (0).
If you are unable to earn full points on the assignment the teaching team will grade your submission manually. Partial credit may be awarded for submissions that fail one or more autograder tests if the teaching team (at their sole discretion) deem a score adjustment warranted.
If you submit a partial solution, feel free to include comments (if you have time) that explain what you were attempting to accomplish in the area(s) of the program that are not working properly. We will review your comments when determining partial credit.
A long time ago in a galaxy far, far away, there occured the Clone Wars (22-19 BBY), a major conflict that pitted the Galatic Republic against the breakaway Separatist Alliance. The Republic fielded genetically modified human clone troopers commanded by members of the Jedi order against Separatist battle droids. The struggle was waged across the galaxy and, in time, inspired an animated television series entitled Star Wars: The Clone Wars which debuted in October 2008 and ran for seven seasons (2008-2014, 2020).
The last assignment features four groups of challenges:
Challenge 01. Implement a number of utl.to_*() functions employing try and except
blocks that will be employed in later challenges.
Challenges 02-05. Utilize a Clone Wars data set that provides summary data about the animated series. You will implement a number of functions that will simplify interacting with the data in order to surface basic information about the episodes and their directors, writers, and viewership.
Challenges 06-08. Work with New York Times article data that charts the creative, cultural, and economic impact of the Star Wars saga both within the US and elsewhere over the past forty-six years.
Challenges 09-20. Recreates the escape of the light freighter Twilight from the sabotaged and doomed Separatist heavy cruiser Malevolence which took place during the first year of the conflict (22 BBY). Your task is to reassemble the crew of the Twilight and take on passengers before disengaging from the Malevolence and heading into deep space. The Jedi generals Anakin Skywalker and Obi-Wan Kenobi together with the astromech droid (robot) R2-D2 had earlier boarded the Malevolence after maneuvering the much smaller Twilight up against the heavy cruiser and docking via an emergency air lock. Their mission was twofold:
- Retrieve the Republican Senator Padmé Amidala and the protocol (communications) droid C-3PO whose ship had been seized after being caught in the Malevolence's tractor beam, and
- Sabotage the warship.
In these challenges you will implement functions and follow a workflow that generates a JSON document that recreates the Twilight's escape from the Malevolence.
May the Force be with You.
Task: Implement the functions utl.to_none(), utl.to_int(),
utl.to_float(), and utl.to_list(). Each function attempts to convert a passed
in value to a more appropriate type.
Replace pass with a code block that attempts to convert the passed in value to None. Review
the function's docstring to better understand the task it is to perform, the parameters it defines,
and the return value it computes.
-
Employ
tryandexceptstatements in order to handle runtime exceptions whenever an invalid conversion is attempted.âť— Do not place code outside the
tryandexceptcode blocks. -
In the
tryblock check if the passed invaluecan be found inNONE_VALUES(perform a case insensitive membership check). If a match is obtained returnNoneto the caller; otherwise, return thevalueunchanged.âť— Don't assume that
valueis "clean"; program defensively and remove leading/trailing spaces before checking if the "cleaned" version of the string matches aNONE_VALUESitem. -
If a runtime exception is encountered "catch" the exception in the
exceptblock and return thevalueto the caller unchanged.đź’ˇ You do not need to specify specific exceptions in the
exceptstatement.
After implementing the function return to main().
-
Uncomment the relevant
assertstatements and test the function. -
If an
AssertionErroris raised, debug your code, and then retest. Repeat as necessary.
Replace pass with a code block that attempts to convert the passed in value to a float.
Review the function's docstring to better understand the task it is to perform, the parameters it
defines, and the return value it computes.
-
Employ
tryandexceptstatements in order to handle runtime exceptions whenever an invalid conversion is attempted.âť— Do not place code outside the
tryandexceptcode blocks. -
If a runtime exception is encountered "catch" the exception in the
exceptblock and return thevalueto the caller unchanged.đź’ˇ You do not need to specify specific exceptions in the
exceptstatement.
After implementing the function return to main().
-
Uncomment the relevant
assertstatements and test the function. -
If an
AssertionErroris raised, debug your code, and then retest. Repeat as necessary.
Replace pass with a code block that attempts to convert the passed in value to an int. Review
the function's docstring to better understand the task it is to perform, the parameters it defines,
and the return value it computes.
-
Employ
tryandexceptstatements in order to handle runtime exceptions whenever an invalid conversion is attempted.âť— Do not place code outside the
tryandexceptcode blocks. -
The function must convert numbers masquerading as strings, incuding those with commas that represent a thousand separator (e.g., '500,000,000') and those with a period that designates a fractional component (e.g., '500,000,000.9999'), to a whole number.
-
If a runtime exception is encountered "catch" the exception in the
exceptblock and return thevalueto the caller unchanged.đź’ˇ You do not need to specify specific exceptions in the
exceptstatement.
After implementing the function return to main().
-
Uncomment the relevant
assertstatements and test the function. -
If an
AssertionErroris raised, debug your code, and then retest. Repeat as necessary.
Replace pass with a code block that attempts to convert the passed in value to a list using a
delimiter if one is provided. Review the function's docstring to better understand the task it is
to perform, the parameters it defines, and the return value it computes.
-
Employ
tryandexceptstatements in order to handle runtime exceptions whenever an invalid conversion is attempted.âť— Do not place code outside the
tryandexceptcode blocks. -
If the caller provides a
delimitervalue the function must use it to split thevalue; otherwise, split the string without specifying a delimiter value.đź’ˇ Let the truth value of
delimiterdetermine how you choose to split the string.âť— Don't assume that
valueis "clean"; program defensively and remove leading/trailing spaces before attempting to convert the string to a list. -
If a runtime exception is encountered "catch" the exception in the
exceptblock and return thevalueto the caller unchanged.đź’ˇ You do not need to specify specific exceptions in the
exceptstatement.
After implementing the function return to main().
-
Uncomment the relevant
assertstatements and test the function. -
If an
AssertionErroris raised, debug your code, and then retest. Repeat as necessary.
Task: Refactor (e.g., modify) the function utl.read_csv_to_dicts() to use a
list comprehension and then call the function to read a CSV file that contains information about
the Clone Wars episodes. Then implement the function has_viewer_data() that checks whether or
not an episode possesses viewership information.
đź’ˇ This challenge involves a list of nested dictionaries. Use the built-in function print() to
explore one of nested dictionaries or call the function utl.write_json() in main(), encode the
data as JSON, and write it to a "test" JSON file so that you can view the list of dictionaries more
easily.
Examine the commented out code in utl.read_csv_to_dicts() function (do not uncomment).
Reimplement the function by writing code inside the with block that retrieves an instance of the
csv.DictReader and then employs a list comprehension to traverse the lines in the reader object
and return a new list of line elements to the caller.
âť— Review lecture notes and code solution files if you have forgotten how to write a list
comprehension. If you are unsuccessful in your endeavors uncomment the code in
utl.read_csv_to_dicts() and get the function working so that you can continue with the assignment.
-
You are limited to writing two (2) lines of code.
- Line 01 assigns an instance of
csv.DictReaderto a variable namedreader. - Line 02 returns a new list of
reader"line" elements to the caller using a list comprehension.
- Line 01 assigns an instance of
-
You must employ existing variable names that appear in the commented out code when writing your list comprehension.
After refactoring utl.read_csv_to_dicts() return to main().
-
Call the function and retrieve the data contained in the file
data-clone_wars_episodes.csv. -
Assign the return value to a variable named
clone_wars_episodes.
Replace pass with a code block that checks whether or not an individual Clone Wars episode
possesses viewership information. Review the function's docstring to better understand the task it
is to perform, the parameters it defines, and the return value it computes.
-
The function must compute the truth value of the passed in episode's "episode_us_viewers_mm" key-value pair, returning either
TrueorFalseto the caller.đź’ˇ Recall that a function can include more than one
returnstatement. That said, you can also employ Python's ternary operator to solve this challenge with a single line of code.
After implementing the function return to main().
-
Test your implementation of
has_viewer_data()by counting the number of episodes in theclone_wars_episodeslist that possess a "episode_us_viewers_mm" numeric value. Employ a loop, a conditional statement, and the accumulator pattern to accomplish the task. Whenever the return value ofhas_viewer_data()equalsTrueincrement your episode count by 1.đź’ˇ Recall that a function call is considered an expression and
ifstatements are composed of one or more expressions. -
The number of episodes that possess an "episode_us_viewers_mm" viewership value equals eighty-eight (
88). If your loop does not accumulate this total, recheck both your implementation ofhas_viewer_data()and yourforloop and loop blockifstatement.
Task: Implement a function that converts Clone Wars episode string values to more appropriate types.
Replace pass with a code block that converts specifed string values to more appropriate types.
Review the function's docstring to better understand the task it is to perform, the parameters it
defines, and the return value it computes.
-
The function accepts a list of nested "episode" dictionaries. You must implement a nested loop to perform the value type conversions.
- Outer loop: passed in
episodeslist of nested dictionaries. - Inner loop: individual "episode" dictionary items.
- Outer loop: passed in
-
Employ
if-elif-elseconditional statements to convert the values encountered to more appropriate types. Utilize the conditional statements to perform the following operations on each key and value encountered:-
Check if the value is a member of
none_values. IfTrueassignNoneto the converted value's associated key. -
Convert certain episode string values to more appropriate types by passing the value to the appropriate
utl.to_*()function and assigning the return value to the converted value's associated key:Current type to New type series_season_num ( str)-> series_season_num ( int|None)series_episode_num ( str)-> series_episode_num ( int|None)season_episode_num ( str)-> season_episode_num ( int|None)episode_prod_code ( str)-> episode_prod_code ( float|None)episode_us_viewers_mm ( str)-> episode_us_viewers_mm ( float|None)episode_writers ( str)-> episode_writers ( list|None)
-
-
After the outer loop terminates return the list of mutated dictionaries to the caller.
After implementing the function, return to main().
-
Call the function
convert_episode_values()and pass it the following argument:clone_wars_episodesand the constantNONE_VALUES. Assign the return value toclone_wars_episodes. -
Call the function
utl.write_json()and writeclone_wars_episodesto the filestu-clone_wars-episodes_converted.json. Compare your file to the test fixture filefxt-clone_wars-episodes_converted.json. Both files must match, line-for-line, and character-for-character.
Task: Implement a function that retrieves the most viewed Clone Wars episode(s).
Replace pass with a code block that finds the most viewed Clone Wars episode(s) in the data
set. Review the function's docstring to better understand the task it is to perform, the parameters
it defines, and the return value it computes.
-
The function must return a list of one or more episodes from the passed in
episodeslist that feature the highest recorded viewership. Include in the list only those episodes that tie for the highest recorded viewership. If no ties exist only one episode will be returned in the list.âť— Ignore episodes with no viewership value.
-
Delegate to
has_viewer_data()the task of checking whether an episode contains a truthy "episode_us_viewers_mm" value. The function needs to check the truth value of "episode_us_viewers_mm" before you attempt to compare the current "episode_us_viewers_mm" value to the previous value.đź’ˇ Assign two local "accumulator" variables to the viewer count and the top episode(s).
After implementing the function return to main().
-
Call the function and pass it the following argument:
clone_wars_episodes. -
Assign the return value to
most_viewed_episode. Pass the variable toprint()and review the terminal output. If the list contains the following elements proceed to the next challenge; if not, recheck your code.[ { 'series_title': 'Star Wars: The Clone Wars', 'series_season_num': 1, 'series_episode_num': 2, 'season_episode_num': 2, 'episode_title': 'Rising Malevolence', 'episode_director': 'Dave Filoni', 'episode_writers': ['Steven Melching'], 'episode_release_date': 'October 3, 2008', 'episode_prod_code': 1.07, 'episode_us_viewers_mm': 4.92 }, { 'series_title': 'Star Wars: The Clone Wars', 'series_season_num': 7, 'series_episode_num': 134, 'season_episode_num': 13, 'episode_title': 'The Lecturers', 'episode_director': 'Anthony Whyte', 'episode_writers': ['Anthony Whyte', 'Chris Teplovs'], 'episode_release_date': 'May 7, 2020', 'episode_prod_code': 7.25, 'episode_us_viewers_mm': 4.92 } ]
Task: Construct a dictionary of Clone Wars directors along with a count of the number of episodes each directed. Sort by episode count (descending) and the director name (ascending).
Replace pass with a code block that returns a dictionary of key-value pairs that associate each
director in the episodes list with a count of the episodes that they are
credited with directing. Review the function's docstring to better understand the task it is to
perform, the parameters it defines, and the return value it computes.
-
The function must accumulates episode counts for each director listed in the
episodeslist. Create an empty accumulator dictionary to hold the director-count key-value pairs (variable name your choice). -
The director's name comprises the key and the associated value represents a count of the number of episodes that they directed.
{ < director_name_01 >: < episode_count >, < director_name_02 >: < episode_count >, ... } -
Employ a nested loop to solve this challenge. As you loop over each episode you will need to extract the director(s) from a string into a list and then loop over each in turn. In most cases you will encounter a single director but exceptions exist. For example Season 7, episode 128 was directed by Saul Ruiz and Bosco Ng.
series_title,series_season_num,series_episode_num,season_episode_num,episode_title,episode_director,episode_writers,episode_release_date,episode_prod_code,episode_us_viewers_mm ... Star Wars: The Clone Wars,7,128,7,Dangerous Debt,"Saul Ruiz, Bosco Ng","Dave Filoni, Charles Murray","April 3, 2020",6.07, ... -
Implement conditional logic in the inner loop block to ensure each director's episode counts are properly tabulated per the following rules:
-
Check if the local accumulator dictionary possesses a key-value pair for the director. If
True, increment the associated value; otherwise add a new key-value pair to the dictionary. -
When accumulating values, increment the director's episode count by
1.0(afloat) if, and only if, the director is the only person credited with directing the episode. -
Otherwise, if two or more directors are credited with directing the episode allocate a fraction of
1.0to each director's episode count. This value is calculated by dividing1.0by the number of directors credited with directing the episode.For example, if two directors are credited with directing the episode, each director's count is incremented by
0.5; if three directors are credited with directing the episode, each director's count is incremented by0.33.đź’ˇ Employ simple division when incrementing the count. Consider how you can employ the list of directors in the equation that you write.
-
After implementing the function return to main().
-
Call the function and pass
clone_wars_episodesto it as the argument. -
Assign the return value to
director_episode_counts. -
Uncomment the provided dictionary comprehension that employs the built-in function
sorted()and alambdafunction to sort the episode counts by the count (descending) and the director's last name. -
Call the function
utl.write_json()and write the sorteddirector_episode_countsto the filestu-clone_wars-director_episode_counts.json. Compare your file to the test fixture filefxt-clone_wars-director_episode_counts.json. Both files must match, line-for-line, and character-for-character.
Task: Implement the function get_news_desks().
Replace pass with a code block that returns a list of New York Times "news desks" sourced from the
passed in articles list. Review the function's docstring to better understand the task it is to
perform, the parameters it defines, and the return value it computes.
đź’ˇ Each article dictionary contains a "news_desk" key-value pair.
-
The list of news desk names returned by the function must not contain any duplicate elements. Accumulate the values carefully.
-
The function must delegate to the function
utl.to_none()the task of converting "news_desk" values that equal "None" (a string) toNone. Only news_desk values that are "truthy" (i.e., not None) are to be returned in the list.đź’ˇ There are a number of articles with a "news_desk" value of "None". Exclude this value from the list by passing each "news_desk" value to
utl.to_none()and assigning the return value to a local variable. You can filter out theNonevalues with a truth value test. -
The function must return a new version of the accumulator list sorted alphanumerically.
After implementing the function return to main().
-
Call the function
utl.read_json()and retrieve the New York Times article data in the file./data-nyt_star_wars_articles.json. Assign the return value toarticles. -
Test your implementation of
get_news_desks()by calling the function and passing to it the following arguments:articlesand the constantNONE_VALUES. Assign the return value to the variablenews_desks. -
Call the function
utl.write_json()and writenews_desksto the filestu-nyt_news_desks.json. Compare your file to the test fixture filefxt-nyt_news_desks.json. The files must match line for line, indent for indent, and character for character.
Task: Implement the function group_articles_by_news_desk().
Replace pass with a code block that returns a dictionary of "news desk" key-value pairs that
group the passed in articles by their parent news desk drawn from the news_desks list. Review
the function's docstring to better understand the task it is to perform, the parameters it defines,
and the return value it computes.
-
Implement a nested loop. Review the
data-nyt_star_wars_articles.jsonandstu-nyt_news_desks.jsonfiles and decide which list should be traversed by the outer loop and which list should be traversed by the inner loop.đź’ˇ The news desk name provides the link between the two lists.
-
Assign an empty list to a local variable. You will accumulate article dictionaries in this list and then assign the list to its "parent" news desk key. There are three locations in the function block where this initial variable assignment could be placed: outside the loops, inside the outer loop, or inside the inner loop. Choose wisely.
-
Each article dictionary added to its parent news desk list represents a "thinned" version of the original. The keys to employ and their order is illustrated by the example below:
{ "web_url": "https://www.nytimes.com/2016/10/20/business/media/lucasfilm-sues-jedi-classes.html", "headline_main": "Classes for Jedis Run Afoul of the Lucasfilm Empire", "news_desk": "Business", "byline_original": "By Erin McCann", "document_type": "article", "material_type": "News", "abstract": "A man whose businesses offers private lessons and certifications for fine-tuning lightsaber skills is operating without the permission of the “Star Wars” owner.", "word_count": 865, "pub_date": "2016-10-19T13:26:21+0000" }❗ Certain keys such as "headline_main", "byline_original", and "material_type" are not found in the original New York Times dictionaries. Hopefully, the names provide a sufficient hint about which values to map (i.e., assign) to each key.
After implementing the function return to main().
-
Call the function and pass it
news_desksandarticlesas arguments. Assign the return value to the variablenews_desk_articles. -
Call the function
utl.write_json()and writenews_desk_articlesto the filestu-nyt_news_desk_articles.json. Compare your file to the test fixture filefxt-nyt_news_desk_articles.json. The files must match line for line, indent for indent, and character for character.
Task Implement the function calculate_articles_mean_word_count().
Replace pass with a code block that returns the mean (e.g., average) word count of the passed in
list of articles less any articles with a word count of zero (0). Review the function's docstring
to better understand the task it is to perform, the parameters it defines, and the return value it
computes.
mean: central value of a set of values that is determined by calculating the sum of the values divided by the number of values.
Requirements
-
The function must calculate the mean word count of the passed in articles excluding from the calculation all articles with a "word_count" value of zero (
0) orNone. -
The function must maintain a count of the number of articles evaluated and a count of the total words accumulated from each article's "word_count" value. Assign the running counts to two local "accumulator" variables.
-
The function must check the truth value of each article's "word_count" before attempting to increment the article count and total words count. If the truth vallue of the "word_count" is
Falsethe article is excluded from the count. -
The function must round the mean value to the second (2nd) decimal place before returning the value to the caller.
After implementing the function return to main().
-
Create an empty dictionary named
mean_word_counts. You will use it to accumulate mean words counts. -
Loop over the
news_desk_articleskey-value pairs. Write a conditional statement inside the loop block that checks if the current key is a member of theignorenews desks tuple. If the key is not a member call the functioncalculate_articles_mean_word_count()and pass it the list of articles mapped (i.e., assigned) to the key. -
Inside the loop add a new key-value pair to
mean_word_countsconsisting of the current key and the return value of the call tocalculate_articles_mean_word_count(). Below is one of the key-value pairs added tomean_word_countsthat your code must produce:{ ... "Obits": 876.62, ... } -
Call the function
utl.write_json()and writemean_word_countsto the filestu-nyt_news_desk_mean_word_counts.json. Compare your file to the test fixture filefxt-nyt_news_desk_mean_word_counts.json. The files must match line-for-line and character-for-character.
Task: Implement the utility function utl.get_nested_dict().
Replace pass with a code block that utilizes a filter string to return a nested dictionary from
the passed in data list. Review the function's docstring to better understand the task it is to
perform, the parameters it defines, and the return value it computes.
The function is employed to traverse lists of nested dictionaries sourced from the following files in search of a particular dictionary representation of a Star Wars droid, person, planet, or starship:
data-wookieepedia_droids.jsondata-wookieepedia_people.jsondata-wookieepedia_planets.csvdata-wookieepedia_starships.csv
đź’ˇ Familiarize yourself with the Wookieepedia-sourced data files before commencing the remaining challenges.
-
Loop over the nested dictionaries in the passed in
datalist. -
Inside the loop block utilize the passed in
keyname to identify the key-value pair in the nested dictionary to evaluate. The value mapped to thekeymust be compared to the passed infiltervalue. If an exact match is obtained the nested dictionary is returned to the caller; otherwiseNoneis returned.
After implementing the function return to main().
-
Call the function
utl.read_csv_to_dicts()and retrieve the supplementary Wookieepedia planet data in the filedata-wookieepedia_planets.csv. Assign the return value towookiee_planets. -
Call the function
utl.get_nested_dict()and pass to it the following arguments:wookiee_planets, the key "name", and the lowercase string "Dagobah". -
Assign the return value to the variable
wookiee_dagobah. -
Call the function
utl.write_json()and writewookiee_dagobahto the filestu-wookiee_dagobah.json. Compare your file to the test fixture filefxt-wookiee_dagobah.jsonThe files must match line for line, indent for indent, and character for character. -
Call
utl.get_nested_dict()a second time and pass to it the following arguments:wookiee_planets, the key "system", and the string "Al'Har system". -
Assign the return value to the variable
wookiee_haruun_kal. -
Call the function
utl.write_json()and writewookiee_haruun_kalto the filestu-wookiee_haruun_kal.json. Compare your file to the test fixture filefxt-wookiee_haruun_kal.json. The files must match line for line, indent for indent, and character for character.
Task: Implement the functions utl.to_gravity_value() and create_planet().
Replace pass with a code block that attempts to convert a planet's "gravity" value to a float by
first removing the "standard" unit of measure substring (if it exists) before converting the
remaining number to a float. Review the function's docstring to better understand the task it is to
perform, the parameters it defines, and the return value it computes.
đź’ˇ Note that "gravity" values vary from planet to planet. The following examples illustrate the challenge:
{
'name': Tatooine,
...
'gravity': '1 standard',
...
}
{
'name': Dagobah,
...,
'gravity': 'N/A',
...
}
{
'name': Haruun Kal,
...
'gravity': '0.98',
...
}-
Employ
tryandexceptstatements in order to handle runtime exceptions whenever an invalid conversion is attempted.exclamation: Do not place code outside the
tryandexceptcode blocks. -
In the
tryblock evaluate whether or not the substring "standard" is part ofvalue(perform a case insensitive check). If found, remove the substring and pass the new (truncated) string to the functionutl.to_float()in order to convert the numeric part of thevalueto a float. If not found passvaluedirectly toutl.to_float().âť— Don't assume that
valueis "clean"; program defensively and remove leading/trailing spaces before attempting to convert the "cleaned" version of the string to a float. -
If a runtime exception is encountered "catch" the exception in the
exceptblock and return thevalueto the caller unchanged.đź’ˇ You do not need to specify specific exceptions in the
exceptstatement.
After implementing the function return to main().
-
Uncomment the relevant
assertstatements and test the function. -
If an
AssertionErroris raised, debug your code, and then retest. Repeat as necessary.
Replace pass with a code block that returns a dictionary representation of a planet based on the
passed in swapi_data dictionary. Review the function's docstring to better understand the task it
is to perform, the parameters it defines, and the return value it computes.
đź’ˇ The workflow outlined below illustrates the general creational pattern applied to each droid, person, planet, species, and starship encountered in the following challenges.
Workflow
-
Retrieve a SWAPI representation of the entity if one exists.
-
Update the SWAPI entity with Wookieepedia data if provided.
-
Return a "thinned" version of the dictionary that retains a subset of the original SWAPI/Wookieepedia key-value pairs, substituting in new keys when required and converting certain values to more appropriate types, including replacing certain string values with
None. -
Serialize the new dictionary as JSON and write the object to a file (i.e., check your work).
âť— The SWAPI entity will serve as the default representation of the entities that feature in the assignment. The Wookieepedia data will be used to enrich the SWAPI data with new and updated key-value pairs.
-
Assign an empty dictionary to a local variable (name your choice). This "planet" dictionary will be employed to accumulate new key-value pairs sourced from
swapi_data. -
If an optional
wookiee_datadictionary is provided by the caller, updateswapi_datawith thewookiee_datakey-value pairs prior to creating the new dictionary representation of the planet. -
The
keysdictionary includes droid, person, planet, species, and starship dictionaries. Each of these nested dictionaries specify the following new dictionary attributes:-
the
swapi_datakey-value pairs to be mapped to the new dictionary. -
the order in which the
swapi_datakey-value pairs are mapped to the new dictionary. -
the key names to be used in the new dictionary.
For example, each key in the
keys"planet" dictionary corresponds to a key inswapi_data. Each value in thekeys"planet" dictionary represents the (new) key name to be used in the new planet dictionary.keys = { ... "planet": { "url": "url", # old key: new key ..., "orbital_period": "orbital_period_days", # old key: new key ... }, ... }
-
-
Access the
keys"planet" dictionary and loop over its keys and values. Inside the loop block employif-elif-elseconditional statements to populate the new planet dictionary with key-value pairs sourced fromswapi_data.Each key in the
keys"planet" dictionary maps to aswapi_datakey-value pair. The associated "planet" value provides the key to utilize in the new dictionary.Convert
swapi_datavalues to more appropriate types as outlined below in the mappings table. Strings found innone_valuesmust be converted toNoneirrespective of case. Delegate type conversions to the variousutl.to_*()functions. Then map theswapi_datavalue to the new key when assigning the key-value pair to the new dictionary.For example, if the
keys"planet" key equals "diameter" perform the following actions:-
access the corresponding
swapi_data"diameter" value, converting it as required to a more appropriate type orNone. -
assign the (converted) value to the new dictionary using the "diameter_km" value as the new key.
< some condition > new_dict[< value >] = swapi_data[< key >] # pass expression to utl.to_*() if required < some other condition > ... ...
đź’ˇ Review the mappings carefully. Opportunities exist to reduce the number of
elifstatements by leveraging the commonalities across the keys.swapi_datadictionaryto "planet" dictionary url ( str)-> url ( str)name ( str)-> name ( str|None)region ( str)-> region ( str|None)sector ( str)-> sector ( str|None)suns ( str)-> suns ( int|None)moons ( str)-> moons ( int|None)orbital_period ( str)-> orbital_period_days ( float|None)diameter ( str)-> diameter_km ( int|None)gravity ( str)-> gravity_std ( float|None)climate ( str)-> climate ( list|None)terrain ( str)-> terrain ( list|None)population ( str)-> population ( int|None) -
After implementing create_planet() return to main().
-
Call the function
get_swapi_resource()and retrieve a SWAPI representation of the planet Tatooine. Make use of the appropriate constant to simplify construction of the URL. Access the "Tatooine" dictionary which is stored in the response object and assign the value toswapi_tatooine. -
Call the function
create_planet()and pass to it the following arguments:keys, andswapi_tatooine. Assign the return value to a variable namedtatooine. -
Call the function
utl.write_json()and writetatooineto the filestu-tatooine-v1p0.json. Compare your file to the test fixture filefxt-tatooine-v1p0.json. Both files must match line for line, indent for indent, and character for character. -
Test the function
create_planet()a second time. First, call the functionutl.get_nested_dict()and pass to it the following arguments:wookiee_planets, the key "name", and theswapi_tatooinename value. Assign the return value towookiee_tatooine. -
Call the function
create_planet()and pass to it the following arguments:keys,swapi_tatooine, andwookiee_tatooine. Assign the return value to the variabletatooine. -
Call the function
utl.write_json()and writetatooineto the filestu-tatooine-v1p1.json. Compare your file to the test fixture filefxt-tatooine-v1p1.json. Both files must match line for line, indent for indent, and character for character.
Task: Implement the functions utl.to_year_era() and create_droid().
Replace pass with a code block that attempts to separate the Galactic standard calendar year and
era (e.g., 896BBY, 24ABY) value into a dictionary comprising year and era key-value pairs.
-
Employ
tryandexceptstatements in order to handle runtime exceptions whenever an invalid conversion is attempted. Do not place code outside thetryandexceptcode blocks. -
In the
tryblock use slicing to access the year and era segments of the string.đź’ˇ Note that while the year segment's length varies (e.g., 896, 19, 0) the era segment of the Galactic calender date string comprises three characters: "BBY" or "ABY". Keep this in mind as you design your slicing expressions.
-
Before mapping the sliced segments to a dictionary, you must first check if the "year" segment of the
valueis a number by employing the appropriatestrmethod. If the substring is numeric, return a dictionary literal that maps the necessary slicing expressions to "year" and "era" keys as values. Structure the dictionary as follows:{'year': < year > (int), 'era': < era > (`str`)} -
Otherwise, if the "year" segment is not considered numeric return the
valueto the caller unchanged. -
If the year segment is numeric, convert the "year" segment to an integer by passing it as the argument to the function
to_int(). Call the function from within the dictionary literal. -
If a runtime exception is encountered "catch" the exception in the
exceptblock and return thevalueto the caller unchanged.đź’ˇ You do not need to specify specific exceptions in the
exceptstatement.
After implementing the function return to main().
-
Uncomment the relevant
assertstatements and test the function. -
If an
AssertionErroris raised, debug your code, and then retest. Repeat as necessary.
Replace pass with a code block that returns a dictionary representation of a driod (e.g., a
sentient robot) based on the passed in swapi_data dictionary. Review the function's docstring to
better understand the task it is to perform, the parameters it defines, and the return value it
computes.
-
Assign an empty dictionary to a local variable (name your choice). This "droid" dictionary will be employed to accumulate new key-value pairs sourced from
swapi_data. -
If an optional
wookiee_datadictionary is provided by the caller, updateswapi_datawith thewookiee_datakey-value pairs prior to creating the new dictionary representation of the droid. -
The
keysdictionary includes droid, person, planet, species, and starship dictionaries. Access thekeys"droid" dictionary and loop over its keys and values. Inside the loop block employif-elif-elseconditional statements to populate the new droid dictionary with key-value pairs sourced fromswapi_data.Each key in the
keys"droid" dictionary maps to aswapi_datakey-value pair. The associated "droid" value provides the key to utilize in the new dictionary.Convert
swapi_datavalues to more appropriate types as outlined below in the mappings table. Strings found innone_valuesmust be converted toNoneirrespective of case. Delegate type conversions to the variousutl.to_*()functions. Then map theswapi_datavalue to the new key when assigning the key-value pair to the new dictionary.đź’ˇ Review the mappings carefully. Opportunities exist to reduce the number of
elifstatements by leveraging the commonalities across the keys.swapi_datadictionaryto "droid" dictionary url ( str)-> url ( str)name ( str)-> name ( str|None)model ( str)-> model ( str|None)manufacturer ( str)-> manufacturer ( str|None)create_year ( str)-> create_date ( dict|None)height ( str)-> height_cm ( float|None)mass ( str)-> mass_kg ( float|None)equipment ( str)-> equipment ( list|None)instructions ( str)-> instructions ( list|None)
After implementing create_droid() return to main().
-
Call the function
get_swapi_resource()and retrieve a SWAPI representation of the astromech droid R2-D2. Make use of the appropriate constant to simplify construction of the URL. Access the "R2-D2" dictionary which is stored in the response object and assign the value toswapi_r2_d2. -
Call the function
utl.read_json()and retrieve the supplementary Wookieepedia droid data in the filedata-wookieepedia_droids.json. Assign the return value towookiee_droids. -
Call the function
utl.get_nested_dict()and pass to it the arguments required to retrieve the Wookieepedia dictionary representation of R2-D2. Assign the return value towookiee_r2_d2. -
Call the function
create_droid()and pass to it the following arguments:keys,swapi_r2_d2, andwookiee_r2_d2. Assign the return value to the variabler2_d2. -
Call the function
utl.write_json()and writer2_d2to the filestu-r2_d2.json. Compare your file to the test fixture filefxt-r2_d2.json. Both files must match line for line, indent for indent, and character for character.
Task: Implement the function create_species().
Replace pass with a code block that returns a dictionary representation of a species based on the
passed in swapi_data dictionary. Review the function's docstring to better understand the task it
is to perform, the parameters it defines, and the return value it computes.
-
Assign an empty dictionary to a local variable (name your choice). This "species" dictionary will be employed to accumulate new key-value pairs sourced from
swapi_data. -
If an optional
wookiee_datadictionary is provided by the caller, updateswapi_datawith thewookiee_datakey-value pairs prior to creating the new dictionary representation of the species. -
The
keysdictionary includes droid, person, planet, species, and starship dictionaries. Access thekeys"species" dictionary and loop over its keys and values. Inside the loop block employif-elif-elseconditional statements to populate the new species dictionary with key-value pairs sourced fromswapi_data.Each key in the
keys"species" dictionary maps to aswapi_datakey-value pair. The associated "species" value provides the key to utilize in the new dictionary.Convert
swapi_datavalues to more appropriate types as outlined below in the mappings table. Strings found innone_valuesmust be converted toNoneirrespective of case. Delegate type conversions to the variousutl.to_*()functions. Then map theswapi_datavalue to the new key when assigning the key-value pair to the new dictionary.đź’ˇ Review the mappings carefully. Opportunities exist to reduce the number of
elifstatements by leveraging the commonalities across the keys.swapi_datadictionaryto "species" dictionary url ( str)-> url ( str)name ( str)-> name ( str|None)classification ( str)-> classification ( str|None)designation ( str)-> designation ( str|None)average_lifespan ( str)-> average_lifespan_yrs ( int|None)average_height ( str)-> average_height_cm ( float|None)language ( str)-> language ( str)
After implementing create_species() return to main().
-
Call the function
get_swapi_resource()and retrieve a SWAPI representation of the human species. Make use of the appropriate constant to simplify construction of the URL. Access the "human" species dictionary which is stored in the response object and assign the value toswapi_human_species. -
Call the function
create_species()and pass to it the following arguments:keysandswapi_human_species. Assign the return value to the variablehuman_species. -
Call the function
utl.write_json()and writehuman_speciesto the filestu-human_species.json. Compare your file to the test fixture filefxt-human_species.json. Both files must match line for line, indent for indent, and character for character.
Task: Implement the function get_homeworld() The function will be utilized by the function
create_person() to enrich a person's home planet information.
Replace pass with a code block that attempts to return a dictionary representation of
a person's home planet. Review the function's docstring to better understand the task it
is to perform, the parameters it defines, and the return value it computes.
-
Retrieve a SWAPI representation of a species using the provided
swapi_url. Assign the return value to a variable (name your choice). -
Create a local variable (name your choice) to which the Wookieepedia-sourced dictionary, if retrieved, can be assigned. Assign it the default value
None. -
If an optional
planetslist is provided by the caller, delegate to the functionutl.get_nested_dict()the task of retrieving a Wookieepedia-sourced representation of the planet. Assign the return value to the local variable. -
Call the function
create_planet()and pass to it all required and optional arguments. Return the function's return value to the caller.
After implementing the function return to main().
-
Retrieve a SWAPI representation of the Jedi knight Anakin Skywalker. Pass the Jedi knight's name as the search
paramsvalue. Make use of the appropriate constant to simplify construction of the URL. -
Access the "Anakin" dictionary from the response object and assign the value to
swapi_anakin. -
Call the function
get_homeworld()and pass to it the following arguments:keys, theswapi_anakindictionary's "homeworld" value, andwookiee_planets. Assign the return value to a variable namedswapi_anakin_homeworld. -
Call the function
utl.write_json()and writeswapi_anakin_homeworldto the filestu-anakin_homeworld.json. Compare your file to the test fixture filefxt-anakin_homeworld.json. Both files must match line for line, indent for indent, and character for character.
Task: Implement the function get_species() The function will be utilized by the function
create_person() to enrich a person's species information.
Replace pass with a code block that attempts to return a dictionary representation of
a person's species. Review the function's docstring to better understand the task it
is to perform, the parameters it defines, and the return value it computes.
-
Retrieve a SWAPI representation of a species using the provided
swapi_url. Assign the return value to a variable (name your choice). -
Create a local variable (name your choice) to which the Wookieepedia-sourced dictionary, if retrieved, can be assigned. Assign it the default value
None. -
If an optional
specieslist is provided by the caller, delegate to the functionutl.get_nested_dict()the task of retrieving a Wookieepedia-sourced representation of the species. Assign the return value to the local variable. -
Call the function
create_species()and pass to it the required and optional arguments. Return the function's return value to the caller.
After implementing the function return to main().
-
Call the function
get_species()and pass to it the following arguments:keysand the first element in theswapi_anakindictionary's "species" list. Assign the return value to a variable namedswapi_anakin_species. -
Call the function
utl.write_json()and writeswapi_anakin_speciesto the filestu-anakin_species.json. Compare your file to the test fixture filefxt-anakin_species.json. Both files must match line for line, indent for indent, and character for character.
Task: Implement the function create_person().
Replace pass with a code block that returns a new person dictionary based on the passed in
swapi_data dictionary. Review the function's docstring to better understand the task it is to
perform, the parameters it defines, and the return value it computes.
-
Assign an empty dictionary to a local variable (name your choice). This "person" dictionary will be employed to accumulate new key-value pairs sourced from
swapi_data. -
If an optional
wookiee_datadictionary is provided by the caller, updateswapi_datawith thewookiee_datakey-value pairs prior to creating the new dictionary representation of the person. -
The
keysdictionary includes droid, person, planet, species, and starship dictionaries. Access thekeys"person" dictionary and loop over its keys and values. Inside the loop block employif-elif-elseconditional statements to populate the new person dictionary with key-value pairs sourced fromswapi_data.Each key in the
keys"person" dictionary maps to aswapi_datakey-value pair. The associated "person" value provides the key to utilize in the new dictionary.Convert
swapi_datavalues to more appropriate types as outlined below in the mappings table. Strings found innone_valuesmust be converted toNoneirrespective of case. Delegate type conversions to the variousutl.to_*()functions. Then map theswapi_datavalue to the new key when assigning the key-value pair to the new dictionary.Retrieving a dictionary representation of the person's home planet is delegated to the function
get_homeworld(). Retrieving a dictionary representation of the person's species is delegated to the functionget_species(). Theplanetsandplanet_keyvalues are passed directly toget_homeworld()while thespeciesandspecies_keyvalues are passed directly toget_species().đź’ˇ Review the mappings carefully. Opportunities exist to reduce the number of
elifstatements by leveraging the commonalities across the keys.swapi_datadictionaryto "person" dictionary url ( str)-> url ( str)name ( str)-> name ( str|None)birth_year ( str)-> birth_date ( dict|None)height ( str)-> height_cm ( float|None)mass ( str)-> mass_kg ( float|None)homeworld ( str)-> homeworld ( dict|None)species ( list)-> species ( dict|None)force_sensitive ( str)-> force_sensitive ( str)
After implementing the function return to main().
-
Call the function
utl.read_json()and retrieve the supplementary Wookieepedia person data in the filedata-wookieepedia_people.json. Assign the return value to a variable namedwookiee_people. -
Call the function
utl.get_nested_dict()and pass to it the arguments required to retrieve the "Anakin Skywalker" dictionary inwookiee_people. Assign the return value to a variable namedwookiee_anakin. -
Call the function
create_person()and pass to it the following arguments:keys,swapi_anakin,wookiee_anakin, andwookiee_planets. Assign the return value to the variableanakin. -
Call the function
utl.write_json()and writeanakinto the filestu-anakin_skywalker.json. Compare your file to the test fixture filefxt-anakin_skywalker.json. Both files must match line for line, indent for indent, and character for character. -
Next, create an "enriched" dictionary representation of the Jedi master and general Obi-Wan Kenobi.
Utilize the same "creational" workflow employed earlier to create Anakin Skywalker:
-
Retrieve a SWAPI dictionary representation of Obi-Wan Kenobi (search on "obi-wan kenobi"). We recommend assigning the return value to a variable named
swapi_obi_wan. -
Retrieve the Wookieepedia representation of Obi-Wan. Consider adopting the same variable naming format adopted for Anakin (e.g.,
wookiee_obi_wan). -
Call the function
create_person()and pass to it the arguments it needs to create a "thinned" dictionary representation of Obi-Wan. Consider assigning the return value to a variable namedobi_wan.
-
-
Call the function
utl.write_json()and writeobi_wanto the filestu-obi_wan_kenobi.json. Compare your file to the test fixture filefxt-obi_wan_kenobi.json. Both files must match line for line, indent for indent, and character for character.
Task: Implement the function create_starship().
Replace pass with a code block that returns a new starship dictionary based on the passed in
data dictionary. Review the function's docstring to better understand the task it is to perform,
the parameters it defines, and the return value it computes.
-
Assign an empty dictionary to a local variable (name your choice). This "starship" dictionary will be employed to accumulate new key-value pairs sourced from
swapi_data. -
If an optional
wookiee_datadictionary is provided by the caller, updateswapi_datawith thewookiee_datakey-value pairs prior to creating the new dictionary representation of the starship. -
The
keysdictionary includes droid, person, planet, species, and starship dictionaries. Access thekeys"starship" dictionary and loop over its keys and values. Inside the loop block employif-elif-elseconditional statements to populate the new starship dictionary with key-value pairs sourced fromswapi_data.Each key in the
keys"starship" dictionary maps to aswapi_datakey-value pair. The associated "starship" value provides the key to utilize in the new dictionary.Convert
swapi_datavalues to more appropriate types as outlined below in the mappings table. Strings found innone_valuesmust be converted toNoneirrespective of case. Delegate type conversions to the variousutl.to_*()functions. Then map theswapi_datavalue to the new key when assigning the key-value pair to the new dictionary.đź’ˇ Review the mappings carefully. Opportunities exist to reduce the number of
elifstatements by leveraging the commonalities across the keys.swapi_datadictionaryto "starship" dictionary url ( str)-> url ( str)name ( str)-> name ( str|None)model ( str)-> model ( str|None)starship_class ( str)-> starship_class ( str|None)manufacturer ( str)-> manufacturer ( str|None)length ( str)-> length_m ( float|None)hyperdrive_rating ( str)-> hyperdrive_rating ( float|None)MGLT ( str)-> max_megalight_hr ( int|None)max_atmosphering_speed ( str)-> max_atmosphering_speed_kph ( int|None)crew ( str)-> crew_size ( int|None)crew_members ( None)-> crew_members ( list|None)passengers ( str)-> max_passengers ( int|None)passengers_on_board ( None)-> passengers_on_board ( list|None)cargo_capacity ( str)-> cargo_capacity_kg ( int|None)consumables ( str)-> consumables ( str)armament ( str)-> armament ( list|None)
âť— The starship Twilight is sourced from Wookieepedia only. No SWAPI representation of the light freighter exists.
After implementing create_starship() return to main().
-
Call the
utl.read_csv_to_dicts()function and retrieve the supplementary Wookieepedia starship data in the filedata-wookieepedia_starships.csv. Assign the return value towookiee_starships. -
Call
utl.get_nested_dict()and pass to it the arguments required to retrieve the light freighter named Twilight inwookiee_starships. Assign the return value to a variable namedwookiee_twilight. -
Call the function
create_starship()and pass the following arguments:keysandwookiee_twilight(pass the starship dictionary as the second (2nd) argument). Assign the return value to a variable namedtwilight. -
Call the function
utl.write_json()and writetwilightto the filestu-twilight.json. Compare your file to the test fixture filefxt-twilight.json. Both files must match line for line, indent for indent, and character for character.
R2 are you quite certain that the ship is in this direction? This way looks potentially dangerous. C-3PO
Task: Implement the function board_passengers(). Get Senator Padmé Amidala, the protocol
droid C-3PO, and the astromech droid R2-D2 aboard the Twilight as passengers.
Replace pass with a code block that assigns a limited number of passengers to a list. Review the
function's docstring to better understand the task it is to perform, the parameters it defines, and
the return value it computes.
-
The passengers must be passed in a
listto theboard_passengers()function. -
The number of passengers permitted to board a starship or other vehicle is limited by the provided
max_passengersvalue. If the number of passengers attempting to board exceedsmax_passengersonly the firstnpassengers (wheren=max_passengers) are permitted to board the vessel.For example, if a starship's
max_passengersvalue equals10and20passengers attempt to board the starship, only the first10passengers are permitted aboard the vessel.
After implementing board_passengers() return to main().
-
Create a dictionary representation of the Galactic senator Padmé Amidala. Pass the senator's name as a
paramsvalue. Utilize the same "creational" workflow employed to create the dictionary representations ofanakinandobi_wan. Use the following variable names to represent Padmé Amidala.swapi_padme(assigned to the SWAPI dictionary)wookiee_padme(assigned to the Wookieepedia dictionary)padme(assigned to thecreate_person()return value)
-
Call the function
utl.write_json()and writepadmeto the filestu-padme_amidala.json. Compare your file to the test fixture filefxt-padme_amidala.json. Both files must match line for line, indent for indent, and character for character. -
Create a dictionary representation of the protocol droid named C-3PO. Pass the droid's name as a
paramsvalue. Utilize the same "creational" workflow employed to creater2_d2. Consider using the following variable names to represent C-3PO.swapi_c_3po(assigned to the SWAPI dictionary)wookiee_c_3po(assigned to the Wookieepedia dictionary)c_3po(assigned to thecreate_droid()return value)
-
Call the function
utl.write_json()and writec_3poto the filestu-c_3po.json. Compare your file to the test fixture filefxt-c_3po.json. Both files must match line for line, indent for indent, and character for character. -
Next, call the function
board_passengers()and pass thetwilightstarship's "max_passengers" value and a list of passengers comprisingpadme,c_3po, andr2_d2(in that order) as arguments. -
Map (i.e., assign) the return value to the
twilightdictionary's "passengers_on_board" key.đź’ˇ Consider testing your function by passing additional passengers to it in excess of the permitted "max_passengers" value. Consider creating dictionary representations of the following Jedi masters:
- Mace Windo (https://swapi.py4e.com/api/people/51/)
- Plo Koon (https://swapi.py4e.com/api/people/58/)
- Shaak Ti (https://swapi.py4e.com/api/people/78/)
- Yoda (https://swapi.py4e.com/api/people/20/)
If the function
board_passengers()is implemented correctly onlypadme,c_3po,r2_d2, and three of the Jedi masters should be able to board thetwilight. You can retrieve both SWAPI and Wookieepedia dictionary representations of each to use for testing. Do this on separate lines and remember to comment out these lines before submitting your solution to Gradescope.đź’ˇ JSON fixture files of these Jedi have also been included in the file dump.
Let's get back to the ship. Power up the engines R2. Anakin Skywalker
Task: Implement the function assign_crew_members(). Assign Anakin Skywalker and
Obi-Wan Kenobi to the Twilight as crew members.
Replace pass with a code block that assigns personnel by position (e.g., pilot, copilot) to a
starship using a dictionary comprehension. Review the function's docstring to better understand the
task it is to perform, the parameters it defines, and the return value it computes.
-
To earn full credit you must create the "crew_members" dictionary by writing a dictionary comprehension on a single line.
âť— If necessary write a
forloop that adds the position/crew member key-value pairs to an accumulation dictionary namedcrew_members. Get it working first and then convert it to a dictionary comprehension.đź’ˇ Avoid looping over the passed in lists. Instead loop over a sequence of numbers and think carefully about the appropriate stop value to employ in order to limit the number of loop iterations. Utilize the sequence of numbers to pair
crew_positionandpersonnelelements by their matching index position. -
The crew positions (e.g., 'pilot', 'copilot') and personnel (e.g., Anakin Skywalker, Obi-Wan Kenobie) must be passed in separate
crew_positionsandpersonnellists to the functionassign_crew_members(). -
Assume that each ship requires a full compliment of personnel to crew the vessel. In other words, if a starship's "crew_size" equals three (
3) you must pass toassign_crew_members()three crew positions and three personnel.Assume too that the maximum number of crew members that can be assigned to a starship is limited by the starship's "crew_size" value. No additional crew members are permitted to be assigned to the starship even if included in the
crew_positionsandpersonnellists. This limitation must be imposed from within the dictionary comprehension.For example, if a starship's "crew_size" value equals
3but4crew positions/personnel are passed to the function only the first3crew positions/personnel are permitted to be added as key-value pairs to the crew members dictionary. -
The passed in
crew_positionsandpersonnellists must contain the same number of elements. The individualcrew_positionsandpersonnelelements are then paired by index position and stored in a dictionary structured as follows:{< crew_position[0] >: < personnel[0] >, < crew_position[1] >: < personnel[1] >, ...}
After implementing assign_crew_members() return to main().
-
Call the function
assign_crew_members()and pass the Twilight's "crew_size" value, a crew positions list comprising the following string elements: "pilot" and "copilot", and a personnel list comprisinganakinandobi_wan. -
Map (i.e., assign) the return value to the
twilightdictionary's "crew_members" key.đź’ˇ Consider testing your function by passing to it an additional crew position (e.g., navigator) and crew member (e.g, Mace Windo in excess of the permitted "crew_size". Do this on a separate line and remember to comment out the line before submitting your solution to Gradescope.
Create a list containing Anakin's "Power up the engines" order (a string) and map (i.e., assign) the
list to the droid r2_d2's "instructions" key.
Task: Sort wookiee_planets and then issue commands to R2-D2 to chart a course to the planet
Naboo. Also demonstrate that you can sort a list of dictionaries using a lambda function.
-
Write a single-line list comprehension that transforms each Wookieepedia-sourced planet dictionary in the
wookiee_planetslist by passing each planet referenced in the comprehension to the functioncreate_planet(). Assign the new list to a variable namedplanets.âť— if your list comprehension triggers a
KeyErrorexception, check your implementationcreate_planet(). The function is likely attempting to access a key in the planet dictionary that does not exist. Recall that there is a friendlydictmethod for dealing with such issues; refactor (i.e., revise) your function block accordingly. -
Perform an in_place sort of the
planetslist passing to it as thekeyfunction alambdafunction that sorts the planets by name. Reverse the sort so that the planets are sorted by name in descending order. -
Call the function
utl.write_json()and writeplanetsto the filestu-planets_sorted_name.json. Compare your file to the test fixture filefxt-planets_sorted_name.json. Both files must match line for line, indent for indent, and character for character.
-
Call the function
utl.get_nested_dict()and pass it the following arguments:planets,diameter_km, and the integer12120. Assign the return value to a variable namednaboo. -
Access the
naboodictionary's "region" and "sector" values and include the names in a formatted string literal (f-string) structured as follows:"Plot course for Naboo, < region >, < sector >" -
Add the f-string to
r2_d2's"instructions" list so that Twilight can chart a course to the planet Naboo, Padmé Amidala's home world.
đź’ˇ If you get stuck on sorting planets by "diameter_km" and "name", pause your sorting work
and proceed to the final task ("Escape from the Malevolvence") and complete it. Then return and
restart this standalone task.
-
Employ the built-in function
sorted()and alambdafunction to sortplanetsby the following attributes:Key Value Order diameter_km int|Nonedescending name ascending str -
You must write your
lambdaexpression using the ternary operator when sorting on "diameter_km" because several planets lack a known diameter and in consequenceNonehas been mapped (i.e., assigned) to their "diameter_km" key. -
Assign the return value of
sorted()to a variable namedplanets_diameter_km.âť— Write the entire statement on a single line to facilitate auto grader testing:
planets_diameter_km = < expression >
-
Call the function
utl.write_json()and writeplanets_diameter_kmto the filestu-planets_sorted_diameter.json. Compare your file to the test fixture filefxt-planets_sorted_diameter.json. Both files must match line for line, indent for indent, and character for character.
R2 release the docking clamp. Anakin Skywalker
Task: Instruct the astromech droid R2-D2 to release the docking clamp and detach the Twilight from the Malevolence.
With our heroes on board the Twilight and the engines fired, the light freighter detaches itself from the stricken heavy cruiser Malevolence and departs to rejoin the Republican fleet before heading to Naboo.
-
Add Anakin's order "Release the docking clamp" to
r2_d2's"instructions" key-value pair. -
Call the function
utl.write_json()and writetwilightto the filestu-twilight_departs.json. Compare your file to the test fixture filefxt-twilight_departs.json. Both files must match line for line, indent for indent, and character for character.
If the files match your job is done. Never mind that Separatist starfighters are in hot pursuit of the Twilight—declare victory!
Congratulations on completing SI 506.