from otree.api import * doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'Uncertainty_OT_FI' PLAYERS_PER_GROUP = 2 NUM_ROUNDS = 10 first_role = 'Group one' second_role = 'Group two' class Subsession(BaseSubsession): pass class Group(BaseGroup): aggregate = models.BooleanField() positive_aggregate = models.BooleanField() clear = models.BooleanField() average_price = models.FloatField() class Player(BasePlayer): # pictures = models.BooleanField() necessary for explanation picture? # if comprehension test is needed, see steph # constants omega_current = models.IntegerField(default = 40) omega_pre = models.IntegerField(default = 40) omega_small = models.IntegerField(default = 20) omega_large = models.IntegerField(default = 60) omega_average = models.IntegerField(default = 40) cost_deduction = models.IntegerField(default = 10) maximum_price = models.IntegerField() shock = models.IntegerField(default=6) shock_announcement = models.BooleanField() display_shock = models.BooleanField() explanation = models.LongStringField() final = models.IntegerField(default=10) # player variables price = models.IntegerField(label="Please enter a price for YOUR good.", min=0) output = models.IntegerField() unit_costs = models.FloatField() total_costs = models.FloatField() revenue = models.FloatField() earnings = models.FloatField(label="Please enter your explanation.", min=0) # variables for payoffs payoff_round = models.FloatField() # if I don't round, then it needs to be a float payoff_acc = models.FloatField() payoff_mon = models.CurrencyField() payoff_mon_total = models.CurrencyField() #roles role_one = models.BooleanField() # summary questionnaire? def price_max(player): return player.omega_current def price_min(player): return player.cost_deduction # assign treatments def creating_session(subsession): #state_aggregate = subsession.session.config['aggregate'] #state_clear = subsession.session.config['clear'] #print(state_aggregate) #print(state_clear) for group in subsession.get_groups(): for p in group.get_players(): if p.id_in_group % 2 == 0: p.role_one = True else: p.role_one = False import random for group in subsession.get_groups(): if subsession.round_number == 1: group.aggregate = random.choice([True, False]) print('set aggregate to', group.aggregate) import itertools aggregate = itertools.cycle([True, False, True, False]) for group in subsession.get_groups(): group.aggregate = next(aggregate) group.positive_aggregate = random.choice([True, False]) print('set positive aggregate to', group.positive_aggregate) import itertools positive_aggregate = itertools.cycle([True, False]) for group in subsession.get_groups(): group.positive_aggregate = next(positive_aggregate) group.clear = random.choice([True, False]) print('set clear to', group.clear) import itertools clear = itertools.cycle([True, False, False, True]) for group in subsession.get_groups(): group.clear = next(clear) else: group.aggregate = group.in_round(1).aggregate group.positive_aggregate = group.in_round(1).positive_aggregate group.clear = group.in_round(1).clear # currently this is only for a positive shock of omega --> group statt player for p in group.get_players(): if 6<= group.round_number <=10: if group.aggregate: if group.positive_aggregate: p.omega_current = p.omega_large else: p.omega_current = p.omega_small else: if p.role_one: p.omega_current = p.omega_large else: p.omega_current = p.omega_small # is this even necessary, if I use if conditions in the template? for group in subsession.get_groups(): for p in group.get_players(): p.clear=group.clear if p.clear: p.shock_announcement=True else: p.shock_announcement = False for group in subsession.get_groups(): if group.round_number==Player.shock: group.display_shock=True else: group.display_shock=False def average_price(group): group.average_price = 0 for player in group.get_players(): group.average_price += player.price group.average_price /= C.PLAYERS_PER_GROUP # calculating the earnings def round_results(group): players = group.get_players() for p in players: if p.price < 10: p.price = 10 players = group.get_players() group.average_price = 0 for player in group.get_players(): group.average_price += player.price group.average_price /= C.PLAYERS_PER_GROUP for p in players: p.output = (p.omega_current - p.price) p.revenue = p.output * p.price p.unit_costs = group.average_price - p.cost_deduction p.total_costs = p.unit_costs * p.output p.earnings = (p.price - p.unit_costs) * p.output for p in players: if p.output < 0: p.output =0 if p.earnings < 0: p.earnings = 0 players = group.get_players() for p in players: p.payoff_round = p.earnings if group.round_number>1: player_in_all_rounds=p.in_all_rounds() p.payoff_acc = sum([p.payoff_round for p in player_in_all_rounds]) else: p.payoff_acc = p.payoff_round p.payoff_mon = p.payoff_acc + 3.5 if p.payoff_mon < 0.1: #? p.payoff_mon = 3.5 # as currently defined, there cannot be negative value in the end. otherwise use if conditions <0 = =0 # further currently there is no test or anything alike included, thus payoff = payoff_total # currently no calibration of the payoffs # PAGES class Introduction(Page): timeout_seconds = 240 def is_displayed(player: Player): return (player.round_number == 1) class Instructions(Page): timeout_seconds = 720 def is_displayed(player: Player): return (player.round_number == 1) # yet no dropout marker right now. if I include it, then include it for the payoff as well class StartWait(WaitPage): # after_all_players_arrive = 'assigned_roles' title_text = "Please wait a moment." body_text = "Please wait for the other players to be ready in order to start the experiment." \ "It will continue shortly." class PriceDecision(Page): form_model = 'player' form_fields = ['price'] class ResultsWait(WaitPage): after_all_players_arrive='round_results' title_text = "Please wait a moment." body_text = "Please wait for the other players to be ready in order to start the experiment. " \ "It will continue shortly." class Explanation(Page): def is_displayed(player: Player): return (player.round_number == 1 or player.round_number == player.shock) form_model = 'player' form_fields = ['explanation'] class ResultsFeedback(Page): pass class ShockAnnouncement(Page): def is_displayed(player: Player): return (player.round_number == player.shock) class FinalPage(Page): def is_displayed(player: Player): return (player.round_number == player.final) page_sequence = [Introduction, Instructions, StartWait, ShockAnnouncement, PriceDecision, ResultsWait, Explanation, ResultsFeedback, FinalPage]