|
1 | | -# Solar System |
| 1 | +## Project: Create a CLI program using OO principles |
2 | 2 |
|
3 | | -## At a Glance |
| 3 | +Upon execution, the CLI program outputs the following: |
4 | 4 |
|
5 | | -- Build a model of a solar system to practice working with classes |
6 | | -- Individual, [stage 1](https://github.com/Ada-Developers-Academy/pedagogy/blob/master/classroom/rule-of-three.md#stage-1) project |
7 | | -- Due before class, **Wednesday Sept 23rd** |
| 5 | +1. **list aliens**: The CLI program, creates a separate list for Earth and Venus with the corresponding alien race(s) who live there |
| 6 | +2. **read alien details**: If an alien race is found, details about the alien is displayed. Otherwise, a message notifies the user that the alien was not found |
| 7 | +3. **add an alien**: A user can add their own alien. The program asks for the name of their alien. Once complete, a third list named "Guest List" is added to the program |
| 8 | +4. **exit**: terminates the program loop to successfully exit the program |
8 | 9 |
|
9 | | -## Learning Goals |
10 | | - |
11 | | -- Create a class to tie together data and methods |
12 | | -- Create a class which manages a collection of other objects |
13 | | -- Write code that interacts with classes |
14 | | - |
15 | | -## Project Structure |
16 | | - |
17 | | -This project is broken up into three waves, each of which consists of a number of steps. You should `git commit` after you've completed each step! |
18 | | - |
19 | | -## Wave 1 |
20 | | - |
21 | | -The learning goal for this wave is to practice working with individual instances of a single class. |
22 | | - |
23 | | -### Instructions |
24 | | - |
25 | | -1. In a file called `planet.rb`, create a class called `Planet`. Each instance of this class will keep track of information about a single planet. |
26 | | - |
27 | | - Pay attention to the details of the class name `Planet`: |
28 | | - |
29 | | - - Class names always start with a capital letter |
30 | | - - Class names are usually a noun or noun-phrase |
31 | | - - Because each instance is only one planet, we use a singular noun (`Planet` instead of `Planets`) |
32 | | - |
33 | | -1. Add a constructor to your `Planet` class. Your constructor should take at least these 5 parameters: |
34 | | - - `name` |
35 | | - - `color` |
36 | | - - `mass_kg` |
37 | | - - `distance_from_sun_km` |
38 | | - - `fun_fact` |
39 | | - |
40 | | - Each parameter should be saved in an instance variable with the same name (e.g. `@color` for `color`). These instance variables should be _readable_ from outside the class, but not _writable_. |
41 | | - |
42 | | - Once you're done, you should be able to write code like this: |
43 | | - |
44 | | - ```ruby |
45 | | - # Load Planet into pry: |
46 | | - # $ pry -r ./planet.rb |
47 | | - earth = Planet.new('Earth', 'blue-green', 5.972e24, 1.496e8, 'Only planet known to support life') |
48 | | - |
49 | | - puts earth.name |
50 | | - # => Earth |
51 | | - puts earth.fun_fact |
52 | | - # => Only planet known to support life |
53 | | - |
54 | | - earth.color = 'pink' |
55 | | - # => NoMethodError: undefined method `color=' for #<Planet:0x00007fcfba04c130> |
56 | | - # => Did you mean? color |
57 | | - ``` |
58 | | - |
59 | | -1. Add another file, `main.rb`. This file should `require_relative` `planet.rb`, and contain one method called `main` that will exercise your code. This method should create two different instances of `Planet` and print out some of their attributes. |
60 | | - |
61 | | - `main.rb` should have this structure: |
62 | | - |
63 | | - ```ruby |
64 | | - # main.rb |
65 | | - require_relative 'planet' |
66 | | -
|
67 | | - def main |
68 | | - # ... do stuff with planets ... |
69 | | - end |
70 | | -
|
71 | | - main |
72 | | - ``` |
73 | | - |
74 | | - Note that we invoke `main` as the last line of your program. |
75 | | - |
76 | | -1. Add an instance method to `Planet` called `summary`. This method should _return_ (not `puts`) a string containing a nicely-formatted description of the planet. Exercise your `summary` method in the `main` method. |
77 | | - |
78 | | - **Question:** Why do we `puts` in `main` but not in `Planet#summary`? |
79 | | - |
80 | | -1. **OPTIONAL:** Add error checking to your constructor. |
81 | | - - Both `mass_kg` and `distance_from_sun_km` must be numbers that are greater than zero. |
82 | | - - What should your program do if they aren't? |
83 | | - - How will you make sure this behavior works? |
84 | | -
|
85 | | -1. **OPTIONAL:** Add minitest tests for `Planet`. |
86 | | -
|
87 | | -## Wave 2 |
88 | | -
|
89 | | -In this wave you will build a second class, `SolarSystem`, which is responsible for keeping track of a _collection_ of instances of `Planet`. |
90 | | -
|
91 | | -### Instructions |
92 | | -
|
93 | | -1. In a new file called `solar_system.rb`, create a new class called `SolarSystem`. |
94 | | - - The constructor should take one parameter, `star_name`, and save it in an instance variable. |
95 | | - - Each `SolarSystem` should have an instance variable called `@planets`, which will store an array of planets. When the `SolarSystem` is created, `@planets` should be set to an empty array. |
96 | | - - Both `@star_name` and `@planets` should be _readable_ but not _writable_. |
97 | | -
|
98 | | -1. Create a method `SolarSystem#add_planet`, which will take an instance of `Planet` as a parameter and add it to the list of planets. |
99 | | -
|
100 | | -1. Create a method `SolarSystem#list_planets`, which will _return_ (not `puts`) a string containing a list of all the planets in the system. The string should be formatted in this style: |
101 | | -
|
102 | | - ```bash |
103 | | - Planets orbiting <star name> |
104 | | - 1. Mercury |
105 | | - 2. Venus |
106 | | - 3. Earth |
107 | | - 4. Mars |
108 | | - 5. Jupiter |
109 | | - ``` |
110 | | -
|
111 | | -1. Update your driver code in `main.rb` to create an instance of `SolarSystem`, add all your `Planet`s to it, and then print the list. Here is an example with one `Planet`: |
112 | | -
|
113 | | - ```ruby |
114 | | - solar_system = SolarSystem.new('Sol') |
115 | | -
|
116 | | - earth = Planet.new('Earth', ...) |
117 | | - solar_system.add_planet(earth) |
118 | | -
|
119 | | - list = solar_system.list_planets |
120 | | - puts list |
121 | | - # => Planets orbiting Sol |
122 | | - # => 1. Earth |
123 | | - ``` |
124 | | -
|
125 | | - **NOTE:** When you first run your driver code, you may get an error like this: |
126 | | - ``` |
127 | | - NameError: uninitialized constant SolarSystem |
128 | | - ``` |
129 | | -
|
130 | | - What does this error mean? What do you need to do to fix it? |
131 | | -
|
132 | | -1. Create a method `SolarSystem#find_planet_by_name`, that takes the name of a planet as a string, and returns the corresponding instance of `Planet`. The lookup should be case-insensitive, so that `Earth`, `earth` and `eArTh` all return the same planet. |
133 | | -
|
134 | | - Update your driver code to exercise this method: |
135 | | -
|
136 | | - ```ruby |
137 | | - found_planet = solar_system.find_planet_by_name('Earth') |
138 | | -
|
139 | | - # found_planet is an instance of class Planet |
140 | | - puts found_planet |
141 | | - # => #<Planet:0x00007fe7c2868ee8> |
142 | | -
|
143 | | - puts found_planet.summary |
144 | | - # => Earth is a blue-green planet ... |
145 | | - ``` |
146 | | -
|
147 | | - Questions for you to consider as you write this method: |
148 | | - - What should your method do if there is no planet with the given name? |
149 | | - - What should your method do if there are multiple planets with the given name? |
150 | | - - Is there a built-in Ruby enumerable method that could help you here? |
151 | | -
|
152 | | -1. **OPTIONAL:** Create a method, `SolarSystem#distance_between`, that takes two planet names as parameters and returns the distance between them. |
153 | | -
|
154 | | - You can assume that all the planets are lined up in a straight line. |
155 | | -
|
156 | | -1. **OPTIONAL:** Add minitest tests for `SolarSystem`. |
157 | | -
|
158 | | -## Wave 3 |
159 | | -
|
160 | | -In this wave, you will build a command line interface (CLI) to allow a user to interact with your classes. This will _replace_ the driver code currently in the `main` method of `main.rb`. |
161 | | -
|
162 | | -### Instructions |
163 | | -
|
164 | | -1. Restructure `main` to do the following: |
165 | | - 1. Create a `SolarSystem` and add some `Planet`s |
166 | | - 1. Enter a control loop that repeatedly asks the user what to do next. The two options at this point are `list planets` and `exit`. |
167 | | -
|
168 | | - Remember that you've already implemented listing planets - you should be able to call that method rather than recreating the logic here. |
169 | | - |
170 | | -1. Add a `planet details` option to the control loop. When the user picks this option, the program should should call a separate method that will: |
171 | | - 1. Ask them for the name of the planet they wish to learn about |
172 | | - 1. Display details for that planet |
173 | | - |
174 | | - Again, you should reuse a method you've already built to handle formatting the planet information. |
175 | | -
|
176 | | -1. Add an `add planet` option to the control loop. When the user picks this option, the program should call a separate method that will: |
177 | | - 1. Ask the user for details about the planet |
178 | | - 1. Create a new instance of `Planet` with that info |
179 | | - 1. Add it to the `SolarSystem` |
180 | | -
|
181 | | - The new planet should now appear in the list of planets, and the user should be able to see its details. |
182 | | -
|
183 | | -1. **OPTIONAL:** Add error handling to the control loop. What happens if the user enters a bad command, asks for details on a planet that doesn't exist, or enters an bad value for a new planet's mass? |
184 | | -
|
185 | | -1. **OPTIONAL:** Implement the optional `distance_between` method from wave 2, then add an option to the control loop to expose it to the user. |
186 | | -
|
187 | | -## What Instructors Are Looking For |
188 | | -Checkout the [feedback template](feedback.md) for how instructors will evaluate your project. |
| 10 | + |
| 11 | + |
0 commit comments