from otree.api import *
import random
import settings
author = 'Patricia Zauchner (zauchner@uni-bremen.de)'
doc = """
A Vote: Arguments after the redistribution app.
"""
# Models
class C(BaseConstants):
NAME_IN_URL = 'a_vote'
PLAYERS_PER_GROUP = 5
NUM_ROUNDS = 1
TokenAdd_1dArticle = settings.TokenAdd_1dArticle
# Arguments
ARG_MIN_LENGHT = 10
ARG_MAX_LENGHT = 250
ARG_BEST_TOKEN = 2 # Not used in this experiment.
ARG_TIME = 5
class Subsession(BaseSubsession):
pass
def creating_session(subsession: Subsession):
"""" create ID, StartToken, Wealth, and Treatments """
#
try:
subsession.session.vars["StartToken"] = subsession.session.config["StartToken"]
except KeyError:
subsession.session.vars["StartToken"] = settings.StartToken
#
#
# Copy the group and player id structure of the first app
if "id_matrix" in subsession.session.vars:
subsession.set_group_matrix(subsession.session.vars['id_matrix'])
else:
subsession.group_randomly() # oTree function
subsession.session.vars['id_matrix'] = subsession.get_group_matrix()
print("ID Matrix created in app a_vote", subsession.session.vars['id_matrix'])
#
# # Whether arguments should be made
try:
subsession.session.vars["do_arguments_a_vote"] = subsession.session.config["do_arguments_a_vote"]
except KeyError:
subsession.session.vars["do_arguments_a_vote"] = getattr(settings, "do_arguments_a_vote", True)
#
#
try:
subsession.session.vars['do_acceptance'] = subsession.session.config["do_acceptance"]
except KeyError:
subsession.session.vars["do_acceptance"] = getattr(settings, "do_acceptance",
False) # If not specified default is False
#
class Group(BaseGroup):
# Treatments - Not used here
GroupAcknowledgement = models.IntegerField(doc="GV: Whether group accepted suggested distribution or not.")
# Arguments
# Number of votes for best argument
AVote_nArgBest_1 = models.IntegerField(doc="Number of group members stating that Player 1s argument was best")
AVote_nArgBest_2 = models.IntegerField(doc="Number of group members stating that Player 2s argument was best")
AVote_nArgBest_3 = models.IntegerField(doc="Number of group members stating that Player 3s argument was best")
AVote_nArgBest_4 = models.IntegerField(doc="Number of group members stating that Player 4s argument was best")
AVote_nArgBest_5 = models.IntegerField(doc="Number of group members stating that Player 5s argument was best")
# Acceptance of arguments - Not used in this experiment
# AVote_nArgAkz_1 = models.IntegerField()
# AVote_nArgAkz_2 = models.IntegerField()
# AVote_nArgAkz_3 = models.IntegerField()
# AVote_nArgAkz_4 = models.IntegerField()
# AVote_nArgAkz_5 = models.IntegerField()
# AVote_nArgAkzNo_1 = models.IntegerField()
# AVote_nArgAkzNo_2 = models.IntegerField()
# AVote_nArgAkzNo_3 = models.IntegerField()
# AVote_nArgAkzNo_4 = models.IntegerField()
# AVote_nArgAkzNo_5 = models.IntegerField()
# Group functions
def define_group_rank(group: Group):
""" Define group rank.
Either get GroupRanks from the participant variables or assign new ones. """
randomnumber = random.sample(list(range(1, 6)), 5)
for p in group.get_players():
try:
p.GroupRank = p.participant.vars["GroupRank"]
except KeyError:
print("AVote ... No Grouprank here. Pretest only!")
p.GroupRank = randomnumber[p.id_in_group - 1] # For Pretest Reasons Only
# Change id_in_group
for p in group.get_players():
p.id_in_group = p.GroupRank
def define_start_token(group: Group):
""" Get start token based on group ranks """
# print("Avote ... Define Start Token (reduced version)")
for p in group.get_players():
# For specific positions
p.StartToken = group.session.vars["StartToken"][p.GroupRank - 1]
# Count acceptance (not used in this experiment)
# def calc_acc_arg(group: Group, argpart):
# if group.session.vars['do_acceptance']:
# # argpart are either a_vote, redistribution, etc.
# group_acc_base = argpart + "_nArgAkz_"
# group_accNo_base = argpart + "_nArgAkzNo_"
# ind_acc_base = argpart + "_ArgAkz_"
# ind_accNo_base = argpart + "_ArgAkzNo_"
#
# for i in range(1, 6):
# group_acc_mod = group_acc_base + str(i)
# group_accNo_mod = group_accNo_base + str(i)
# ind_acc_mod = ind_acc_base + str(i)
# ind_accNo_mod = ind_accNo_base + str(i)
# # Calculations
# setattr(group, group_acc_mod,
# sum((vars(p)[ind_acc_mod]) for p in group.get_players() if vars(p)[ind_acc_mod] is not None))
# setattr(group, group_accNo_mod, 5 - vars(group)[group_acc_mod])
# Calculate best argument
def calc_best_arg(group: Group, argpart):
""" Calculate the best argument
'argpart' is either "AVote", "BVote", "Rej" or "Acc" """
group_best_base = argpart + "_nArgBest_"
ind_best_base = argpart + "_ArgBest_"
for i in range(1, 6):
group_best_mod = group_best_base + str(i)
ind_best_mod = ind_best_base + str(i)
# Calculations
setattr(group, group_best_mod, sum((vars(p)[ind_best_mod]) for p in group.get_players()))
# Assign count of best argument to subjects.
listofbest = [] # Für Übersicht
for p in group.get_players():
setattr(p, argpart + "_nArgBest", vars(group)[group_best_base + str(p.GroupRank)])
listofbest.append(vars(p)[argpart + "_nArgBest"])
# Who won best argument?
winners = [i for i, j in enumerate(listofbest) if j == max(listofbest)]
for p in group.get_players():
# If winner
if (p.GroupRank - 1) in winners and len(winners) <= 2: # There are max 2 winners.
setattr(p, argpart + "_ArgBest", 1)
# setattr(p, argpart + "_ArgToken", C.ARG_BEST_TOKEN) # Not used in this experiment.
if len(winners) == 1:
setattr(p, argpart + "_ArgBestSingle", 1)
else:
setattr(p, argpart + "_ArgBestSingle", 2)
# If not winner
else:
setattr(p, argpart + "_ArgBest", 0)
# setattr(p, argpart + "_ArgToken", 0)
setattr(p, argpart + "_ArgBestSingle", 0)
# p.participant.vars[argpart + "_ArgToken"] = getattr(p, argpart + "_ArgToken")
class Player(BasePlayer):
GroupRank = models.IntegerField(doc="GV: Rank in group")
# Start Token
StartToken = models.FloatField(doc="GV: StartToken after deduction of taxes")
# After Voting: Argument
AVote_AckArg = models.TextField(
doc="Individual argument for the group decision",
label="",
max_length=250
)
# AVote --> Akezptieren -- Argumente nach Wahl (not used in this experiment)
# AVote_ArgAkz_1 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect
# )
# AVote_ArgAkz_2 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect
# )
# AVote_ArgAkz_3 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect
# )
# AVote_ArgAkz_4 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect
# )
# AVote_ArgAkz_5 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect
# )
# Vote for best argument
AVote_ArgBest_1 = models.BooleanField(
doc="Individual votes for best argument - for player 1",
blank=True, initial=False)
AVote_ArgBest_2 = models.BooleanField(
doc="Individual votes for best argument - for player 2",
blank=True, initial=False)
AVote_ArgBest_3 = models.BooleanField(
doc="Individual votes for best argument - for player 3",
blank=True, initial=False)
AVote_ArgBest_4 = models.BooleanField(
doc="Individual votes for best argument - for player 4",
blank=True, initial=False)
AVote_ArgBest_5 = models.BooleanField(
doc="Individual votes for best argument - for player 5",
blank=True, initial=False)
# AVote --> Bestes Argument für neue Verteilung berechnen - Gewinner und Token
AVote_nArgBest = models.IntegerField(doc="Number of votes for best vote")
AVote_ArgBest = models.IntegerField(doc="Whether participant is one of the best-vote winners")
# AVote_ArgToken=models.IntegerField(initial=0, doc="Token für the argument.") # Not used in this experiment
AVote_ArgBestSingle = models.IntegerField(doc="Whether participant is the only best-vote winner")
# -----------------------------------------------------------------------------------------------------------------
# Pages
class WaitpageBefore(WaitPage):
"""I just need this page for pretesting a single app """
@staticmethod
def after_all_players_arrive(group: Group):
print(
"------------------------------------- Start AVote App ------------------------------------------------")
# Get GroupAcknowledgement
for p in group.get_players():
# GroupAcknowledgement wurde in redistribution/AckResultWP berechnet
p.group.GroupAcknowledgement = p.participant.vars.get("GroupAcknowledgement", 1)
define_group_rank(group)
define_start_token(group)
class WaitForArgs(WaitPage):
""" Wait for the arguments of the group members """
@staticmethod
def is_displayed(player):
return player.session.vars['do_arguments_a_vote']
class WaitForVotes(WaitPage):
""" Wait for the votes for the best argument """
@staticmethod
def is_displayed(player):
return player.session.vars['do_arguments_a_vote']
class AVote_Arg(Page):
""" Enter the argument """
template_name = 'a_vote/AVote_Arg.html'
@staticmethod
def is_displayed(player):
# print("Player's Group Rank: ", player.GroupRank, " and Start Token: ", player.StartToken)
return player.session.vars['do_arguments_a_vote']
#
timer_text = 'Verbleibende Zeit (in Sek.):'
@staticmethod
def get_timeout_seconds(player):
# second argument of get()-method is the default---in this case the respective value from the settings
return player.session.config.get("minutes_for_arguments",
settings.minutes_for_arguments) * 60
#
@staticmethod
def vars_for_template(player):
return {
"secondsTimerIsShown": player.session.config.get("secondsTimerIsShown",
settings.secondsTimerIsShown)
# The last 60 seconds when the timer is shown
}
@staticmethod
def before_next_page(player, timeout_happened): # Note: timeout_happend is either none or True
answer = player.AVote_AckArg
if timeout_happened is True:
answer += " (Zeit abgelaufen)"
player.AVote_AckArg = answer
# Formfields
form_model = "player"
form_fields = ["AVote_AckArg"]
class AVote_RateBestArg(Page):
""" Acceptance of arguments """
template_name = 'a_vote/AVote_RateBestArg.html'
@staticmethod
def is_displayed(player):
return player.session.vars['do_arguments_a_vote'] and player.session.vars['do_acceptance']
#
form_model = "player"
@staticmethod
def get_form_fields(player):
field_list = []
for i in range(1, 6):
if player.GroupRank != i:
field_list.append("AVote_ArgAkz_" + str(i))
return field_list
#
@staticmethod
def vars_for_template(player):
""" A person cannot accept their own argument. Their assigned variable hence gets a value of -98. """
if player.GroupRank == 1:
player.AVote_ArgAkz_1 = -98
elif player.GroupRank == 2:
player.AVote_ArgAkz_2 = -98
elif player.GroupRank == 3:
player.AVote_ArgAkz_3 = -98
elif player.GroupRank == 4:
player.AVote_ArgAkz_4 = -98
elif player.GroupRank == 5:
player.AVote_ArgAkz_5 = -98
class AVote_RateBestArg2(Page):
""" Vote for best argument """
template_name = 'a_vote/AVote_RateBestArg2.html'
@staticmethod
def is_displayed(player):
# print("Avote .... do_acceptance-Variable", player.subsession.session.vars['do_acceptance']) # Delete again
return player.session.vars['do_arguments_a_vote']
form_model = "player"
@staticmethod
def get_form_fields(player):
field_list = []
for i in range(1, 6):
if player.GroupRank != i:
field_list.append("AVote_ArgBest_" + str(i))
return field_list
class AVote_BestUebersicht(Page):
""" Show results for acceptances and votes for best argument """
template_name = 'a_vote/AVote_BestUebersicht.html'
@staticmethod
def is_displayed(player):
return player.session.vars['do_arguments_a_vote']
@staticmethod
def vars_for_template(player):
calc_best_arg(player.group, "AVote")
# player.group.calc_acc_arg("AVote") # Not used in this experiment
page_sequence = [
WaitpageBefore,
AVote_Arg,
WaitForArgs,
AVote_RateBestArg,
AVote_RateBestArg2,
WaitForVotes,
AVote_BestUebersicht,
]