0

I’m working with OTree with self: https://otree.readthedocs.io/en/self/

On the first page of my experiment, I ask the players to provide an access code / their matriculation number via StringField. If their input is not in my dict in Constants, I want to send them directly to a page where I tell them „Sorry, you can’t participate“ with the only option for them to click the next button and exit the experiment.

I have tried the following:

in models.py

class Constants(BaseConstants):
    name_in_url = 'prisoners_test1'
    players_per_group = 2
    num_rounds = 1
  
    matriculation_dict = {
            '123': ('Adam Smith', 'Economics'),
            '124': ('Ada Lovelace', 'Programming'),
            '125': ('Charles Babbage', 'Mathematics'),
        }

class Player(BasePlayer):
    matriculation = models.StringField(label='Please provide your Matriculation Number')

    access = models.BooleanField()
    def matriculation_not_found(self):
         if self.matriculation in Constants.matriculation_dict:
             self.access = True
         else: self.access = False

in pages.py

class ExcludedPlayer(Page):
    def is_displayed(self):
        return self.player.access == False

page_sequence = [Matriculation, ExcludedPlayer, P1_Decision, P2_Decision, ResultsWaitPage, Results]

The problem is that the value of access is not updated through my if statement.

My second problem is that even if the page ExcludedPlayer is displayed (b/c I set initial value of access = False), the player is directed to the other pages (P1_Decision, ResultsWaitPage, Results) after clicking next. How can I end the game for the excluded player?

Thank you for your help!

Julian
  • 9
  • 3

1 Answers1

2

To your first problem:

To update the access field, you need to call your matriculation_not_found method somewhere. A good place for this is the otree built-in method before_next_page in your Matriculation class:

class Matriculation(Page):

    def before_next_page(self):
        self.player.matriculation_not_found()

Or in newer otree versions (no-self format):

class Matriculation(Page):

    @staticmethod
    def before_next_page(player, timeout_happened):
        player.matriculation_not_found()

To your second problem:

The easiest way to prevent the excluded players from seeing the upcoming pages is to remove the next-button. Simply delete the following line from the ExcludedPlayer.html template:

{{ next_button }}

If for some reason you don't want that, you can also check on each of the upcoming pages in the is_displayed method whether access is allowed or not. For example for the P1_Decision page:

class P1_Decision(Page):
    
    def is_displayed(self):
        return self.player.access

And again the same in the new no-self format:

class P1_Decision(Page):
    
    @staticmethod
    def is_displayed(player):
        return player.access

Another alternative would be to swap out the ExcludedPlayers page to a later app (let's call it 'exculuded_players_app') and skip the pages (and apps) in between using the app_after_this_page method:

class Matriculation(Page):

    def before_next_page(self):
        self.player.matriculation_not_found()

    def app_after_this_page(self, upcoming_apps):
        if not self.player.access:
            return 'exculuded_players_app'

And again the same in the new no-self format:

class Matriculation(Page):

    @staticmethod
    def before_next_page(player, timeout_happened):
        player.matriculation_not_found()
    
    @staticmethod
    def app_after_this_page(player, upcoming_apps):
        if not player.access:
            return 'exculuded_players_app'
davidlucius
  • 206
  • 2
  • 4