from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, random, ) author = 'Aoi_Kokado' doc = """ 卒研用実験 """ class Constants(BaseConstants): name_in_url = '2023年卒論用実験_前半' players_per_group = 3 num_rounds = 8 num_choices = 10 min_choice = 101 max_choice = min_choice + num_choices - 1 #instructions_template = 'Jikken_2023/instructions.html' class Subsession(BaseSubsession): def creating_session(self): if self.round_number == 1: self.group_randomly() else: self.group_like_round(1) class Group(BaseGroup): min_choice = models.IntegerField() end_point = models.IntegerField() class Player(BasePlayer): teian = models.StringField( choices = [['提案する','提案する'],['提案しない','提案しない']], label = 'カルテルを提案しますか?', widget = widgets.RadioSelectHorizontal, ) def other_players_all_no(self): return all([p.teian == '提案しない' for p in self.get_others_in_group()]) def other_players_all_yes(self): return all([p.teian == '提案する' for p in self.get_others_in_group()]) def other_player_some_yes(self): return any([p.teian == '提案する' for p in self.get_others_in_group()]) def other_player_some_no(self): return any([p.teian == '提案しない' for p in self.get_others_in_group()]) binjo = models.StringField( choices = [['参加する','参加する'],['参加しない','参加しない']], label = 'カルテルに参加しますか?', widget = widgets.RadioSelectHorizontal, ) def other_player_some_not_binjo(self): return any([p.teian == '参加しない' for p in self.get_others_in_group()]) def other_player_all_not_binjo(self): return all([p.teian == '参加しない' for p in self.get_others_in_group()]) def other_player_all_binjo(self): return all([p.teian == '参加する' for p in self.get_others_in_group()]) 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() def set_soten(self): self.soten =self.choice_number - 100 self.soten_point = 6*self.soten soten_point = models.FloatField() caltel_point = models.FloatField() result_point = models.FloatField() def set_simple_point(self): self.result_point = self.soten_point * self.points 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) def set_all_question_to_yes_1(self): if self.hokoku_1: self.hokoku_2 = '報告する' self.hokoku_3 = '報告する' def set_all_question_to_yes_2(self): if self.hokoku_2: self.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(self): if self.rank == 1: self.penalty_point = 0 elif self.rank == 2: self.penalty_point = 0.5 elif self.rank == 3: self.penalty_point = 1 else: self.penalty_point = 0 random_time = models.IntegerField() finally_point = models.IntegerField() bakkin = models.IntegerField() penalty_random = models.IntegerField() random_result = models.IntegerField() def set_penalty(self): self.bakkin = self.result_point * 0.1 * self.penalty_point def set_penalty_random(self): self.penalty_random = self.result_point * 0.1 def set_penalty_random_point(self): self.random_result = self.result_point - self.penalty_random def set_finally_point(self): self.finally_point = self.result_point - self.bakkin from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants import random class zenhan(Page): def is_displayed(self): return self.round_number == 1 timeout_seconds = 10 class teian(Page): form_model = 'player' form_fields = ['teian'] class teian_result(WaitPage): pass class binjo(Page): def is_displayed(self): return any(player.teian == '提案しない' for player in self.group.get_players()) and any(player.teian == '提案する' for player in self.group.get_players()) form_model = 'player' form_fields = ['binjo'] class binjo_wait(WaitPage): pass class hokoku_first(Page): timeout_seconds = 30 def is_displayed(self): return all(player.teian == '提案する' for player in self.group.get_players()) or all(player.binjo == '参加する' for player in self.group.get_players()) form_model = 'player' form_fields = ['hokoku_1'] def before_next_page(self): self.player.set_all_question_to_yes_1() class wait_chat(WaitPage): pass class caltel_choice(Page): timeout_seconds = 120 def is_displayed(self): return all(player.teian == '提案する' for player in self.group.get_players()) or all(player.binjo == '参加する' for player in self.group.get_players()) form_model = 'player' form_fields = ['choice_number','hokoku_2'] def before_next_page(self): self.player.set_all_question_to_yes_2() class wait_page(WaitPage): pass class hokoku_last(Page): timeout_seconds = 30 def is_displayed(self): return all(player.teian == '提案する' for player in self.group.get_players()) or all(player.binjo == '参加する' for player in self.group.get_players()) form_model = 'player' form_fields = ['hokoku_3'] class all_not_teian_choice(Page): timeout_seconds = 60 def is_displayed(self): return all(player.teian == '提案しない' for player in self.group.get_players()) form_model = 'player' form_fields = ['choice_number'] class not_caltel_choice(Page): timeout_seconds = 60 def is_displayed(self): return any(player.binjo == '参加しない' for player in self.group.get_players()) form_model = 'player' form_fields = ['choice_number'] class calculation_1(WaitPage): def after_all_players_arrive(self): for player in self.group.get_players(): player.set_soten() group = self.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): def after_all_players_arrive(self): for player in self.group.get_players(): player.set_simple_point() class calculation_3(WaitPage): def is_displayed(self): binjo_players = self.group.get_players() return all(player.teian == '提案する' for player in self.group.get_players()) or all(player.binjo == '参加する' for player in binjo_players) def after_all_players_arrive(self): players = self.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) player.rank_point() class calculation_4(WaitPage): def before_next_page(self): self.player.random_time = random.randint(1,10) def is_displayed(self): return self.player.random_time == 1 def after_all_players_arrive(self): for player in self.group.get_players(): player.set_penalty_random() player.set_penalty_random_point() class Results(Page): timeout_seconds = 15 class random_number(WaitPage): def is_displayed(self): return self.round_number >= 8 def after_all_players_arrive(self): end_point = random.randint(1,100) if end_point <=20: pass else: @staticmethod def app_after_this_page(player,upconing_apps): if player.whatever: return upconing_apps[0] class check(Page): pass page_sequence = [zenhan,teian,teian_result,binjo,binjo_wait,hokoku_first,wait_chat,caltel_choice,wait_page,hokoku_last,all_not_teian_choice,not_caltel_choice, calculation_1,calculation_2,calculation_3,calculation_4,Results]