import random
from otree.api import *
doc = """
This is a pilot version of inference-Self in the Failures of Strategic Thinking project.
"""
class C(BaseConstants):
NAME_IN_URL = 'inference'
PLAYERS_PER_GROUP = None
NUM_ROUNDS = 1
MIN_TIME = 7 # in minutes
MAX_TIME = 15 # in minutes
NUMBER_OF_MISTAKES = 1
RATE_OF_MISTAKES = 2
BONUS_PER_CORRECT_TASK_PART1 = cu(0.15)
BONUS_PER_CORRECT_TASK_PART2 = cu(0.25)
OUTSIDE_OPTION = cu(1.5)
NUMBER_OF_TASKS_PART1 = 2
NUMBER_OF_TASKS_PART2 = 10
PART1_TEMPLATE = 'inference/part1.html'
PART2_TEMPLATE = 'inference/part2.html'
BONUS_TEMPLATE = 'inference/bonus.html'
COMPUTER_TYPES = 'inference/computerTypes.html'
REVIEW_INSTRUCTIONS = 'inference/reviewInstructions.html'
class Subsession(BaseSubsession):
pass
class Group(BaseGroup):
pass
class Player(BasePlayer):
cq1 = models.IntegerField(blank=True,
choices=[
[1, 'It does not do anything.'],
[2, 'It solves math tasks that can be easy or hard.'],
[3, 'It decides whether the math tasks are easy or hard.']
],
widget=widgets.RadioSelect,
label='What does the Computer do?'
)
cq2 = models.IntegerField(blank=True,
choices=[
[1, 'Only one, which can be of the Good or the Bad type.'],
[2, 'Two, one of the Good type and one of the Bad type.'],
[3, 'There are many computers.']
],
widget=widgets.RadioSelect,
label='How many Computers are there?'
)
cq3 = models.IntegerField(blank=True,
choices=[
[1, 'Yes, there is only one computer which solves tasks in both part 1 and part 2,'
' but the computer can be of a different type in parts 1 and part 2.'],
[2, 'No, there are two computers, one for each part.'],
[3, 'Yes, there is only one computer which solves tasks in both part 1 and part 2,'
' and the computer can only be of one type throughout the study.']
],
widget=widgets.RadioSelect,
label='Is the Computer that solves tasks in part 1 the same as the one that solves tasks'
' in part 2 of this study?'
)
cq4 = models.IntegerField(blank=True,
choices=[
[1, 'It makes no mistakes in easy or hard tasks.'],
[2, 'It makes ' + str(C.NUMBER_OF_MISTAKES) + ' mistakes every ' +
str(C.RATE_OF_MISTAKES) + ' easy tasks.'],
[3, 'It makes ' + str(C.NUMBER_OF_MISTAKES) + ' mistakes every ' +
str(C.RATE_OF_MISTAKES) + ' hard tasks.']
],
widget=widgets.RadioSelect,
label='How many mistakes does a computer make if it is of the Good type?'
)
cq5 = models.IntegerField(blank=True,
choices=[
[1, 'It makes no mistakes in easy or hard tasks.'],
[2, 'It makes ' + str(C.NUMBER_OF_MISTAKES) + ' mistakes every ' +
str(C.RATE_OF_MISTAKES) + ' easy tasks.'],
[3, 'It makes ' + str(C.NUMBER_OF_MISTAKES) + ' mistakes every ' +
str(C.RATE_OF_MISTAKES) + ' hard tasks.']
],
widget=widgets.RadioSelect,
label='How many mistakes does a computer make if it is of the Bad type?'
)
cq6 = models.IntegerField(blank=True,
choices=[
[1, 'It faces ' + str(C.NUMBER_OF_MISTAKES) + ' easy and ' + str(C.NUMBER_OF_MISTAKES)
+ ' hard tasks, for a total of ' + str(C.NUMBER_OF_MISTAKES*2) + '.'],
[2, 'It has not yet been decided. It is your task to decide it.'],
[3, 'It faces ' + str(C.NUMBER_OF_TASKS_PART1) + ' hard tasks.'],
],
widget=widgets.RadioSelect,
label='In part 1, does the computer face ' + str(C.NUMBER_OF_TASKS_PART1) + ' easy or ' +
str(C.NUMBER_OF_TASKS_PART1) + ' hard tasks?'
)
cq7 = models.IntegerField(blank=True,
choices=[
[1, 'It faces ' + str(C.NUMBER_OF_TASKS_PART2) + ' easy and ' + str(C.NUMBER_OF_TASKS_PART2)
+ ' hard tasks, for a total of ' + str(C.NUMBER_OF_TASKS_PART2 * 2) + '.'],
[2, 'It has not yet been decided. It is your task to decide it.'],
[3, 'It faces ' + str(C.NUMBER_OF_TASKS_PART2) + ' hard tasks.']
],
widget=widgets.RadioSelect,
label='In part 2, does the computer face ' + str(C.NUMBER_OF_TASKS_PART2) + ' easy or ' +
str(C.NUMBER_OF_TASKS_PART2) + ' hard tasks?'
)
cq8 = models.IntegerField(blank=True,
choices=[
[1, 'For each task that the computer solves correctly, you get ' +
str(C.BONUS_PER_CORRECT_TASK_PART1) + '. This applies to both tasks.'],
[2, 'For each task that the computer solves correctly in part 1, you get ' +
str(C.BONUS_PER_CORRECT_TASK_PART1) + '. '
'You can choose your bonus for part 2 to be ' + str(C.BONUS_PER_CORRECT_TASK_PART2)
+ ' for each correctly solved task, or a fixed bonus of ' + str(C.OUTSIDE_OPTION)
+ '.'],
[3, 'For each task that the computer solves correctly, you get ' +
str(C.BONUS_PER_CORRECT_TASK_PART1) + ' in part 1, and ' +
str(C.BONUS_PER_CORRECT_TASK_PART2) + ' in part 2. '
'This applies to both tasks, and you get ' +
str(C.OUTSIDE_OPTION) + ' on top of it.']
],
widget=widgets.RadioSelect,
label='How is your bonus determined?'
)
cq9 = models.IntegerField(blank=True,
choices=[
[1, 'Only one.'],
[2, 'Two decisions.'],
[3, 'I do not have to make any decisions.']
],
widget=widgets.RadioSelect,
label='How many decisions will you make in this study?'
)
mistakes = models.IntegerField(blank=True)
payoffPart2 = models.CurrencyField(blank=True)
taskDifficulty = models.IntegerField(choices=[
[1, 'Easy'],
[2, 'Hard']
],
widget=widgets.RadioSelect,
label='What type of task does the computer face in part 1?',
blank=True)
bonusChoice = models.IntegerField(blank=True,
choices=[
[1, str(C.BONUS_PER_CORRECT_TASK_PART2) + ' for each task the computer '
'solves correctly in this part.'],
[2, str(C.OUTSIDE_OPTION) + ' independently of how many tasks the computer '
'solves in this part.']
],
widget=widgets.RadioSelect,
label='How do we determine your bonus for part 2?')
feedback = models.LongStringField(label=None, blank=True)
feedbackDifficulty = models.IntegerField(label="How difficult were the instructions? Please answer on a scale of 1 "
"to 10 with 10 being the most difficult",
blank=True,
choices=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
widget=widgets.RadioSelectHorizontal)
feedbackUnderstanding = models.IntegerField(label="How well did you understand what you were asked to do?"
" Please answer on a scale of 1 to 10 with 10 being the case when"
" you understood perfectly",
blank=True,
choices=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
widget=widgets.RadioSelectHorizontal)
feedbackSatisfied = models.IntegerField(label="How satisfied are you with this study overall?"
" Please answer on a scale of 1 to 10 with 10 being the most "
"satisfied",
blank=True,
choices=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
widget=widgets.RadioSelectHorizontal)
feedbackPay = models.IntegerField(label="How appropriate do you think the payment for this study is relative to "
"other ones on Prolific? Please answer on a scale of 1 to 10 with 10 being "
"the most appropriate",
blank=True,
choices=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
widget=widgets.RadioSelectHorizontal)
compType = models.FloatField()
explain = models.LongStringField(label='When you chose, did you choose to have the computer face the easy '
'or the hard tasks? Why?',
blank=True)
lottery = models.IntegerField(blank=True,
choices=[
[1, '50% chance of getting ' +
str(C.BONUS_PER_CORRECT_TASK_PART1 * C.NUMBER_OF_TASKS_PART1 *
C.NUMBER_OF_MISTAKES / C.RATE_OF_MISTAKES +
C.OUTSIDE_OPTION) + ' and 50% chance of getting ' +
str(C.BONUS_PER_CORRECT_TASK_PART1 * C.NUMBER_OF_TASKS_PART1 +
C.BONUS_PER_CORRECT_TASK_PART2 * C.NUMBER_OF_TASKS_PART2) + '.'],
[2,
str(C.OUTSIDE_OPTION + C.BONUS_PER_CORRECT_TASK_PART1 * C.NUMBER_OF_TASKS_PART1)
+ ' for sure.']
],
widget=widgets.RadioSelect,
label='Given the chance, please choose which of the options below you would'
' prefer to receive:')
advice = models.IntegerField(blank=True,
choices=[
[1, 'Advice that the Computer faces easy tasks.'],
[2, 'Advice that the Computer faces hard tasks.']
],
widget=widgets.RadioSelect,
label='If you could advice another participant on their decision of whether '
'the computer faces easy or hard tasks, which would you advise them to choose?'
'')
for j in range(1, 10):
locals()['cq' + str(j) + '_mistakes'] = models.IntegerField(blank=True, initial=0)
del j
# FUNCTIONS
# PAGES
class Welcome(Page):
pass
class Consent(Page):
pass
class Instructions(Page):
pass
class Instructions1(Page):
pass
class CQ(Page):
form_model = 'player'
form_fields = ['cq1', 'cq2', 'cq3', 'cq4', 'cq5', 'cq6', 'cq7', 'cq8', 'cq9']
@staticmethod
def error_message(player, values):
if not player.session.config['development']:
solutions = dict(
cq1=2,
cq2=1,
cq3=3,
cq4=1,
cq5=3,
cq6=2,
cq7=3,
cq8=2,
cq9=2
)
error_messages = dict()
for field_name in solutions:
if values[field_name] is None:
error_messages[field_name] = 'Please, answer the question.'
elif values[field_name] != solutions[field_name]:
error_messages[field_name] = 'Please, correct your answers!'
name = 'player.' + str(field_name) + '_mistakes'
exec("%s += 1" % name)
return error_messages
class Instructions2(Page):
pass
class EnvironmentStage(Page):
form_model = 'player'
form_fields = ['taskDifficulty']
@staticmethod
def error_message(player, values):
if not player.session.config['development'] and values['taskDifficulty'] is None:
return 'Please, answer the question.'
@staticmethod
def before_next_page(player, timeout_happened):
taskDifficultyMaybeNone = player.field_maybe_none('taskDifficulty')
if player.session.config['development'] and taskDifficultyMaybeNone is None:
player.taskDifficulty = 1
class PostDifficultyChoice(Page):
@staticmethod
def before_next_page(player, timeout_happened):
player.compType = random.choice([0, 1])
# print('compType:', player.compType, 'TaskDifficulty:', player.taskDifficulty)
if player.taskDifficulty == 1:
player.mistakes = 0
else:
if player.compType < 0.5:
# print('MISTAKES')
player.mistakes = int(C.NUMBER_OF_MISTAKES*C.NUMBER_OF_TASKS_PART1/C.RATE_OF_MISTAKES)
else:
player.mistakes = 0
player.payoff = C.BONUS_PER_CORRECT_TASK_PART1 * (C.NUMBER_OF_TASKS_PART1 - player.mistakes)
class ObserveMistakes(Page):
pass
class BonusChoice(Page):
form_model = 'player'
form_fields = ['bonusChoice']
@staticmethod
def before_next_page(player, timeout_happened):
if player.bonusChoice == 1:
if player.compType < 0.5:
player.mistakes = int(C.NUMBER_OF_MISTAKES*C.NUMBER_OF_TASKS_PART2/C.RATE_OF_MISTAKES)
else:
player.mistakes = 0
player.payoffPart2 = C.BONUS_PER_CORRECT_TASK_PART2 * (C.NUMBER_OF_TASKS_PART2 - player.mistakes)
else:
player.payoffPart2 = C.OUTSIDE_OPTION
player.payoff += player.payoffPart2
@staticmethod
def error_message(player, values):
if not player.session.config['development'] and values['bonusChoice'] is None:
return 'Please, answer the question.'
class PostBonusChoice(Page):
@staticmethod
def vars_for_template(player):
return dict(
payoffPart2=player.payoffPart2
)
class Hypothetical(Page):
form_model = 'player'
form_fields = ['advice', 'lottery', 'explain']
@staticmethod
def error_message(player, values):
if not player.session.config['development'] and (values['lottery'] is None or values['advice'] is None or not
values['explain']):
return 'Please, answer the questions.'
class End(Page):
form_model = 'player'
form_fields = ['feedback', 'feedbackDifficulty', 'feedbackUnderstanding', 'feedbackSatisfied', 'feedbackPay']
@staticmethod
def before_next_page(player, timeout_happened):
player.participant.finished = True
class Redirect(Page):
pass
page_sequence = [
Welcome,
Consent,
Instructions,
Instructions1,
CQ,
Instructions2,
EnvironmentStage,
PostDifficultyChoice,
ObserveMistakes,
BonusChoice,
PostBonusChoice,
Hypothetical,
End,
Redirect
]