Search code examples
pythonotree

Python: Simple Counter in Otree


I am trying to implement a simple score counter in Otree (Python Library) by modifying the quiz game template to make it two players.

Eventually, I want this counter to update only on certain conditions, but for now, I'm just trying to add 10 after every round.

In models.py, I have defined a player class like so:

class Player(BasePlayer):

    question_id = models.IntegerField()
    confidence = models.FloatField(widget=widgets.Slider(attrs={'step': '0.01'}))

    question = models.StringField()
    solution = models.StringField()
    submitted_answer = models.StringField(widget=widgets.RadioSelect)
    is_correct = models.BooleanField()
    total_score = models.IntegerField(initial = 0)

    def other_player(self):
        return self.get_others_in_group()[0]

    def current_question(self):
        return self.session.vars['questions'][self.round_number - 1]

    def check_correct(self):
        self.is_correct = self.submitted_answer == self.solution

    def check_if_awarded_points(self):
        self.get_others_in_group()[0].submitted_answer == self.submitted_answer == self.solution

    def score_points(self):
        self.total_score+=10
        self.payoff += c(10)

The only relevant function above is "score points" which I call in the pages.py template like so:

class ResultsWaitPage(WaitPage):
    def after_all_players_arrive(self):
        for p in self.group.get_players():
            p.score_points()

I then create a results page which shows me the results of the quiz after each question in order to test that either "total_score' or "pay-offs" is increasing by 10 each question.

class IntermediateResults(Page):

    def vars_for_template(self):
        return {
            'total_score': [p.total_score for p in self.group.get_players()],
            'total_payoff': [p.payoff for p in self.group.get_players()]

        }

If I expose the values of total_payoff and total_score using Django, I see that their value is 10, and it never changes. I don't know why this is the case. Any thoughts?


Solution

  • if you modify the standard quiz game which is the part of oTree package (here), then you can see that it is multi-round game, where each set of questions is in a separate round.

    In oTree each round has its own set of players (belonging to one participant). Which means that your code works ok, but you just get the information about the current round (where indeed their total score is 10. What you need instead is to obtain the scores and payoffs from previous rounds, not only the current one.

    Something like that should work:

    class IntermediateResults(Page):
    
      def vars_for_template(self):
        allplayers = self.group.get_players()
        total_score = sum([sum([p.total_score for p in pp.in_all_rounds()]) for pp in allplayers])
        total_payoff = sum([sum([p.payoff for p in pp.in_all_rounds()]) for pp in allplayers])
        return {
            'total_score': total_score,
            'total_payoff': total_payoff,
    
        } 
    

    Although I should note that what you get in total_score is a sum of all scores of both players so far - I am not sure under what conditions somebody needs this information, but I do not know your specific design.