0

I am programming a version of the public goods game but using roles. Because of that, i cant obtain the sum of the total contributions of the players who are from a determined role. I tried with the following code:

self.total_contribution1 = sum( [p.contribution for p in self.get_players() if p.role== 'A'])

But it didn't worked and i only obtained an error of Invalid Operation

If i dont write the "if part" of that code, it runs, but the values of the attributes like that one become 0

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

author = 'Your name here'

doc = """
Simple public goods game
"""


class Constants(BaseConstants):
name_in_url = 'tiebout_incertidumbre'
players_per_group = 4
num_rounds = config_leex_1.PEMG_number_rounds #10
instructions_template = 'beec_mg/Instructions.html'
multiplier1 = 1
multiplier2 = 2
multiplier3 = 3
i = 1
j = 1
k = 1

class Subsession(BaseSubsession):
def creating_session(self):

    for p in self.get_players():
        p.endowment = random.randint(1, 100)
        p.prob = random.randint(0,100)
        # Random creation of endowments for every round

class Group(BaseGroup):

    total_contribution1 = models.CurrencyField(initial=0)
    total_contribution2 = models.CurrencyField(initial=0)
    total_contribution3 = models.CurrencyField(initial=0)
    mean_contribution1 = models.CurrencyField(initial=0)
    mean_contribution2 = models.CurrencyField(initial=0)
    mean_contribution3 = models.CurrencyField(initial=0)
    totalp1 = models.IntegerField(initial=0)
    totalp2 = models.IntegerField(initial=0)
    totalp3 = models.IntegerField(initial=0)
    individual_share1 = models.CurrencyField(initial=0)
    individual_share2 = models.CurrencyField(initial=0)
    individual_share3 = models.CurrencyField(initial=0)

    def set_payoffs(self):
        # NOTA 1: LAS SUMAS CON FOR NO ESTÁN FUNCIONANDO, YA QUE DAN DE         
        VALOR 0
        # NOTA 2: Los sums con if botan un error de invalid operation
        # NOTA 3: Segun SO, se deberia incluir parentesis después de p.role
    # if p.role== 'A':
    # self.total_contribution1 = sum(
        # [p.contribution for p in self.get_players() if p.role() == 'A'])
        for p in self.get_players():
            if p.role() == 'A':
                self.total_contribution1=+ p.contribution

        for p in self.get_players():
            if p.role() == 'B':
                self.total_contribution2=+ p.contribution

        for p in self.get_players():
            if p.role() == 'C':
                self.total_contribution3=+ p.contribution

        # if p.role== 'B'
        # self.total_contribution2 = sum(
        # [p.contribution for p in self.get_players()])
        # if p.role== 'C'
        # self.total_contribution3 = sum(
        # [p.contribution for p in self.get_players()])

        # if p.role== 'A'
        # self.totalp1 = sum(
        # [p.counter for p in self.get_players() if p.role() == 'A'])
        for p in self.get_players():
            if p.role() == 'A':
                self.totalp1=+1

        for p in self.get_players():
            if p.role() == 'B':
                self.totalp2=+1

        for p in self.get_players():
            if p.role() == 'C':
                self.totalp3=+1

        # if p.role == 'B'
    # self.totalp2 = sum(
        # [p.counter for p in self.get_players() if p.role() == 'B'])
    # if p.role == 'C'
    # self.totalp3 = sum(
        # [p.counter for p in self.get_players() if p.role() == 'C'])

    self.individual_share1 = self.total_contribution1 *         
    Constants.multiplier1 / self.totalp1
    self.individual_share2 = self.total_contribution2 *                 
    Constants.multiplier2 / self.totalp2
    self.individual_share3 = self.total_contribution3 * 
    Constants.multiplier3 / self.totalp3

    self.mean_contribution1 = self.total_contribution1/self.totalp1
    self.mean_contribution2 = self.total_contribution2 /self.totalp2
    self.mean_contribution3 = self.total_contribution3 /self.totalp3


    for p in self.get_players():
        if p.role == "A":
            p.payoff = p.endowment - p.contribution + self.individual_share1
        elif p.role == "B":
            if p.prob <= 75:
                p.payoff = p.endowment - p.contribution + 
    self.individual_share2
            else:
                p.payoff = p.endowment - p.contribution
        else:
            if p.prob <= 50:
                p.payoff = p.endowment - p.contribution + 
    self.individual_share3
            else:
                p.payoff = p.endowment - p.contribution

class Player(BasePlayer):
    prob =models.IntegerField(min=0, max=100)
    endowment = models.CurrencyField(min=0, max=100, initial=0)
    contribution = models.CurrencyField(verbose_name='Deslice hasta 
    seleccionar la cantidad a enviar deseada',
                                    min=0,max=100,
                                    initial=0,widget=widgets.SliderInput())
    counter = models.IntegerField(initial=1)
    roller = models.IntegerField(verbose_name='Deslice hasta seleccionar el 
    número de la opción deseada',
                             min=1, max=3,
                             widget=widgets.SliderInput())
   # Se está usando un slider para esta opción pues permite evitar 
   confusiones en caso se use un grupo de botones
   # los cuales se podrían clickear en cualquier momento sin que el jugador 
   entienda si ya se registró o no su decisión

   def role(self):
      if self.roller == 1:
          return 'A'
      elif self.roller == 2:
          return 'B'
      else:
          return 'C'from otree.api import (

1 Answers1

1

role is a method not a field. so to make it work you need to use this:

self.total_contribution1 = sum( [p.contribution for p in self.get_players() if p.role() == 'A'])

Attention to the parentheses I added after role

Philipp Chapkovski
  • 1,949
  • 3
  • 22
  • 43
  • I tried your solution, but i get the same error message: self.individual_share2 = self.total_contribution2 * Constants.multiplier2 / self.totalp2 File "d:\python\lib\site-packages\otree\currency\__init__.py", line 62, in binary_function return self.__class__(method(self, other)) decimal.InvalidOperation: [] – Marco Gutiérrez Nov 07 '18 at 13:36
  • You refer to another code here. Can you post the entire one? – Philipp Chapkovski Nov 07 '18 at 13:39
  • I've just done it. Now i moved the if's and for's, but the results are the same (im still getting the same error message). – Marco Gutiérrez Nov 08 '18 at 03:17
  • this one won't work: self.total_contribution1=+ p.contribution because it should be `+=` not `=+` – Philipp Chapkovski Nov 08 '18 at 11:11
  • Still getting the same mistake self.individual_share1 = self.total_contribution1 * Constants.multiplier1 / self.totalp1 File "d:\python\lib\site-packages\otree\currency\__init__.py", line 62, in binary_function return self.__class__(method(self, other)) decimal.InvalidOperation: [] – Marco Gutiérrez Nov 09 '18 at 00:09
  • The problem was solved :D The initial value of totalp"i" needed to be 1 and you were correct about the += – Marco Gutiérrez Nov 09 '18 at 00:47