in_round() function in oTree - django

Consider a game with 3 rounds. In every round the player makes a choice (stored in the variable choice).
Now, in the 3rd round I want to call someFunction and thereby access the choice made in the 2nd round.
Unfortunately someFunction returns None. I do not understand why. If I place the function call in a template file, everything works out fine.
Help would be appriciated - I ve been searching for hours.
class Subsession(BaseSubsession):
def before_session_starts(self):
if self.round_number == 3:
for player in self.get_players():
player.participant.vars['someKey'] = player.someFunction()
class Player(BasePlayer):
choice = models.CharField(initial=None,
choices=['A','B','C'],
widget=widgets.RadioSelect())
def someFunction(self):
return self.in_round(2).choice
Why is this happening?

the before_session_starts function is executed before the session starts (hence its name). Thus, when it is executed the player has not done his/her choice yet. That is why someFunction returns None.
You can set player.participant.vars['someKey'] = self.player.choice in the end of 2nd round, which will give you result you are looking for.
class Choice(Page):
def before_next_page(self):
if self.player.round_number == 2:
player.participant.vars['someKey'] = self.player.choice

Related

Assign nested function to variable with parameter

disclaimer: My title may not be accurate as far as what I would like to accomplish, but I can update if someone can correct my terminology
I have 2 functions, each with a separate purpose and usable on its own, but occasionally I would like to combine the two to perform both actions at once and return a single result, and to do this I would like to assign to a variable name
I know I can create a 3rd function that does basically what I want as it is really simple.. though it's become a bit of a challenge to myself to find a way of doing this
def str2bool(string):
return string.lower() in ("yes", "true", "t", "1")
def get_setting(string):
if string == 'cat':
return 'yes'
else:
return 'no'
VALID_BOOL = str2bool(get_setting)
print VALID_BOOL('cat')
So basically I would like to assign the combination of the 2 functions to a variable that I can call and pass in the string parameter to evaluate
In my real world code, get_setting() would retrieve a user setting and return the value, I would then like to test that value and return it as a boolean
Again I know I can just create a 3rd function that would get the value and do the quick test.. but this is more for learning to see if it can be done as I'm trying to do.. and so far my different variations of assigning and calling aren't working, is it even possible or would it turn too complex?
Using lambda is easy, but i don't know if it is exactly what you are looking for.
Example:
f = lambda astring : str2bool(get_setting(astring))
Outputs:
>>> f('cat')
True

Is there a way to choose a random constructor to use in python?

Is there any way to choose a random one of my constructors to use? I have a pretty in depth code, but wrote up a silly one below just to make it as simple as possible.
class Engine(object):
def __init__(self, scenario, fart, shart):
self.scenario = scenario
self.fart = fart
self.shart = shart
self.outcomes = [fart,shart]
def giveScenario(self):
print self.scenario
def chooseOutcome(self):
outcome = random.choice(self.outcomes)
print outcome
dinner = Engine('You are at dinner','You fart','You shart')
home = Engine('You are at home','You fart','You shart')
Now let's say I was going to make a game where it chooses a random one of these two constructors (either the dinner or home one) to load into this bad boy, is there any way to do that?
Edit: To be clear, I know how to choose a random outcome, i am wondering how I can get this program to run and choose ONLY dinner or ONLY home to run.
[randomly chosen operator].chooseOutcome()
Would return either
"You are at dinner" / "You are at home" and the given outcome
Unless I've completely misunderstood what you're asking, this is pretty easy:
dinner = Engine('You are at dinner','You fart','You shart')
home = Engine('You are at home','You fart','You shart')
random.choice([dinner, home]).chooseOutcome()
or, if you only need this once and want to avoid unnecessary instantiations:
Engine(
random.choice(['You are at dinner', 'You are at home']),
'You fart',
'You shart',
).chooseOutcome()
If you need to call several operations on the same randomly chosen Engine, just store the result of random.choice([dinner, home]) or of Engine(random.choice(['You are at dinner', 'You are at home']), 'You fart','You shart'), respectively.

Any ideas for why two side by side print statements in python would not execute?

I have a class defined as this:
class decider(object):
def __init__(self, brain):
self.brain = brain
##stuff
## brain is an object
In a class function I have two print statements, right next to each other, like so:
def somefunction(self, someParam):
print "Something First"
print "Another something: " + self.brain.aVariable + ", " + self.brain.anotherVariable
# more stuff
# execution continues as normal
# the object called in brain exists (ive checked)
In another function (in the same class) I call this function.The first print statement is printing, the second one is not. No exceptions are raised and the code just skips that line. No crashes either. I find this pretty bizarre and had not happened to me until now. Is there a reason for why this could possibly be happening?
If it matters, I'm running python 2.7 on an embedded system with an ATOM Z530 processor.
Could be buffered? Does anything print after the second call?
Add another print after the second call to force to clear the buffer

