from otree.api import * from MGPGG_utils.common_functions import setting_groups import time doc = """ Code for MGPGG (Linear VCM) for the SHARED endowment and DEFINITE rounds """ class C(BaseConstants): NAME_IN_URL = 'SharedEndowment' PLAYERS_PER_GROUP = None NUM_ROUNDS = 20 # 10 rounds for pilot ENDOWMENT = cu(20) MULTIPLIER = 2 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): # Each player needs to store the information (id) of their fellow group members blue_group_partner_one_id = models.IntegerField() blue_group_partner_two_id = models.IntegerField() blue_group_partner_three_id = models.IntegerField() # For Group One: each player needs to store the total_investment and their individual share of the project blue_group_total_investment = models.CurrencyField() blue_group_individual_share = models.CurrencyField() # Store player IDs for group two green_group_partner_one_id = models.IntegerField() green_group_partner_two_id = models.IntegerField() green_group_partner_three_id = models.IntegerField() # Store total investment and individual share for Group Twos green_group_total_investment = models.CurrencyField() green_group_individual_share = models.CurrencyField() # For a round, a participants payoff is their earnings from their First and Second Group # However, for SHARED endowment, this is a PROFIT/LOSS not a payoff. blue_group_profit = models.CurrencyField() green_group_profit = models.CurrencyField() personal_account = models.CurrencyField() # Each round, each subject makes a decision to each group of how much of their endowment to contribute blue_group_investment = models.CurrencyField( min=0, max=C.ENDOWMENT ) green_group_investment = models.CurrencyField( min=0, max=C.ENDOWMENT ) # Track decision time start_time = models.FloatField(initial=0) time_spent_invest = models.FloatField(initial=0) time_spent_results = models.FloatField(initial=0) time_spent_cumulative_results = models.FloatField(initial=0) # Error Tracking num_errors_invest = models.IntegerField(initial=0) # Functions def set_payoffs_shared_endowment(subsession: Subsession): """ Function to set payoffs in a round for when the subjects are in the Shared Endowment treatment. :param subsession: utilize subsession to make use of the get_players() function to create a list of the Player instances for the experiment session. :return: traits stored to the Player instances for that round. """ players = subsession.get_players() setting_groups(players) for p in players: # Calculate Group One Information p.blue_group_total_investment = p.blue_group_investment + \ players[(p.blue_group_partner_one_id - 1)].blue_group_investment + \ players[(p.blue_group_partner_two_id - 1)].blue_group_investment + \ players[(p.blue_group_partner_three_id - 1)].blue_group_investment p.blue_group_individual_share = (p.blue_group_total_investment * C.MULTIPLIER) / 4 p.blue_group_profit = p.blue_group_individual_share - p.blue_group_investment # Calculate Group Two Information p.green_group_total_investment = p.green_group_investment + \ players[(p.green_group_partner_one_id - 1)].green_group_investment + \ players[(p.green_group_partner_two_id - 1)].green_group_investment + \ players[(p.green_group_partner_three_id - 1)].green_group_investment p.green_group_individual_share = (p.green_group_total_investment * C.MULTIPLIER) / 4 p.green_group_profit = p.green_group_individual_share - p.green_group_investment p.personal_account = C.ENDOWMENT - p.blue_group_investment - p.green_group_investment p.payoff = C.ENDOWMENT + p.blue_group_profit + p.green_group_profit # PAGES class Invest(Page): form_model = 'player' form_fields = ['blue_group_investment', 'green_group_investment'] @staticmethod def is_displayed(player: Player): player.start_time = time.time() return True @staticmethod def error_message(player: Player, values): if values['blue_group_investment'] + values['green_group_investment'] > C.ENDOWMENT: end_time = time.time() elapsed_time = end_time - player.start_time player.time_spent_invest += elapsed_time # Increment total time spent on this page player.start_time = time.time() # Reset the start time for the next iteration player.num_errors_invest += 1 return 'The sum of your investment to your two group accounts cannot exceed your endowment (20)' @staticmethod def vars_for_template(player: Player): # Get the player's history up to the current round previous_rounds = player.in_previous_rounds() # Extract investment and payoff for each round history = [ { 'round_number': p.round_number, 'blue_group_investment': p.blue_group_investment, 'green_group_investment': p.green_group_investment, 'blue_group_total_investment': p.blue_group_total_investment, 'green_group_total_investment': p.green_group_total_investment, 'blue_group_individual_share': p.blue_group_individual_share, 'green_group_individual_share': p.green_group_individual_share, 'personal_account': p.personal_account, 'payoff': p.payoff } for p in previous_rounds ] return {'history': history} @staticmethod def before_next_page(player: Player, timeout_happened): player.time_spent_invest += time.time() - player.start_time # Save invest decision time spent class ResultsWaitPage(WaitPage): wait_for_all_groups = True after_all_players_arrive = set_payoffs_shared_endowment class Results(Page): @staticmethod def is_displayed(player: Player): player.start_time = time.time() return True @staticmethod def before_next_page(player: Player, timeout_happened): player.time_spent_results = time.time() - player.start_time # Save results time spent class CumulativeResults(Page): @staticmethod def is_displayed(player: Player): player.start_time = time.time() return player.round_number == C.NUM_ROUNDS @staticmethod def vars_for_template(player: Player): cumulative_payoff = sum([p.payoff for p in player.in_all_rounds() if p.payoff]) return {'cumulative_payoff': cumulative_payoff} @staticmethod def before_next_page(player: Player, timeout_happened): player.time_spent_cumulative_results = time.time() - player.start_time # Save cumulative results time spent page_sequence = [Invest, ResultsWaitPage, Results, CumulativeResults]