loading...
Cover image for API > CLI > Space Exploration

API > CLI > Space Exploration

codinghall profile image codinghall ・6 min read

I could not be more excited for my first capstone project at Flatiron School. Eight weeks flew by in the blink of an eye!

My husband and I recently watched the 2014 science documentary Cosmos: A Spacetime Odyssey, presented by astrophysicist Neil deGrasse Tyson. I am amazed by Tyson's storytelling approach through this so-called "Ship of the Imagination", where he travels beyond space and time to explore and explain the cosmos. The documentary series contributed to my CLI (Command-Line Interface) project domain modeling, Space Exploration.

Screen_Shot_2020-09-13_at_10.26.09_AM

RESTful API search

The next fun exercise would be finding the appropriate data either scraping from HTML, or fetching remote data sources from RESTful API. I discovered two APIs that I really like. One provided me with Planetary data, and the other provided Spacecraft data (powered by SpaceX). My first approach was to retrieve these remote data sources, and manipulate the data within my domain modeling.

class API 

    def self.space_data
        url = 'https://...'
        uri = URI.parse(url)
        response = Net::HTTP.get_response(uri)
        response.body

        space_data = JSON.parse(response.body)["bodies"]
    end 
    # => 'json' module returns Ruby hashes with key and value pairs

    def self.planets
        planets = []

        space_data.each do |data|
            if data["isPlanet"] == true
                planets << data["englishName"]
            end 
        end 

        planets 
    end 
    # => ["1 Ceres", "136199 Eris", "Uranus", "Pluto", "Neptune",...

    def self.planet_info(name)
        space_data.detect do |data|
            if data["englishName"] == name 
                puts "Name: " + data["englishName"].to_s
                puts "  Mean Radius: " + data["meanRadius"].to_s + " kilometres"
                puts "  Density: " + data["density"].to_s + " g.cm3"
                puts "  Gravity: " + data["gravity"].to_s + " m.s-2"
                puts "  Perihelion: " + data["perihelion"].to_s + " kilometres"
                puts "  Aphelion: " + data["aphelion"].to_s + " kilometres"
                if data["discoveredBy"] != ""
                    puts "  Discovered by: " + data["discoveredBy"].to_s
                end 
                if data["discoveryDate"] != ""
                    puts "  Discovery Date: " + data["discoveryDate"].to_s
                end 
            end 
        end 
    end 
    # => self.planet_info("Uranus")
    # => Name: Uranus
    # => Mean Radius: 25362.0 kilometres
    # => Density: 1.27 g.cm3
    # => Gravity: 8.87 m.s-2
    # => Perihelion: 2734998229 kilometres
    # => Aphelion: 3006318143 kilometres
    # => Discovered by: William Herschel
    # => Discovery Date: 13/03/1781

    def self.spacecraft
        url = 'https://...'
        uri = URI.parse(url)
        response = Net::HTTP.get_response(uri)
        response.body

        spacecraft = JSON.parse(response.body)
    end
    # => 'json' module returns Ruby hashes with key and value pairs

    def self.spacecraft_info 
        spacecraft.each do |ship|
            puts ship["rocket_name"].to_s 
            puts ship["description"].to_s
            puts "  Height: " + ship["height"]["feet"].to_s + " feet"
            puts "  Mass: " + ship["mass"]["lb"].to_s + " lbs"
            puts "  Success Rate: " + ship["success_rate_pct"].to_s + "%"
        end 
        nil 
    end 
    # => Falcon 1
    # => The Falcon 1 was an expendable launch system privately developed and...
    # =>   Height: 73 feet
    # =>   Mass: 66460 lbs
    # =>   Success Rate: 40%
    # => Falcon 9
    # => Falcon 9 is a two-stage rocket designed and manufactured by SpaceX...
    # => ..

end

Domain Modeling Design

There are 3 main model (or classes). They are Astronaut, Spacecraft and Planet. The three main object relationships between one another are as follows:

Astronaut has many Spacecraft
Astronaut visits many Planets via Spacecraft

Spacecraft belongs-to Astronaut, or has-many Astronauts
Spacecraft lands on Planet(s)

Planet belongs to Spacecraft
Planet has-many Astronauts via Spacecraft

The SpaceExploration::CLI class allows the user to interface within the domain modeling, while the API class is responsible for providing responses to the user. I created a diagram of the overall control flow where it displays each class' responsibility. The belongs-to and has-many relationships are mimicking real world space exploration.

Space-Exp Diagram

