Class Item
In: app/models/item.rb
Parent: ActiveRecord::Base

Methods

Included Modules

Constants::Item

Attributes

agree  [RW] 

Public Class methods

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # File app/models/item.rb, line 123
123:     def per_page; PER_PAGE end

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

Public Instance methods

[Source]

    # 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

[Source]

     # 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

[Source]

    # 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

[Source]

    # File app/models/item.rb, line 25
25:   def question
26:     questions.first
27:   end

[Source]

    # 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

[Source]

    # 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

[Source]

    # 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

[Source]

    # 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

[Source]

    # 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

[Source]

    # 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

[Source]

    # File app/models/item.rb, line 49
49:   def wins_for_country(country_code, question_id)
50:     wins(question_id, nil, { 'responses.ip_country_code' => country_code })
51:   end

[Validate]