oTree Forum >

Record information on waiting page

#1 by Xinxin ,

I am trying to record subjects' behaviors on the waiting page, for example: how many times they use the provided calculator to test different cases. 

I tried to use a hidden input form field but realize that the changed value is not submitted. Is there a good way to record this additional information on the waiting page? Would using a personalized waiting page help? 

Thanks for any help or suggestion in advance.

#2 by Xinxin ,

If it helps, here is my code (which worked fine for "normal" pages: 
Page:
            <input type="hidden" name="calculatorHistory9" value="," id="id_calculatorHistory"/>


    <script>
    
    var select = document.getElementById('id_calculatorHistory'),
    input = document.getElementById('calculatorHistory9');

    select.addEventListener('change', function(){
        input.value = select.value;
        document.getElementById('form').submit();
    });
    
    </script>

#3 by Chris_oTree

Take a look in the featured snippets here on oTree Hub. There is an app called wait_page_from_scratch. This is a regular Page that behaves like a wait page. You can add form fields etc to this page.

#4 by Xinxin ,

Hi Chris,

A follow-up question: I think the wait_page_from_scratch can only be used once. If I want to implement multiple wait pages in one app, is there a way to reset the group level variables wait_for_ids and arrived_ids? 

Also, how to use this page to achieve a function similar to after_all_players_arrive on this customized page? 

Currently, I am using the function to achieve what used to be after_all_players_arrive  = check_club_formed. Just want to make sure that I am using it correctly.
    @staticmethod
    def before_next_page(player: Player, timeout_happened):
        if player.id_in_subsession ==1 :
            group = player.group
            group = check_club_formed(group)
Thanks,
Xinxin

#5 by Chris_oTree ,

Yes that will only work once per round. So the first thing to check is if you can split the game into multiple rounds. If not, then you can easily define multiple fields like:

class Group(BaseGroup):
    wait_for_ids1 = models.LongStringField(initial='[]')
    arrived_ids1 = models.LongStringField(initial='[]')

    wait_for_ids2 = models.LongStringField(initial='[]')
    arrived_ids2 = models.LongStringField(initial='[]')

And make the live method check the correct field depending on how many wait pages you have passed.

As for after_all_players_arrive, I recommend setting a group field like:

did_aapa = models.BooleanField(initial=False)

("aapa" is just an abbreviation for after_all_players_arrive)

Then you can run check_club_formed either in the live method (before sending finished=True), or in before_next_page, e.g.:

if not group.did_aapa:
    check_club_formed(group)
    group.did_aapa = True
    
This will ensure it is only run once. I don't recommend basing it on player.id_in_group or player.id_in_subsession, because there is no guarantee that Player 1 will proceed to the next page before the others. You should ensure that the function ran before any player is able to load the following page.

#6 by Xinxin ,

It seems that if I clear the two variables wait_for_ids and arrived_ids, the wait page can be re-used. 

def ClearWaitPageHistory(group: Group):
    group.wait_for_ids = '[]'
    group.arrived_ids = '[]'


I wonder whether I can put this function after check_club_formed
if not group.did_aapa:
    check_club_formed(group)
    ClearWaitPageHistory(group)
    group.did_aapa = True
    
Is there a potential issue for this method?

#7 by Chris_oTree ,

That might work if you're careful, but it's more foolproof to use differently named fields.

#8 by Chris_oTree ,

And by the way you will need did_aapa1, did_aapa2, etc...

#9 by Xinxin ,

Thanks a lot for the replies. Now it works properly, but I notice that the form is still not submitted. 

I created a scratch wait page and was able to specify the form fields, but it doesn't submit the contents. I used a hidden input element to store the information. 

html: 
        <input type="hidden" id='button_history' name="button_c_w" />


class ScratchWaitPage(Page):
    form_model = 'player'
    form_fields = ['button_c_w'] 
    
Wonder whether I should add anything else in Javascript (maybe).

#10 by Chris_oTree ,

Try with a regular input first (not hidden). Maybe the JavaScript code that sets that hidden input is not working.

#11 by Xinxin ,

hmmm, I don't think it works.

#12 by Xinxin ,

Turns out that the reason my form is not submitted is that my approach doesn't work:

if not group.did_aapa:
    check_club_formed(group)
    ClearWaitPageHistory(group)
    group.did_aapa = True

When I clear the wait page history, some players haven't submitted their wait page, the clearHistory() will prevent them from submitting their wait page. What Chris suggested before works better, by creating 

class Group(BaseGroup):
    wait_for_ids1 = models.LongStringField(initial='[]')
    arrived_ids1 = models.LongStringField(initial='[]')

    wait_for_ids2 = models.LongStringField(initial='[]')
    arrived_ids2 = models.LongStringField(initial='[]')
    
And carefully makes changes in the relevant functions. 

Just a book-keeping in case anyone run into a similar situation and avoid some lessons.

#13 by Xinxin ,

Hi Chris,

One more question related to the customized wait page: how could I write the test.py for a customized wait page? 

Although the tutorial says that when writing a robot, ignore the wait page. My program seems to be stuck on the wait page. I am not sure what is the best way to continue the robots.

Thanks in advance.

Best,
Xinxin

#14 by Chris_oTree ,

That is not a wait page. It is a regular page you made to behave roughly like a wait page. Anyway you might need to use call_live_method.

#15 by Xinxin ,

Thanks for the reply. I was not able to figure out how to write this call_live_method properly on a customized wait page. Is it possible to show me how to bypass the scratch_wait_page by using the call_live_method as a showcase? 

Here is my attempt: 

def call_live_method(method, **kwargs):
    method(0, {'type': 'wait_page'})
    
    
yield  Submission(scratch_wait_page ,check_html=False)     

It doesn't seem to work and the keyError is 0.

#16 by Xinxin ,

Kindly follow up with the above request.

Write a reply

Set forum username