from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random import itertools import numpy as np import math import pandas as pd author = 'Elisa Macchi' doc = """ Experiment 1 : Test how body mass affects perceived income """ class Constants(BaseConstants): # Session: name_in_url = 'experiment_1' players_per_group = None num_rounds = 1 pilot = 'yes' n_players = 3 n_questions = 8 # Payoffs: bonus = c(4) # Image info read from csv: df = pd.read_csv('experiment_1/image_info.csv') img_f = ['1_thin.jpg', '2_thin.jpg', '3_thin.jpg'] img_o = ['1_original.jpg', '2_original.jpg', '3_original.jpg'] img_t = ['1_fat.jpg', '2_fat.jpg', '3_fat.jpg'] images = img_f + img_o + img_t age = [31, 40, 52] gender = [1, 0, 1] # Endowment (trust and dictator game): endowment = c(5) # Multiplier trust game: multiplier = 3 # Correct answers to understanding questions: correct_answers = {'uq1': 3, 'uq2': 2, 'uq3': 2} class Subsession(BaseSubsession): def creating_session(self): # randomize to treatments treatments = itertools.cycle(['original', 'thin', 'fat']) for p in self.get_players(): p.info = random.choice([True, False]) # Randomize whether additional info if p.info: # Randomize whether car/no car info. p.car = random.choice([1, 2]) else: p.car = 0 p.treatment = next(treatments) if p.treatment == "fat": imgs = itertools.cycle(Constants.img_f) imgs_age = itertools.cycle(Constants.age) imgs_gen = itertools.cycle(Constants.gender) p.participant.vars['images'] = next(imgs) p.image_url = next(imgs) p.image_age = next(imgs_age) p.image_gender = next(imgs_gen) if p.treatment == "original": imgs = itertools.cycle(Constants.img_o) imgs_age = itertools.cycle(Constants.age) imgs_gen = itertools.cycle(Constants.gender) p.participant.vars['images'] = next(imgs) p.image_url = next(imgs) p.image_age = next(imgs_age) p.image_gender = next(imgs_gen) if p.treatment == "thin": imgs = itertools.cycle(Constants.img_t) imgs_age = itertools.cycle(Constants.age) imgs_gen = itertools.cycle(Constants.gender) p.participant.vars['images'] = next(imgs) p.image_url = next(imgs) p.image_age = next(imgs_age) p.image_gender = next(imgs_gen) class Group(BaseGroup): def set_payoffs(self): all_players = self.get_players() for image in Constants.images: # group of players with the same image players = [p for p in all_players if p.participant.vars['images'] == image] # n players per group n = 0 for p in all_players: if p.participant.vars['images'] == image: n += 1 if n > 0: # Robust Bayesian Truth Serum for one picture: choices = [8, 9, 10] # option j = jointly 8,9,10 # Build X_bar_j: the proportion of the n responders endorsing option j as their belief i = [0, 0, 0, 0, 0, 0, 0, 0] for player in players: for choice in choices: if player.b1 == choice: i[0] += 1 if player.b2 == choice: i[1] += 1 if player.b3 == choice: i[2] += 1 if player.b4 == choice: i[3] += 1 if player.b5 == choice: i[4] += 1 if player.b6 == choice: i[5] += 1 if player.b7 == choice: i[6] += 1 if player.b8 == choice: i[7] += 1 if n > 0: x_bar = [item/n for item in i] else: x_bar = [0] * Constants.n_questions # Build Y_bar_j: the geometric mean of the endorsement predictions for option j # p = array of LOG prediction of the proportion of participants endorsing option j # (each row is one player, each column is one question) p = [] for i in range(n): p.append([0] * Constants.n_questions) j = 0 for player in players: p[j][0] = player.b1 / 10 p[j][1] = player.b2 / 10 p[j][2] = player.b3 / 10 p[j][3] = player.b4 / 10 p[j][4] = player.b5 / 10 p[j][5] = player.b6 / 10 p[j][6] = player.b7 / 10 p[j][7] = player.b8 / 10 j += 1 print('predictions') print(p) p = np.log(p) sum_p = [sum(column) for column in zip(*p)] y_bar = [np.exp(i) for i in np.divide(sum_p, n)] # score_j: score for each question score_q = [0,0,0,0,0,0,0,0] for i in range(Constants.n_questions): score_q[i] = np.log(x_bar[i] / y_bar[i]) # Final iscore for each player, by question!!! iscore = [] for i in range(Constants.n_questions): iscore.append([0] * n) for player in range(n): iscore[0][player] = score_q[0] + x_bar[0] + x_bar[0] * np.log(p[player][0] / x_bar[0]) iscore[1][player] = score_q[1] + x_bar[1] + x_bar[1] * np.log(p[player][1] / x_bar[1]) iscore[2][player] = score_q[2] + x_bar[2] + x_bar[2] * np.log(p[player][2] / x_bar[2]) iscore[3][player] = score_q[3] + x_bar[3] + x_bar[3] * np.log(p[player][3] / x_bar[3]) iscore[4][player] = score_q[4] + x_bar[4] + x_bar[4] * np.log(p[player][4] / x_bar[4]) iscore[5][player] = score_q[5] + x_bar[5] + x_bar[5] * np.log(p[player][5] / x_bar[5]) iscore[6][player] = score_q[6] + x_bar[6] + x_bar[6] * np.log(p[player][6] / x_bar[6]) iscore[7][player] = score_q[7] + x_bar[7] + x_bar[7] * np.log(p[player][6] / x_bar[7]) j = 0 for player in players: player.iscore1 = iscore[0][j] player.iscore2 = iscore[1][j] player.iscore3 = iscore[2][j] player.iscore4 = iscore[3][j] player.iscore5 = iscore[4][j] player.iscore6 = iscore[5][j] player.iscore7 = iscore[6][j] player.iscore8 = iscore[7][j] player.participant.vars['iscore1'] = player.iscore1 player.participant.vars['iscore2'] = player.iscore2 player.participant.vars['iscore3'] = player.iscore3 player.participant.vars['iscore4'] = player.iscore4 player.participant.vars['iscore5'] = player.iscore5 player.participant.vars['iscore6'] = player.iscore6 player.participant.vars['iscore7'] = player.iscore7 player.participant.vars['iscore8'] = player.iscore8 j += 1 # Define bonus winners (best in group!) top_one_third_q1 = np.argsort(iscore[0])[-1:] top_one_third_q2 = np.argsort(iscore[1])[-1:] top_one_third_q3 = np.argsort(iscore[2])[-1:] top_one_third_q4 = np.argsort(iscore[3])[-1:] top_one_third_q5 = np.argsort(iscore[4])[-1:] top_one_third_q6 = np.argsort(iscore[5])[-1:] top_one_third_q7 = np.argsort(iscore[6])[-1:] top_one_third_q8 = np.argsort(iscore[7])[-1:] top_one_third = [[top_one_third_q1], [top_one_third_q2], [top_one_third_q3], [top_one_third_q4], [top_one_third_q5], [top_one_third_q6], [top_one_third_q7], [top_one_third_q8]] for p in players: p.total_bonus = 0 for question in range(Constants.n_questions): if p.id_in_group in top_one_third[question]: p.total_bonus += Constants.bonus winners = np.unique(top_one_third) for p in players: p.payoff = p.total_bonus if p.id_in_group in winners: p.is_top_one_third = True class Player(BasePlayer): # Treatment: treatment = models.StringField() image_url = models.StringField() order = models.StringField() age_portrait = models.IntegerField() gender_portrait = models.BooleanField() educ_portrait = models.BooleanField() # Car/No Car variation: info = models.BooleanField() car = models.IntegerField() # Images Characteristics image_age = models.IntegerField() image_gender = models.BooleanField() # Understanding Questions: cp_error = models.BooleanField() # set to True when a person answers erroneously at a comprehension page uq1 = models.IntegerField( choices=[[1, 'It is irrelevant because all the pictures have been blurred and cannot be distinguished.'], [2, 'It does not determine in any way your payment.'], [3, 'All of the above.'], ], widget=widgets.RadioSelect, label="The fact that some pictures are original and some are not:") uq2 = models.IntegerField( choices=[[1, 'No additional bonus.'], [2, 'A $0.5 bonus for each question, that is maximum bonus of $2, on top of your base pay.'], [3, 'A maximum bonus of $0.5, on top of your base pay.'], ], widget=widgets.RadioSelect, label="By answering the questions you have the chance to win:") uq3 = models.IntegerField( choices=[[1, 'You try to game the experiment.'], [2, 'You answer what you really think.'], [3, 'You answer randomly.'], ], widget=widgets.RadioSelect, label="Your chances to win the bonus are highest if:") # Beliefs: b1 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, label=''' How would you rate this person's income? ''') # income b2 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, label=''' How would you rate this person's health? ''') # income b3 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, label=''' How likely would you be to go on a date with this person? ''') # income b4 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, label=''' How would you rate this person attractiveness? ''') # income b5 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, label=''' How long do you think this person will live? ''') # longevity b6 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, label=''' How likely is this person to yield to temptation, according to you? ''') # longevity b7 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, label=''' How likely is this person to be hard-working, according to you? ''') # longevity b8 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, label=''' How would you rate this person's intelligence? ''') # intelligence # Perception: q1 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, verbose_name=''' How many would think this person is very rich? ''') # income q2 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, verbose_name=''' How many would think this person is very healthy? ''') # health q3 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, verbose_name=''' How many would go on a date with this person? ''') # dating q4 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, verbose_name=''' How many people would consider this person very attractive? ''') # attractiveness q5 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, verbose_name=''' How many people would think this person will live a long life? ''') # longevity q6 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, verbose_name=''' How many people would think this person easily yields to temptation? ''') # self-control q7 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, verbose_name=''' How many people would consider this person hard-working? ''') # work ethos q8 = models.IntegerField(choices=[[0, ""], [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], [8, ""], [9, ""], [10, ""]], widget=widgets.RadioSelectHorizontal, default=None, verbose_name=''' How many people would consider this person very smart? ''') # intelligence # Payments def role(self): if self.image_url == '1_thin.jpg': return '1_thin.jpg' if self.image_url == '2_thin.jpg': return '2_thin.jpg' if self.image_url == '3_thin.jpg': return '3_thin.jpg' if self.image_url == '1_original.jpg': return '1_original.jpg' if self.image_url == '2_original.jpg': return '2_original.jpg' if self.image_url == '3_original.jpg': return '3_original.jpg' if self.image_url == '1_fat.jpg': return '1_fat.jpg' if self.image_url == '2_fat.jpg': return '2_fat.jpg' if self.image_url == '3_fat.jpg': return '3_fat.jpg' iscore1 = models.FloatField() iscore2 = models.FloatField() iscore3 = models.FloatField() iscore4 = models.FloatField() iscore5 = models.FloatField() iscore6 = models.FloatField() iscore7 = models.FloatField() iscore8 = models.FloatField() is_top_one_third = models.BooleanField() total_bonus = models.CurrencyField()