from otree.api import * import math import pandas as pd import itertools import numpy as np import time class C(BaseConstants): NAME_IN_URL = 'instructions' INSTRUCTIONS_TEMPLATE = 'cpr_instructions/templates/instructions.html' COMPREHENSION_TEMPLATE = 'cpr_instructions/templates/comprehension.html' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 A = 2.3 B = 0.025 LEFT_ATTEMPTS = 5 # A = 0.92 # B = 0.01 class Subsession(BaseSubsession): pass def creating_session(subsession): players = subsession.get_players() for p in players: p.participant.finished_participant = False class Group(BaseGroup): pass class Player(BasePlayer): # group_extraction = models.IntegerField(initial=0) answer5 = models.FloatField( label="5. YOU extracted 2 tokens and the rest extracted 58 tokens. " "Meaning that the GROUP (including you) extracted 60. " "The total group return is 48 ECUs, you will receive:") answer3 = models.FloatField( label="3. YOU extracted 10 tokens and the rest extracted 50 tokens. " "Meaning that the GROUP (including you) extracted 60. " "The total group return is 48 ECUs, you will receive:") answer4 = models.FloatField( label="4. YOU extracted 10 tokens and the rest extracted 30 tokens. " "Meaning that the GROUP (including you) extracted 40. " "The total group return is 52 ECUs, you will receive:") answer1 = models.FloatField( label="1. YOU extracted 15 tokens and the rest extracted 45 tokens. " "How much is the total GROUP extraction (including you)?") answer2 = models.FloatField( label="2. YOU extracted 5 tokens and the total GROUP extraction is 20. " "How much did the rest of group extracted (excluding you)?") attempts = models.IntegerField(initial=5) # FUNCTIONS # PAGES class Instructions(Page): def live_method(player, data): group_extraction = data["focal"] + data["p1"] + data["p2"] + data["p3"] response = dict(focal=data["focal"], group_extraction=group_extraction, payoff_focal=payoff_extraction(data["focal"], group_extraction), payoff_p1=payoff_extraction(data["p1"], group_extraction), payoff_p2=payoff_extraction(data["p2"], group_extraction), payoff_p3=payoff_extraction(data["p3"], group_extraction), ) return {0: response} def payoff_extraction(x, x_total): return round((x / x_total) * ((C.A * x_total) - (C.B * math.pow(x_total, 2))), 2) class Comprehension(Page): form_model = 'player' form_fields = ['answer1', 'answer2', 'answer3', "answer4", "answer5"] @staticmethod def error_message(player, values): if not player.participant.finished_participant: solutions = dict( answer5=1.6, answer3=8, answer4=13, answer1=60, answer2=15 ) error_messages = dict() error_attempt = False for field_name in solutions: if values[field_name] != solutions[field_name]: error_messages[field_name] = 'Wrong answer, please try again' if not error_attempt: player.attempts -= 1 error_attempt = True if player.attempts == 1: player.participant.finished_participant = True player.participant.completion_status = "failed_test" player.participant.reason_finished = "It is important for us that the participants who take part of this experiment know the task well. Since you took more than 5 attempts to answer the comprehension questions, we cannot allow you to continue this experiment. You will still be paid for your time and the previous two tasks." return error_messages @staticmethod def before_next_page(player, timeout_happened): player.participant.wait_page_arrival = time.time() player.participant.group_size_task3 = 4 @staticmethod def app_after_this_page(player, upcoming_apps): if player.participant.finished_participant and player.participant.completion_status == "failed_test": player.participant.payoff_task3 = 0 return "cpr_results" page_sequence = [Instructions, Comprehension]