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]