Random Treatments

789 views
Skip to first unread message

Irtaza Ali Ajmal

unread,
Mar 8, 2021, 7:48:50 AM3/8/21
to oTree help & discussion
Hello I am new at programming in oTree and I am trying to make a software in oTree which should be able to select 1 treatments out of 48 randomly for each subject.

Can someone tell me how can I do that?

Kind Regards

Rok

unread,
Mar 9, 2021, 10:58:40 AM3/9/21
to oTree help & discussion

Hello,

If you just want to ask each participant a different question and a text input for an answer, then you may only need one page where the question changes. You can do that for example by assigning each participant a StringField variable which contains the question and display it on the page with {{ player.variable_name }}.

If your treatments are only one or two pages but will differ greatly in the interface and the kind of inputs you expect (dropdowns, numbers, texts, buttons): You could make a more complicated template where all those inputs are custom html elements that are hidden by default and then display the question and an appropriate element based on the participant id. Alternatively since you say you’re new to programming you can just make all the different 48 pages and only display the one you want to to the participant with is_displayed() - https://otree.readthedocs.io/en/latest/pages.html#is-displayed

Alternatively, either if you meant treatments as more complex series of pages or actual full treatments, or if you find the following solution better: You could make 48 actual treatments in otree then first have a small ‘intro treatment’ for everyone, where you use the new app_after_this_page() - https://otree.readthedocs.io/en/latest/pages.html?highlight=next#app-after-this-page - to select the appropriate treatment for each participant.

Hope that gives you a few ideas and good luck. :)
Rok

Irtaza Ali Ajmal

unread,
Mar 11, 2021, 11:16:18 AM3/11/21
to oTree help & discussion
Thank you for your help.

I've another question.

I have 3 variables in models.py for those I've created buttons in HTML file.

How can I have access to them in html file, basically there are 3 buttons in html file which are images and I want to record everytime one of the three options is selected.

Attaching a screenshot which might help.

Thank you

Kind Regards

Irtaza

Captura.PNG

Rok

unread,
Mar 11, 2021, 3:09:17 PM3/11/21
to oTree help & discussion
Hello,

this part of the documentation might help:

besides the stuff in the example, you will want to add an onclick function to your buttons, and then make a javascript function that will increase the hidden fields mentioned in the docs (linked above).


don't forget to set the inputs in above example to type="hidden", and their name and id fields to the same name as your 3 variables in Player. Also, don't forget to set your page's form_model and form_fields (form model is Player, and fields are the names of your 3 variables - ex. ['name1', 'name2', 'name3']).

Good luck,
Rok

Irtaza Ali Ajmal

unread,
Mar 12, 2021, 3:48:48 AM3/12/21
to oTree help & discussion
Hello, I've tried this but it doesn't work.

Let me try to explain it better.

I am attaching 4 screenshots.

In 1st screenshot you can see the variables I've declared in models.py.

In 2 screenshot you can see see how I've created buttons in templates in HTML.

In 3 screenshot we you can see the variables are shown in admin monitor. I want them to increase each time one of the 3 buttons is pressed, if 1st is pressed then verde should increase, if 2nd button is pressed then amarillo should increase and same goes for last one.

and in 4th screenshot you can see the user interface.

Hopefully you'll tell me how can I put this,

Kind Regards

Thanks in advance

Irtaza
1.PNG
3.PNG
2.PNG
4.PNG

Rok

unread,
Mar 12, 2021, 6:19:26 AM3/12/21
to oTree help & discussion

Yes, what you want is exactly what I’ve described in the last reply.

Instead of the stuff in your second picture, copy in this:

<button id="close-image" onclick="incrementValue(1)"><img src={% static "treatment1/5.PNG" %}/></button>
<button id="close-image" onclick="incrementValue(2)"><img src={% static "treatment1/6.PNG" %}/></button>
<button id="close-image" onclick="incrementValue(3)"><img src={% static "treatment1/7.PNG" %}/></button>

<input type="hidden" name="verde" id="field_1" value="0"/>
<input type="hidden" name="amarillo" id="field_2" value="0"/>
<input type="hidden" name="rojo" id="field_3" value="0"/>

<script>
function incrementValue(button_number)
{
    // piece together id of the field
    id = 'field_'+button_number;
    // get current value of the field
    var value = parseInt(document.getElementById(id).value, 10);
    // if value is not a number, set it to 0
    value = isNaN(value) ? 0 : value;
    // increase value
    value++;
    // set value to the field
    document.getElementById(id).value = value;
}
</script>

