""" NOTE: I replaced with . and replace {% load otree %} with {% load static otree %} (used for the Instrucitons page and Decisions pages). The highcharts now has license issue and the website is not approachable, so I copy paste the js codes and saved as a js. file under static. """ from otree.api import * from .models import Constants # ========================= # Introduction for each task/round # ========================= ROUND1_TEXT_Decision1 = "
In this game you can choose between box U or box K, both containing 100 balls, " \ "which can be either purple or yellow. One ball will be drawn from the box you have chosen. " \ "You will win $5 if a purple ball is drawn. You will win $0 if a yellow ball is drawn.
" \ "For box K you can see the exact proportion of purple balls and yellow balls below. " \ "Box U also contains purple and yellow balls, " \ "but the proportions are not shown in advance. " \ "Hence, both boxes contain 100 balls with two different colors (purple and yellow). " \ "The composition of purple and yellow balls is known (K) for box K and unknown (U) for box U.
" \ "Please select the box of your choice: U or K. If you think both boxes are equally attractive, you can select Indifferent." ROUND_LATER_TEXT_Decision1 = "We play the same game again, but with a different proportion of purple and yellow balls in box K (see below). " \ " Everything else is the same.
" \ "Again, you can choose between box U or box K, both containing 100 balls. " \ "which can be either purple or yellow. One ball will be drawn from the box you have chosen. " \ "You will win $5 if a purple ball is drawn. You will win $0 if a yellow ball is drawn.
" \ "Please select the box of your choice: U or K. If you think both boxes are equally attractive, you can select Indifferent." ROUND1_TEXT_Decision2 = "In this game you can choose between box U or box K, both containing 100 balls of 10 different colors. " \ "One ball will be drawn from the box you have chosen. " \ "You will win $5 if a purple ball is drawn. You will win $0 if a ball of other colors is drawn.
" \ "For box K you can see the exact proportion of colored balls below. " \ "Box U also contains 10 different colors of balls, " \ "but the proportions are not shown in advance. " \ "Hence, both boxes contain 100 balls with the same 10 different colors. " \ "The composition of colored balls is known (K) for box K and unknown (U) for box U.
" \ "Please select the box of your choice: U or K. If you think both boxes are equally attractive, you can select Indifferent." ROUND_LATER_TEXT_Decision2 = "We play the same game again, but with a different proportion of colored balls in box K (see below). " \ " Everything else is the same.
" \ "Again, you can choose between box U or box K, both containing 100 balls of 10 different colors. " \ "One ball will be drawn from the box you have chosen. " \ "You will win $5 if a purple ball is drawn. You will win $0 if a ball of other colors is drawn.
"\ "Please select the box of your choice: U or K. If you think both boxes are equally attractive, you can select Indifferent." ROUND1_TEXT_Decision3 = "In this game you can choose between box U or box K, both containing 100 balls of 10 different colors. " \ "One ball will be drawn from the box you have chosen. " \ "If the ball drawn from the box is any color OTHER than purple you will win $5. If the ball drawn from the box is purple you will win $0.
" \ "For box K you can see the exact proportion of colored balls below. " \ "Box U also contains 10 different colors of balls, " \ "but the proportions are not shown in advance. " \ "Hence, both boxes contain 100 balls with the same 10 different colors. " \ "The composition of colored balls is known (K) for box K and unknown (U) for box U.
" \ "Please select the box of your choice: U or K. If you think both boxes are equally attractive, you can select Indifferent." ROUND_LATER_TEXT_Decision3 = "We play the same game again, but with a different proportion of colored balls in box K (see below). " \ " Everything else is the same.
" \ "Again, you can choose between box U or box K, both containing 100 balls of 10 different colors. " \ "One ball will be drawn from the box you have chosen. " \ "If the ball drawn from the box is any color OTHER than purple you will win $5. If the ball drawn from the box is purple you will win $5.
"\ "Please select the box of your choice: U or K. If you think both boxes are equally attractive, you can select Indifferent." # ========================= # 工具函数 # ========================= def _current_task_key(participant): idx = participant.vars.get('amb_task_index', 0) order = participant.vars.get('amb_order', []) return order[idx] if idx < len(order) else None def _is_task_available(participant, key): st = participant.vars.get('amb_state', {}).get(key) if not st: return False return (not st.get('done', False)) and (st.get('rounds_done', 0) < Constants.MAX_ROUNDS_PER_TASK) # ========================= # Instructions # ========================= class Instructions(Page): template_name = 'Ambiguity_New/Instructions.html' def is_displayed(self): return not self.participant.vars.get('instructions_shown', False) def before_next_page(self, timeout_happened=False): self.participant.vars['instructions_shown'] = True class Quiz(Page): def is_displayed(self): return self.round_number == 1 form_model = 'player' # form fields # ---------------------------------------------------------------------------------------------------------------- def get_form_fields(self): return ['q1a', 'q1b', 'q2'] ans1a = 3 ans1b = 5 ans2 = 3 def error_message(self, values): # count number of incorrect attempts. if self.player.incorrect_attempts == None: self.player.incorrect_attempts = 0 if values['q1a'] != self.ans1a or values['q1b'] != self.ans1b or values['q2'] != self.ans2: self.player.incorrect_attempts += 1 # define error message that is displayed. if values['q1a'] != self.ans1a: return 'Your answer to Question 1a is incorrect!' if values['q1b'] != self.ans1b: return 'Your answer to Question 1b is incorrect!' if values['q2'] != self.ans2: return 'Your answer to Question 2 is incorrect!' def vars_for_template(self): return { 'answer1a': self.ans1a, 'answer1b': self.ans1b, 'answer2': self.ans2, } # ========================= # Decision 1: 两色,紫中奖,50% # ========================= class Decision1(Page): template_name = 'Ambiguity_New/Decision1.html' form_model = 'player' form_fields = ['choice'] def is_displayed(self): return _current_task_key(self.participant) == 'task1' and _is_task_available(self.participant, 'task1') def vars_for_template(self): self.player.prepare_round() p = self.player.shown_known_prob or 0 purple_percent = int(round(p * 100)) nonpurple_percent = 100 - purple_percent return dict( known_purple_percent=purple_percent, known_non_purple_percent=nonpurple_percent, win_percent=purple_percent, lose_percent=nonpurple_percent, round_text=ROUND1_TEXT_Decision1 if self.player.round_in_task == 1 else ROUND_LATER_TEXT_Decision1, win_sentence="You win $5 if a purple ball is drawn." ) def before_next_page(self, timeout_happened=False): self.player.update_after_choice() # ========================= # Middle Screen 1 # ========================= class Middle_Screen1(Page): def is_displayed(self): st = self.participant.vars['amb_state'].get('task1', {}) shown = self.participant.vars.get('mid1_shown', False) return st.get('done') and not shown def before_next_page(self, timeout_happened=False): self.participant.vars['amb_task_index'] = 1 self.participant.vars['mid1_shown'] = True # ========================= # Decision 2: 十色,紫中奖,10% # ========================= class Decision2(Page): template_name = 'Ambiguity_New/Decision2.html' form_model = 'player' form_fields = ['choice'] def is_displayed(self): return _current_task_key(self.participant) == 'task2' and _is_task_available(self.participant, 'task2') def vars_for_template(self): self.player.prepare_round() p = self.player.shown_known_prob or 0 purple_percent = int(round(p * 100)) nonpurple_percent = 100 - purple_percent return dict( known_purple_percent=purple_percent, known_non_purple_percent=nonpurple_percent, win_percent=purple_percent, lose_percent=nonpurple_percent, round_text=ROUND1_TEXT_Decision2 if self.player.round_in_task == 1 else ROUND_LATER_TEXT_Decision2, win_sentence="You win $5 if a purple ball is drawn." ) def before_next_page(self, timeout_happened=False): self.player.update_after_choice() # ========================= # Middle Screen 2 # ========================= class Middle_Screen2(Page): def is_displayed(self): st = self.participant.vars['amb_state'].get('task2', {}) shown = self.participant.vars.get('mid2_shown', False) return st.get('done') and not shown def before_next_page(self, timeout_happened=False): self.participant.vars['amb_task_index'] = 2 self.participant.vars['mid2_shown'] = True # ========================= # Decision 3: 十色,非紫中奖,90% # ========================= class Decision3(Page): template_name = 'Ambiguity_New/Decision3.html' form_model = 'player' form_fields = ['choice'] def is_displayed(self): return _current_task_key(self.participant) == 'task3' and _is_task_available(self.participant, 'task3') def vars_for_template(self): self.player.prepare_round() p = self.player.shown_known_prob or 0 purple_percent = int(round(p * 100)) nonpurple_percent = 100 - purple_percent return dict( known_purple_percent=purple_percent, known_non_purple_percent=nonpurple_percent, win_percent=nonpurple_percent, # 翻转 lose_percent=purple_percent, round_text=ROUND1_TEXT_Decision3 if self.player.round_in_task == 1 else ROUND_LATER_TEXT_Decision3, win_sentence="You win $5 if a non-purple ball is drawn." ) def before_next_page(self, timeout_happened=False): self.player.update_after_choice() # ========================= # Final Screen # ========================= """ class Final_Screen(Page): template_name = 'Ambiguity_New/Final_Screen.html' def is_displayed(self): st = self.participant.vars.get('amb_state', {}) # 三个任务都完成才显示 return all(st.get(k, {}).get('done') for k in ['task1', 'task2', 'task3']) """ class Final_Screen(Page): template_name = 'Ambiguity_New/Final_Screen.html' def is_displayed(self): st = self.participant.vars.get('amb_state', {}) all_done = all(st.get(k, {}).get('done') for k in ['task1', 'task2', 'task3']) shown = self.participant.vars.get('final_shown', False) return all_done and not shown def before_next_page(self, timeout_happened=False): # 标记为已展示一次,防止回到本页 self.participant.vars['final_shown'] = True # ========================= # 结果页 # ========================= """ class Results(Page): template_name = 'Ambiguity_New/Results.html' def is_displayed(self): state = self.participant.vars.get('amb_state', {}) return all(state.get(k, {}).get('done') for k in ['task1', 'task2', 'task3']) def vars_for_template(self): def fmt(v): return '-' if v is None else f'{int(round((v or 0) * 100))}%' return dict( indiff_task1=fmt(self.player.indiff_task1), indiff_task2=fmt(self.player.indiff_task2), indiff_task3=fmt(self.player.indiff_task3), ) """ page_sequence = [ Instructions, Quiz, Decision1, Middle_Screen1, Decision2, Middle_Screen2, Decision3, Final_Screen ]