if condition doesn't work but else condition works

106 views Asked by At

When I run the following code in a python console, it works as expected. However, when I run it in oree, only the else condition is taken into consideration. So even if the conditions are fulfilled, I only get results with the values 3.85 and 0.1 (and not 2 or 1.6).

for k in range(1,11):
    locals()['choice' + str(k)] = random.randint(0,1)
    locals()['resultHL' + str(k)] = []
win = []

for i in range(1, 11):
    choice = 0
    exec(f'choice+=choice{i}')
    rnum = random.random()
    probability = i / 10
    if rnum <= probability:
        win.append(1)
        if choice == 1:
            exec(f'resultHL{i} = 2')
        else:
            exec(f'resultHL{i} = 3.85')
    else:
        win.append(0)
        if choice == 1:
            exec(f'resultHL{i} = 1.6')
        else:
            exec(f'resultHL{i} = 0.1')

I have to make the variables a particular way because of the syntax in oTree.

class Player(BasePlayer):
    number_entered = models.FloatField(min=0, max=100)
    result_risk = models.FloatField()
    win_risk = models.BooleanField()
    for k in range(1,11):
        locals()['choice' + str(k)] = make_booleanfield()
        locals()['probHL' + str(k)] = models.FloatField()
        locals()['winHL' + str (k)] = models.BooleanField()
        locals()['resultHL' + str(k)] = models.FloatField()
    del k

def make_booleanfield():
    return models.BooleanField(
        choices=[[True,'A'],[False,'B'],],
        widget=widgets.RadioSelectHorizontal,
    )


class ResultsHL(Page):
    @staticmethod
    def vars_for_template(player: Player):
        for i in range(1, 11):
            choice = 0
            exec(f'choice+=player.choice{i}')
            rnum = random.random()
            probability = i / 10
            exec(f'player.probHL{i}=probability')
            if rnum <= probability:
                exec(f'player.winHL{i}=1')
                if choice == 1:
                    exec(f'player.resultHL{i} = C.A_win')
                else:
                    exec(f'player.resultHL{i} = C.B_win')
            else:
                exec(f'player.winHL{i}=0')
                if choice == 1:
                    exec(f'player.resultHL{i} = C.A_lose')
                else:
                    exec(f'player.resultHL{i} = C.B_lose')
1

There are 1 answers

0
Samwise On

The locals()/exec() stuff probably has a scoping bug -- rather than trying to debug it, I suggest just using dicts or lists. Here's an example using three lists instead of 20 ints and one list, with a stub Player class to sort of mimic your use case:

import random

class Player:
    def __init__(self):
        self.result = 0.0


choices = [random.randint(0, 1) for _ in range(10)]
players = [Player() for _ in range(10)]
wins = [int(random.random() <= i / 10) for i in range(1, 11)]

for player, choice, win in zip(players, choices, wins):
    if win:
        if choice:
            player.result = 2
        else:
            player.result = 3.85
    else:
        if choice:
            player.result = 1.6
        else:
            player.result = 0.1


print([player.result for player in players])

prints (e.g.):

[1.6, 0.1, 1.6, 0.1, 1.6, 0.1, 2, 3.85, 0.1, 2]

I might also suggest trimming down the if/else stuff by using a table:

results = (
    (2.00, 3.85),  # win
    (1.60, 0.10),  # loss
)

for player, choice, win in zip(players, choices, wins):
    player.result = results[win][choice]