import time from otree.api import * import random doc = """ A bargaining game without instruction and fancy interface """ class Constants(BaseConstants): ''' For testing, num_round: line 17, 18; time of page: line 60-62; ''' name_in_url = 'secondary_bargaining' players_per_group = 2 # (initial variable) the size of bargaining group num_rounds_phase1 = 4 # the number of rounds in the first treatment (complete information) num_rounds_phase2 = 4 # the number of rounds in the second phase (incomplete information) num_rounds = int(num_rounds_phase1 + num_rounds_phase2) # (initial variable) the number of rounds in total num_subjects = 24 # (initial variable) the number of players in this session players_per_mgroup = 6 # the number of players in each matching group num_mgroup = int(num_subjects/players_per_mgroup) # the number of matching groups in this session # parameters of the game pg_cost = 2 # the cost (threshold) of the public good pg_valueH = 3 # the high type value of the public good pg_valueL = 1 # the low type value of the public good conflict = -1 # players' payoff when there is a conflict prob_H = 0.5 # the probability of players being a high type mg_assignment = list(range(1, num_subjects + 1)) random.shuffle(mg_assignment) # this is the assignment of matching group # the first 6 numbers in this list is the first matching group, then the second, third and fourth matching group num_instructionpage = 9 # the number of instruction pages num_instructionpage2 = 6 # the number of instruction pages for phase 2 # the solution to the control questions quiz_TF_1_solution = 1 # the solution to the 1st, 2nd and 3rd True or False quiz quiz_TF_2_solution = 0 quiz_TF_3_solution = 1 quiz_Bargain_1_solution = 3 # multiple choice 1st and 2nd quiz_Bargain_2_solution = 4 quiz_Bargain_3_solution = 1 quiz_Results_1_solution = 3 # results display quiz_Results_2_solution = 1 quiz_phase2 = 0 # the calculation of payoff num_rounds_choseneachphase = 2 # the number of rounds chosen each treatment calculated into payoff participation_fee = 4 # in euros transfer_rate = 2 # 2 tokens = 1 euro # timeout limit for some pages time_information = 30 # time limit: second time_bargaininitial = 45 time_bargainafter = 15 # time_results = 15 : no limit on result display # Questionnaire gender = {1: "Male", 2: "Female", 3: "Non-Binary", 4: "Prefer not to say"} major = {1: "Math, Physics", 2: "Econ, Stats", 3: "Business & Management", 4: "Biology, Chemistry & other Natural sciences", 5: "Engineering & Architecture", 6: "Languages", 7: "Classical Studies", 8: "Arts", 9: "Psychology, Sociology & other social sciences", 10: "Law & Political Sciences", 11: "Medicine & related disciplines", 12: "Others"} nationality = {1: "Italian", 2: "Other European countries", 3: "non European countries"} risk_sure_payment_initial = 160 # in the multiple choices between changing sure payment and fixed lottery - the initial sure_payment fairness_preference = {1: "Scale of strongly disagree", 2: "Somewhat disagree", 3: "Neither agree nor disagree", 4: "Somewhat agree", 5: "Strongly agree"} # Templates Information_template = 'Information_for_display.html' Bargaining_You = 'Bargaining_You.html' Bargaining_YourMatch = 'Bargaining_YourMatch.html' HistoryBox = 'HistoryBox.html' Quiz_Page1_TF = 'Quiz_phase1_page01_TF.html' Quiz_Page2_TF = 'Quiz_phase1_page02_TF.html' Quiz_Page3_Bargaining1 = 'Quiz_phase1_page03_Bargaining1.html' Quiz_Page4_Bargaining1_solution = 'Quiz_phase1_page04_Bargaining1_solution.html' Quiz_Page5_Bargaining2 = 'Quiz_phase1_page05_Bargaining2.html' Quiz_Page6_Bargaining2_solution = 'Quiz_phase1_page06_Bargaining2_solution.html' Quiz_Page7_Bargaining3 = 'Quiz_phase1_page07_Bargaining3.html' Quiz_Page8_Bargaining3_solution = 'Quiz_phase1_page08_Bargaining3_solution.html' Quiz_Page9_Results1 = 'Quiz_phase1_page09_Results1.html' Quiz_Page10_Results1_solution = 'Quiz_phase1_page10_Results1_solution.html' Quiz_Page11_Results2 = 'Quiz_phase1_page11_Results2.html' Quiz_Page12_Results2_solution = 'Quiz_phase1_page12_Results2_solution.html' Quiz_endpage = 'Quiz_phase1_page13_endpage.html' Quiz2_Page1_TF = 'Quiz_phase2_page01_TF.html' Quiz2_Page2_TF = 'Quiz_phase2_page02_TF.html' Ques01 = 'Questionnaire_p01.html' Ques02 = 'Questionnaire_p02.html' Ques03 = 'Questionnaire_p03.html' Ques04 = 'Questionnaire_p04.html' Ques05 = 'Questionnaire_p05.html' Ques06 = 'Questionnaire_p06.html' Ques07 = 'Questionnaire_p07.html' Ques08 = 'Questionnaire_p08.html' Ques09 = 'Questionnaire_p09.html' Ques10 = 'Questionnaire_p10.html' Ques11 = 'Questionnaire_p11.html' Ques12 = 'Questionnaire_p12.html' Ques13 = 'Questionnaire_p13.html' Ques14 = 'Questionnaire_p14.html' class Subsession(BaseSubsession): chosen_phase1_1 = models.IntegerField() chosen_phase1_2 = models.IntegerField() chosen_phase2_1 = models.IntegerField() chosen_phase2_2 = models.IntegerField() chosen_guess = models.IntegerField() class Group(BaseGroup): # Overall bargaining process total_value = models.IntegerField() # players' total value of the pg total_propose = models.IntegerField() # players' total final proposal agreement = models.BooleanField( # whether players have reached an agreement in this round initial=False ) conflict = models.BooleanField( # whether players have reached a conflict in this round initial=False ) # initial bargaining stage total_propose1 = models.IntegerField() # the sum of players' proposal at the initial stage agreement1 = models.BooleanField( # whether players reach the agreement at the initial stage initial=False ) random_setpayoff1 = models.FloatField() # the random number generated for selecting the final contribution plan at the initial stage # second bargaining stage total_propose2 = models.IntegerField() # the sum of players' proposal at the second stage agreement2 = models.BooleanField( # whether the players reach the agreement at the second stage initial=False ) conflict2 = models.BooleanField( # whether the players reach the conflict at the second stage initial=False ) random_setpayoff2 = models.FloatField() # the random number generated for selecting the final contribution plan at the second stage # Third bargaining stage total_propose3 = models.IntegerField() # the sum of players' proposal at the third stage agreement3 = models.BooleanField( # whether the players reach the agreement at the third stage initial=False ) conflict3 = models.BooleanField( # whether the players reach the conflict at the third stage initial=False ) random_setpayoff3 = models.FloatField() # the random number generated for selecting the final contribution plan at the third stage class Player(BasePlayer): IDnumber = models.StringField( label="Please enter your ID code: " ) matching_group = models.IntegerField() # the number of the matching group this player belongs to round_number_phase = models.IntegerField() # the round number for each phase random_setvalue = models.FloatField() # the random number generated to set players' value value = models.IntegerField() # the pg's value to the player value_match = models.IntegerField() # the value of player's match in this round propose = models.IntegerField() # player's final proposal before this round's bargaining is over propose_match = models.IntegerField() # player's match's final proposal before this round's bargaining is over contribution = models.IntegerField() # player's final contribution (if agreement; else, an outlier value, -99) contribution_match = models.IntegerField() # player's match's final contribution (if agreement) profit = models.IntegerField() # player's profit in this round profit_match = models.IntegerField() # player's match's profit in this round agreement = models.BooleanField( initial=False ) # whether there is an agreement reached in this round conflict = models.BooleanField( initial=False ) # whether there is a conflict reached in this round proposal_accepted = models.BooleanField() # these 2 variables are to move group.agreement/conflict to player.() so that we can use is_displayed for page value_match_guess = models.IntegerField( # player's guess on her match's value in this round initial=-1 ) # the instruction page pagenumber = models.IntegerField( # the page number of the instruction initial=1 ) '''pagenumber2 = models.IntegerField( # the page number of the instruction in phase 2 initial=1 )''' # since it's also fine to still use pagenumber in phase 2's instruction, so this one is not used quizpagenumber = models.IntegerField( # the pagenumber in the control question part initial=1 ) quiz_TF_1 = models.IntegerField( initial=-1 ) # the player's quiz answer to the 1st, 2nd and 3rd True or False quiz quiz_TF_2 = models.IntegerField( initial=-1 ) quiz_TF_3 = models.IntegerField( initial=-1 ) quiz_Bargain_1 = models.IntegerField( initial=-1 ) # multiple choice on bargaining process quiz_Bargain_2 = models.IntegerField( initial=-1 ) quiz_Bargain_3 = models.IntegerField( initial=-1 ) quiz_Results_1 = models.IntegerField( initial=-1 ) # multiple choice on results display quiz_Results_2 = models.IntegerField( initial=-1 ) quiz_phase2 = models.IntegerField( initial=-1 ) # the only TF in plase 2 quiz_TF_1_check = models.BooleanField( initial=False ) # whether the player's answer to these questions are correct quiz_TF_2_check = models.BooleanField( initial=False ) quiz_TF_3_check = models.BooleanField( initial=False ) quiz_Bargain_1_check = models.BooleanField( initial=False ) quiz_Bargain_2_check = models.BooleanField( initial=False ) quiz_Bargain_3_check = models.BooleanField( initial=False ) quiz_Results_1_check = models.BooleanField( initial=False ) quiz_Results_2_check = models.BooleanField( initial=False ) quiz_phase2_check = models.BooleanField( initial=False ) information_timestart = models.FloatField() # the start time of entering into information page information_endtime = models.FloatField( # the end time of this information page initial=-99 ) information_time_spent = models.FloatField() # the time spent in this information page information_scala_a = models.IntegerField( initial=1 ) # the initial bargaining stage propose1 = models.IntegerField( # player's proposal at the initial stage # choices=list(range(0, value)), # Subjects can only choose to contribute from 0 to their value label="How much will you contribute?", initial=0 ) propose1_match = models.IntegerField() # player's match's proposal at the initial stage propose1_scala_a = models.IntegerField( # this is a scala to get the start time of a bargaining stage initial=1 ) propose1_list = models.LongStringField( # player's click history on initial proposal initial="#" ) # to store player's each click on proposal amount propose1_timestart = models.FloatField() # the start time of this bargaining stage (to calculate the duration of bargaining) propose1_timelist = models.LongStringField( # the list of when clicks happen initial="#" ) # to store the time of player's each click propose1_endtime = models.FloatField( initial=-99 ) # the end time of this bargaining stage propose1_time_spent = models.FloatField() # the time spent to make the initial proposal # the second bargaining stage num_bargainstage = models.IntegerField( # the number of bargaining stages the player is in initial=1 ) add2 = models.IntegerField( # player's proposal adjustment made at the second stage label="How much do you want to add to your previous contribution proposal?", initial=0 ) add2_match = models.IntegerField() # player's match's proposal adjustment made at the second stage propose2 = models.IntegerField() # player's proposal after the adjustment made at the second stage propose2_match = models.IntegerField() # player's match's proposal after the adjustment made at the second stage propose2_scala_a = models.IntegerField( # this is a scala to get the start time of a bargaining stage initial=1 ) propose2_list = models.LongStringField( # player's click history on initial proposal initial="#" ) # to store player's each click on proposal amount propose2_timestart = models.FloatField() # the start time of this bargaining stage (to calculate the duration of bargaining) propose2_timelist = models.LongStringField( # the list of when clicks happen initial="#" ) # to store the time of player's each click propose2_endtime = models.FloatField( initial=-99 ) # the end time of this bargaining stage propose2_time_spent = models.FloatField() # the time spent to make the initial proposal # the third bargaining stage add3 = models.IntegerField( # player's proposal adjustment made at the third stage label="How much do you want to add to your previous contribution proposal?", initial=0 ) add3_match = models.IntegerField() # player's match's proposal adjustment made at the third stage propose3 = models.IntegerField() # player's proposal after the adjustment made at the third stage propose3_match = models.IntegerField() # player's match's proposal after the adjustment made at the third stage propose3_scala_a = models.IntegerField( # this is a scala to get the start time of a bargaining stage initial=1 ) propose3_list = models.LongStringField( # player's click history on initial proposal initial="#" ) # to store player's each click on proposal amount propose3_timestart = models.FloatField() # start time of bargaining stage (to calculate duration of bargaining) propose3_timelist = models.LongStringField( # the list of when clicks happen initial="#" ) # to store the time of player's each click propose3_endtime = models.FloatField( initial=-99 ) # the end time of this bargaining stage propose3_time_spent = models.FloatField() # the time spent to make the initial proposal # For questionnaire q_pagenumber = models.IntegerField( # the page number of questionnaire part initial=1 ) q_age = models.IntegerField( # the age of the subject initial=-1 ) q_gender = models.IntegerField( # the gender of the subject initial=-1 # 0: male; 1: female; 2: non-binary; 99: prefer not to say ) q_major_1 = models.IntegerField( # the major of the subject (macro thematic area) initial=-1 ) q_major_2 = models.StringField( initial='none' ) q_nationality = models.IntegerField( # the nationality of the subject (macro thematic area) initial=-1 ) q_nationality_2 = models.StringField( # the exact country name if player is not italian initial='none' ) q_risk = models.FloatField( # the number indicating player's willingness to take risk initial=-1 ) risk_sure_payment_2 = models.IntegerField() # the sure payment in the second multiple choice between sure payment and lottery risk_sure_payment_3 = models.IntegerField() risk_sure_payment_4 = models.IntegerField() risk_sure_payment_5 = models.IntegerField() q_risk2_1 = models.IntegerField( # player's choice on the first lottery & sure payment choice initial=-1 # 1: lottery; 2: sure payment ) q_risk2_2 = models.IntegerField( # player's choice on the second lottery & sure payment choice initial=-1 # 1: lottery; 2: sure payment ) q_risk2_3 = models.IntegerField( # player's choice on the third lottery & sure payment choice initial=-1 # 1: lottery; 2: sure payment ) q_risk2_4 = models.IntegerField( # player's choice on the fourth lottery & sure payment choice initial=-1 # 1: lottery; 2: sure payment ) q_risk2_5 = models.IntegerField( # player's choice on the fifth lottery & sure payment choice initial=-1 # 1: lottery; 2: sure payment ) q_fair_1 = models.IntegerField( # player's fairness preference on the first statement initial=-1 ) q_fair_2 = models.IntegerField( # player's fairness preference on the second statement initial=-1 ) q_altruism_1 = models.FloatField( # player's amount willing to donate when getting 1000 lottery initial=-1 ) q_altruism_2 = models.FloatField( # player's self-evaluation on how willing to share with others initial=-1 ) # Final outcome payoff_chosen_phase1_1 = models.IntegerField() payoff_chosen_phase1_2 = models.IntegerField() payoff_chosen_phase2_1 = models.IntegerField() payoff_chosen_phase2_2 = models.IntegerField() payoff_chosen_guess = models.IntegerField() payoff_final = models.FloatField() # FUNCTIONS def creating_session(subsession): mg1 = list(Constants.mg_assignment[0: Constants.players_per_mgroup]) mg2 = list(Constants.mg_assignment[Constants.players_per_mgroup: 2 * Constants.players_per_mgroup]) mg3 = list(Constants.mg_assignment[2 * Constants.players_per_mgroup: 3 * Constants.players_per_mgroup]) mg4 = list(Constants.mg_assignment[3 * Constants.players_per_mgroup: 4 * Constants.players_per_mgroup]) random.shuffle(mg1) random.shuffle(mg2) random.shuffle(mg3) random.shuffle(mg4) mg_all = mg1 + mg2 + mg3 + mg4 new_matching_order = [mg_all[i:i + 2] for i in range(0, len(mg_all), 2)] subsession.set_group_matrix(new_matching_order) if subsession.round_number == Constants.num_rounds: phase1 = random.sample(range(1, Constants.num_rounds_phase1 + 1), Constants.num_rounds_choseneachphase) phase2 = random.sample(range(1, Constants.num_rounds_phase2 + 1), Constants.num_rounds_choseneachphase + 1) # one more round chosen in phase2 for guess subsession.chosen_phase1_1 = phase1[0] subsession.chosen_phase1_2 = phase1[1] subsession.chosen_phase2_1 = phase2[0] subsession.chosen_phase2_2 = phase2[1] subsession.chosen_guess = phase2[2] def set_values(group: Group): players = group.get_players() for player in players: player.round_number_phase = player.round_number if player.round_number <= Constants.num_rounds_phase1 \ else player.round_number - Constants.num_rounds_phase1 player.random_setvalue = random.uniform(0, 1) player.value = Constants.pg_valueL if player.random_setvalue > Constants.prob_H else Constants.pg_valueH values = [p.value for p in players] group.total_value = sum(values) for player in players: player.value_match = group.total_value - player.value def propose1_choices(player): choices = list(range(0, min(player.value, Constants.pg_cost) + 1)) # Subjects can only contribute non-negative value no more than player's value and pg cost. # Since range(a,b) only includes a but doesn't include b, we use min +1 as b to include min return choices def set_payoffs1(group): group.random_setpayoff1 = random.uniform(0, 1) players = group.get_players() proposes = [p.propose1 for p in players] group.total_propose1 = sum(proposes) group.agreement1 = group.total_propose1 >= Constants.pg_cost group.agreement = group.agreement1 or group.agreement2 or group.agreement3 for player in players: player.num_bargainstage = 2 player.agreement = group.agreement player.propose1_match = group.total_propose1 - player.propose1 if group.agreement1: if group.random_setpayoff1 > 0.5: # use the contribution plan proposed by id_in_group = 1 for player in players: player.propose = player.propose1 player.propose_match = player.propose1_match group.total_propose = player.propose + player.propose_match if player.id_in_group == 1: '''if you are the one whose plan is accepted, your contribution is your proposal, and your match's contribution is pg_cost minus your contribution''' player.contribution = player.propose1 player.contribution_match = Constants.pg_cost - player.propose1 player.proposal_accepted = True else: '''if you are not the one whose plan is accepted, your match's contribution is his/her proposal, and your contribution is pg_cost minus your match's contribution''' player.contribution_match = player.propose1_match player.contribution = Constants.pg_cost - player.propose1_match player.proposal_accepted = False else: # use the contribution plan proposed by id_in_group = 2 for player in players: # similar as above player.propose = player.propose1 player.propose_match = player.propose1_match group.total_propose = player.propose + player.propose_match if player.id_in_group == 2: player.contribution = player.propose1 player.contribution_match = Constants.pg_cost - player.propose1 player.proposal_accepted = True else: player.contribution_match = player.propose1_match player.contribution = Constants.pg_cost - player.propose1_match player.proposal_accepted = False for player in players: player.profit = player.value - player.contribution player.profit_match = player.value_match - player.contribution_match else: for player in players: player.contribution = -99 # use an outlier value which means no contribution is made player.contribution_match = -99 # similar as above def add2_choices(player): if min(player.value, Constants.pg_cost) - player.propose1 >= 2: choices = [0, 1, 2] elif min(player.value, Constants.pg_cost) - player.propose1 == 0: choices = [0] else: choices = [0, 1] return choices def set_payoffs2(group): group.random_setpayoff2 = random.uniform(0, 1) players = group.get_players() for player in players: player.num_bargainstage = 3 '''if player.add2 == 0: player.propose2 = player.propose1 + 0 if player.add2 == 1: player.propose2 = player.propose1 + 1 if player.add2 == 2: player.propose2 = player.propose1 + 2''' player.propose2 = player.propose1 + player.add2 proposes = [p.propose2 for p in players] group.total_propose2 = sum(proposes) group.agreement2 = group.total_propose2 >= Constants.pg_cost group.agreement = group.agreement1 or group.agreement2 or group.agreement3 for player in players: player.agreement = group.agreement player.propose2_match = group.total_propose2 - player.propose2 add2_match = player.propose2_match - player.propose1_match player.add2_match = add2_match '''if add2_match == 0: player.add2_match = "+0" elif add2_match == 1: player.add2_match = "+1" else: player.add2_match = "+2"''' add2_all = [p.add2 for p in players] group.conflict2 = add2_all == [0, 0] group.conflict = group.conflict2 or group.conflict3 for player in players: player.conflict = group.conflict if group.conflict2 or group.agreement2: player.propose = player.propose2 player.propose_match = player.propose2_match group.total_propose = player.propose + player.propose_match if group.agreement2: if group.random_setpayoff2 > 0.5: # use the contribution plan proposed by id_in_group = 1 for player in players: if player.id_in_group == 1: '''if you are the one whose plan is accepted, your contribution is your proposal, and your match's contribution is pg_cost minus your contribution''' player.contribution = player.propose2 player.contribution_match = Constants.pg_cost - player.propose2 player.proposal_accepted = True else: '''if you are not the one whose plan is accepted, your match's contribution is his/her proposal, and your contribution is pg_cost minus your match's contribution''' player.contribution_match = player.propose2_match player.contribution = Constants.pg_cost - player.propose2_match player.proposal_accepted = False else: # use the contribution plan proposed by id_in_group = 2 for player in players: # similar as above if player.id_in_group == 2: player.contribution = player.propose2 player.contribution_match = Constants.pg_cost - player.propose2 player.proposal_accepted = True else: player.contribution_match = player.propose2_match player.contribution = Constants.pg_cost - player.propose2_match player.proposal_accepted = False for player in players: player.profit = player.value - player.contribution player.profit_match = player.value_match - player.contribution_match else: for player in players: player.contribution = -99 # use an outlier value which means no contribution is made player.contribution_match = -99 # similar as above if group.conflict2: player.profit = Constants.conflict player.profit_match = Constants.conflict def add3_choices(player): if min(player.value, Constants.pg_cost) - player.propose2 >= 2: choices = [0, 1, 2] elif min(player.value, Constants.pg_cost) - player.propose2 == 0: choices = [0] else: choices = [0, 1] return choices def set_payoffs3(group): group.random_setpayoff3 = random.uniform(0, 1) players = group.get_players() for player in players: '''if player.add3 == "+0": player.propose3 = player.propose2 + 0 if player.add3 == "+1": player.propose3 = player.propose2 + 1 if player.add3 == "+2": player.propose3 = player.propose2 + 2''' player.num_bargainstage = 4 player.propose3 = player.propose2 + player.add3 proposes = [p.propose3 for p in players] group.total_propose3 = sum(proposes) group.agreement3 = group.total_propose3 >= Constants.pg_cost group.agreement = group.agreement1 or group.agreement2 or group.agreement3 for player in players: player.agreement = group.agreement player.propose3_match = group.total_propose3 - player.propose3 add3_match = player.propose3_match - player.propose2_match '''if add3_match == 0: player.add3_match = "+0" elif add3_match == 1: player.add3_match = "+1" else: player.add3_match = "+2"''' player.add3_match = add3_match add3_all = [p.add3 for p in players] group.conflict3 = add3_all == [0, 0] group.conflict = group.conflict2 or group.conflict3 for player in players: player.conflict = group.conflict player.propose = player.propose3 player.propose_match = player.propose3_match group.total_propose = player.propose + player.propose_match if group.agreement3: if group.random_setpayoff3 > 0.5: # use the contribution plan proposed by id_in_group = 1 for player in players: if player.id_in_group == 1: '''if you are the one whose plan is accepted, your contribution is your proposal, and your match's contribution is pg_cost minus your contribution''' player.contribution = player.propose3 player.contribution_match = Constants.pg_cost - player.propose3 player.proposal_accepted = True else: '''if you are not the one whose plan is accepted, your match's contribution is his/her proposal, and your contribution is pg_cost minus your match's contribution''' player.contribution_match = player.propose3_match player.contribution = Constants.pg_cost - player.propose3_match player.proposal_accepted = False else: # use the contribution plan proposed by id_in_group = 2 for player in players: # similar as above if player.id_in_group == 2: player.contribution = player.propose3 player.contribution_match = Constants.pg_cost - player.propose3 player.proposal_accepted = True else: player.contribution_match = player.propose3_match player.contribution = Constants.pg_cost - player.propose3_match player.proposal_accepted = False for player in players: player.profit = player.value - player.contribution player.profit_match = player.value_match - player.contribution_match else: for player in players: player.contribution = -99 # use an outlier value which means no contribution is made player.contribution_match = -99 # similar as above if group.conflict3: player.profit = Constants.conflict player.profit_match = Constants.conflict def set_outcome(group): players = group.get_players() for p in players: S = p.subsession prevplayer_phase1_1 = p.in_round(S.chosen_phase1_1) prevplayer_phase1_2 = p.in_round(S.chosen_phase1_2) prevplayer_phase2_1 = p.in_round(S.chosen_phase2_1 + Constants.num_rounds_phase1) prevplayer_phase2_2 = p.in_round(S.chosen_phase2_2 + Constants.num_rounds_phase1) prevplayer_guess = p.in_round(S.chosen_guess + Constants.num_rounds_phase1) p.payoff_chosen_phase1_1 = prevplayer_phase1_1.profit p.payoff_chosen_phase1_2 = prevplayer_phase1_2.profit p.payoff_chosen_phase2_1 = prevplayer_phase2_1.profit p.payoff_chosen_phase2_2 = prevplayer_phase2_2.profit p.payoff_chosen_guess = 1 if prevplayer_guess.value_match_guess == prevplayer_guess.value_match else 0 p.payoff_final = (p.payoff_chosen_phase1_1 + p.payoff_chosen_phase1_2 + p.payoff_chosen_phase2_1 + p.payoff_chosen_phase2_2)/2 + p.payoff_chosen_guess + Constants.participation_fee # PAGES """ We need 4 pages ID: participants enter their ID code Information page: tell subjects their values Contribution page: subjects choose the contribution Waiting page: wait until the other one finish contributing Result page: inform subjects of their payoffs from this round """ class ID(Page): @staticmethod def is_displayed(player): return player.round_number == 1 form_model = 'player' form_fields = ['IDnumber'] class StartWaiting(WaitPage): @staticmethod def is_displayed(player): return player.round_number == 1 wait_for_all_groups = True class Instruction(Page): @staticmethod def is_displayed(player): return player.round_number == 1 @staticmethod def live_method(player: Player, data): if 'pagechange' in data: page = player.pagenumber + data['pagechange'] if page <= Constants.num_instructionpage and page >= 1: player.pagenumber = page if 'doneinstru' in data: player.pagenumber = 99 if 'backinstru' in data: player.pagenumber = 1 if 'quizTF1' in data: quiztf1 = int(data['quizTF1']) player.quiz_TF_1 = quiztf1 player.quiz_TF_1_check = player.quiz_TF_1 == Constants.quiz_TF_1_solution if 'quizTF2' in data: player.quiz_TF_2 = data['quizTF2'] player.quiz_TF_2_check = player.quiz_TF_2 == Constants.quiz_TF_2_solution if 'quizTF3' in data: player.quiz_TF_3 = data['quizTF3'] player.quiz_TF_3_check = player.quiz_TF_3 == Constants.quiz_TF_3_solution if 'quizB1' in data: player.quiz_Bargain_1 = data['quizB1'] player.quiz_Bargain_1_check = player.quiz_Bargain_1 == Constants.quiz_Bargain_1_solution if 'quizB2' in data: player.quiz_Bargain_2 = data['quizB2'] player.quiz_Bargain_2_check = player.quiz_Bargain_2 == Constants.quiz_Bargain_2_solution if 'quizB3' in data: player.quiz_Bargain_3 = data['quizB3'] player.quiz_Bargain_3_check = player.quiz_Bargain_3 == Constants.quiz_Bargain_3_solution if 'quizR1' in data: player.quiz_Results_1 = data['quizR1'] player.quiz_Results_1_check = player.quiz_Results_1 == Constants.quiz_Results_1_solution if 'quizR2' in data: player.quiz_Results_2 = data['quizR2'] player.quiz_Results_2_check = player.quiz_Results_2 == Constants.quiz_Results_2_solution if 'nextquizpage' in data: player.quizpagenumber = player.quizpagenumber + 1 return {0: dict(news=player.pagenumber)} class Instruction2(Page): @staticmethod def is_displayed(player): return player.round_number == Constants.num_rounds_phase1 + 1 @staticmethod def live_method(player: Player, data): if 'pagechange' in data: page = player.pagenumber + data['pagechange'] if page <= Constants.num_instructionpage and page >= 1: player.pagenumber = page if 'doneinstru' in data: player.pagenumber = 99 if 'backinstru' in data: player.pagenumber = 1 if 'nextquizpage' in data: player.quizpagenumber = player.quizpagenumber + 1 if 'quiz2TF1' in data: player.quiz_phase2 = data['quiz2TF1'] player.quiz_phase2_check = Constants.quiz_phase2 == player.quiz_phase2 return {0: dict(news=player.pagenumber)} class InstructionWait(WaitPage): '''@staticmethod def is_displayed(player): return player.round_number == 1 or player.round_number == Constants.num_rounds_phase1 + 1 wait_for_all_groups = True''' pass class EnterWaiting(WaitPage): after_all_players_arrive = 'set_values' class Information(Page): timeout_seconds = Constants.time_information @staticmethod def vars_for_template(player: Player): if player.information_scala_a == 1: player.information_timestart = time.time() player.information_scala_a = player.information_scala_a + 1 return dict( ttt=1 ) @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.information_time_spent = Constants.time_information else: player.information_endtime = time.time() player.information_time_spent = player.information_endtime - player.information_timestart class BargainingInitial(Page): # Initial bargaining stage '''form_model = 'player' form_fields = ['propose1']''' timeout_seconds = Constants.time_bargaininitial @staticmethod def vars_for_template(player: Player): if player.propose1_scala_a == 1: player.propose1_timestart = time.time() player.propose1_scala_a = player.propose1_scala_a + 1 return dict( choicelist=propose1_choices(player) ) @staticmethod def live_method(player: Player, data): '''if 'starttime' in data: player.propose1_timestart = data['starttime']''' if 'choice' in data: player.propose1 = data['choice'] player.propose1_list = player.propose1_list + "," + str(data['choice']) click_time = time.time() player.propose1_timelist = player.propose1_timelist + ',' + str(click_time) return @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.propose1_time_spent = Constants.time_bargaininitial else: player.propose1_endtime = time.time() player.propose1_time_spent = player.propose1_endtime - player.propose1_timestart class BargainingWaiting1(WaitPage): after_all_players_arrive = 'set_payoffs1' class BargainingSecond(Page): # Second bargaining stage @staticmethod def is_displayed(player): return (not player.agreement) and (not player.conflict) @staticmethod def vars_for_template(player: Player): if player.propose2_scala_a == 1: player.propose2_timestart = time.time() player.propose2_scala_a = player.propose2_scala_a + 1 return dict( choicelist=add2_choices(player) ) @staticmethod def live_method(player: Player, data): if 'choice' in data: player.add2 = data['choice'] player.propose2_list = player.propose2_list + "," + str(data['choice']) click_time = time.time() player.propose2_timelist = player.propose2_timelist + ',' + str(click_time) return @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.propose2_time_spent = Constants.time_bargainafter else: player.propose2_endtime = time.time() player.propose2_time_spent = player.propose2_endtime - player.propose2_timestart timeout_seconds = Constants.time_bargainafter class BargainingWaitng2(WaitPage): @staticmethod def is_displayed(player): return (not player.agreement) and (not player.conflict) after_all_players_arrive = 'set_payoffs2' class BargainingThird(Page): # Third bargaining stage @staticmethod def is_displayed(player): return (not player.agreement) and (not player.conflict) @staticmethod def vars_for_template(player: Player): if player.propose3_scala_a == 1: player.propose3_timestart = time.time() player.propose3_scala_a = player.propose3_scala_a + 1 return dict( choicelist=add3_choices(player) ) @staticmethod def live_method(player: Player, data): if 'choice' in data: player.add3 = data['choice'] player.propose3_list = player.propose3_list + "," + str(data['choice']) click_time = time.time() player.propose3_timelist = player.propose3_timelist + ',' + str(click_time) return @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.propose3_time_spent = Constants.time_bargainafter else: player.propose3_endtime = time.time() player.propose3_time_spent = player.propose3_endtime - player.propose3_timestart timeout_seconds = Constants.time_bargainafter class ResultsWaitPage(WaitPage): @staticmethod def is_displayed(player): return (not player.agreement) and (not player.conflict) after_all_players_arrive = 'set_payoffs3' class Results(Page): @staticmethod def live_method(player: Player, data): if 'guess' in data: player.value_match_guess = data['guess'] return {0: dict(news=player.pagenumber)} class Questionnaire(Page): @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds ''' form_model = 'player' form_fields = ['q_age'] @staticmethod def vars_for_template(player: Player): return dict( gender_list = )''' @staticmethod def live_method(player: Player, data): if 'age' in data: if player.q_age == -1: player.q_age = data['age'] player.q_pagenumber = player.q_pagenumber + 1 if 'gender' in data: player.q_gender = data['gender'] if 'major' in data: player.q_major_1 = data['major'] if 'major2' in data: player.q_major_2 = data['major2'] player.q_pagenumber = player.q_pagenumber + 1 if 'nation' in data: player.q_nationality = data['nation'] if 'nation2' in data: player.q_nationality_2 = data['nation2'] player.q_pagenumber = player.q_pagenumber + 1 if 'risk' in data: player.q_risk = data['risk'] player.q_pagenumber = player.q_pagenumber + 1 if 'risk1' in data: player.q_risk2_1 = data['risk1'] player.risk_sure_payment_2 = Constants.risk_sure_payment_initial + 80 if player.q_risk2_1 == 1 \ else Constants.risk_sure_payment_initial - 80 if 'risk2' in data: player.q_risk2_2 = data['risk2'] player.risk_sure_payment_3 = player.risk_sure_payment_2 + 40 if player.q_risk2_2 == 1 \ else player.risk_sure_payment_2 - 40 if 'risk3' in data: player.q_risk2_3 = data['risk3'] player.risk_sure_payment_4 = player.risk_sure_payment_3 + 20 if player.q_risk2_3 == 1 \ else player.risk_sure_payment_3 - 20 if 'risk4' in data: player.q_risk2_4 = data['risk4'] player.risk_sure_payment_5 = player.risk_sure_payment_4 + 10 if player.q_risk2_4 == 1 \ else player.risk_sure_payment_4 - 10 if 'risk5' in data: player.q_risk2_5 = data['risk5'] if 'fair1' in data: player.q_fair_1 = data['fair1'] if 'fair2' in data: player.q_fair_2 = data['fair2'] if 'altruism1' in data: player.q_altruism_1 = data['altruism1'] player.q_pagenumber = player.q_pagenumber + 1 if 'altruism2' in data: player.q_altruism_2 = data['altruism2'] player.q_pagenumber = player.q_pagenumber + 1 if 'next' in data: player.q_pagenumber = player.q_pagenumber + 1 return {0: dict(news=1)} class BeforeOutcome(WaitPage): @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds after_all_players_arrive = 'set_outcome' class Outcome(Page): @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds page_sequence = [ID, StartWaiting, Instruction, Instruction2, EnterWaiting, Information, BargainingInitial, BargainingWaiting1, BargainingSecond, BargainingWaitng2, BargainingThird, ResultsWaitPage, Results, BeforeOutcome, Questionnaire, Outcome]