from otree.api import *
from settings import POINTS_CUSTOM_NAME
from random import randint
from _utils.payoff import (
get_endowment_in_points,
get_points_per_real_world_currency_unit
)
c = Currency
doc = """
Dictator Game - Treatment: Variant 1
Course: Behavioral Economic Experiments in the Context of the COVID-19 Pandemic
Created by: David Lucius (david.lucius@posteo.de)
"""
# ----------------------------------------------------------------------------------------------------------------------
# MODELS
# ----------------------------------------------------------------------------------------------------------------------
# hier haben wir den Multiplier (2) eingefügt, mit dem die abgegebene Anzahl Taler multipliziert wird.
# players_per_group = None weil alle zusammen in einer Gruppe spielen
class Constants(BaseConstants):
name_in_url = 'variant_1'
players_per_group = None
num_rounds = 3
multiplier = 2
# Hier können die Info-Texte bearbeitet werden:
# Dazu bitte einfach den Text hinter der entsprechenden Entscheidungsnummer austauschen.
info_texts = {
1: 'Hallo',
2: '
Nun sind Sie dazu verpflichtet mindestens 5 Taler abzugeben. '
'Das bedeutet, dass Sie maximal 5 Ihrer Taler behalten dürfen.
'
'Sollten Sie trotz der Pflicht weniger als '
'5 Taler abgeben, so ergibt sich folgende Konsequenz: '
'Unter allen Personen, die weniger als 5 Taler abgeben, '
'wird zufällig eine Person bestimmt, die ihre gesamten behaltenen Taler dieser Spielrunde verliert. '
'Diese Person erhält allerdings trotzdem ihren Anteil der gesammelten Taler von der Gemeinschaft.',
3: 'Die Pflicht, 5 Taler abzugeben, ist nun aufgehoben
',
4: '4 …',
5: '5Info-Text Pflicht …'
}
class Subsession(BaseSubsession):
is_winning_dec = models.BooleanField(initial=False)
@property
def num_players(self):
return len(self.get_players())
def creating_session(subsession):
if subsession.round_number == 1:
subsession.session.winning_dec = randint(1, Constants.num_rounds)
if subsession.round_number == subsession.session.winning_dec:
subsession.is_winning_dec = True
subsession.group_randomly()
class Group(BaseGroup):
total_contribution = models.FloatField()
total_profit = models.IntegerField()
individual_share = models.FloatField()
class Player(BasePlayer):
taler = models.IntegerField(
label='',
min=0
)
contribution = models.IntegerField()
freeriding = models.BooleanField()
loosing = models.BooleanField()
q3 = models.StringField(
label='Sind Sie geimpft?',
choices=[
'Ja',
'Nein',
],
widget=widgets.RadioSelect
)
q4 = models.StringField(
label='Hatten Sie bereits Covid19?',
choices=[
'Ja',
'Nein',
],
widget=widgets.RadioSelect
)
q5 = models.IntegerField(
label='Die Impfung ist die Rettung aus der Pandemie.',
choices=[
(1, 'Stimme überhaupt nicht zu'),
(2, 'Stimme eher nicht zu'),
(3, 'Stimme weder zu noch stimme ich nicht zu'),
(4, 'Stimme eher zu'),
(5, 'Stimme voll und ganz zu'),
],
)
q6 = models.IntegerField(
label='2G (Geimpft oder Genesen) in geschlossenen Räumlichkeiten für Freizeitvergnügen halte ich für sinnvoll '
'(z.B. Restaurant, Kino, Konzerte).',
choices=[
(1, 'Stimme überhaupt nicht zu'),
(2, 'Stimme eher nicht zu'),
(3, 'Stimme weder zu noch stimme ich nicht zu'),
(4, 'Stimme eher zu'),
(5, 'Stimme voll und ganz zu'),
],
)
q7 = models.IntegerField(
label='In maskenpflichtigen Bereichen trage ich stets meine Maske.',
choices=[
(1, 'Stimme überhaupt nicht zu'),
(2, 'Stimme eher nicht zu'),
(3, 'Stimme weder zu noch stimme ich nicht zu'),
(4, 'Stimme eher zu'),
(5, 'Stimme voll und ganz zu'),
],
)
q8 = models.IntegerField(
label='Ich trage meine Maske stets ordnungsgemäß. Ich bedecke sowohl meinen Mund als auch meine Nase.',
choices=[
(1, 'Stimme überhaupt nicht zu'),
(2, 'Stimme eher nicht zu'),
(3, 'Stimme weder zu noch stimme ich nicht zu'),
(4, 'Stimme eher zu'),
(5, 'Stimme voll und ganz zu'),
],
)
q9 = models.IntegerField(
label='Händeschütteln und Umarmungen vermeide ich.',
choices=[
(1, 'Stimme überhaupt nicht zu'),
(2, 'Stimme eher nicht zu'),
(3, 'Stimme weder zu noch stimme ich nicht zu'),
(4, 'Stimme eher zu'),
(5, 'Stimme voll und ganz zu'),
],
)
q10 = models.IntegerField(
label='Ich halte Abstand zu meinen Mitmenschen (wenn möglich).',
choices=[
(1, 'Stimme überhaupt nicht zu'),
(2, 'Stimme eher nicht zu'),
(3, 'Stimme weder zu noch stimme ich nicht zu'),
(4, 'Stimme eher zu'),
(5, 'Stimme voll und ganz zu'),
],
)
q11 = models.IntegerField(
label='Mein Verhalten während der Covid19-Pandemie empfinde ich als gewissenhaft.',
choices=[
(1, 'Stimme überhaupt nicht zu'),
(2, 'Stimme eher nicht zu'),
(3, 'Stimme weder zu noch stimme ich nicht zu'),
(4, 'Stimme eher zu'),
(5, 'Stimme voll und ganz zu'),
],
)
q12 = models.StringField(
label='Bitte wählen Sie Ihr Geschlecht',
choices=[
'Männlich',
'Weiblich',
'Divers',
],
widget=widgets.RadioSelectHorizontal
)
q13 = models.IntegerField(
label='Wie alt sind Sie?'
)
q14 = models.StringField(
label='Studieren Sie?',
choices=[
'Ja',
'Nein',
],
widget=widgets.RadioSelectHorizontal
)
q15 = models.StringField(
label='An welcher Fakultät studieren Sie?',
choices=[
'Rechtswissenschaften',
'Wirtschafts- und Sozialwissenschaften',
'Erziehungswissenschaften',
'Geisteswissenschaften',
'Psychologie und Bewegungswissenschaften',
'Betriebswirtschaft',
'Sonstige',
'Ich studiere nicht',
],
)
def taler_max(player):
return get_endowment_in_points(player)
# ----------------------------------------------------------------------------------------------------------------------
# PAGES
# ----------------------------------------------------------------------------------------------------------------------
# hier haben wir timeouts eingebaut, um die Zeit pro Seite zu begrenzen
class Intro(Page):
timeout_seconds = 120
@staticmethod
def is_displayed(player):
return player.round_number == 1
@staticmethod
def vars_for_template(player):
return dict(
endowment_in_points=c(get_endowment_in_points(player)),
points_per_real_world_currency_unit=c(get_points_per_real_world_currency_unit(player)),
)
class DecisionInfo(Page):
timeout_seconds = 60
@staticmethod
def is_displayed(player):
return player.round_number >= 2
@staticmethod
def vars_for_template(player):
return dict(
endowment_in_points=c(get_endowment_in_points(player)),
points_per_real_world_currency_unit=c(get_points_per_real_world_currency_unit(player))
)
class DecisionNeu(Page):
timeout_seconds = 120
form_model = 'player'
form_fields = [
'taler'
]
@staticmethod
def vars_for_template(player):
return dict(
POINTS_CUSTOM_NAME=POINTS_CUSTOM_NAME,
endowment_in_points=c(get_endowment_in_points(player)),
points_per_real_world_currency_unit=c(get_points_per_real_world_currency_unit(player)),
num_other_players=player.subsession.num_players - 1,
)
@staticmethod
def js_vars(player):
return dict(
endowment_in_points=get_endowment_in_points(player)
)
@staticmethod
def before_next_page(player: Player, timeout_happened):
player.contribution = get_endowment_in_points(player)-player.taler
if player.round_number == 2:
if player.contribution < 5:
player.freeriding = True
else:
player.freeriding = False
class Questionnaire(Page):
timeout_seconds = 60
form_model = 'player'
form_fields = [
'q3',
'q4',
]
@staticmethod
def is_displayed(player):
return player.round_number == Constants.num_rounds
class Questionnaire2(Page):
timeout_seconds = 180
form_model = 'player'
form_fields = [
'q5',
'q6',
'q7',
'q8',
'q9',
'q10',
'q11',
]
@staticmethod
def is_displayed(player):
return player.round_number == Constants.num_rounds
class Questionnaire3(Page):
timeout_seconds = 60
form_model = 'player'
form_fields = [
'q12',
'q13',
'q14',
'q15',
]
@staticmethod
def is_displayed(player):
return player.round_number == Constants.num_rounds
class Info(Page):
form_model = 'player'
@staticmethod
def is_displayed(player):
return player.round_number == Constants.num_rounds
class Payment(Page):
@staticmethod
def is_displayed(player):
return player.round_number == Constants.num_rounds
@staticmethod
def vars_for_template(player):
return dict(
POINTS_CUSTOM_NAME=POINTS_CUSTOM_NAME,
points_in_round_1=[player.in_round(1).taler],
points_in_round_2=[player.in_round(2).taler],
points_in_round_3=[player.in_round(3).taler],
contrib_in_round_1=[player.in_round(1).contribution],
contrib_in_round_2=[player.in_round(2).contribution],
contrib_in_round_3=[player.in_round(3).contribution],
groupcontrib_in_round_1=[player.group.in_round(1).total_profit],
groupcontrib_in_round_2=[player.group.in_round(2).total_profit],
groupcontrib_in_round_3=[player.group.in_round(3).total_profit],
taler_in_winning_dec=c(player.in_round(player.session.winning_dec).taler),
share_in_winning_dec=c(player.group.in_round(player.group.session.winning_dec).individual_share),
points_in_winning_dec=c(player.in_round(player.session.winning_dec).taler + player.group.in_round(
player.group.session.winning_dec).individual_share),
freerider=c(player.in_round(2).freeriding),
loosing_money=c(player.in_round(2).loosing),
)
class RoundWaitPage(WaitPage):
body_text = 'Bitte warten Sie, bis alle Entscheidungen getroffen wurden.'
@staticmethod
def after_all_players_arrive(group: Group):
total_contribution = 0
for player in group.get_players():
total_contribution += player.contribution
group.total_contribution = total_contribution
group.total_profit = total_contribution * Constants.multiplier
group.individual_share = total_contribution * Constants.multiplier / (len(group.get_players()))
if group.round_number == group.session.winning_dec:
for p in group.get_players():
p.payoff = p.taler + p.group.individual_share
list_of_freeriders = []
if group.round_number == 2:
for player in group.get_players():
if player.freeriding:
list_of_freeriders.append(player.id_in_group)
freerider_id = list_of_freeriders[0]
for player in group.get_players():
player.loosing = False
if player.id_in_group == freerider_id:
player.loosing = True
player.payoff = 0
# Payment erst ganz am Ende
page_sequence = [
Intro,
DecisionInfo,
DecisionNeu,
RoundWaitPage,
Info,
Questionnaire,
Questionnaire2,
Questionnaire3,
Payment
]