#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.