from otree.api import * from django.utils.safestring import mark_safe from math import ceil import random import html doc = """ Second opinion game with big group """ class C(BaseConstants): NAME_IN_URL = 'mainexperiment' PLAYERS_PER_GROUP = 12 NUM_PRACTICE_ROUNDS = 4 NUM_REAL_ROUNDS = 16 NUM_ROUNDS = NUM_PRACTICE_ROUNDS + NUM_REAL_ROUNDS Problem = {1: 'Major', 2: 'Minor'} Role = {1: 'Seller', 2: 'Buyer'} Expert = {1: 'Seller 1', 2: 'Seller 2'} Percentage = {0: "rarely: 0%-20%", 1: "not often: 21%-40%", 2: "often: 41%-60%", 3: "very often: 61%-80%", 4: "almost always: 81%-100%"} random.seed(30) Real_Problem = [[random.randint(1, 2) for _ in range(20)] for _ in range(6)] # they dont allow to use c.num_rounds in this for some reason, the first num in range is the num # rounds and the second is num of buyer # Real_Problem = [[1, 2], [2, 1]] # first row is the problem of consumer 1 and the second row is the problem of consumer 2 round_change_k = [NUM_PRACTICE_ROUNDS + 9] #round_change_V = [NUM_PRACTICE_ROUNDS + 9] #round_change_k = [NUM_PRACTICE_ROUNDS + 5, NUM_PRACTICE_ROUNDS + 9, NUM_PRACTICE_ROUNDS + 13] V = [6, 12] Price = [6, 2] Cost = [3.5, 0] k = [0.1, 1.1] lottery = 3.0 multiplier = 2 con_endowment = 0 exp_endowment = 0 Total_con_endowment = 13 Total_exp_endowment = 13 def roundup(x, u=0.50): return ceil(x / u) * u def make_expert_field(label): a = mark_safe("Major treatment") b = mark_safe("Minor treatment") return models.BooleanField( choices=[[True, a], [False, b]], label=label, html_labels=True ) def make_consumer_field(label): a = mark_safe("Reject the offer and buy from Seller 2 ") return models.BooleanField( choices=[[True, "Accept the offer"], [False, a]], label=label, ) def make_percentage_field(label): return models.IntegerField( choices=[[0, "Rarely: 0%-20%"], [1, "Not often: 21%-40%"], [2, "Often: 41%-60%"], [3, "Very often: 61%-80%"], [4, "Almost always: 81%-100%"]], label=label, ) def make_guess_field(label): return models.IntegerField( choices=[[0, "0"], [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"], [6, "6"]], label=label, ) class Group(BaseGroup): pvalue = models.IntegerField() pk = models.FloatField() numacceptH = models.IntegerField() numacceptL = models.IntegerField() numovertreat = models.IntegerField() numhonestoffer = models.IntegerField() numhonestexp = models.IntegerField(initial=0) honoff_ch = models.IntegerField() #def pvalue(group): #if group.round_number < C.round_change_V[1]: #return C.V[0] #else: #return C.V[1] #def pk(group): #if group.round_number < C.round_change_k[1] or group.round_number >= C.round_change_k[3]: #return C.k[0] #else: #return C.k[1] class Subsession(BaseSubsession): is_practice_round = models.BooleanField() real_round_number = models.IntegerField() def creating_session(subsession: Subsession): subsession.is_practice_round = ( subsession.round_number <= C.NUM_PRACTICE_ROUNDS ) if not subsession.is_practice_round: subsession.real_round_number = ( subsession.round_number - C.NUM_PRACTICE_ROUNDS ) import itertools if subsession.round_number == 1: subsession.group_randomly(fixed_id_in_group=True) else: subsession.group_like_round(1) if subsession.round_number == 1: if subsession.session.config['within'] == 1: value = [6, 0.1] elif subsession.session.config['within'] == 2: value = [12, 0.1] elif subsession.session.config['within'] == 3: value = [6, 1.1] else: value = [12, 1.1] for group in subsession.get_groups(): group.pvalue = value[0] group.pk = value[1] player = group.get_player_by_id(1) player.participant.pvalue = group.pvalue player.participant.pk = group.pk elif subsession.round_number in C.round_change_k: for group in subsession.get_groups(): player = group.get_player_by_id(1) #if player.participant.pvalue == 6: # group.pvalue = 12 #else: # group.pvalue = 6 if player.participant.pk == 0.1: group.pk = 1.1 else: group.pk = 0.1 group.pvalue = player.participant.pvalue player.participant.pk = group.pk else: for group in subsession.get_groups(): player = group.get_player_by_id(1) group.pvalue = player.participant.pvalue group.pk = player.participant.pk class Player(BasePlayer): def role(player): if player.round_number == 1: if player.id_in_group <= C.PLAYERS_PER_GROUP // 2: player.participant.type = 1 else: player.participant.type = 2 return player.participant.type else: return player.participant.type # def problem(player): # if player.id_in_group > 2: # return C.Real_Problem[player.id_in_group - 3][player.round_number - 1] # else: # return 'No problem' # def obsproblem(player): # if player.id_in_group <= 2: # n = C.PLAYERS_PER_GROUP // 2 # obsproblem = [[0, 0], [0, 0]] # for i in range(n): # for j in range(C.NUM_ROUNDS): # if random.randrange(100) < player.session.config['beta']: # obsproblem[i][j] = C.Real_Problem[i][j] # else: # if C.Real_Problem[i][j] == 1: # obsproblem[i][j] = 2 # else: # obsproblem[i][j] = 1 # return obsproblem # else: # return 'I am a consumer.' # problem problem = models.IntegerField() obsproblem = models.IntegerField() # Overtreament decision overtreat1 = make_expert_field(mark_safe('Buyer 1')) overtreat2 = make_expert_field(mark_safe('Buyer 2')) overtreat3 = make_expert_field(mark_safe('Buyer 3')) overtreat4 = make_expert_field(mark_safe('Buyer 4')) overtreat5 = make_expert_field(mark_safe('Buyer 5')) overtreat6 = make_expert_field(mark_safe('Buyer 6')) # Search decision acceptH = make_consumer_field(mark_safe('If Seller 1 offers you a major treatment, would you like to accept or reject?')) acceptL = make_consumer_field(mark_safe('If Seller 1 offers you a minor treatment, would you like to accept or reject?')) # Expert guess conacceptH = make_guess_field(mark_safe("Out of 6 buyers, how many of them will accept a major treatment?")) conacceptL = make_guess_field(mark_safe("Out of 6 buyers, how many of them will accept a minor treatment?")) opponentOvertreat = make_percentage_field( mark_safe("How often would the other sellers offer a minor treatment?") ) # Consumer guess honestOffer = make_percentage_field(mark_safe("How often would the sellers offer a minor treatment?")) honestExp = make_guess_field(mark_safe("Out of 6 sellers, how many of them offer(s) a minor treatment to all buyer(s) with a minor problem?")) numofconsumer = models.IntegerField(initial=0) numcon11 = models.IntegerField(initial=0) numcon12 = models.IntegerField(initial=0) numcon21 = models.IntegerField(initial=0) numcon22 = models.IntegerField(initial=0) numofrej = models.IntegerField(initial=0) numrej11 = models.IntegerField(initial=0) numrej12 = models.IntegerField(initial=0) numrej21 = models.IntegerField(initial=0) numrej22 = models.IntegerField(initial=0) #buy from which expert buyfrom = models.IntegerField(initial=0) #the purchased treatment acceptoffer = models.IntegerField() #the problem is solved or not problemissolved = models.IntegerField() #result of quess question opponenthon_ch = models.IntegerField() honoff_ch_result = models.IntegerField() numaccepth_prac = models.IntegerField() numacceptl_prac = models.IntegerField() numhonest_exp_prac = models.IntegerField(initial=0) #password to new section password = models.IntegerField() #risk preference risk = models.FloatField(min=0, max=3, decimal_palce=2, label="") # function for the expert offer #def offer(player): # offer = [[0, 0], [0, 0]] # n = player.round_number - 1 # if player.obsproblem()[0][n] == 1 or player.overtreat1: # offer[0][n] = 1 #else: # offer[0][n] = 2 # if player.obsproblem()[1][n] == 1 or player.overtreat2: # offer[1][n] = 1 #else: # offer[1][n] = 2 # return offer guesspoint1 = models.FloatField() guesspoint2 = models.FloatField() guesspoint3 = models.FloatField() total_guesspoints = models.FloatField() real_round_number = models.IntegerField(initial=0) # function for the consumer acceptance def accept(player): if player.acceptH and player.acceptL: return 3 elif player.acceptH and not player.acceptL: return 1 elif not player.acceptH and player.acceptL: return 2 else: return 0 # Function def obsproblem(player: Player): n = C.PLAYERS_PER_GROUP // 2 rows, cols = n, C.NUM_ROUNDS obsproblem = [([0] * cols) for i in range(rows)] #obsproblem = [0] * n if player.id_in_group <= n: for i in range(n): for j in range(C.NUM_ROUNDS): if random.randrange(100) < player.session.config['beta']: obsproblem[i][j] = C.Real_Problem[i][j] else: if C.Real_Problem[i][j] == 1: obsproblem[i][j] = 2 else: obsproblem[i][j] = 1 player.participant.obsprob = obsproblem else: player.participant.obsprob = obsproblem #print('real problem is here', C.Real_Problem) #print('obs problem is here', obsproblem) return player.participant.obsprob def problem(player: Player): if player.id_in_group > C.PLAYERS_PER_GROUP // 2: player.problem = C.Real_Problem[player.id_in_group - C.PLAYERS_PER_GROUP // 2 - 1][ player.round_number - 1] else: player.problem = 0 return player.problem def get_real_round_num(player: Player): if player.round_number > C.NUM_PRACTICE_ROUNDS: player.real_round_number = player.round_number - C.NUM_PRACTICE_ROUNDS return player.real_round_number def offer(player: Player): if player.id_in_group <= C.PLAYERS_PER_GROUP // 2: offer = [0] * (C.PLAYERS_PER_GROUP // 2) overtreat = [player.overtreat1, player.overtreat2, player.overtreat3, player.overtreat4, player.overtreat5, player.overtreat6] random.shuffle(overtreat) player.participant.overtreatdec = overtreat #print(player.participant.overtreatdec) for i in range(C.PLAYERS_PER_GROUP // 2): r = player.round_number-1 if player.participant.obsprob[i][r] == 1 or overtreat[i]: offer[i] = 1 else: offer[i] = 2 #print('offer is here',offer) player.participant.offer = offer return player.participant.offer def is_displayed_con(player: Player): return player.id_in_group > C.PLAYERS_PER_GROUP // 2 def is_displayed_exp(player: Player): return player.id_in_group <= C.PLAYERS_PER_GROUP // 2 def before_next_page_exp(player: Player, timeout_happened): #practice round payoff if player.round_number <= C.NUM_PRACTICE_ROUNDS: # pre-made other players parameters random_con = random.randint(0, C.PLAYERS_PER_GROUP // 2 - 1) # pick one of six consumer's problem #print(random_con) group = player.group pC = group.get_player_by_id(random_con + C.PLAYERS_PER_GROUP // 2 +1) id = pC.id_in_group #print('con',id) para_set = [random.randint(1, 2) for _ in range(2)] # other expert_off, order # guess question3 fake_opponent_offer = [random.randint(1, 2) for _ in range(6 * ((C.PLAYERS_PER_GROUP // 2) - 1))] numophonest = fake_opponent_offer.count(2) #print(para_set, numophonest) totalopoffer = ((C.PLAYERS_PER_GROUP // 2) * 6) - 6 opponenthon = numophonest * 100 // totalopoffer if 0 <= opponenthon <= 20: opponenthon_ch = 0 elif 21 <= opponenthon <= 40: opponenthon_ch = 1 elif 41 <= opponenthon <= 60: opponenthon_ch = 2 elif 61 <= opponenthon <= 80: opponenthon_ch = 3 elif 81 <= opponenthon <= 100: opponenthon_ch = 4 else: opponenthon_ch = -2 print('Some things were wrong in counting the honest offer (ex q3)') player.opponenthon_ch = opponenthon_ch if opponenthon_ch == player.opponentOvertreat: player.guesspoint3 = 1 else: player.guesspoint3 = 0 fake_con_acc = [random.randint(0, 3) for _ in range(C.PLAYERS_PER_GROUP // 2)] # pre-made consumer's acceptance # guess question 1 and 2 player.numaccepth_prac = fake_con_acc.count(1) + fake_con_acc.count(3) player.numacceptl_prac = fake_con_acc.count(2) + fake_con_acc.count(3) # question1 if player.conacceptH == player.numaccepth_prac: player.guesspoint1 = 1 else: player.guesspoint1 = 0 # question2 if player.conacceptL == player.numacceptl_prac: player.guesspoint2 = 1 else: player.guesspoint2 = 0 player.total_guesspoints = player.guesspoint1 + player.guesspoint2 + player.guesspoint3 con_acc = fake_con_acc[0] #print(con_acc) if random.randrange(100) < player.session.config['beta']: otherex_obs = pC.problem else: if pC.problem == 1: otherex_obs = 2 else: otherex_obs = 1 if otherex_obs == 1: otherex_off = 1 else: otherex_off = fake_opponent_offer[0] # chosen offer of the other expert #print(otherex_off) offer = player.participant.offer[random_con] #print(offer) if para_set[1] == 1: # be the first visit player.participant.matchedoffer = [offer] if offer == con_acc or con_acc == 3: player.payoff = C.exp_endowment + C.Price[offer - 1] - C.Cost[offer - 1] player.numofconsumer = 1 if offer != pC.problem and offer == 2: # the problem is not solved player.numcon12 = 1 # row: have problem 1 column: purchased 2 else: # the problem is solved if offer == 1 and pC.problem == 1: player.numcon11 = 1 elif offer == 2 and pC.problem == 2: player.numcon22 = 1 else: player.numcon21 = 1 else: # the expert is rejected player.payoff = C.exp_endowment player.numofrej = 1 if offer != pC.problem and offer == 2: player.numrej12 = 1 # row: have problem 1 column: reject 2 else: if offer == 1 and pC.problem == 1: player.numrej11 = 1 elif offer == 2 and pC.problem == 2: player.numrej22 = 1 else: player.numrej21 = 1 elif para_set[1] == 2: # be the second visit if otherex_off == con_acc or con_acc == 3: player.payoff = C.exp_endowment player.participant.matchedoffer = [] else: # another expert is rejected player.participant.matchedoffer = [offer] player.payoff = C.exp_endowment + C.Price[offer - 1] - C.Cost[offer - 1] player.numofconsumer = 1 if offer != pC.problem and offer == 2: # the problem is not solved player.numcon12 = 1 # row: have problem 1 column: purchased 2 else: # the problem is solved if offer == 1 and pC.problem == 1: player.numcon11 = 1 elif offer == 2 and pC.problem == 2: player.numcon22 = 1 else: player.numcon21 = 1 else: pass def before_next_page_con(player: Player, timeout_happened): #practice round payoff if player.round_number <= C.NUM_PRACTICE_ROUNDS: fake_offer = [random.randint(1, 2) for _ in range(6 * C.PLAYERS_PER_GROUP // 2)] #print('alloffer', fake_offer) # fake_offer = [[random.randint(1, 2) for _ in range(6)] for _ in range(C.PLAYERS_PER_GROUP//2)] # guess question 1 numhonest = fake_offer.count(2) totaloffer = (C.PLAYERS_PER_GROUP // 2 * 6) honoff = (numhonest * 100) // totaloffer if 0 <= honoff <= 20: honoff_ch = 0 elif 21 <= honoff <= 40: honoff_ch = 1 elif 41 <= honoff <= 60: honoff_ch = 2 elif 61 <= honoff <= 80: honoff_ch = 3 elif 81 <= honoff <= 100: honoff_ch = 4 else: honoff_ch = -2 print('Some things were wrong in counting the honest offer (co q1)') player.honoff_ch_result = honoff_ch if honoff_ch == player.honestOffer: player.guesspoint1 = 1 else: player.guesspoint1 = 0 # guess question 2 col = 6 # number of choices each expert made fake_offer_m = [fake_offer[i:i + col] for i in range(0, len(fake_offer), col)] #print(fake_offer_m) for i in range(len(fake_offer_m)): # range num of row (row is the number of expert) expert_offer = fake_offer_m[i] honest = expert_offer.count(0) if honest == len(fake_offer_m): # always honest all zeros in all fields player.numhonest_exp_prac = player.numhonest_exp_prac + 1 # if player.honestExp == player.numhonest_exp_prac: # player.guesspoint2 = 3 # else: # player.guesspoint2 = 0 player.total_guesspoints = player.guesspoint1 # + player.guesspoint2 para_set = [fake_offer[0], fake_offer[6]] # offers of 2 experts are the first 2 ex_obs = [0, 0] ex_off = [0, 0] prob = player.problem for i in range(2): if random.randrange(100) < player.session.config['beta']: ex_obs[i] = prob else: if prob == 1: ex_obs[i] = 2 else: ex_obs[i] = 1 if ex_obs[i] == 1: ex_off[i] = 1 else: ex_off[i] = para_set[i] #print(prob) #print(ex_off) #print(player.accept()) if ex_off[0] == player.accept() or player.accept() == 3: player.acceptoffer = ex_off[0] player.buyfrom = 1 if ex_off[0] != prob and ex_off[0] == 2: # the problem is not solved player.problemissolved = 0 player.payoff = C.con_endowment - C.Price[ex_off[0] - 1] # row: have problem 1 column: purchased 2 else: # the problem is solved player.payoff = C.con_endowment + player.group.pvalue - C.Price[ex_off[0] - 1] player.problemissolved = 1 else: # consumer search player.acceptoffer = ex_off[1] player.buyfrom = 2 if ex_off[1] != prob and ex_off[1] == 2: # the problem is not solved player.problemissolved = 0 player.payoff = C.con_endowment - C.Price[ex_off[1] - 1] - player.group.pk # row: have problem 1 column: purchased 2 else: # the problem is solved player.problemissolved = 1 player.payoff = C.con_endowment + player.group.pvalue - C.Price[ex_off[1] - 1] - player.group.pk else: pass def set_payoffs_prac(group: Group): #not use players = group.get_players() for player in players: if player.id_in_group <= C.PLAYERS_PER_GROUP // 2: #pre-made other players parameters random_con = random.randint(0, C.PLAYERS_PER_GROUP // 2 -1) # pick one of six consumer's problem pC = group.get_player_by_id(random_con + C.PLAYERS_PER_GROUP // 2) para_set = [random.randint(1, 2) for _ in range(2)] #other expert_off, order #guess question3 fake_opponent_offer = [random.randint(1, 2) for _ in range(6 * ((C.PLAYERS_PER_GROUP // 2) - 1))] numophonest = fake_opponent_offer.count(2) #print(para_set, numophonest) totalopoffer = ((C.PLAYERS_PER_GROUP // 2) * 6) - 6 opponenthon = numophonest * 100 // totalopoffer if 0 <= opponenthon <= 20: opponenthon_ch = 0 elif 21 <= opponenthon <= 40: opponenthon_ch = 1 elif 41 <= opponenthon <= 60: opponenthon_ch = 2 elif 61 <= opponenthon <= 80: opponenthon_ch = 3 elif 81 <= opponenthon <= 100: opponenthon_ch = 4 else: opponenthon_ch = -2 print('Some things were wrong in counting the honest offer (ex q3)') player.opponenthon_ch = opponenthon_ch if opponenthon_ch == player.opponentOvertreat: player.guesspoint3 = 1 else: player.guesspoint3 = 0 fake_con_acc = [random.randint(0, 3) for _ in range(C.PLAYERS_PER_GROUP // 2)] # pre-made consumer's acceptance #guess question 1 and 2 player.numaccepth_prac = fake_con_acc.count(1) + fake_con_acc.count(3) player.numacceptl_prac = fake_con_acc.count(2) + fake_con_acc.count(3) # question1 if player.conacceptH == player.numaccepth_prac: player.guesspoint1 = 1 else: player.guesspoint1 = 0 # question2 if player.conacceptL == player.numacceptl_prac: player.guesspoint2 = 1 else: player.guesspoint2 = 0 player.total_guesspoints = player.guesspoint1 + player.guesspoint2 + player.guesspoint3 con_acc = fake_con_acc[0] #print(con_acc) if random.randrange(100) < group.session.config['beta']: otherex_obs = pC.problem else: if pC.problem == 1: otherex_obs = 2 else: otherex_obs = 1 if otherex_obs == 1: otherex_off = 1 else: otherex_off = fake_opponent_offer[0] #chosen offer of the other expert #print(otherex_off) offer = player.participant.offer[random_con] #print(offer) if para_set[1] == 1: #be the first visit player.participant.matchedoffer = [offer] if offer == con_acc or con_acc == 3: player.payoff = C.exp_endowment + C.Price[offer - 1] - C.Cost[offer - 1] player.numofconsumer = 1 if offer != pC.problem and offer == 2: # the problem is not solved player.numcon12 = 1 # row: have problem 1 column: purchased 2 else: # the problem is solved if offer == 1 and pC.problem == 1: player.numcon11 = 1 elif offer == 2 and pC.problem == 2: player.numcon22 = 1 else: player.numcon21 = 1 else: # the expert is rejected player.payoff = C.exp_endowment player.numofrej = 1 if offer != pC.problem and offer == 2: player.numrej12 = 1 # row: have problem 1 column: reject 2 else: if offer == 1 and pC.problem == 1: player.numrej11 = 1 elif offer == 2 and pC.problem == 2: player.numrej22 = 1 else: player.numrej21 = 1 elif para_set[1] == 2: #be the second visit if otherex_off == con_acc or con_acc == 3: player.payoff = C.exp_endowment player.participant.matchedoffer = [] else: # another expert is rejected player.participant.matchedoffer = [offer] player.payoff = C.exp_endowment + C.Price[offer - 1] - C.Cost[offer - 1] player.numofconsumer = 1 if offer != pC.problem and offer == 2: # the problem is not solved player.numcon12 = 1 # row: have problem 1 column: purchased 2 else: # the problem is solved if offer == 1 and pC.problem == 1: player.numcon11 = 1 elif offer == 2 and pC.problem == 2: player.numcon22 = 1 else: player.numcon21 = 1 else: #be the consumer fake_offer = [random.randint(1, 2) for _ in range(6 * C.PLAYERS_PER_GROUP//2)] #print('alloffer', fake_offer) #fake_offer = [[random.randint(1, 2) for _ in range(6)] for _ in range(C.PLAYERS_PER_GROUP//2)] #guess question 1 numhonest = fake_offer.count(2) totaloffer = (C.PLAYERS_PER_GROUP // 2 * 6) honoff = (numhonest * 100) // totaloffer if 0 <= honoff <= 20: honoff_ch = 0 elif 21 <= honoff <= 40: honoff_ch = 1 elif 41 <= honoff <= 60: honoff_ch = 2 elif 61 <= honoff <= 80: honoff_ch = 3 elif 81 <= honoff <= 100: honoff_ch = 4 else: honoff_ch = -2 print('Some things were wrong in counting the honest offer (co q1)') player.honoff_ch_result = honoff_ch if honoff_ch == player.honestOffer: player.guesspoint1 = 1 else: player.guesspoint1 = 0 #guess question 2 col = 6 #number of choices each expert made fake_offer_m = [fake_offer[i:i+col] for i in range(0, len(fake_offer), col)] #print(fake_offer_m) for i in range(len(fake_offer_m)): # range num of row (row is the number of expert) expert_offer = fake_offer_m[i] honest = expert_offer.count(0) if honest == len(fake_offer_m): # always honest all zeros in all fields player.numhonest_exp_prac = player.numhonest_exp_prac + 1 #if player.honestExp == player.numhonest_exp_prac: # player.guesspoint2 = 3 #else: # player.guesspoint2 = 0 player.total_guesspoints = player.guesspoint1 #+ player.guesspoint2 para_set = [fake_offer[0], fake_offer[6]] #offers of 2 experts are the first 2 ex_obs = [0,0] ex_off = [0,0] prob = player.problem for i in range(2): if random.randrange(100) < player.session.config['beta']: ex_obs[i] = prob else: if prob == 1: ex_obs[i] = 2 else: ex_obs[i] = 1 if ex_obs[i] == 1: ex_off[i] = 1 else: ex_off[i] = para_set[i] #print(prob) #print(ex_off) #print(player.accept()) if ex_off[0] == player.accept() or player.accept() == 3: player.acceptoffer = ex_off[0] player.buyfrom = 1 if ex_off[0] != prob and ex_off[0] == 2: # the problem is not solved player.problemissolved = 0 player.payoff = C.con_endowment - C.Price[ex_off[0]-1] # row: have problem 1 column: purchased 2 else: # the problem is solved player.problemissolved = 1 player.payoff = C.con_endowment + group.pvalue - C.Price[ex_off[0]-1] else: #consumer search player.acceptoffer = ex_off[1] player.buyfrom = 2 if ex_off[1] != prob and ex_off[1] == 2: # the problem is not solved player.problemissolved = 0 player.payoff = C.con_endowment - C.Price[ex_off[1]-1] - group.pk # row: have problem 1 column: purchased 2 else: # the problem is solved player.problemissolved = 1 player.payoff = C.con_endowment + group.pvalue - C.Price[ex_off[1]-1] - group.pk def display(x): return C.Problem[x] def set_payoffs(group: Group): expert = list(range(1, C.PLAYERS_PER_GROUP // 2 + 1)) n = 2 # number of experts drawn exp1offer = [0] * (C.PLAYERS_PER_GROUP // 2) # initial list of selected expert's offer exp2offer = [0] * (C.PLAYERS_PER_GROUP // 2) r = group.round_number - 1 for i in range(C.PLAYERS_PER_GROUP // 2): pC = group.get_player_by_id(C.PLAYERS_PER_GROUP // 2 + i + 1) # choose the consumer ordered by id matchedexp = random.sample(expert, n) # choose 2 experts for that consumer #print('2 experts for con',matchedexp) pE1 = group.get_player_by_id(matchedexp[0]) # the first visited expert pE2 = group.get_player_by_id(matchedexp[1]) # the second opinion conproblem = pC.problem conacc = pC.accept() exp1offer[i] = pE1.participant.offer[i] # the first expert's offer for buyer id C.PLAYERS_PER_GROUP // 2 + i + 1 exp2offer[i] = pE2.participant.offer[i] # the first expert's offer for buyer id C.PLAYERS_PER_GROUP // 2 + i + 1 past1matched = pE1.participant.matchedoffer past1matched.append(exp1offer[i]) pE1.participant.matchedoffer = past1matched if conacc == exp1offer[i] or conacc == 3: # consumer purchases from the first expert addpayoff1 = C.exp_endowment + C.Price[exp1offer[i] - 1] - C.Cost[exp1offer[i] - 1] addpayoff2 = C.exp_endowment numreject1 = 0 numcon1 = 1 numcon2 = 0 numcon2mat = [[0, 0], [0, 0]] numrej1mat = [[0, 0], [0, 0]] pC.acceptoffer = exp1offer[i] # the offer accepted from the first expert pC.buyfrom = 1 #print('f',i) if exp1offer[i] != conproblem and exp1offer[i] == 2: # the problem is not solved pC.problemissolved = 0 pC.payoff = C.con_endowment - C.Price[exp1offer[i] - 1] numcon1mat = [[0, 1], [0, 0]] # row: have problem 1 column: purchased 2 else: # the problem is solved pC.problemissolved = 1 pC.payoff = C.con_endowment + group.pvalue - C.Price[exp1offer[i] - 1] if exp1offer[i] == 1 and conproblem == 1: numcon1mat = [[1, 0], [0, 0]] elif exp1offer[i] == 2 and conproblem == 2: numcon1mat = [[0, 0], [0, 1]] else: numcon1mat = [[0, 0], [1, 0]] else: #consumer purchased from the second expert addpayoff1 = C.exp_endowment addpayoff2 = C.exp_endowment + C.Price[exp2offer[i] - 1] - C.Cost[exp2offer[i] - 1] numreject1 = 1 numcon1 = 0 numcon2 = 1 numcon1mat = [[0, 0], [0, 0]] pC.acceptoffer = exp2offer[i] pC.buyfrom = 2 past2matched = pE2.participant.matchedoffer past2matched.append(exp2offer[i]) pE2.participant.matchedoffer = past2matched #print('consumer num', i) if exp2offer[i] != conproblem and exp2offer[i] == 2: # the problem is not solved pC.problemissolved = 0 pC.payoff = C.con_endowment - C.Price[exp2offer[i] - 1] - group.pk numcon2mat = [[0, 1], [0, 0]] else: # the problem is solved pC.problemissolved = 1 pC.payoff = C.con_endowment + group.pvalue - C.Price[exp2offer[i] - 1] - group.pk if exp2offer[i] == 1 and conproblem == 1: numcon2mat = [[1, 0], [0, 0]] elif exp2offer[i] == 2 and conproblem == 2: numcon2mat = [[0, 0], [0, 1]] else: numcon2mat = [[0, 0], [1, 0]] if exp1offer[i] == 1 and conproblem == 1: numrej1mat = [[1, 0], [0, 0]] elif exp1offer[i] == 1 and conproblem == 2: numrej1mat = [[0, 0], [1, 0]] elif exp1offer[i] == 2 and conproblem == 1: numrej1mat = [[0, 1], [0, 0]] else: numrej1mat = [[0, 0], [0, 1]] pE1.payoff = pE1.payoff + addpayoff1 pE2.payoff = pE2.payoff + addpayoff2 # number of consumer who accepted for each expert pE1.numofconsumer = pE1.numofconsumer + numcon1 pE2.numofconsumer = pE2.numofconsumer + numcon2 # number of consumer who rejected for each expert pE1.numofrej = pE1.numofrej + numreject1 # number of consumer who accepted for each expert (detailed) pE1.numcon11 = pE1.numcon11 + numcon1mat[0][0] pE1.numcon12 = pE1.numcon12 + numcon1mat[0][1] pE1.numcon21 = pE1.numcon21 + numcon1mat[1][0] pE1.numcon22 = pE1.numcon22 + numcon1mat[1][1] pE2.numcon11 = pE2.numcon11 + numcon2mat[0][0] pE2.numcon12 = pE2.numcon12 + numcon2mat[1][0] pE2.numcon21 = pE2.numcon21 + numcon2mat[0][1] pE2.numcon22 = pE2.numcon22 + numcon2mat[1][1] # number of consumer who rejected for each expert (detailed) pE1.numrej11 = pE1.numrej11 + numrej1mat[0][0] pE1.numrej12 = pE1.numrej12 + numrej1mat[0][1] pE1.numrej21 = pE1.numrej21 + numrej1mat[1][0] pE1.numrej22 = pE1.numrej22 + numrej1mat[1][1] #count decision players = group.get_players() sumAcceptH = [p.field_maybe_none('acceptH') for p in players] sumAcceptL = [p.field_maybe_none('acceptL') for p in players] sumovertreat1 = [p.field_maybe_none('overtreat1') for p in players] sumovertreat2 = [p.field_maybe_none('overtreat2') for p in players] sumovertreat3 = [p.field_maybe_none('overtreat3') for p in players] sumovertreat4 = [p.field_maybe_none('overtreat4') for p in players] sumovertreat5 = [p.field_maybe_none('overtreat5') for p in players] sumovertreat6 = [p.field_maybe_none('overtreat6') for p in players] sumovertreat = sumovertreat1 + sumovertreat2 + sumovertreat3 + sumovertreat4 + sumovertreat5 + sumovertreat6 sumovertreat_mat = [sumovertreat1, sumovertreat2, sumovertreat3, sumovertreat4, sumovertreat5, sumovertreat6] totalhon = [] for i in range(len(sumovertreat_mat[0])): #range num of column ind_overtreat = [row[i] for row in sumovertreat_mat] #call columns honest = ind_overtreat.count(0) totalhon.append(honest) if honest == len(sumovertreat_mat): #always honest all zeros in all fields group.numhonestexp = group.numhonestexp + 1 group.numacceptH = sum(filter(None, sumAcceptH)) group.numacceptL = sum(filter(None, sumAcceptL)) group.numovertreat = sum(filter(None, sumovertreat)) group.numhonestoffer = (C.PLAYERS_PER_GROUP // 2)*6 - group.numovertreat for p in players: if p.id_in_group <= C.PLAYERS_PER_GROUP //2: # question1 if p.conacceptH == group.numacceptH: p.guesspoint1 = 1 else: p.guesspoint1 = 0 # question2 if p.conacceptL == group.numacceptL: p.guesspoint2 = 1 else: p.guesspoint2 = 0 # question3 totalopoffer = ((C.PLAYERS_PER_GROUP //2 ) * 6) - 6 opponenthon = (group.numhonestoffer - totalhon[p.id_in_group-1])*100 // totalopoffer if 0 <= opponenthon <= 20: opponenthon_ch = 0 elif 21 <= opponenthon <= 40: opponenthon_ch = 1 elif 41 <= opponenthon <= 60: opponenthon_ch = 2 elif 61 <= opponenthon <= 80: opponenthon_ch = 3 elif 81 <= opponenthon <= 100: opponenthon_ch = 4 else: opponenthon_ch = -2 print('Some things were wrong in counting the honest offer (ex q3)') p.opponenthon_ch = opponenthon_ch if opponenthon_ch == p.opponentOvertreat: p.guesspoint3 = 1 else: p.guesspoint3 = 0 p.total_guesspoints = p.guesspoint1 + p.guesspoint2 + p.guesspoint3 else: # question1 totaloffer = (C.PLAYERS_PER_GROUP // 2 * 6) honoff = (group.numhonestoffer * 100) // totaloffer if 0 <= honoff <= 20: honoff_ch = 0 elif 21 <= honoff <= 40: honoff_ch = 1 elif 41 <= honoff <= 60: honoff_ch = 2 elif 61 <= honoff <= 80: honoff_ch = 3 elif 81 <= honoff <= 100: honoff_ch = 4 else: honoff_ch = -2 print('Some things were wrong in counting the honest offer (co q1)') group.honoff_ch = honoff_ch p.honoff_ch_result = honoff_ch #save the group variable in player class if honoff_ch == p.honestOffer: p.guesspoint1 = 1 else: p.guesspoint1 = 0 # question2 #if p.honestExp == group.numhonestexp: # p.guesspoint2 = 3 #else: # p.guesspoint2 = 0 p.total_guesspoints = p.guesspoint1 #+ p.guesspoint2 def before_next_page1(player: Player, timeout_happened): participant = player.participant # if it's the last round if player.round_number == C.NUM_ROUNDS: b = 4 #number of blocks random_round_mat = [random.sample(range(C.NUM_PRACTICE_ROUNDS + 1, C.NUM_PRACTICE_ROUNDS + C.NUM_REAL_ROUNDS // b + 1), 2), random.sample(range(C.NUM_PRACTICE_ROUNDS + C.NUM_REAL_ROUNDS // b + 1, C.NUM_PRACTICE_ROUNDS + 2*(C.NUM_REAL_ROUNDS // b) + 1), 2), random.sample(range(C.NUM_PRACTICE_ROUNDS + 2*(C.NUM_REAL_ROUNDS // b) + 1, C.NUM_PRACTICE_ROUNDS + 3 * (C.NUM_REAL_ROUNDS // b) + 1),2), random.sample(range(C.NUM_PRACTICE_ROUNDS + 3*(C.NUM_REAL_ROUNDS // b) + 1, C.NUM_ROUNDS + 1), 2)] #print(random_round_mat) selected_around = [row[0] for row in random_round_mat] selected_ground = [row[1] for row in random_round_mat] pick_rounds = selected_around + selected_ground participant.selected_round = pick_rounds #print(participant.selected_round) participant.task2_payoff = 0 for i in range(2 * C.NUM_REAL_ROUNDS // b): player_in_selected_round = player.in_round(pick_rounds[i]) if i == 0: #add only task1 payoffs addpayoff = player_in_selected_round.payoff participant.payoff = addpayoff participant.task1_payoff = addpayoff #print(addpayoff) #print('h') elif i >= C.NUM_REAL_ROUNDS // b: #add only task2 payoffs addpayoff = player_in_selected_round.total_guesspoints participant.payoff = participant.payoff + addpayoff participant.task2_payoff = participant.task2_payoff + addpayoff #print(addpayoff) #print('hh') else: addpayoff = player_in_selected_round.payoff participant.payoff = participant.payoff + addpayoff participant.task1_payoff = participant.task1_payoff + addpayoff #print(addpayoff) #print('hhh') if player.id_in_group <= C.PLAYERS_PER_GROUP // 2: participant.payoff = participant.payoff + C.Total_exp_endowment else: participant.payoff = participant.payoff + C.Total_con_endowment #lottery r = random.uniform(0, 1) participant.savings = C.lottery - player.risk if r >= 0.5: participant.win_lottery = True participant.bonus = C.multiplier * player.risk else: participant.win_lottery = False participant.bonus = 0.0 participant.payoff = roundup(participant.payoff + participant.bonus + participant.savings) participant.risk = player.risk #all_rounds = player.in_all_rounds() #participant.round_players = all_rounds[4:] # PAGES class Passtonewsec(Page): form_model = 'player' form_fields = ['password'] @staticmethod def is_displayed(player): return player.round_number in [C.NUM_PRACTICE_ROUNDS + 8] @staticmethod def error_message(player: Player, values): solution = dict(password=695) if values != solution: return "Your password is incorrect. Please try again" class Intro(Page): @staticmethod def vars_for_template(player): a = C.Role[player.role()] b = player.session.config['within'] c1 = C.NUM_PRACTICE_ROUNDS + 1 c2 = C.NUM_PRACTICE_ROUNDS + 9 #c3 = C.NUM_PRACTICE_ROUNDS + 9 #c4 = C.NUM_PRACTICE_ROUNDS + 13 return dict( a=a, b=b, c1=c1, c2=c2 ) @staticmethod def before_next_page(player: Player, timeout_happened): get_real_round_num(player) problem(player) obsproblem(player) class ExpDe(Page): form_model = 'player' form_fields = ['overtreat1', 'overtreat2', 'overtreat3', 'overtreat4', 'overtreat5', 'overtreat6'] is_displayed = is_displayed_exp @staticmethod def vars_for_template(player): a = player.session.config['beta'] return dict( a=a, ) @staticmethod def before_next_page(player: Player, timeout_happened): offer(player) player.participant.matchedoffer = [] #print('empty:', player.participant.matchedoffer) class ExpGuess(Page): form_model = 'player' form_fields = ['conacceptH', 'conacceptL', 'opponentOvertreat'] is_displayed = is_displayed_exp before_next_page = before_next_page_exp class ConDe(Page): form_model = 'player' form_fields = ['acceptH', 'acceptL'] is_displayed = is_displayed_con @staticmethod def vars_for_template(player): a = player.session.config['beta'] return dict( a=a, ) class ConGuess(Page): form_model = 'player' form_fields = ['honestOffer'] is_displayed = is_displayed_con before_next_page = before_next_page_con class ResultsWaitPage(WaitPage): @staticmethod def is_displayed(player): return player.round_number > C.NUM_PRACTICE_ROUNDS @staticmethod def after_all_players_arrive(group: Group): #if group.subsession.is_practice_round: # print('hehe') # set_payoffs_prac(group) # else: # print('ho') set_payoffs(group) class ExpResults(Page): is_displayed = is_displayed_exp #before_next_page = before_next_page1 @staticmethod def vars_for_template(player): a = len(player.participant.matchedoffer) b = player.participant.matchedoffer.count(1) c = player.participant.matchedoffer.count(2) if player.guesspoint1 > 0: d = 'correct' else: d = 'incorrect' if player.guesspoint2 > 0: e = 'correct' else: e = 'incorrect' f = C.Percentage[player.opponenthon_ch] if player.guesspoint3 > 0: g = 'correct' else: g = 'incorrect' h = player.total_guesspoints return dict( a=a, b=b, c=c, d=d, e=e, f=f, g=g, h=h ) class ConResults(Page): is_displayed = is_displayed_con #before_next_page = before_next_page1 @staticmethod def vars_for_template(player): a = C.Problem[player.problem] b = C.Problem[player.acceptoffer] c = C.Expert[player.buyfrom] d = C.Percentage[player.honoff_ch_result] if player.guesspoint1 > 0: e = 'correct' else: e = 'incorrect' #if player.guesspoint2 > 0: # f = 'correct' #else: # f = 'incorrect' g = player.total_guesspoints return dict( a=a, b=b, c=c, d=d, e=e, #f=f, g=g ) class NewGameWaitPage(WaitPage): wait_for_all_groups = True title_text = 'Waiting for other players to begin the game' body_text = " " @staticmethod def is_displayed(player): return player.round_number == 1 class SectionWaitPage(WaitPage): wait_for_all_groups = True title_text = 'Waiting for other players to begin the new section' body_text = "The experimenter will hand in the new section instructions." @staticmethod def is_displayed(player): return player.round_number in [C.NUM_PRACTICE_ROUNDS, C.NUM_PRACTICE_ROUNDS + 8] class NewpartWaitPage(WaitPage): wait_for_all_groups = True title_text = 'Waiting for other players to begin Part 2' body_text = "Part 2 and 3 instructions will show on your screen." @staticmethod def is_displayed(player): return player.round_number == C.NUM_ROUNDS class Risk(Page): form_model = 'player' form_fields = ['risk'] before_next_page = before_next_page1 @staticmethod def is_displayed(player): return player.round_number == C.NUM_ROUNDS class EndgameWaitPage(WaitPage): wait_for_all_groups = True title_text = 'Waiting for other players' body_text = " " @staticmethod def is_displayed(player): return player.round_number == C.NUM_PRACTICE_ROUNDS + 16 class Endgame(Page): @staticmethod def vars_for_template(player): all_rounds = player.in_all_rounds() round_players = all_rounds[4:] return dict( round_players=round_players ) @staticmethod def is_displayed(player): return player.round_number == C.NUM_ROUNDS page_sequence = [NewGameWaitPage, Intro, ExpDe, ExpGuess, ConDe, ConGuess, ResultsWaitPage, ExpResults, ConResults, SectionWaitPage, Passtonewsec, Endgame, NewpartWaitPage, Risk]