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, ]