-
Notifications
You must be signed in to change notification settings - Fork 25
Tiger level challenge #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 7 commits
3327705
db6bd24
7b24a18
e44934a
5e25e2d
f2b49c6
0cbe442
a14999e
69448dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| api_key.rb |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| --color | ||
| --format documentation |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,28 @@ | ||
| require "open-uri" | ||
| require "json" | ||
| require "ostruct" | ||
| require_relative "./movie" | ||
| require_relative "./api_key" | ||
|
|
||
| class Api | ||
|
|
||
| APIKEY="4t6456xa33z8qhcqyuqgnkjh" | ||
| APIKEY=API_KEY | ||
|
|
||
| def self.search_by_title(title) | ||
| url = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=#{APIKEY}&q=#{URI.encode(title)}&page_limit=1" | ||
| struct = OpenStruct.new(get_url_as_json(url).fetch("movies").first) | ||
| Movie.new(id: struct.id.to_i, | ||
| title: struct.title, | ||
| year: struct.year, | ||
| score: struct.ratings["critics_score"] | ||
| ) | ||
| struct.id.nil? ? "Sorry we could not find that movie" : store_movie(struct) | ||
| end | ||
|
|
||
|
|
||
| def self.get_url_as_json(url) | ||
| JSON.parse(open(url).read) | ||
| end | ||
|
|
||
| def self.store_movie(movie_struct) | ||
| Movie.new(id: movie_struct.id.to_i, | ||
| title: movie_struct.title, | ||
| year: movie_struct.year, | ||
| score: movie_struct.ratings["critics_score"] | ||
| ) | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,114 @@ | ||
| require_relative "lib/movie" | ||
| require_relative "lib/api" | ||
|
|
||
| def find_movie | ||
| puts "OH HAI. Search?" | ||
| movie_title = gets | ||
| movie = Api.search_by_title(movie_title) | ||
| puts "Found: #{movie.title}. Score: #{movie.score}" | ||
| end | ||
| class MovieJson | ||
|
|
||
| attr_reader :movies | ||
| def initialize | ||
| @movies = [] | ||
| end | ||
|
|
||
| def run | ||
| search | ||
| end | ||
|
|
||
| find_movie | ||
| def movie_search_by_title | ||
| puts "OH HAI. Please add a movie you like" | ||
| print ">>" | ||
| movie_title = gets.downcase.chomp | ||
| return "Sorry, but you have to actually enter something to search" if movie_title.empty? | ||
| puts "Cool, searching for #{movie_title}" | ||
| search = add_to_movie_list(movie_title) | ||
| return search if search.class == String | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't love this -- checking a specific class isn't done usually in Ruby. If you wanted something like this, you could check the signature of the object. movie.respond_to? :titleThat way it can be any object, as long as it following the protocol/interface you need. More broadly, I'd rather you use a NilClass pattern than return a string. Here's an example library I like: https://github.com/avdi/naught |
||
| puts movie_title != search.title ? "This is the closest we could find: #{search.title} was released in #{search.year}. It recieved a critics score of #{search.score}" : "#{search.title} was released in #{search.year}. It recieved a critics score of #{search.score}" | ||
| end | ||
|
|
||
| def add_to_movie_list(movie) | ||
| found_movie = Api.search_by_title(movie) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One of the things you can do in ruby is "tap" an object. I think it could work well here: This method seems to do 2 things though: it searches for movies, and adds to a list. Is this the right name for that method? |
||
| @movies << found_movie | ||
| found_movie | ||
| end | ||
|
|
||
| def search_again(response) | ||
| if response == "yes" | ||
| movie_search_by_title | ||
| elsif response == "no" | ||
| false | ||
| else | ||
| puts "I don't understand that" | ||
| end | ||
| end | ||
|
|
||
| while true do | ||
| puts "Search Again (Y/N)" | ||
| answer = gets.upcase[0] | ||
| if answer == "Y" | ||
| find_movie | ||
| else | ||
| break | ||
| def search | ||
| puts "Would you like to: \n1) Search\n2) Average rating?\n3) Average year?\n4) Calculate movie happiness?\n5) Exit?" | ||
| print ">>" | ||
| u_start = gets.chomp | ||
| if u_start == "1" | ||
| puts movie_search_by_title | ||
| while true | ||
| puts "Search Again? Yes or No" | ||
| re_search = gets.downcase.chomp | ||
| break if search_again(re_search) == false | ||
| end | ||
| search | ||
| elsif u_start == "2" | ||
| puts average_raiting | ||
| search | ||
| elsif u_start == "3" | ||
| puts average_year | ||
| search | ||
| elsif u_start == "4" | ||
| puts calculate_happiness | ||
| search | ||
| else | ||
| puts "Exiting..." | ||
| end | ||
| end | ||
|
|
||
| def average_raiting | ||
| @movies.map {|movie| movie.score}.reduce(:+).to_f / @movies.size | ||
| end | ||
|
|
||
| def average_year | ||
| avg_year = @movies.map { |movie| movie.year}.reduce(:+).to_f / @movies.size | ||
| avg_year.to_i | ||
| end | ||
|
|
||
| def calculate_happiness | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method definitely works; it's hard to read though. Could you rewrite it using the constraint that a method should be no more than 3 lines long? |
||
| # ratings = @movies.map { |movie| movie.score } | ||
| year_avg = {} | ||
| @movies.each { |movie| year_avg[movie.year] = [] } | ||
| @movies.each { |movie| year_avg[movie.year].push(movie.score) } | ||
| years = @movies.map { |movie| movie.year}.sort | ||
| oldest_year_avg = year_avg[years[0]].reduce(:+).to_f / year_avg[years[0]].size | ||
| youngest_year_avg = year_avg[years[-1]].reduce(:+).to_f / year_avg[years[-1]].size | ||
| slope = years[0] - years[-1] != 0 ? (youngest_year_avg - oldest_year_avg).to_f / (years[-1] - years[0]).to_f : 0 | ||
| if slope == 0 | ||
| return "You're neutral" | ||
| elsif slope > 0 | ||
| return "You're getting happier!" | ||
| else | ||
| return "You're getting sadder" | ||
| end | ||
| end | ||
|
|
||
| end | ||
| MovieJson.new.run if __FILE__ == $PROGRAM_NAME | ||
| # def find_movie | ||
| # puts "OH HAI. Search?" | ||
| # movie_title = gets | ||
| # movie = Api.search_by_title(movie_title) | ||
| # puts "Found: #{movie.title}. Score: #{movie.score}" | ||
| # end | ||
|
|
||
| # find_movie | ||
|
|
||
| # while true do | ||
| # puts "Search Again (Y/N)" | ||
| # answer = gets.upcase[0] | ||
| # if answer == "Y" | ||
| # find_movie | ||
| # else | ||
| # break | ||
| # end | ||
| # end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {"total":0,"movies":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=Forrest+Gump&page_limit=1&page=1","next":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=Forrest+Gump&page_limit=1&page=2"},"link_template":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q={search-term}&page_limit={results-per-page}&page={page-number}"} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| require_relative "../movie_json" | ||
| require_relative "../lib/api" | ||
| require_relative "../lib/movie" | ||
|
|
||
| describe MovieJson do | ||
|
|
||
| let(:movie) { Movie.new(id: "111", | ||
| title: "Forrest Gump", | ||
| year: 1994, | ||
| score: 71) | ||
| } | ||
| let(:happy_movie) { Movie.new(id: "112", | ||
| title: "Happy movie", | ||
| year: 1995, | ||
| score: 99) | ||
| } | ||
| let(:sad_movie) { Movie.new(id: "113", | ||
| title: "Sad movie", | ||
| year: 1995, | ||
| score: 1)} | ||
|
|
||
| before do | ||
| # Api.stub(:get_url_as_json) { JSON.parse(File.read("spec/fixtures/forrest.json")) } | ||
| Api.stub(:search_by_title) {movie} | ||
| # MovieJson.stub(:gets).and_return("") | ||
| end | ||
|
|
||
| describe "#movie_search_by_title" do | ||
| it "should return a warning when no movie is entered into the search" do | ||
| movie_search1 = MovieJson.new | ||
| movie_search1.stub(:gets).and_return("") | ||
| movie_search1.movie_search_by_title.should == "Sorry, but you have to actually enter something to search" | ||
| end | ||
| end | ||
|
|
||
| it "should allow the user to add two movies they like" do | ||
| movie_search2 = MovieJson.new | ||
| movie_search2.add_to_movie_list(movie) | ||
| movie_search2.add_to_movie_list(movie) | ||
| expect(movie_search2.movies.length).to eq(2) | ||
| end | ||
|
|
||
| describe "#average_raiting" do | ||
| it "should give average rating of the movies in your list" do | ||
| movie_search3 = MovieJson.new | ||
| movie_search3.add_to_movie_list(movie) | ||
| movie_search3.add_to_movie_list(movie) | ||
| expect(movie_search3.average_raiting).to eq(71) | ||
| end | ||
| end | ||
|
|
||
| describe "#average_year" do | ||
| it "should give the average year of the movies in your list" do | ||
| movie_search4 = MovieJson.new | ||
| movie_search4.add_to_movie_list(movie) | ||
| movie_search4.add_to_movie_list(movie) | ||
| expect(movie_search4.average_year).to eq(1994) | ||
| end | ||
| end | ||
|
|
||
| describe "#calculate_happiness" do | ||
| it "should say your neutral at neutral slope" do | ||
| movie_search5 = MovieJson.new | ||
| movie_search5.add_to_movie_list(movie) | ||
| movie_search5.add_to_movie_list(movie) | ||
| movie_search5.calculate_happiness.should == "You're neutral" | ||
| end | ||
|
|
||
| it "should say your happier at postive slope" do | ||
| movie_search6 = MovieJson.new | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't have to name these each time --- every spec can be |
||
| movie_search6.add_to_movie_list(movie) | ||
| Api.stub(:search_by_title) {happy_movie} | ||
| movie_search6.add_to_movie_list(happy_movie) | ||
| movie_search6.calculate_happiness.should == "You're getting happier!" | ||
| end | ||
|
|
||
| it "should say your sadder at negative slope" do | ||
| movie_search7 = MovieJson.new | ||
| movie_search7.add_to_movie_list(movie) | ||
| Api.stub(:search_by_title) {sad_movie} | ||
| movie_search7.add_to_movie_list(sad_movie) | ||
| movie_search7.calculate_happiness.should == "You're getting sadder" | ||
| end | ||
|
|
||
| it "should take the average of years that are the same and determine slope" do | ||
| movie_search7 = MovieJson.new | ||
| movie_search7.add_to_movie_list(movie) | ||
| Api.stub(:search_by_title) {sad_movie} | ||
| movie_search7.add_to_movie_list(sad_movie) | ||
| Api.stub(:search_by_title) {happy_movie} | ||
| movie_search7.add_to_movie_list(happy_movie) | ||
| movie_search7.calculate_happiness.should == "You're getting sadder" | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,8 @@ | ||
| require_relative "../lib/movie" | ||
|
|
||
|
|
||
|
|
||
|
|
||
| describe Movie do | ||
|
|
||
| it "should store the title, year, and score" do | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the moving the key into a git-ignored file. But, you can just have that set your variable... in
api_key.rbhave it set APIKEY directly. This line ends up looking odd (and future-you won't remember what this is)