from cProfile import label from pickle import TRUE import random import numpy as np from otree.api import * author = 'Jing Zhou' 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') 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() scenario = 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() # What are the compositions of Box O and Box G? Ans: 1 CQ1 = models.IntegerField(widget=widgets.RadioSelect, label='') CQ2 = models.IntegerField(widget=widgets.RadioSelect, label='') CQ3 = models.IntegerField(widget=widgets.RadioSelect, label='') CQ4 = models.IntegerField(widget=widgets.RadioSelect, label='') # record the submission for each task num_failed_attempts = models.FloatField(initial=0) failed_more_than1 = models.BooleanField(initial=False) # Rank the reports by usefulness ratio_rank = models.IntegerField(widget=widgets.RadioSelect, label='', choices=[ [1, 'Extremely useful'], [2, 'Useful'], [3, 'Somewhat useful'], [4, 'Neither useful nor useless'], [5, 'Somewhat useless'], [6, 'Useless'], [7, 'Extremely useless'], ]) difference_rank = models.IntegerField(widget=widgets.RadioSelect, label='', choices=[ [1, 'Extremely useful'], [2, 'Useful'], [3, 'Somewhat useful'], [4, 'Neither useful nor useless'], [5, 'Somewhat useless'], [6, 'Useless'], [7, 'Extremely useless'], ]) count_rank = models.IntegerField(widget=widgets.RadioSelect, label='', choices=[ [1, 'Extremely useful'], [2, 'Useful'], [3, 'Somewhat useful'], [4, 'Neither useful nor useless'], [5, 'Somewhat useless'], [6, 'Useless'], [7, 'Extremely useless'], ]) sequence_rank = models.IntegerField(widget=widgets.RadioSelect, label='', choices=[ [1, 'Extremely useful'], [2, 'Useful'], [3, 'Somewhat useful'], [4, 'Neither useful nor useless'], [5, 'Somewhat useless'], [6, 'Useless'], [7, 'Extremely useless'], ]) criteria = models.LongStringField( label='', ) # demographic info gender = models.IntegerField(label='What is your gender?', widget=widgets.RadioSelect, choices=[ [1, 'Female'], [2, 'Male'], [3, 'Others'], [4, 'Prefer not to state'] ]) age = models.IntegerField(label='What is your age group?', widget=widgets.RadioSelect, choices=[ [1, 'Under 18'], [2, '18 - 24'], [3, '25 - 34'], [4, '35 - 44'], [5, '45 - 54'], [6, '55 - 70'], [7, 'Above 70'], [8, 'Prefer not to answer'] ]) edu = models.IntegerField(label='What is your highest level of education?', widget=widgets.RadioSelect, choices=[ [1, 'Did not graduate high school'], [2, 'High school graduate, diploma, or equivalent (such as GED)'], [3, 'Began college, no degree'], [4, 'Associate degree'], [5, 'Bachelor degree'], [6, 'Postgraduate or professional degree'] ] ) familiar_stat = models.IntegerField(label='Do you consider yourself familiar with probability theory and statistics?', widget=widgets.RadioSelect, choices=[ [1, 'Yes'], [2, 'No'], ] ) excel_count = models.IntegerField( label='Do you consider yourself good at counting and estimating numbers?', widget=widgets.RadioSelect, choices=[ [1, 'Yes'], [2, 'No'], ] ) quiz1 = models.IntegerField(label='A bat and a ball cost $10.50 in total. The bat costs $10.00 more than the ball. How much does the ball cost?', widget=widgets.RadioSelect, choices=[ [1, '$0.50'], [2, '$10.00'], [3, '$10.25'], [4, '$0.25'] ] ) quiz2 = models.IntegerField(label='If it takes 7 machines 7 minutes to make 7 widgets, how long would it take 70 mechines to make 70 widgets?', widget=widgets.RadioSelect, choices=[ [1, '1 minutes'], [2, '490 minutes'], [3, '70 minutes'], [4, '7 minutes'] ] ) quiz3 = models.IntegerField(label='In a community, there is a rapidly-spreading virus. Every day, the virus infects twice as many people. If it takes 42 days for the virus to infect the entire community, how long would it take the virus to infect half the community?', widget=widgets.RadioSelect, choices=[ [1, '21 days'], [2, '42 days'], [3, '2 days'], [4, '41 days'] ]) def get_box(player): box = random.randint(1, 2) return box def get_signal_N(player): signal_N = random.choice([1, 5, 7, 15, 75, 135, 225]) 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(225)] 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 Box G = 1 Box O = 2 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()#sample size signal = player.get_signal(box,signal_N) report_t = random.randint(2,5) # if box==1: signal_count1 = signal.count(1) signal_count2 = signal.count(2) 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_count1 2: player.failed_more_than1 = True else: return errors @staticmethod def before_next_page(player: Player, timeout_happened): session = player.session participant = player.participant if player.failed_more_than1 == False: session.completions_by_treatment[participant.color] += 1 else: session.completions_by_treatment[participant.color] += 0 class Failed(Page): @staticmethod def is_displayed(player: Player): return player.failed_more_than1 class Part2Prepare(Page): timeout_seconds = 0 @staticmethod def before_next_page(player: Player, timeout_happened): if player.round_number == 1: player.stage2_seq = str(player.get_stage2_seq()) else: player.stage2_seq = player.in_round(1).stage2_seq stage2_seq = player.stage2_seq.strip('][').split(', ') stage2_question = int(stage2_seq[player.round_number - 1]) use_assigned_report = int(stage2_question <= Constants.preassigned_length) player.preassigned = use_assigned_report box = player.get_box() if use_assigned_report == 1: preassigened_list_this = Constants.preassigned_list[stage2_question - 1] report_t = int(preassigened_list_this['form']) player.report_t = report_t player.box = box player.scenario = int(preassigened_list_this['id']) signal_N = int(preassigened_list_this['sample_size']) player.signal_N = signal_N if box == 1: if preassigened_list_this['signal_count1'] != '': signal_count1 = int(preassigened_list_this['signal_count1']) signal_count2 = int(preassigened_list_this['signal_count2']) else: signal_count1 = 9999 signal_count2 = 9999 if preassigened_list_this['signal_ratio'] != '': signal_ratio1 = 100 - int(preassigened_list_this['signal_ratio']) signal_ratio2 = 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(225): # max signal length if i <= (len(signal_raw) - 1) and len(signal_raw) > 0: 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_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(225): # max signal length if i <= (len(signal_raw) - 1) and 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_ratio1 = data[1] signal_diff = data[2] signal_count1 = data[3] signal = int(str(data[4]).strip('][').replace(', ', '').replace('0', '')) signal_reverse = int( str(data[4]).strip('][').replace(', ', '').replace('1', '3').replace('2', '1').replace('3', '2').replace( '0', '')) signal_N = data[5] 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 == 2: if ((signal_ratio1 == int(current_checking_question['signal_ratio']) and signal_N == int( current_checking_question['sample_size'])) or (signal_ratio1 == 100 - int( current_checking_question['signal_ratio']) and signal_N == int( current_checking_question['sample_size']))): return False if report_t == 3: if ((signal_diff == int(current_checking_question['signal_diff']) and signal_N == int( current_checking_question['sample_size'])) or (signal_diff == -int(current_checking_question['signal_diff']) and signal_N == int( current_checking_question['sample_size']))): return False if report_t == 4: if ((signal_count1 == int(current_checking_question['signal_count1']) and signal_N == int( current_checking_question['sample_size'])) or (signal_count1 == int( current_checking_question['signal_count2']) and signal_N == int( current_checking_question['sample_size']))): 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_ratio1 = data[1] signal_diff = data[2] signal_count1 = data[3] signal_count2 = len(data[4]) - signal_count1 signal = str(data[4]) signal_reverse = str(data[4]).replace('1', '3').replace('2', '1').replace('3', '2') signal_N = data[5] 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 == 2: if (( signal_ratio1 == current_checking_question.signal_ratio and signal_N == current_checking_question.signal_N) or ( signal_ratio1 == 100 - current_checking_question.signal_ratio and signal_N == current_checking_question.signal_N)): return False if report_t == 3: if (( signal_diff == current_checking_question.signal_diff and signal_N == current_checking_question.signal_N) or ( signal_diff == -current_checking_question.signal_diff and signal_N == current_checking_question.signal_N)): return False if report_t == 4: if (( signal_count1 == current_checking_question.signal_count1 and signal_N == current_checking_question.signal_N) or ( signal_count2 == current_checking_question.signal_count1 and signal_N == current_checking_question.signal_N)): 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(2, 5) signal_count1 = signal.count(1) signal_count2 = signal.count(2) 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_ratio1, signal_diff, signal_count1, signal, signal_N] 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_diff = signal_diff player.signal_ratio = signal_ratio1 player.signal_count1 = signal_count1 player.signal_count2 = signal_count2 player.signal_N = signal_N @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_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 rows = [] num_cells = len(signal) for row_number in range(1, num_cells + 1): rows.append( dict( row_number=row_number, cells=signal[row_number - 1], is_last=row_number == num_cells, divisible_by_4=row_number % 15 == 0, ) ) return dict(box=box, signal_N=signal_N, signal=signal, signal_ratio1=signal_ratio1, signal_ratio2=signal_ratio2, signal_count1=signal_count1, signal_count2=signal_count2, signal_diff=signal_diff, signal_raw=signal_raw, signal_diff_abs=signal_diff_abs, report_t=report_t, num_rounds=Constants.num_rounds - 1, num_cells=num_cells, rows=rows, 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_ratio1 = data[1] signal_diff = data[2] signal_count1 = data[3] signal = str(data[4]) signal_N = 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 == 2: if (signal_ratio1==current_checking_question.signal_ratio and signal_N == current_checking_question.signal_N): return current_checking_question.round_number if report_t == 3: if (signal_diff==current_checking_question.signal_diff and signal_N == current_checking_question.signal_N): return current_checking_question.round_number if report_t == 4: if (signal_count1==current_checking_question.signal_count1 and signal_N == current_checking_question.signal_N): 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 if player.round_number == Constants.num_rounds: cards = random.sample(list(range(2,5)), k=2) card1 = cards[0] card2 = cards[1] #randomly pick two ranks player_choice = player.in_round(Constants.num_rounds) # rank_ratio = player_choice.ratio_rank # rank_difference = player_choice.difference_rank # rank_count = player_choice.count_rank # rank_seq = player_choice.sequence_rank # ranks = [rank_ratio,rank_difference,rank_count,rank_seq] # if ranks[card1-2] < ranks[card2-2]: # player.picked_report = card1 # elif ranks[card1-2] > ranks[card2-2]: # player.picked_report = card2 # else: # random_select = random.randint(1,2) # player.picked_report = cards[random_select-1] # # player.picked_rank1 = ranks[card1-2] # player.picked_rank2 = ranks[card2-2] # # player.card1 = card1 # player.card2 = card2 reports_t = player.get_reports_t() played_round = check_existed_list([reports_t['report_t'], reports_t['signal_ratio1'], reports_t['signal_diff'], reports_t['signal_count1'], reports_t['signal'], reports_t['signal_N'],]) player.played_round = played_round 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_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.signal_N = reports_t['signal_N'] 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_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 player.signal_N = played_data.signal_N class Part3(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_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 signal_N = player.signal_N rows = [] num_cells = len(signal) # picked_report = player.picked_report # card1 = player.card1 # card2 = player.card2 # picked_rank1 = player.picked_rank1 # picked_rank2 = player.picked_rank2 for row_number in range(1, num_cells + 1): rows.append( dict( row_number=row_number, cells=signal[row_number - 1], is_last=row_number == num_cells, divisible_by_4=row_number % 15 == 0, ) ) return dict(played_round = played_round, box=box, report_t=report_t, signal=signal, signal_N=signal_N, signal_ratio1=signal_ratio1, signal_ratio2=signal_ratio2, signal_count1=signal_count1, signal_count2=signal_count2, signal_diff=signal_diff, signal_diff_abs=abs(signal_diff), belief_dummy=belief_dummy, num_cells=num_cells, # picked_report=picked_report, # picked_rank1=picked_rank1, # picked_rank2=picked_rank2, rows=rows, # card1=card1, # card2=card2, belief_dummy2=belief_dummy2) @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds) @staticmethod def before_next_page(player: Player, timeout_happened): played_round = player.played_round class ranking(Page): form_model = 'player' form_fields = ['ratio_rank', 'difference_rank', 'count_rank', 'sequence_rank', 'criteria'] @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds 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 player.random_ball1 = 100 * random.random() player.random_ball2 = 100 * random.random() random_num1 = round(player.random_ball1,2) random_num2 = round(player.random_ball2,2) if box == 1: payoff_belief = round(5 * int(belief>min(random_num1,random_num2))) elif box == 2: payoff_belief = round(5 * int(belief2>min(random_num1,random_num2))) payoff = round(payoff_belief +showup,2) player.payoff = payoff return dict(box=box, belief=belief, belief2 = belief2, random_num1=random_num1, random_num2=random_num2, showup = showup, payoff_belief = payoff_belief, payoff=payoff) @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds @staticmethod def before_next_page(player, timeout_happened): player.participant.finished = True class Survey1(Page): form_model = 'player' form_fields = ['feedback_box', 'strategy_box2', 'strategy_box3', 'strategy_box4', 'strategy_box5'] @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds class Survey2(Page): form_model = 'player' form_fields = ['gender', 'age', 'edu', 'familiar_stat', 'excel_count', 'quiz1', 'quiz2', 'quiz3'] @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 = [ Intro2, Intro3, ComprehensionQuestions, Failed, Part2Prepare, Part2, Part3Intro, Part3, ranking, Survey1, Survey2, Results]