#1 by Rita
hello everyone At present, I am conducting a transaction experiment. I plan to have four participants, two in each group, one seller and one buyer. In the first round, I will randomly assign roles according to the system, that is, [1,2], [3,4]. In the second round, I plan to use set_group_matrix to rearrange groups [1,4], [3,2]. But after I use set_group_matrix, the second round will not work. I want to know which part of my team is wrong. Thank you everyone Here is my code from otree.api import * class Constants(BaseConstants): name_in_url = 'trading_experiment' players_per_group = 2 num_rounds = 2 num_groups = 2 SELLER_ROLE = '卖家' BUYER_ROLE = '买家' room_name = 'room1' cost = 10 quality_average = 65 class Subsession(BaseSubsession): def creating_session(self): print(f"Creating session for round {self.round_number}") if self.round_number == 1: print(f"Round {self.round_number} initial group matrix: {self.get_group_matrix()}") # 不在这里处理第二轮的重排 class Group(BaseGroup): seller_decision_quality = models.IntegerField() seller_decision_price = models.CurrencyField() class Player(BasePlayer): 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 ) class Introduction(Page): @staticmethod def vars_for_template(player: Player): return { 'role': player.role } 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 @staticmethod def vars_for_template(player: Player): group = player.group return { 'quality': group.seller_decision_quality, 'price': group.seller_decision_price, } class BuyerDecision(Page): form_model = 'player' form_fields = ['purchase_decision'] @staticmethod def is_displayed(player): return player.role == Constants.BUYER_ROLE @staticmethod def vars_for_template(player: Player): group = player.group return { 'quality': group.seller_decision_quality, 'price': group.seller_decision_price, } 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 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 } class GroupRearrangeWaitPage(WaitPage): wait_for_all_groups = True @staticmethod def after_all_players_arrive(subsession: Subsession): if subsession.round_number == 2: new_structure = [ [1, 4], [3, 2] ] subsession.set_group_matrix(new_structure) print(f"Round {subsession.round_number} new group matrix: {subsession.get_group_matrix()}") page_sequence = [ Introduction, SellerDecision, SellerWaitPage, BuyerView, BuyerDecision, BuyerQuality, ResultsWaitPage, SellerResults, Results, GroupRearrangeWaitPage # 将重新分组的 WaitPage 添加到页面序列的最后 ]
#2 by Daniel_Frey
Each round is its own subsession, so at the end of round 1 you change the group matrix of subsession 1, but not in subsession 2. You can set the group matrix in your creating_session-function, since it will run once for each round (i.e. subsession). Furthermore, are you using oTree 5 or oTree 3? If you're using oTree 5, creating_session should be placed at the same level as the Subsession-class, not in it: class Subsession(BaseSubsession): pass def creating_session(subsession: Subsession): if subsession.round_number == 1: print(f"Round {self.round_number} initial group matrix: {self.get_group_matrix()}") # 不在这里处理第二轮的重排 if subsession.round_number == 2: new_structure = [ [1, 4], [3, 2] ] subsession.set_group_matrix(new_structure) print(f"Round {subsession.round_number} new group matrix: {subsession.get_group_matrix()}")
#3 by Rita
I am using otree 5, thank you, I know how to do it now and it works.