| Class | Item |
| In: |
app/models/item.rb
|
| Parent: | ActiveRecord::Base |
| agree | [RW] |
# File app/models/item.rb, line 199
199: def by_win_percent(conditions)
200: all({ :order => '(items_questions.wins/items_questions.ratings) desc',
201: :group => 'items.id',
202: :joins => 'INNER JOIN items_questions ON items_questions.item_id=items.id'
203: }.merge(conditions))
204: end
# File app/models/item.rb, line 129
129: def for_question(question, country_code, reject_under = REJECT_WITH_RATINGS_UNDER)
130: not_by_country = country_code.to_s.empty?
131: ratings = {}
132: wins = {}
133: percents = {}
134: if not_by_country
135: ratings = ratings_overall(question)
136: wins = wins_overall(question)
137: percents = wins.keys.inject({}) do |hash, key|
138: rating = ratings[key]
139: hash[key] = rating > 0 ? 100.0 * wins[key] / rating : 0
140: hash
141: end
142: else
143: group = Group.first(:conditions => "groups.code LIKE '#{country_code}'")
144: result = ActiveRecord::Base.connection.execute(
145: "SELECT item_id, ratings, wins, losses FROM stats WHERE question_id=#{question.id} AND group_id=#{group.id};"
146: )
147: stat = result.fetch_hash
148: begin
149: item_id = stat['item_id'].to_i
150: ratings[item_id] = stat['ratings'].to_i
151: wins[item_id] = win = stat['wins'].to_i
152: percents[item_id] = [win, stat['losses'].to_i].to_percent
153: stat = result.fetch_hash
154: end while !stat.nil?
155: result.free
156: end
157: pos = 0
158: ranks = percents.sort_by do |percent|
159: [-percent.last, -wins[percent.first]]
160: end
161: ranks = ranks.inject({}) do |hash, percent|
162: hash[percent.first] = pos += 1
163: hash
164: end
165: [wins, ratings, percents, ranks]
166: end
# File app/models/item.rb, line 184
184: def new_remote(item, attachment, questions, visit_id)
185: ext_id = Pairwise.item(item.description || DEFAULT_ITEM_NAME, questions)
186: item.item_id_ext = ext_id.first
187: item.visit_id = visit_id
188: attachment.save
189: item.attachment_id = attachment.id
190: item.save
191: item.questions << questions.map { |q| Question.find_by_question_id_ext(q) }
192: item
193: end
# File app/models/item.rb, line 125
125: def page_find(page = 1)
126: paginate(:page => page || 1, :include => [:flags, :questions], :order => "items.created_at desc, flags.active desc")
127: end
# File app/models/item.rb, line 306
306: def pairwise_rank(question)
307: Pairwise.list(:item, question.question_id_ext, RANK_ALGO_ID)
308: end
# File app/models/item.rb, line 213
213: def ratings_for_country(question, country = nil, with_skips = false)
214: joins = "INNER JOIN prompts ON (prompts.id=responses.prompt_id AND prompts.question_id=#{question.id}) INNER JOIN items_prompts ON (items_prompts.prompt_id=prompts.id)"
215: joins = "INNER JOIN items_responses ON items_responses.response_id=responses.id #{joins}" unless with_skips
216: conditions = { 'responses.active''responses.active' => true }
217: conditions.merge!('responses.ip_country_code''responses.ip_country_code' => country) if country
218: ratings = question.item_ids.inject({}) do |hash, id|
219: hash[id] = 0
220: hash
221: end
222: for response in Response.all({
223: :select => "COUNT(*) AS ratings, items_prompts.item_id AS id",
224: :conditions => conditions,
225: :joins => joins,
226: :group => 'items_prompts.item_id'
227: }) do
228: ratings[response.id.to_i] = response.ratings.to_i
229: end
230: ratings
231: end
232:
233: def wins_overall(question)
234: ItemsQuestion.all(:conditions => { :question_id => question.id, :item_id => question.item_ids }, :select => 'item_id, wins').inject({}) do |hash, el|
235: hash[el.item_id] = el.wins || 0
236: hash
237: end
238: end
239:
240: def wins_for_country(question, country = nil)
241: joins = "INNER JOIN items_responses ON (items_responses.response_id=responses.id) INNER JOIN prompts ON (responses.prompt_id=prompts.id AND prompts.question_id=#{question.id})"
242: conditions = {
243: 'items_responses.item_id''items_responses.item_id' => question.item_ids,
244: 'responses.active''responses.active' => true
245: }
246: conditions.merge!('responses.ip_country_code''responses.ip_country_code' => country) if country
247: wins = question.item_ids.inject({}) do |hash, id|
248: hash[id] = 0
249: hash
250: end
251: for response in Response.all({
252: :select => "COUNT(*) AS wins, items_responses.item_id AS id",
253: :conditions => conditions,
254: :joins => joins,
255: :group => 'items_responses.item_id'
256: }) do
257: wins[response.id.to_i] = response.wins.to_i
258: wins
259: end
260: wins
261: end
262:
263: def win_percents_overall_array(question_id, item_ids)
264: ItemsQuestion.all(
265: :conditions => { :question_id => question_id, :item_id => item_ids },
266: :select => '(100*CONVERT(wins, DECIMAL(13,10))/(wins + losses)) AS win_percent',
267: :order => 'item_id'
268: ).map { |el| el.win_percent.to_f || 0 }
269: end
270:
271: def win_percents_overall(question_id, item_ids)
272: ItemsQuestion.all(
273: :conditions => { :question_id => question_id, :item_id => item_ids },
274: :select => 'item_id, (100*CONVERT(wins, DECIMAL(13,10))/(wins + losses)) AS win_percent'
275: ).inject({}) do |hash, el|
276: hash[el.item_id.to_i] = el.win_percent.to_f || 0
277: hash
278: end
279: end
280:
281: # def win_percents_for_country(question, country)
282: # wins = wins_for_country(question)
283: # ratings = ratings_for_country(question)
284: # question.items.inject({}) do |hash, item|
285: # rating = ratings[item.id]
286: # hash[item.id] = rating != 0 ? 100 * (wins[item.id].to_f / rating) : 0
287: # hash
288: # end
289: # end
290: #
291: # # in tests batching further than this causes inefficient joins
292: # def win_percents_for_countries(question_id, items, countries, overall = false)
293: # percents = items.to_a.inject({}) do |hash, item|
294: # hash[item] = countries.map { |country| item.win_percent_for_country(country, question_id) }
295: # hash
296: # end
297: # if overall
298: # overall = win_percents_overall(question_id, items)
299: # percents.each { |key, value| percents[key] = value.unshift(overall[key.id]) }
300: # else
301: # percents
302: # end
303: # end
304:
305: private
306: def pairwise_rank(question)
307: Pairwise.list(:item, question.question_id_ext, RANK_ALGO_ID)
308: end
309: end
310:
311: private
312: def update_item_state(state)
313: update_attribute(:active, state)
314: Pairwise.update_item_state(item_id_ext, state)
315: end
316: end
# File app/models/item.rb, line 206
206: def ratings_overall(question)
207: ItemsQuestion.all(:conditions => { :question_id => question.id, :item_id => question.item_ids }, :select => 'item_id, (wins + losses) as ratings').inject({}) do |hash, el|
208: hash[el.item_id] = el.ratings || 0
209: hash
210: end
211: end
if nil position or unaccounted response, refresh from pairwise
# File app/models/item.rb, line 169
169: def refresh_rank(question)
170: if refresh_rank?(question.id)
171: ids_ext_to_rank = (pairwise_rank(question) || return).to_hash
172: ItemsQuestion.all(:conditions => { 'items_questions.question_id' => question.id, 'items.item_id_ext' => ids_ext_to_rank.keys, 'items.active' => true }, :include => :item).each do |iq|
173: iq.update_attribute(:position, ids_ext_to_rank[iq.item.item_id_ext.to_i])
174: end if ids_ext_to_rank.keys.length > 0
175: Response.update_last_response(LAST_RANK_RESPONSE, question.id)
176: end
177: end
# File app/models/item.rb, line 195
195: def refresh_rank?(question_id)
196: count(:conditions => { :active => true }, :joins => "INNER JOIN items_questions ON (question_id=#{question_id.to_i} AND item_id=items.id AND position IS NULL)") > Constants::Responses::UntilRank::ITEMS || Response.refresh_response?(LAST_RANK_RESPONSE, question_id)
197: end
# File app/models/item.rb, line 312
312: def update_item_state(state)
313: update_attribute(:active, state)
314: Pairwise.update_item_state(item_id_ext, state)
315: end
# File app/models/item.rb, line 179
179: def valid_objects(item, attachment, questions)
180: # so validation is always run on item and attachment
181: (item.valid? || attachment.valid?) && item.valid? && attachment.valid? && !questions.empty?
182: end
# File app/models/item.rb, line 271
271: def win_percents_overall(question_id, item_ids)
272: ItemsQuestion.all(
273: :conditions => { :question_id => question_id, :item_id => item_ids },
274: :select => 'item_id, (100*CONVERT(wins, DECIMAL(13,10))/(wins + losses)) AS win_percent'
275: ).inject({}) do |hash, el|
276: hash[el.item_id.to_i] = el.win_percent.to_f || 0
277: hash
278: end
279: end
# File app/models/item.rb, line 263
263: def win_percents_overall_array(question_id, item_ids)
264: ItemsQuestion.all(
265: :conditions => { :question_id => question_id, :item_id => item_ids },
266: :select => '(100*CONVERT(wins, DECIMAL(13,10))/(wins + losses)) AS win_percent',
267: :order => 'item_id'
268: ).map { |el| el.win_percent.to_f || 0 }
269: end
# File app/models/item.rb, line 240
240: def wins_for_country(question, country = nil)
241: joins = "INNER JOIN items_responses ON (items_responses.response_id=responses.id) INNER JOIN prompts ON (responses.prompt_id=prompts.id AND prompts.question_id=#{question.id})"
242: conditions = {
243: 'items_responses.item_id''items_responses.item_id' => question.item_ids,
244: 'responses.active''responses.active' => true
245: }
246: conditions.merge!('responses.ip_country_code''responses.ip_country_code' => country) if country
247: wins = question.item_ids.inject({}) do |hash, id|
248: hash[id] = 0
249: hash
250: end
251: for response in Response.all({
252: :select => "COUNT(*) AS wins, items_responses.item_id AS id",
253: :conditions => conditions,
254: :joins => joins,
255: :group => 'items_responses.item_id'
256: }) do
257: wins[response.id.to_i] = response.wins.to_i
258: wins
259: end
260: wins
261: end
262:
263: def win_percents_overall_array(question_id, item_ids)
264: ItemsQuestion.all(
265: :conditions => { :question_id => question_id, :item_id => item_ids },
266: :select => '(100*CONVERT(wins, DECIMAL(13,10))/(wins + losses)) AS win_percent',
267: :order => 'item_id'
268: ).map { |el| el.win_percent.to_f || 0 }
269: end
270:
271: def win_percents_overall(question_id, item_ids)
272: ItemsQuestion.all(
273: :conditions => { :question_id => question_id, :item_id => item_ids },
274: :select => 'item_id, (100*CONVERT(wins, DECIMAL(13,10))/(wins + losses)) AS win_percent'
275: ).inject({}) do |hash, el|
276: hash[el.item_id.to_i] = el.win_percent.to_f || 0
277: hash
278: end
279: end
280:
281: # def win_percents_for_country(question, country)
282: # wins = wins_for_country(question)
283: # ratings = ratings_for_country(question)
284: # question.items.inject({}) do |hash, item|
285: # rating = ratings[item.id]
286: # hash[item.id] = rating != 0 ? 100 * (wins[item.id].to_f / rating) : 0
287: # hash
288: # end
289: # end
290: #
291: # # in tests batching further than this causes inefficient joins
292: # def win_percents_for_countries(question_id, items, countries, overall = false)
293: # percents = items.to_a.inject({}) do |hash, item|
294: # hash[item] = countries.map { |country| item.win_percent_for_country(country, question_id) }
295: # hash
296: # end
297: # if overall
298: # overall = win_percents_overall(question_id, items)
299: # percents.each { |key, value| percents[key] = value.unshift(overall[key.id]) }
300: # else
301: # percents
302: # end
303: # end
304:
305: private
306: def pairwise_rank(question)
307: Pairwise.list(:item, question.question_id_ext, RANK_ALGO_ID)
308: end
309: end
# File app/models/item.rb, line 233
233: def wins_overall(question)
234: ItemsQuestion.all(:conditions => { :question_id => question.id, :item_id => question.item_ids }, :select => 'item_id, wins').inject({}) do |hash, el|
235: hash[el.item_id] = el.wins || 0
236: hash
237: end
238: end
# File app/models/item.rb, line 93
93: def activate
94: # only allow activation of items with attachments
95: update_item_state(true) unless self.attachment.nil?
96: end
# File app/models/item.rb, line 98
98: def plot(for_questions = nil)
99: # groups = Group.all(:select => 'code, name')
100: # countries = groups.map(&:code)
101: # country_names = groups.map(&:name)
102: # (for_questions || questions).each do |question|
103: # graph = Scruffy::Graph.new
104: # graph.title = question.name.strip_tags
105: # graph.renderer = Scruffy::Renderers::Standard.new
106: # percents = countries.map { |country| win_percent_for_country(country, question.id).to_i }
107: # percents.unshift(win_percent(question.id))
108: # graph.add :bar, 'percent wins', percents
109: # graph.render(
110: # :min_value => 0,
111: # :max_value => 100,
112: # :size => [520, 300],
113: # :to => "#{Constants::Config::Paths::PLOTS}question_#{question.id}_item_#{id}.png",
114: # :as => 'png',
115: # :point_markers => ['', 'All', '', 'China', '', 'Japan', '', 'US', '']
116: # )
117: # end
118: end
# File app/models/item.rb, line 84
84: def position(question_id = nil)
85: (question_id.nil? ? items_questions : items_questions.find_all_by_question_id(question_id)).avg(:position)
86: end
# File app/models/item.rb, line 29
29: def ratings(question_id, with_skips = false, joins = nil, conditions = {})
30: if with_skips && joins.nil? && conditions.empty?
31: items_questions.find_by_question_id(question_id).ratings
32: elsif joins.nil? && conditions.empty?
33: iq = items_questions.find_by_question_id(question_id)
34: iq.wins + iq.losses
35: else
36: joins = "INNER JOIN prompts ON prompts.id=responses.prompt_id INNER JOIN items_prompts ON (items_prompts.prompt_id=prompts.id AND items_prompts.item_id=#{id}) #{joins}"
37: joins = "INNER JOIN items_responses ON items_responses.response_id=responses.id #{joins}" unless with_skips
38: Response.count(:joins => joins, :conditions => {
39: 'prompts.question_id''prompts.question_id' => question_id,
40: 'responses.active''responses.active' => true
41: }.merge(conditions))
42: end
43: end
# File app/models/item.rb, line 45
45: def ratings_for_country(country_code, question_id, with_skips = true)
46: ratings(question_id, with_skips, nil, { 'responses.ip_country_code' => country_code })
47: end
# File app/models/item.rb, line 88
88: def suspend
89: update_item_state(false)
90: Prompt.update_all("active=0", "prompts.active=1 AND prompts.id IN (#{self.prompt_ids.join(',')})")
91: end
# File app/models/item.rb, line 62
62: def win_percent(question_id = nil, with_skips = false, joins = nil, conditions = {})
63: if question_id
64: if joins.nil? && conditions.empty?
65: if with_skips
66: items_questions.first(:conditions => { :question_id => question_id }, :select => '100*(wins/ratings) AS win_percent').win_percent.to_f
67: else
68: items_questions.first(:conditions => { :question_id => question_id }, :select => '100*(wins/(wins+losses)) AS win_percent').win_percent.to_f
69: end
70: else
71: ratings = ratings(question_id, with_skips, joins, conditions)
72: ratings.zero? ? 0 : 100 * (wins(question_id, joins, conditions) / ratings.to_f)
73: end
74: else
75: # for all questions
76: questions.map { |q| win_percent(q.id, with_skips, joins) }.avg
77: end
78: end
# File app/models/item.rb, line 80
80: def win_percent_for_country(country_code, question_id = nil, with_skips = false)
81: win_percent(question_id, with_skips, nil, { 'responses.ip_country_code' => country_code })
82: end
# File app/models/item.rb, line 53
53: def wins(question_id, joins = nil, conditions = {})
54: if joins.nil? && conditions.empty?
55: items_questions.find_by_question_id(question_id).wins
56: else
57: joins = "INNER JOIN items_responses ON (items_responses.response_id=responses.id AND items_responses.item_id=#{id}) INNER JOIN prompts ON (responses.prompt_id=prompts.id AND prompts.question_id=#{question_id}) #{joins}"
58: Response.count(:joins => joins, :conditions => { 'responses.active''responses.active' => true }.merge(conditions))
59: end
60: end