Rok

Rok

unread,
Mar 12, 2021, 6:24:23 AM3/12/21
to oTree help & discussion

Additionally, you’ll need to set your page’s form model and fields (in the page where you're showing your 3 buttons):

class MyPage(Page):
    form_model = 'player'
    form_fields = [' verde', 'amarillo', 'rojo']

Also, your buttons should not have the same id. It will work but id’s are meant to be unique. If you need your buttons to have the same identifier for CSS, use class instead fo id, and change #close-image in yoru CSS to .close-image

Rok

Irtaza Ali Ajmal

unread,
Mar 12, 2021, 7:22:55 AM3/12/21
to oTree help & discussion
Hello Rok, 

I've tried it and I am getting this error on the last page where there are buttons. Attaching you screenshots.


Thank you by the way.
If it's possible for you, can we do this through skype that'd be a lot easier. (Irtaza...@live.com)

Kind Regards

2.PNG
1.PNG
Message has been deleted

Rok

unread,
Mar 12, 2021, 8:14:33 AM3/12/21
to oTree help & discussion

whoops, there’s a space character in the form_fields above. Copy the following over your current form fields.

form_fields = ['verde', 'amarillo', 'rojo']

I’d rather keep helping you on here, in case it helps someone else in the future. :)

Let me know how it goes,
Rok

Irtaza Ali Ajmal

unread,
Mar 12, 2021, 8:15:50 AM3/12/21
to Rok, oTree help & discussion

Yes, Thank you, it’s working now.


Very kind of you and your team.

 

Kind regards

 

Sent from Mail for Windows 10

--
You received this message because you are subscribed to a topic in the Google Groups "oTree help & discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/otree/gWiz_EexLD0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to otree+un...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/otree/b507ec32-f4af-4526-a688-0309db0d4401n%40googlegroups.com.

 

Rok

unread,
Mar 12, 2021, 9:15:08 AM3/12/21
to oTree help & discussion
Glad to be of help. Good luck with your experiment. :)

Rok

Irtaza Ali Ajmal

unread,
Mar 22, 2021, 8:06:19 AM3/22/21
to Rok, oTree help & discussion
Hello Rok, Hope you are doing well.

I've to make few changes in the recent project and was hoping you could help since I am new at this,

So in 1st image I have three buttons, but I want them to be aligned them as in the screenshot number 2.

2nd questions is how can I programme each button that if "Masquefa " is pressed it shows 2 pages
and if "Poetas Anonimos" is pressed I want to show 2 different pages.

Attaching you screenshot and the html code.

HTML CODE BELOW

{% extends "global/Page.html" %}
{% load otree %}
{% load otree static %}

{% block title %}

<div style="text-align: center"> Pantalla 3 </div>

{% endblock %}


{% block content %}

<div style="text-align: center">
<img src={% static "verde/3.1.PNG" %}/>
</div>

<p align="left">
<button id="close-image" onclick="incrementValue(1)"><img src={% static "verde/3.3.PNG" %}/></button>
<button id="close-image" onclick="incrementValue(2)"><img src={% static "verde/3.4.PNG" %}/></button>
<button id="close-image" onclick="incrementValue(3)"><img src={% static "verde/3.5.PNG" %}/></button>
</p>

<input type="hidden" name="masquefa" id="field_1" value="0"/>
<input type="hidden" name="poetas_anonimos" id="field_2" value="0"/>
<input type="hidden" name="avenida_cataluña" id="field_3" value="0"/>

</p>

<br>

</br>

<!-- <div style="text-align: center">
<button class="otree-btn-next btn btn-primary">Continuar</button>
</div> -->


<script>
function incrementValue(button_number)
{
    // piece together id of the field
    id = 'field_'+button_number;
    // get current value of the field
    var value = parseInt(document.getElementById(id).value, 10);
    // if value is not a number, set it to 0
    value = isNaN(value) ? 0 : value;
    // increase value
    value++;
    // set value to the field
    document.getElementById(id).value = value;
}
</script>

{% endblock %}

1.PNG
2.PNG

Rok

unread,
Mar 22, 2021, 9:53:40 AM3/22/21
to oTree help & discussion
Hello,

How are you displaying the content above your buttons? Is it all just one big picture? the {% static "verde/3.1.PNG" %}? If you'd like the buttons overlayed over a picture you could do that but I highly suggest splitting the above content into smaller elements, for example something like this:


