oTree Forum >

How to check whether the answers of two players match

#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!'

Write a reply

Set forum username