def post(self, request, code): session = db.get_or_404(Session, code=code) # background task because it makes http requests, # so it will need its own lock. session.advance_last_place_participants() # task = BackgroundTask(session.advance_last_place_participants) return Response('ok')
def get(self, request: Request): anonymous_code = request.path_params['anonymous_code'] session = db.get_or_404(Session, _anonymous_code=anonymous_code) label = request.query_params.get('participant_label') participant = participant_or_none_if_exceeded(session, label=label) if not participant: return no_participants_left_http_response() return RedirectResponse(participant._start_url())
def post(self, request, code): session = db.get_or_404(Session, code=code) successful_payments = 0 failed_payments = 0 post_data = self.get_post_data() mturk_client = get_mturk_client(use_sandbox=session.mturk_use_sandbox) payment_page_response = self.redirect('MTurkSessionPayments', code=session.code) # use worker ID instead of assignment ID. Because 2 workers can have # the same assignment (if 1 starts it then returns it). we can't really # block that. # however, we can ensure that 1 worker does not get 2 assignments, # by enforcing that the same worker is always assigned to the same participant. participants = session.pp_set.filter( Participant.mturk_worker_id.in_(post_data.getlist('workers')) ) for p in participants: # need the try/except so that we try to pay the rest of the participants payoff = p.payoff_in_real_world_currency() try: if payoff > 0: mturk_client.send_bonus( WorkerId=p.mturk_worker_id, AssignmentId=p.mturk_assignment_id, BonusAmount='{0:.2f}'.format(Decimal(payoff)), # prevent duplicate payments UniqueRequestToken='{}_{}'.format( p.mturk_worker_id, p.mturk_assignment_id ), # this field is required. Reason='Thank you', ) # approve assignment should happen AFTER bonus, so that if bonus fails, # the user will still show up in assignments_not_reviewed. # worst case is that bonus succeeds but approval fails. # in that case, exception will be raised on send_bonus because of UniqueRequestToken. # but that's OK, then you can just unselect that participant and pay the others. mturk_client.approve_assignment(AssignmentId=p.mturk_assignment_id) successful_payments += 1 except Exception as e: msg = ( 'Could not pay {} because of an error communicating ' 'with MTurk: {}'.format(p._numeric_label(), str(e)) ) enqueue_admin_message('error', msg) logger.error(msg) failed_payments += 1 if failed_payments > 10: return payment_page_response msg = 'Successfully made {} payments.'.format(successful_payments) if failed_payments > 0: msg += ' {} payments failed.'.format(failed_payments) enqueue_admin_message('warning', msg) else: enqueue_admin_message('success', msg) return payment_page_response
def get(self, request: Request): """anything essential should be done in """ code = request.path_params['code'] pp = db.get_or_404(Participant, code=code) label = request.query_params.get(otree.constants.participant_label) pp.initialize(label) first_url = pp._url_i_should_be_on() return RedirectResponse(first_url)
def post(self, request, code): session = db.get_or_404(Session, code=code) with MTurkClient( use_sandbox=session.mturk_use_sandbox, request=request ) as mturk_client: expiration = datetime(2015, 1, 1) mturk_client.update_expiration_for_hit( HITId=session.mturk_HITId, # If you update it to a time in the past, # the HIT will be immediately expired. ExpireAt=expiration, ) session.mturk_expiration = expiration.timestamp() # don't need a message because the MTurkCreateHIT page will # statically say the HIT has expired. return self.redirect('MTurkCreateHIT', code=code)
def get(self, request): code = request.path_params['code'] participant = db.get_or_404(Participant, code=code) if participant.is_browser_bot: session = participant.session has_next_submission = browser_bots.enqueue_next_post_data( participant_code=participant.code) if has_next_submission: msg = ('Finished the last page, ' 'but the bot is still trying ' 'to submit more pages.') raise BotError(msg) browser_bots.send_completion_message(session_code=session.code, participant_code=code) return render('otree/OutOfRangeNotification.html', {})
def post(self, request, code): session = db.get_or_404(Session, code=code) with MTurkClient( use_sandbox=session.mturk_use_sandbox, request=request ) as mturk_client: for p in session.pp_set.filter( Participant.mturk_worker_id.in_(self.get_post_data().getlist('workers')) ): mturk_client.reject_assignment( AssignmentId=p.mturk_assignment_id, # The boto3 docs say this param is optional, but if I omit it, I get: # An error occurred (ValidationException) when calling the RejectAssignment operation: # 1 validation error detected: Value null at 'requesterFeedback' # failed to satisfy constraint: Member must not be null RequesterFeedback='', ) enqueue_admin_message('success', "Rejected the selected assignments") return self.redirect('MTurkSessionPayments', code=code)
async def dispatch(self) -> None: self.request = request = Request(self.scope, receive=self.receive) participant_code = request.path_params['participant_code'] msg = ( "This user does not exist in the database. " "Maybe the database was reset." ) participant = db.get_or_404(Participant, code=participant_code, msg=msg) # if the player tried to skip past a part of the subsession # (e.g. by typing in a future URL) # or if they hit the back button to a previous subsession # in the sequence. url_should_be_on = participant._url_i_should_be_on() if not request.url.path == url_should_be_on: response = RedirectResponse(url_should_be_on, status_code=302) else: self.set_attributes(participant) response = await run_in_threadpool(self.inner_dispatch, request) # response = self.inner_dispatch(request) await response(self.scope, self.receive, self.send)
def inner_dispatch(self, request): self.session = db.get_or_404(Session, code=request.path_params['code']) return super().inner_dispatch(request)
def get(self, request: Request): code = request.path_params['code'] session = self.session = db.get_or_404(Session, code=code) GET = request.query_params try: assignment_id = GET['assignmentId'] worker_id = GET['workerId'] except KeyError: return Response( 'URL is missing assignmentId or workerId parameter', status_code=404) qual_id = session.config['mturk_hit_settings'].get( 'grant_qualification_id') use_sandbox = session.mturk_use_sandbox if qual_id and not use_sandbox: # this is necessary because MTurk's qualification requirements # don't prevent 100% of duplicate participation. See: # https://groups.google.com/forum/#!topic/otree/B66HhbFE9ck previous_participation = (dbq(Participant).join(Session).filter( Participant.session != session, Session.mturk_qual_id == qual_id, Participant.mturk_worker_id == worker_id, ).scalar() is not None) if previous_participation: return Response('You have already accepted a related HIT') # if using sandbox, there is no point in granting quals. # https://groups.google.com/forum/#!topic/otree/aAmqTUF-b60 # don't pass request arg, because we don't want to show a message. # using the fully qualified name because that seems to make mock.patch work mturk_client = otree.views.mturk.get_mturk_client( use_sandbox=use_sandbox) # seems OK to assign this multiple times mturk_client.associate_qualification_with_worker( QualificationTypeId=qual_id, WorkerId=worker_id, # Mturk complains if I omit IntegerValue IntegerValue=1, ) try: # just check if this worker already game, but # don't filter for assignment, because maybe they already started # and returned the previous assignment # in this case, we should assign back to the same participant # so that we don't get duplicates in the DB, and so people # can't snoop and try the HIT first, then re-try to get a bigger bonus pp = self.session.pp_set.filter_by(mturk_worker_id=worker_id).one() except NoResultFound: pp = self.session.pp_set.filter_by( visited=False).order_by('id').first() if not pp: return no_participants_left_http_response() # 2014-10-17: needs to be here even if it's also set in # the next view to prevent race conditions # this needs to be inside the lock pp.visited = True pp.mturk_worker_id = worker_id # reassign assignment_id, even if they are returning, because maybe they accepted # and then returned, then re-accepted with a different assignment ID # if it's their second time pp.mturk_assignment_id = assignment_id return RedirectResponse(pp._start_url(), status_code=302)