from otree.api import *
c = cu
doc = ''
class Constants(BaseConstants):
name_in_url = 'E2_pgg2'
players_per_group = 3
num_rounds = 10
multiplier = 2
max_punishment = 6
endowment = 6
max_reward = 6
plus = 12
thanks = 4.3
admin_report_template = 'E2_pgg2/admin_report.html'
instructions_template = 'E2_pgg2/instructions.html'
def vars_for_admin_report(subsession):
session = subsession.session
contributions = [p.contribution for p in subsession.get_players() if p.contribution != None]
if contributions:
return dict(
avg_contribution=sum(contributions) / len(contributions),
min_contribution=min(contributions),
max_contribution=max(contributions),
)
else:
return dict(
avg_contribution='(no data)',
min_contribution='(no data)',
max_contribution='(no data)',
)
class Subsession(BaseSubsession):
pass
def set_payoffs(group):
players = group.get_players()
#グループ全員の公共の金庫への貢献量
group.total_contribution = sum([p.contribution for p in players])
#個人への分配
group.individual_share = round((group.total_contribution * Constants.multiplier / Constants.players_per_group),2)
for p in players:
#個人の金庫+分配
p.pay = round(((Constants.endowment - p.contribution) + group.individual_share),2)
#追加
p.plus = Constants.plus
#罰則
self_pfield = get_self_pfield(p)
#他の参加者から受けた罰則
punish_received = [getattr(other,self_pfield) for other in p.get_others_in_group()]
p.punish_received = round(sum(punish_received))
#他の参加者に罰則を与えるのにかかったコスト
punish_sent = [getattr(p,field) for field in punish_fields(p)]
p.self_cost_of_punish = round(sum(punish_sent))
#報酬
self_rfield = get_self_rfield(p)
#他の人から与えられた報酬
reward_received = [getattr(other,self_rfield) for other in p.get_others_in_group()]
p.reward_received = round(sum(reward_received))
#他の参加者に報酬を与えるのにかかったコスト
reward_sent = [getattr(p,field) for field in reward_fields(p)]
p.self_cost_of_reward = round(sum(reward_sent))
#ゲーム後の個人の収益
p.after = round((p.pay + p.plus - p.self_cost_of_punish -p.self_cost_of_reward - p.punish_received + p.reward_received),2)
#●回ゲーム後の個人の収益
if p.round_number > 1:
prev_player = p.in_round(p.round_number - 1)
prev_player.total += p.after
p.total = round((prev_player.total),2)
if p.round_number == 1:
p.total = p.participant.token_stage1 + p.after
#謝礼金
import math
p.thanks =math.ceil(p.total * Constants.thanks) + 100
class Group(BaseGroup):
total_contribution = models.IntegerField(initial=0)
individual_share = models.FloatField(initial=0)
def get_self_pfield(player):
group = player.group
return 'punish{}'.format(player.id_in_group)
def punish_fields(player):
fields = ['punish1','punish2','punish3']
#can't punish yourself
fields.remove(get_self_pfield(player))
return fields
def get_self_rfield(player):
group = player.group
return 'reward{}'.format(player.id_in_group)
def reward_fields(player):
rfields = ['reward1','reward2','reward3']
#can't reward yourself
rfields.remove(get_self_rfield(player))
return rfields
class Player(BasePlayer):
contribution = models.IntegerField(label='6トークンのうち『グループの口座』に何トークン投資しますか?
(残りのトークンは全て『あなたの口座』に入れられます。)
0~6で入力してください。
 ', max=Constants.endowment, min=0)
pay = models.FloatField()
plus = models.IntegerField()
punish1 = models.IntegerField(initial=0, label='プレーヤー1に対する『罰則』額を決定してください。0~6で入力してください。', max=Constants.max_punishment, min=0)
punish2 = models.IntegerField(initial=0, label='プレーヤー2に対する『罰則』額を決定してください。0~6で入力してください。', max=Constants.max_punishment, min=0)
punish3 = models.IntegerField(initial=0, label='プレーヤー3に対する『罰則』額を決定してください。0~6で入力してください。', max=Constants.max_punishment, min=0)
punish_received = models.IntegerField()
self_cost_of_punish = models.IntegerField()
reward1 = models.IntegerField(initial=0, label='プレーヤー1に対する『報酬』額を決定してください。0~6で入力してください。', max=Constants.max_reward, min=0)
reward2 = models.IntegerField(initial=0, label='プレーヤー2に対する『報酬』額を決定してください。0~6で入力してください。', max=Constants.max_reward, min=0)
reward3 = models.IntegerField(initial=0, label='プレーヤー3に対する『報酬』額を決定してください。0~6で入力してください。', max=Constants.max_reward, min=0)
reward_received = models.IntegerField()
self_cost_of_reward = models.IntegerField()
after = models.FloatField()
total = models.FloatField(initial=0)
thanks = models.IntegerField()
def custom_export(players):
import datetime
yield ['session', 'participant_code', 'group', 'id_in_group','participant_current_page',
'participant_index_in_pages', 'participant_max_page_index', 'round_number', 'total_token','thanks',
'contribution', 'group_total_contribution', 'group_individual_share', 'posession_before_sunction',
'punish_for_1', 'punish_for_2', 'punish_for_3','punish_cost',
'reward_to_1','reward_to_2', 'reward_to_3', 'reward_cost',
'punish_received', 'reward_received',
'each_token']
for p in players:
pp = p.participant
session = p.session
yield [session.code, pp.code, p.group.id_in_subsession, p.id_in_group, pp._current_page_name,
pp._index_in_pages, pp._max_page_index, p.round_number, p.total, p.thanks,
p.contribution, p.group.total_contribution, p.group.individual_share, p.pay,
p.punish1, p.punish2, p.punish3, p.self_cost_of_punish,
p.reward1, p.reward2, p.reward3, p.self_cost_of_reward,
p.punish_received, p.reward_received,
p.after]
class Contribute2(Page):
form_model = 'player'
form_fields = ['contribution']
timeout_seconds = 60
timer_text = '残り'
class WaitPage1(WaitPage):
wait_for_all_groups = True
title_text = 'しばらくお待ちください'
body_text = '他の参加者の入力が終わるまでお待ちください。'
class SunctionP1(Page):
form_model = 'player'
form_fields = ['punish2', 'punish3', 'reward2', 'reward3']
timeout_seconds = 120
timer_text = '残り'
@staticmethod
def is_displayed(player):
group = player.group
return player.id_in_group == 1
return True
@staticmethod
def error_message(player, values):
print('values is', values)
if values['punish2'] + values['punish3'] >6:
return '『罰則』の合計が6トークンを越えています'
print('values is', values)
if values['reward2'] + values['reward3'] >6:
return '『報酬』の合計が6トークンを越えています'
class SunctionP2(Page):
form_model = 'player'
form_fields = ['punish1', 'punish3', 'reward1', 'reward3']
timeout_seconds = 120
timer_text = '残り'
@staticmethod
def is_displayed(player):
group = player.group
return player.id_in_group == 2
return True
@staticmethod
def error_message(player, values):
print('values is', values)
if values['punish1'] + values['punish3'] >6:
return '『罰則』の合計が6トークンを越えています'
print('values is', values)
if values['reward1'] + values['reward3'] >6:
return '『報酬』の合計が6トークンを越えています'
class SunctionP3(Page):
form_model = 'player'
form_fields = ['punish1', 'punish2', 'reward1', 'reward2']
timeout_seconds = 120
timer_text = '残り'
@staticmethod
def is_displayed(player):
group = player.group
return player.id_in_group == 3
return True
@staticmethod
def error_message(player, values):
print('values is', values)
if values['punish1'] + values['punish2'] >6:
return '『罰則』の合計が6トークンを越えています'
print('values is', values)
if values['reward1'] + values['reward2'] >6:
return '『報酬』の合計が6トークンを越えています'
class WaitPage2(WaitPage):
after_all_players_arrive = set_payoffs
title_text = 'しばらくお待ちください'
body_text = '他の参加者の入力が終わるまでお待ちください。'
class Results2(Page):
form_model = 'player'
timeout_seconds = 30
timer_text = '残り'
@staticmethod
def vars_for_template(player):
group = player.group
return dict(total_earnings=group.total_contribution * Constants.multiplier)
@staticmethod
def before_next_page(player, timeout_happened):
participant = player.participant
participant.round1+=1
class Last(Page):
form_model = 'player'
@staticmethod
def is_displayed(player):
return player.round_number == Constants.num_rounds
page_sequence = [Contribute2, WaitPage1, SunctionP1, SunctionP2, SunctionP3, WaitPage2, Results2, Last]