The journey begins at the International Space Station. The user, an Astronaut, will enter his/her name and years of space traveling experience. The user has an additional option to add another astronaut forming a crew. There will be 3 readily-available Spacecraft selections. They are SpaceX spacecraft, and the data is provided by SpaceX RESTful API. The user will have the option to select Planet, Dwarf Planet or Asteroid as a destination. Individual planetary attributes are limited to our Solar System in the Milky Way galaxy. The spacecraft will not be able to make its landing when the planet's gravity is equivalent to 0.0. The journey does not stop as the astronaut and/or the space crew arrive at their first destination. It will be a continuous loop of traveling options to other destinations, starting with the closest planet based on the user's current position. There are a total of 13 planets, and 273 dwarf planets and/or asteroids. If the spacecraft success rate is less than 50%, the space crew need to re-route back to the International Space Station, and select a different spacecraft. The user will also have another additional option to add another astronaut. Once the user completes his/her space travel, the whole space crew will return to the International Space Station with a summary record of astronauts list involved in this mission, spacecraft selected, and planets visited.

Setting up Ruby environment

I have to admit that setting up Ruby gemspec and config/environment.rb took me a while. I decided to watch a few video tutorials, learned simple bash commands, and found this tutorial video highly useful in setting up a basic Ruby environment. I set up ./bin/console as my immediate IRB session, which has been very useful in testing every single class and instance method, along with binding.pry especially when manipulating remote data sources. They became my Ruby's best friends. The ./bin/space_exploration would be the user starting point, triggering SpaceExploration::CLI.new.

There are a few fun Ruby gems that I explored. require_all is useful in lieu of repetitively utilizing require_relative. Few gems for fetching remote data sources include open-uri, net/http, and json. I am an architect, and design plays a huge role in what I do. I believe the better user interface I provide, the better the user experience in interacting with my application. colorize and lolize are amazing Ruby gems to add more colors. I plan to explore more Ruby gems post submission.

On a side note, learning git was another personal milestone achievement. I am now more comfortable with submitting my repo to GitHub manually, and understanding git in general. I was advised to keep my GitHub repo organized early as there will be more repo submissions as time progresses.

Command-Line Interface, Class and Module

The main challenge when developing the API, CLI, and other Classes was assigning responsibilities. There were a few times where I assigned class and instance methods incorrectly as it became more complex. Each model or class has its own sets of behaviors and attributes, and it is prudent to understand where each set belongs to which class. Re-factoring codes became an essential daily routine in order to maintain DRY (Don't-Repeat-Yourself) codes. The module was created to absorb any repetitive code occurring in each Class. It was another re-factoring exercise worth re-visiting once object relationships were defined.

After a week of ferociously coding my way through project completion, I went back and re-assessed my overall object relationships. I found myself spending a tremendous amount of time on my CLI class. This is where most of my code resides. One example is setting up if / else or case / when conditions for various user inputs. It forced me to create additional instance methods in order to loop-back to the original instance method when receiving invalid user inputs. This is useful in order to avoid jeopardizing the logic of the other methods that perceive valid feedback.

Overall, I am happy to be able to immerse myself in greater depths of understanding Ruby: Object-Oriented Programming (OOP). I recall last month that I only grasped basic Ruby procedural programming concepts. Ruby OOP is robust in its practical application from object relationships and architecture to meta-programming. I cannot wait to learn what Flatiron School has to offer next.

GitHub logo fentyhall / mod1_cli_space_exploration

Welcome to your Space Exploration, where you can select your space crew, pick your favorite spacecraft (powered by SpaceX), and infinite amount of planets in our Solar System to travel to!

SPACE EXPLORATION

Domain >> Space Travel Welcome to your Space Exploration, where you can select your space crew, pick your favorite spacecraft (powered by SpaceX), and infinite amount of planets in Milky Way Galaxy to travel to!

Relationships:

There are 3 main Model or classes >> Astronaut, Spacecraft and Planet.

Astronaut has many Spacecraft
Astronaut visits many Planets via Spacecraft
Spacecraft belongs-to Astronaut, or has-many Astronauts
Spacecraft lands on Planet(s)

Planet belongs to Spacecraft 
Planet has-many Astronauts via Spacecraft

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file lib/space_exploration. To experiment with that code, run bin/console for an interactive prompt.

TODO: Delete this and the text above, and describe your gem

Installation

Add this line to your application's Gemfile:

gem 'space_exploration'

And then execute:

  $

...

Post Scriptum:
I am currently enrolled in Flatiron's part-time Software Engineering program, and have decided to blog my coding journey. I believe one of the catalyst to becoming a good programmer is to welcome constructive criticism. Feel free to drop a message. 🙂

Keep Calm, and Code On.

External Sources:
Wikipedia
ASCII Art Archive
CLI Live Project Build: Part 1

Posted on by:

codinghall profile

codinghall

@codinghall

Programmer who was an architect, love solving puzzles!

Discussion

pic
Editor guide