diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..f29f7c93 --- /dev/null +++ b/Rakefile @@ -0,0 +1,9 @@ +require 'rake/testtask' + +Rake::TestTask.new do |t| + t.libs = ["lib"] + t.warning = true + t.test_files = FileList['specs/*_spec.rb'] +end + +task default: :test \ No newline at end of file diff --git a/lib/main.rb b/lib/main.rb new file mode 100644 index 00000000..98c5d9b4 --- /dev/null +++ b/lib/main.rb @@ -0,0 +1,112 @@ +require_relative "planet" +require_relative "solar_system" + +require "awesome_print" +require "colorize" + +SOLAR_SYSTEM = SolarSystem.new("Sol") + +# Optional: handling user entering bad command +def handling_input(input) + possible_inputs = ["list planets", "planet details", "add planet", "find distance", "exit"] + until possible_inputs.any? { |word| word == input } + print "Invalid input.\nPlease enter \"list planets\", \"planet details\", \"add planet\", \"find distance\" or \"exit\": " + input = gets.chomp.downcase + end + return input +end + +def existing_planets + earth = Planet.new("Earth", "blue-green", 5.972e24, 1.496e8, "it's the only planet known to support life") + SOLAR_SYSTEM.add_planet(earth) + + venus = Planet.new("Venus", "yellow", 4.867e24, 67.3e6, "40 spacecraft have explored Venus") + SOLAR_SYSTEM.add_planet(venus) + + mercury = Planet.new("Mercury", "blue", 3.285e23, 28.6e6, "kid-friendly") + SOLAR_SYSTEM.add_planet(mercury) + + mars = Planet.new("Mars", "orange", 6.39e23, 141.7e6, "it has 2 moons") + SOLAR_SYSTEM.add_planet(mars) +end + +def list_planets(input) + if input == "list planets" + list = SOLAR_SYSTEM.list_planets + puts list.colorize(:green) + end +end + +def planet_details(input) + if input == "planet details" + puts "Which planet do you want to learn about? Choose one: Earth, Venus, Mercury, Mars" + planet_chosen = gets.chomp.downcase + # Optional: when user enters a planet that doesn't exist, raise an exception. + if !SOLAR_SYSTEM.planets.map { |planet| planet.name }.include?(planet_chosen.capitalize) + raise ArgumentError, "Planet entered is not in the list." + end + puts "\n" + puts SOLAR_SYSTEM.find_planet_by_name(planet_chosen).summary.colorize(:green) + end +end + +def add_planet(input) + if input == "add planet" + puts "What is the planet's name?" + name = gets.chomp.capitalize + puts "What is its color?" + color = gets.chomp + puts "What is its mass(kg)?" + mass_kg = gets.chomp.to_f + # Optional: if user enters a bad value + until mass_kg > 0 + puts "Mass must be a number greater than 0. Please enter again: " + mass_kg = gets.chomp.to_f + end + puts "What is its distance from the Sun in km?" + distance_from_sun_km = gets.chomp.to_f + # Optional: if the user enters a bad value + until distance_from_sun_km > 0 + puts "Distance from the Sun must be a number greater than 0. Please enter again: " + distance_from_sun_km = gets.chomp.to_f + end + puts "What is its fun fact?" + fun_fact = gets.chomp + + planet = Planet.new(name, color, mass_kg, distance_from_sun_km, fun_fact) + SOLAR_SYSTEM.add_planet(planet) + puts "#{name} has been added with the details below:".colorize(:green) + puts SOLAR_SYSTEM.find_planet_by_name(name).summary.colorize(:green) + end +end + +def find_distance(input) + if input == "find distance" + puts "Enter first planet: " + planet_name1 = gets.chomp.downcase + puts "Enter second planet: " + planet_name2 = gets.chomp.downcase + puts "The distance is #{SOLAR_SYSTEM.distance_between(planet_name1, planet_name2)}".colorize(:green) + end +end + +def main + existing_planets + puts "What would you like to do?" + print "Please enter \"list planets\", \"planet details\", \"add planet\", \"find distance\" or \"exit\": " + input = gets.chomp.downcase + input = handling_input(input) + + until input == "exit" + list_planets(input) + planet_details(input) + add_planet(input) + find_distance(input) # OPTIONAL: Implement the optional distance_between method + puts "What would you like to do next?" + puts "Please enter \"list planets\", \"planet details\", \"add planet\", \"find distance\" or \"exit\": " + input = gets.chomp + input = handling_input(input) + end +end + +main diff --git a/lib/planet.rb b/lib/planet.rb new file mode 100644 index 00000000..47e426bc --- /dev/null +++ b/lib/planet.rb @@ -0,0 +1,16 @@ +class Planet + attr_reader :name, :color, :mass_kg, :distance_from_sun_km, :fun_fact + + def initialize(name, color, mass_kg, distance_from_sun_km, fun_fact) + @name = name + @color = color + @mass_kg = mass_kg + @distance_from_sun_km = distance_from_sun_km + @fun_fact = fun_fact + end + + # gets the details of the planet + def summary + return "#{name} is a/an #{color} planet. Its mass is #{mass_kg}kg, and it is #{distance_from_sun_km}km from the Sun. Fun fact: #{fun_fact}." + end +end diff --git a/lib/solar_system.rb b/lib/solar_system.rb new file mode 100644 index 00000000..413bc0eb --- /dev/null +++ b/lib/solar_system.rb @@ -0,0 +1,39 @@ +require_relative "planet" + +class SolarSystem + attr_reader :star_name, :planets #should keep? if so, need to add to spec + + def initialize(star_name) + @star_name = star_name + @planets = [] + end + + def add_planet(planet) + raise ArgumentError, "Planet has to be an instance of Planet class" if !planet.is_a?(Planet) + raise ArgumentError, "Planet has already been added." if @planets.any? { |i| i.name.downcase == planet.name.downcase } + @planets.push(planet) + end + + def list_planets + list = "\nPlanets orbitting #{@star_name}:\n" + @planets.each_with_index do |planet, index| + list = list + "#{index + 1}. #{planet.name}\n" + end + return list + end + + def find_planet_by_name(name) + @planets.each do |planet| + return planet if (planet.name).downcase == name.downcase + end + # if the planet is not found, raise an exception + raise ArgumentError, "#{name} is not found." + end + + # Optional: takes two planet names as parameters and returns the distance between them + def distance_between(planet_name1, planet_name2) + distance_planet1 = find_planet_by_name(planet_name1).distance_from_sun_km + distance_planet2 = find_planet_by_name(planet_name2).distance_from_sun_km + return (distance_planet1 - distance_planet2).abs + end +end diff --git a/specs/planet_spec.rb b/specs/planet_spec.rb new file mode 100644 index 00000000..880d73c5 --- /dev/null +++ b/specs/planet_spec.rb @@ -0,0 +1,34 @@ + +require "minitest/autorun" +require "minitest/reporters" +require "minitest/skip_dsl" + +require_relative "../lib/planet" + +# Get that nice colorized output +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new + +describe "planet" do + describe "initialize" do + it "will create an instance of the class Planet with 5 parameters" do + new_planet = Planet.new("earth", "blue", 45, 67, "supports life") + expect(new_planet).must_be_instance_of Planet + end + + it "will correctly read the parameters of the planet" do + new_planet = Planet.new("earth", "blue", 45, 67, "supports life") + expect(new_planet.name).must_equal "earth" + expect(new_planet.color).must_equal "blue" + expect(new_planet.mass_kg).must_equal 45 + expect(new_planet.distance_from_sun_km).must_equal 67 + expect(new_planet.fun_fact).must_equal "supports life" + end + + describe "summary" do + it "will return a summary of the planet" do + new_planet = Planet.new("earth", "blue", 45, 67, "supports life") + expect(new_planet.summary).must_be_instance_of String + end + end + end +end diff --git a/specs/solar_system_spec.rb b/specs/solar_system_spec.rb new file mode 100644 index 00000000..e9de1d86 --- /dev/null +++ b/specs/solar_system_spec.rb @@ -0,0 +1,65 @@ +require "minitest/autorun" +require "minitest/reporters" + +require_relative "../lib/solar_system" + +# Get that nice colorized output +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new + +describe "solar_system" do + describe "initialize method" do + new_sol = SolarSystem.new("New Sol") + it "will create an instance of the class SolarSystem with an empty array planets " do + expect(new_sol).must_be_instance_of SolarSystem + expect(new_sol.planets).must_equal [] + end + + it "will read the star name when initialized" do + expect(new_sol.star_name).must_equal "New Sol" + end + end + + describe "add_planet method" do + new_sol = SolarSystem.new("New Sol") + it "will take a planet and return an array of planets" do + pluto = Planet.new("Pluto", "pink", 56, 87, "pet-friendly") + expect(new_sol.add_planet(pluto)).must_be_instance_of Array + end + + it "will take the parameter as a planet" do + pluto = "Pluto" + # note to me: when using curly braces, the code inside runs before expect + # when using with .must_raise + expect { new_sol.add_planet(pluto) }.must_raise ArgumentError + end + end + + describe "list_planets method" do + new_sol = SolarSystem.new("New Sol") + pluto = Planet.new("Pluto", "pink", 56, 87, "pet-friendly") + new_sol.add_planet(pluto) + it "will return true if the list is an instance of a string" do + expect(new_sol.list_planets).must_be_instance_of String + end + end + + describe "find_planet_by_name method" do + new_sol = SolarSystem.new("New Sol") + pluto = Planet.new("Pluto", "pink", 56, 87, "pet-friendly") + new_sol.add_planet(pluto) + it "will return an instance of Planet" do + expect(new_sol.find_planet_by_name("Pluto")).must_be_instance_of Planet + end + end + + describe "distance_between method" do + it "will return the distance between two planets" do + new_sol = SolarSystem.new("New_Sol") + pluto = Planet.new("Pluto", "pink", 56, 87, "pet-friendly") + puffer = Planet.new("Puffer", "yellow", 78, 89, "not a planet") + new_sol.add_planet(pluto) + new_sol.add_planet(puffer) + expect(new_sol.distance_between(pluto.name, puffer.name)).must_equal 2 + end + end +end