from cProfile import label import random import numpy as np from otree.api import * author = 'ChienHsun Lin' doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'Bayesian_Grouping' players_per_group = None import csv with open('Bayesian_Grouping/preassigned_list.csv',encoding='utf-8') as file: preassigned_list = list(csv.DictReader(file)) preassigned_length = len(preassigned_list) random_rounds = 0 num_rounds = preassigned_length+random_rounds+1 # MODIFY ONLY THE FIRST NUMBER FOR ROUNDS #num_rounds = 3 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): form1 = models.FloatField() form2 = models.FloatField() form3 = models.FloatField() form4 = models.FloatField() form5 = models.FloatField() belief = models.IntegerField() practice_belief_1 = models.IntegerField() practice_belief_2 = models.IntegerField() payment_stage = models.IntegerField() box = models.IntegerField() report_order = models.StringField() report_t = models.IntegerField() signal_N = models.IntegerField() signal = models.StringField() stage2_seq = models.StringField() preassigned = models.IntegerField() name = models.StringField(label="Your name:") perm = models.StringField(label="Your perm number (first 6 digits):") venmo = models.StringField(label="Your Venmo ID:") gender = models.IntegerField(label="Your gender:", choices=[ [1, 'Female'], [2, 'Male'], [3, 'Others'], [4, 'Prefer not to state'] ] ) major = models.StringField(label="Your Major:") grade = models.IntegerField(label="The current year of school you're in:", choices=[ [1, '1st year undergraduate'], [2, '2nd year undergraduate'], [3, '3rd year undergraduate'], [4, '4th year undergraduate'], [5, '5th year or higher undergraduate'], [6, 'graduate school'] ] ) def get_box(player): box = random.randint(1, 2) return box def get_signal_N(player): signal_N = random.choice([3, 5, 9, 15]) return signal_N def get_stage2_seq(player): #Assign pre-determined reports num_list = [i for i in range(1,Constants.num_rounds)] stage2_seq = random.sample(num_list,k=len(num_list)) return stage2_seq def get_signal(player,box,signal_N): signal = [0 for i in range(15)] for i in range(signal_N): if box == 1: signal[i] = int(random.randint(1, 10) > 7) + 1 #30% gets 2=green #70% gets 1=orange if box == 2: signal[i] = int(random.randint(1, 10) <= 7) + 1 return signal def get_reports_t(player): box = player.get_box() signal_N = player.get_signal_N() signal = player.get_signal(box,signal_N) report_t = random.randint(1,5) # if box==1: signal_count1 = signal.count(1) signal_count2 = signal.count(2) signal_majority = int(signal_count1>signal_count2) signal_ratio1 = round(signal_count1/signal_N*100) signal_ratio2 = round(signal_count2/signal_N*100) signal_diff = signal_count1-signal_count2 # if box==2: # signal_count1 = signal.count(2) # signal_count2 = signal.count(1) # signal_majority = int(signal_count10: signal+=[int(signal_raw[i])] else: signal+=[0] player.signal=str(signal) if box ==2: if preassigened_list_this['signal_count1']!='': signal_count1 = int(preassigened_list_this['signal_count2']) signal_count2 = int(preassigened_list_this['signal_count1']) else: signal_count1 = 9999 signal_count2 = 9999 if preassigened_list_this['signal_majority']!='': signal_majority = 1-int(preassigened_list_this['signal_majority']) else: signal_majority = 9999 if preassigened_list_this['signal_ratio']!='': signal_ratio1 = int(preassigened_list_this['signal_ratio']) signal_ratio2 = 100-int(preassigened_list_this['signal_ratio']) else: signal_ratio1 = 9999 signal_ratio2 = 9999 if preassigened_list_this['signal_diff']!='': signal_diff = -int(preassigened_list_this['signal_diff']) else: signal_diff = 9999 signal_raw = preassigened_list_this['signal_str'] signal = [] for i in range(15): #max signal length if i <= (len(signal_raw)-1) & len(signal_raw)>0: signal+=[3-int(signal_raw[i])] #1->2 / 2->1 else: signal+=[0] player.signal=str(signal) else: def check_preassigned_list(data): report_t = data[0] signal_majority = data[1] signal_ratio1 = data[2] signal_diff = data[3] signal_count1 = data[4] signal = int(str(data[5]).strip('][').replace(', ','').replace('0', '')) signal_reverse = int(str(data[5]).strip('][').replace(', ','').replace('1','3').replace('2','1').replace('3','2').replace('0','')) preassigned_forms = Constants.preassigned_list for i in range(Constants.preassigned_length): current_checking_question = preassigned_forms[i] if (report_t==int(current_checking_question['form'])): if report_t == 1: return False if report_t == 2: if (signal_ratio1==int(current_checking_question['signal_ratio']) or signal_ratio1==100-int(current_checking_question['signal_ratio'])) : return False if report_t == 3: if signal_diff==int(current_checking_question['signal_diff']): return False if report_t == 4: if (signal_count1==int(current_checking_question['signal_count1']) or signal_count1==int(current_checking_question['signal_count2'])): return False if report_t == 5: #print(signal,'or',signal_reverse,'vs',current_checking_question['signal_str']) if (signal==int(current_checking_question['signal_str']) or signal_reverse == int(current_checking_question['signal_str'])): return False return True def check_existed_list(data): report_t = data[0] signal_majority = data[1] signal_ratio1 = data[2] signal_diff = data[3] signal_count1 = data[4] signal_count2 = len(data[5]) - signal_count1 signal = str(data[5]) signal_reverse = str(data[5]).replace('1','3').replace('2','1').replace('3','2') past_para = player.in_previous_rounds() if player.round_number>1: for i in range(player.round_number-1): if int(stage2_seq[i]) < Constants.preassigned_length: continue current_checking_question = past_para[i] if (report_t==current_checking_question.report_t): if report_t == 1: return False if report_t == 2: if (signal_ratio1==current_checking_question.signal_ratio or signal_ratio1==100-current_checking_question.signal_ratio ): return False if report_t == 3: if signal_diff==current_checking_question.signal_diff: return False if report_t == 4: if (signal_count1==current_checking_question.signal_count1 or signal_count2==current_checking_question.signal_count1): return False if report_t == 5: if (signal==current_checking_question.signal or signal_reverse == current_checking_question.signal): return False return True while True: signal_N = player.get_signal_N() signal = player.get_signal(box,signal_N) report_t = random.randint(1,5) signal_count1 = signal.count(1) signal_count2 = signal.count(2) signal_majority = int(signal_count1>signal_count2) signal_ratio1 = round(signal_count1/signal_N*100) signal_ratio2 = round(signal_count2/signal_N*100) signal_diff = signal_count1-signal_count2 info_t = [report_t,signal_majority,signal_ratio1,signal_diff,signal_count1,signal] check_flag = check_preassigned_list(info_t) and check_existed_list(info_t) # print('assigned:',check_preassigned_list(info_t),', appeared:',check_existed_list(info_t)) if check_flag==True: break player.report_t = report_t player.box = box player.signal_N=signal_N player.signal=str(signal) player.signal_majority = signal_majority player.signal_diff = signal_diff player.signal_ratio = signal_ratio1 player.signal_count1 = signal_count1 player.signal_count2 = signal_count2 @staticmethod def is_displayed(player: Player): return player.round_number < Constants.num_rounds class Part2(Page): form_model = 'player' form_fields = ['belief'] @staticmethod def vars_for_template(player: Player): stage2_seq = player.stage2_seq.strip('][').split(', ') box = player.box report_t = player.report_t #signal_N = player.signal_N signal = [] signal_raw = player.signal.strip('][').split(', ') for i in range(len(signal_raw)): signal += [int(signal_raw[i])] signal_majority = player.signal_majority signal_diff = player.signal_diff signal_diff_abs = abs(signal_diff) signal_ratio1 = player.signal_ratio signal_ratio2 = 100 - player.signal_ratio signal_count1 = player.signal_count1 signal_count2 = player.signal_count2 return dict(box=box, #signal_N=signal_N, signal=signal, signal_ratio1 = signal_ratio1, signal_ratio2 = signal_ratio2, signal_majority = signal_majority, signal_count1 = signal_count1, signal_count2 = signal_count2, signal_diff = signal_diff, signal_diff_abs = signal_diff_abs, report_t = report_t, num_rounds = Constants.num_rounds-1, stage2_seq=stage2_seq) @staticmethod def is_displayed(player: Player): return player.round_number < Constants.num_rounds class Part3Intro(Page): @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds @staticmethod def vars_for_template(player: Player): return dict(num_of_questions = Constants.num_rounds-1) @staticmethod def before_next_page(player: Player, timeout_happened): def check_existed_list(data): report_t = data[0] signal_majority = data[1] signal_ratio1 = data[2] signal_diff = data[3] signal_count1 = data[4] signal = str(data[5]) past_para = player.in_previous_rounds() if player.round_number>1: for i in range(player.round_number-1): current_checking_question = past_para[i] if (report_t==current_checking_question.report_t): if report_t == 1: if signal_majority == current_checking_question.signal_majority: return current_checking_question.round_number if report_t == 2: if signal_ratio1==current_checking_question.signal_ratio: return current_checking_question.round_number if report_t == 3: if (signal_diff==current_checking_question.signal_diff and signal_majority == current_checking_question.signal_majority): return current_checking_question.round_number if report_t == 4: if signal_count1==current_checking_question.signal_count1: return current_checking_question.round_number if report_t == 5: if signal==current_checking_question.signal: return current_checking_question.round_number return 0 #Code starts here player.random_ball1 = 100*random.random() player.random_ball2 = 100*random.random() if player.round_number == Constants.num_rounds: payment_stage = random.randint(1, 2) player.payment_stage = payment_stage if payment_stage==1: cards = random.sample(list(range(1,26)),k=2) #21-25: reports 1-5 card1 = cards[0] card2 = cards[1] reports_t = player.get_reports_t() player.box = reports_t['box'] #player.report_t = reports_t['report_t'] player.signal_majority = reports_t['signal_majority'] player.signal_ratio = reports_t['signal_ratio1'] player.signal_diff = reports_t['signal_diff'] player.signal_count1 = reports_t['signal_count1'] player.signal_count2 = reports_t['signal_count2'] player.signal = str(reports_t['signal']) player.card1=card1 player.card2=card2 elif payment_stage==2: reports_t = player.get_reports_t() played_round = check_existed_list([reports_t['report_t'], reports_t['signal_majority'], reports_t['signal_ratio1'], reports_t['signal_diff'], reports_t['signal_count1'], reports_t['signal'],]) player.played_round = played_round player.payoff_from_card = 0 #positive only in Stage 1 if played_round==0: player.box = reports_t['box'] player.signal_N = reports_t['signal_N'] player.report_t = reports_t['report_t'] player.signal_majority = reports_t['signal_majority'] player.signal_ratio = reports_t['signal_ratio1'] player.signal_diff = reports_t['signal_diff'] player.signal_count1 = reports_t['signal_count1'] player.signal_count2 = reports_t['signal_count2'] player.signal = str(reports_t['signal']) elif played_round>0: played_data = player.in_round(played_round) player.box = played_data.box player.report_t = played_data.report_t player.signal_majority = played_data.signal_majority player.signal_ratio = played_data.signal_ratio player.signal_diff = played_data.signal_diff player.signal_count1 = played_data.signal_count1 player.signal_count2 = played_data.signal_count2 player.signal = played_data.signal class Part3_1(Page): form_model = 'player' form_fields = ['belief'] @staticmethod def vars_for_template(player: Player): box = player.box order_raw = player.in_round(1).report_order.strip('][').split(' ') report_order=[] for i in range(len(order_raw)): report_order += [int(order_raw[i])] # FINDING OUT THE WINNING CARDS cards = [player.card1,player.card2] card1 = cards[0] if card1>20: card1_money = 0 else: card1_money = round(card1/4,2) card2 = cards[1] if card2>20: card2_money = 0 else: card2_money = round(card2/4,2) player_choice = player.in_round(1) form1WTP = player_choice.form1 form2WTP = player_choice.form2 form3WTP = player_choice.form3 form4WTP = player_choice.form4 form5WTP = player_choice.form5 WTPs = [form1WTP,form2WTP,form3WTP,form4WTP,form5WTP] #Draw balls signal = [] signal_raw = player.signal.strip('][').split(', ') for i in range(len(signal_raw)): signal += [int(signal_raw[i])] signal_majority = player.signal_majority signal_ratio1 = player.signal_ratio signal_ratio2 = 100 - player.signal_ratio signal_diff = player.signal_diff signal_count1 = player.signal_count1 signal_count2 = player.signal_count2 if max(cards)>20 and min(cards)<= 20: #Report + Money comparing_WTP = min(cards)/10 report_WTP = WTPs[max(cards)-20-1] if report_WTP>= comparing_WTP: winning_card = max(cards) report_wins = 1 winning_report = report_order[winning_card-21] player.report_t = winning_report payoff_from_card = 0 else: winning_card=min(cards) payoff_from_card = round(min(cards)/4,2) report_wins = 0 winning_report = 0 elif max(cards)>20 and min(cards)>20: report_wins = 1 report_WTP1 = WTPs[min(cards)-20-1] report_WTP2 = WTPs[max(cards)-20-1] payoff_from_card = 0 if report_WTP1 > report_WTP2: winning_card=min(cards) winning_report = report_order[winning_card-21] player.report_t = winning_report elif report_WTP1 < report_WTP2: winning_card = max(cards) winning_report = report_order[winning_card-21] player.report_t = winning_report else: report_wins = 0 winning_card = max(cards) winning_report = 0 payoff_from_card = round(max(cards)/4,2) payoff_from_card = round(payoff_from_card,2) player.payoff_from_card = payoff_from_card return dict(card1 = card1, card2 = card2, box = box, card1_money = card1_money, card2_money = card2_money, winning_card = winning_card, winning_report = winning_report, payoff_from_card = payoff_from_card, signal=signal, signal_ratio1 = signal_ratio1, signal_ratio2 = signal_ratio2, signal_majority = signal_majority, signal_count1 = signal_count1, signal_count2 = signal_count2, signal_diff = signal_diff, signal_diff_abs = abs(signal_diff), report_wins = report_wins) @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds and player.payment_stage == 1) class Part3_2(Page): form_model = 'player' form_fields = ['belief'] @staticmethod def vars_for_template(player: Player): played_round = player.played_round if played_round>0: belief_dummy = player.in_round(played_round).belief belief_dummy2 = 100-belief_dummy player.belief = belief_dummy else: belief_dummy = -1 belief_dummy2 = -1 box = player.box report_t = player.report_t signal = [] signal_raw = player.signal.strip('][').split(', ') for i in range(len(signal_raw)): signal += [int(signal_raw[i])] signal_majority = player.signal_majority signal_ratio1 = player.signal_ratio signal_ratio2 = 100 - player.signal_ratio signal_diff = player.signal_diff signal_count1 = player.signal_count1 signal_count2 = player.signal_count2 return dict(played_round = played_round, box = box, report_t = report_t, signal=signal, signal_ratio1 = signal_ratio1, signal_ratio2 = signal_ratio2, signal_majority = signal_majority, signal_count1 = signal_count1, signal_count2 = signal_count2, signal_diff = signal_diff, signal_diff_abs = abs(signal_diff), belief_dummy = belief_dummy, belief_dummy2 = belief_dummy2) @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds and player.payment_stage == 2) @staticmethod def before_next_page(player: Player, timeout_happened): played_round = player.played_round class Results(Page): form_model = 'player' # form_fields = ['feedback_box','strategy_box'] @staticmethod def vars_for_template(player: Player): showup = 5 box = player.box belief = player.belief belief2 = 100 - belief payoff_from_card = round(player.payoff_from_card,2) random_num1 = round(player.random_ball1,2) random_num2 = round(player.random_ball2,2) if box == 1: payoff_belief = round(10 * int(belief>min(random_num1,random_num2))) elif box == 2: payoff_belief = round(10 * int(belief2>min(random_num1,random_num2))) payoff = round(payoff_belief + payoff_from_card +showup,2) player.payoff = payoff return dict(box=box, belief=belief, belief2 = belief2, random_num1=random_num1, random_num2=random_num2, showup = showup, payoff_from_card = payoff_from_card, payoff_belief = payoff_belief, payoff=payoff) @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds class Survey2(Page): form_model = 'player' # form_fields = ['gender', 'major','grade','feedback_box','strategy_box'] form_fields = ['gender', 'major','grade'] @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds class End(Page): @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds page_sequence = [Consent, Survey1, Intro1, Intro2, Practice1, Practice2, Part1Intro, Part1, Part2Intro, Part2Prepare, Part2, Part3Intro, Part3_1, Part3_2, Results, Survey2, End] ###Maybe switch the position of the boxes?