This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Assignment 7 - Meteoric Design, Implementation, and Test

Apply low-level design rules to implement and test your application.
  • 1:

Code resources

Submitting code or other solutions from anywhere other than your own brains is cheating.

  • Can you research how to use a particular function or library such as pytest? Yes.
  • Can you get code that solves all or part of your homework? No.
  • When in doubt, ask. I will not be upset if you ask.

Refer to the full details in the Syllabus on Canvas.

Setup

  1. Click this link: https://classroom.github.com/a/VLhFcyMu
    • The first teammate: Create a name like “alice-bob” using your first names.
    • The second (and third) teammate: Join the team your partner made.
  2. Accept the assignment.
  3. Click the link to your team repo on the confirmation page.
  4. git clone the repository to your computer, and open the directory in PyCharm.
  5. Configure pytest:
    • Click the bottom right of PyCharm where your Python version is listed. Select Add New Interpreter -> Add Local Interpreter, then hit Okay on the pop-up.
    • Open a new Integrated Terminal window in PyCharm.
    • Run pip install pytest pytest-cov

Introduction and Problem Statement

You will complete a program to analyze the NASA Meteorite Landings dataset: https://data.nasa.gov/dataset/meteorite-landings-api. You will work with your partner(s) to design, implement, and test your solution.

You may only collaborate with your partner(s). All partners must contribute equally to the assignment. Each person is responsible for implementing and testing part of the solution.

Read the Problem Statement: PDF or web. Paper hand-outs will be provided in class.

Part A) Design

In class, discuss the organization of your code with your partner(s). Discuss the Problem Statement, and then think of a sensible design in terms of the functions and optionally the modules (files) you will create.

Follow the 5 low level design rules:

  1. Avoid magic literals.
  2. Functions should have a single responsibility.
  3. DRY (Don’t Repeat Yourself) and the Rule of Three.
  4. Handle errors at the lowest sensible level, and re-raise/re-throw them otherwise.
  5. Raise specific errors and define your own if needed.

There are many ways to solve this problem while adhering to the design rules. You may evolve your design during Implementation and Test.

Your focus at this stage (prior to writing code) should be on the Single Responsibility Principle. By the end of class, show the instructor:

  • Function signatures you have stubbed (only written the def line) in meteoric.py.
  • Docstrings that (i) explain each function, and (ii) specify which partner is responsible for implementing and testing the function.

Part B) Implementation & Test

This part is completed as homework. Coordinate your work via Slack, email, or text, and contribute your work to your team’s GitHub repo.

Implementation requirements

  1. Implement a solution to the Problem Statement in meteoric.py.
  2. Each person must work in a branch in git, then merge into main when appropriate. I will only look at the main branch when grading. Review the content from Assignment 6 on proper Git workflow.
  3. Put your names at the top of meteoric.py in the module docstring.
  4. You may create classes and files and use imported libraries, but these things are not necessary.
  5. Your solution must adhere to the 5 rules of low-level program design.
  6. You are free to modify the provided code, including load_data() code.
  7. You will need to implement the haversine formula. You may use code from the web, but include the link to the source website in a code comment.
  8. Add docstrings following our conventions to any functions, classes, and files you create.
  9. The code must adhere to the PEP8 coding conventions discussed in class.

Testing requirements

  1. Add test cases to test_meteoric.py to verify your new code.
  2. You must achieve 90% branch coverage in all source files except for the main() function.
  3. If you create additional source files, you must also create a corresponding test_*.py unit test.
  4. All test cases must run from the CLI with pytest.
  5. Use pytest --cov --cov-branch --cov-report=html to generate a branch coverage HTML report in your project directory.
    • note: the htmlcov/ and .coverage files generated by pytest are ignored by Git and will not appear in your repos. This is intentional.

Rubric

  • (5pts) PEP8 coding conventions followed
  • (5pts) Docstring conventions followed for modules (files), classes (if any), and functions.
  • (25pts) User commands are correctly implemented, including exception handling of user input errors.
  • (10pts) Adherence to our 6 low level design rules.
  • (15pts) Multiple test cases with proper test structure for your source code. pytest branch coverage HTML report demonstrating ≥90% branch coverage of all source code except for main().

Submission due Nov 17

Commit and push your code to GitHub following the prescribed workflow when working with git from Assignment 6.

  • Each person must work in a branch in git, then merge into main when appropriate.
  • Make sure to push your branches to GitHub.
  • I will only look at the main branch when grading, so your branches must be properly merged into main.

You do not submit anything to Canvas.

