import random from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) from .machine_learning_algo import prediction_generator doc = """ This is a standard 2-player trust game where the amount sent by player 1 gets tripled. The trust game was first proposed by Berg, Dickhaut, and McCabe (1995) . """ ############################################################ # definition of constant variables ############################################################ class Constants(BaseConstants): name_in_url = 'trust_machine_learning' players_per_group = 2 num_rounds = 1 payoff_stage = random.randint(1, 2) payoff_round = random.randint(1, num_rounds) relevant_decision = random.randint(1, 2) Treatment = 1 page_sequence = random.randint(1,10) payoff_factor = 0.05 show_up = 2 instructions_template = 'final_design_ak_beliefs/instructions.html' instructions_SPD = 'final_design_ak_beliefs/instructions_SPD.html' machine_learning_info = 'final_design_ak_beliefs/machine_learning_info.html' random_machine_info ='final_design_ak_beliefs/random_machine_info.html' # Initial amount allocated to each player endowment = 10 multiplier = 3 competitiveness_score = 'On a scale from 1(low) to 7(high):How competitive would you rate yourself?' openness_score = 'On a scale from 1(low) to 7(high):How open to new experiences would you rate yourself?' conscentiousness_score = 'On a scale from 1(low) to 7(high):How conscentious would you rate yourself?' agreeableness_score = 'On a scale from 1(low) to 7(high):How considerate and warm towards others would you rate yourself?' neuroticism_score = 'On a scale from 1(low) to 7(high):How easily are you upset/stressed?' extraversion_score = 'On a scale from 1(low) to 7(high):How outgoing are you?' younger_siblings = 'Do you have younger siblings?' older_siblings = 'Do you have older siblings?' financed_by_parents = 'Have you been financed by your parents during your studies/ apprenticeship?' mother_uni = 'Did your mother study at a university/applied university/college?' father_uni = 'Did your father study at university/applied university/college?' gender = 'What is your biological sex?' age = 'In which year were you born?' choicesLikert = [ [1, '1'], [2, '2'], [3, '3'], [4, '4'], [5, '5'], [6, '6'], [7, '7']] ageDict = {'age__1950-1960': 0, 'age__1960-1970': 0, 'age__1970-1980': 0, 'age__1980-1990': 0, 'age__1990-2000': 0, 'age__>2000': 0} choicesAge = [ [0, '<1960'], [1, '1961-1970'], [2, '1971-1980'], [3, '1981-1990'], [4, '1991-2000'], [5, 'age >2000']] choicesGender = [ [0, 'Female'], [1, 'Male']] choicesBoolean = [ [1, 'yes'], [0, 'No'], ] ############################################################ # Random assignment of subsession level, i.e. ROUND ############################################################ class Subsession(BaseSubsession): #keeping track of the current round #in round == 1 there will be no machine #in round == 2 there will be a machine #current_round = Constants.num_rounds #groupng and matching players randomly each round def creating_session(self): self.group_randomly() ############################################################ # GROUP LEVEL VARIABLES AND METHODS ############################################################ class Group(BaseGroup): #FOR METHOD ALL PLAYERS ARRIVE FUNCTIONS NEED TO BE CALLED VIA GROUPS #THEREFORE GROUP CALLS FUNCTION FOR EACH INDIVIDUAL PLAYER IN THE GROUP def set_payoffs(self): for p in self.get_players(): p.set_payoff() def functions(self): for p in self.get_players(): p.function() def functions_oppo(self): for p in self.get_players(): p.function_oppo() def set_payoffs_SPD(self): for p in self.get_players(): p.payoffs_SPD() def set_payoffs_trust_no_machine(self): for p in self.get_players(): p.payoffs_trust_no_machine() def set_payoffs_trust_machine(self): for p in self.get_players(): p.payoffs_trust_machine() def set_payoffs_trust_random_machine(self): for p in self.get_players(): p.payoffs_trust_random_machine() ############################################################ # SUBJECT LEVEL VARIABLES AND METHODS ############################################################ class Player(BasePlayer): ############################### # SEQUENTIAL PD ############################### # SPD DECISION FIRST MOVER sent_amount_SPD = models.IntegerField( choices=[[0, 'Option A (keep your 10 points)'], [10, 'Option B (send your 10 points)']], widget=widgets.RadioSelect, label='Please make a choice' ) # SPD DECISIONS SECOND MOVER # FM DEFECTS sent_back_amount_SPD_defect = models.IntegerField( choices=[[0, 'Option A (keep your 10 points)'], [10, 'Option B (send your 10 points)']], widget=widgets.RadioSelect, label='Please make a choice' ) #FM COOPERATE sent_back_amount_SPD_coop = models.IntegerField( choices=[[0, 'Option A (keep your 10 points)'], [10, 'Option B (send your 10 points)']], widget=widgets.RadioSelect, label='Please make a choice' ) ############################### # ML APPLICATION ############################### # RELEVANT VARIABLES FOR MACHINE LEARNING APPLICATION order = models.IntegerField(initial=Constants.payoff_stage) prediction = models.IntegerField(initial=-1) prediction_oppo = models.IntegerField(initial=-1) # prediction for random machine prediction_random = models.IntegerField(initial=-1) prediction_random_oppo = models.IntegerField(initial=-1) #payoffs SPD payoff_spd = models.IntegerField(initial=-1) role_spd = models.IntegerField(initial=-1) dec_opponent_spd = models.IntegerField(initial=-1) dec_spd = models.IntegerField(initial=-1) #payoffs Trust without machine payoff_trust_no_machine = models.IntegerField(initial=-1) role_trust_no_machine = models.IntegerField(initial=-1) dec_opponent_trust_no_machine = models.IntegerField(initial=-1) dec_trust_no_machine = models.IntegerField(initial=-1) oppo_return_no_machine = models.IntegerField(initial=-1) #payoffs Trust with machine payoff_trust_machine = models.IntegerField(initial=-1) role_trust_machine = models.IntegerField(initial=-1) dec_opponent_trust_machine = models.IntegerField(initial=-1) dec_trust_machine = models.IntegerField(initial=-1) oppo_return_machine_trust = models.IntegerField(initial=-1) oppo_return_machine_no_trust = models.IntegerField(initial=-1) #payoffs Trust with random machine payoff_trust_random_machine = models.IntegerField(initial=-1) role_trust_random_machine = models.IntegerField(initial=-1) dec_opponent_trust_random_machine = models.IntegerField(initial=-1) dec_trust_random_machine = models.IntegerField(initial=-1) oppo_return_random_machine_trust = models.IntegerField(initial=-1) oppo_return_random_machine_no_trust = models.IntegerField(initial=-1) #income income = models.FloatField(initial=-1) ############################### # ML QUESTIONNAIRE ############################### # QUESIONNAIRE ITEMS # NOTE: q_1 is an integer field for calucations in prediction dummy # impotant to write a function that transforms the types into the ones that the machine learning apliation needs # Dataset position in the KI model: row 1 q_1 = models.IntegerField(label=Constants.competitiveness_score, choices=Constants.choicesLikert, widget=widgets.RadioSelect) # Dataset position in the KI model: row 2 q_2 = models.IntegerField(label=Constants.openness_score, choices=Constants.choicesLikert, widget=widgets.RadioSelect) # Dataset position in the KI model: row 3 q_3 = models.IntegerField(label=Constants.conscentiousness_score, choices=Constants.choicesLikert, widget=widgets.RadioSelect) # Dataset position in the KI model: row 4 q_4 = models.IntegerField(label=Constants.agreeableness_score, choices=Constants.choicesLikert, widget=widgets.RadioSelect) # Dataset position in the KI model: row 5 q_5 = models.IntegerField(label=Constants.neuroticism_score, choices=Constants.choicesLikert, widget=widgets.RadioSelect) # Dataset position in the KI model: row 6 q_6 = models.IntegerField(label=Constants.extraversion_score, choices=Constants.choicesLikert, widget=widgets.RadioSelect) # Dataset position in the KI model: row 7 q_7 = models.IntegerField(label=Constants.younger_siblings, choices=Constants.choicesBoolean, widget=widgets.RadioSelect) # Dataset position in the KI model: row 8 q_8 = models.IntegerField(label=Constants.older_siblings, choices=Constants.choicesBoolean, widget=widgets.RadioSelect) # Dataset position in the KI model: row 9 q_9 = models.IntegerField(label=Constants.financed_by_parents, choices=Constants.choicesBoolean, widget=widgets.RadioSelect) # Dataset position in the KI model: row 18 q_10 = models.IntegerField(label=Constants.mother_uni, choices=Constants.choicesBoolean, widget=widgets.RadioSelect) # Dataset position in the KI model: row 17 q_11 = models.IntegerField(label=Constants.father_uni, choices=Constants.choicesBoolean, widget=widgets.RadioSelect) # Dataset position in the KI model in one hot end coding: row 11 - 16 q_12 = models.IntegerField(label=Constants.age, choices=Constants.choicesAge, widget=widgets.RadioSelect) # Dataset position in the KI model: row 10 q_13 = models.IntegerField(label=Constants.gender, choices=Constants.choicesGender, widget=widgets.RadioSelect) ############################### # TRUST GAME NO MACHINE ############################### #FIRST MOVER DECISIONS - TRUST GAME sent_amount = models.IntegerField( choices=[[0, 'Option 1 (keep your 10 points)'], [10, 'Option 2 (send your 10 points)']], widget=widgets.RadioSelect, label='Please make a choice' ) belief_no_machine = models.IntegerField(min=0, max=30, label='Please enter an integer between 0 and 30') sent_back_amount_no_machine = models.IntegerField( doc="""Amount sent back by P2 given P1 sent 1""", min=0, max=30, label='Please make a choice' ) ############################### # TRUST GAME WITH MACHINE ############################### sent_amount_with_machine = models.IntegerField( choices=[[0, 'Option 1 (keep your 10 points)'], [10, 'Option 2 (send your 10 points)']], widget=widgets.RadioSelect, label='Please make a choice' ) belief_machine_trust = models.IntegerField(min=0, max=30, label='Please enter an integer between 0 and 30') belief_machine_no_trust = models.IntegerField(min=0, max=30, label='Please enter an integer between 0 and 30') #SECOND MOVER DECISIONS - TRUST GAME sent_back_amount_machine_trust = models.IntegerField( doc="""Amount sent back by P2 given P1 sent 2""", min=0, max=30, label='Please make a choice' ) sent_back_amount_machine_no_trust = models.IntegerField( doc="""Amount sent back by P2 given P1 sent 3""", min=0, max=30, label='Please make a choice' ) ############################### # TRUST GAME WITH Random MACHINE ############################### sent_amount_with_random_machine = models.IntegerField( choices=[[0, 'Option 1 (keep your 10 points)'], [10, 'Option 2 (send your 10 points)']], widget=widgets.RadioSelect, label='Please make a choice' ) belief_random_machine_trust = models.IntegerField(min=0, max=30, label='Please enter an integer between 0 and 30') belief_random_machine_no_trust = models.IntegerField(min=0, max=30, label='Please enter an integer between 0 and 30') #SECOND MOVER DECISIONS - TRUST GAME sent_back_amount_random_machine_trust = models.IntegerField( doc="""Amount sent back by P2 given P1 sent 2""", min=0, max=30, label='Please make a choice' ) sent_back_amount_random_machine_no_trust = models.IntegerField( doc="""Amount sent back by P2 given P1 sent 3""", min=0, max=30, label='Please make a choice' ) #DETERMINING IDENTITY OF OPPONENT def other_player(self): return self.get_others_in_group()[0] #DUMMY FUNCTION FOR MAKING PREDICTIONS # 1 = TRUSTWORHTY # 0 = NOT TRUSTWORTHY #NOTE: DEPENDING ON THE NATURE OF INPUTS I NEED TO BE CAREFUL WITH CALCULATIONS def function(self): #if values are not passed on across rounds there will be a none value if self.q_12 == 0: xRaw = [self.q_1, self.q_2, self.q_3, self.q_4, self.q_5, self.q_6, self.q_7, self.q_8, self.q_9, self.q_13, 1, 0, 0, 0, 0, 0, self.q_10, self.q_11] if self.q_12 == 1: xRaw = [self.q_1, self.q_2, self.q_3, self.q_4, self.q_5, self.q_6, self.q_7, self.q_8, self.q_9, self.q_13, 0, 1, 0, 0, 0, 0, self.q_10, self.q_11] if self.q_12 == 2: xRaw = [self.q_1, self.q_2, self.q_3, self.q_4, self.q_5, self.q_6, self.q_7, self.q_8, self.q_9, self.q_13, 0, 0, 1, 0, 0, 0, self.q_10, self.q_11] if self.q_12 == 3: xRaw = [self.q_1, self.q_2, self.q_3, self.q_4, self.q_5, self.q_6, self.q_7, self.q_8, self.q_9, self.q_13, 0, 0, 0, 1, 0, 0, self.q_10, self.q_11] if self.q_12 == 4: xRaw = [self.q_1, self.q_2, self.q_3, self.q_4, self.q_5, self.q_6, self.q_7, self.q_8, self.q_9, self.q_13, 0, 0, 0, 0, 1, 0, self.q_10, self.q_11] if self.q_12 == 5: xRaw = [self.q_1, self.q_2, self.q_3, self.q_4, self.q_5, self.q_6, self.q_7, self.q_8, self.q_9, self.q_13, 0, 0, 0, 0, 0, 1, self.q_10, self.q_11] x = xRaw # prediction gives out a value y = prediction_generator(x) self.prediction = y ############################### # RANDOM MACHINE # 1. Selects a random stop iteration for the seeded random prediction # 2. Selects randomly from the set of variables # 3. Seeds the random generator with the value of selected variable # 4. Runs a while loop, in which the rand prediction is repeated # 5. While loop stops at stop iteration. In this way, we try to preserve true randomness and avoid determinism through the data ############################### LvarList = [self.q_1, self.q_2, self.q_3, self.q_4, self.q_5, self.q_6, self.q_7, self.q_8, self.q_9, self.q_10, self.q_11,self.q_12,self.q13] random_stop = random.randint(0,100) random_select = random.randint(0, 12) random_seed = LvarList[random_select] random.seed(random_seed) loop_counter= 0 while loop_counter < random_stop: y_rand = random.randint(0,1) loop_counter = loop_counter +1 self.prediction_random = y_rand # soft max #if y > 10: # self.prediction = 1 #else: # self.prediction = 0 def function_oppo(self): self.prediction_oppo = self.other_player().prediction self.prediction_random_oppo = self.other_player().prediction_random #??? def prediction_opponent(self): return self.other_player().prediction #payoffs SPD def payoffs_SPD(self): if self.id_in_group == 1: self.role_spd = 1 self.dec_spd = self.sent_amount_SPD if self.sent_amount_SPD == 0: self.dec_opponent_spd = self.other_player().sent_back_amount_SPD_defect self.payoff_spd = 10 + 2*self.other_player().sent_back_amount_SPD_defect elif self.sent_amount_SPD == 10: self.dec_opponent_spd = self.other_player().sent_back_amount_SPD_coop self.payoff_spd = 0 + 2*self.other_player().sent_back_amount_SPD_coop elif self.id_in_group == 2: self.dec_opponent_spd = self.other_player().sent_amount_SPD self.role_spd = 2 if self.other_player().sent_amount_SPD == 0: self.dec_spd = self.sent_back_amount_SPD_defect self.payoff_spd = 0 + (10-self.sent_back_amount_SPD_defect) elif self.other_player().sent_amount_SPD == 10: self.dec_spd = self.sent_back_amount_SPD_coop self.payoff_spd = 20 + (10 - self.sent_back_amount_SPD_coop) #payoffs trust no machine def payoffs_trust_no_machine(self): self.oppo_return_no_machine = self.other_player().sent_back_amount_no_machine if self.id_in_group == 1: self.role_trust_no_machine = 1 self.dec_trust_no_machine = self.sent_amount if self.sent_amount == 0: self.dec_opponent_trust_no_machine = 0 self.payoff_trust_no_machine = 10 elif self.sent_amount == 10: self.dec_opponent_trust_no_machine = self.other_player().sent_back_amount_no_machine self.payoff_trust_no_machine = self.other_player().sent_back_amount_no_machine if self.id_in_group == 2: self.dec_opponent_trust_no_machine = self.other_player().sent_amount self.role_trust_no_machine = 2 if self.other_player().sent_amount == 0: self.dec_trust_no_machine = 0 self.payoff_trust_no_machine = 0 elif self.other_player().sent_amount == 10: self.dec_trust_no_machine = self.sent_back_amount_no_machine self.payoff_trust_no_machine = 30 - self.sent_back_amount_no_machine #belief payoffs if (self.other_player().sent_back_amount_no_machine+3 >= self.belief_no_machine) and (self.other_player().sent_back_amount_no_machine-3 <= self.belief_no_machine): self.payoff_trust_no_machine = self.payoff_trust_no_machine + 4 #payoffs machine trust def payoffs_trust_machine(self): self.oppo_return_machine_trust = self.other_player().sent_back_amount_machine_trust self.oppo_return_machine_no_trust = self.other_player().sent_back_amount_machine_no_trust if self.id_in_group == 1: self.role_trust_machine = 1 self.dec_trust_machine = self.sent_amount_with_machine if self.sent_amount_with_machine == 0: self.dec_opponent_trust_machine = 0 self.payoff_trust_machine = 10 elif self.sent_amount_with_machine == 10: if self.prediction_oppo == 1: self.dec_opponent_trust_machine = self.other_player().sent_back_amount_machine_trust self.payoff_trust_machine = self.other_player().sent_back_amount_machine_trust elif self.prediction_oppo == 0: self.dec_opponent_trust_machine = self.other_player().sent_back_amount_machine_no_trust self.payoff_trust_machine = self.other_player().sent_back_amount_machine_no_trust elif self.id_in_group == 2: self.dec_opponent_trust_machine = self.other_player().sent_amount_with_machine self.role_trust_machine = 2 if self.other_player().sent_amount_with_machine == 0: self.dec_trust_machine = 0 self.payoff_trust_machine = 0 elif self.other_player().sent_amount_with_machine == 10: if self.prediction == 1: self.dec_trust_machine = self.sent_back_amount_machine_trust self.payoff_trust_machine = 30 - self.sent_back_amount_machine_trust elif self.prediction == 0: self.dec_trust_machine = self.sent_back_amount_machine_no_trust self.payoff_trust_machine = 30 - self.sent_back_amount_machine_no_trust #belief payoffs if (self.other_player().sent_back_amount_machine_trust + 3 >= self.belief_machine_trust) and (self.other_player().sent_back_amount_machine_trust - 3 <= self.belief_machine_trust): self.payoff_trust_machine = self.payoff_trust_machine + 2 if (self.other_player().sent_back_amount_machine_no_trust + 3 >= self.belief_machine_no_trust) and (self.other_player().sent_back_amount_machine_no_trust - 3 <= self.belief_machine_no_trust): self.payoff_trust_machine = self.payoff_trust_machine + 2 def payoffs_trust_random_machine(self): self.oppo_return_random_machine_trust = self.other_player().sent_back_amount_machine_trust self.oppo_return_random_machine_no_trust = self.other_player().sent_back_amount_machine_no_trust if self.id_in_group == 1: self.role_trust_random_machine = 1 self.dec_trust_random_machine = self.sent_amount_with_random_machine if self.sent_amount_with_random_machine == 0: self.dec_opponent_trust_random_machine = 0 self.payoff_trust_random_machine = 10 elif self.sent_amount_with_random_machine == 10: if self.prediction_random_oppo == 1: self.dec_opponent_trust_random_machine = self.other_player().sent_back_amount_random_machine_trust self.payoff_trust_random_machine = self.other_player().sent_back_amount_random_machine_trust elif self.prediction_random_oppo == 0: self.dec_opponent_trust_random_machine = self.other_player().sent_back_amount_random_machine_no_trust self.payoff_trust_random_machine = self.other_player().sent_back_amount_random_machine_no_trust elif self.id_in_group == 2: self.dec_opponent_trust_random_machine = self.other_player().sent_amount_with_random_machine self.role_trust_random_machine = 2 if self.other_player().sent_amount_with_random_machine == 0: self.dec_trust_random_machine = 0 self.payoff_trust_random_machine = 0 elif self.other_player().sent_amount_with_random_machine == 10: if self.prediction_random == 1: self.dec_trust_random_machine = self.sent_back_amount_random_machine_trust self.payoff_trust_random_machine = 30 - self.sent_back_amount_random_machine_trust elif self.prediction_random == 0: self.dec_trust_random_machine = self.sent_back_amount_random_machine_no_trust self.payoff_trust_random_machine = 30 - self.sent_back_amount_random_machine_no_trust #belief payoffs if (self.other_player().sent_back_amount_random_machine_trust + 3 >= self.belief_random_machine_trust) and (self.other_player().sent_back_amount_random_machine_trust - 3 <= self.belief_random_machine_trust): self.payoff_trust_random_machine = self.payoff_trust_random_machine + 2 if (self.other_player().sent_back_amount_random_machine_no_trust + 3 >= self.belief_random_machine_no_trust) and (self.other_player().sent_back_amount_random_machine_no_trust - 3 <= self.belief_random_machine_no_trust): self.payoff_trust_random_machine = self.payoff_trust_random_machine + 2 #SETTING PAYOFFS def set_payoff(self): self.income = ((self.payoff_trust_machine + self.payoff_trust_no_machine + self.payoff_spd)) * Constants.payoff_factor + Constants.show_up