def qualify(qualification, value, worker): """Assign a qualification to a worker.""" # create connection to AWS from boto.mturk.connection import MTurkConnection config = PsiturkConfig() config.load_config() aws_access_key_id = config.get('AWS Access', 'aws_access_key_id') aws_secret_access_key = config.get('AWS Access', 'aws_secret_access_key') conn = MTurkConnection(aws_access_key_id, aws_secret_access_key) def get_workers_with_qualification(qualification): """Get workers with the given qualification.""" results = [] continue_flag = True page = 1 while(continue_flag): new_results = conn.get_qualifications_for_qualification_type( qualification, page_size=100, page_number=page) if(len(new_results) == 0): continue_flag = False else: results.extend(new_results) page = page + 1 return results results = get_workers_with_qualification(qualification) workers = [x.SubjectId for x in results] # assign the qualification click.echo( "Assigning qualification {} with value {} to worker {}".format( qualification, value, worker)) if worker in workers: result = conn.update_qualification_score(qualification, worker, value) else: result = conn.assign_qualification(qualification, worker, value) if result: click.echo(result) # print out the current set of workers with the qualification results = get_workers_with_qualification(qualification) click.echo("{} workers with qualification {}:".format( len(results), qualification)) values = [r.IntegerValue for r in results] unique_values = list(set([r.IntegerValue for r in results])) for v in unique_values: click.echo("{} with value {}".format( len([val for val in values if val == v]), v))
def qualify(qualification, value, worker): """Assign a qualification to a worker.""" # create connection to AWS from boto.mturk.connection import MTurkConnection config = PsiturkConfig() config.load_config() aws_access_key_id = config.get('AWS Access', 'aws_access_key_id') aws_secret_access_key = config.get('AWS Access', 'aws_secret_access_key') conn = MTurkConnection(aws_access_key_id, aws_secret_access_key) def get_workers_with_qualification(qualification): """Get workers with the given qualification.""" results = [] continue_flag = True page = 1 while(continue_flag): new_results = conn.get_qualifications_for_qualification_type( qualification, page_size=100, page_number=page) if(len(new_results) == 0): continue_flag = False else: results.extend(new_results) page = page + 1 return results results = get_workers_with_qualification(qualification) workers = [x.SubjectId for x in results] # assign the qualification click.echo( "Assigning qualification {} with value {} to worker {}".format( qualification, value, worker)) if worker in workers: result = conn.update_qualification_score(qualification, worker, value) else: result = conn.assign_qualification(qualification, worker, value) if result: click.echo(result) # print out the current set of workers with the qualification results = get_workers_with_qualification(qualification) click.echo("{} workers with qualification {}:".format( len(results), qualification)) values = [r.IntegerValue for r in results] unique_values = list(set([r.IntegerValue for r in results])) for v in unique_values: click.echo("{} with value {}".format( len([val for val in values if val == v]), v))
def AwardHits(): mtc = MTurkConnection(aws_access_key_id=ACCESS_ID, aws_secret_access_key=SECRET_KEY, host=HOST) # this finds our json files, you need to have already downloaded them and put them in a folder path_to_json = '/Users/scotti.5/Dropbox/Shared Lab Folder/Experiments/Contextual_LTM/mTurk Analysis/newData' json_files = [ pos_json for pos_json in os.listdir(path_to_json) if pos_json.endswith('.json') ] # here I define my pandas Dataframe with the columns I want to get from the json jsons_data = pd.DataFrame(columns=['WORKERID', 'Bonus']) # we need both the json and an index number so use enumerate() for index, js in enumerate(json_files): with open(os.path.join(path_to_json, js)) as json_file: json_text = json.load(json_file) subjID = [] cashprize = [] assignmentNum = [] # here you need to know the layout of your json and each json has to have subjID = json_text['WORKERID'] print(subjID) cashprize = json_text['Bonus'] assignmentNum = json_text['ASSIGNMENTID'] # here I push a list of data into a pandas DataFrame at row given by 'index' jsons_data.loc[index] = [subjID, cashprize] subjID = jsons_data.loc[0, 'WORKERID'] cashprize = jsons_data.loc[0, 'Bonus'] # block worker from future HITs mtc.assign_qualification('38XLDN1M8DBWG1FPHU43ZCVTZ4T3DT', subjID) bonusHIT = mtc.grant_bonus( worker_id=subjID, assignment_id=assignmentNum, bonus_price=mtcPrice.Price(amount=cashprize), reason='Bonus awarded based on memory experiment performance') assert (bonusHIT.status == True) print bonusHIT
class MTurkProvider(object): description = 'This is a task authored by a requester on Daemo, a research crowdsourcing platform. ' \ 'Mechanical Turk workers are welcome to do it' keywords = ['daemo'] countries = ['US', 'CA'] min_hits = 1000 def __init__(self, host, aws_access_key_id, aws_secret_access_key): self.host = host self.connection = MTurkConnection( aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, host=settings.MTURK_HOST) self.connection.APIVersion = "2014-08-15" if not self.host: raise ValueError("Please provide a host url") def get_connection(self): return self.connection @staticmethod def _mturk_system_qualifications(qualification): requirements = [] for item in qualification.items.all(): if item.expression['attribute'] not in [ 'location', 'approval_rate', 'total_tasks' ]: continue requirement = None if item.expression['attribute'] == 'location': op = OP_IN if item.expression['operator'] == 'in' else OP_NOT_IN requirement = MultiLocaleRequirement(op, [ val.strip() for val in item.expression['value'] if val is not None and val != '' ]) elif item.expression['attribute'] == 'approval_rate': op = OP_GT if item.expression['operator'] == 'gt' else OP_LT requirement = PercentAssignmentsApprovedRequirement( op, item.expression['value']) elif item.expression['attribute'] == 'total_tasks': op = OP_GT if item.expression['operator'] == 'gt' else OP_LT requirement = NumberHitsApprovedRequirement( op, item.expression['value']) requirements.append(requirement) return requirements def get_qualifications(self, project, boomerang_threshold, add_boomerang): requirements = [] if project.qualification is not None: requirements += self._mturk_system_qualifications( project.qualification) boomerang_qual, success = self.create_qualification_type( owner_id=project.owner_id, project_id=project.group_id, name='Boomerang Score #{}'.format(project.group_id), flag=FLAG_Q_BOOMERANG, description='No description available') boomerang = None if boomerang_threshold <= int(settings.BOOMERANG_MIDPOINT * 100): for i, bucket in enumerate(WAIT_LIST_BUCKETS): if int(bucket[1] * 100) <= boomerang_threshold: boomerang_blacklist, success = \ self.create_qualification_type(owner_id=project.owner_id, name='Boomerang Waitlist #{}-{}'.format(project.group_id, len( WAIT_LIST_BUCKETS) - i), flag=FLAG_Q_BOOMERANG, description='No description available', deny=True, project_id=project.group_id, bucket=bucket) if success and add_boomerang: boomerang = BoomerangRequirement( qualification_type_id=boomerang_blacklist.type_id, comparator=OP_DNE, integer_value=None) requirements.append(boomerang) else: boomerang = BoomerangRequirement( qualification_type_id=boomerang_qual.type_id, comparator=OP_GTEQ, integer_value=boomerang_threshold) if success and add_boomerang: requirements.append(boomerang) return Qualifications(requirements), boomerang_qual def create_hits(self, project, tasks=None, repetition=None): # if project.min_rating > 0: # return 'NOOP' if not tasks: cursor = connection.cursor() # noinspection SqlResolve query = ''' SELECT max(id) id, repetition, group_id, repetition - sum(existing_assignments) remaining_assignments, min_rating FROM ( SELECT t_rev.id, t.group_id, t.min_rating, p.repetition, CASE WHEN ma.id IS NULL OR ma.status IN (%(skipped)s, %(rejected)s, %(expired)s) THEN 0 ELSE 1 END existing_assignments FROM crowdsourcing_task t INNER JOIN crowdsourcing_project p ON t.project_id = p.id INNER JOIN crowdsourcing_task t_rev ON t_rev.group_id = t.group_id LEFT OUTER JOIN mturk_mturkhit mh ON mh.task_id = t_rev.id LEFT OUTER JOIN mturk_mturkassignment ma ON ma.hit_id = mh.id WHERE t.project_id = (%(project_id)s) AND t_rev.exclude_at IS NULL AND t_rev.deleted_at IS NULL ) t GROUP BY group_id, repetition, min_rating HAVING sum(existing_assignments) < repetition; ''' cursor.execute( query, { 'skipped': TaskWorker.STATUS_SKIPPED, 'rejected': TaskWorker.STATUS_REJECTED, 'expired': TaskWorker.STATUS_EXPIRED, 'project_id': project.id }) tasks = cursor.fetchall() rated_workers = Rating.objects.filter( origin_type=Rating.RATING_REQUESTER).count() add_boomerang = rated_workers > 0 duration = project.timeout if project.timeout is not None else datetime.timedelta( hours=24) lifetime = project.deadline - timezone.now( ) if project.deadline is not None else datetime.timedelta(days=7) for task in tasks: question = self.create_external_question(task[0]) mturk_hit = MTurkHIT.objects.filter(task_id=task[0]).first() qualifications, boomerang_qual = self.get_qualifications( project=project, boomerang_threshold=int(round(task[4], 2) * 100), add_boomerang=add_boomerang) qualifications_mask = 0 if qualifications is not None: qualifications_mask = FLAG_Q_LOCALE + FLAG_Q_HITS + FLAG_Q_RATE + FLAG_Q_BOOMERANG hit_type, success = self.create_hit_type( title=project.name, description=self.description, price=project.price, duration=duration, keywords=self.keywords, approval_delay=datetime.timedelta(days=2), qual_req=qualifications, qualifications_mask=qualifications_mask, boomerang_threshold=int(round(task[4], 2) * 100), owner_id=project.owner_id, boomerang_qual=boomerang_qual) if not success: return 'FAILURE' if mturk_hit is None: try: hit = self.connection.create_hit( hit_type=hit_type.string_id, max_assignments=task[3], lifetime=lifetime, question=question)[0] self.set_notification(hit_type_id=hit.HITTypeId) mturk_hit = MTurkHIT(hit_id=hit.HITId, hit_type=hit_type, task_id=task[0]) except MTurkRequestError as e: error = e.errors[0][0] if error == 'AWS.MechanicalTurk.InsufficientFunds': message = { "type": "ERROR", "detail": "Insufficient funds on your Mechanical Turk account!", "code": error } redis_publisher = RedisPublisher(facility='bot', users=[project.owner]) message = RedisMessage(json.dumps(message)) redis_publisher.publish_message(message) return 'FAILED' else: if mturk_hit.hit_type_id != hit_type.id: result, success = self.change_hit_type_of_hit( hit_id=mturk_hit.hit_id, hit_type_id=hit_type.string_id) if success: mturk_hit.hit_type = hit_type mturk_hit.save() return 'SUCCESS' def create_hit_type(self, owner_id, title, description, price, duration, boomerang_threshold, keywords=None, approval_delay=None, qual_req=None, qualifications_mask=0, boomerang_qual=None): hit_type = MTurkHITType.objects.filter( owner_id=owner_id, name=title, description=description, price=Decimal(str(price)), duration=duration, qualifications_mask=qualifications_mask, boomerang_threshold=boomerang_threshold).first() if hit_type is not None: return hit_type, True reward = Price(price) try: mturk_ht = self.connection.register_hit_type( title=title, description=description, reward=reward, duration=duration, keywords=keywords, approval_delay=approval_delay, qual_req=qual_req)[0] hit_type = MTurkHITType(owner_id=owner_id, name=title, description=description, price=Decimal(str(price)), keywords=keywords, duration=duration, qualifications_mask=qualifications_mask, boomerang_qualification=boomerang_qual, boomerang_threshold=boomerang_threshold) hit_type.string_id = mturk_ht.HITTypeId hit_type.save() except MTurkRequestError: return None, False return hit_type, True def create_external_question(self, task, frame_height=800): task_hash = Hashids(salt=settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH) task_id = task_hash.encode(task) url = self.host + '/mturk/task/?taskId=' + task_id question = ExternalQuestion(external_url=url, frame_height=frame_height) return question def update_max_assignments(self, task): task = Task.objects.get(id=task['id']) mturk_hit = task.mturk_hit if not mturk_hit: raise MTurkHIT.DoesNotExist( "This task is not associated to any mturk hit") assignments_completed = task.task_workers.filter(~Q(status__in=[ TaskWorker.STATUS_REJECTED, TaskWorker.STATUS_SKIPPED, TaskWorker.STATUS_EXPIRED ])).count() remaining_assignments = task.project.repetition - assignments_completed if remaining_assignments > 0 and mturk_hit.num_assignments == mturk_hit.mturk_assignments. \ filter(status=TaskWorker.STATUS_SUBMITTED).count() and \ mturk_hit.mturk_assignments.filter(status=TaskWorker.STATUS_IN_PROGRESS).count() == 0: self.add_assignments(hit_id=mturk_hit.hit_id, increment=1) self.extend_hit(hit_id=mturk_hit.hit_id) mturk_hit.status = MTurkHIT.STATUS_IN_PROGRESS mturk_hit.num_assignments += 1 mturk_hit.save() elif remaining_assignments == 0: self.expire_hit(hit_id=mturk_hit.hit_id) mturk_hit.status = MTurkHIT.STATUS_EXPIRED mturk_hit.save() elif remaining_assignments > 0 and \ mturk_hit.status == MTurkHIT.STATUS_EXPIRED: self.extend_hit(hit_id=mturk_hit.hit_id) mturk_hit.status = MTurkHIT.STATUS_IN_PROGRESS return 'SUCCESS' def get_assignment(self, assignment_id): try: return self.connection.get_assignment(assignment_id)[0], True except MTurkRequestError as e: error = e.errors[0][0] if error == 'AWS.MechanicalTurk.InvalidAssignmentState': return assignment_id, False return None, False def set_notification(self, hit_type_id): self.connection.set_rest_notification( hit_type=hit_type_id, url=self.host + '/api/mturk/notification', event_types=[ 'AssignmentReturned', 'AssignmentAbandoned', 'AssignmentAccepted', 'AssignmentSubmitted' ]) def approve_assignment(self, task_worker): task_worker_obj = TaskWorker.objects.get(id=task_worker['id']) if hasattr(task_worker_obj, 'mturk_assignments' ) and task_worker_obj.mturk_assignments.first() is not None: try: self.connection.approve_assignment( task_worker_obj.mturk_assignments.first().assignment_id) except MTurkRequestError: return False return True def reject_assignment(self, task_worker): task_worker_obj = TaskWorker.objects.get(id=task_worker['id']) if hasattr(task_worker_obj, 'mturk_assignments' ) and task_worker_obj.mturk_assignments.first() is not None: try: self.connection.reject_assignment( task_worker_obj.mturk_assignments.first().assignment_id) except MTurkRequestError: return False return True def expire_hit(self, hit_id): try: self.connection.expire_hit(hit_id) except MTurkRequestError: return False return True def disable_hit(self, hit_id): try: self.connection.disable_hit(hit_id) except MTurkRequestError: return False return True def extend_hit(self, hit_id): try: self.connection.extend_hit(hit_id=hit_id, expiration_increment=604800) # 7 days except MTurkRequestError: return False return True def add_assignments(self, hit_id, increment=1): try: self.connection.extend_hit(hit_id=hit_id, assignments_increment=increment) except MTurkRequestError: return False return True def test_connection(self): try: return self.connection.get_account_balance()[0], True except MTurkRequestError as e: error = e.errors[0][0] if error == 'AWS.NotAuthorized': return None, False return None, False def get_account_balance(self): try: return self.connection.get_account_balance()[0] except MTurkRequestError: return None def create_qualification_type(self, owner_id, name, flag, description, project_id, auto_granted=False, auto_granted_value=None, deny=False, bucket=None): # noinspection SqlResolve query = ''' SELECT * FROM ( SELECT task.target_id, task.username, round(task.task_w_avg::NUMERIC, 2) rating --round(coalesce(task.task_w_avg, requester.requester_w_avg, -- platform.platform_w_avg)::NUMERIC, 2) rating FROM ( SELECT target_id, origin_id, project_id, username, sum(weight * power((%(BOOMERANG_TASK_ALPHA)s), t.row_number)) / sum(power((%(BOOMERANG_TASK_ALPHA)s), t.row_number)) task_w_avg FROM ( SELECT r.id, r.origin_id, p.group_id project_id, weight, r.target_id, -1 + row_number() OVER (PARTITION BY target_id ORDER BY tw.created_at DESC) AS row_number, u.username username FROM crowdsourcing_rating r INNER JOIN crowdsourcing_task t ON t.id = r.task_id INNER JOIN crowdsourcing_project p ON p.id = t.project_id INNER JOIN crowdsourcing_taskworker tw ON t.id = tw.task_id AND tw.worker_id=r.target_id INNER JOIN auth_user u ON u.id = r.target_id WHERE origin_id = (%(origin_id)s) AND origin_type = (%(origin_type)s)) t GROUP BY origin_id, target_id, project_id, username) task WHERE task.project_id = (%(project_id)s) ) r ''' extra_query = 'WHERE rating BETWEEN (%(lower_bound)s) AND (%(upper_bound)s);' params = { 'origin_type': Rating.RATING_REQUESTER, 'origin_id': owner_id, 'project_id': project_id, 'BOOMERANG_REQUESTER_ALPHA': settings.BOOMERANG_REQUESTER_ALPHA, 'BOOMERANG_PLATFORM_ALPHA': settings.BOOMERANG_PLATFORM_ALPHA, 'BOOMERANG_TASK_ALPHA': settings.BOOMERANG_TASK_ALPHA } obj_params = {'upper_bound': 300, 'lower_bound': 100} if deny and bucket is not None: query += extra_query params.update({'upper_bound': bucket[1], 'lower_bound': bucket[0]}) obj_params.update({ 'upper_bound': bucket[1] * 100, 'lower_bound': bucket[0] * 100, 'is_blacklist': True }) cursor = connection.cursor() cursor.execute(query, params=params) worker_ratings_raw = cursor.fetchall() worker_ratings = [{ "worker_id": r[0], "worker_username": r[1], "rating": r[2] } for r in worker_ratings_raw] qualification = MTurkQualification.objects.filter(owner_id=owner_id, flag=flag, name=name).first() assigned_workers = [] if qualification is None: try: qualification_type = self.connection. \ create_qualification_type(name=name, description=description, status='Active', auto_granted=auto_granted, auto_granted_value=auto_granted_value)[0] qualification = MTurkQualification.objects.create( owner_id=owner_id, flag=flag, name=name, description=description, auto_granted=auto_granted, auto_granted_value=auto_granted_value, type_id=qualification_type.QualificationTypeId, **obj_params) except MTurkRequestError: return None, False else: assigned_workers = MTurkWorkerQualification.objects.values( 'worker').filter(qualification=qualification).values_list( 'worker', flat=True) for rating in worker_ratings: user_name = rating["worker_username"].split('.') if len(user_name) == 2 and user_name[0] == 'mturk': mturk_worker_id = user_name[1].upper() if mturk_worker_id not in assigned_workers: self.assign_qualification( qualification_type_id=qualification.type_id, worker_id=mturk_worker_id, value=int(rating['rating'] * 100)) defaults = { 'qualification': qualification, 'worker': mturk_worker_id, 'score': int(rating['rating'] * 100) } MTurkWorkerQualification.objects.update_or_create( qualification=qualification, worker=mturk_worker_id, defaults=defaults) return qualification, True def change_hit_type_of_hit(self, hit_id, hit_type_id): try: result = self.connection.change_hit_type_of_hit( hit_id=hit_id, hit_type=hit_type_id) except MTurkRequestError: return None, False return result, True def update_worker_boomerang(self, project_id, worker_id, task_avg, requester_avg): """ Update boomerang for project Args: project_id: worker_id: task_avg: requester_avg Returns: str """ hit = MTurkHIT.objects.select_related( 'hit_type__boomerang_qualification').filter( task__project__group_id=project_id).first() if hit is not None: qualification = hit.hit_type.boomerang_qualification worker_qual = MTurkWorkerQualification.objects.filter( qualification=qualification, worker=worker_id).first() if worker_qual is not None: self.update_score(worker_qual, score=int(task_avg * 100), override=True) else: MTurkWorkerQualification.objects.create( qualification=qualification, worker=worker_id, score=int(task_avg * 100), overwritten=True) self.assign_qualification( qualification_type_id=qualification.type_id, worker_id=worker_id, value=int(task_avg * 100)) # other_quals = MTurkWorkerQualification.objects.filter(~Q(qualification=qualification), # worker=worker_id, # overwritten=False) # for q in other_quals: # self.update_score(q, score=int(requester_avg * 100)) return 'SUCCESS' def update_score(self, worker_qual, score, override=False): if worker_qual is None: return False try: self.connection.update_qualification_score( worker_qual.qualification.type_id, worker_qual.worker, score) worker_qual.overwritten = override worker_qual.score = score worker_qual.save() except MTurkRequestError: return False return True def assign_qualification(self, qualification_type_id, worker_id, value=1): """ Revoke a qualification from a WorkerId Args: qualification_type_id: worker_id: value Returns: bool """ try: self.connection.assign_qualification(qualification_type_id, worker_id, value, send_notification=False) return True except MTurkRequestError: return False def revoke_qualification(self, qualification_type_id, worker_id): try: self.connection.revoke_qualification( qualification_type_id=qualification_type_id, subject_id=worker_id) return True except MTurkRequestError: return False def notify_workers(self, worker_ids, subject, message_text): try: self.connection.notify_workers(worker_ids, subject, message_text) return True except MTurkRequestError: return False
from boto.mturk.qualification import Requirement from boto.mturk.connection import MTurkConnection conn = MTurkConnection( aws_access_key_id="AKIAI7LNZISMTBL77M3Q", aws_secret_access_key="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") name = "DiCarlo Lab Special Compensation %s, 3" % userid description = name qual_type = conn.create_qualification_type(name, description, 'Active') qtypeid = qual_type[0].QualificationTypeId print(qtypeid) req = Requirement(qtypeid, 'Exists') conn.assign_qualification(qtypeid, userid, value=1, send_notification=True) exp = CompensationExperiment( htmlsrc='compensate.html', htmldst='compensate_n%04d.html', sandbox=False, title='Special Compensation for %s, New' % userid, reward=0, duration=3500, description="***Compensation for invited workers only***", comment="compensation, reimbursement", collection_name=None, max_assignments=1, bucket_name='dicarlo_special_compensation', trials_per_hit=1, other_quals=[req])
csv_workers = [] if args.txt: txt_workers = list(extract_txt(args.txt)) print('Extracted %s workerss from %s' % (len(txt_workers), args.txt)) raw_input('Press enter to continue') else: txt_workers = [] for worker in args.workers + csv_workers + txt_workers: # if the worker doesn't already have the qualification, then # assign it, otherwise just update the qualification score qual = old_quals.get(worker) if qual is None: print("Assigning qualification '%s' to worker '%s'" % (args.qualification, worker)) result = conn.assign_qualification(args.qualification, worker, args.value) if result: print(result) elif args.lower or args.value > qual: print("Updating qualification '%s' for worker '%s'" % (args.qualification, worker)) result = conn.update_qualification_score(args.qualification, worker, args.value) if result: print(result) # print(out the current set of workers with the qualification) new_quals = get_quals() print("\n%d workers with qualification %s:" % (len(new_quals), args.qualification)) s = pd.Series(new_quals)
from boto.mturk.connection import MTurkConnection import sys from os.path import expanduser home = expanduser("~") worker_id = sys.argv[1] ACCESS_ID = open(home + '/keys/aws-public').next().strip() SECRET_KEY = open(home + '/keys/aws-private').next().strip() HOST = 'mechanicalturk.amazonaws.com' mtc = MTurkConnection(aws_access_key_id=ACCESS_ID, aws_secret_access_key=SECRET_KEY, host=HOST) mtc.assign_qualification('3JCU2M9SCZTQEZ2N021NJ70XCXMFY2', worker_id)
# read in all workerids that have already been approved. workerids_file = open('%s' % current_round_file, 'r') already_approved = workerids_file.readlines() workerids_file.close() # for each assignment, check if workerid has already been approved. If not, approve assignment & append workerid to list. workerids_file = open('%s' % current_round_file, 'a') for x in range (0, len(already_approved)): already_approved[x] = already_approved[x].rstrip('\n') for a in assignments: if a.WorkerId not in already_approved: if auto_approve_yesno.lower() == 'yes': mturk_connect.approve_assignment(a.AssignmentId) workerids_file.write(a.WorkerId) workerids_file.write('\n') # if it's the first round, and the Block Past Workers option has been selected, assign this qual to all workers completing the hit. if rounds_so_far == 1: if Block_past_workers_yesno.lower() == 'yes': quals_file = open('quals.txt', 'r') quals_ids = quals_file.readlines() quals_file.close() Block_past_workers_id = quals_ids[0].rstrip('\n') mturk_connect.assign_qualification(Block_past_workers_id, a.WorkerId, send_notification = False) workerids_file.close()
class MTurkProvider(object): description = 'This is a task authored by a requester on Daemo, a research crowdsourcing platform. ' \ 'Mechanical Turk workers are welcome to do it' keywords = ['daemo'] countries = ['US', 'CA'] min_hits = 1000 def __init__(self, host, aws_access_key_id, aws_secret_access_key): self.host = host self.connection = MTurkConnection( aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, host=settings.MTURK_HOST ) self.connection.APIVersion = "2014-08-15" if not self.host: raise ValueError("Please provide a host url") def get_connection(self): return self.connection @staticmethod def _mturk_system_qualifications(qualification): requirements = [] for item in qualification.items.all(): if item.expression['attribute'] not in ['location', 'approval_rate', 'total_tasks']: continue requirement = None if item.expression['attribute'] == 'location': op = OP_IN if item.expression['operator'] == 'in' else OP_NOT_IN requirement = MultiLocaleRequirement(op, [val.strip() for val in item.expression['value'] if val is not None and val != '']) elif item.expression['attribute'] == 'approval_rate': op = OP_GT if item.expression['operator'] == 'gt' else OP_LT requirement = PercentAssignmentsApprovedRequirement(op, item.expression['value']) elif item.expression['attribute'] == 'total_tasks': op = OP_GT if item.expression['operator'] == 'gt' else OP_LT requirement = NumberHitsApprovedRequirement(op, item.expression['value']) requirements.append(requirement) return requirements def get_qualifications(self, project, boomerang_threshold, add_boomerang): requirements = [] if project.qualification is not None: requirements += self._mturk_system_qualifications(project.qualification) boomerang_qual, success = self.create_qualification_type(owner_id=project.owner_id, project_id=project.group_id, name='Boomerang Score #{}'.format(project.group_id), flag=FLAG_Q_BOOMERANG, description='No description available') boomerang = None if boomerang_threshold <= int(settings.BOOMERANG_MIDPOINT * 100): for i, bucket in enumerate(WAIT_LIST_BUCKETS): if int(bucket[1] * 100) <= boomerang_threshold: boomerang_blacklist, success = \ self.create_qualification_type(owner_id=project.owner_id, name='Boomerang Waitlist #{}-{}'.format(project.group_id, len( WAIT_LIST_BUCKETS) - i), flag=FLAG_Q_BOOMERANG, description='No description available', deny=True, project_id=project.group_id, bucket=bucket) if success and add_boomerang: boomerang = BoomerangRequirement(qualification_type_id=boomerang_blacklist.type_id, comparator=OP_DNE, integer_value=None) requirements.append(boomerang) else: boomerang = BoomerangRequirement(qualification_type_id=boomerang_qual.type_id, comparator=OP_GTEQ, integer_value=boomerang_threshold) if success and add_boomerang: requirements.append(boomerang) return Qualifications(requirements), boomerang_qual def create_hits(self, project, tasks=None, repetition=None): # if project.min_rating > 0: # return 'NOOP' if not tasks: cursor = connection.cursor() # noinspection SqlResolve query = ''' SELECT max(id) id, repetition, group_id, repetition - sum(existing_assignments) remaining_assignments, min_rating FROM ( SELECT t_rev.id, t.group_id, t.min_rating, p.repetition, CASE WHEN ma.id IS NULL OR ma.status IN (%(skipped)s, %(rejected)s, %(expired)s) THEN 0 ELSE 1 END existing_assignments FROM crowdsourcing_task t INNER JOIN crowdsourcing_project p ON t.project_id = p.id INNER JOIN crowdsourcing_task t_rev ON t_rev.group_id = t.group_id LEFT OUTER JOIN mturk_mturkhit mh ON mh.task_id = t_rev.id LEFT OUTER JOIN mturk_mturkassignment ma ON ma.hit_id = mh.id WHERE t.project_id = (%(project_id)s) AND t_rev.exclude_at IS NULL AND t_rev.deleted_at IS NULL ) t GROUP BY group_id, repetition, min_rating HAVING sum(existing_assignments) < repetition; ''' cursor.execute(query, {'skipped': TaskWorker.STATUS_SKIPPED, 'rejected': TaskWorker.STATUS_REJECTED, 'expired': TaskWorker.STATUS_EXPIRED, 'project_id': project.id}) tasks = cursor.fetchall() rated_workers = Rating.objects.filter(origin_type=Rating.RATING_REQUESTER).count() add_boomerang = rated_workers > 0 duration = project.timeout if project.timeout is not None else datetime.timedelta(hours=24) lifetime = project.deadline - timezone.now() if project.deadline is not None else datetime.timedelta( days=7) for task in tasks: question = self.create_external_question(task[0]) mturk_hit = MTurkHIT.objects.filter(task_id=task[0]).first() qualifications, boomerang_qual = self.get_qualifications(project=project, boomerang_threshold=int( round(task[4], 2) * 100), add_boomerang=add_boomerang) qualifications_mask = 0 if qualifications is not None: qualifications_mask = FLAG_Q_LOCALE + FLAG_Q_HITS + FLAG_Q_RATE + FLAG_Q_BOOMERANG hit_type, success = self.create_hit_type(title=project.name, description=self.description, price=project.price, duration=duration, keywords=self.keywords, approval_delay=datetime.timedelta(days=2), qual_req=qualifications, qualifications_mask=qualifications_mask, boomerang_threshold=int(round(task[4], 2) * 100), owner_id=project.owner_id, boomerang_qual=boomerang_qual) if not success: return 'FAILURE' if mturk_hit is None: try: hit = self.connection.create_hit(hit_type=hit_type.string_id, max_assignments=task[3], lifetime=lifetime, question=question)[0] self.set_notification(hit_type_id=hit.HITTypeId) mturk_hit = MTurkHIT(hit_id=hit.HITId, hit_type=hit_type, task_id=task[0]) except MTurkRequestError as e: error = e.errors[0][0] if error == 'AWS.MechanicalTurk.InsufficientFunds': message = { "type": "ERROR", "detail": "Insufficient funds on your Mechanical Turk account!", "code": error } redis_publisher = RedisPublisher(facility='bot', users=[project.owner]) message = RedisMessage(json.dumps(message)) redis_publisher.publish_message(message) return 'FAILED' else: if mturk_hit.hit_type_id != hit_type.id: result, success = self.change_hit_type_of_hit(hit_id=mturk_hit.hit_id, hit_type_id=hit_type.string_id) if success: mturk_hit.hit_type = hit_type mturk_hit.save() return 'SUCCESS' def create_hit_type(self, owner_id, title, description, price, duration, boomerang_threshold, keywords=None, approval_delay=None, qual_req=None, qualifications_mask=0, boomerang_qual=None): hit_type = MTurkHITType.objects.filter(owner_id=owner_id, name=title, description=description, price=Decimal(str(price)), duration=duration, qualifications_mask=qualifications_mask, boomerang_threshold=boomerang_threshold).first() if hit_type is not None: return hit_type, True reward = Price(price) try: mturk_ht = self.connection.register_hit_type(title=title, description=description, reward=reward, duration=duration, keywords=keywords, approval_delay=approval_delay, qual_req=qual_req)[0] hit_type = MTurkHITType(owner_id=owner_id, name=title, description=description, price=Decimal(str(price)), keywords=keywords, duration=duration, qualifications_mask=qualifications_mask, boomerang_qualification=boomerang_qual, boomerang_threshold=boomerang_threshold) hit_type.string_id = mturk_ht.HITTypeId hit_type.save() except MTurkRequestError: return None, False return hit_type, True def create_external_question(self, task, frame_height=800): task_hash = Hashids(salt=settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH) task_id = task_hash.encode(task) url = self.host + '/mturk/task/?taskId=' + task_id question = ExternalQuestion(external_url=url, frame_height=frame_height) return question def update_max_assignments(self, task): task = Task.objects.get(id=task['id']) mturk_hit = task.mturk_hit if not mturk_hit: raise MTurkHIT.DoesNotExist("This task is not associated to any mturk hit") assignments_completed = task.task_workers.filter(~Q(status__in=[TaskWorker.STATUS_REJECTED, TaskWorker.STATUS_SKIPPED, TaskWorker.STATUS_EXPIRED])).count() remaining_assignments = task.project.repetition - assignments_completed if remaining_assignments > 0 and mturk_hit.num_assignments == mturk_hit.mturk_assignments. \ filter(status=TaskWorker.STATUS_SUBMITTED).count() and \ mturk_hit.mturk_assignments.filter(status=TaskWorker.STATUS_IN_PROGRESS).count() == 0: self.add_assignments(hit_id=mturk_hit.hit_id, increment=1) self.extend_hit(hit_id=mturk_hit.hit_id) mturk_hit.status = MTurkHIT.STATUS_IN_PROGRESS mturk_hit.num_assignments += 1 mturk_hit.save() elif remaining_assignments == 0: self.expire_hit(hit_id=mturk_hit.hit_id) mturk_hit.status = MTurkHIT.STATUS_EXPIRED mturk_hit.save() elif remaining_assignments > 0 and \ mturk_hit.status == MTurkHIT.STATUS_EXPIRED: self.extend_hit(hit_id=mturk_hit.hit_id) mturk_hit.status = MTurkHIT.STATUS_IN_PROGRESS return 'SUCCESS' def get_assignment(self, assignment_id): try: return self.connection.get_assignment(assignment_id)[0], True except MTurkRequestError as e: error = e.errors[0][0] if error == 'AWS.MechanicalTurk.InvalidAssignmentState': return assignment_id, False return None, False def set_notification(self, hit_type_id): self.connection.set_rest_notification(hit_type=hit_type_id, url=self.host + '/api/mturk/notification', event_types=['AssignmentReturned', 'AssignmentAbandoned', 'AssignmentAccepted', 'AssignmentSubmitted']) def approve_assignment(self, task_worker): task_worker_obj = TaskWorker.objects.get(id=task_worker['id']) if hasattr(task_worker_obj, 'mturk_assignments') and task_worker_obj.mturk_assignments.first() is not None: try: self.connection.approve_assignment(task_worker_obj.mturk_assignments.first().assignment_id) except MTurkRequestError: return False return True def reject_assignment(self, task_worker): task_worker_obj = TaskWorker.objects.get(id=task_worker['id']) if hasattr(task_worker_obj, 'mturk_assignments') and task_worker_obj.mturk_assignments.first() is not None: try: self.connection.reject_assignment(task_worker_obj.mturk_assignments.first().assignment_id) except MTurkRequestError: return False return True def expire_hit(self, hit_id): try: self.connection.expire_hit(hit_id) except MTurkRequestError: return False return True def disable_hit(self, hit_id): try: self.connection.disable_hit(hit_id) except MTurkRequestError: return False return True def extend_hit(self, hit_id): try: self.connection.extend_hit(hit_id=hit_id, expiration_increment=604800) # 7 days except MTurkRequestError: return False return True def add_assignments(self, hit_id, increment=1): try: self.connection.extend_hit(hit_id=hit_id, assignments_increment=increment) except MTurkRequestError: return False return True def test_connection(self): try: return self.connection.get_account_balance()[0], True except MTurkRequestError as e: error = e.errors[0][0] if error == 'AWS.NotAuthorized': return None, False return None, False def get_account_balance(self): try: return self.connection.get_account_balance()[0] except MTurkRequestError: return None def create_qualification_type(self, owner_id, name, flag, description, project_id, auto_granted=False, auto_granted_value=None, deny=False, bucket=None): # noinspection SqlResolve query = ''' SELECT * FROM ( SELECT task.target_id, task.username, round(task.task_w_avg::NUMERIC, 2) rating --round(coalesce(task.task_w_avg, requester.requester_w_avg, -- platform.platform_w_avg)::NUMERIC, 2) rating FROM ( SELECT target_id, origin_id, project_id, username, sum(weight * power((%(BOOMERANG_TASK_ALPHA)s), t.row_number)) / sum(power((%(BOOMERANG_TASK_ALPHA)s), t.row_number)) task_w_avg FROM ( SELECT r.id, r.origin_id, p.group_id project_id, weight, r.target_id, -1 + row_number() OVER (PARTITION BY target_id ORDER BY tw.created_at DESC) AS row_number, u.username username FROM crowdsourcing_rating r INNER JOIN crowdsourcing_task t ON t.id = r.task_id INNER JOIN crowdsourcing_project p ON p.id = t.project_id INNER JOIN crowdsourcing_taskworker tw ON t.id = tw.task_id AND tw.worker_id=r.target_id INNER JOIN auth_user u ON u.id = r.target_id WHERE origin_id = (%(origin_id)s) AND origin_type = (%(origin_type)s)) t GROUP BY origin_id, target_id, project_id, username) task WHERE task.project_id = (%(project_id)s) ) r ''' extra_query = 'WHERE rating BETWEEN (%(lower_bound)s) AND (%(upper_bound)s);' params = { 'origin_type': Rating.RATING_REQUESTER, 'origin_id': owner_id, 'project_id': project_id, 'BOOMERANG_REQUESTER_ALPHA': settings.BOOMERANG_REQUESTER_ALPHA, 'BOOMERANG_PLATFORM_ALPHA': settings.BOOMERANG_PLATFORM_ALPHA, 'BOOMERANG_TASK_ALPHA': settings.BOOMERANG_TASK_ALPHA } obj_params = {'upper_bound': 300, 'lower_bound': 100} if deny and bucket is not None: query += extra_query params.update({'upper_bound': bucket[1], 'lower_bound': bucket[0]}) obj_params.update({'upper_bound': bucket[1] * 100, 'lower_bound': bucket[0] * 100, 'is_blacklist': True}) cursor = connection.cursor() cursor.execute(query, params=params) worker_ratings_raw = cursor.fetchall() worker_ratings = [{"worker_id": r[0], "worker_username": r[1], "rating": r[2]} for r in worker_ratings_raw] qualification = MTurkQualification.objects.filter(owner_id=owner_id, flag=flag, name=name).first() assigned_workers = [] if qualification is None: try: qualification_type = self.connection. \ create_qualification_type(name=name, description=description, status='Active', auto_granted=auto_granted, auto_granted_value=auto_granted_value)[0] qualification = MTurkQualification.objects.create(owner_id=owner_id, flag=flag, name=name, description=description, auto_granted=auto_granted, auto_granted_value=auto_granted_value, type_id=qualification_type.QualificationTypeId, **obj_params) except MTurkRequestError: return None, False else: assigned_workers = MTurkWorkerQualification.objects.values('worker').filter( qualification=qualification).values_list('worker', flat=True) for rating in worker_ratings: user_name = rating["worker_username"].split('.') if len(user_name) == 2 and user_name[0] == 'mturk': mturk_worker_id = user_name[1].upper() if mturk_worker_id not in assigned_workers: self.assign_qualification( qualification_type_id=qualification.type_id, worker_id=mturk_worker_id, value=int(rating['rating'] * 100)) defaults = { 'qualification': qualification, 'worker': mturk_worker_id, 'score': int(rating['rating'] * 100) } MTurkWorkerQualification.objects.update_or_create(qualification=qualification, worker=mturk_worker_id, defaults=defaults) return qualification, True def change_hit_type_of_hit(self, hit_id, hit_type_id): try: result = self.connection.change_hit_type_of_hit(hit_id=hit_id, hit_type=hit_type_id) except MTurkRequestError: return None, False return result, True def update_worker_boomerang(self, project_id, worker_id, task_avg, requester_avg): """ Update boomerang for project Args: project_id: worker_id: task_avg: requester_avg Returns: str """ hit = MTurkHIT.objects.select_related('hit_type__boomerang_qualification').filter( task__project__group_id=project_id).first() if hit is not None: qualification = hit.hit_type.boomerang_qualification worker_qual = MTurkWorkerQualification.objects.filter(qualification=qualification, worker=worker_id).first() if worker_qual is not None: self.update_score(worker_qual, score=int(task_avg * 100), override=True) else: MTurkWorkerQualification.objects.create(qualification=qualification, worker=worker_id, score=int(task_avg * 100), overwritten=True) self.assign_qualification(qualification_type_id=qualification.type_id, worker_id=worker_id, value=int(task_avg * 100)) # other_quals = MTurkWorkerQualification.objects.filter(~Q(qualification=qualification), # worker=worker_id, # overwritten=False) # for q in other_quals: # self.update_score(q, score=int(requester_avg * 100)) return 'SUCCESS' def update_score(self, worker_qual, score, override=False): if worker_qual is None: return False try: self.connection.update_qualification_score(worker_qual.qualification.type_id, worker_qual.worker, score) worker_qual.overwritten = override worker_qual.score = score worker_qual.save() except MTurkRequestError: return False return True def assign_qualification(self, qualification_type_id, worker_id, value=1): """ Revoke a qualification from a WorkerId Args: qualification_type_id: worker_id: value Returns: bool """ try: self.connection.assign_qualification(qualification_type_id, worker_id, value, send_notification=False) return True except MTurkRequestError: return False def revoke_qualification(self, qualification_type_id, worker_id): try: self.connection.revoke_qualification(qualification_type_id=qualification_type_id, subject_id=worker_id) return True except MTurkRequestError: return False def notify_workers(self, worker_ids, subject, message_text): try: self.connection.notify_workers(worker_ids, subject, message_text) return True except MTurkRequestError: return False
class MTurk(object): def __init__(self, app=None): self.host = 'https://mechanicalturk.sandbox.amazonaws.com' self.secret_key = None self.access_id = None self.app = app if app is not None: self.init_app(app) def init_app(self, app): app.config.setdefault('MTURK_SECRET_KEY', None) app.config.setdefault('MTURK_ACCESS_ID', None) app.config.setdefault('MTURK_SANDBOX', True) self.update_credentials(app.config['MTURK_ACCESS_ID'], app.config['MTURK_SECRET_KEY']) self.is_sandbox = app.config['MTURK_SANDBOX'] self.valid_login = self.verify_aws_login() def update_credentials(self, aws_access_key_id, aws_secret_access_key): self.aws_access_key_id = aws_access_key_id self.aws_secret_access_key = aws_secret_access_key def verify_aws_login(self): if ((self.aws_secret_access_key is None) or (self.aws_access_key_id is None)): logging.warning('No AWS keys found in app configuration') else: host = 'mechanicalturk.amazonaws.com' params = dict(aws_access_key_id=self.aws_access_key_id, aws_secret_access_key=self.aws_secret_access_key, host=host) self.mtc = MTurkConnection(**params) try: self.mtc.get_account_balance() except MTurkRequestError as e: return dict(success=False, message=e.error_message) else: return True def connect_to_turk(self): if not self.valid_login: logging.warning( 'Sorry, unable to connect to Amazon Mechanical Turk. Please check your credentials' ) return False if self.is_sandbox: host = 'mechanicalturk.sandbox.amazonaws.com' else: host = 'mechanicalturk.amazonaws.com' mturkparams = dict(aws_access_key_id=self.aws_access_key_id, aws_secret_access_key=self.aws_secret_access_key, host=host) self.mtc = MTurkConnection(**mturkparams) return True def get_account_balance(self): if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') try: balance = self.mtc.get_account_balance() except MTurkRequestError as e: return dict(success=False, message=e.error_message) else: return balance def get_reviewable_hits(self): if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') try: hits = self.mtc.get_all_hits() except MTurkRequestError as e: return dict(success=False, message=e.error_message) reviewable_hits = [ hit for hit in hits if hit.HITStatus == "Reviewable" or hit.HITStatus == "Reviewing" ] hits_data = [ MTurkHIT({ 'hitid': hit.HITId, 'title': hit.Title, 'status': hit.HITStatus, 'max_assignments': hit.MaxAssignments, 'number_assignments_completed': hit.NumberOfAssignmentsCompleted, 'number_assignments_pending': hit.NumberOfAssignmentsPending, 'number_assignments_available': hit.NumberOfAssignmentsAvailable, 'creation_time': hit.CreationTime, 'expiration': hit.Expiration }) for hit in reviewable_hits ] return hits_data def get_all_hits(self): """ Get all HITs """ if not self.connect_to_turk(): return False try: hits = self.mtc.get_all_hits() except MTurkRequestError as e: return dict(success=False, message=e.error_message) hits_data = [ MTurkHIT({ 'hitid': hit.HITId, 'title': hit.Title, 'status': hit.HITStatus, 'max_assignments': hit.MaxAssignments, 'number_assignments_completed': hit.NumberOfAssignmentsCompleted, 'number_assignments_pending': hit.NumberOfAssignmentsPending, 'number_assignments_available': hit.NumberOfAssignmentsAvailable, 'creation_time': hit.CreationTime, 'expiration': hit.Expiration, }) for hit in hits ] return hits_data def get_active_hits(self): """ Get active HITs """ if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') # hits = self.mtc.search_hits() try: hits = self.mtc.get_all_hits() except MTurkRequestError as e: return dict(success=False, message=e.error_message) active_hits = [hit for hit in hits if not hit.expired] hits_data = [ MTurkHIT({ 'hitid': hit.HITId, 'title': hit.Title, 'status': hit.HITStatus, 'max_assignments': hit.MaxAssignments, 'number_assignments_completed': hit.NumberOfAssignmentsCompleted, 'number_assignments_pending': hit.NumberOfAssignmentsPending, 'number_assignments_available': hit.NumberOfAssignmentsAvailable, 'creation_time': hit.CreationTime, 'expiration': hit.Expiration, }) for hit in active_hits ] return hits_data def get_hit(self, hit_id, response_groups=None): if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') try: hit = self.mtc.get_hit(hit_id, response_groups)[0] except MTurkRequestError as e: return False return hit def get_workers(self, assignment_status=None): """ Get workers """ if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') try: hits = self.mtc.search_hits(sort_direction='Descending', page_size=20) except MTurkRequestError as e: return False hit_ids = [hit.HITId for hit in hits] workers_nested = [ self.mtc.get_assignments(hit_id, status=assignment_status, sort_by='SubmitTime', page_size=100) for hit_id in hit_ids ] workers = [val for subl in workers_nested for val in subl] # Flatten nested lists worker_data = [{ 'hitId': worker.HITId, 'assignmentId': worker.AssignmentId, 'workerId': worker.WorkerId, 'submit_time': worker.SubmitTime, 'accept_time': worker.AcceptTime, 'status': worker.AssignmentStatus, 'completion_code': worker.answers[0][0].fields[0] } for worker in workers] return worker_data def bonus_worker(self, assignment_id, amount, reason=""): """ Bonus worker """ if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') try: bonus = MTurkConnection.get_price_as_price(amount) assignment = self.mtc.get_assignment(assignment_id)[0] worker_id = assignment.WorkerId self.mtc.grant_bonus(worker_id, assignment_id, bonus, reason) return True except MTurkRequestError as e: return dict(success=False, message=e.error_message) def approve_worker(self, assignment_id, feedback=None): """ Approve worker """ if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') try: self.mtc.approve_assignment(assignment_id, feedback=feedback) return True except MTurkRequestError as e: return False def reject_worker(self, assignment_id): """ Reject worker """ if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') try: self.mtc.reject_assignment(assignment_id, feedback=None) return True except MTurkRequestError as e: return dict(success=False, message=e.error_message) def unreject_worker(self, assignment_id): """ Unreject worker """ if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') try: self.mtc.approve_rejected_assignment(assignment_id) return True except MTurkRequestError as e: return dict(success=False, message=e.error_message) def assign_qualification(self, qualification_type_id, worker_id, value=1, send_notification=True): if not self.connect_to_turk(): return dict(success=False, message='Could not connect to AWS') try: self.mtc.assign_qualification(qualification_type_id, worker_id, value, send_notification) return True except MTurkRequestError as e: return dict(success=False, message=e.error_message) def revoke_qualification(self, subject_id, qualification_type_id, reason=None): if not self.connect_to_turk(): return False try: self.mtc.revoke_qualification(subject_id, qualification_type_id, reason) return True except MTurkRequestError as e: return dict(success=False, message=e.error_message) def notify_worker(self, worker_id, subject, message_text): if not self.connect_to_turk(): return False try: self.mtc.notify_workers(worker_id, subject, message_text) return True except MTurkRequestError as e: return dict(success=False, message=e.error_message) def list_workers_with_qualification(self, qualification_type_id): if not self.connect_to_turk(): return False try: workers = self.mtc.get_all_qualifications_for_qual_type( qualification_type_id) except MTurkRequestError as e: return dict(success=False, message=e.error_message) workers = [w.SubjectId for w in workers] return workers
from boto.mturk.connection import MTurkConnection conn = MTurkConnection( aws_access_key_id="AKIAI7LNZISMTBL77M3Q", aws_secret_access_key="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" ) name = "DiCarlo Lab Special Compensation %s, 3" % userid description = name qual_type = conn.create_qualification_type(name, description, "Active") qtypeid = qual_type[0].QualificationTypeId print(qtypeid) req = Requirement(qtypeid, "Exists") conn.assign_qualification(qtypeid, userid, value=1, send_notification=True) exp = CompensationExperiment( htmlsrc="compensate.html", htmldst="compensate_n%04d.html", sandbox=False, title="Special Compensation for %s, New" % userid, reward=0, duration=3500, description="***Compensation for invited workers only***", comment="compensation, reimbursement", collection_name=None, max_assignments=1, bucket_name="dicarlo_special_compensation", trials_per_hit=1, other_quals=[req],
from csv import DictReader from boto.mturk.connection import MTurkConnection, MTurkRequestError from boto import config parser = argparse.ArgumentParser(description='Assign a qualification to Amazon Mechanical Turk workers') parser.add_argument('-q', '--qualification', required=True, help='Qualification ID') parser.add_argument('-r', '--resultsfile', required=True, help='Filename of tab delimited CSV file with results') parser.add_argument('-s', '--sandbox', action='store_true', help='Run the command in the Mechanical Turk Sandbox (used for testing purposes)') parser.add_argument('-p', '--profile', help='Run commands using specific aws credentials rather the default. To set-up alternative credentials see http://boto3.readthedocs.org/en/latest/guide/configuration.html#shared-credentials-file') args = parser.parse_args() if args.sandbox: if not config.has_section('MTurk'): config.add_section('MTurk') config.set('MTurk', 'sandbox', 'True') mturk_website = 'requestersandbox.mturk.com' with open(args.resultsfile, 'r') as infile: results = list(DictReader(infile, delimiter='\t')) mtc = MTurkConnection(is_secure=True, profile_name=args.profile) for row in results: try: mtc.assign_qualification(args.qualification, row['workerid'], value=1, send_notification=False) print("Assigning {} to {}".format(args.qualification, row['workerid'])) except MTurkRequestError as e: print("Skipping {} for {}".format(args.qualification, row['workerid']))