def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if not request.args.has_key('uniqueId'): raise ExperimentError('improper_inputs') # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0 for record in user_data['data']: # for line in data file trial = record['trialdata'] if trial['phase']=='TEST': if trial['hit']==True: bonus += 0.02 user.bonus = bonus db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def worker_complete(): """Overide the psiTurk worker_complete route. This skirts around an issue where the participant's status reverts to 3 because of rogue calls to this route. It does this by changing the status only if it's not already >= 100. """ exp = experiment(session) if 'uniqueId' not in request.args: resp = {"status": "bad request"} return jsonify(**resp) else: unique_id = request.args['uniqueId'] exp.log("Completed experiment %s" % unique_id) try: user = Participant.query.\ filter(Participant.uniqueid == unique_id).one() if user.status < 100: user.status = 3 user.endhit = datetime.datetime.now() session_psiturk.add(user) session_psiturk.commit() status = "success" except exc.SQLAlchemyError: status = "database error" resp = {"status": status} return jsonify(**resp)
def check_secret_code(): current_app.logger.info(request.form['workerid']) current_app.logger.info(request.form['code']) uniqueId = request.form['uniqueid'] try: worker = LegitWorker.query.filter(and_(LegitWorker.amt_worker_id ==request.form['workerid'], \ LegitWorker.completion_code == request.form['code'], \ LegitWorker.status=='owed')).one() except: abort(406) worker.submitted() db_session.add(worker) db_session.commit() try: user = Participant.query.\ filter(Participant.uniqueid == uniqueId).one() user.bonus = worker.bonus user.status = COMPLETED user.endhit = datetime.datetime.now() db_session.add(user) db_session.commit() except: abort(406) resp = {"bonus": user.bonus} return jsonify(**resp)
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if not request.args.has_key('uniqueId'): raise ExperimentError( 'improper_inputs' ) # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON #bonus already computed by in experiment js user.bonus = user_data['bonus'] db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def compute_bonus(): current_app.logger.info("accessing route /compute_bonus") # check that request includes a uniqueId if not request.args.has_key('uniqueId'): raise ExperimentError( 'improper_inputs' ) # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON import random r = random.random() whichToBonus = 0 if r > 0.5: whichToBonus = 1 bonus = 0 for record in user_data['data']: # for line in data file trial = record['trialdata'] # get part of line holding trial info if trial[ 'phase'] == 'apav': #check that trial is in test phase, not instructions if trial['trial'] == 243 and trial[ 'habitatNum'] == whichToBonus: bonus = float(trial['scoreAfter']) user.bonus = bonus #set bonus field to new value db_session.add(user) db_session.commit() #commit to database resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def emit(self, topic, argument=None, room=None): #log emissions to current task in database for future analysis/playback if topic == 'load': if len(argument.keys()) < 3: print("small load: " + str(argument)) return argument['waypoints'] = {} print("attempting to load " + str(hash(frozenset(argument))) + " to " + str(room)) if self.current_task >= 0 and topic != "sleep_callback": try: argument_string = json.dumps(argument) record = Emission(topic, argument_string, room) #self.session_id, self.current_task, task = db_session.query(Task).filter( Task.session_id == self.session_id).filter( Task.task_number == self.current_task).first() if task is not None: task.emissions.append(record) db_session.commit() except Exception as e: print("problem logging emission: " + str(topic) + ": " + str(e) + " on task " + str(self.session_id) + "::" + str(self.current_task)) if argument is None: self.sio.emit(topic, room=room) else: self.sio.emit(topic, argument, room=room)
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if not request.args.has_key('uniqueId'): raise ExperimentError( 'improper_inputs' ) # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0. numcorrect = 0 for record in user_data['data']: # for line in data file trial = record['trialdata'] if trial['phase'] == 'TEST': if trial['hit'] == True: numcorrect += 1 user.bonus = ceil((numcorrect / 40.0 * 1.0) * 100) / 100. db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def check_secret_code(): current_app.logger.info(request.form["workerid"]) current_app.logger.info(request.form["code"]) uniqueId = request.form["uniqueid"] try: worker = LegitWorker.query.filter( and_( LegitWorker.amt_worker_id == request.form["workerid"], LegitWorker.completion_code == request.form["code"], LegitWorker.status == "owed", ) ).one() except: abort(406) worker.submitted() db_session.add(worker) db_session.commit() try: user = Participant.query.filter(Participant.uniqueid == uniqueId).one() user.bonus = worker.bonus user.status = COMPLETED user.endhit = datetime.datetime.now() db_session.add(user) db_session.commit() except: abort(406) resp = {"bonus": user.bonus} return jsonify(**resp)
def patch(self, campaign_id): campaign = Campaign.query.filter(Campaign.id == campaign_id).one() data = request.json did_something = False if 'is_active' in data and campaign.is_active and not data['is_active']: campaign.end() did_something = True elif 'goal' in data: goal = data['goal'] completed_count = Participant.count_completed( codeversion=services_manager.codeversion, mode=services_manager.mode) assert goal > completed_count, 'Goal {} must be greater than current completed {}.'.format( goal, completed_count) campaign.goal = goal did_something = True if did_something: db_session.add(campaign) db_session.commit() return campaign
def compute_bonus(): current_app.logger.info("accessing route /compute_bonus") # check that request includes a uniqueId if not request.args.has_key('uniqueId'): raise ExperimentError('improper_inputs') # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON import random r = random.random() whichToBonus = 0 if r > 0.5: whichToBonus = 1 bonus = 0 for record in user_data['data']: # for line in data file trial = record['trialdata'] # get part of line holding trial info if trial['phase']=='apav': #check that trial is in test phase, not instructions if trial['trial']==243 and trial['habitatNum'] == whichToBonus: bonus = float(trial['scoreAfter']) user.bonus = bonus #set bonus field to new value db_session.add(user) db_session.commit() #commit to database resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def save(self, *objects): """Add all the objects to the session and commit them.""" from psiturk.db import db_session as session_psiturk if len(objects) > 0: self.session.add_all(objects) self.session.commit() session_psiturk.commit()
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if 'uniqueId' not in request.args: raise ExperimentError('improper_inputs') # original author wants to change this line uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query\ .filter(Participant.uniqueid == uniqueId)\ .one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0 for record in user_data['data']: # for line in data file trial = record['trialdata'] if trial['phase'] == 'TEST': if trial['hit'] is True: bonus += 0.02 user.bonus = bonus db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp) except Exception as e: current_app.logger.info("Error: %s", repr(e)) abort(404) # again, bad to display HTML, but...
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if not request.args.has_key('uniqueId'): raise ExperimentError( 'improper_inputs' ) # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0 for record in user_data['data']: # for line in data file trial = record['trialdata'] if trial[u'phase'] == u'Experiment': if trial['Reward'] > 0: #task pays up to $1.00 in bonus and there are 132 trials bonus += 1.00 / 132.0 user.bonus = round(bonus, 2) db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if 'uniqueId' not in request.args: raise ExperimentError( 'improper_inputs') # original author wants to change this line uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query\ .filter(Participant.uniqueid == uniqueId)\ .one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0 for record in user_data['data']: # for line in data file trial = record['trialdata'] if trial['phase'] == 'TEST': if trial['hit'] is True: bonus += 0.02 user.bonus = bonus db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp) except Exception as e: current_app.logger.info("Error: %s", repr(e)) abort(404) # again, bad to display HTML, but...
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascript client if not request.args.has_key('uniqueId'): raise ExperimentError( 'improper_inputs' ) # i don't like returning HTML to JSON requests... maybe should change this unique_id = request.args['uniqueId'] # try: # lookup user in database # in order to check for IP address violations get the user this way and then check for user.ipaddress user = Participant.query. \ filter(Participant.uniqueid == unique_id). \ one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0 for record in user_data['data']: # for line in data file trial = record['trialdata'] if trial['phase'] == 'trial' and trial['included']: bonus += float(trial['choice']) elif trial['phase'] == 'exit': bonus = 0 break user.bonus = "%.2f" % round(bonus, 2) db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp)
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if not 'uniqueId' in request.args: # i don't like returning HTML to JSON requests... maybe should change this raise ExperimentError('improper_inputs') uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0.00 for record in user_data['data']: # for line in data file trial = record['trialdata'] if trial['phase'] == 'TEST' and 'accuracy' in trial: bonus += trial['accuracy'] * 0.01 bonus = round(bonus, 2) user.bonus = bonus db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def create_participant(worker_id, hit_id, assignment_id, mode): """Create a participant. This route will be hit very early on as any nodes the participant creates will be defined in reference to the participant object. You must specify the worker_id, hit_id, assignment_id and mode in the url. """ # check this worker hasn't already taken part parts = models.Participant.query.filter_by(worker_id=worker_id).all() if parts: print "participant already exists!" return Response(status=200) # make the participant participant = models.Participant(worker_id=worker_id, assignment_id=assignment_id, hit_id=hit_id, mode=mode) session.add(participant) session.commit() # make a psiturk participant too, for now from psiturk.models import Participant as PsiturkParticipant psiturk_participant = PsiturkParticipant(workerid=worker_id, assignmentid=assignment_id, hitid=hit_id) session_psiturk.add(psiturk_participant) session_psiturk.commit() # return the data return success_response(field="participant", data=participant.__json__(), request_type="participant post")
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if not request.args.has_key('uniqueId'): raise ExperimentError( 'improper_inputs' ) # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] # print("wow") # print("uniqueid:",uniqueId) try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0 # print("got here") # print(user_data['data']) for record in user_data['data']: # for line in data file trial = record['trialdata'] # print(trial['phase']) if trial['phase'] == 'END': if trial['status'] == 'submit': bonus = 0.00 # print("also got here") user.bonus = bonus db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} # print("not sure what's going on") return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if not request.args.has_key("uniqueId"): raise ExperimentError( "improper_inputs" ) # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args["uniqueId"] try: # lookup user in database user = Participant.query.filter(Participant.uniqueid == uniqueId).one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0 for record in user_data["data"]: # for line in data file trial = record["trialdata"] if trial["blockID"] != "Practice" and trial["blockID"] != "Test": bonus += trial["dollars"] # if trial['phase']=='TEST': # if trial['hit']==True: # bonus += 0.02 user.bonus = round(bonus, 2) db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def compute_bonus(): current_app.logger.info("accessing route /compute_bonus") # check that request includes a uniqueId if not request.args.has_key('uniqueId'): raise ExperimentError( 'improper_inputs' ) # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON bonuses = [] for record in user_data['data']: # for line in data file trial = record['trialdata'] # get part of line holding trial info if trial['phase'] == 'apavPhase' and trial['globalTrial'] == 252: user.bonus = float( trial['scoreAfter']) #set bonus field to the final bonus db_session.add(user) db_session.commit() #commit to database resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def complete_override(): ''' Debugging route for complete. ''' if not 'uniqueId' in request.args: raise ExperimentError('improper_inputs') else: unique_id = request.args['uniqueId'] mode = request.args['mode'] try: user = Participant.query.\ filter(Participant.uniqueid == unique_id).one() user.status = COMPLETED user.endhit = datetime.utcnow() db_session.add(user) db_session.commit() except: raise ExperimentError('error_setting_worker_complete') else: # send them back to mturk. if (mode == 'sandbox' or mode == 'live'): return render_template('closepopup.html') else: if mode == 'lab': link = unique_id.split(':')[0] try: unique_link = UniqueLink.query.\ filter(UniqueLink.link == link).one() unique_link.status = LINK_SUBMITTED db_session.add(unique_link) db_session.commit() except: current_app.logger.error( "Couldn't change status to SUBMITTED for %s" % link) return render_template('complete.html')
def launch(): """Launch the experiment.""" exp = experiment(db.init_db(drop_all=False)) exp.log("Launching experiment...", "-----") init_db() exp.recruiter().open_recruitment(n=exp.initial_recruitment_size) session_psiturk.commit() session.commit() return success_response(request_type="launch")
def set_new_goal(self, goal): self.goal = goal db_session.add(self) db_session.commit() from .experiment import app job = app.apscheduler.get_job(self.campaign_job_id) kwargs = job.kwargs kwargs['campaign'] = self job.modify(kwargs=kwargs) return self
def end(self): self.is_active = False self.ended = datetime.datetime.now(datetime.timezone.utc) from .experiment import app try: app.apscheduler.remove_job(self.campaign_job_id) except JobLookupError: pass db_session.add(self) db_session.commit() return self
def register_user(uid): #todo: validate user (how?) #queue = queue if uid not in queue: queue.append(uid) if len(queue) > 1 and uid not in games: a = queue.pop(0) b = queue.pop(0) # randomly assign role if random.random() > .5: a, b = b, a pattern_config = config.get("Task Parameters", "patterns").split(',') pattern_map = { "Demonstrate": pattern.HtmlUnityDemonstrate, "Reward": pattern.HtmlUnityReward, "Apprentice": pattern.HtmlUnityApprentice, "Test": pattern.HtmlUnityTest } #todo: weight pattern selection sample by quanity of type in database, if needed pattern_types = [pattern_map[name.strip()] for name in pattern_config] n_teach = int(config.get("Task Parameters", "num_teaching_tasks")) n_test = int(config.get("Task Parameters", "num_testing_tasks")) new_game = random.choice(pattern_types)(sio=sio, teacher=a, student=b, num_teaching_tasks=n_teach, num_testing_tasks=n_test) print("created new game of type " + str(new_game.__class__.__name__)) for user in [a, b]: games[user] = new_game arg = { "role": games[user].role_string(user), "pattern": new_game.__class__.__name__ } #sio.emit("sendTrainingMessage", "* You've been matched as "+ games[user].role_string(user) + ".", room=user) sio.emit("instructions", arg, room=user) #initial task #new_game.new_task() db_session.commit() else: sio.emit("sendTrainingMessage", "* Waiting for a partner.", room=uid)
def ineligible(): current_app.logger.info("Participant ineligible") try: unique_id = request.args['uniqueId'] current_app.logger.info("Marking ineligible %s" % unique_id) user = Participant.query. \ filter(Participant.uniqueid == unique_id).one() user.status = 8 # INELIGIBLE db_session.add(user) db_session.commit() except exc.SQLAlchemyError: raise ExperimentError('tried_to_quit') raise IneligibilityError()
def final_state(self, data): try: task_number = data.get('task_number', self.prev_task) prev_task_record = db_session.query(Task).filter( Task.session_id == self.session_id).filter( Task.task_number == task_number).first() if prev_task_record is not None: #print("dumping final task info to: " + str(self.session_id) + "::" + str(task_number)) prev_task_record.final_state = json.dumps(data) db_session.commit() #print("saved game state to " + str(self.prev_task_id)) except Exception as e: print("error storing final state" + str(e))
def set_initial_state(self, actor, state, level_path=None): """ handles an initial_state coming from an actor, or call with predefined level to """ if self.current_task_record is not None: try: db_session.add(self.current_task_record) except Exception: pass if self.current_task_record.task_number == self.current_task: return #already set initial state for this task #if self.initial_state is None: self.initial_state = state self.current_state = state print("level loaded for task " + str(self.current_task) + " current state set: " + str(hash(frozenset(state))) + ", size: " + str(len(state))) new_task = Task(session_id=self.session_id, task_number=self.current_task, init_state=state) new_task.level_path = level_path self.current_task_record = new_task session_record = db_session.query(Session).filter( Session.session_id == self.session_id).one() session_record.tasks.append(new_task) new_task.student = self.student #db_session.query(User).filter(User.user_id == self.student).one() new_task.teacher = self.teacher #db_session.query(User).filter(User.user_id == self.teacher).one() new_task.init_state = json.dumps(state) db_session.commit() print("creating task with id: " + str(new_task.session_id) + "::" + str(new_task.task_number)) #self.current_task_id = (BLAH) # first initial state submitted is chosen #self.current_state = state self.prev_state = state #self.state_stack=[state] self.unity_lock = self.init_unity_lock self.html_lock = self.init_html_lock self.emit('load', self.current_state, room=actor) self.update_ui(actor) if len(self.unity_lock) > 1: self.emit('load', self.current_state, room=self.partner(actor)) self.update_ui(self.partner(actor))
def launch(): """Launch the experiment.""" exp = experiment(db.init_db(drop_all=False)) exp.log("Launch route hit, initializing tables and opening recruitment.", "-----") init_db() exp.recruiter().open_recruitment(n=exp.initial_recruitment_size) session_psiturk.commit() session.commit() exp.log("Experiment successfully launched!", "-----") data = {"status": "success"} js = dumps(data) return Response(js, status=200, mimetype='application/json')
def compute_bonus(): uniqueId = request.args['uniqueId'] try: user = Participant.query.filter(Participant.uniqueid == uniqueId).one() user_data = loads(user.datastring) final_record = user_data['data'][-2] trial = final_record['trialdata'] bonus = max(0, min(17, trial['totalReward'])) user.bonus = "{:.2f}".format(bonus) db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} except: resp = {"bonusComputed": "failure"} return jsonify(**resp)
def mark_bad(): if not 'uniqueId' in request.args: raise ExperimentError('improper_inputs') else: uniqueId = request.args['uniqueId'] user = Participant\ .query.\ filter(Participant.uniqueid == uniqueId).\ one() user.status = BAD db_session.add(user) db_session.commit() resp = {user.uniqueid: user.status} return jsonify(**resp)
def test_wrapper_get_all_hits_all_studies(self, amt_services_wrapper, create_dummy_hit, list_hits, helpers): create_dummy_hit('3XJOUITW8URHJMX7F00H20LGRIAQTX') create_dummy_hit('3BFNCI9LYKQ2ENUY4MLKKW0NSU437W') from psiturk.db import db_session from psiturk.models import Hit Hit.query.filter_by(hitid='3BFNCI9LYKQ2ENUY4MLKKW0NSU437W').delete() db_session.commit() hits = list_hits(all_studies=False) assert '3BFNCI9LYKQ2ENUY4MLKKW0NSU437W' not in [ hit.options['hitid'] for hit in hits] hits = list_hits(all_studies=True) assert '3BFNCI9LYKQ2ENUY4MLKKW0NSU437W' in [ hit.options['hitid'] for hit in hits]
def do_it(participant_attributes={}): participant_attribute_defaults = { 'workerid': faker.md5(raw_output=False), 'hitid': faker.md5(raw_output=False), 'assignmentid': faker.md5(raw_output=False), } participant_attributes = dict(list( participant_attribute_defaults.items()) + list(participant_attributes.items())) init_db() participant = Participant(**participant_attributes) db_session.add(participant) db_session.commit() return participant
def campaign(): from psiturk.models import Campaign parameters = { 'codeversion': '1.0', 'mode': 'sandbox', 'goal': 100, 'minutes_between_rounds': 1, 'assignments_per_round': 10, 'hit_reward': 1.00, 'hit_duration_hours': 1, } new_campaign = Campaign(**parameters) from psiturk.db import db_session db_session.add(new_campaign) db_session.commit() return new_campaign
def complete_session(): if not 'trialdata' in request.form: abort(404) else: trialdata = loads(request.form['trialdata']) try: for trial in trialdata: log_print(trial) word_txt = trial['word'] rt = trial['rt'] features = trial['features'] log_print(word_txt) # update word word = Word.query.filter(Word.word_string == word_txt).one() log_print(word.word_string) for feature_index in features.keys(): feature_name = features[feature_index]['feat'] log_print(feature_index) log_print(feature_name) # update feature feature = Feature.query.filter( Feature.feature_string == feature_name).one() log_print(feature.feature_string) db_session.add(feature) # record rating myrating = Rating(word, feature, request.form['uniqueId']) myrating.set_rating( float(features[feature_index]['rating'][:-1])) log_print(request.form['uniqueId']) db_session.add(feature) db_session.add(myrating) db_session.add(word) db_session.commit() log_print("saved") except: log_print("error saving") abort(404) else: return jsonify(status="saved")
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascript client if not request.args.has_key('uniqueId'): raise ExperimentError('improper_inputs') # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON bonus = 0 # find actual reward/max expected reward and multiply by max $ amount to give ($1?) # take average over each collaboration setting? questiondata = user_data['questiondata'] num_iterations = questiondata['num_iterations'] bonuses = [] for robot in questiondata['robot_order']: key = str(robot) + "_hard_collaborate_suggest" data_dict = questiondata[key] # payoffs = np.array(data_dict['arm_payoffs']) # probabilities = np.array(data_dict['arm_probabilities']) # max_exp_reward = max(payoffs * probabilities) * num_iterations payoff_matrix = np.array(data_dict['arms_payoff_matrix']) max_exp_reward = max(payoff_matrix.dot([0, 1, 2, 3, 4])) * num_iterations actual_reward = data_dict['all_total_rewards'][-1] bonuses.append(min(1, 1 * (actual_reward / max_exp_reward))) bonus = np.average(bonuses) if bonus >= 0.5: user.bonus = round(bonus, 2) else: user.bonus = 0.00 db_session.add(user) db_session.commit() resp = {"bonusComputed": "success"} return jsonify(**resp) except Exception as e: print "error updating bonus" print e abort(404) # again, bad to display HTML, but...
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if not request.args.has_key('uniqueId'): raise ExperimentError('improper_inputs') # lookup user in database uniqueid = request.args['uniqueId'] user = Participant.query.\ filter(Participant.uniqueid == uniqueid).\ one() final_bonus = 'NONE' # load the bonus information try: all_data = json.loads(user.datastring) question_data = all_data['questiondata'] final_bonus = question_data['final_bonus'] final_bonus = round(float(final_bonus), 2) if final_bonus > MAX_BONUS: raise ValueError('Bonus of {} excedes MAX_BONUS of {}'.format( final_bonus, MAX_BONUS)) user.bonus = final_bonus db_session.add(user) db_session.commit() resp = { 'uniqueId': uniqueid, 'bonusComputed': 'success', 'bonusAmount': final_bonus } except: current_app.logger.error( 'error processing bonus for {}'.format(uniqueid)) current_app.logger.error(format_exc()) resp = { 'uniqueId': uniqueid, 'bonusComputed': 'failure', 'bonusAmount': final_bonus } current_app.logger.info(str(resp)) return jsonify(**resp)
def complete_exp(): if not 'uniqueId' in request.form: raise ExperimentError('improper_inputs') unique_id = request.form['uniqueId'] current_app.logger.info("completed experimente") try: user = Participant.query.\ filter(Participant.uniqueid == unique_id).one() user.status = COMPLETED user.endhit = datetime.datetime.now() db_session.add(user) db_session.commit() resp = {"status": "success"} except exc.SQLAlchemyError: current_app.logger.error("DB error: Unique user not found.") resp = {"status": "error, uniqueId not found"} return jsonify(**resp)
def complete_condition(): if not 'filename' in request.form: abort(404) else: try: pix = Pixels.query.filter(Pixels.filename==request.form['filename']).one() pix.n_completed = pix.n_completed + 1 if pix.illustrations == None: pix.illustrations = request.form['drawing_data'] else: pix.illustrations = pix.illustrations + request.form['drawing_data'] db_session.add(pix) db_session.commit() except: current_app.logger.info("error saving") abort(404) else: return jsonify(status="saved")
def complete_session(): if not 'trialdata' in request.form: abort(404) else: trialdata = loads(request.form['trialdata']) try: for trial in trialdata: log_print(trial) word_txt = trial['word'] rt = trial['rt'] features = trial['features'] log_print(word_txt) # update word word = Word.query.filter(Word.word_string==word_txt).one() log_print(word.word_string) for feature_index in features.keys(): feature_name = features[feature_index]['feat'] log_print(feature_index) log_print(feature_name) # update feature feature = Feature.query.filter(Feature.feature_string==feature_name).one() log_print(feature.feature_string) db_session.add(feature) # record rating myrating = Rating(word, feature, request.form['uniqueId']) myrating.set_rating(float(features[feature_index]['rating'][:-1])) log_print(request.form['uniqueId']) db_session.add(feature) db_session.add(myrating) db_session.add(word) db_session.commit() log_print("saved") except: log_print("error saving") abort(404) else: return jsonify(status="saved")
def compute_bonus(): current_app.logger.info("accessing route /compute_bonus") # check that request includes a uniqueId if not request.args.has_key('uniqueId'): raise ExperimentError('improper_inputs') # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON user.bonus = float(user_data['questiondata']['finalBonus']) db_session.add(user) db_session.commit() #commit to database resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def nudge(): """Call the participant submission trigger for everyone who finished.""" exp = experiment(session) exp.log("Nudging the experiment along.") # If a participant is hung at status 4, we must have missed the # notification saying they had submitted, so we bump them to status 100 # and run the submission trigger. participants = Participant.query.filter_by(status=4).all() for participant in participants: exp.log("Nudging participant {}".format(participant)) participant_id = participant.uniqueid # Assign participant status 100. participant.status = 100 session_psiturk.commit() # Recruit new participants. exp.participant_submission_trigger( participant_id=participant_id, assignment_id=participant.assignmentid) # If a participant has status 3, but has an endhit time, something must # have gone awry, so we bump the status to 100 and call it a day. participants = Participant.query.filter( and_( Participant.status == 3, Participant.endhit != None)).all() for participant in participants: exp.log("Bumping {} from status 3 (with endhit time) to 100.") participant.status = 100 session_psiturk.commit() return Response( dumps({"status": "success"}), status=200, mimetype='application/json')
def dashboard(): if "mode" in request.form: if request.form["mode"] == "add": if ("workerid" in request.form) and ("bonus" in request.form): newworker = LegitWorker(workerid=request.form["workerid"]) newworker.set_bonus(float(request.form["bonus"])) db_session.add(newworker) db_session.commit() elif request.form["mode"] == "delete": if "index" in request.form: current_app.logger.info("deleting") try: lw = LegitWorker.query.filter(LegitWorker.index == int(request.form["index"])).one() db_session.delete(lw) db_session.commit() except: flash(u"Sorry, was unable to delete that worker. Perhaps they were already deleted!", "error") try: workers = LegitWorker.query.all() return render_template("dashboard.html", workers=workers) except TemplateNotFound: abort(404)
def compute_bonus(): current_app.logger.info("accessing route /compute_bonus") # check that request includes a uniqueId if not request.args.has_key('uniqueId'): raise ExperimentError('improper_inputs') # i don't like returning HTML to JSON requests... maybe should change this uniqueId = request.args['uniqueId'] try: # lookup user in database user = Participant.query.\ filter(Participant.uniqueid == uniqueId).\ one() user_data = loads(user.datastring) # load datastring from JSON bonuses = [] for record in user_data['data']: # for line in data file trial = record['trialdata'] # get part of line holding trial info if trial['phase']=='apavPhase' and trial['globalTrial']==252: user.bonus = float(trial['scoreAfter']) #set bonus field to the final bonus db_session.add(user) db_session.commit() #commit to database resp = {"bonusComputed": "success"} return jsonify(**resp) except: abort(404) # again, bad to display HTML, but...
def dashboard(): if 'mode' in request.form: if request.form['mode']=='add': if ('workerid' in request.form) and ('bonus' in request.form): if (LegitWorker.query.filter(LegitWorker.amt_worker_id == request.form['workerid']).count() == 0): newworker = LegitWorker(workerid=request.form['workerid']) newworker.set_bonus(float(request.form['bonus'])) db_session.add(newworker) db_session.commit() else: flash('That worker has already been added!', 'error') elif request.form['mode']=='delete': if ('index' in request.form): current_app.logger.info('deleting') try: lw=LegitWorker.query.filter(LegitWorker.index == int(request.form['index'])).one() db_session.delete(lw) db_session.commit() except: flash(u'Sorry, was unable to delete that worker. Perhaps they were already deleted!', 'error') elif request.form['mode']=='refresh': failed_workers = [] workers = LegitWorker.query.all() for lw in workers: try: user = Participant.query.filter(Participant.workerid == lw.amt_worker_id).one() if user.status == BONUSED: try: lw.paid() db_session.add(lw) db_session.commit() except Exception as ex: current_app.logger.error('Could not update worker %s to paid status: %s', lw.amt_worker_id, ex) failed_workers.append(w.amt_worker_id) except NoResultFound: pass # hasn't submitted yet... if len(failed_workers) > 0: display_str = u'Could not update the following workers:' for w in failed_workers: display_str += '\n%s' % (w) flash(display_str, 'error') try: workers = LegitWorker.query.all() return render_template('dashboard.html', workers = workers) except TemplateNotFound: abort(404)
def compensate(): #getrequest parts try: workerId = request.args['workerId'] except: #keyError: now workerId was provided #render dat entry page try: return render_template('compensateentry.html') except TemplateNotFound: abort(404) if workerId == "": try: return render_template('compensateentry.html') except TemplateNotFound: abort(404) # Messages. Maybe move into the template? messages = { "hitSubbed": {"type": "success", "title": "Your HIT is under review.", "content": "It looks like you already submitted your HIT. We'll take action on it soon!"}, "returnHIT": {"type": "info", "title":"Please return your HIT.", "content":"In order to recieve compensation, please submit or return your HIT then refresh this page. Thanks."}, "notEnough": {"type": "info", "title":"Sorry; you're not eligible for payment.", "content": "It looks like you didn't make it far enough into the experiment to be eligible for payment. However, we've removed you from our list of participants so if we ever run the experiment again, you may participate!"}, "takeDummy": {"type": "info", "title":"Please complete the Compensation HIT.", "content": """Because you haven't submitted work for us in the past, we need you to complete a 'dummy' compensation HIT. Follow these instructions: <ol> <li>Return the HIT if you have not yet done so. <li>Go here: <a href="https://www.mturk.com/mturk/searchbar?selectedSearchType=hitgroups&requesterId=AH1PO6KC4YRE3" target="_blank">CPL's HITs on MTurk</a> <li>Take and submit the HIT called "Psiturk Compensation HIT - DO NOT TAKE UNLESS INSTRUCTED TO DO SO" <li>Wait 3-5 minutes and refresh this page. </ol>"""}, "success": {"type": "success", "title": "We have credited your account.", "content": "Thanks - you've been given a bonus of $%s for your time."}, "alreadyPayed": {"type": "success", "title": "You've been payed.", "content": "Our records show you have already been payed for this HIT. Thanks for your participation!"}, "fatal": {"type": "warning", "title": "Something went wrong.", "content": """Please contact us at <a href="mailto:[email protected]">[email protected]</a> and include the following information: <ul> <li>worker id: %(workerid)s <li>assignmentid: %(assignmentid)s </ul> """} } # Get the row of the worker in the database worker = Participant.query.\ filter(Participant.workerid == workerId).first() # filter(Participant.assignmentid == assignmentId, # Participant.hitid == hitId).first() # If the worker is in the db, check status if worker: #grab the rest of the info hitId = worker.hitid assignmentId = worker.assignmentid #if worker has already submitted, if worker.status in [4]: message = messages['hitSubbed'] #if the worker was already bonused elif worker.status in [5,7]: message = messages['alreadyPayed'] #if the worker's HIT is still in progress, tell them to turn it in elif worker.status in [0,1,2,3]: message = messages['returnHIT'] #if the worker did in fact quit early (meaning they can't finish it) else: # worker.status == 6 #get trialCount and conditionNum conditionNum = "" trialCount = 0 if hasattr(worker, 'datastring'): try: # get condition workerobj = loads(worker.datastring) conditionNum = workerobj['questiondata']['realCondition'] except: #print "malformed datastring for worker", worker.workerid pass try: #count trials trials = workerobj['data'] for trial in trials: trialCount += int(trial['trialdata']['phase'] == 'TEST') except: # print "no data" pass #If they didn't complete any trials, # remove them from db and display sorry print "Num trials completed:", trialCount if trialCount == 0: db_session.delete(worker) db_session.commit() message = messages['notEnough'] else: #they completed some of the trials #min bonus is 1 c. amount = max(0.01,round(float(trialCount)/[417,818][conditionNum]*2.50,2)) amount = min(amount, 2.50) #sanity check try: bonusAssignment = getAnAssignmentId(workerId) worker_bonus(bonusAssignment, amount, 'auto bonus system') #update worker worker.status = 7 db_session.add(worker) db_session.commit() message = messages['success'] message['content'] = message['content'] % amount except NoAMTConnection: abort(503) except WorkerAlreadyCredited: message = messages['alreadyPayed'] except CreditTransactionError: message = messages['fatal'] message['content'] = message['content'] % {"workerid": workerId, "assignmentid": assignmentId} except WorkerNotRegistered: message = messages['takeDummy'] else: message = messages['notEnough'] try: return render_template('compensate.html', message = message, workerId = workerId) except TemplateNotFound: abort(404)
def worker_function(event_type, assignment_id, participant_id): """Process the notification.""" exp = experiment(session) key = "-----" exp.log("Received an {} notification for assignment {}, participant {}".format(event_type, assignment_id, participant_id), key) if assignment_id is not None: # save the notification to the notification table notif = models.Notification( assignment_id=assignment_id, event_type=event_type) session.add(notif) session.commit() # try to identify the participant participants = Participant.query\ .filter_by(assignmentid=assignment_id)\ .all() # if there are multiple participants select the most recent if len(participants) > 1: if event_type in ['AssignmentAbandoned', 'AssignmentReturned']: participants = [p for p in participants if p.status < 100] if participants: participant = min(participants, key=attrgetter('beginhit')) else: return None else: participant = max(participants, key=attrgetter('beginhit')) # if there are none (this is also bad news) print an error elif len(participants) == 0: exp.log("Warning: No participants associated with this assignment_id. Notification will not be processed.", key) return None # if theres only one participant (this is good) select them else: participant = participants[0] elif participant_id is not None: participant = Participant.query.filter_by(uniqueid=participant_id).all()[0] else: raise ValueError("Error: worker_function needs either an assignment_id or a \ participant_id, they cannot both be None") participant_id = participant.uniqueid key = participant_id[0:5] if event_type == 'AssignmentAccepted': pass elif event_type == 'AssignmentAbandoned': if participant.status < 100: exp.log("Participant status = {}, setting status to 104 and failing all nodes.".format(participant.status), key) participant.status = 104 session_psiturk.commit() nodes = models.Node.query\ .filter_by(participant_id=participant_id, failed=False)\ .all() for node in nodes: node.fail() session.commit() elif event_type == 'AssignmentReturned': if participant.status < 100: exp.log("Participant status = {}, setting status to 103 and failing all nodes.".format(participant.status), key) participant.status = 103 session_psiturk.commit() nodes = models.Node.query\ .filter_by(participant_id=participant_id, failed=False)\ .all() for node in nodes: node.fail() session.commit() elif event_type == 'AssignmentSubmitted': if participant.status < 100: # Approve the assignment. exp.recruiter().approve_hit(assignment_id) # Check that the participant's data is okay. worked = exp.data_check(participant=participant) # If it isn't, fail their nodes and recruit a replacement. if not worked: exp.log("Participant failed data check: failing nodes, setting status to 105, and recruiting replacement participant", key) participant.status = 105 session_psiturk.commit() for node in models.Node.query.filter_by(participant_id=participant_id, failed=False).all(): node.fail() session.commit() exp.recruiter().recruit_participants(n=1) else: # if their data is ok, pay them a bonus # note that the bonus is paid before the attention check bonus = exp.bonus(participant=participant) if bonus >= 0.01: exp.log("Bonus = {}: paying bonus".format(bonus), key) exp.recruiter().reward_bonus( assignment_id, bonus, exp.bonus_reason()) else: exp.log("Bonus = {}: NOT paying bonus".format(bonus), key) # Perform an attention check attended = exp.attention_check(participant=participant) # if they fail the attention check fail their nodes and replace them if not attended: exp.log("Attention check failed: failing nodes, setting status to 102, and recruiting replacement participant", key) participant.status = 102 session_psiturk.commit() for node in models.Node.query.filter_by(participant_id=participant_id, failed=False).all(): node.fail() session.commit() exp.recruiter().recruit_participants(n=1) else: # otherwise everything is good # recruit is run to see if it is time to recruit more participants exp.log("All checks passed: setting status to 101 and running recruit()", key) participant.status = 101 session_psiturk.commit() exp.submission_successful(participant=participant) session.commit() exp.recruit() exp.log_summary() else: exp.log("Error: unknown event_type {}".format(event_type), key)
TILEPATH = './static/images/tiles/' TARGETFILE = 'brain.png' NTILES = 16 # first delete all the files in the static/images/tiles folder files = os.listdir(TILEPATH) for myfile in files: if myfile != 'placeholder.txt': print "removing existing file", TILEPATH+myfile os.remove(TILEPATH+myfile) # query existing pixels Pixels.query.delete() # create the tiles using the target image tiles = image_slicer.slice(TARGETFILE, NTILES, save=False) image_slicer.save_tiles(tiles, prefix='tile', directory='static/images/tiles', format='png') # add tiles to database for tile in tiles: pixel_width, pixel_height = tile.image.size print "dimensions:", (pixel_width, pixel_height) , "filename:", tile.filename pixel_attributes = dict(filename = tile.filename, n_completed = 0, width = pixel_width, height = pixel_height) pixel = Pixels(**pixel_attributes) db_session.add(pixel) db_session.commit()
def compute_bonus(): # check that user provided the correct keys # errors will not be that gracefull here if being # accessed by the Javascrip client if not request.args.has_key('uniqueId'): raise ExperimentError('improper_inputs') # i don't like returning HTML to JSON requests... maybe should change this # lookup user in database uniqueid = request.args['uniqueId'] user = Participant.query.\ filter(Participant.uniqueid == uniqueid).\ one() # load the bonus information with open("static/json/bonus_map_adp_pac_nonadp.json", "r") as fh: bonuses = json.load(fh)['stim_bonus'] current_app.logger.info("Computing bonus for unique id '%s'", uniqueid) total_bonus = 0 try: stim = None data = json.loads(user.datastring)["data"] for record in data: trialdata = record['trialdata'] if trialdata['eventType'] == "INITIALIZE_TRIAL": #and trialdata['stimType'] == "normal": stim = trialdata['stimId'] elif trialdata['eventType'] == "END_TRIAL" and stim is not None: #sequence = "".join([str(int(x) + 1) for x in trialdata['humanGoalSeq']]) if stim.find("h_move") != -1: sequence = "".join([str(int(x) + 1) for x in trialdata['humanCapSeq']]) elif stim.find("r_move") != -1: sequence = "".join([str(int(x) + 1) for x in trialdata['predGoalSeq']]) if sequence not in bonuses[stim]: current_app.logger.error( "no such sequence '{}' for stimulus '{}' ({})".format( sequence, stim, uniqueid)) raise KeyError trial_bonus = round(bonuses[stim][sequence], 2) # stored_bonus = round(trialdata['trialBonus'] / 100.0, 2) total_bonus = round(total_bonus + trial_bonus, 2) # if trial_bonus != stored_bonus: # current_app.logger.warning( # "bonus mismatch for {} on stim {} with sequence {}: {:f} (json) vs {:f} (js)".format( # uniqueid, stim, sequence, trial_bonus, stored_bonus)) user.bonus = total_bonus db_session.add(user) db_session.commit() resp = { "uniqueId": uniqueid, "bonusComputed": "success", "bonusAmount": total_bonus } except: current_app.logger.error("error processing bonus for {}".format(uniqueid)) current_app.logger.error(traceback.format_exc()) resp = { "uniqueId": uniqueid, "bonusComputed": "failure", "bonusAmount": total_bonus } current_app.logger.info(str(resp)) return jsonify(**resp)