oTree Forum >

set_group_matrix

#1 by Rita (edited )

Hello everyone, I am conducting a trading experiment. The experiment assumes that there are 20 participants, 10 sellers, and 10 buyers. Sellers bid on products and buyers decide whether to purchase. In this experiment, I named sellers Seller 1, Seller 2..., Seller 10, and buyers Buyer 1, Buyer 2, Buyer 3..., Buyer 10. During the experiment, Seller 1 and Buyer 1 are grouped together, while Seller 2 and Buyer 2 are grouped together. In addition, if the buyer chooses to purchase this product during the experiment, then this buyer and their corresponding seller will not enter the next round of transactions. If the buyer chooses not to purchase this product, they can choose whether to enter the next round, and if they choose to enter the next round of transactions, they will be reassigned to a new seller (who also did not sell anything). How should I rewrite my code? Here is my current code.
If someone helps me, I would be very grateful.


from otree.api import *

class Constants(BaseConstants):
    name_in_url = 'trading_experiment'
    players_per_group = 2
    num_rounds = 10
    num_groups = 10
    SELLER_ROLE = '卖家'
    BUYER_ROLE = '买家'
    room_name = 'room1'
    cost = 10
    quality_average = 65

class Subsession(BaseSubsession):
    pass

def creating_session(subsession: Subsession):
    players = [p for p in subsession.get_players() if p.active]  # 仅包括活跃的玩家
    n_players = len(players)
    offset = subsession.round_number - 1  # 每一轮增加的偏移量
    new_structure = make_matrix(n_players, offset)
    subsession.set_group_matrix(new_structure)

    for i, player in enumerate(players, start=1):
        if i <= 3:
            player.role_name = f'卖家{i}'
        else:
            player.role_name = f'买家{i - 10}'

    print(f"Round {subsession.round_number} group matrix: {subsession.get_group_matrix()}")
    for player in players:
        print(f"Player {player.id_in_subsession}: {player.role_name}")

