From ed9dabca2f4a4e3bacb95e5f6152fe72494f2089 Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Thu, 25 Jul 2013 14:41:31 -0500 Subject: [PATCH 1/6] Panda Level Fixes --- lib/api.rb | 6 +++++- spec/api_spec.rb | 14 ++++++++++++++ spec/fixtures/none_found.json | 31 +++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 spec/fixtures/none_found.json 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/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}"} From 09f0f27037890f0bde440d6dd64271da33e48d28 Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Thu, 25 Jul 2013 15:34:37 -0500 Subject: [PATCH 2/6] Changes to command line app for Panda Level --- movie_json.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/movie_json.rb b/movie_json.rb index d8a91d7..f6fd749 100644 --- a/movie_json.rb +++ b/movie_json.rb @@ -5,7 +5,12 @@ def find_movie puts "OH HAI. Search?" movie_title = gets movie = Api.search_by_title(movie_title) - puts "Found: #{movie.title}. Score: #{movie.score}" + + if movie == :NotFound + puts "Didn't find that one." + else + puts "Found: #{movie.title}. Score: #{movie.score}" + end end find_movie From 2396735ee11d605f081d2c2393d58b8750abf446 Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Thu, 25 Jul 2013 15:50:44 -0500 Subject: [PATCH 3/6] Tiger Level with planning ahead for Eagle --- lib/collection.rb | 18 ++++++++++++++++++ spec/collection_spec.rb | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 lib/collection.rb create mode 100644 spec/collection_spec.rb diff --git a/lib/collection.rb b/lib/collection.rb new file mode 100644 index 0000000..be792ea --- /dev/null +++ b/lib/collection.rb @@ -0,0 +1,18 @@ +class Collection + attr_reader :movies + + def initialize + @movies = [] + end + + def add_movie movie + @movies << movie unless movie == :NotFound + end + + def average_score + + return 0 if @movies.size == 0 + + @movies.inject(0.0) {|sum, movie| sum + movie.score} / @movies.size + end +end \ No newline at end of file diff --git a/spec/collection_spec.rb b/spec/collection_spec.rb new file mode 100644 index 0000000..37de334 --- /dev/null +++ b/spec/collection_spec.rb @@ -0,0 +1,40 @@ +require_relative "../lib/movie" +require_relative "../lib/collection" + +describe Collection do + + let(:collection) {Collection.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)} + + 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 :NotFound + 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 + +end \ No newline at end of file From 9990ec6108b9c40b19c6072698b3368368f72ca6 Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Fri, 26 Jul 2013 11:09:19 -0500 Subject: [PATCH 4/6] Eagle level movie averaging and display --- lib/collection.rb | 41 +++++++++++++++++++++++++++++++++++++-- movie_json.rb | 33 +++++++++++++++++++++++++++++-- spec/collection_spec.rb | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 4 deletions(-) diff --git a/lib/collection.rb b/lib/collection.rb index be792ea..d5b2ec5 100644 --- a/lib/collection.rb +++ b/lib/collection.rb @@ -10,9 +10,46 @@ def add_movie movie end def average_score + average_for_movies @movies + end + + def average_for_movies(movie_list) + return 0 if movie_list.size == 0 - return 0 if @movies.size == 0 + movie_list.inject(0.0) {|sum, movie| sum + movie.score} / movie_list.size + end + + def average_year + return :NoData if @movies.size == 0 - @movies.inject(0.0) {|sum, movie| sum + movie.score} / @movies.size + @movies.inject(0) {|sum, movie| sum + movie.year} / @movies.size + end + + def average_per_year + dictionary = {} + separate_by_years.each {|year_list| dictionary[year_list.first.year.to_s] = average_for_movies year_list} + dictionary end + + def separate_by_years + sorted_movies = @movies.sort { |x,y| x.year <=> y.year } + array_of_years([],[sorted_movies.first], sorted_movies.slice(1,sorted_movies.length - 1)) + end + + def array_of_years(years_array, current_movies, remaining_movies) + if remaining_movies.size == 0 + years_array << current_movies + return years_array + else + movie = remaining_movies.first + if movie.year == current_movies.first.year + current_movies << movie + array_of_years(years_array, current_movies, remaining_movies.slice(1,remaining_movies.length- 1)) + else + years_array << current_movies + array_of_years(years_array, [movie], remaining_movies.slice(1,remaining_movies.length- 1)) + end + end + end + end \ No newline at end of file diff --git a/movie_json.rb b/movie_json.rb index f6fd749..0bd1afb 100644 --- a/movie_json.rb +++ b/movie_json.rb @@ -1,10 +1,15 @@ require_relative "lib/movie" require_relative "lib/api" +require_relative "lib/collection" + + +@collection = Collection.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) + @collection.add_movie movie if movie == :NotFound puts "Didn't find that one." @@ -13,14 +18,38 @@ def find_movie 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 + 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 break end end diff --git a/spec/collection_spec.rb b/spec/collection_spec.rb index 37de334..2333f0c 100644 --- a/spec/collection_spec.rb +++ b/spec/collection_spec.rb @@ -6,6 +6,7 @@ let(:collection) {Collection.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([]) @@ -36,5 +37,47 @@ 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 + + describe "decompose movie array into list of movies by year" + + it "should return a list of lists for a single movie" do + array_of_arrays = collection.array_of_years([], [movie], []) + array_of_arrays.should eq([[movie]]) + end + it "should put two movies with different years into different lists" do + + separate_list = collection.array_of_years([], [movie], [movie3]) + separate_list.should eq([[movie], [movie3]]) + end + + it "should put two movies with the same year in the same list" do + + + separate_list = collection.array_of_years([], [movie], [movie2]) + separate_list.should eq([[movie, movie2]]) + end + + it "should separate a collection of movies by year" do + collection.add_movie movie + collection.add_movie movie2 + collection.add_movie movie3 + separate_list = collection.separate_by_years + + separate_list.should eq([[movie, movie2], [movie3]]) + end end \ No newline at end of file From 10dcb0dc77ac40c091767e8ef079104d7ae6f3e0 Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Fri, 26 Jul 2013 13:54:07 -0500 Subject: [PATCH 5/6] Eagle level work --- lib/collection.rb | 14 ++++++++++++++ movie_json.rb | 11 +++++++++++ spec/collection_spec.rb | 31 ++++++++++++++++++++++--------- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/lib/collection.rb b/lib/collection.rb index d5b2ec5..18d59b0 100644 --- a/lib/collection.rb +++ b/lib/collection.rb @@ -51,5 +51,19 @@ def array_of_years(years_array, current_movies, remaining_movies) end end 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 :NeedMoreData 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 0bd1afb..4b5e7f0 100644 --- a/movie_json.rb +++ b/movie_json.rb @@ -39,6 +39,16 @@ def show_averages_by_year 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 @@ -50,6 +60,7 @@ def show_averages_by_year show_collection_average show_year_average show_averages_by_year + show_slope break end end diff --git a/spec/collection_spec.rb b/spec/collection_spec.rb index 2333f0c..5c1f931 100644 --- a/spec/collection_spec.rb +++ b/spec/collection_spec.rb @@ -52,25 +52,25 @@ collection.average_per_year.should eq({"1992" => 74, "1995" => 98}) end - describe "decompose movie array into list of movies by year" - + describe "decompose movie array into list of movies by year" do + it "should return a list of lists for a single movie" do array_of_arrays = collection.array_of_years([], [movie], []) array_of_arrays.should eq([[movie]]) end - + it "should put two movies with different years into different lists" do - separate_list = collection.array_of_years([], [movie], [movie3]) - separate_list.should eq([[movie], [movie3]]) - end + separate_list = collection.array_of_years([], [movie], [movie3]) + separate_list.should eq([[movie], [movie3]]) + end + + it "should put two movies with the same year in the same list" do - it "should put two movies with the same year in the same list" do - - separate_list = collection.array_of_years([], [movie], [movie2]) separate_list.should eq([[movie, movie2]]) end + end it "should separate a collection of movies by year" do collection.add_movie movie @@ -80,4 +80,17 @@ separate_list.should eq([[movie, movie2], [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(:NeedMoreData) + end + end \ No newline at end of file From 04a54a262aa88619875338c35466e857283b41e9 Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Mon, 29 Jul 2013 12:00:25 -0500 Subject: [PATCH 6/6] Rework based on jwo comments --- lib/collection.rb | 69 ------------------- lib/movie_collection.rb | 59 ++++++++++++++++ movie_json.rb | 4 +- ...ction_spec.rb => movie_collection_spec.rb} | 41 +++-------- 4 files changed, 70 insertions(+), 103 deletions(-) delete mode 100644 lib/collection.rb create mode 100644 lib/movie_collection.rb rename spec/{collection_spec.rb => movie_collection_spec.rb} (60%) diff --git a/lib/collection.rb b/lib/collection.rb deleted file mode 100644 index 18d59b0..0000000 --- a/lib/collection.rb +++ /dev/null @@ -1,69 +0,0 @@ -class Collection - attr_reader :movies - - def initialize - @movies = [] - end - - def add_movie movie - @movies << movie unless movie == :NotFound - 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 :NoData if @movies.size == 0 - - @movies.inject(0) {|sum, movie| sum + movie.year} / @movies.size - end - - def average_per_year - dictionary = {} - separate_by_years.each {|year_list| dictionary[year_list.first.year.to_s] = average_for_movies year_list} - dictionary - end - - def separate_by_years - sorted_movies = @movies.sort { |x,y| x.year <=> y.year } - array_of_years([],[sorted_movies.first], sorted_movies.slice(1,sorted_movies.length - 1)) - end - - def array_of_years(years_array, current_movies, remaining_movies) - if remaining_movies.size == 0 - years_array << current_movies - return years_array - else - movie = remaining_movies.first - if movie.year == current_movies.first.year - current_movies << movie - array_of_years(years_array, current_movies, remaining_movies.slice(1,remaining_movies.length- 1)) - else - years_array << current_movies - array_of_years(years_array, [movie], remaining_movies.slice(1,remaining_movies.length- 1)) - end - end - 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 :NeedMoreData 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/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 4b5e7f0..6bf1ae3 100644 --- a/movie_json.rb +++ b/movie_json.rb @@ -1,9 +1,9 @@ require_relative "lib/movie" require_relative "lib/api" -require_relative "lib/collection" +require_relative "lib/movie_collection" -@collection = Collection.new +@collection = MovieCollection.new def find_movie puts "OH HAI. Add a movie to your collection?" diff --git a/spec/collection_spec.rb b/spec/movie_collection_spec.rb similarity index 60% rename from spec/collection_spec.rb rename to spec/movie_collection_spec.rb index 5c1f931..4519adf 100644 --- a/spec/collection_spec.rb +++ b/spec/movie_collection_spec.rb @@ -1,9 +1,9 @@ require_relative "../lib/movie" -require_relative "../lib/collection" +require_relative "../lib/movie_collection" -describe Collection do +describe MovieCollection do - let(:collection) {Collection.new} + 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)} @@ -18,7 +18,7 @@ end it "should not add the Not Found sentinel" do - collection.add_movie :NotFound + collection.add_movie :not_found collection.movies.should eq([]) end @@ -49,36 +49,13 @@ collection.add_movie movie collection.add_movie movie3 collection.add_movie movie2 - collection.average_per_year.should eq({"1992" => 74, "1995" => 98}) - end - - describe "decompose movie array into list of movies by year" do - - it "should return a list of lists for a single movie" do - array_of_arrays = collection.array_of_years([], [movie], []) - array_of_arrays.should eq([[movie]]) - end - - it "should put two movies with different years into different lists" do - - separate_list = collection.array_of_years([], [movie], [movie3]) - separate_list.should eq([[movie], [movie3]]) - end - - it "should put two movies with the same year in the same list" do - - separate_list = collection.array_of_years([], [movie], [movie2]) - separate_list.should eq([[movie, movie2]]) - end + collection.average_per_year.should eq({1992 => 74, 1995 => 98}) end - it "should separate a collection of movies by year" do - collection.add_movie movie - collection.add_movie movie2 - collection.add_movie movie3 - separate_list = collection.separate_by_years + it "should separate an array of movies by year" do + movie_hash = collection.movies_by_year [movie, movie2, movie3] - separate_list.should eq([[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 @@ -90,7 +67,7 @@ it "should return a sentintal if it can't compute the slope" do collection.add_movie movie - collection.rating_slope.should eq(:NeedMoreData) + collection.rating_slope.should eq(:need_more_data) end end \ No newline at end of file