diff --git a/lib/api.rb b/lib/api.rb index a8d499c..cecc4c5 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -8,7 +8,11 @@ class Api 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) + full_json = get_url_as_json(url) + + return :NotFound if full_json.fetch("total").to_i == 0 + + struct = OpenStruct.new(full_json.fetch("movies").first) Movie.new(id: struct.id.to_i, title: struct.title, year: struct.year, diff --git a/lib/movie_collection.rb b/lib/movie_collection.rb new file mode 100644 index 0000000..a428aa0 --- /dev/null +++ b/lib/movie_collection.rb @@ -0,0 +1,59 @@ +require_relative "./movie" + +class MovieCollection + attr_reader :movies + + def initialize + @movies = [] + end + + def add_movie movie + @movies << movie unless movie == :not_found + end + + def average_score + average_for_movies @movies + end + + def average_for_movies(movie_list) + return 0 if movie_list.size == 0 + + movie_list.inject(0.0) {|sum, movie| sum + movie.score} / movie_list.size + end + + def average_year + return :no_data if @movies.size == 0 + + @movies.inject(0) {|sum, movie| sum + movie.year} / @movies.size + end + + def average_per_year + dictionary = {} + movies_by_year(@movies).each_pair { |key, value| dictionary[key] = average_for_movies value} + dictionary + end + + def movies_by_year(movies) + hash = {} + movies.each do |movie| + hash[movie.year] ||= [] + hash[movie.year] << movie + end + hash + end + + def rating_slope + yearly_averages = average_per_year + # I think the keys should already be sorted by year, but just in case do it anyway + sorted_years = yearly_averages.keys.sort + + return :need_more_data if sorted_years.length < 2 + + first_avg = yearly_averages[sorted_years.first] + last_avg = yearly_averages[sorted_years.last] + + (first_avg - last_avg).to_f / (sorted_years.first.to_i - sorted_years.last.to_i).to_f + + end + +end \ No newline at end of file diff --git a/movie_json.rb b/movie_json.rb index d8a91d7..6bf1ae3 100644 --- a/movie_json.rb +++ b/movie_json.rb @@ -1,21 +1,66 @@ require_relative "lib/movie" require_relative "lib/api" +require_relative "lib/movie_collection" + + +@collection = MovieCollection.new def find_movie - puts "OH HAI. Search?" + puts "OH HAI. Add a movie to your collection?" movie_title = gets movie = Api.search_by_title(movie_title) - puts "Found: #{movie.title}. Score: #{movie.score}" + @collection.add_movie movie + + if movie == :NotFound + puts "Didn't find that one." + else + puts "Found: #{movie.title}. Score: #{movie.score}" + end +end + +def show_collection_average + puts "The average score of your collection is #{@collection.average_score}." + if @collection.average_score > 75 + puts "Excellent tastes!" + elsif @collection.average_score > 25 + puts "Nice collection." + else + puts "You have very unique tastes." + end +end + +def show_year_average + puts "The average year of your collection is #{@collection.average_year}" +end + +def show_averages_by_year + yearly_averages = @collection.average_per_year + puts "Your movie average by year is:" + yearly_averages.each { |year, avg| puts "#{year} : #{avg}" } +end + +def show_slope + slope = @collection.rating_slope + puts "The slope of your movie ratings is #{slope}." + if slope < 0 + puts "Your tastes are declining. You mad, bro?" + else + puts "The quality of films is improving. Release that anger!" + end end find_movie while true do - puts "Search Again (Y/N)" + puts "Add another? (Y/N)" answer = gets.upcase[0] if answer == "Y" find_movie else + show_collection_average + show_year_average + show_averages_by_year + show_slope break end end diff --git a/spec/api_spec.rb b/spec/api_spec.rb index 9014106..4b17e28 100644 --- a/spec/api_spec.rb +++ b/spec/api_spec.rb @@ -24,4 +24,18 @@ it "should return the year" do movie.year.should eq(1994) end + + describe "empty movie tests" do + + let(:emptyMovie) {Api.search_by_title("FHAHAHAHA")} + + before do + Api.stub(:get_url_as_json) { JSON.parse(File.read("spec/fixtures/none_found.json"))} + end + + it "should return a not found sentintel when there is no movie" do + movie = Api.search_by_title("FHFHFHF") + movie.should eq(:NotFound) + end + end end diff --git a/spec/fixtures/none_found.json b/spec/fixtures/none_found.json new file mode 100644 index 0000000..a86b7f7 --- /dev/null +++ b/spec/fixtures/none_found.json @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{"total":0,"movies":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=FHAHAHAHA&page_limit=1&page=1"},"link_template":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q={search-term}&page_limit={results-per-page}&page={page-number}"} diff --git a/spec/movie_collection_spec.rb b/spec/movie_collection_spec.rb new file mode 100644 index 0000000..4519adf --- /dev/null +++ b/spec/movie_collection_spec.rb @@ -0,0 +1,73 @@ +require_relative "../lib/movie" +require_relative "../lib/movie_collection" + +describe MovieCollection do + + let(:collection) {MovieCollection.new} + let(:movie) {Movie.new(title: "Pulp Fiction", year: 1992, id: 233, score: 50) } + let(:movie2) { Movie.new(title: "Run Lola Run", year: 1992, id: 233, score: 98)} + let(:movie3) { Movie.new(title: "Run Lola Run", year: 1995, id: 233, score: 98)} + + it "contains a set of movies" do + collection.movies.should eq([]) + end + + it "should add a movie to the collection" do + collection.add_movie movie + collection.movies.should eq([movie]) + end + + it "should not add the Not Found sentinel" do + collection.add_movie :not_found + collection.movies.should eq([]) + end + + it "the average score of an empty collection should be zero" do + collection.average_score.should eq(0) + end + + it "should have an average score the same as the movie in a single collection" do + + collection.add_movie movie + collection.average_score.should eq(50) + end + + it "should provide the average score for collection" do + collection.add_movie movie + collection.add_movie movie2 + collection.average_score.should eq(74) + end + + it "should provide the average year for the collection" do + collection.add_movie movie + collection.add_movie movie2 + collection.add_movie movie3 + collection.average_year.should eq(1993) + end + + it "should provide the average score per year" do + collection.add_movie movie + collection.add_movie movie3 + collection.add_movie movie2 + collection.average_per_year.should eq({1992 => 74, 1995 => 98}) + end + + it "should separate an array of movies by year" do + movie_hash = collection.movies_by_year [movie, movie2, movie3] + + movie_hash.should eq({1992 => [movie, movie2], 1995 => [movie3]}) + end + + it "should calculate the slope of ratings from the first year to the last year of the collection" do + collection.add_movie movie + collection.add_movie movie2 + collection.add_movie movie3 + collection.rating_slope.should eq(8) + end + + it "should return a sentintal if it can't compute the slope" do + collection.add_movie movie + collection.rating_slope.should eq(:need_more_data) + end + +end \ No newline at end of file