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))
Exemple #2
0
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))
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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])
Exemple #6
0
        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)
Exemple #7
0
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)
Exemple #8
0
# 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
Exemple #11
0
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']))