class Player(otree.models.BasePlayer): # <built-in> group = models.ForeignKey(Group, null=True) subsession = models.ForeignKey(Subsession) # </built-in> private_value = models.MoneyField( doc="""How much the player values the item, generated randomly""" ) bid_amount = models.MoneyField( default=None, doc="""Amount bidded by the player""" ) def bid_amount_choices(self): return money_range(Constants.min_allowable_bid, Constants.max_allowable_bid, 0.05) is_winner = models.BooleanField( default=False, doc="""Indicates whether the player is the winner""" ) def generate_private_value(self): return round(random.uniform(Constants.min_allowable_bid, Constants.max_allowable_bid), 1) def set_payoff(self): if self.is_winner: self.payoff = self.private_value - self.bid_amount if self.payoff < 0: self.payoff = 0 else: self.payoff = 0
class Player(otree.models.BasePlayer): # <built-in> group = models.ForeignKey(Group, null=True) subsession = models.ForeignKey(Subsession) # </built-in> item_value_estimate = models.MoneyField( doc="""Estimate of the common value, may be different for each player""" ) bid_amount = models.MoneyField(doc="""Amount bidded by the player""") def bid_amount_error_message(self, value): if not Constants.min_allowable_bid <= value <= Constants.max_allowable_bid: return 'The amount bidded must be between {} and {}, inclusive.'.format( Constants.min_allowable_bid, Constants.max_allowable_bid) is_winner = models.BooleanField( default=False, doc="""Indicates whether the player is the winner""") def set_payoff(self): if self.is_winner: self.payoff = self.subsession.item_value - self.bid_amount if self.payoff < 0: self.payoff = 0 else: self.payoff = 0
class Group(otree.models.BaseGroup): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> players_per_group = 2 sent_amount = models.MoneyField( default=None, doc="""Amount sent by P1""", ) sent_back_amount = models.MoneyField( default=None, doc="""Amount sent back by P2""", ) def sent_amount_choices(self): """Range of allowed values during send""" return money_range(0, self.subsession.amount_allocated, self.subsession.increment_amount) def sent_back_amount_choices(self): """Range of allowed values during send back""" return money_range(0, self.sent_amount * 3, self.subsession.increment_amount) def set_payoffs(self): p1 = self.get_player_by_id(1) p2 = self.get_player_by_id(2) p1.payoff = self.subsession.amount_allocated - self.sent_amount + self.sent_back_amount p2.payoff = self.subsession.amount_allocated + self.sent_amount * 3 - self.sent_back_amount
class Subsession(otree.models.BaseSubsession): name_in_url = 'principal_agent' max_fixed_payment = models.MoneyField( default=7.00, doc="""Maxmimum absolute value for agent's fixed pay""") reject_principal_pay = models.MoneyField( default=0, doc="""Amount principal gets if contract is rejected""") reject_agent_pay = models.MoneyField( default=1.00, doc="""Amount agent gets if contract is rejected""") agent_work_effort_base_return = models.MoneyField( default=0.7, doc="""Total return for single unit of agent's work effort""") @staticmethod def cost_from_effort(effort): costs = { 1: 0, 2: .20, 3: .40, 4: .60, 5: .90, 6: 1.20, 7: 1.60, 8: 2.00, 9: 2.50, 10: 3.00 } return Money(costs[effort]) def return_from_effort(self, effort): return effort * Money(self.agent_work_effort_base_return)
class Group(otree.models.BaseGroup): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> players_per_group = 2 total_return = models.MoneyField( doc="""Total return from agent's effort = [Return for single unit of agent's work effort] * [Agent's work effort]""" ) agent_fixed_pay = models.MoneyField( doc="""Amount offered as fixed pay to agent""" ) agent_return_share = models.FloatField( doc="""Agent's share of total return""", ) agent_work_effort = models.PositiveIntegerField( doc="""Agent's work effort, [1, 10]""", ) agent_work_cost = models.MoneyField( doc="""Agent's cost of work effort""" ) contract_accepted = models.NullBooleanField( doc="""Whether agent accepts proposal""", widget=widgets.RadioSelect(), ) # choices def agent_fixed_pay_choices(self): return money_range(-Constants.max_fixed_payment, Constants.max_fixed_payment, 0.50) def agent_work_effort_choices(self): return range(1, 10+1) def agent_return_share_choices(self): return Constants.agent_return_share_choices def set_payoffs(self): principal = self.get_player_by_role('principal') agent = self.get_player_by_role('agent') if not self.contract_accepted: principal.payoff = Constants.reject_principal_pay agent.payoff = Constants.reject_agent_pay else: self.agent_work_cost = cost_from_effort(self.agent_work_effort) self.total_return = return_from_effort(self.agent_work_effort) money_to_agent = self.agent_return_share*self.total_return + self.agent_fixed_pay agent.payoff = money_to_agent - self.agent_work_cost principal.payoff = self.total_return - money_to_agent
class Subsession(otree.models.BaseSubsession): name_in_url = 'private_value_auction' min_allowable_bid = models.MoneyField(default=0.0, doc="""Minimum value of item""") max_allowable_bid = models.MoneyField(default=10.0, doc="""Maximum value of item""")
class Subsession(otree.models.BaseSubsession): name_in_url = 'coordination' group_amount = models.MoneyField( default=1.00, doc="""Payoff for each player if choices group""") mismatch_amount = models.MoneyField( default=0.00, doc="""Payoff for each player if choices don't group""")
class Subsession(otree.models.BaseSubsession): name_in_url = 'matrix_symmetric' self_A_other_A = models.MoneyField(default=0.10) self_A_other_B = models.MoneyField( default=0.00, doc='''How much I make if I choose A and the other player chooses B''' ) self_B_other_A = models.MoneyField(default=0.30) self_B_other_B = models.MoneyField(default=0.40)
class Subsession(otree.models.BaseSubsession): name_in_url = 'bertrand_competition' marginal_cost = models.MoneyField( default=0.20, doc= """Marginal cost of production, effectively the minimum price (exclusive)""" ) maximum_price = models.MoneyField(default=1.00, doc="""The maximum price""")
class Subsession(otree.models.BaseSubsession): name_in_url = 'volunteer_dilemma' general_benefit = models.MoneyField( default=1.00, doc="""Payoff for each player if at least one volunteers""" ) volunteer_cost = models.MoneyField( default=0.40, doc="""Cost incurred by volunteering player""" )
class Subsession(otree.models.BaseSubsession): name_in_url = 'trust' amount_allocated = models.MoneyField( default=1.00, doc="""Initial amount allocated to each player""" ) increment_amount = models.MoneyField( default=0.05, doc="""The increment between amount choices""" )
class Subsession(otree.models.BaseSubsession): name_in_url = 'traveler_dilemma' reward = models.MoneyField(default=0.10, doc="""Player's reward for the lowest claim""") penalty = models.MoneyField( default=0.10, doc="""Player's deduction for the higher claim""") max_amount = models.MoneyField(default=1.00, doc="""The maximum claim to be requested""") min_amount = models.MoneyField(default=0.20, doc="""The minimum claim to be requested""")
class Subsession(otree.models.BaseSubsession): name_in_url = 'exp2' most_common_rating = models.IntegerField( default=None, choices=RATING_CHOICES, doc="rating given most often among players") def most_common_rating_choices(self): return self.RATING_CHOICES def set_payoffs(self): for p in self.get_players(): # if p.rating == p.random_rating: if p.rating == self.most_common_rating: p.payoff = self.match_payoff else: p.payoff = 0 def most_common(self): ratings = [p.rating for p in self.get_players()] self.most_common_rating = collections.Counter(ratings).most_common( 1)[0][0] # at the moment, the program does not take care of ties match_payoff = models.MoneyField( default=200, doc="payoff if answer matches most common answer")
class Player(otree.models.BasePlayer): # <built-in> subsession = models.ForeignKey(Subsession) group = models.ForeignKey(Group, null=True) # </built-in> q_doctor = models.PositiveIntegerField(default=None, verbose_name=''' A doctor gives you 3 pills, and tells you to take 1 pill every 30 minutes starting right away. After how many minutes will you run out of pills?''', correct_answer=60, correct_answer_explanation=''' You take the first pill right now, the second pill after 30 minutes, and the third pill after 60 minutes, so after 60 minutes you will have run out of pills. ''') q_meal = models.MoneyField(default=None, verbose_name=''' A meal, including a beverage, costs {} in total. The food costs 5 times as much as the beverage. How much does the food cost?' '''.format(Money(1.20)), correct_answer=Money(1.00), correct_answer_explanation=''' The beverage costs {} and the food costs {} '''.format(Money(0.20), Money(1.00)))
class Group(otree.models.BaseGroup): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> players_per_group = 3 num_winners = models.PositiveIntegerField( default=None, doc="""How many players offer lowest price""") winning_price = models.MoneyField(default=None, doc="""Lowest price""") def set_payoffs(self): self.winning_price = min([p.price for p in self.players]) self.num_winners = len( [p for p in self.players if p.price == self.winning_price]) winner_payoff = (self.winning_price - self.subsession.marginal_cost) / self.num_winners for p in self.players: if p.price == self.winning_price: p.is_a_winner = True p.payoff = winner_payoff else: p.is_a_winner = False p.payoff = 0
class Subsession(otree.models.BaseSubsession): name_in_url = 'common_value_auction' def highest_bid(self): return max([p.bid_amount for p in self.get_players()]) def set_winner(self): players_with_highest_bid = [ p for p in self.get_players() if p.bid_amount == self.highest_bid() ] winner = random.choice( players_with_highest_bid) # if tie, winner is chosen at random winner.is_winner = True item_value = models.MoneyField( default=lambda: round( random.uniform(Constants.min_allowable_bid, Constants. max_allowable_bid), 1), doc="""Common value of the item to be auctioned, random for treatment""" ) def generate_value_estimate(self): minimum = self.item_value - Constants.estimate_error_margin maximum = self.item_value + Constants.estimate_error_margin estimate = round(random.uniform(minimum, maximum), 1) if estimate < Constants.min_allowable_bid: estimate = Constants.min_allowable_bid if estimate > Constants.max_allowable_bid: estimate = Constants.max_allowable_bid return estimate
class Player(otree.models.BasePlayer): # <built-in> group = models.ForeignKey(Group, null=True) subsession = models.ForeignKey(Subsession) # </built-in> # claim by player claim = models.MoneyField(default=None, doc=""" Each player's claim """) def claim_choices(self): """Range of allowed claim values""" return money_range(self.subsession.min_amount, self.subsession.max_amount, 0.05) def other_player(self): return self.other_players_in_group()[0] def set_payoff(self): if self.claim < self.other_player().claim: self.payoff = self.claim + self.subsession.reward elif self.claim > self.other_player().claim: self.payoff = self.other_player().claim - self.subsession.penalty else: self.payoff = self.claim
class Subsession(otree.models.BaseSubsession): name_in_url = 'lemon_market' max_bid_amount = models.MoneyField(default=1.00, doc=""" Maximum allowed bid amount. """)
class Subsession(otree.models.BaseSubsession): name_in_url = 'bargaining' amount_shared = models.MoneyField(default=1.00, doc=""" Amount to be shared by both players """)
class Player(otree.models.BasePlayer): # <built-in> match = models.ForeignKey(Match, null=True) treatment = models.ForeignKey(Treatment, null=True) subsession = models.ForeignKey(Subsession) # </built-in> contribution = models.MoneyField(default=None, doc="player's own contribution")
class Treatment(otree.models.BaseTreatment): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> match_payoff = models.MoneyField( default=200, doc="payoff if answer matches most common answer" )
class Player(otree.models.BasePlayer): # <built-in> subsession = models.ForeignKey(Subsession) group = models.ForeignKey(Group, null = True) # </built-in> # initial shares and cash cash = models.MoneyField(default=20) shares = models.PositiveIntegerField(default=5) # order fields order_type = models.CharField(max_length=10, choices=['Buy Order', 'Sell Order', 'None'], widget=widgets.RadioSelect()) bp = models.MoneyField(default=0.00, doc="""maximum buying price per share""") bn = models.PositiveIntegerField(default=0, doc="""number of shares willing to buy""") sp = models.MoneyField(default=0.00, doc="""minimum selling price per share""") sn = models.PositiveIntegerField(default=0, doc="""number of shares willing to sell.""") def other_player(self): """Returns other player in group. Only valid for 2-player groupes.""" return self.other_players_in_group()[0] QUESTION_1_CHOICES = ['P=3, N=2','P=2, N=3','P=2.5, N=3','P=2.5, N=2','No transaction will take place',] QUESTION_2_CHOICES = ['$8, $12', '$12, $8', '$8, $8', '$12, $12', '$10, $10'] understanding_question_1 = models.CharField(max_length=100, null=True, choices=QUESTION_1_CHOICES, verbose_name='', widget=widgets.RadioSelect()) understanding_question_2 = models.CharField(max_length=100, null=True, choices=QUESTION_2_CHOICES, verbose_name='', widget=widgets.RadioSelect()) # check correct answers def is_understanding_question_1_correct(self): return self.understanding_question_1 == self.subsession.understanding_1_correct def is_understanding_question_2_correct(self): return self.understanding_question_2 == self.subsession.understanding_2_correct def my_field_error_message(self, value): if not 0 <= value <= 10: return 'Value is not in allowed range' def role(self): # you can make this depend of self.id_in_group return ''
class Subsession(otree.models.BaseSubsession): name_in_url = 'common_value_auction' def highest_bid(self): return max([p.bid_amount for p in self.players]) def set_winner(self): players_with_highest_bid = [ p for p in self.players if p.bid_amount == self.highest_bid() ] winner = random.choice( players_with_highest_bid) # if tie, winner is chosen at random winner.is_winner = True item_value = models.MoneyField( default=lambda: random_item_value, doc="""Common value of the item to be auctioned, random for treatment""" ) min_allowable_bid = models.MoneyField(default=min_value, doc="""Minimum value of item""") max_allowable_bid = models.MoneyField(default=max_value, doc="""Maximum value of item""") estimate_error_margin = models.MoneyField( default=1.00, doc="""Error margin for the value estimates shown to the players""") def generate_value_estimate(self): minimum = self.item_value - self.estimate_error_margin maximum = self.item_value + self.estimate_error_margin estimate = round(random.uniform(minimum, maximum), 1) if estimate < self.min_allowable_bid: estimate = self.min_allowable_bid if estimate > self.max_allowable_bid: estimate = self.max_allowable_bid return estimate
class Group(otree.models.BaseGroup): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> bid_amount = models.MoneyField(doc=""" Amount bidded by the bidder """) random_value = models.MoneyField(doc=""" Random value for the value of commodity to be auctioned. """) players_per_group = 1 def calculate_value(self): self.random_value = random.choice(money_range(0.00, 1.00)) def bid_amount_choices(self): return money_range(0, Constants.max_bid_amount, 0.05)
class Player(otree.models.BasePlayer): # <built-in> group = models.ForeignKey(Group, null=True) subsession = models.ForeignKey(Subsession) # </built-in> contribution = models.MoneyField(default=None, doc="player's own contribution") def contribution_choices(self): return money_range(0, self.subsession.endowment, 1.00)
class Subsession(otree.models.BaseSubsession): name_in_url = 'exp3' endowment = models.MoneyField( default=20.00, doc="payoff = p(endowment-contribution)+a/N*sum(contribution)") a = models.FloatField( default=2.0, doc="payoff = p(endowment-contribution)+a/N*sum(contribution)")
class Match(otree.models.BaseMatch): # <built-in> treatment = models.ForeignKey(Treatment) subsession = models.ForeignKey(Subsession) # </built-in> players_per_match = 10 sum_contribution = models.MoneyField( default=None, doc="sum of contributions in a matching group") avg_contribution = models.MoneyField( default=None, doc="average contribution of the other players") def sum_avg(self): self.sum_contribution = sum(p.contribution for p in self.players) self.avg_contribution = self.sum_contribution / self.players_per_match def set_payoffs(self): for p in self.players: p.payoff = (p.treatment.endowment - p.contribution ) + p.treatment.a * p.match.avg_contribution
class Group(otree.models.BaseGroup): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> players_per_group = PLAYERS_PER_GROUP sum_contribution = models.MoneyField(default=None, doc="sum of contributions per group") avg_contribution = models.MoneyField( default=None, doc="average contribution of all players in group") def sum_avg(self): self.sum_contribution = sum(p.contribution for p in self.get_players()) self.avg_contribution = self.sum_contribution / self.players_per_group def set_payoffs(self): for p in self.get_players(): p.payoff = ( self.subsession.endowment - p.contribution ) + self.subsession.a / self.players_per_group * self.sum_contribution
class Subsession(otree.models.BaseSubsession): name_in_url = 'stag_hunt' stag_stag_amount = models.MoneyField( default=0.20, doc="""Payoff if both players choose stag""" ) stag_hare_amount = models.MoneyField( default=0.00, doc="""Payoff if the player chooses stag but the other hare""" ) hare_stag_amount = models.MoneyField( default=0.10, doc="""Payoff if the player chooses hare but the other stag""" ) hare_hare_amount = models.MoneyField( default=0.10, doc="""Payoff if both players choose hare""" )
class Treatment(otree.models.BaseTreatment): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> endowment = models.MoneyField( default=20.00, doc="payoff = p(endowment-contribution)+a/N*sum(contribution)") a = models.FloatField( default=2.0, doc="payoff = p(endowment-contribution)+a/N*sum(contribution)") def contribution_choices(self): return money_range(0, self.endowment, 1.00)