from otree.api import * class C(BaseConstants): NAME_IN_URL = 'auction_2_13to3' PLAYERS_PER_GROUP = 2 NUM_ROUNDS = 20 FIRST_ROUNDS=10 SECOND_ROUNDS=10 INSTRUCTIONS_TEMPLATE = 'auction_2_13to3/instructions.html' PAYOFF_TEMPLATE='auction_2_13to3/payoff_instructions.html' BID_MIN = cu(0) BID_MAX = cu(100) #COST=cu(3) FIRST_COST=cu(13) SECOND_COST=cu(3) TIME=[None,None,None,None,None] #イントロ、情報、入札、結果、ED SECOND_TIME=[30,45,45,30,None] LAST_TIME=[90,90,90,90,None] #11ラウンド目 class Subsession(BaseSubsession): highest_gain=models.CurrencyField() class Group(BaseGroup): highest_bid = models.CurrencyField() second_highest_bid = models.CurrencyField() which_cost=models.CurrencyField(doc="前半と後半でコスト変化") tie_true=models.BooleanField( initial=False, doc="""Trueならば同点""" ) class Player(BasePlayer): item_value = models.CurrencyField( doc="""評価値を格納""" ) bid_amount = models.IntegerField( min=C.BID_MIN, max=C.BID_MAX, doc="""入札額の入力""", label="入札額", ) # bid_amount = models.CurrencyField( # choices=range(0,101) # # ) is_winner = models.BooleanField( initial=False, doc="""Trueならば落札""" ) is_highest_valuer = models.BooleanField( initial=False, doc="""Trueならば最高評価値をもつ入札者""" ) acquisition=models.BooleanField( initial=True, doc="""情報を取得するかどうか。したらTrue""", label="商品の評価値を取得しますか?", ) information_cost=models.CurrencyField( doc="""情報を取得したらコストの値、しなかったらゼロ""" ) time_out=models.BooleanField( initial=False, doc="""Trueならばタイムアウト(データから除外する)""" ) total_payoff = models.CurrencyField( doc="""評価値を格納""" ) # FUNCTIONS def creating_session(subsession: Subsession): #subsession.group_randomly() pass def set_winner(group: Group): import random players = group.get_players() bid_list=sorted([p.bid_amount for p in players],reverse=True) group.highest_bid = bid_list[0] group.second_highest_bid = bid_list[1] players_with_highest_bid = [p for p in players if p.bid_amount == group.highest_bid] players_with_second_highest_bid = [p for p in players if p.bid_amount == group.second_highest_bid] winner = random.choice( players_with_highest_bid ) # if tie, winner is chosen at random if len(players_with_highest_bid)>=2: group.tie_true=True #同点の場合 winner.is_winner = True #効率性の導出のため、最も高い評価値を持つ人を識別 group_highest_value=max([p.item_value for p in players]) players_with_highest_value = [p for p in players if p.item_value == group_highest_value] for p in players_with_highest_value: p.is_highest_valuer=True for p in players: set_payoff(p) def generate_value(group: Group): import random value = random.randint(C.BID_MIN, C.BID_MAX) return value def choose_cost(group: Group): if group.round_number <= C.FIRST_ROUNDS: group.which_cost=C.FIRST_COST else: group.which_cost=C.SECOND_COST return group.which_cost def information_cost(player: Player): cost=0 group=player.group if player.acquisition==True: #cost =C.COST cost =group.which_cost return cost def set_payoff(player: Player): group = player.group if player.is_winner: player.payoff = player.item_value - group.second_highest_bid - player.information_cost else: player.payoff = - player.information_cost #ゲームの最後にランキング表示 def payoff_rank(player: Player): subsession = player.subsession players = subsession.get_players() rank_dict={} for p in players: p_id=p.id_in_subsession p.total_payoff=total_payoff_gen(p) rank_dict[p_id]=p.total_payoff rank_dict=dict(rank_dict) payoff_rank_list=sorted([p.total_payoff for p in players],reverse=True) rank_dict=sorted(rank_dict.items(), key=lambda x:x[1], reverse=True) rank_dict=dict(rank_dict) subsession.highest_gain=payoff_rank_list[0] rank_number_list=list(range(1,len(players)+1)) rank_values=list(rank_dict.values()) rank_keys=list(rank_dict.keys()) #参加者の順位の抽出 your_id=player.id_in_subsession your_rank_def=0 your_rank_flag=True while your_rank_flag: your_rank_def+=1 if your_id==rank_keys[your_rank_def-1]: your_rank=your_rank_def your_rank_flag=False #五位まで表示 if len(rank_number_list)>5: rank_number_list=rank_number_list[0:5] rank_values=rank_values[0:5] rank_keys=rank_keys[0:5] return rank_values,rank_keys,rank_number_list,your_rank def total_payoff_gen(player: Player): player_in_all_rounds = player.in_all_rounds() return sum([p.payoff for p in player_in_all_rounds]) # PAGES class IntroductionWaitPage(WaitPage): group_by_arrival_time = True after_all_players_arrive=choose_cost template_name = 'MyWaitPage.html' class Interval(Page): def is_displayed(player: Player): return player.round_number == C.FIRST_ROUNDS+1 timeout_seconds = 60 class Introcut(Page): def is_displayed(player: Player): return player.round_number == 4 or player.round_number == 14 timeout_seconds = 30 class Introduction(Page): def is_displayed(player: Player): return player.round_number <= 3 or (player.round_number >= 11 and player.round_number<=13) @staticmethod def get_timeout_seconds(player): if player.round_number == 1 : return C.TIME[0] elif player.round_number == C.FIRST_ROUNDS+1 : return C.LAST_TIME[0] else: return C.SECOND_TIME[0] #@staticmethod def before_next_page(player: Player, timeout_happened): # group = player.group # player.item_value = generate_value(group) if timeout_happened: player.time_out = True class Acquisition(Page): @staticmethod def get_timeout_seconds(player): if player.round_number == 1 : return C.TIME[1] elif player.round_number == C.FIRST_ROUNDS+1 : return C.LAST_TIME[1] else: return C.SECOND_TIME[1] form_model = 'player' form_fields = ['acquisition'] @staticmethod def before_next_page(player: Player, timeout_happened): group = player.group player.item_value = generate_value(group) player.information_cost=information_cost(player) if timeout_happened: player.time_out = True class Bid(Page): @staticmethod def get_timeout_seconds(player): if player.round_number == 1 : return C.TIME[2] elif player.round_number == C.FIRST_ROUNDS+1 : return C.LAST_TIME[2] else: return C.SECOND_TIME[2] form_model = 'player' form_fields = ['bid_amount'] @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.time_out = True class ResultsWaitPage(WaitPage): after_all_players_arrive = set_winner template_name = 'MyWaitPage.html' class Results(Page): @staticmethod def get_timeout_seconds(player): if player.round_number == 1 : return C.TIME[3] elif player.round_number == C.FIRST_ROUNDS+1 : return C.LAST_TIME[3] else: return C.SECOND_TIME[3] def vars_for_template(player: Player): player_in_all_rounds = player.in_all_rounds() return dict( total_payoff=sum([p.payoff for p in player_in_all_rounds]), player_in_all_rounds=player_in_all_rounds, ) class ResultsSummary(Page): timeout_seconds = C.TIME[4] @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS @staticmethod def vars_for_template(player: Player): session = player.session subsession = player.subsession player_in_all_rounds = player.in_all_rounds() after_all_players_arrive=payoff_rank(player) return dict( total_payoff=sum([p.payoff for p in player_in_all_rounds]), player_in_all_rounds=player_in_all_rounds, rank_value=payoff_rank(player)[0], rank_key=payoff_rank(player)[1], rank_number=payoff_rank(player)[2], your_rank=payoff_rank(player)[3], ) page_sequence = [IntroductionWaitPage,Interval,Introcut,Introduction,Acquisition, Bid, ResultsWaitPage, Results,ResultsSummary]