def make_matrix(n_players, offset):
    p1s = list(range(1, n_players // 2 + 1))
    p2s = list(range(n_players // 2 + 1, n_players + 1))

    # Rotate p2s by the offset
    return list(zip(p1s, p2s[offset:] + p2s[:offset]))

class Group(BaseGroup):
    seller_decision_quality = models.IntegerField()
    seller_decision_price = models.CurrencyField()

class Player(BasePlayer):
    role_name = models.StringField()
    quality = models.IntegerField(
        label="商品的品质:",
        min=60, max=70
    )
    price = models.CurrencyField(
        label="商品的价格:",
        min=0
    )
    quality_buyer = models.IntegerField(
        label="买家实际收到商品的品质:",
        min=-10, max=10
    )
    purchase_decision = models.BooleanField(
        label="你是否购买这个商品?",
        choices=[
            [True, '购买'],
            [False, '不购买']
        ],
        widget=widgets.RadioSelect
    )
    active = models.BooleanField(initial=True)  # 标记玩家是否在下一轮中参与

class Introduction(Page):
    @staticmethod
    def vars_for_template(player: Player):
        group = player.group
        seller = group.get_player_by_role(Constants.SELLER_ROLE)
        buyer = group.get_player_by_role(Constants.BUYER_ROLE)

        return {
            'player_role_name': player.role_name,
            'seller_role_name': seller.role_name if seller else 'N/A',
            'buyer_role_name': buyer.role_name if buyer else 'N/A',
        }

class SellerDecision(Page):
    form_model = 'player'
    form_fields = ['quality', 'price']

    @staticmethod
    def is_displayed(player):
        return player.role == Constants.SELLER_ROLE

    @staticmethod
    def before_next_page(player: Player, timeout_happened):
        group = player.group
        group.seller_decision_quality = player.quality
        group.seller_decision_price = player.price

class SellerWaitPage(WaitPage):
    @staticmethod
    def is_displayed(player):
        return player.role == Constants.BUYER_ROLE

    @staticmethod
    def after_all_players_arrive(group: Group):
        pass

class BuyerView(Page):
    @staticmethod
    def is_displayed(player):
        return player.role == Constants.BUYER_ROLE and player.active

    @staticmethod
    def vars_for_template(player: Player):
        current_group = player.group
        all_rounds_data = []

        if player.round_number > 1:
            for previous_round in player.in_previous_rounds():
                previous_round_group = previous_round.group
                previous_round_player = previous_round

                if previous_round_player.role == Constants.BUYER_ROLE:
                    previous_round_buyer = previous_round_player
                    previous_round_seller = previous_round_group.get_player_by_role(Constants.SELLER_ROLE)
                else:
                    previous_round_buyer = previous_round_group.get_player_by_role(Constants.BUYER_ROLE)
                    previous_round_seller = previous_round_player

                round_data = {
                    'round_number': previous_round.round_number,
                    'seller_quality': previous_round_group.seller_decision_quality,
                    'seller_price': previous_round_group.seller_decision_price,
                    'buyer_decision': '是' if previous_round_buyer.purchase_decision else '否',
                    'quality_buyer': previous_round_buyer.quality_buyer if previous_round_buyer.purchase_decision else '无',
                }

                all_rounds_data.append(round_data)

        current_round_data = {
            'quality': current_group.seller_decision_quality,
            'price': current_group.seller_decision_price
        }

        return {
            'quality': current_round_data['quality'],
            'price': current_round_data['price'],
            'all_rounds_data': all_rounds_data
        }

class BuyerDecision(Page):
    form_model = 'player'
    form_fields = ['purchase_decision']

    @staticmethod
    def is_displayed(player):
        return player.role == Constants.BUYER_ROLE and player.active

    @staticmethod
    def vars_for_template(player: Player):
        group = player.group
        return {
            'quality': group.seller_decision_quality,
            'price': group.seller_decision_price,
        }

    @staticmethod
    def before_next_page(player: Player, timeout_happened):
        if player.purchase_decision:
            player.active = False
            player.get_others_in_group()[0].active = False

class BuyerQuality(Page):
    form_model = 'player'
    form_fields = ['quality_buyer']

    @staticmethod
    def is_displayed(player: Player):
        return player.role == Constants.BUYER_ROLE and player.purchase_decision

    @staticmethod
    def vars_for_template(player: Player):
        group = player.group
        return {
            'seller_quality': group.seller_decision_quality,
            'seller_price': group.seller_decision_price,
            'player': player
        }

class ResultsWaitPage(WaitPage):
    def after_all_players_arrive(self):
        pass

class SellerResults(Page):
    @staticmethod
    def is_displayed(player):
        return player.role == Constants.SELLER_ROLE

    @staticmethod
    def vars_for_template(player: Player):
        group = player.group
        buyer = group.get_player_by_role(Constants.BUYER_ROLE)
        return {
            'quality': group.seller_decision_quality,
            'price': group.seller_decision_price,
            'buyer_decision': '是' if buyer.purchase_decision else '否',
            'quality_buyer': buyer.quality_buyer if buyer.purchase_decision else '无'
        }

class Results(Page):
    @staticmethod
    def vars_for_template(player: Player):
        group = player.group
        buyer = group.get_player_by_role(Constants.BUYER_ROLE)
        seller = group.get_player_by_role(Constants.SELLER_ROLE)

        if buyer.purchase_decision:
            buyer_benefit = group.seller_decision_quality + buyer.quality_buyer - group.seller_decision_price
            seller_benefit = group.seller_decision_price - Constants.cost
        else:
            buyer_benefit = 0
            seller_benefit = 0

        if player.round_number == 1:
            all_rounds_data = [{
                'round_number': player.round_number,
                'seller_quality': group.seller_decision_quality,
                'seller_price': group.seller_decision_price,
                'buyer_decision': '是' if buyer.purchase_decision else '否',
                'quality_buyer': buyer.quality_buyer if buyer.purchase_decision else '无',
            }]
        else:
            all_rounds_data = []
            for previous_round in player.in_all_rounds():
                previous_round_group = previous_round.group
                previous_round_buyer = previous_round_group.get_player_by_role(Constants.BUYER_ROLE)
                previous_round_seller = previous_round_group.get_player_by_role(Constants.SELLER_ROLE)

                round_data = {
                    'round_number': previous_round.round_number,
                    'seller_quality': previous_round_group.seller_decision_quality,
                    'seller_price': previous_round_group.seller_decision_price,
                    'buyer_decision': '是' if previous_round_buyer.purchase_decision else '否',
                    'quality_buyer': previous_round_buyer.quality_buyer if previous_round_buyer.purchase_decision else '无',
                }
                all_rounds_data.append(round_data)

        return {
            'seller_quality': group.seller_decision_quality,
            'seller_price': group.seller_decision_price,
            'buyer_decision': '是' if buyer.purchase_decision else '否',
            'quality_buyer': buyer.quality_buyer if buyer.purchase_decision else '无',
            'buyer_benefit': buyer_benefit,
            'seller_benefit': seller_benefit,
            'all_rounds_data': all_rounds_data
        }

class GroupRearrangeWaitPage(WaitPage):
    wait_for_all_groups = True

    @staticmethod
    def after_all_players_arrive(subsession: Subsession):
        creating_session(subsession)

page_sequence = [
    Introduction,
    SellerDecision,
    SellerWaitPage,
    BuyerView,
    BuyerDecision,
    BuyerQuality,
    ResultsWaitPage,
    SellerResults,
    Results,
    GroupRearrangeWaitPage
]

Write a reply

Set forum username