oTree Forum >

Narrow data format in Otree

#1 by thaicao (edited )

Dear all, 

In my experiment, I want to conduct a multi-armed bandit task where participants can sample values of different distributions by clicking on the respective buttons as long as they want. For each click, I want to record the id of the button and the values generated from the options. However, my code only records the id and value from the last click (see code). Because there is no restriction on the number of samples so I can't create a player field for each sample. Is there any way to have a narrow data format where each row of the dataset record the id and value of a sample/button click? I'm very new at Otree and programming, so I'm very grateful for any suggestions. 

Python code:
class C(BaseConstants):
    NAME_IN_URL = 'Arm5'
    NUM_ROUNDS = 1
    BANDIT_MU = (5.1, 5.2, 5.3)
class Subsession(BaseSubsession):
class Group(BaseGroup):
class Player(BasePlayer):
    value = models.FloatField()
    arm = models.IntegerField()

def custom_export(players):
    yield ['participant_code', 'id_in_group'] 
    for p in players:
        pp = p.participant
        yield [pp.code, p.id_in_group]

class Bandit(Page):
    form_model = 'player'
    def live_method(player: Player, data):        
        import random
        player.arm = data
        mu = C.BANDIT_MU[data]
        player.value = round(random.uniform(mu -5, mu +5),2)
        response = dict(arm = player.arm, value = player.value)
        return {player.id_in_group: response}
    <input id="1" type="button" value ="1" onclick="sendValue(this.id)" > Option 1 </input> 
    <input id="2" type="button" value="2" onclick="sendValue(this.id)" > Option 2 </input>
    <input id="3" type="button" value="3" onclick="sendValue(this.id)" > Option 3 </input>
    <div>Value of option </div> <div id="output"></div>

  // Get a reference to the output element
  const outputElement = document.getElementById("output");

  // send the value of the option being clicked to python code
  function sendValue(clicked){
  // Sending the random value from python to page
  function liveRecv(data){
    outputElement.innerHTML = data.arm + " is " + data.value
  // Hide the new value after 3 seconds
  setTimeout(function() {
    outputElement.innerHTML = "";
  }, 3000)

#2 by thaicao

I found a solution in case anyone has the same problem:
- create a player string field to contain the repeated trials
class Player(BasePlayer):
    seq_value = models.LongStringField(initial= "") # record the sequence of values sampled
    seq_arm = models.LongStringField(initial= "") # record the sequence of arms sampled
- append the new data into the blank string field every time a button is pressed using live_method
class Bandit(Page):
    form_model = 'player'
    def live_method(player: Player, data): 
    player.seq_value += ";" + str(player.value) # append the sampled value to the sequence
       player.seq_arm += ";" + str(player.arm)

Write a reply

Set forum username