choice.rb
6.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
class Choice < ActiveRecord::Base
acts_as_versioned :if_changed => [:data, :creator_id, :question_id, :active]
belongs_to :question, :counter_cache => true
belongs_to :creator, :class_name => "Visitor", :foreign_key => "creator_id"
validates_presence_of :creator, :on => :create, :message => "can't be blank"
validates_presence_of :question, :on => :create, :message => "can't be blank"
validates_presence_of :data
#validates_length_of :item, :maximum => 140
has_many :votes
has_many :losing_votes, :class_name => "Vote", :foreign_key => "loser_choice_id"
has_many :flags
has_many :prompts_on_the_left, :class_name => "Prompt", :foreign_key => "left_choice_id"
has_many :prompts_on_the_right, :class_name => "Prompt", :foreign_key => "right_choice_id"
has_many :appearances_on_the_left, :through => :prompts_on_the_left, :source => :appearances
has_many :appearances_on_the_right, :through => :prompts_on_the_right, :source => :appearances
has_many :skips_on_the_left, :through => :prompts_on_the_left, :source => :skips
has_many :skips_on_the_right, :through => :prompts_on_the_right, :source => :skips
named_scope :active, :conditions => { :active => true }
named_scope :inactive, :conditions => { :active => false}
named_scope :inactive_ignore_flagged, :include => :flags, :conditions => {:active => false, :flags => {:id => nil}}
named_scope :reproved, :joins => :flags
named_scope :not_created_by, lambda { |creator_id|
{ :conditions => ["creator_id <> ?", creator_id] }
}
after_save :update_questions_counter
after_save :update_prompt_queue
attr_protected :prompts_count, :wins, :losses, :score, :prompts_on_the_right_count, :prompts_on_the_left_count
attr_readonly :question_id
attr_accessor :part_of_batch_create
def update_questions_counter
unless part_of_batch_create
self.question.update_attribute(:inactive_choices_count, self.question.choices.inactive.length)
end
end
# if changing a choice to active, we want to regenerate prompts
def update_prompt_queue
unless part_of_batch_create
if self.changed.include?('active') && self.active?
self.question.mark_prompt_queue_for_refill
if self.question.choices.size - self.question.inactive_choices_count > 1 && self.question.uses_catchup?
self.question.delay.add_prompt_to_queue
end
end
end
end
def before_create
unless self.score
self.score = 50.0
end
unless self.active?
#puts "this choice was not specifically set to active, so we are now asking if we should auto-activate"
self.active = question.should_autoactivate_ideas? ? true : false
#puts "should question autoactivate? #{question.should_autoactivate_ideas?}"
#puts "will this choice be active? #{self.active}"
end
return true #so active record will save
end
def compute_score
(wins.to_f+1)/(wins+1+losses+1) * 100
end
def compute_score!
self.score = compute_score
#changed to quote tables according the database type (wasn't working in postgres)
Choice.connection.execute("UPDATE #{connection.quote_table_name("choices")}
SET #{connection.quote_column_name("score")} = #{self.score},
#{connection.quote_column_name("updated_at")} = '#{Time.now.utc.to_s(:db)}'
WHERE
#{connection.quote_column_name("id")} = #{self.id}")
end
def user_created
self.creator_id != self.question.creator_id
end
def creator_identifier
self.creator.identifier
end
def compute_bt_score(btprobs = nil)
if btprobs.nil?
btprobs = self.question.bradley_terry_probs
end
p_i = btprobs[self.id]
total = 0
btprobs.each do |id, p_j|
if id == self.id
next
end
total += (p_i / (p_i + p_j))
end
total / (btprobs.size-1)
end
def activate!
(self.active = true)
self.save!
end
def deactivate!
(self.active = false)
self.save!
end
protected
def generate_prompts
#once a choice is added, we need to generate the new prompts (possible combinations of choices)
#do this in a new process (via delayed jobs)? Maybe just for uploaded ideas
previous_choices = (self.question.choices - [self])
return if previous_choices.empty?
inserts = []
timestring = Time.now.utc.to_s(:db) #isn't rails awesome?
#add prompts with this choice on the left
previous_choices.each do |r|
inserts.push("(NULL, #{self.question_id}, NULL, #{self.id}, '#{timestring}', '#{timestring}', NULL, 0, #{r.id}, NULL, NULL)")
end
#add prompts with this choice on the right
previous_choices.each do |l|
inserts.push("(NULL, #{self.question_id}, NULL, #{l.id}, '#{timestring}', '#{timestring}', NULL, 0, #{self.id}, NULL, NULL)")
end
#changed to quote tables according the database type (wasn't working in postgres)
sql = "INSERT INTO #{connection.quote_table_name("prompts")}
(#{connection.quote_column_name("algorithm_id")},
#{connection.quote_column_name("question_id")},
#{connection.quote_column_name("voter_id")},
#{connection.quote_column_name("left_choice_id")},
#{connection.quote_column_name("created_at")},
#{connection.quote_column_name("updated_at")},
#{connection.quote_column_name("tracking")},
#{connection.quote_column_name("votes_count")},
#{connection.quote_column_name("right_choice_id")},
#{connection.quote_column_name("active")},
#{connection.quote_column_name("randomkey")}) VALUES #{inserts.join(', ')}"
Question.update_counters(self.question_id, :prompts_count => 2*previous_choices.size)
ActiveRecord::Base.connection.execute(sql)
#VALUES (NULL, 108, NULL, 1892, '2010-03-16 11:12:37', '2010-03-16 11:12:37', NULL, 0, 1893, NULL, NULL)
# INSERT INTO `prompts` (`algorithm_id`, `question_id`, `voter_id`, `left_choice_id`, `created_at`, `updated_at`, `tracking`, `votes_count`, `right_choice_id`, `active`, `randomkey`) VALUES(NULL, 108, NULL, 1892, '2010-03-16 11:12:37', '2010-03-16 11:12:37', NULL, 0, 1893, NULL, NULL)
#previous_choices.each { |c|
# question.prompts.create!(:left_choice => c, :right_choice => self)
# question.prompts.create!(:left_choice => self, :right_choice => c)
#}
end
end