from otree.api import * import shared_constants from experiment_text import comp_choices from session_utils import get_language, merge_t, texts_for doc = """ Practice Round: Replicates Part 1, Part 2, and Part 3 flows with a dummy topic. Opinion codes are 'A' (e.g. dogs) and 'B' (e.g. cats). """ class C(BaseConstants): NAME_IN_URL = 'practice_round' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 PRACTICE_ROOM = {'label': '6A-H', 'majority_n': 6, 'minority_n': 4, 'cost_val': 20} PUNISHMENT_FEE = shared_constants.PUNISHMENT_FEE PREDICTION_BONUS = 10 class Subsession(BaseSubsession): pass def creating_session(subsession): if subsession.round_number == 1: lang = subsession.session.config.get('language', 'en') for p in subsession.get_players(): p.participant.vars['language'] = lang p.participant.session_language = lang class Group(BaseGroup): pass class Player(BasePlayer): practice_opinion = models.StringField( label="", widget=widgets.RadioSelect, ) practice_punish = models.BooleanField( label="", choices=[ [True, "Yes"], [False, "No"], ], widget=widgets.RadioSelect, ) practice_expressed = models.StringField( label="", widget=widgets.RadioSelect, ) practice_belief = models.IntegerField( min=0, max=10, label="", ) # --- Comprehension Check Fields --- comp_q1 = models.IntegerField( label="", choices=[ [1, "1"], [2, "2"], [3, "3"], ], widget=widgets.RadioSelect, ) comp_q2 = models.IntegerField( label="", choices=[ [1, "1"], [2, "2"], [3, "3"], ], widget=widgets.RadioSelect, ) comp_q3 = models.IntegerField( label="", choices=[ [1, "1"], [2, "2"], [3, "3"], ], widget=widgets.RadioSelect, ) def practice_opinion_choices(player): t = texts_for(player) return [ ['A', t['practice_option_dogs']], ['B', t['practice_option_cats']], ] def practice_punish_choices(player): t = texts_for(player) return [[True, t['yes']], [False, t['no']]] def _practice_label(t, code): return t['practice_option_dogs'] if code == 'A' else t['practice_option_cats'] def practice_expressed_choices(player): t = texts_for(player) true_code = player.practice_opinion other = 'B' if true_code == 'A' else 'A' return [ ['true', _practice_label(t, true_code)], ['lie', _practice_label(t, other)], ] def comp_q1_choices(player): return comp_choices(get_language(player), 'q1') def comp_q2_choices(player): return comp_choices(get_language(player), 'q2') def comp_q3_choices(player): return comp_choices(get_language(player), 'q3') class PracticePart1(Page): form_model = 'player' form_fields = ['practice_opinion', 'practice_punish'] @staticmethod def vars_for_template(player): t = texts_for(player) topic = t['practice_topic'] cost = C.PUNISHMENT_FEE return merge_t( player, { 'topic': topic, 'cost': cost, 'page_title': t['practice_title_p1'].format(topic=topic), 'practice_q2_heading_f': t['practice_q2_heading'].format(cost=cost), 'practice_q2_help_f': t['practice_q2_help'].format(cost=cost), }, ) class PracticePart2(Page): form_model = 'player' form_fields = ['practice_expressed'] @staticmethod def vars_for_template(player): room = C.PRACTICE_ROOM t = texts_for(player) topic = t['practice_topic'] true_code = player.practice_opinion majority_code = 'A' if true_code == 'B' else 'B' true_opinion_label = _practice_label(t, true_code) majority_opinion_label = _practice_label(t, majority_code) image_name = f"{room['majority_n']}A-H.png" return merge_t( player, { 'topic': topic, 'true_opinion': true_opinion_label, 'majority_opinion': majority_opinion_label, 'room': room, 'current_c_val': room['cost_val'], 'image_path': 'room_composition/' + image_name, 'page_title': t['practice_p2_title'].format(topic=topic), 'practice_p2_p1': t['practice_p2_p1'].format( maj=room['majority_n'], minr=room['minority_n'], maj_op=majority_opinion_label, true_op=true_opinion_label, topic=topic, labeled_a=t['labeled_as_a'], labeled_b=t['labeled_as_b'], ), 'practice_p2_p2': t['practice_p2_p2'].format(cost=room['cost_val']), }, ) class PracticePart3(Page): form_model = 'player' form_fields = ['practice_belief'] @staticmethod def vars_for_template(player): room = C.PRACTICE_ROOM t = texts_for(player) topic = t['practice_topic'] true_code = player.practice_opinion majority_code = 'A' if true_code == 'B' else 'B' my_label = _practice_label(t, true_code) maj_label = _practice_label(t, majority_code) image_name = f"{room['majority_n']}A-H.png" return merge_t( player, { 'topic': topic, 'my_true_opinion': my_label, 'majority_opinion': maj_label, 'room': room, 'current_c_val': room['cost_val'], 'image_path': 'room_composition/' + image_name, 'page_title': t['practice_p3_title'], 'practice_p3_li1': t['practice_p3_li1'].format(op=my_label, topic=topic), 'practice_p3_li2': t['practice_p3_li2'].format( maj=room['majority_n'], minr=room['minority_n'], maj_op=maj_label, my_op=my_label, opt_a=t['paren_option_a'], opt_b=t['paren_option_b'], ), 'practice_p3_li3': t['practice_p3_li3'].format(cost=room['cost_val']), 'practice_belief_prompt_f': t['practice_belief_prompt'].format(op=my_label), }, ) class ComprehensionCheck(Page): form_model = 'player' form_fields = ['comp_q1', 'comp_q2', 'comp_q3'] @staticmethod def vars_for_template(player): return merge_t(player) class PracticeResults(Page): @staticmethod def vars_for_template(player): cost_p1 = C.PUNISHMENT_FEE if player.practice_punish else 0 cost_p2 = C.PRACTICE_ROOM['cost_val'] if player.practice_expressed == 'lie' else 0 total_earnings = 1 - cost_p1 - cost_p2 + C.PREDICTION_BONUS t = texts_for(player) bonus = C.PREDICTION_BONUS return merge_t( player, { 'cost_p1': cost_p1, 'cost_p2': cost_p2, 'bonus_p3': bonus, 'total_loss': cost_p1 + cost_p2, 'total_earnings': total_earnings, 'practice_results_erase_td': ( t['practice_results_erase_yes'].format(cost=cost_p1) if cost_p1 > 0 else t['practice_results_erase_no'] ), 'practice_results_prediction_td': t['practice_results_prediction_text'].format(bonus=bonus), }, ) page_sequence = [PracticePart1, PracticePart2, PracticePart3, PracticeResults, ComprehensionCheck]