from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ExtraModel, ) from otree.export import sanitize_for_csv import time author = 'Huanren Zhang' doc = """ Raven's progressive matrices test measuring cognitive ability """ class Constants(BaseConstants): name_in_url = 'ravens_lite' players_per_group = None answer_keys = [1, 1, 5, 2, 5, 8] num_rounds = 1 num_questions = len(answer_keys) minutes_given = int(num_questions/2) instructions_template = 'ravens_lite/Instructions.html' class Subsession(BaseSubsession): def creating_session(self): questions = [] for p in self.get_players(): for question_id in range(1,Constants.num_questions+1): questions.append(Question(player=p, question_id = question_id)) # Question.objects.create(player=p, **permutation) Question.objects.bulk_create(questions) print(len(Question.objects.all())) class Group(BaseGroup): pass class Player(BasePlayer): num_completed = models.IntegerField(initial=0) # record how many quesitons are completed so far num_correct = models.IntegerField(initial=0) loading_time = models.FloatField(initial=0) # decision time in seconds decision_time = models.FloatField() # decision time in seconds belief1 = models.IntegerField(min=0,max=Constants.num_questions) belief2 = models.IntegerField(min=1,max=20) def live_method(self, data): print(data) if data: if data['type'] == 'submission': question = Question.objects.filter(player=self, ans_correct=None)[0] # print(Question.objects.filter(player=self, ans_correct=None)) # displayed_timestamp = data['displayed_timestamp'] # answered_timestamp = data['answered_timestamp'] self.participant.vars['time_left'] -= data['time_used'] question.answer = int(data['answer']) question.decision_time = round((data['time_used']+self.participant.vars['time_used'] )*10)/10 question.ans_correct = question.answer == Constants.answer_keys[question.question_id-1] # print(type(question.answer),question.answer,type(Constants.answer_keys[question.question_id-1]), # Constants.answer_keys[question.question_id-1]) # print(question.question_id,question.ans_correct,question.answer,question.decision_time) question.save() self.num_completed += 1 self.loading_time = max(self.loading_time, round( (time.time() - self.participant.vars['display_timestamp'] - data['time_used']) * 10) / 10) self.participant.vars['time_used'] = 0 return elif data['type'] == 'unload': ## unload self.participant.vars['time_left'] -= data['time_used'] self.participant.vars['time_used'] += data['time_used'] # if self.num_completed == Constants.num_questions: # return {self.id_in_group: dict(is_finished=True)} self.participant.vars['display_timestamp'] = time.time() # for question in Question.objects.filter(player=self): # print(question.player.participant.code,question.question_id, question.ans_correct) question = Question.objects.filter(player=self, ans_correct=None)[0] # print('next one:',question.question_id,question.ans_correct) payload = dict(question_id=question.question_id,time_left=self.participant.vars['time_left']) return {self.id_in_group: payload} class Question(ExtraModel): player = models.Link(Player) question_id = models.IntegerField() answer = models.IntegerField() ans_correct = models.BooleanField() decision_time = models.FloatField() # decision time in seconds def custom_export(players): fields_to_export = ['question_id','answer','ans_correct','decision_time'] yield ['session', 'participant'] + fields_to_export # for trial in Question.objects.all(): # yield [trial.player.session.code, trial.player.participant.code] \ # + [sanitize_for_csv(getattr(trial, f)) for f in fields_to_export] for p in players: row_start = [p.session.code, p.participant.code] trials = Question.objects.filter(player=p) for trial in trials: if not(trial.answer is None): yield row_start + [sanitize_for_csv(getattr(trial, f)) for f in fields_to_export]