I'm not sure I follow on what is supposed to happen when you press the buttons. You would like to show two pages on a button press? Do you mean when you press a button you are redirected to certain otree page sequence, for example, button Masquefa takes you to MyPageOne then from that one to MyPageTwo, but if you press another button, Poetas Anonimos, you will instead continue to MyPageSeven and from that one to MyPageEight?

To achieve the above, you can use is_displayed() on the pages that you want to show to some participants and hide to others. So from the above example, you would put the is_displayed() function in pages MyPageOne, MyPageTwo, MyPageSeven, MyPageEight, and inside the function just check the appropriate player variable, like:

class MyPageOne(Page):
  def is_displayed(player):
    return player.masquefa > 0

(The above just checks if button Masquefa was ever pressed, so MyPageOne will be skipped by all players who never pressed the button Masquefa, etc.. You probably have to make the displayed logic a bit more complex)

Rok

Irtaza Ali Ajmal

unread,
Mar 22, 2021, 10:04:54 AM3/22/21
to Rok, oTree help & discussion

Thank you Rok, I think this might work.

 

I’ll try this and will let you know.

 

“I'm not sure I follow on what is supposed to happen when you press the buttons. You would like to show two pages on a button press? Do you mean when you press a button you are redirected to certain otree page sequence, for example, button Masquefa takes you to MyPageOne then from that one to MyPageTwo, but if you press another button, Poetas Anonimos, you will instead continue to MyPageSeven and from that one to MyPageEight?”

 

This is exactly what I want to do.

 

Each button should show me 2 different pages.

 

For example if I press first button, It should show me 2 different pages.

 

Thank you once again.

 

Kind Regards!

Enviado desde Correo para Windows 10

Irtaza Ali Ajmal

unread,
Mar 22, 2021, 11:21:03 AM3/22/21
to Rok, oTree help & discussion

Hello Rok,

"

To achieve the above, you can use is_displayed() on the pages that you want to show to some participants and hide to others. So from the above example, you would put the is_displayed() function in pages MyPageOne, MyPageTwo, MyPageSeven, MyPageEight, and inside the function just check the appropriate player variable, like:


class MyPageOne(Page):
  def is_displayed(player):
    return player.masquefa > 0

"

I've done this for all three different pages and I am getting this error.

As you can see in 5.png, I've created 3 buttons and then I've created 6 pages in total for these 3 buttons, (2 for each page)

When I click on any button, I get the error. As you can see in 7.png.

Also attaching you a screenshot of code of pages.py


Kindly let me know how to solve it. I am stuck here,


Kind Regards


Irtaza

5.PNG
6.PNG
7.PNG

Rok

unread,
Mar 22, 2021, 1:02:39 PM3/22/21
to oTree help & discussion
Oh you're in the old oTree 3.0...

You need to change the is_displayed function a bit then (changes are bolded):

class MyPageOne(Page):
  def is_displayed(self):
    return self.player.masquefa > 0

The above is assuming that there is a variable in your Player class called masquefa. :)

Rok

Irtaza Ali Ajmal

unread,
Mar 22, 2021, 1:16:33 PM3/22/21
to Rok, oTree help & discussion

from otree.api import Currency as c, currency_range
from ._builtin import Page, WaitPage
from .models import Constants

class Page1(Page):
     pass

class Page2(Page):
    pass
   
class Page3(Page):
    form_model = 'player'
    form_fields = ['masquefa', 'poetas_anonimos', 'avenida_cataluña']
   
class Page4_masquefa(Page):


     def is_displayed(self):
         return self.player.masquefa > 0
      

class Page5_masquefa(Page):
    form_model = 'player'
    form_fields = ['salir', 'ver_datos', 'crear_alerta']
   
class Page4_poetas(Page):
     def is_displayed(self):
        return self.player.poetas_anonimos > 0
   
   
class Page5_poetas(Page):
    form_model = 'player'
    form_fields = ['salir', 'ver_datos', 'crear_alerta']

class Page4_avenida(Page):
    def is_displayed(self):
        return self.player.avenida_cataluña > 0
   
   
class Page5_avenida(Page):
    form_model = 'player'
    form_fields = ['salir', 'ver_datos', 'crear_alerta']
   
class Instrucciones(Page):
    pass
   
class Results(Page):
    pass
   
page_sequence = [
                Page1,
                Page2,
                Page3,
                Page4_masquefa,
                Page5_masquefa,
                Page4_poetas,
                Page5_poetas,
                Page4_avenida,
                Page5_avenida,
                ]

