oTree Forum >

distinguising "none" investment and 0 investment

#1 by txb000

Please see the code below, I am trying to distinguish 0 investment with someone who made no investment but the timer runs out, that actually affects the payoffs. Can someone guide?

from otree.api import models, BaseConstants, BasePlayer, BaseSubsession, BaseGroup, Page, WaitPage
import random

class Constants(BaseConstants):
    name_in_url = 'contest_game'
    players_per_group = 2
    num_rounds = 1

    WINNER_PAYOFF = 240
    LOSER_PAYOFF = 120

class Player(BasePlayer):
    endowment = models.IntegerField(initial=120)
    cost = models.FloatField()
    investment = models.IntegerField(min=0, max=120)
    payoff_new = models.CurrencyField()

class Subsession(BaseSubsession):
    def creating_session(self):
        self.group_randomly(fixed_id_in_group=True)
        for group in self.get_groups():
            players = group.get_players()

            # Set cost for each player
            for player in players:
                player.cost = random.choice([0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5])

class Group(BaseGroup):
    investment_p1 = models.IntegerField()
    investment_p2 = models.IntegerField()

    def calculate_payoffs(self):
        p1, p2 = self.get_players()

        # Check if investments are None (e.g., due to a timeout)
        if self.investment_p1 is None or self.investment_p2 is None:
            p1.payoff_new = 0
            p2.payoff_new = 0
            return

        total_investment = self.investment_p1 + self.investment_p2

        if total_investment > 0:
            p1_likelihood = self.investment_p1 / total_investment
            p2_likelihood = self.investment_p2 / total_investment

            winner = p1 if p1_likelihood > p2_likelihood else p2
        else:
            winner = random.choice([p1, p2])

        if winner == p1:
            p1.payoff_new = Constants.WINNER_PAYOFF - p1.cost * p1.investment
            p2.payoff_new = Constants.LOSER_PAYOFF - p2.cost * p2.investment
        else:
            p1.payoff_new = Constants.LOSER_PAYOFF - p1.cost * p1.investment
            p2.payoff_new = Constants.WINNER_PAYOFF - p2.cost * p2.investment

        # Adjust payoff for timeout
        if self.investment_p1 is None:
            p1.payoff_new = 0
        if self.investment_p2 is None:
            p2.payoff_new = 0

class Results(Page):
    @staticmethod
    def vars_for_template(player):
        return {
            'player_payoff': player.payoff_new,
            # 'opponent_payoff': player.get_others_in_group()[0].payoff_new,
        }

    # timeout_seconds = 20  # Set the desired timeout duration

class InvestmentDecision(Page):
    form_model = 'player'
    form_fields = ['investment']

    @staticmethod
    def vars_for_template(player):
        # Set cost for the player before displaying the page
        player.cost = random.choice([0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5])

        return {
            'player_cost': player.cost,
        }

    @staticmethod
    def before_next_page(player, timeout_happened):
        group = player.group

        if player.investment is None:
            # Handle the case of no investment (timed out)
            player.payoff_new = 0
        elif player.id_in_group == 1:
            group.investment_p1 = player.investment
        elif player.id_in_group == 2:
            group.investment_p2 = player.investment

    timeout_seconds = 30  # Set the desired timeout duration

class WaitForSecondParticipant(WaitPage):
    @staticmethod
    def after_all_players_arrive(group):
        group.calculate_payoffs()

    body_text = "Waiting for the other participant to make their decision."
    timeout_seconds = 5  # Set the desired timeout duration

page_sequence = [InvestmentDecision, WaitForSecondParticipant, Results]

#2 by Fanist

Hey, just a quick thought, how about setting default value of Player.investment as -99? then you can compare -99 and 0 as no investment.

Write a reply

Set forum username