Class: Turkee::TurkeeTask

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

Constant Summary collapse

HIT_FRAMEHEIGHT =

belongs_to :task, :polymorphic => true

1000

Class Method Summary collapse

Class Method Details

.clear_all_turks(force = false) ⇒ Object

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



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
# File 'lib/turkee.rb', line 103

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_reviewable

  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! if (hit.status == "Assignable" || hit.status == 'Unassignable')

        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.find_by_hit_id(hit.id)
        if turkee_task
          turkee_task.complete = true
          turkee_task.save
        end

        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) ⇒ Object

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



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/turkee.rb', line 77

def self.create_hit(host, hit_title, hit_description, typ, num_assignments, reward, lifetime)

  model    = Object::const_get(typ)
  duration = lifetime.to_i
  f_url    = form_url(host, model)

  h = RTurk::Hit.create(:title => hit_title) do |hit|
    hit.assignments = num_assignments
    hit.description = hit_description
    hit.reward      = reward
    hit.lifetime    = duration.days.seconds.to_i
    hit.question(f_url, :frame_height => HIT_FRAMEHEIGHT)
    # hit.qualifications.add :approval_rate, { :gt => 80 }
  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,     :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.


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
# File 'lib/turkee.rb', line 25

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 = turkee_task.nil? ? TurkeeTask.unprocessed_hits : Array.new << turkee_task

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

        hit.assignments.each do |assignment|
          next unless assignment.status == 'Submitted'
          next unless TurkeeImportedAssignment.find_by_assignment_id(assignment.id).nil?

          params     = assignment.answers.map { |k, v| "#{CGI::escape(k)}=#{CGI::escape(v)}" }.join('&')
          param_hash = Rack::Utils.parse_nested_query(params)
          model      = find_model(param_hash)

          next if model.nil?

          result = model.create(param_hash[model.to_s.underscore])

          # If there's a custom approve? method, see if we should approve the submitted assignment
          #  otherwise just approve it by default
          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}"
            result.approve? ? assignment.approve!('') : assignment.reject!('Rejected criteria.')
          else
            assignment.approve!('')
          end

          TurkeeImportedAssignment.create(:assignment_id => assignment.id) rescue nil

        end

        if hit.completed_assignments == turk.hit_num_assignments
          hit.dispose!
          model.hit_complete(turk) if model.respond_to?(:hit_complete)
        end
      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