from otree.api import * doc = """ Strategy method for ultimatum game. """ class C(BaseConstants): NAME_IN_URL = 'strategy_method' PLAYERS_PER_GROUP = 2 NUM_ROUNDS = 1 INSTRUCTIONS_FILE = __name__ + '/instructions.html' ENDOWMENT = cu(100) #初期保有の金額設定 OFFER_CHOICES = currency_range(0, ENDOWMENT, 10) #選択できるレンジ OFFER_CHOICES_COUNT = len(OFFER_CHOICES) POSSIBLE_ALLOCATIONS = [] for OFFER in OFFER_CHOICES: POSSIBLE_ALLOCATIONS.append(dict(p1_amount=OFFER, p2_amount=ENDOWMENT - OFFER)) class Subsession(BaseSubsession): pass def make_strategy_field(number): return models.BooleanField( label="あなたは{}の提案を受け入れますか?".format(cu(number)), widget=widgets.RadioSelectHorizontal, # note to self: remove this once i release bugfix choices=[[False, 'No'], [True, 'Yes']], ) class Group(BaseGroup): amount_offered = models.CurrencyField(choices=C.OFFER_CHOICES,) offer_accepted = models.BooleanField() # another way to implement this game would be with an ExtraModel, instead of making # all these hardcoded fields. # that's what the choice_list app does. # that would be more flexible, but also more complex since you would have to implement the # formfields yourself with HTML and Javascript. # in this case, since the rules of the game are pretty simple, # and there are not too many fields, # just defining these hardcoded fields is fine. response_0 = make_strategy_field(0) response_10 = make_strategy_field(10) response_20 = make_strategy_field(20) response_30 = make_strategy_field(30) response_40 = make_strategy_field(40) response_50 = make_strategy_field(50) response_60 = make_strategy_field(60) response_70 = make_strategy_field(70) response_80 = make_strategy_field(80) response_90 = make_strategy_field(90) response_100 = make_strategy_field(100) def set_payoffs(group: Group): p1, p2 = group.get_players() amount_offered = group.amount_offered #提案額の定義。同一グループの中から提案額を引っ張ってくる group.offer_accepted = getattr(group, 'response_{}'.format(int(amount_offered))) #提案が受け入れられるかどうか。 if group.offer_accepted: #提案が受け入れられた場合の計算 p1.payoff = C.ENDOWMENT - amount_offered p2.payoff = amount_offered else: #提案が拒否された場合の計算(お互い0円) p1.payoff = 0 p2.payoff = 0 class Player(BasePlayer): pass class P1(Page): form_model = 'group' form_fields = ['amount_offered'] @staticmethod def is_displayed(player: Player): #提案者(id_in_group==1)のみ表示 return player.id_in_group == 1 class P2(Page): form_model = 'group' form_fields = ['response_{}'.format(int(i)) for i in C.OFFER_CHOICES] @staticmethod def is_displayed(player: Player): #応答者(id_in_group==2)のみ表示 return player.id_in_group == 2 class ResultsWaitPage(WaitPage): after_all_players_arrive = set_payoffs #全員がたどり着いたら、利得を計算 title_text = "ありがとうございました" body_text = ( "しばらくお待ちください。他のプレイヤーが到着すると、利得が計算されます。" ) class Results(Page): pass page_sequence = [ P1, P2, ResultsWaitPage, Results, ]