# Models
from otree.api import *
import random
from collections import Counter
import time
import settings
author = 'Patricia Zauchner (zauchner@uni-bremen.de)'
doc = """
Rejection: Finding a new Distribution if the group rejected the suggested distribution procedure.
"""
class C(BaseConstants):
NAME_IN_URL = 'rejection'
PLAYERS_PER_GROUP = 5
NUM_ROUNDS = 1
NEEDS = settings.Needs
USUAL_CONSUMPTION = 0.9 # 90% of the income will be consumed
TOKEN_ADD_TOTAL = settings.TokenAddTotal
TokenAdd_1dArticle = settings.TokenAdd_1dArticle
# Arguments
ARG_MIN_LENGHT = 10
ARG_MAX_LENGHT = 250
ARG_TIME = 5
CHAT_HEIGHT = 600
# Time (in minutes)
CHAT_TIME_DISTRIBUTION = settings.minutes_for_chrej1 # Formerly known as ChatTime_Verteilung
CHAT_TIME_DISTRIBUTION_CORR = settings.minutes_for_chrej2 # Formerly known as ChatTime_VerteilungKorr
CHAT_TIME_DISTRIBUTION_CORRSEK = CHAT_TIME_DISTRIBUTION_CORR * 60 # Formerly known as ChatTime_VerteilungKorrSek
class Subsession(BaseSubsession):
...
def creating_session(subsession: Subsession):
"""" create ID, StartToken, Wealth, and Treatments """
#
try:
subsession.session.vars["StartToken"] = subsession.session.config["StartToken"]
# print("Rejection ... StartToken taken from session config")
except KeyError:
subsession.session.vars["StartToken"] = settings.StartToken
# print("Rejection ... StartToken taken from settings")
try:
subsession.session.vars["Taxes"] = subsession.session.config["Taxes"]
# print("Rejection ... Taxes taken from session config")
except KeyError:
subsession.session.vars["Taxes"] = settings.Taxes
# print("Rejection ... Taxes taken from settings")
subsession.session.vars["StartTokenPT"] = [] # StartToken --> Brutto pre taxes
for i in range(0, 5):
subsession.session.vars["StartTokenPT"].append(subsession.session.vars["StartToken"][i] + subsession.session.vars["Taxes"][i])
#
#
# 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 rejection", subsession.session.vars['id_matrix'])
#
# # Whether arguments should be made
try:
subsession.session.vars['do_arguments_rejection'] = subsession.session.config["do_arguments_rejection"]
# print("Rejection ... do_arguments_rejection in session.config is",
# subsession.session.vars['do_arguments_rejection'])
except KeyError:
subsession.session.vars["do_arguments_rejection"] = getattr(settings, "do_arguments_rejection", True)
#
#
try:
subsession.session.vars['do_acceptance'] = subsession.session.config["do_acceptance"]
except KeyError:
subsession.session.vars["do_acceptance"] = getattr(settings, "do_acceptance", False)
#
class Group(BaseGroup):
REDIS = models.IntegerField(initial=1) # 0 = DIS, 1 = REDIS ---> FIS: From now on always redis
# Effort is not needed in this app
GroupAcknowledgement = models.IntegerField(doc="GV: Whether group accepted suggested distribution or not.")
# GroupRank und StartToken zuweisen
# StartToken zuweisen
# Chat Channels und Nickname
# Chat Channels
Channel_DisProcedure = models.TextField(doc="Chat channel")
Channel_DisProcedureCorr = models.TextField(doc="Chat channel")
# Arguments
# Number of votes for best argument
Rej_nArgBest_1 = models.IntegerField(doc="Number of group members stating that Player 1s argument was best")
Rej_nArgBest_2 = models.IntegerField(doc="Number of group members stating that Player 2s argument was best")
Rej_nArgBest_3 = models.IntegerField(doc="Number of group members stating that Player 3s argument was best")
Rej_nArgBest_4 = models.IntegerField(doc="Number of group members stating that Player 4s argument was best")
Rej_nArgBest_5 = models.IntegerField(doc="Number of group members stating that Player 5s argument was best")
# Acceptance of arguments - Not used in this experiment
# Rej_nArgAkz_1 = models.IntegerField()
# Rej_nArgAkz_2 = models.IntegerField()
# Rej_nArgAkz_3 = models.IntegerField()
# Rej_nArgAkz_4 = models.IntegerField()
# Rej_nArgAkz_5 = models.IntegerField()
#
# Rej_nArgAkzNo_1 = models.IntegerField()
# Rej_nArgAkzNo_2 = models.IntegerField()
# Rej_nArgAkzNo_3 = models.IntegerField()
# Rej_nArgAkzNo_4 = models.IntegerField()
# Rej_nArgAkzNo_5 = models.IntegerField()
# Count acceptance (not used in this experiment)
# def calc_acc_arg(self, argpart):
# if self.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(self, group_acc_mod,
# sum((vars(p)[ind_acc_mod]) for p in self.get_players() if vars(p)[ind_acc_mod] is not None))
# setattr(self, group_accNo_mod, 5 - vars(self)[group_acc_mod])
# Choice for new distribution
NumElegibleToVoteNewDis = models.IntegerField(
doc="Number of group members eligible to vote",
initial=5)
# Choice for new distribution - Reached/TokenAdd_New/SumRoundIncome/WealthNewDis/WealthNewDis_5R"
found_new_distribution = models.IntegerField( # Old variable name: NeueVerteilungErreicht
doc="Whether new distribution was found by the group in the first try.",
initial=0)
found_new_distribution_corr = models.IntegerField( # Old variable name: NeueVerteilungErreicht_Corr
doc="Whether new distribution was found by the group in the second try.",
initial=0)
# Election for distribution ELECTORAL RESULT - TokenAdd_New_1/5"
# First try
TokenAdd_New_1 = models.FloatField(
doc="Voting result in first try. Assingment to player 1.",
)
TokenAdd_New_2 = models.FloatField(
doc="Voting result in first try. Assingment to player 2.",
)
TokenAdd_New_3 = models.FloatField(
doc="Voting result in first try. Assingment to player 3.",
)
TokenAdd_New_4 = models.FloatField(
doc="Voting result in first try. Assingment to player 4.",
)
TokenAdd_New_5 = models.FloatField(
doc="Voting result in first try. Assingment to player 5.",
)
# Second try
TokenAdd_New_corr_1 = models.FloatField(
doc="Voting result in second try. Assingment to player 1.",
)
TokenAdd_New_corr_2 = models.FloatField(
doc="Voting result in second try. Assingment to player 2.",
)
TokenAdd_New_corr_3 = models.FloatField(
doc="Voting result in second try. Assingment to player 3.",
)
TokenAdd_New_corr_4 = models.FloatField(
doc="Voting result in second try. Assingment to player 4.",
)
TokenAdd_New_corr_5 = models.FloatField(
doc="Voting result in second try. Assingment to player 5.",
)
# Group Functions
def nickname(group: Group):
group.Channel_DisProcedure = str(group.id_in_subsession) + "_DisProc"
group.Channel_DisProcedureCorr = str(group.id_in_subsession) + "_DisProcCorr"
rand = random.sample(list(range(0, 5)), 5)
for p in group.get_players():
p.Nickname = "Player " + str(p.GroupRank)
if "randomnicknamecolors" not in p.participant.vars:
p.participant.vars["randomnicknamecolors"] = rand
# CountSame - individual level . Count Number of same inputs
def abzahlen(group: Group, Correction): # Neue Version
"""
How many group members entered the same numbers?
Old function name in ztree: Countsame.
If this function is called after the Correction chat, enter "Corr" when calling the function.
Wird in Pages --> Rej_5_Chat_DistributionProcedure_2WP_After aufgerufen
"""
corr = ""
if Correction == "Corr":
corr = "_" + "corr"
listofallvotes = []
for p in group.get_players():
listofallvotes.append([
vars(p)["iTokenAddVoteFor" + corr + "_" + str(1)],
vars(p)["iTokenAddVoteFor" + corr + "_" + str(2)],
vars(p)["iTokenAddVoteFor" + corr + "_" + str(3)],
vars(p)["iTokenAddVoteFor" + corr + "_" + str(4)],
vars(p)["iTokenAddVoteFor" + corr + "_" + str(5)]
])
new_listofallvotes = map(tuple, listofallvotes)
final_count = Counter(new_listofallvotes)
voteergebnis = [k for k, v in final_count.items() if v >= 3]
voteergebnis = [list(row) for row in voteergebnis]
# Distribution was achieved?
if not voteergebnis: # If empty, then no distribution was found
setattr(group, "found_new_distribution" + corr, 0)
elif voteergebnis[0] == [0, 0, 0, 0, 0]:
print("Rejection ... No distribution found because skipped")
setattr(group, "found_new_distribution" + corr, 0)
else:
setattr(group, "found_new_distribution" + corr, 1)
# Save group election result
for i in range(1, 6):
setattr(group, "TokenAdd_New" + corr + "_" + str(i), voteergebnis[0][i - 1])
# Save result for individuals
for p in group.get_players():
for i in range(1, 6):
if p.GroupRank == i:
p.TokenAdd = getattr(group, "TokenAdd_New" + corr + "_" + str(i))
# Calculate Token Add
# Calculate Roundincome after Tokenadd and Needs-Satisfaction
for p in group.get_players():
p.SumRoundIncome = p.StartToken + p.TokenAdd
if p.SumRoundIncome * C.USUAL_CONSUMPTION < C.NEEDS:
p.ConsumptionFinal = C.NEEDS
p.WealthNewDis_1R = p.SumRoundIncome - C.NEEDS
else:
p.ConsumptionFinal = p.SumRoundIncome * C.USUAL_CONSUMPTION
p.WealthNewDis_1R = p.SumRoundIncome * (1-C.USUAL_CONSUMPTION)
p.WealthNewDis_5R = p.WealthNewDis_1R * 5
p.participant.vars["WealthNewDis_5R"] = p.WealthNewDis_5R
def define_start_token(group: Group):
""" Get start token based on group ranks """
for p in group.get_players():
# For specific positions
p.StartToken = group.session.vars["StartToken"][p.GroupRank - 1]
p.StartTokenPT = group.session.vars["StartTokenPT"][p.GroupRank - 1]
p.Taxes = group.session.vars["Taxes"][p.GroupRank - 1]
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()))
# print(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.ArgBestToken)
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")
def results_graph(group: Group):
""" Called in Pages - class Rej_9_Rounds(Page)"""
series_Start = []
series_TokenAdd = []
series_Income = []
series_Cumulative = []
series_highest_lowest = []
series_WealthAt1 = []
series_WealthAt5 = []
wealth_min = 0
wealth_max = 0
for p in group.get_players():
# Wealth
series_WealthAt1.append({
"name": p.GroupRank,
"y": p.WealthNewDis_1R})
series_WealthAt5.append({
"name": p.GroupRank,
"y": p.WealthNewDis_1R * 5})
# min/max Runde 1
if p.WealthNewDis_1R < wealth_min:
wealth_min = p.WealthNewDis_1R
if p.WealthNewDis_1R > wealth_max:
wealth_max = p.WealthNewDis_1R
# min/max Rund e5
if p.WealthNewDis_5R < wealth_min:
wealth_min = p.WealthNewDis_5R
if p.WealthNewDis_5R > wealth_max:
wealth_max = p.WealthNewDis_5R
series_Start.append({
"name": p.GroupRank,
"y": p.StartToken})
series_TokenAdd.append({
"name": p.GroupRank,
"y": p.TokenAdd})
cumulativedata = [0,
p.WealthNewDis_1R * 1,
p.WealthNewDis_1R * 2,
p.WealthNewDis_1R * 3,
p.WealthNewDis_1R * 4,
p.WealthNewDis_1R * 5
]
series_Cumulative.append({
"name": p.GroupRank,
"data": cumulativedata})
series_highest_lowest.append(p.WealthNewDis_1R * 5)
series_Income.append(p.StartToken + p.TokenAdd)
return {
"StartToken": series_Start,
"TokenAdd": series_TokenAdd,
"Cumulative": series_Cumulative,
"MinValue_B": min_max_graph(series_highest_lowest)[0],
"MaxValue_B": min_max_graph(series_highest_lowest)[1],
"MinValue_A": 0,
"MaxValue_A": min_max_graph(series_Income)[1],
# Wealth
"WealthAt1": series_WealthAt1,
"WealthAt5": series_WealthAt5,
"wealth_min": wealth_min,
"wealth_max": wealth_max,
}
def min_max_graph(list_):
""" Calculate the minimun and maximum values for the graph. """
if min(list_) >= 0:
minlist = -5
maxlist = max(list_) + 3
else:
minlist = min(list_) - 5
maxlist = max(list_) + 3
return minlist, maxlist
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("Rejection ... 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
class Player(BasePlayer):
# Variables for all apps
# Income of the individuals
StartToken = models.FloatField(doc="StartToken after deduction of taxes")
StartTokenPT = models.FloatField(doc="StartToken pre taxes; formally coded as StartTokenAlt")
Taxes = models.FloatField(doc="Taxes to be deducted from StartTokenPT")
ConsumptionFinal = models.FloatField(
doc="Final consumption = with TokenAdd as voted for by group as alternative distribution")
SumRoundIncome = models.FloatField(doc="Final income in each round.")
GroupRank = models.IntegerField(doc="GV: Rank in group")
# Arguments Rejection
# Enter arguments for new distribution. Only with Rejection ----- initials still delete
iTokenAddSuggestion_1 = models.FloatField(
doc="Argument for new distribution. Assignment to Player 1",
# label="Player 1 (" + str(format(C.StartToken_0[1-1], '.0f')) + "Token)",
min=0, max=C.TOKEN_ADD_TOTAL,
)
iTokenAddSuggestion_2 = models.FloatField(
doc="Argument for new distribution. Assignment to Player 2",
# label="Player 2 (" + str(format(C.StartToken_0[2-1], '.0f')) + "Token)",
min=0, max=C.TOKEN_ADD_TOTAL,
)
iTokenAddSuggestion_3 = models.FloatField(
doc="Argument for new distribution. Assignment to Player 3",
# label="Player 3 (" + str(format(C.StartToken_0[3-1], '.0f')) + "Token)",
min=0, max=C.TOKEN_ADD_TOTAL,
)
iTokenAddSuggestion_4 = models.FloatField(
doc="Argument for new distribution. Assignment to Player 4",
# label="Player 4 (" + str(format(C.StartToken_0[4-1], '.0f')) + "Token)",
min=0, max=C.TOKEN_ADD_TOTAL,
)
iTokenAddSuggestion_5 = models.FloatField(
doc="Argument for new distribution. Assignment to Player 5",
# label="Player 5 (" + str(format(C.StartToken_0[5-1], '.0f')) + "Token)",
min=0, max=C.TOKEN_ADD_TOTAL,
)
Rej_Arg = models.TextField(
doc="The argument a person has entered for their preferred distribution of the 20 Token.",
label="",
max_length=250,
# blank=True # this will be overridden later in the javascript
)
# Accept arguments - Rejection (not used in this experiment)
# Rej_ArgAkz_1 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect,
#
# )
# Rej_ArgAkz_2 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect,
#
# )
# Rej_ArgAkz_3 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect,
#
# )
# Rej_ArgAkz_4 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect,
#
# )
# Rej_ArgAkz_5 = models.IntegerField(
# choices=[
# [1, "Ich akzeptiere das Argument"],
# [0, "Ich akzeptiere das Argument nicht"],
# ],
# widget=widgets.RadioSelect,
#
# )
# Vote for best argument
Rej_ArgBest_1 = models.BooleanField(
doc="Individual votes for best argument - for player 1",
blank=True, initial=False)
Rej_ArgBest_2 = models.BooleanField(
doc="Individual votes for best argument - for player 2",
blank=True, initial=False)
Rej_ArgBest_3 = models.BooleanField(
doc="Individual votes for best argument - for player 3",
blank=True, initial=False)
Rej_ArgBest_4 = models.BooleanField(
doc="Individual votes for best argument - for player 4",
blank=True, initial=False)
Rej_ArgBest_5 = models.BooleanField(
doc="Individual votes for best argument - for player 5.",
blank=True, initial=False)
# Rej --> Calculate best argument for new distribution - winners and tokens
Rej_nArgBest = models.IntegerField(doc="Number of votes for best vote")
Rej_ArgBest = models.IntegerField(doc="Whether participant is one of the best-vote winners")
# Rej_ArgToken = models.IntegerField(initial=0, doc="Token for the argument.") # Not used in this experiment
Rej_ArgBestSingle = models.IntegerField(doc="Whether participant is the only best-vote winner")
# Helping variables Chat
Nickname = models.TextField(doc="Nickname in chat")
# New Distribution
TokenAdd = models.FloatField(doc="Chosen new distribution - if suggested distribution was rejected")
# Votes for new distribution - First try -iTokenAddVoteFor_1
iTokenAddVoteFor_1 = models.FloatField(
doc="Individual votes for assignment to player 1 in new distribution. First try.",
min=0,
max=C.TOKEN_ADD_TOTAL)
iTokenAddVoteFor_2 = models.FloatField(
doc="Individual votes for assignment to player 2 in new distribution. First try.",
min=0,
max=C.TOKEN_ADD_TOTAL)
iTokenAddVoteFor_3 = models.FloatField(
doc="Individual votes for assignment to player 3 in new distribution. First try.",
min=0,
max=C.TOKEN_ADD_TOTAL)
iTokenAddVoteFor_4 = models.FloatField(
doc="Individual votes for assignment to player 4 in new distribution. First try.",
min=0,
max=C.TOKEN_ADD_TOTAL)
iTokenAddVoteFor_5 = models.FloatField(
doc="Individual votes for assignment to player 5 in new distribution. First try.",
min=0,
max=C.TOKEN_ADD_TOTAL)
# Votes for new distribution - Second try - iTokenAddVoteFor_corr_1
iTokenAddVoteFor_corr_1 = models.FloatField(
doc="Individual votes for assignment to player 1 in new distribution. Second try.",
# initial=0,
min=0,
max=C.TOKEN_ADD_TOTAL)
iTokenAddVoteFor_corr_2 = models.FloatField(
doc="Individual votes for assignment to player 2 in new distribution. Second try.",
# initial=0,
min=0,
max=C.TOKEN_ADD_TOTAL)
iTokenAddVoteFor_corr_3 = models.FloatField(
doc="Individual votes for assignment to player 3 in new distribution. Second try.",
# initial=0,
min=0,
max=C.TOKEN_ADD_TOTAL)
iTokenAddVoteFor_corr_4 = models.FloatField(
doc="Individual votes for assignment to player 4 in new distribution. Second try.",
# initial=0,
min=0,
max=C.TOKEN_ADD_TOTAL)
iTokenAddVoteFor_corr_5 = models.FloatField(
doc="Individual votes for assignment to player 5 in new distribution. Second try.",
# initial=0,
min=0,
max=C.TOKEN_ADD_TOTAL)
# Wealth für Final Distribution as Voted
WealthNewDis_1R = models.FloatField(doc="Wealth after one round in newly chosen distribution")
WealthNewDis_5R = models.FloatField(doc="Wealth after five rounds in newly chosen distribution")
# Chat times
Rej1_ChatStart = models.IntegerField(
doc="Start of first chat. Since epoch, in UTC",
null=True, default=-99) # old player.ChatDisProStart
Rej1corr_ChatStart = models.IntegerField(
doc="Start of second chat. Since epoch, in UTC",
null=True, default=-99) # old player.ChatDisProStartKorr
# Pages
class Before_Intro_WP(WaitPage):
""" Intro to rejection app.
Variable GroupAcknowledgement is defined here. """
# Note. GroupRank etc. cannot be calculated if this is in the same page.
@staticmethod
def after_all_players_arrive(group: Group):
print("------------------------------------- Start Rejection App ---------------------------------------------")
# Get GroupAcknowledgement
for p in group.get_players():
# GroupAcknowledgement has been calculated in redistribution/AckResultWP
p.group.GroupAcknowledgement = p.participant.vars.get("GroupAcknowledgement", 0)
define_group_rank(group)
define_start_token(group)
nickname(group) # Create nicknames for chat
class Rej_1_Intro(Page):
# TODO text must be adjusted here if there are no arguments.
template_name = 'rejection/rejection/Rej_1_Intro.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0
class Rej_2_Arg(Page):
""" Enter the argument """
template_name = 'rejection/rejection/Rej_2_Arg.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and \
player.session.vars['do_arguments_rejection']
# Timeout for arguments
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 {
"languageDE": 1 if settings.LANGUAGE_CODE == 'de' else 0,
"secondsTimerIsShown": player.session.config.get("secondsTimerIsShown",
settings.secondsTimerIsShown)
# 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
# If a person hasn't entered a valid distribution (timeout is automatically assumed here)
if (player.iTokenAddSuggestion_1 +
player.iTokenAddSuggestion_2 +
player.iTokenAddSuggestion_3 +
player.iTokenAddSuggestion_4 +
player.iTokenAddSuggestion_5 != C.TOKEN_ADD_TOTAL):
player.iTokenAddSuggestion_1 = player.iTokenAddSuggestion_2 = \
player.iTokenAddSuggestion_3 = player.iTokenAddSuggestion_4 = \
player.iTokenAddSuggestion_5 = -99
player.Rej_Arg = " (Zeit abgelaufen)"
# If a person has entered a valid distribution but a timeout happened when entering the argument
if ((player.iTokenAddSuggestion_1 +
player.iTokenAddSuggestion_2 +
player.iTokenAddSuggestion_3 +
player.iTokenAddSuggestion_4 +
player.iTokenAddSuggestion_5 == C.TOKEN_ADD_TOTAL) and timeout_happened):
player.Rej_Arg = player.Rej_Arg + " (Zeit abgelaufen)"
form_model = "player"
form_fields = ["iTokenAddSuggestion_1", "iTokenAddSuggestion_2",
"iTokenAddSuggestion_3", "iTokenAddSuggestion_4",
"iTokenAddSuggestion_5", "Rej_Arg"]
def error_message(player, values):
if sum([values["iTokenAddSuggestion_1"],
values["iTokenAddSuggestion_2"],
values["iTokenAddSuggestion_3"],
values["iTokenAddSuggestion_4"],
values["iTokenAddSuggestion_5"]]) != C.TOKEN_ADD_TOTAL:
return ("Die Summe der von Ihnen gewählten Verteilung beträgt nicht" + str(
C.TOKEN_ADD_TOTAL) + "Token!")
# FOR PRESENTATION ONLY!!! !
# @staticmethod
# def before_next_page(player, timeout_happened):
# player.iTokenAddSuggestion_1 = C.TOKEN_ADD_TOTAL
# player.iTokenAddSuggestion_2 = 0
# player.iTokenAddSuggestion_3 = 0
# player.iTokenAddSuggestion_4 = 0
# player.iTokenAddSuggestion_5 = 0
# player.Rej_Arg = "xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx " \
# "xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx " \
# "xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx" \
# " xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xx"
class Rej_3_RateBestArg(Page):
""" Acceptance of arguments """
template_name = 'rejection/rejection/Rej_3_RateBestArg.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and \
player.session.vars['do_arguments_rejection'] \
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("Rej_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.Rej_ArgAkz_1 = -98
elif player.GroupRank == 2:
player.Rej_ArgAkz_2 = -98
elif player.GroupRank == 3:
player.Rej_ArgAkz_3 = -98
elif player.GroupRank == 4:
player.Rej_ArgAkz_4 = -98
elif player.GroupRank == 5:
player.Rej_ArgAkz_5 = -98
class Rej_3_RateBestArg2(Page):
""" Vote for best argument """
template_name = 'rejection/rejection/Rej_3_RateBestArg2.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and player.session.vars['do_arguments_rejection']
form_model = "player"
@staticmethod
def get_form_fields(player):
field_list = []
for i in range(1, 6):
if player.GroupRank != i:
field_list.append("Rej_ArgBest_" + str(i))
return field_list
class WaitForArgs(WaitPage):
""" Wait for the arguments of the group members """
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and player.session.vars['do_arguments_rejection']
class WaitForVotes(WaitPage):
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and player.session.vars['do_arguments_rejection']
class Rej_4_BestUebersicht(Page):
""" Show results for acceptances and votes for best argument """
template_name = 'rejection/rejection/Rej_4_BestUebersicht.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and \
player.session.vars['do_arguments_rejection']
@staticmethod
def vars_for_template(player):
calc_best_arg(player.group, "Rej")
# player.group.calc_acc_arg("Rej") # Not used in this experiment
class Rej_5_Chat_DistributionProcedure_0WP_Before(WaitPage):
""" Waitpage before Chat """
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0
@staticmethod
def after_all_players_arrive(group: Group):
for p in group.get_players():
p.Rej1_ChatStart = int(round(time.time()))
class Rej_5_Chat_DistributionProcedure_1(Page):
""" Chat to find a new distribution """
template_name = 'rejection/rejection/Rej_5_Chat_DistributionProcedure_1.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0
form_model = "player"
form_fields = ["iTokenAddVoteFor_1", "iTokenAddVoteFor_2",
"iTokenAddVoteFor_3", "iTokenAddVoteFor_4",
"iTokenAddVoteFor_5"]
def error_message(player, values):
if sum([values["iTokenAddVoteFor_1"],
values["iTokenAddVoteFor_2"],
values["iTokenAddVoteFor_3"],
values["iTokenAddVoteFor_4"],
values["iTokenAddVoteFor_5"]]) != C.TOKEN_ADD_TOTAL:
return ("Die Summe der von Ihnen gewählten Verteilung beträgt nicht " + str(
C.TOKEN_ADD_TOTAL) + " Token!")
# For presentation only!!!!
# @staticmethod
# def vars_for_template(player):
# player.iTokenAddSuggestion_1 = C.TOKEN_ADD_TOTAL
# player.iTokenAddSuggestion_2 = 0
# player.iTokenAddSuggestion_3 = 0
# player.iTokenAddSuggestion_4 = 0
# player.iTokenAddSuggestion_5 = 0
# player.Rej_Arg = "xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx " \
# "xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx " \
# "xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx" \
# " xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xx"
# FOR PRESENTATION ONLY!!
# @staticmethod
# def before_next_page(player, timeout_happened):
# player.iTokenAddVoteFor_1 = 10
# player.iTokenAddVoteFor_2 = 10
# player.iTokenAddVoteFor_3 = 0
# player.iTokenAddVoteFor_4 = 0
# player.iTokenAddVoteFor_5 = 0
class Rej_5_Chat_DistributionProcedure_2WP_After(WaitPage):
""" Chat to find a new distribution.
If a person enters their assignments but needs to wait for the other participants. """
template_name = 'rejection/rejection/Rej_5_Chat_DistributionProcedure_2WP_After.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0
@staticmethod
def after_all_players_arrive(group: Group):
abzahlen(group, Correction="")
class Rej_6_Voting_Results(Page):
template_name = 'rejection/rejection/Rej_6_Voting_Results.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0
@staticmethod
def vars_for_template(player):
if player.group.found_new_distribution == 1:
return dict(
languageDE=1 if settings.LANGUAGE_CODE == 'de' else 0,
Token1=str(player.group.TokenAdd_New_1),
Token2=str(player.group.TokenAdd_New_2),
Token3=str(player.group.TokenAdd_New_3),
Token4=str(player.group.TokenAdd_New_4),
Token5=str(player.group.TokenAdd_New_5)
)
else:
return dict(
languageDE=1 if settings.LANGUAGE_CODE == 'de' else 0,
Token1=-99,
Token2=-99,
Token3=-99,
Token4=-99,
Token5=-99
)
class Rej_7_Chat_DistributionProcedureKorr_0WP_Before(WaitPage):
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and player.group.found_new_distribution == 0
@staticmethod
def after_all_players_arrive(group: Group):
for p in group.get_players():
p.Rej1corr_ChatStart = int(round(time.time()))
class Rej_8_Chat_DistributionProcedureKorr_1(Page):
""" Second chat to find a new distribution - 1 minute more to enter the correct numbers """
template_name = 'rejection/rejection/Rej_7_Chat_DistributionProcedureKorr_1.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and player.group.found_new_distribution == 0
form_model = "player"
form_fields = ["iTokenAddVoteFor_corr_1", "iTokenAddVoteFor_corr_2",
"iTokenAddVoteFor_corr_3", "iTokenAddVoteFor_corr_4",
"iTokenAddVoteFor_corr_5"]
def error_message(player, values):
if sum([values["iTokenAddVoteFor_corr_1"], values["iTokenAddVoteFor_corr_2"],
values["iTokenAddVoteFor_corr_3"],
values["iTokenAddVoteFor_corr_4"], values["iTokenAddVoteFor_corr_5"]]) != C.TOKEN_ADD_TOTAL:
return ("Die Summe der von Ihnen gewählten Verteilung beträgt nicht " + str(
C.TOKEN_ADD_TOTAL) + " Token!")
class Rej_8_Chat_DistributionProcedureKorr_WP_After(WaitPage):
template_name = 'rejection/rejection/Rej_7_Chat_DistributionProcedureKorr_WP_After.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and player.group.found_new_distribution == 0
@staticmethod
def after_all_players_arrive(group: Group):
abzahlen(group, Correction="Corr")
class Rej_8_Voting_ResultsKorr(Page):
template_name = 'rejection/rejection/Rej_8_Voting_ResultsKorr.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 and player.group.found_new_distribution == 0
@staticmethod
def vars_for_template(player):
if player.group.found_new_distribution_corr == 1:
# Send as string, otherwise the javascript won't take the commas
return dict(
languageDE=1 if settings.LANGUAGE_CODE == 'de' else 0,
Token1=str(player.group.TokenAdd_New_corr_1),
Token2=str(player.group.TokenAdd_New_corr_2),
Token3=str(player.group.TokenAdd_New_corr_3),
Token4=str(player.group.TokenAdd_New_corr_4),
Token5=str(player.group.TokenAdd_New_corr_5)
)
else:
return dict(
languageDE=1 if settings.LANGUAGE_CODE == 'de' else 0,
Token1=-99,
Token2=-99,
Token3=-99,
Token4=-99,
Token5=-99
)
class Rej_9_Rounds1(Page):
template_name = 'rejection/rejection/Rej_9_Rounds1.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 \
and (player.group.found_new_distribution == 1 or player.group.found_new_distribution_corr == 1)
@staticmethod
def vars_for_template(player):
return results_graph(player.group)
class Rej_9_Rounds2(Page):
template_name = 'rejection/rejection/Rej_9_Rounds2.html'
@staticmethod
def is_displayed(player):
return player.group.GroupAcknowledgement == 0 \
and (player.group.found_new_distribution == 1 or player.group.found_new_distribution_corr == 1)
@staticmethod
def vars_for_template(player):
return results_graph(player.group)
page_sequence = [
Before_Intro_WP, # Can be taken out when passing through.
Rej_1_Intro,
Rej_2_Arg,
WaitForArgs,
Rej_3_RateBestArg,
Rej_3_RateBestArg2,
WaitForVotes,
Rej_4_BestUebersicht,
Rej_5_Chat_DistributionProcedure_0WP_Before,
Rej_5_Chat_DistributionProcedure_1,
Rej_5_Chat_DistributionProcedure_2WP_After,
Rej_6_Voting_Results,
Rej_7_Chat_DistributionProcedureKorr_0WP_Before,
Rej_8_Chat_DistributionProcedureKorr_1,
Rej_8_Chat_DistributionProcedureKorr_WP_After,
Rej_8_Voting_ResultsKorr,
Rej_9_Rounds1,
Rej_9_Rounds2
]