It's not working.

Also attaching you code of models.py

from otree.api import (
    models,
    widgets,
    BaseConstants,
    BaseSubsession,
    BaseGroup,
    BasePlayer,
    Currency as c,
    currency_range,
)

import random

author = 'Irtaza Ali Ajmal'

doc = """
Emivasa Tratamiento 1
"""


class Constants(BaseConstants):
    name_in_url = 'treatment1'
    players_per_group = None
    num_rounds = 1


class Subsession(BaseSubsession):
    pass


class Group(BaseGroup):
    pass


class Player(BasePlayer):
    masquefa = models.IntegerField()
    poetas_anonimos = models.IntegerField()
    avenida_cataluña = models.IntegerField()
       
    salir = models.IntegerField()
    ver_datos = models.IntegerField()
    crear_alerta = models.IntegerField()
   

Rok

unread,
Mar 22, 2021, 2:15:49 PM3/22/21
to oTree help & discussion
Just to make sure, set initial value of your three player variables to 0

class Player(BasePlayer):
    masquefa = models.IntegerField(initial=0)
    poetas_anonimos = models.IntegerField(initial=0)
    avenida_cataluña = models.IntegerField(initial=0)

What is the new error you get?

Rok

Irtaza Ali Ajmal

unread,
Mar 23, 2021, 7:37:27 AM3/23/21
to Rok, oTree help & discussion

Hello Rok,

So I am going to try to explain better.

Basically I have one app which in total has 9 pages. First 2 pages are just introduction where I show the images, then on the 3rd page there are 3 selection buttons which are

  • Masquefa
  • Poetas Anonimos
  • Avenida Cataluña

So here if we select First option one 3rd page"Masquefa" it should just show pages "Page4_masquefa and Page5_masquefa"

and if we select 2nd option "Poetas Anonimos" it should just show pages "Page4_poetas_anonimos and Page5_poetas_anonimos"

And same goes if we select 3rd option "Avenida Cataluña" it should just show pages Page4_avenida_cataluña and Page5_avenida_cataluña"

But here the problem is after I choose the button "Masquefa" on 3rd page, it takes me to "Page4_masquefa" which is correct but then I click on the next button to go to "Page5_masquefa"

The 5th page also has 3 buttons.

  • Salir
  • Ver Datos
  • Crear alerta

By pressing either of the buttons it should take me to next app which is a questionnaire, but unfortunately it's taking me to "Page5_poetas_anonimos" and then by pressing either of the three buttons it's taking me to "Page5_avenida_cataluña" and after that the whole apps ends.

Attaching you code of my pages.py and of modeld.py so you could have a look.

Kind Regards

Irtaza

pages.py
models.py

Rok

unread,
Mar 23, 2021, 9:31:42 AM3/23/21
to oTree help & discussion
Hello,

In your Page5_avenida_cataluña, you check for the wrong variable: return self.player.poetas_anonimos > 0

Your whole app ends after page 5 because you forgot to include your questionaire pages in page_sequence. :)

Here's a fixed models.py. I included debug print statements so you can see the values of variables on every step, for easier debugging if there are further issues. (Writing the print statements is also how I noticed your errors above.)


Best Regards,
Rok

Irtaza Ali Ajmal

unread,
Mar 23, 2021, 10:24:39 AM3/23/21
to Rok, oTree help & discussion

Thank you very much, it’s working now.

 

I just have 2 more doubts and hopefully you can help with them as well.

 

1st doubt:

 

So I am gonna have a button "salir" on some pages (3,4) (as you can see in the screenshots 1 and 2) and the function of this button should be that when it's pressed it should take me to next app.

 

How can I do that?

 

the button "salir" is in app "treatment1" and the next application is "questionarie_full".

 

The purpose of this button is whenever it's pressed, should skip the next pages of the app and take me to the next app directly.

 

2nd doubt:

 

I’ve 3 variables on the 5th page, so I want to record a specific number once either of the buttons is pressed. (Screenshot 3)

 

For example I want to store in the variables:

 

When someone presses the button “crear alerta” I want to store a value of 1

 

When someone presses the button “ver datos” I want to store value 5

 

And finally when someone presses the button “Salir” I want to store value of 10.

 

That’s the only 2 things left to complete my Project.

 

Attaching screenshots.

 

Kind Regards

 

 

 

 

Enviado desde Correo para Windows 10

 

