Class: Turkee::TurkeeTask

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
lib/models/turkee_task.rb

Constant Summary collapse

HIT_FRAMEHEIGHT =
1000

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.clear_all_turks(force = false) ⇒ Object

DON’T PUSH THIS BUTTON UNLESS YOU MEAN IT. :)



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
# File 'lib/models/turkee_task.rb', line 101

def self.clear_all_turks(force = false)
  # Do NOT execute this function if we're in production mode
  raise "You can only clear turks in the sandbox/development environment unless you pass 'true' for the force flag." if Rails.env == 'production' && !force

  hits = RTurk::Hit.all

  logger.info "#{hits.size} reviewable hits. \n"

  unless hits.empty?
    logger.info "Approving all assignments and disposing of each hit."

    hits.each do |hit|
      begin
        hit.expire!
        hit.assignments.each do |assignment|
          logger.info "Assignment status : #{assignment.status}"
          assignment.approve!('__clear_all_turks__approved__') if assignment.status == 'Submitted'
        end

        turkee_task = TurkeeTask.where(hit_id: hit.id).first
        turkee_task.complete_task if turkee_task.present?

        hit.dispose!
      rescue Exception => e
        # Probably a service unavailable
        logger.error "Exception : #{e.to_s}"
      end
    end
  end

end

.create_hit(host, hit_title, hit_description, typ, num_assignments, reward, lifetime, duration = nil, qualifications = {}, params = {}, opts = {}) ⇒ Object

Creates a new Mechanical Turk task on AMZN with the given title, desc, etc



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
# File 'lib/models/turkee_task.rb', line 68

def self.create_hit(host, hit_title, hit_description, typ, num_assignments, reward, lifetime,
                    duration = nil, qualifications = {}, params = {}, opts = {})
  model = typ.to_s.constantize
  f_url = build_url(host, model, params, opts)

  h = RTurk::Hit.create(:title => hit_title) do |hit|
    hit.max_assignments = num_assignments if hit.respond_to?(:max_assignments)
    hit.assignments = num_assignments if hit.respond_to?(:assignments)

    hit.description = hit_description
    hit.reward = reward
    hit.lifetime = lifetime.to_i.days.seconds.to_i
    hit.duration = duration.to_i.hours.seconds.to_i if duration
    hit.question(f_url, :frame_height => HIT_FRAMEHEIGHT)
    unless qualifications.empty?
      qualifications.each do |key, value|
        hit.qualifications.add key, value
      end
    end
  end

  TurkeeTask.create(:sandbox => RTurk.sandbox?,
                    :hit_title => hit_title, :hit_description => hit_description,
                    :hit_reward => reward.to_f, :hit_num_assignments => num_assignments.to_i,
                    :hit_lifetime => lifetime, :hit_duration => duration,
                    :form_url => f_url, :hit_url => h.url,
                    :hit_id => h.id, :task_type => typ,
                    :complete => false)

end

.process_hits(turkee_task = nil) ⇒ Object

Use this method to go out and retrieve the data for all of the posted Turk Tasks.

Each specific TurkeeTask object (determined by task_type field) is in charge of
accepting/rejecting the assignment and importing the data into their respective tables.


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
# File 'lib/models/turkee_task.rb', line 22

def self.process_hits(turkee_task = nil)

  begin
    # Using a lockfile to prevent multiple calls to Amazon.
    Lockfile.new('/tmp/turk_processor.lock', :max_age => 3600, :retries => 10) do

      turks = task_items(turkee_task)

      turks.each do |turk|
        hit = RTurk::Hit.new(turk.hit_id)

        callback_models = Set.new
        hit.assignments.each do |assignment|
          next unless (assignment.status)
          next if assignment_exists?(assignment)

          model, param_hash = map_imported_values(assignment, turk.task_type)
          next if model.nil?

          callback_models << model

          result = save_imported_values(model, param_hash)

          # If there's a custom approve? method, see if we should approve the submitted assignment
          #  otherwise just approve it by default
          turk.process_result(assignment, result)

          TurkeeImportedAssignment.record_imported_assignment(assignment, result, turk)
        end

        turk.set_expired?(callback_models) if !turk.set_complete?(hit, callback_models)
      end
    end
  rescue Lockfile::MaxTriesLockError => e
    logger.info "TurkTask.process_hits is already running or the lockfile /tmp/turk_processor.lock exists from an improperly shutdown previous process. Exiting method call."
  end

end

.save_imported_values(model, param_hash) ⇒ Object



61
62
63
64
65
# File 'lib/models/turkee_task.rb', line 61

def self.save_imported_values(model, param_hash)
  key = model.to_s.underscore.gsub('/','_') # Namespaced model will come across as turkee/turkee_study,
                                            #  we must translate to turkee_turkee_study"
  model.create(param_hash[key])
end

Instance Method Details

#complete_taskObject



133
134
135
136
# File 'lib/models/turkee_task.rb', line 133

def complete_task
  self.complete = true
  save!
end

#increment_complete_assignmentsObject



175
176
177
178
179
180
# File 'lib/models/turkee_task.rb', line 175

def increment_complete_assignments
  raise "Missing :completed_assignments attribute. Please upgrade Turkee to the most recent version." unless respond_to?(:completed_assignments)

  self.completed_assignments += 1
  save
end

#initiate_callback(method, models) ⇒ Object



157
158
159
# File 'lib/models/turkee_task.rb', line 157

def initiate_callback(method, models)
  models.each { |model| model.send(method, self) if model.respond_to?(method) }
end

#process_result(assignment, result) ⇒ Object



161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/models/turkee_task.rb', line 161

def process_result(assignment, result)
  if result.errors.size > 0
    logger.info "Errors : #{result.inspect}"
    assignment.reject!('Failed to enter proper data.')
  elsif result.respond_to?(:approve?)
    logger.debug "Approving : #{result.inspect}"
    self.increment_complete_assignments
    result.approve? ? assignment.approve!('') : assignment.reject!('Rejected criteria.')
  else
    self.increment_complete_assignments
    assignment.approve!('')
  end
end

#set_complete?(hit, models) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
141
142
143
144
145
146
147
# File 'lib/models/turkee_task.rb', line 138

def set_complete?(hit, models)
  if completed_assignments?
    hit.dispose!
    complete_task
    initiate_callback(:hit_complete, models)
    return true
  end

  false
end

#set_expired?(models) ⇒ Boolean

Returns:

  • (Boolean)


149
150
151
152
153
154
155
# File 'lib/models/turkee_task.rb', line 149

def set_expired?(models)
  if expired?
    self.expired = true
    save!
    initiate_callback(:hit_expired, models)
  end
end