import random import numpy as np from otree.api import * doc = """ JMP """ class C(BaseConstants): NAME_IN_URL = 'study' PLAYERS_PER_GROUP = 2 NUM_ROUNDS = 8 TEMPLATE_REPORT_CHEAP = 'trust/profit_report_cheap.html' TEMPLATE_REPORT_EXPENSIVE = 'trust/profit_report_expensive.html' TEMPLATE_RECAP = 'trust/recap_template.html' TEMPLATE_WAIT_PAGE = 'trust/wait_page_template.html' TEMPLATE_MTURK_WAIT_PAGE = 'trust/mturk_wait_page_template.html' TEMPLATE_MTURK_WAIT_PAGE = 'trust/mturk_wait_page_template.html' TEMPLATE_INSTRUCTIONS = 'attention/instructions_template.html' SUPERVISOR_ENDOWMENT = cu(450) EMPLOYEE_ENDOWMENT = cu(410) BENEFIT_EFFORT=3 EFFORT_MAX = cu(50) EFFORT_MAX_TOTAL = EFFORT_MAX*3 BONUS_MAX_TOTAL = cu(300) BONUS_MAX_PER_TASK = BONUS_MAX_TOTAL/3 BONUS_MAX_TOTAL_STRING = str(BONUS_MAX_TOTAL) BONUS_MAX_PER_TASK_STRING = str(BONUS_MAX_PER_TASK) RETURN_MAX_TOTAL=EFFORT_MAX_TOTAL*BENEFIT_EFFORT COST_INFO_HIGH=cu(300) COST_INFO_LOW=cu(40) class Subsession(BaseSubsession): pass # def creating_session(self): # if self.round_number == 1: # for g in self.get_groups(): # p1 = g.get_player_by_id(1) # # if 'treatment_info' in self.session.config: # p1.participant.vars['treatment_info'] = self.session.config['treatment_info'] # else: # p1.participant.vars['treatment_info'] = random.choice([0, 1, 2]) # #0=outcome only # #1=outcome+effort # #2=effort only class Group(BaseGroup): effort_a = models.CurrencyField( min=0, max=C.EFFORT_MAX ) effort_b = models.CurrencyField( min=0, max=C.EFFORT_MAX ) effort_c = models.CurrencyField( min=0, max=C.EFFORT_MAX ) effort_total =models.CurrencyField() collected_expensive_info = models.BooleanField( choices=[ [True, 'Full information package'], [False, 'Basic information package'], ],label="What type of information will you collect for this period?") bonus_total = models.CurrencyField(min=0, max=C.BONUS_MAX_TOTAL,label="Please choose a bonus amount to award to the employee related to their overall performence (between 0 and " + C.BONUS_MAX_TOTAL_STRING+")") bonus_a = models.CurrencyField(min=0, max=C.BONUS_MAX_PER_TASK,label="Please choose a bonus amount to award to the employee related to their performence on Project A (between 0 and " + C.BONUS_MAX_PER_TASK_STRING+")") bonus_b = models.CurrencyField(min=0, max=C.BONUS_MAX_PER_TASK,label="Please choose a bonus amount to award to the employee related to their performence on Project B (between 0 and " + C.BONUS_MAX_PER_TASK_STRING+")") bonus_c = models.CurrencyField(min=0, max=C.BONUS_MAX_PER_TASK,label="Please choose a bonus amount to award to the employee related to their performence on Project C (between 0 and " + C.BONUS_MAX_PER_TASK_STRING+")") payoff_supervisor = models.CurrencyField() payoff_employee = models.CurrencyField() profit = models.CurrencyField() cost_info_supervisor = models.CurrencyField() is_expensive_treatment = models.BooleanField() is_disaggregate_treatment = models.BooleanField() random_period = models.IntegerField() class Player(BasePlayer): collegue_left = models.BooleanField() participant_left = models.BooleanField() waited_for_group = models.BooleanField() kicked_out_period = models.IntegerField() def group_by_arrival_time_method(subsession, waiting_players): players = [p for p in waiting_players] if len(players) >= 2: if random.choice([0, 1]): return [players[0], players[1]] else: return [players[1], players[0]] def role(player: Player): return {1: 'Supervisor', 2: 'Employee'}[player.id_in_group] # PAGES def kick_after_page(player: Player): if 'participant_left' in player.participant.vars or 'collegue_left' in player.participant.vars: player.participant.vars["kicked_out_period"] = player.subsession.round_number player.kicked_out_period = player.subsession.round_number return "kicked_out" class mtrurk_wait_page(WaitPage): template_name = C.TEMPLATE_MTURK_WAIT_PAGE group_by_arrival_time = True @staticmethod def is_displayed(player: Player): return player.round_number == 1 @staticmethod def vars_for_template(player: Player): player.waited_for_group = True return dict( is_wrong_role=False, waiting_for_effort=False, waiting_for_bonus=False, waiting_for_confrontation=False, is_waiting_for_supervisor_info_choice_employee=False ) class supervisorEffortWaitPage(WaitPage): template_name = C.TEMPLATE_WAIT_PAGE title_text = "Please wait for the employee to decide how much effort to put in. " body_text = "" @staticmethod def vars_for_template(player: Player): if player.id_in_group == 2: is_employee = True bold = False else: is_employee = False bold = True return dict( is_wrong_role=is_employee, waiting_for_effort=bold, waiting_for_bonus=False, waiting_for_confrontation=False, is_waiting_for_supervisor_info_choice_employee=is_employee ) @staticmethod def app_after_this_page(player: Player, upcoming_apps): return kick_after_page(player) class employeeBonusWaitPage(WaitPage): template_name = C.TEMPLATE_WAIT_PAGE title_text = "Please wait for the supervisor to decide how much bonus to award to you. " body_text = "" @staticmethod def vars_for_template(player: Player): if player.id_in_group == 1: is_supervisor = True bold = False else: is_supervisor = False bold = True return dict( is_wrong_role=is_supervisor, waiting_for_effort=False, waiting_for_bonus=bold, waiting_for_confrontation=False, is_waiting_for_supervisor_info_choice_employee=False ) @staticmethod def app_after_this_page(player: Player, upcoming_apps): return kick_after_page(player) class Intro(Page): @staticmethod def is_displayed(player: Player): return player.subsession.round_number == 1 @staticmethod def vars_for_template(player: Player): player.waited_for_group = False if player.id_in_group == 1: player.participant.vars['role'] = "Supervisor" if player.id_in_group == 2: player.participant.vars['role'] = "Employee" return dict( is_wrong_role=False, waiting_for_effort=False, waiting_for_bonus=False, waiting_for_confrontation=False, is_waiting_for_supervisor_info_choice_employee=False ) class employee_effort_choice(Page): form_model = 'group' form_fields = ['effort_a','effort_b','effort_c'] @staticmethod def vars_for_template(player: Player): return dict( effort_label_a="Please choose how many points to invest in Project A between 0 and {}:".format( C.EFFORT_MAX), effort_label_b="Please choose how many points to invest in Project B between 0 and {}:".format( C.EFFORT_MAX), effort_label_c="Please choose how many points to invest in Project C between 0 and {}:".format( C.EFFORT_MAX) ) @staticmethod def is_displayed(player: Player): return player.id_in_group == 2 @staticmethod def before_next_page(player, timeout_happened): player.group.profit=(player.group.effort_a+player.group.effort_b+player.group.effort_c)*C.BENEFIT_EFFORT player.group.effort_total=player.group.effort_a+player.group.effort_b+player.group.effort_c class employee_profit_report(Page): @staticmethod def is_displayed(player: Player): return player.id_in_group == 2 class supervisor_info_choice(Page): form_model = 'group' form_fields = ['collected_expensive_info'] @staticmethod def is_displayed(player: Player): return player.id_in_group == 1 @staticmethod def js_vars(player: Player): player.group.is_expensive_treatment = player.participant.vars['expensive'] player.group.is_disaggregate_treatment= player.participant.vars['disaggregated'] cost=0 if player.group.is_expensive_treatment==1: cost=C.COST_INFO_HIGH else: cost=C.COST_INFO_LOW return dict( cost=cost, ) @staticmethod def before_next_page(player, timeout_happened): if player.group.collected_expensive_info: if player.group.is_expensive_treatment==1: player.group.cost_info_supervisor=C.COST_INFO_HIGH else: player.group.cost_info_supervisor=C.COST_INFO_LOW else: player.group.cost_info_supervisor=0 class bonus(Page): form_model = 'group' @staticmethod def get_form_fields(player): if player.group.is_disaggregate_treatment == 1: return ['bonus_a', 'bonus_b', 'bonus_c'] else: return ['bonus_total'] @staticmethod def is_displayed(player: Player): return player.id_in_group == 1 @staticmethod def before_next_page(player, timeout_happened): player.group.payoff_supervisor = (player.group.profit + C.SUPERVISOR_ENDOWMENT-player.group.cost_info_supervisor) if player.subsession.round_number == C.NUM_ROUNDS: payoff_period = random.randrange(1, C.NUM_ROUNDS + 1, 1) player.group.random_period = payoff_period if player.group.is_disaggregate_treatment == 1: player.group.bonus_total=player.group.bonus_a+player.group.bonus_b+player.group.bonus_c player.group.payoff_employee = ( C.EMPLOYEE_ENDOWMENT + player.group.bonus_total - player.group.effort_total ) class employee_bonus_report(Page): @staticmethod def is_displayed(player: Player): return player.id_in_group == 2 @staticmethod def vars_for_template(player: Player): return dict( cost_effort="filler", ) @staticmethod def before_next_page(player, timeout_happened): if player.subsession.round_number == C.NUM_ROUNDS: player.participant.payoff = player.group.in_round( player.group.random_period ).payoff_employee class supervisor_payoff_report(Page): @staticmethod def is_displayed(player: Player): return player.id_in_group == 1 and player.subsession.round_number == C.NUM_ROUNDS @staticmethod def vars_for_template(player: Player): current_period = player.subsession.round_number list_periods = [] if current_period == C.NUM_ROUNDS: player.participant.payoff = player.group.in_round( player.group.random_period ).payoff_supervisor list_periods = list(player.group.in_all_rounds()) else: list_periods.append(player.group.in_round(current_period)) return dict( next_round=player.subsession.round_number + 1, group_periods=list_periods, ) class next_period(Page): @staticmethod def is_displayed(player: Player): return not(player.subsession.round_number == C.NUM_ROUNDS) @staticmethod def vars_for_template(player: Player): return dict( next_period=player.subsession.round_number+1 ) class employee_payoff_report(Page): @staticmethod def is_displayed(player: Player): return player.id_in_group == 2 and player.subsession.round_number == C.NUM_ROUNDS @staticmethod def vars_for_template(player: Player): list_periods = [] list_periods = list(player.group.in_all_rounds()) return dict( group_periods=list_periods, ) page_sequence = [ mtrurk_wait_page, Intro, supervisor_info_choice, employee_effort_choice, supervisorEffortWaitPage, employee_profit_report, bonus, employeeBonusWaitPage, employee_bonus_report, supervisor_payoff_report, employee_payoff_report, next_period, ]