import random
from otree import widgets
from otree.api import (BaseConstants, BaseGroup, BasePlayer, BaseSubsession, Currency as c, models)
from settings import POINTS_CUSTOM_NAME
author = 'Robert zur Bonsen'
doc = """
"""
class Constants(BaseConstants):
name_in_url = 'exp'
players_per_group = 2
num_rounds = 1
proposer = 'A'
responder = 'B'
endowment_p_first_stage_label = 'a1'
endowment_p_second_stage_label = 'a2'
endowment_r_first_stage_label = 'b1'
endowment_r_second_stage_label = 'b2'
template_instructions = 'main/Instructions.html'
template_footer = 'main/Footer.html'
points_label = POINTS_CUSTOM_NAME
class Subsession(BaseSubsession):
@property
def points_per_real_world_currency(self):
return c(1 / self.session.config['real_world_currency_per_point'])
def creating_session(self):
self.session.vars['next'] = 1 #True # Geändert
class Group(BaseGroup):
# Treatment
endowment_first_stage = models.CurrencyField()
endowment_second_stage = models.CurrencyField()
endowment_other = models.CurrencyField()
upper_range = models.CurrencyField()
treatment = models.IntegerField() # Geändert? ...models.BooleanField()
# Game
#offer = models.CurrencyField(min=0)
offer = models.CurrencyField()
initial = models.CurrencyField()#Geändert
response = models.BooleanField()
timeout_happened = models.BooleanField()
#treatment = models.IntegerField() # Geändert?
#Contractingspace
def offer_error_message(self, value):
print('value is', value)
if value > 160:
self.initial = value
return 'Cannot offer more than 160'
if value < 0:
self.initial = value
return 'Cannot offer less than 0'
#def offer_min(self):
# return 0
#def offer_max(self):
#return self.endowment_first_stage + self.endowment_second_stage
# return 200 #Geändert
def run_first_stage(self):
#if self.treatment: #geändert
if self.treatment == 1: #geändert
self.endowment_first_stage = 0
self.endowment_second_stage = self.session.config['endowment']
self.endowment_other = 0#geändert
self.upper_range = self.session.config['endowment']
elif self.treatment == 2: #geändert
self.endowment_first_stage = self.session.config['endowment'] / 2
self.endowment_second_stage = self.session.config['endowment'] / 2 #geändert
self.endowment_other = 0#geändert
self.upper_range = self.session.config['endowment']
elif self.treatment == 3: #geändert
self.endowment_first_stage = 0
self.endowment_second_stage = self.session.config['endowment'] / 2
self.endowment_other = self.session.config['endowment'] / 2#geändert
self.upper_range = self.session.config['endowment'] / 2
else:
self.endowment_first_stage = self.session.config['endowment'] / 2
self.endowment_second_stage = self.session.config['endowment'] / 2 # geändert
self.endowment_other = 0 # geändert
self.upper_range = self.session.config['endowment'] / 2
p1, p2 = self.get_players()
p1.payoff = self.endowment_first_stage
p2.payoff = self.endowment_other # 0
def set_payoffs(self):
p1, p2 = self.get_players()
if self.response:
p1.payoff += self.endowment_second_stage - self.offer
p2.payoff += self.offer
else:
p1.payoff = 0
p2.payoff = 0
@property
def active(self):
return all([p.active for p in self.get_players()])
QUESTIONS = {
'own_payoff': {
'label': f'How many {Constants.points_label} will you earn as bonus?',
'widget': widgets.RadioSelect
},
'stranger_payoff': {
'label': f'How many {Constants.points_label} will the stranger earn as bonus?',
'widget': widgets.RadioSelect
},
'fairoffer': {
'label': 'In your opinion, what would have been a fair offer (please enter the amount)?',
'min': 0,
},
'lowestoffer': {
'label': 'What is the lowest offer that you would have accepted?',
'min': 0,
},
'age': {
'label': 'Which category below includes your age?',
'choices': ['20 or younger',
'21-40',
'41-60',
'61 or older',
],
'widget': widgets.RadioSelect
},
'gender': {
'label': 'What is your gender?',
'choices': ['Female', 'Male', 'Other'],
'widget': widgets.RadioSelect
},
'education': {
'label': 'What is the highest level of school you have completed or the highest degree you have received?',
'choices': ['Less than high school degree',
'High school degree or equivalent',
'College degree or equivalent',
],
'widget': widgets.RadioSelect
},
'student': {
'label': 'Are you currently enrolled in a college / university?',
'choices': ['No',
'Yes',
],
'widget': widgets.RadioSelect
},
'employment': {
'label': 'Which of the following categories best describes your employment status?',
'choices': [
'Part-time employed',
'Full-time employed',
'Unemployed',
],
'widget': widgets.RadioSelect
},
'income': {
'label': 'How much total combined money did all members of your household earn in 2020?',
'choices': [
'$0 – $19,999',
'$20,000 – $39,999',
'$40,000 – $59,999',
'$60,000 or more',
'no reply',
],
'widget': widgets.RadioSelect
},
'region': {
'label': 'Which region do you currently live in?',
'choices': [
'US',
'Rest of the World',
],
'widget': widgets.RadioSelect
},
'batandball': {
'label': '''A bat and a ball cost $1.10 in total.
The bat costs a dollar more than the ball.
How many dollars does the ball cost?''',
'min': 0,
},
'machineswidgets': {
'label': '''If it takes 5 machines 5 minutes to make 5 widgets,
how many minutes would it take 100 machines to make 100 widgets?''',
'min': 0,
},
'lilypads': {
'label': '''In a lake, there is a patch of lily pads.
Every day, the patch doubles in size.
If it takes 48 days for the patch to cover the entire lake, how many days would it take for the patch to cover half of the lake?''',
'min': 0,
},
}
class Player(BasePlayer):
# Game
#time_ok = models.BooleanField()
timeout_happened = models.BooleanField()
@property
def active(self):
return self.participant.vars['active']
@active.setter
def active(self, value):
if not value:
self.payoff = c(0)
self.participant.vars['active'] = value
@property
def role(self):
if self.id_in_group == 1:
return Constants.proposer
else:
return Constants.responder
@property
def stranger(self):
return self.group.get_player_by_id(2 if self.id_in_group == 1 else 1)
def timeout(self):
self.timeout_happened = True
self.group.timeout_happened = True
self.active = False
for p in self.group.get_players():
p.payoff = 0
# Post-Quiz
q_own_payoff = models.IntegerField(**QUESTIONS['own_payoff'])
def q_own_payoff_choices(self):
choices = [
[1, self.payoff],
[0, self.payoff + 10],
[0, self.payoff + 20],
]
random.shuffle(choices)
return choices
q_stranger_payoff = models.IntegerField(**QUESTIONS['stranger_payoff'])
def q_stranger_payoff_choices(self):
choices = [
[1, self.stranger.payoff],
[0, self.stranger.payoff + 10],
[0, self.stranger.payoff + 20],
]
random.shuffle(choices)
return choices
# Demographics
fairoffer = models.IntegerField(**QUESTIONS['fairoffer'])
lowestoffer = models.IntegerField(**QUESTIONS['lowestoffer'])
age = models.StringField(**QUESTIONS['age'])
gender = models.StringField(**QUESTIONS['gender'])
# student = models.StringField(**QUESTIONS['student'])
# education = models.StringField(**QUESTIONS['education'])
# income = models.StringField(**QUESTIONS['income'])
region = models.StringField(**QUESTIONS['region'])
batandball = models.FloatField(**QUESTIONS['batandball'])
machineswidgets = models.IntegerField(**QUESTIONS['machineswidgets'])
lilypads = models.IntegerField(**QUESTIONS['lilypads'])