#1 by yogu
I would like to develop a program that allows the two players to proceed if their answers match, and an error message appears if their answers do not match. To implement this feature, I wrote code with the following strategies: 1. Get the value of the event that a radio button is clicked in Javascript 2. Put the value acquired by Javascript into the current_choice_player1 and current_choice_player2 variables of the Group class 3. When the Next button is pressed, check whether the contents of Group.current_choice_player1 and Group.current_choice_player2 are the same or not, and output an error message if they are different Now my program has the ability to move on if the answers of the two players match. However, I cannot implement the features to display an error message when the answers of two players do not match. When each player selects a different option and clicks "Next," the following error appears: """ Application error (500) TypeError: getattr(): attribute name must be string """ The error seems to be due to "errors = {2: 'Your choice does not match with your partner!'}" statement, but I don't know how to fix it. Here are my python and HTML code. # __init__.py """ from otree.api import * doc = """ Two players have to match their answer to the question. If each player's answer does not match, error message appears. """ class C(BaseConstants): NAME_IN_URL = 'test_question_20230615' PLAYERS_PER_GROUP = 2 NUM_ROUNDS = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): current_choice_player1 = models.StringField() current_choice_player2 = models.StringField() class Player(BasePlayer): question = models.StringField( choices=[['Apple', 'Apple'], ['Banana', 'Banana'], ['Grape', 'Grape']], label='Which fruits do you like?', widget=widgets.RadioSelect ) # PAGES class MyPage(Page): form_model = 'player' form_fields = ['question'] @staticmethod def live_method(player: Player, data): print(data) if player.id_in_group == 1: Group.current_choice_player1 = data elif player.id_in_group == 2: Group.current_choice_player2 = data print(Group.current_choice_player1) print(Group.current_choice_player2) @staticmethod def error_message(player: Player, values): if player.id_in_group == 2: if Group.current_choice_player1 != Group.current_choice_player2: errors = {2: 'Your choice does not match with your partner!'} return errors elif player.id_in_group == 1: if Group.current_choice_player1 != Group.current_choice_player2: errors = {1: 'Your choice does not match with your partner!'} return errors class ResultsWaitPage(WaitPage): pass class Results(Page): pass page_sequence = [MyPage, ResultsWaitPage, Results] """ # MyPage.html """ {{ block title }} Test question {{ endblock }} {{ block scripts }} <script> function checkradiobutton(){ var questions = document.getElementsByName("question"); for(var i = 0; i < questions.length; i++){ if(questions[i].checked){ liveSend(questions[i].value) } } } var ready = false; otree.on_load(function() { ready = true; }); </script> {{ endblock }} {{ block content }} <div class="mb-3 _formfield"> <label class="col-form-label" for="id_question">Which fruits do you like?</label> <div class="controls"> <div id="id_question" required> <div class="form-check"> <input class="form-check-input" type="radio" id="id_question-0" name="question" required value="Apple" onchange="checkradiobutton()"> <label for="id_question-0">Apple</label> </div> <div class="form-check"> <input class="form-check-input" type="radio" id="id_question-1" name="question" required value="Banana" onchange="checkradiobutton()"> <label for="id_question-1">Banana</label> </div> <div class="form-check"> <input class="form-check-input" type="radio" id="id_question-2" name="question" required value="Grape" onchange="checkradiobutton()"> <label for="id_question-2">Grape</label> </div> </div> </div> </div> {{ formfield_errors 'question' }} {{ next_button }} {{ endblock }} """ If anyone has any ideas, even if they are trivial, I would be grateful for any suggestions. Thank you in advance.
#2 by yogu
The code worked by just changing from errors = {2: 'Your choice does not match with your partner!'} to errors = 'Your choice does not match with your partner!'. Thus, the new code is like this: @staticmethod def error_message(player: Player, values): if player.id_in_group == 2: if Group.current_choice_player1 != Group.current_choice_player2: return 'Your choice does not match with your partner!' elif player.id_in_group == 1: if Group.current_choice_player1 != Group.current_choice_player2: return 'Your choice does not match with your partner!'
#3
by
BonnEconLab
Your code indicates that you have only two players per group: PLAYERS_PER_GROUP = 2. Hence, you should be able to do without the conditionals testing player.id_in_group. The following should suffice: @staticmethod def error_message(player: Player, values): if Group.current_choice_player1 != Group.current_choice_player2: return 'Your choice does not match with your partner!'
#4 by yogu (edited )
Dear BonnEconLab Members, Thank you for your suggestion. I finally found that the variable data should be stored in the group class starting with a lowercase letter. @staticmethod def error_message(player: Player, values): group = player.group if group.current_choice_player1 != group.current_choice_player2: return 'Your choice does not match with your partner!'