from otree.api import * import random import csv doc = """ This is the first session of the iq project. First Subjects have to do IQ test, ... """ # ############################################################################################################# # ########################################## MODELS ########################################################### # ############################################################################################################# class Constants(BaseConstants): name_in_url = 'iq_session1' players_per_group = None num_rounds = 1 IQChoices = [ [1, '1'], [2, '2'], [3, '3'], [4, '4'], [5, '5'], [6, '6'], [7, '7'], [8, '8'] ] # Here are the correct answers of the IQ test so we can check whether people do it right. correct_answer_IQ_1 = 5 correct_answer_IQ_2 = 6 correct_answer_IQ_3 = 6 correct_answer_IQ_4 = 4 correct_answer_IQ_5 = 5 correct_answer_IQ_6 = 3 correct_answer_IQ_7 = 2 correct_answer_IQ_8 = 6 correct_answer_IQ_9 = 8 correct_answer_IQ_10 = 2 # we have to set actual payment, these are just example numbers so far. base_payment = 14 extra_payoff = 6 days_single = 14 days_double = 28 # correct_answer_IQs = [1 for i in range(0, 10)] # correct_answer_IQs[5] += 3 # for answer in correct_answer_IQs: # print(answer) class Group(BaseGroup): pass class Subsession(BaseSubsession): pass class Player(BasePlayer): #Melessa_ID = models.IntegerField(min=10000, max=999999999999) Melessa_ID = models.StringField() answer_IQ_1 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) answer_IQ_2 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) answer_IQ_3 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) answer_IQ_4 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) answer_IQ_5 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) answer_IQ_6 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) answer_IQ_7 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) answer_IQ_8 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) answer_IQ_9 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) answer_IQ_10 = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], widget=widgets.RadioSelectHorizontal) # Sum of correct answers iq_result = models.IntegerField(initial=0) # Rank (from 1 to 10 ) that depends on the relative performance in the iq test Rank = models.IntegerField(initial=10) # Rank = 0 # Positive and Negative feedback can be between 0 and 3, negative feedback + positive feedback = 3 PositiveFeedback = models.IntegerField() NegativeFeedback = models.IntegerField() ConfirmPosFeedback = models.IntegerField(label='', min=0, max=3, blank=True) ConfirmNegFeedback = models.IntegerField(label='', min=0, max=3, blank=True) payoutrelevant1 = models.IntegerField(initial=10) payoutrelevant2 = models.IntegerField(initial=10) extraPayoff1 = models.IntegerField(initial=0) BeliefTopHalf1 = models.IntegerField( label="I think the likelihood (in percent) that I rank better than half of my ten group members is: ", max=100, min=0, initial=None, #blank=True ) details_beliefs_1_1=models.BooleanField(initial=False) # details_beliefs_1_2 = models.BooleanField(initial=False) #details_beliefs_1_3 = models.BooleanField(initial=False) #details_beliefs_1_4 = models.BooleanField(initial=False) details_feedback_1 = models.BooleanField(initial=False) BeliefBottomHalf1 = models.IntegerField() feedback_order = models.IntegerField() Belief1_1 = models.IntegerField(min=0, max=100, initial=None) Belief2_1 = models.IntegerField(min=0, max=100, initial=None) Belief3_1 = models.IntegerField(min=0, max=100, initial=None) Belief4_1 = models.IntegerField(min=0, max=100, initial=None) Belief5_1 = models.IntegerField(min=0, max=100, initial=None) Belief6_1 = models.IntegerField(min=0, max=100, initial=None) Belief7_1 = models.IntegerField(min=0, max=100, initial=None) Belief8_1 = models.IntegerField(min=0, max=100, initial=None) Belief9_1 = models.IntegerField(min=0, max=100, initial=None) Belief10_1 = models.IntegerField(min=0, max=100, initial=None) consent = models.BooleanField(initial=True) # ############################################################################################################# # ##################################### FUNCTIONS ####################################################### # ############################################################################################################# # This function determines whether or not the player receives extra payoff. This depends on his stated beliefs. # e use the binarized scoring rule # Only one out of all beliefs are payoff relevant. # This Function works as follows: First, I determine which belief of the 11 first ones is payout relevant, # then I determine the payoff according to the binarized scoring rule # THIS FUNCTION SHOULD WORK FINE def set_extrapayoff1(player: Player): player.payoutrelevant1 = random.randint(0, 10) if player.payoutrelevant1 == 0: if player.Rank < 6 and player.BeliefTopHalf1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank > 5 and player.BeliefTopHalf1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 1: if player.Rank == 1 and player.Belief1_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 1 and player.Belief1_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 2: if player.Rank == 2 and player.Belief2_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 2 and player.Belief2_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 3: if player.Rank == 3 and player.Belief3_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 3 and player.Belief3_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 4: if player.Rank == 4 and player.Belief4_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 4 and player.Belief4_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 5: if player.Rank == 5 and player.Belief5_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 5 and player.Belief5_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 6: if player.Rank == 6 and player.Belief6_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 6 and player.Belief6_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 7: if player.Rank == 7 and player.Belief7_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 7 and player.Belief7_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 8: if player.Rank == 8 and player.Belief8_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 8 and player.Belief8_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 9: if player.Rank == 9 and player.Belief9_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 9 and player.Belief9_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 10: if player.Rank == 10 and player.Belief10_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.Rank != 10 and player.Belief10_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 # This function counts the correct answers from a player in the iq test # and gives back the result (iq_result) = (sum of correct answers) def set_iq_result(player): # player.iq_result = 0 if player.answer_IQ_1 == Constants.correct_answer_IQ_1: player.iq_result += 1 if player.answer_IQ_2 == Constants.correct_answer_IQ_2: player.iq_result += 1 if player.answer_IQ_3 == Constants.correct_answer_IQ_3: player.iq_result += 1 if player.answer_IQ_4 == Constants.correct_answer_IQ_4: player.iq_result += 1 if player.answer_IQ_5 == Constants.correct_answer_IQ_5: player.iq_result += 1 if player.answer_IQ_6 == Constants.correct_answer_IQ_6: player.iq_result += 1 if player.answer_IQ_7 == Constants.correct_answer_IQ_7: player.iq_result += 1 if player.answer_IQ_8 == Constants.correct_answer_IQ_8: player.iq_result += 1 if player.answer_IQ_9 == Constants.correct_answer_IQ_9: player.iq_result += 1 if player.answer_IQ_10 == Constants.correct_answer_IQ_10: player.iq_result += 1 # This function ranks players in a group according to their result # THERE IS A PROBLEM WITH THIS FUNCTION BECAUSE OF GROUP AS AN ARGUMENT -> Fehlermeldung 'missing arguments ... ' # but I dont know anymore where it could be missing .... def set_ranking(player): with open('iq_session1/static/pilot_iq_results.csv', 'r') as df: data = csv.DictReader(df) player.Rank = 1 groupmembers = random.sample(range(1, 150), k=9) for row in data: for g in groupmembers: if g == int(row['id']): if player.iq_result < int(row['iq_result']): player.Rank = player.Rank + 1 elif player.iq_result == int(row['iq_result']): luck = random.choices([0, 1], k=1) if luck == 1: player.Rank = player.Rank + 1 # This function selects three other players from the group and compares the rank of the player to their ranks. # Then it gives feedback accordingly. # HIS FUNCTION SHOULD WORK FINE - I TRIED IT OUT :) # Compared to three other participants, positive feedback is the number of others who are ranked worse. def set_PositiveFeedback(player): if player.Rank == 1: player.PositiveFeedback = 3 elif player.Rank == 2: player.PositiveFeedback = 0 # I don't actually compare them with the other players as it is easier without the interaction # and we know which ranks are possible newlist = random.sample([100, 10, 30, 40, 50, 60, 70, 80, 90], k=3) for m in newlist: if m > 20: player.PositiveFeedback += 1 elif player.Rank == 3: player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 60, 70, 80, 90], k=3) for m in newlist: if m > 30: player.PositiveFeedback += 1 elif player.Rank == 4: player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 30, 50, 60, 70, 80, 90], k=3) for m in newlist: if m > 40: player.PositiveFeedback += 1 elif player.Rank == 5: player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 30, 60, 70, 80, 90], k=3) for m in newlist: if m > 50: player.PositiveFeedback += 1 elif player.Rank == 6: player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 30, 70, 80, 90], k=3) for m in newlist: if m > 60: player.PositiveFeedback += 1 elif player.Rank == 7: player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 60, 30, 80, 90], k=3) for m in newlist: if m > 70: player.PositiveFeedback += 1 elif player.Rank == 8: player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 60, 70, 30, 90], k=3) for m in newlist: if m > 80: player.PositiveFeedback += 1 elif player.Rank == 9: player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 60, 70, 80, 30], k=3) for m in newlist: if m > 90: player.PositiveFeedback += 1 else: player.PositiveFeedback = 0 # This function defines the number of negative feedback individuals get def set_NegativeFeedback(player): player.NegativeFeedback = 3 - player.PositiveFeedback # ################################################################################################################## # ################################# PAGEs #################################################### # ################################################################################################################## class GeneralInstructions(Page): form_model = 'player' form_fields = ['Melessa_ID'] @staticmethod def before_next_page(player: Player, timeout_happened): player.participant.melessa_id = player.Melessa_ID class InstructionIQ(Page): pass class ExampleIQ(Page): pass # On this page people do the iq test. I put it all on one page and included timeout and IT WORKS :)) class RavenAll(Page): page_name = "Task" form_model = 'player' form_fields = ['answer_IQ_1', 'answer_IQ_2', 'answer_IQ_3', 'answer_IQ_4', 'answer_IQ_5', 'answer_IQ_6', 'answer_IQ_7', 'answer_IQ_8', 'answer_IQ_9', 'answer_IQ_10'] timeout_seconds = 600 @staticmethod def before_next_page(player, timeout_happened): return dict( rank=set_iq_result(player) ) # Here we explain the Rankings class Ranking(Page): @staticmethod def before_next_page(player, timeout_happened): return dict( rank=set_ranking(player) ) class BeliefInstructions1a(Page): form_model = 'player' form_fields = ['details_beliefs_1_1'] class BeliefInstructions1b(Page): @staticmethod def is_displayed(player: Player): return player.details_beliefs_1_1==True # Here we elicit subjects belief that they are in the top half class BelievesTopHalf1(Page): form_model = 'player' form_fields = ['BeliefTopHalf1'] # on this page we want to elicit probabilistic beliefs class BeliefDistributionTopHalf1(Page): form_model = 'player' form_fields = ['Belief1_1', 'Belief2_1', 'Belief3_1', 'Belief4_1', 'Belief5_1',] # This function should give an error message if the probabilities don't add up to "BeliefsTopHalf". # Subjects should only be able to continue if the numbers add up, otherwise its contradictory # But additional to the error message we should generally add up the numbers for them to see. # I DIDNT FIGURE OUT HOW TO DO THIS UNTIL NOW .... @staticmethod def error_message(player:Player, values): # if (values['Belief1_1'] == None or values['Belief2_1'] == None or values['Belief3_1'] == None or values['Belief4_1'] == None or values['Belief5_1'] == None) and values['details_beliefs_1_3'] == False: # return 'You need to fill in your guess' if values['Belief1_1'] != None and values['Belief2_1'] != None and values['Belief3_1'] != None and values['Belief4_1'] != None and values['Belief5_1'] != None: summe = values['Belief1_1'] + values['Belief2_1'] + values['Belief3_1'] + values['Belief4_1'] + values[ 'Belief5_1'] if summe != player.BeliefTopHalf1: return 'The sum is {}. The numbers must add up to {}.'.format(summe, player.BeliefTopHalf1) # Now we have the same for probabilistic beliefs in the lower half. class BeliefDistributionBottomHalf1(Page): form_model = 'player' form_fields = ['Belief6_1', 'Belief7_1', 'Belief8_1', 'Belief9_1', 'Belief10_1'] @staticmethod def vars_for_template(player: Player): return dict( BeliefBottomHalf1=100 - player.BeliefTopHalf1 ) @staticmethod def error_message(player:Player, values): # if (values['Belief6_1'] == None or values['Belief7_1'] == None or values['Belief8_1'] == None or values[ # 'Belief9_1'] == None or values['Belief10_1'] == None) and values['details_beliefs_1_4'] == False: # return 'You need to fill in your guess' summe = values['Belief6_1'] + values['Belief7_1'] + values['Belief8_1'] + values['Belief9_1'] + values[ 'Belief10_1'] if summe != 100 - player.BeliefTopHalf1: return 'The sum is {}. The numbers must add up to {}.'.format(summe, 100 - player.BeliefTopHalf1) @staticmethod def before_next_page(player:Player, timeout_happened): player.feedback_order = random.randint(0,1) # 0 -> negative feedback first. 1 -> positive feedback first. # Here we give people the feedback class FeedbackGivenNegFirst(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 0 @staticmethod def vars_for_template(player:Player): return dict ( PositiveFeedback = set_PositiveFeedback(player), NegativeFeedback = set_NegativeFeedback(player), ) @staticmethod def before_next_page(player, timeout_happened): return dict( extraPayoff1 = set_extrapayoff1(player), ) class FeedbackGivenPosFirst(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 1 @staticmethod def vars_for_template(player:Player): return dict ( PositiveFeedback = set_PositiveFeedback(player), NegativeFeedback = set_NegativeFeedback(player), ) @staticmethod def before_next_page(player, timeout_happened): return dict( extraPayoff1 = set_extrapayoff1(player), ) # Here we let people repeat their feedback. class FeedbackRepetitionPosFirsta(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 1 form_model = 'player' form_fields = ['ConfirmNegFeedback', 'ConfirmPosFeedback','details_feedback_1'] @staticmethod def error_message(player: Player, values): if (values['ConfirmNegFeedback'] == None or values['ConfirmPosFeedback'] == None) and values['details_feedback_1']==False: return 'You need to fill in the fields' class FeedbackRepetitionNegFirsta(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 0 form_model = 'player' form_fields = ['ConfirmNegFeedback', 'ConfirmPosFeedback','details_feedback_1'] @staticmethod def error_message(player: Player, values): if (values['ConfirmNegFeedback'] == None or values['ConfirmPosFeedback'] == None) and values['details_feedback_1']==False: return 'You need to fill in the fields' class FeedbackRepetitionNegFirstb(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 0 and player.details_feedback_1==True form_model = 'player' form_fields = ['ConfirmNegFeedback', 'ConfirmPosFeedback'] @staticmethod def error_message(player: Player, values): if values['ConfirmNegFeedback']==None or values['ConfirmPosFeedback']==None: return 'You need to fill in the fields' class FeedbackRepetitionPosFirstb(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 1 and player.details_feedback_1==True form_model = 'player' form_fields = ['ConfirmNegFeedback', 'ConfirmPosFeedback'] @staticmethod def error_message(player: Player, values): if values['ConfirmNegFeedback']==None or values['ConfirmPosFeedback']==None: return 'You need to fill in the fields' # Now all the beliefs Stuff is repeated exactly (only minor chang in the wording if instructions) class Demographics(Page): form_model = 'player' form_fields = ['gender', 'age', 'studies', 'degree', 'field', 'english', 'attention_check_1'] class Big5(Page): form_model = 'player' form_fields = [ 'item1A', 'item1B', 'item1C', 'item1D', 'item1E', 'item1F', 'item1G', 'item1H', 'item1I', 'item1J' ] # We might not show this pag, but it could be useful to check ... # class LastPage(Page): # def vars_for_template(player: Player): # extraPayoff1 = set_extraPayoff1(player) # extraPayoff2 = set_extraPayoff2(player) # payoff = set_Payoff_Session1(player) # return { # "ExtraPayoff1": player.extraPayoff1, # "ExtraPayoff2": player.extraPayoff2, # "Payoff": player.payoff, # } class LastPage(Page): pass class Raven(Page): pass class Part1(Page): pass class Part2(Page): pass class Consent(Page): form_model = 'player' form_fields = [ 'consent' ] @staticmethod def error_message(player:Player, values): if values['consent'] == False: return 'You need to give consent to participate in this study.' page_sequence = [ #Consent, GeneralInstructions, Part1, InstructionIQ, ExampleIQ, RavenAll, Part2, Ranking, BeliefInstructions1a, BeliefInstructions1b, BelievesTopHalf1, #BelievesTopHalf1b, BeliefDistributionTopHalf1, #BeliefDistributionTopHalf1b, BeliefDistributionBottomHalf1, #BeliefDistributionBottomHalf1b, FeedbackGivenNegFirst, FeedbackGivenPosFirst, FeedbackRepetitionNegFirsta, FeedbackRepetitionNegFirstb, FeedbackRepetitionPosFirsta, FeedbackRepetitionPosFirstb, #Demographics, #Big5, #LastPage, ]