import random from otree.api import * author = 'Aoi_Kokado' doc = """ 卒研用実験 """ class Constants(BaseConstants): name_in_url = '2023年卒論用実験_練習' players_per_group = 3 num_rounds = 1 num_choices = 10 min_choice = 101 max_choice = min_choice + num_choices - 1 # instructions_template = 'Jikken_2023/instructions.html' class Subsession(BaseSubsession): pass class Group(BaseGroup): min_choice = models.IntegerField() class Player(BasePlayer): teian = models.StringField( choices=[['提案する', '提案する'], ['提案しない', '提案しない']], label='カルテルを提案しますか?', widget=widgets.RadioSelectHorizontal, ) binjo = models.StringField( choices=[['参加する', '参加する'], ['参加しない', '参加しない']], label='カルテルに参加しますか?', widget=widgets.RadioSelectHorizontal, ) choice_number = models.IntegerField( choices=[(i, i) for i in range(Constants.min_choice, Constants.max_choice + 1)], ) soten = models.FloatField() points = models.FloatField(initial=0, doc='このラウンドでの獲得ポイントです。') soten_point = models.FloatField() soten_point = models.FloatField() caltel_point = models.FloatField() result_point = models.FloatField() hokoku_1 = models.StringField( choices=[['報告する', '報告する'], ['報告しない', '報告しない']], widget=widgets.RadioSelectHorizontal, label='カルテルを報告しますか?', ) hokoku_2 = models.StringField( choices=[['報告する', '報告する'], ['報告しない', '報告しない']], widget=widgets.RadioSelectHorizontal, label='カルテルを報告しますか?', ) hokoku_3 = models.StringField( choices=[['報告する', '報告する'], ['報告しない', '報告しない']], widget=widgets.RadioSelectHorizontal, label='カルテルを報告しますか?', ) rank = models.IntegerField(initial=None) penalty_point = models.IntegerField(initial=None) random_time = models.IntegerField() finally_point = models.IntegerField() bakkin = models.IntegerField() penalty_random = models.IntegerField() random_result = models.IntegerField() # FUNCTIONS def creating_session(subsession: Subsession): if subsession.round_number == 1: subsession.group_randomly() else: subsession.group_like_round(1) def other_players_all_no(player: Player): return all([p.teian == '提案しない' for p in player.get_others_in_group()]) def other_players_all_yes(player: Player): return all([p.teian == '提案する' for p in player.get_others_in_group()]) def other_player_some_yes(player: Player): return any([p.teian == '提案する' for p in player.get_others_in_group()]) def other_player_some_no(player: Player): return any([p.teian == '提案しない' for p in player.get_others_in_group()]) def other_player_some_not_binjo(player: Player): return any([p.teian == '参加しない' for p in player.get_others_in_group()]) def other_player_all_not_binjo(player: Player): return all([p.teian == '参加しない' for p in player.get_others_in_group()]) def other_player_all_binjo(player: Player): return all([p.teian == '参加する' for p in player.get_others_in_group()]) def set_soten(player: Player): player.soten = player.choice_number - 100 player.soten_point = 6 * player.soten def set_simple_point(player: Player): player.result_point = player.soten_point * player.points def set_all_question_to_yes_1(player: Player): if player.hokoku_1: player.hokoku_2 = '報告する' player.hokoku_3 = '報告する' def set_all_question_to_yes_2(player: Player): if player.hokoku_2: player.hokoku_3 = '報告する' # def tie_penalty_point(self,tied_rank_list): # penalty_point_list = [1, 2, 3] # self.penalty_point = penalty_point_list[tied_rank_list.index(self.rank)] def rank_point(player: Player): if player.rank == 1: player.penalty_point = 0 elif player.rank == 2: player.penalty_point = 0.5 elif player.rank == 3: player.penalty_point = 1 else: player.penalty_point = 0 def set_penalty(player: Player): player.bakkin = player.result_point * 0.1 * player.penalty_point def set_penalty_random(player: Player): player.penalty_random = player.result_point * 0.1 def set_penalty_random_point(player: Player): player.random_result = player.result_point - player.penalty_random def set_finally_point(player: Player): player.finally_point = player.result_point - player.bakkin # PAGES class stop(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 class rensyu(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 timeout_seconds = 15 class teian(Page): form_model = 'player' form_fields = ['teian'] class teian_result(WaitPage): pass class binjo(Page): form_model = 'player' form_fields = ['binjo'] class binjo_wait(WaitPage): #def field_maybe_none(binjo): pass class hokoku_first(Page): timeout_seconds = 30 @staticmethod def is_displayed(player: Player): return all(player.teian == '提案する' for player in player.group.get_players()) or all( player.binjo == '参加する' for player in player.group.get_players() ) form_model = 'player' form_fields = ['hokoku_1'] @staticmethod def before_next_page(player: Player, timeout_happened): set_all_question_to_yes_1(player) class wait_chat(WaitPage): pass class caltel_choice(Page): timeout_seconds = 120 @staticmethod def is_displayed(player: Player): return all(player.teian == '提案する' for player in player.group.get_players()) or all( player.binjo == '参加する' for player in player.group.get_players() ) form_model = 'player' form_fields = ['choice_number', 'hokoku_2'] @staticmethod def before_next_page(player: Player, timeout_happened): set_all_question_to_yes_2(player) class wait_page(WaitPage): pass class hokoku_last(Page): timeout_seconds = 30 @staticmethod def is_displayed(player: Player): return all(player.teian == '提案する' for player in player.group.get_players()) or all( player.binjo == '参加する' for player in player.group.get_players() ) form_model = 'player' form_fields = ['hokoku_3'] class not_caltel_choice(Page): timeout_seconds = 60 @staticmethod def is_displayed(player: Player): return any(player.binjo == '参加しない' for player in player.group.get_players()) form_model = 'player' form_fields = ['choice_number'] class calculation_1(WaitPage): @staticmethod def after_all_players_arrive(group: Group): for player in group.get_players(): set_soten(player) group = group choices = [p.choice_number for p in group.get_players()] group.min_choice = min(choices) for player in group.get_players(): if player.choice_number == group.min_choice: num_players_with_min_choice = choices.count(group.min_choice) player.points = 1 / num_players_with_min_choice else: player.points = 0 class calculation_2(WaitPage): @staticmethod def after_all_players_arrive(group: Group): for player in group.get_players(): set_simple_point(player) class calculation_3(WaitPage): @staticmethod def is_displayed(player: Player): binjo_players = player.group.get_players() return all(player.teian == '提案する' for player in player.group.get_players()) or all( player.binjo == '参加する' for player in binjo_players ) @staticmethod def after_all_players_arrive(group: Group): players = group.get_players() players.sort(key=lambda x: (x.hokoku_1, x.hokoku_2, x.hokoku_3), reverse=True) for i, player in enumerate(players, 1): player.rank = i # tied_rank_list = [i for i,player in enumerate(players) if player.rank == players[0].rank] # for player in players: # player.tie_penalty_point(tied_rank_list) rank_point(player) class Results(Page): timeout_seconds = 15 page_sequence = [ stop, rensyu, teian, teian_result, binjo, binjo_wait, hokoku_first, wait_chat, caltel_choice, wait_page, hokoku_last, not_caltel_choice, calculation_1, calculation_2, calculation_3, Results, ]