mmc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +6 -0
- data/bin/mmc +286 -0
- data/lib/mmc.rb +1 -0
- data/mmc.gemspec +13 -0
- metadata +51 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/Gemfile
ADDED
data/bin/mmc
ADDED
@@ -0,0 +1,286 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'json'
|
5
|
+
require 'open-uri'
|
6
|
+
require 'nokogiri'
|
7
|
+
|
8
|
+
# Method for converting fractions to decimals. Used below in "calculate_average" method.
|
9
|
+
def frac_to_float(str)
|
10
|
+
numerator, denominator = str.split("/").map(&:to_f)
|
11
|
+
denominator ||= 1
|
12
|
+
numerator/denominator
|
13
|
+
end
|
14
|
+
|
15
|
+
def identify_movie(title)
|
16
|
+
def search(title)
|
17
|
+
url = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=hv4pzbs4n46nmv7s9w87nzwu&q=#{title}&page_limit=20"
|
18
|
+
buffer = open(url).read
|
19
|
+
|
20
|
+
# convert JSON data into a hash
|
21
|
+
result = JSON.parse(buffer)
|
22
|
+
end
|
23
|
+
|
24
|
+
#Format and produce the search output
|
25
|
+
def search_output(movie_list)
|
26
|
+
count = 0
|
27
|
+
movie_list["movies"].each do |h|
|
28
|
+
print "#{count}) "
|
29
|
+
if count <10
|
30
|
+
print " " #Ensure that first column is 2 spaces wide
|
31
|
+
end
|
32
|
+
print "Title: #{h["title"]}"
|
33
|
+
if h["title"].length < 70
|
34
|
+
print " "*(70-h["title"].length) #Ensure that first column is 70 spaces wide
|
35
|
+
end
|
36
|
+
print "Year: #{h["year"]}"
|
37
|
+
print "\n"
|
38
|
+
count += 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#Allow user to select a film from the search results
|
43
|
+
def user_select(movie_list)
|
44
|
+
print "Enter the number of the film you want: "
|
45
|
+
num = gets.to_i
|
46
|
+
movie_sought = movie_list["movies"][num]
|
47
|
+
end
|
48
|
+
|
49
|
+
# RUN FUNCTIONS IN IDENTIFY_MOVIE #
|
50
|
+
movie_list = search(title) #List of movies that match the search
|
51
|
+
total_num = movie_list["total"] #Total number of search results
|
52
|
+
puts "Which of these #{total_num} films did you mean?" #Ask user to identify the film they want to examine
|
53
|
+
search_output(movie_list)
|
54
|
+
user_select(movie_list)
|
55
|
+
end
|
56
|
+
|
57
|
+
def rt(id, score_only)
|
58
|
+
|
59
|
+
def get_movie(id)
|
60
|
+
url = "http://api.rottentomatoes.com/api/public/v1.0/movies/#{id}.json?apikey=hv4pzbs4n46nmv7s9w87nzwu"
|
61
|
+
buffer = open(url).read
|
62
|
+
# convert JSON data into a hash
|
63
|
+
result = JSON.parse(buffer)
|
64
|
+
return result
|
65
|
+
end
|
66
|
+
|
67
|
+
# Pull up reviewers list
|
68
|
+
|
69
|
+
def get_all_critics(id, score_only)
|
70
|
+
if score_only #if score_only, just take all critics
|
71
|
+
url = "http://api.rottentomatoes.com/api/public/v1.0/movies/#{id}/reviews.json?review_type=all&page_limit=30&page=1&country=us&apikey=hv4pzbs4n46nmv7s9w87nzwu"
|
72
|
+
else
|
73
|
+
print "All critics, or just top critics? (all/top): "
|
74
|
+
type = gets.chomp!
|
75
|
+
if type == "top"
|
76
|
+
url = "http://api.rottentomatoes.com/api/public/v1.0/movies/#{id}/reviews.json?review_type=top_critic&country=us&apikey=hv4pzbs4n46nmv7s9w87nzwu"
|
77
|
+
elsif
|
78
|
+
url = "http://api.rottentomatoes.com/api/public/v1.0/movies/#{id}/reviews.json?review_type=all&page_limit=30&page=1&country=us&apikey=hv4pzbs4n46nmv7s9w87nzwu"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
buffer = open(url).read
|
82
|
+
# convert JSON data into a hash
|
83
|
+
result = JSON.parse(buffer)
|
84
|
+
return result
|
85
|
+
end
|
86
|
+
|
87
|
+
#Form the list of critics, let users exclude critics
|
88
|
+
def filter_critics(movie_critics)
|
89
|
+
#Print out list of critics that have numerical reviews
|
90
|
+
count = 0
|
91
|
+
movie_critics["reviews"].each do |a|
|
92
|
+
if a["original_score"]
|
93
|
+
puts "#{count}) Critic: #{a["critic"]}"
|
94
|
+
end
|
95
|
+
count += 1
|
96
|
+
end
|
97
|
+
|
98
|
+
print "Which critics to exclude? (identify critic by number; put spaces between numbers; type \"n\" if none):"
|
99
|
+
temp = gets
|
100
|
+
unless temp == "n\n"
|
101
|
+
critic_num_to_exclude = temp.split(' ')
|
102
|
+
critic_num_to_exclude.collect!{|i| i.to_i } #convert array values to numbers
|
103
|
+
|
104
|
+
critic_to_exclude = []
|
105
|
+
|
106
|
+
critic_num_to_exclude.each do |n| #form an array of excluded critics reviews
|
107
|
+
critic_to_exclude << movie_critics["reviews"][n]
|
108
|
+
end
|
109
|
+
|
110
|
+
critic_to_exclude.each do |c| #delete excluded critics reviews from main array of review
|
111
|
+
movie_critics["reviews"].delete(c)
|
112
|
+
end
|
113
|
+
|
114
|
+
critics_list = critic_to_exclude.collect {|c| c["critic"]}
|
115
|
+
print "Excluded critics: #{critics_list} \n"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
#Converts critic ratings, e.g. "A", "5/5", "78/100", to a 100 point scale
|
120
|
+
def score_convert(n)
|
121
|
+
score = 0
|
122
|
+
if n.length <= 2 #if the score is in "A", "A+", "C-" form
|
123
|
+
case n[0] #to account for the first letter
|
124
|
+
when "A"
|
125
|
+
score = 95
|
126
|
+
when "B"
|
127
|
+
score = 85
|
128
|
+
when "C"
|
129
|
+
score = 75
|
130
|
+
when "D"
|
131
|
+
score = 65
|
132
|
+
else
|
133
|
+
score = 50
|
134
|
+
end
|
135
|
+
|
136
|
+
case n[1] #to account for + and -
|
137
|
+
when "+"
|
138
|
+
score += 3
|
139
|
+
when "-"
|
140
|
+
score -=3
|
141
|
+
end
|
142
|
+
end
|
143
|
+
if n.include? "/" #if the score is in X/Y form
|
144
|
+
score = (frac_to_float(n)*100).to_i
|
145
|
+
end
|
146
|
+
score
|
147
|
+
end
|
148
|
+
|
149
|
+
def display_final_stats(movie_critics, score_only)
|
150
|
+
sum = 0
|
151
|
+
count = 0
|
152
|
+
movie_critics["reviews"].each_with_index do |a, index|
|
153
|
+
if a["original_score"]
|
154
|
+
unless score_only
|
155
|
+
puts "#{index}) "
|
156
|
+
puts "Critic: #{a["critic"]}"
|
157
|
+
puts "Original Score: #{a["original_score"]}"
|
158
|
+
end
|
159
|
+
|
160
|
+
converted_score = score_convert(a["original_score"])
|
161
|
+
puts "Converted Score: #{converted_score}" unless score_only
|
162
|
+
sum += converted_score
|
163
|
+
|
164
|
+
unless score_only
|
165
|
+
puts "Quote: #{a["quote"]}"
|
166
|
+
print "\n"
|
167
|
+
end
|
168
|
+
count += 1
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
#Calculates average converted score, for all RT critics
|
173
|
+
avg_converted_score = ((sum.to_f)/count)
|
174
|
+
print "\n"
|
175
|
+
printf("Rotten tomatoes: %.2f", "#{avg_converted_score}")
|
176
|
+
print "\n"
|
177
|
+
return avg_converted_score
|
178
|
+
end
|
179
|
+
|
180
|
+
# RUN FUNCTIONS #
|
181
|
+
movie_found = get_movie(id) #movie_found is a hash that has the basic movie info
|
182
|
+
movie_critics = get_all_critics(id, score_only)
|
183
|
+
filter_critics(movie_critics) unless score_only
|
184
|
+
show_movie_details_score = display_final_stats(movie_critics, score_only)
|
185
|
+
end
|
186
|
+
|
187
|
+
def imdb(title) #returns the movie that the user selected
|
188
|
+
|
189
|
+
def get_movie(title)
|
190
|
+
url = "http://www.imdbapi.com/?i=&t=#{title}"
|
191
|
+
buffer = open(url).read
|
192
|
+
|
193
|
+
# convert JSON data into a hash
|
194
|
+
result = JSON.parse(buffer)
|
195
|
+
return result
|
196
|
+
end
|
197
|
+
|
198
|
+
movie_found = get_movie(title) #movie_found is a hash that has the basic movie info
|
199
|
+
|
200
|
+
#Print out basic info (not individual critics reviews)
|
201
|
+
print "IMDB Rating: ", movie_found["Rating"], "\n\n"
|
202
|
+
print "Title: ", movie_found["Title"], "\n"
|
203
|
+
print "Year: ", movie_found["Year"], "\n"
|
204
|
+
print "Runtime: ", movie_found["Runtime"], "\n"
|
205
|
+
print "\n"
|
206
|
+
return (movie_found["Rating"].to_f)*10
|
207
|
+
end
|
208
|
+
|
209
|
+
def metacritic(title)
|
210
|
+
#insert metacritic scraping here
|
211
|
+
movie = Nokogiri::HTML(open("http://www.metacritic.com/movie/#{title}"))
|
212
|
+
rating = movie.at_css(".score_value").text
|
213
|
+
print "Metacritic: ", rating, "\n"
|
214
|
+
return rating
|
215
|
+
end
|
216
|
+
|
217
|
+
def in_theaters
|
218
|
+
url = "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?page_limit=25&page=1&country=us&apikey=hv4pzbs4n46nmv7s9w87nzwu"
|
219
|
+
buffer = open(url).read
|
220
|
+
|
221
|
+
# convert JSON data into a hash
|
222
|
+
result = JSON.parse(buffer)
|
223
|
+
movies = result["movies"]
|
224
|
+
movies.sort! {|x, y| x["ratings"]["critics_score"] <=> y["ratings"]["critics_score"]}
|
225
|
+
movies.reverse!
|
226
|
+
|
227
|
+
puts "Current Releases"
|
228
|
+
|
229
|
+
print "Score", " "*2, "Title", "\n"
|
230
|
+
movies.each do |h|
|
231
|
+
score = h["ratings"]["critics_score"]
|
232
|
+
print score
|
233
|
+
if score.to_s.length == 1
|
234
|
+
print " "*6
|
235
|
+
else
|
236
|
+
print " "*5
|
237
|
+
end
|
238
|
+
puts h["title"]
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
temp = in_theaters
|
243
|
+
|
244
|
+
#Ask user to enter a title
|
245
|
+
print "Movie title (search entire Rotten Tomatoes database): "
|
246
|
+
title = gets #take in movie title from command line
|
247
|
+
title.chomp!.gsub!(' ', '+') # sub spaces for plus signs
|
248
|
+
|
249
|
+
#Find the movie, based on the user's input
|
250
|
+
movie = identify_movie(title)
|
251
|
+
|
252
|
+
#Reformat the title, so IMDB and MC will recognize it
|
253
|
+
title_for_imdb = movie["title"].downcase.gsub(" ", "+")
|
254
|
+
title_for_mc = movie["title"].downcase.gsub(" ", "-")
|
255
|
+
|
256
|
+
#Use ID to find the movie in RT
|
257
|
+
id = movie["id"]
|
258
|
+
|
259
|
+
#Let user jump straight to meta-metascore and skip everything else
|
260
|
+
|
261
|
+
print "Skip straight to the meta-metascore? (y/n)"
|
262
|
+
if gets.chomp! == "y"
|
263
|
+
score_only = true
|
264
|
+
end
|
265
|
+
|
266
|
+
#Run the 3 main functions for RT, IMDB, and MC
|
267
|
+
rt_score = rt(id, score_only)
|
268
|
+
mc_score = metacritic(title_for_mc).to_i
|
269
|
+
imdb_score = imdb(title_for_imdb)
|
270
|
+
|
271
|
+
#Let users define weights
|
272
|
+
if score_only
|
273
|
+
meta_meta_score = (rt_score + mc_score + imdb_score)/3.0
|
274
|
+
else
|
275
|
+
print "How much weight to Rotten Tomatoes? (0-1): "
|
276
|
+
rt_weight = gets.to_f
|
277
|
+
printf("How much weight to metacritic? (0 - %.2f): ", (1-rt_weight))
|
278
|
+
mc_weight = gets.to_f
|
279
|
+
imdb_weight = 1-(rt_weight+mc_weight)
|
280
|
+
printf("Weight to imdb is %.2f", imdb_weight)
|
281
|
+
print "\n"
|
282
|
+
#Calculate and display the meta-metascore
|
283
|
+
meta_meta_score = rt_score*rt_weight + imdb_score*imdb_weight + mc_score*mc_weight
|
284
|
+
end
|
285
|
+
printf("Meta-metascore: %.2f", meta_meta_score)
|
286
|
+
print "\n\n"
|
data/lib/mmc.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
#Empty file
|
data/mmc.gemspec
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'mmc'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2011-10-22'
|
5
|
+
s.summary = "Meta metacritic"
|
6
|
+
s.description = "Calculates a 'meta metascore' for a given movie by averaging its scores from rotten tomatoes, metacritic, and imdb."
|
7
|
+
s.authors = ["Jimmy Li"]
|
8
|
+
s.email = 'jyl702@gmail.com'
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.executables = ['mmc']
|
11
|
+
s.homepage =
|
12
|
+
'http://rubygems.org/gems/mmc'
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mmc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jimmy Li
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-22 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: Calculates a 'meta metascore' for a given movie by averaging its scores
|
15
|
+
from rotten tomatoes, metacritic, and imdb.
|
16
|
+
email: jyl702@gmail.com
|
17
|
+
executables:
|
18
|
+
- mmc
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- bin/mmc
|
25
|
+
- lib/mmc.rb
|
26
|
+
- mmc.gemspec
|
27
|
+
homepage: http://rubygems.org/gems/mmc
|
28
|
+
licenses: []
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options: []
|
31
|
+
require_paths:
|
32
|
+
- lib
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 1.8.5
|
48
|
+
signing_key:
|
49
|
+
specification_version: 3
|
50
|
+
summary: Meta metacritic
|
51
|
+
test_files: []
|