1 -

Problem Statement

Problem outline

Write a program the analyzes the NASA Meteorite Landings dataset available at https://data.nasa.gov/widgets/gh4g-9sfh. The program runs from the Terminal/CLI. The program will have two primary capabilities. The first is to display all meteorites discovered in a given year. The second is to display the meteorite geographically closest to a provided latitude and longitude.

The program must run from the CLI as python meteoric.py <command> <argument>. See the input format and sample inputs for examples of running the program.

Input format

The program must understand the following commands:

  • year <integer>: Print out the meteorite name, latitude, and longitude for all meteorites discovered in the <integer> year. It is possible that no meteorites were discovered in a given year. Example usage: python meteoric.py year 1999
  • geopoint <latitude,longitude>: Print out the meteorite name, latitude, and longitude for the meteorite with the closest great-circle distance to the coordinates. Latitude is a float in the range [-90.0, 90.0]. Longitude is a float in the range [-180.0, 180.0]. Example usage: python meteoric.py geopoint 34.2257,-77.9447

The data in meteorite_landings.csv looks like this:

name,id,year,reclat,reclong
Aachen,1,1880,50.775,6.08333
Aarhus,2,1951,56.18333,10.23333
Abee,6,1952,54.21667,-113
Acapulco,10,1976,16.88333,-99.9
...
FieldDescription
nameA name for the specific meteorite.
idA unique integer identifier for the meteorite.
yearThe year the meteorite was found or observed. Years are positive 4-digit integers.
reclatThe latitude at which the meteorite was found. Latitudes are floats in the range [-90.0,90.0].
reclongThe longitude at which the meteorite was found. Longitudes are floats in the range [-180.0,180.0].

Important: a load_data() function is provided in meteoric.py that loads the data from meteorite_landings.csv into a list of lists. You do not need to validate the data in the CSV file, however, some fields may be blank if the information is missing.

Output format

  • Print meteorite data to the console in a human-friendly format.
  • When searching for all meteorites that were discovered in a given year the program will either: (a) display a list of meteorites discovered, or (b) display a message stating no meteorites were found for the given year.
  • When searching for the closest meteorite landing from a specific location, the program will display the name (or names if two or more meteorites have an equal distance from the specified location) of the meteorite closest to the location given by the user.
  • If the user fails to provide a valid command or valid arguments, the console displays an error message indicating what the user did incorrectly.

Exceptional conditions

Do not assume the <command> or <argument> are present or valid. The program must print an error message, not an exception or stack trace, if given bad arguments.

  • user can put in an invalid command keyword
  • user does not give an argument
  • user gives an invalid data type with the year keyword
  • user enters a year with no meteorite
  • user inputs latitude and longitude incorrectly
  • user enters multiple arguments
  • user gives an out of range latitude or longitude

Sample input

  1. python meteoric.py test: invalid command
  2. python meteoric.py year: missing argument
  3. python meteoric.py geopoint: missing argument
  4. python meteoric.py year s: invalid argument
  5. python meteoric.py geopoint abcdef: invalid argument
  6. python meteoric.py year 1999 2001 asd: invalid arguments
  7. python meteoric.py geopoint 120.884,300.475: invalid latitude and longitude
  8. python meteoric.py geopoint 32.558,78.854: valid search by geopoint
  9. python meteoric.py year 1818: valid search by year
  10. python meteoric.py year 55: valid search by year, no meteorites match that year

Sample output

You may change these to be more precised if you like, but not less precise.

  1. Invalid command and argument. Correct format is python meteoric.py <command> <argument>.

  2. Invalid command and argument. Correct format is python meteoric.py <command> <argument>.

  3. Invalid command and argument. Correct format is python meteoric.py <command> <argument>.

  4. Invalid argument. year argument must be an integer.

  5. Invalid argument. geopoint argument must be latitude,longitude.

  6. Invalid command and argument. Correct format is python meteoric.py <command> <argument>.

  7. Invalid argument. geopoint latitude or longitude out of range.

  8. Meteorite(s) discovered closest to 32.4, 103.92:
        Guangyuan, latitude: 32.4, longitude: 105.9
    
  9. Meteorite(s) discovered in 1818: 
        Seres, latitude: 41.05, longitude: 23.56667
        Slobodka, latitude: 55, longitude: 35
        Zaborzika, latitude: 50.28333, longitude: 27.68333
        Cambria, latitude: 43.2, longitude: -78.8
        Cape York, latitude: 76.13333, longitude: -64.93333
    
  10. No meteorites found for the year 55.