TypeError: unbound method loadDisplacement() must be called with person instance as first argument (got float64 instance instead)

This is the code I have written so far:
I am very new to python so am trying to use the most basic ways of accomplishing goals as possible as I currently don't know how to make it more efficient etc.
def simulateBeamRun(personlist, beam, times):
times = np.linspace(0,35,500)
templist = []
maxdeflectionlist = []
for t in times:
for i in personlist: #for each person instance
Tuple = personModel.person.loadDisplacement(t)
if 0 < Tuple(1) < beamModel.beam.L:
templist.append(Tuple)
else:
pass
return templist
File "beamSimulation.py", line 40, in simulateBeamRun
Tuple = personModel.person.loadDisplacement(t)
The error I am getting is:
TypeError: unbound method loadDisplacement() must be called with person instance as first argument (got float64 instance instead)
personlist is a list of lists each containing arrivalTime, weight, gait, speed for a given "person". This is so that it gives values to the constructor. Load displacement is the only other function in the person class:
class person(object):
"""This class models the displacement of a person's load as they run at
'speed' in one dimension. It assumes that the load is always concentrated
in a single point and that the displacement of that point is less than or
equal to the displacement of the person's centre of mass. Also the
displacement of the load will always be a multiple of 'gait'.
"""
def __init__(self, arrivalTime, weight, gait, speed):
"""This constructor function defines the person's weight, gait and
running speed as well as the time that they arrive at the position of
zero displacement.
"""
how do I fix this?
Given the limited code presented, some of this is just guessing, but it might point you in the right direction, at least:
There's no need to pass in the times argument if you're just going to immediately overwrite it with times = ....
You're not using maxdeflectionlist for anything, so it's not really needed (although maybe you're planning to later...).
Inside your for i in ... loop, i is your iteration variable, and should take each value successively from personlist. Guessing from variable names, these might be the person instances that you need to get displacements from, so the line that you're getting the error on should maybe be Tuple = i.loadDisplacement(t). If that's not the case, given your later comments, perhaps you need to instantiate a person object from the data in i - something like p = personModel.person(some, arguments, extracted, from, i), and then follow that with Tuple = p.loadDisplacement(t). Calling loadDisplacement() as you have is more appropriate for a class method or static method, not for an instance method, which is the essential meaning behind the error message you get. It's telling you that personModel.person is not a person instance - it's probably a class object.
The else: pass bit is sort of pointless.

Python input, ifstatement, return

I have to create a function that takes an input, and returns a corresponding Grade.
So for example if the user inputs A+ output is 90%
or
if the input is A output is 80%
or
if the input is B output is 70%
I have some sort of Idea on how to do this... but I am having trouble on wrapping my head around on how I can return the statement??
def percent (percentage):
if ( percentage )== A+
return ("90%")
elif (percentage)== A
return ("80%")
Is this the correct way of going about it?
OK, so first, welcome to Python. Second, this is Pythonic way of doing this - define a dict:
grades = {'A+': "90%", 'A': "80%", ...}
then
return grades[precentage]
will do the job.
You need to protect against the case where the grade is not in the dict, for example, if the user entered some mistake, like G. There are a few ways to go about that:
A simple if:
if precentage in grades:
return grades[precentage]
else:
return "bad precentage"
After you get used to Python you will be more aesthetic about your code and will want to do better than state twice bote grades and precentage, so you can do simply:
return grades.get(precentage, "bad precentage")
Or using a special dict with default values:
import collections
grades = collections.defaultdict(lambda: "bad precentage", [("A+", "90%"), ("A", "80%")])
then
grades[precentage]
will automatically return "bad precentage" upon bad input.
#user2829744 You don't want to have to repeatedly call if statements based on what the percentage is, that would make the code unnecessarily long.
Instead, you want to have a list or tuple (a variable which stores multiple elements) that the program can compare the user's inputted value to, and then calculate the percentage mark.
Take this for example:
def percentage(per):
grades=["A+","A","B","C","D","E","F"]
percentage=("90%","80%","70%","60%","50%","40%","30%")
for i in range(7):
if per.upper()==grades[i]:
return percentage[i]
d="a"
print(percentage(d))
What happens is that i counts up to the number seven, and if the value of i in grades (let's say i is 5, then that would be grades[5] which would be an "E") then the function returns the value of i in the percentage tuple. In my case, the interpreter outputs 80%
Logically, your way of going about it (by actually dealing with every grade possible in separate if statements) would work too, however like I said your code would be longer and chances are you'd make a few typos along the way that you'd have to edit. Of course, my code has a few problems too, like what if the user enters a grade which I don't have in the tuple. This is easily fixable though as you would just need to tell the interpreter what to do if that happens.
A bit brief I know, but I hope this helps
You could do something like this
user_input = int(input("percentage: ")
if user_input < 0 and user_input > 10:
print('F")
And then you can just duplicate the code and change the numbers and the return grade
Hope it helps :)