De: Rok
Enviado: martes, 23 de marzo de 2021 14:31
Para: oTree help & discussion
Asunto: Re: [oTree] Re: Random Treatments

 

Hello,

1.PNG
2.PNG
3.PNG

Rok

unread,
Mar 23, 2021, 10:41:51 AM3/23/21
to oTree help & discussion
For your first issue, you can again do it with is_displayed() like we did before but you complicate your return statement a bit (you can use "and" to do things like "return self.player.masquefa > 0 and self.player.skip == 0"), or use app_after_this_page()

Do something like:
<button name="crear_alerta" value=1>crear alerta</button>
<button name="ver_datos" value=5>ver datos</button>
<button name="salir" value=10>salir</button>

Rok

Irtaza Ali Ajmal

unread,
Mar 23, 2021, 10:53:43 AM3/23/21
to Rok, oTree help & discussion

About the second issue, as you told me, it creates 3 new buttons as you’ll see in the screenshot.

 

But stores the values correctly, I want them to be hidden behind the images buttons.

 

Attaching you HTML file so you could take a look.

1.PNG
Page5_masquefa.html

Rok

unread,
Mar 23, 2021, 4:23:23 PM3/23/21
to oTree help & discussion
The html code for the buttons I wrote you previously were just an example, you should edit your existing buttons not just paste new buttons next to the current ones. :)

<button id="close-image" name="salir" value=10><img src={% static "treatment1/Boton6.PNG" %}/></button>
etc...

Rok

Irtaza Ali Ajmal

unread,
Mar 23, 2021, 4:50:12 PM3/23/21
to ot...@googlegroups.com

Dear Rok,

I've tried it how you said for rest of buttons too, but unfortunately it doesn't work.

Attaching a screenshot.

Kindly let me know what I am doing wrong.

Irtaza

2.PNG

Irtaza Ali Ajmal

unread,
Mar 23, 2021, 4:50:38 PM3/23/21
to Rok, oTree help & discussion

Dear Rok,

I've tried it how you said for rest of buttons too, but unfortunately it doesn't work.

Attaching a screenshot.

Kindly let me know what I am doing wrong.

Irtaza
El 23/03/2021 a las 21:23, Rok escribió:
2.PNG

Rok

unread,
Mar 23, 2021, 6:18:03 PM3/23/21
to oTree help & discussion
Try deleting the hidden inputs, this time you only need the buttons.

Rok

Irtaza Ali Ajmal

unread,
Mar 24, 2021, 4:51:32 AM3/24/21
to Rok, oTree help & discussion

If I delete the hidden inputs, I get this error, even though it stores the value of the variable, but doesn't go to next page.


Irtaza

1.PNG
Page5_masquefa.html

Rok

unread,
Mar 24, 2021, 8:30:22 AM3/24/21
to oTree help & discussion
In the first screenshot it is telling you there's an error and it explains how to display it. Knowing the error would usually help. :)

But I'm guessing the problem is that you set the page's form fields to all 3 variables (which is okay), but with the buttons you only submit one value to one of the variables. The remaining variables don't have values and that's (probably) causing the error.

Set your remaining three Player variables to initial=0

Rok

Irtaza Ali Ajmal

unread,
Mar 24, 2021, 8:32:36 AM3/24/21
to Rok, oTree help & discussion

I’ve done it and I still get the same error, I’ve set all these 3 variables models.py to initial = 0.

 

If you want I can attach models.py, pages.py and one of HTML file.

 

Kind Regards

 

Irtaza

Rok

unread,
Mar 24, 2021, 8:42:28 AM3/24/21
to oTree help & discussion
Try setting them to blank=True also, so like models.IntegerField(initial=0, blank=True)

Rok

unread,
Mar 24, 2021, 8:48:46 AM3/24/21
to oTree help & discussion
If it doesnt help, please put {{ form.errors }} somewhere in your page like it is telling you to.

Rok

Irtaza Ali Ajmal

unread,
Mar 24, 2021, 10:20:17 AM3/24/21
to Rok, oTree help & discussion

Thank you once again.

It worked with (blank=True)

Kind Regards

Irtaza Ali

Irtaza Ali Ajmal

unread,
Apr 13, 2021, 6:24:45 AM4/13/21
to Rok, oTree help & discussion

Hello Rok,

 

Hope you are doing well.

 

I’ve some doubts about a payment app.

 

I was hoping maybe you could help.

Reply all
Reply to author
Forward
0 new messages