from otree.api import *
c = Currency
doc = """
Your app description
"""
class C(BaseConstants):
NAME_IN_URL = '_Task'
PLAYERS_PER_GROUP = None
NUM_ROUNDS = 100
PAYROWS = 1
class Subsession(BaseSubsession):
pass
class Group(BaseGroup):
pass
class Player(BasePlayer):
# saves number of rows
num_payrows = models.IntegerField(
label='Please select how many sequences you want to count in the next task:',
initial=0,
choices=[6, 9, 12],
widget=widgets.RadioSelect,
blank=True,
)
num_payrows_assign = models.IntegerField(
label="Please select how many digits (of '0' and '1') each sequence will contain in the next task:",
initial=0,
choices=[9, 14, 18],
widget=widgets.RadioSelect,
blank=True,
)
Row_1 = models.IntegerField(min=0, max=18, label='', blank=True)
Easy_Rows = models.IntegerField(initial=0)
Difficult_Rows = models.IntegerField(initial=0)
Sum_Easy_Rows = models.IntegerField(initial=0)
Sum_Difficult_Rows = models.IntegerField(initial=0)
StartTime = models.FloatField(initial=0)
EndTime = models.IntegerField(initial=0)
TaskTime = models.FloatField(initial=0)
correct_answers = models.IntegerField(initial=0)
answer = models.IntegerField()
num_answers = models.IntegerField(initial=0)
num_payrounds = models.IntegerField(initial=0)
difficulty = models.IntegerField()
def Task_difficulty(player: Player):
participant = player.participant
if player.round_number == 1:
player.difficulty = 18
player.Difficult_Rows = 1
return 18
else:
# Sum_Easy_Rows = 0
# Sum_Difficult_Rows = 0
payrows = participant.NumPayrows
previous_players = player.in_previous_rounds()
Sum_Easy_Rows = sum([p.Easy_Rows for p in previous_players])
Sum_Difficult_Rows = sum([p.Difficult_Rows for p in previous_players])
# for temp_player in previous_players:
# Sum_Easy_Rows += temp_player.Easy_Rows
# Sum_Difficult_Rows += temp_player.Difficult_Rows
if player.round_number == participant.PayRounds:
if Sum_Difficult_Rows > Sum_Easy_Rows:
player.Easy_Rows = 1
player.difficulty = 9
return 9
else:
player.Difficult_Rows = 1
player.difficulty = 18
return 18
else:
prev_player = player.in_round(participant.PayRounds - payrows)
player.difficulty = prev_player.difficulty
if player.difficulty == 18:
player.Difficult_Rows = 1
else:
player.Easy_Rows = 1
return prev_player.difficulty
def create_task(seed, player: Player):
import random
random.seed(seed + (player.round_number*7))
# Generate a list of random integers between 0 and 1 - 9 Numbers
random_numbers = [random.randint(0, 1) for _ in range(Task_difficulty(player))]
# Convert the list of integers to a string
numbers_string = ''.join(map(str, random_numbers))
# Count the number of times '1' appears in the string
solution = numbers_string.count('1')
return numbers_string, solution
# Global definition of Timer
def get_timeout_seconds(player):
participant = player.participant
return participant.expiry - participant.pagetime
def Row_1_error_message(player, value):
if value is None:
return 'Field must be filled!'
def num_payrows_error_message(player, value):
if player.participant.treatment == 'SelfSelection' and value == 0:
return 'Field must be filled!'
def num_payrows_assign_error_message(player, value):
if player.round_number > 1 and value == 0 and player.participant.treatment != 'SelfSelection':
return 'Field must be filled!'
class TaskRow:
task = ''
formfield = ''
index = ''
def __init__(self, task, formfield, index):
self.task = task
self.formfield = formfield
self.index = index
# PAGES
class Introduction(Page):
# Show page only in the first round
@staticmethod
def is_displayed(player):
return player.round_number == 1
@staticmethod
def before_next_page(player, timeout_happened):
participant = player.participant
participant.expiry = 5 * 60
participant.pagetime = 0
def vars_for_template(player):
return {
'treatment': player.participant.treatment,
}
class Explanation(Page):
form_model = 'player'
form_fields = ['num_payrows', 'num_payrows_assign']
def vars_for_template(player):
participant = player.participant
if player.round_number > 1:
num_payrows_prev = participant.NumPayrows
else:
num_payrows_prev = 1
if participant.treatment != 'SelfSelection':
import random
Payrows = [6, 9, 12]
player.num_payrows = random.choice(Payrows)
difficulty = Task_difficulty(player)
if difficulty == 18:
return {'Task_Difficulty': 'a difficult task (with long sequences)',
'display_finished_tasks': player.round_number > 1,
'num_payrows_prev': num_payrows_prev,
'num_payrows': player.num_payrows,
'treatment': participant.treatment,
}
else:
return {'Task_Difficulty': 'an easy task (with short sequences)',
'display_finished_tasks': player.round_number > 1,
'num_payrows_prev': num_payrows_prev,
'num_payrows': player.num_payrows,
'treatment': participant.treatment,
}
def is_displayed(player):
if player.round_number > 1:
return player.round_number == player.participant.PayRounds and get_timeout_seconds(player) > 3
else:
return get_timeout_seconds(player) > 3
def before_next_page(player, timeout_happened):
participant = player.participant
participant.PayRounds = player.round_number + player.num_payrows
participant.NumPayrows = player.num_payrows
class Task(Page):
form_model = 'player'
form_fields =['Row_1']
# End the task by Closing the Page if less than 3 seconds before timeout
@staticmethod
def is_displayed(player):
return get_timeout_seconds(player) > 3
timer_text = 'Time left for all tasks:'
# Only necessary to visualize the timer in template
def get_timeout_seconds(player):
participant = player.participant
return participant.expiry - participant.pagetime
def vars_for_template(player: Player):
tasks = []
solutions = []
import time
player.StartTime = int(time.time())
participant = player.participant
for row in range(1):
task, solution = create_task(row, player)
tasks.append(TaskRow(task, 'Row_%s'%int(row+1), row+1))
solutions.append(solution)
CurrentRow = 1 + participant.NumPayrows + player.round_number - participant.PayRounds
participant.solution = solutions
return (dict(tasks=tasks,
formstrings=['Row_%s' % i for i in range(1, C.PAYROWS + 1)],
num_payrows=participant.NumPayrows,
CurrentRow=CurrentRow,
treatment=participant.treatment))
# check correct answers each round by comparing rows and solutions
def before_next_page(player: Player, timeout_happened):
participant = player.participant
if player.Row_1 == participant.solution[0]:
player.correct_answers = 1
if player.Row_1 is not None:
player.answer = 1
import time
player.EndTime = int(time.time())
SumPagetimeRoundOne = player.EndTime - player.StartTime
player.TaskTime = SumPagetimeRoundOne
previous_players = player.in_previous_rounds()
SumCurrentPagetime = SumPagetimeRoundOne
for temp_player in previous_players:
SumCurrentPagetime += temp_player.EndTime - temp_player.StartTime
participant.pagetime = SumCurrentPagetime
combined_correct_task = player.correct_answers
num_answers = player.answer
for temp_player in previous_players:
combined_correct_task += temp_player.correct_answers
num_answers += temp_player.answer
participant.combined_correct_task = combined_correct_task
participant.total_answers = num_answers
class ThankYou(Page):
# Show page after the last round
@staticmethod
def is_displayed(player: Player):
return player.round_number == C.NUM_ROUNDS
def before_next_page(player: Player, timeout_happened):
participant = player.participant
player_all_rounds = player.in_all_rounds()
participant.avg_TaskTime = sum([p.TaskTime for p in player_all_rounds]) / participant.total_answers
player.Sum_Easy_Rows = sum([p.Easy_Rows for p in player_all_rounds])
player.Sum_Difficult_Rows = sum([p.Difficult_Rows for p in player_all_rounds])
class CombinedResults(Page):
pass
class ResultsWaitPage(WaitPage):
pass
class Results(Page):
pass
page_sequence = [Introduction, Explanation, Task, ThankYou]