# from otree.api import * # import numpy as np # import random # import GPD # from db.database import create_database_tables # from db.crud import get_ancestor_players, add_player_history # doc = """ # This is an intergenerational "Prisoner's Dilemma". Two players are asked separately # whether they want to cooperate or defect. Their choices directly determine the # payoffs. # """ # ## Random seed # # delta # # survey # class C(BaseConstants): # NAME_IN_URL = 'GPD' # INSTRUCTIONS_TEMPLATE = 'GPD/instructions.html' # INSTRUCTIONS_SURVEY = 'GPD/instructions-survey.html' # PAYOFF_CC = 65 # PAYOFF_CD = 10 # PAYOFF_DC = 100 # PAYOFF_DD = 35 # PAYOFF_I = 5 # interpretation payoff # NUM_ROUNDS = 50 # C_TAG = '1' # label for cooperation # D_TAG = '2' # label for defection # num_gen = 2 # num_dynasty = 5 # PLAYERS_PER_GROUP = num_gen*2 # delta = 50 # gamma = 1 # inactive_color = ["#FAE5CB", "#CBE6FA"] # active_color = ["SandyBrown", "LightSkyBlue"] # history_color = active_color # outcome_color = ["Orange", "DeepSkyBlue"] # button_color = outcome_color # hover_color = ["#FE9900", "#00C4FE"] # genfile = 'gen' # groupfile = 'advice' # history = [{}, # {'P1': {'period': '1', 'name_opp_action': C_TAG, 'opp_cooperate': True}}, # {'P1': {'period': '1', 'name_opp_action': D_TAG, 'opp_cooperate': False}} # ] # questions for advice survey # class Subsession(BaseSubsession): # dice_roll = models.IntegerField(initial=-10) # gen_number = models.IntegerField(initial=-10) # which generation this round corresponds to # first_period = models.BooleanField(initial=True) # True if it is the first period of a match # last_period = models.BooleanField(initial=False) # True if it is the last period of a match # period_number = models.IntegerField(initial=1) # current_gen = models.IntegerField(initial=1) # num_questions = models.IntegerField(initial = 0) # delta = models.IntegerField(initial = C.delta) # stop_session = models.BooleanField(initial = False) # dynasty_session = models.IntegerField(initial = -1) # payoff_round = models.IntegerField(initial = -1) # round = models.IntegerField(initial = -1) # class Group(BaseGroup): # number = models.IntegerField() # dynasty = models.IntegerField(initial = -1) # class Player(BasePlayer): # # Game fields # final_period = models.BooleanField(initial = False) # ready to receive payoff, leave experiment # action = models.StringField(initial=C.D_TAG) # cooperate = models.BooleanField( # choices=[[True, C.C_TAG], [False, C.D_TAG]], # doc="""This player's decision""", # widget=widgets.RadioSelect, # initial= False, # ) # react = models.BooleanField( # choices=[[True, C.C_TAG], [False, C.D_TAG]], # doc="""This player's decision""", # widget=widgets.RadioSelect, # initial= False,) # session_gen = models.IntegerField(initial = 1) # gen = models.IntegerField(initial = 1) # # advice # ancestor_advice = models.LongStringField(label="Advice to you", default="") # ancestor_participant_id = models.IntegerField(default=0) # g_advice = models.LongStringField(initial = '',label="Advice:") # # ID fields # session_end = models.BooleanField(initial = False) # last_gen = models.BooleanField(initial = False) # side = models.BooleanField(initial = False) # stage = models.IntegerField(initial=-1) # # Survey fields # r_survey = models.BooleanField(initial = True) # interpreting received advice # interpret = models.BooleanField() # clear = models.BooleanField(label="Does the advice clearly indicate what to do in this scenario?") # g_responses = models.StringField(initial = '') # # NEW FIELD TO CORRECT WAITING # released_to_endwait = models.BooleanField(initial = False) # # FUNCTIONS # def creating_session(subsession: Subsession): # if len(subsession.get_groups())>C.num_dynasty: # ValueError("Too many groups") # nround = subsession.round_number # current round # ## ROLL Round incrementing # if subsession.session.config['gen_end']: # delta = 1-(1-C.delta)/(1+C.gamma) # else: # delta = C.delta # # draw random number for each round # seed = random.seed(a=None, version=2) # random.seed(a=seed, version=2) # extra_rounds = C.num_dynasty*2+len(C.history) # accounts for survey question rounds # dice_rolls = np.random.randint(1, 101, C.NUM_ROUNDS+1).tolist() # while sum(i > delta for i in dice_rolls[0:(C.NUM_ROUNDS-len(C.history)-extra_rounds)]) < C.num_gen: # dice_rolls = np.random.randint(1, 101, C.NUM_ROUNDS+1).tolist() # subsession.session.vars['dice_rolls'] = dice_rolls # roll = -1 # if nround == 1: # subsession.period_number = 1 # subsession.round = 1 # roll = dice_rolls[1] # else: # if subsession.in_round(nround-1).last_period: # subsession.period_number = 1 # subsession.round = 1 # else: # subsession.period_number = subsession.in_round(nround-1).period_number + 1 # subsession.round = subsession.in_round(nround-1).round + 1 # if subsession.period_number == 3: # subsession.round = subsession.round - 1 # ## player advice/incrementing # # initialize roles and draw advice # players = subsession.get_players() # subsession.dynasty_session = subsession.session.config['dynasty_session'] # if nround == 1: # subsession.group_randomly() # subsession.period_number = 1 # subsession.current_gen = 1 # # OLDER CODE # # try: # # ancestors = get_ancestor_players(subsession.dynasty_session) # # except: # # ancestors = [] # # print('No Ancestors') # # finally: # # dynasties = list(range(0, C.num_dynasty)) # # dynasty_ages = list(range(0, C.num_dynasty)) # # num_groups = len(subsession.get_groups()) # # print('Dynasty') # # for dynasty in dynasties: # # dynasty_ancestors = [ancestor for ancestor in ancestors if ancestor.dynasty == dynasty] # # try: # # age = max([ancestor.gen for ancestor in dynasty_ancestors]) # generation of dynasty # # except: # # age = 0 # # dynasty_ages[dynasty] = age # # for n in range(num_groups,C.num_dynasty): # # long_dynasties = [i for i in range(0,len(dynasties)) if dynasty_ages[i] == max(dynasty_ages)] # maximum length dynasties # # excess = max(long_dynasties) # dynasties to remove # # dynasties.remove(dynasties[excess]) # remove first dynasty reaching this value # # dynasty_ages.remove(dynasty_ages[excess]) # # ancestor_players = [ancestor for ancestor in ancestors if ancestor.dynasty in dynasties] # # THIS CODE ATTEMPTS TO FIX THE ISSUE OF STARTING AT A LATER GENERATION AND PULLING EARLIER, NON-EXISTENT DATA # dynasties = list(range(0, C.num_dynasty)) # dynasty_ages = [0] * C.num_dynasty # num_groups = len(subsession.get_groups()) # dynasties = dynasties[:num_groups] # ancestor_players = [] # create_database_tables() # #subsession.group_randomly() # # randomly assign groups, generations, dynasty # num = 0 # for group in subsession.get_groups(): # gens = [] # group.number = num # group.dynasty = dynasties[num] # group_gen = dynasty_ages[num] # for i in range(1,C.num_gen+1): # gens = gens + [i, i] # random.shuffle(gens) # num += 1 # group_players = group.get_players() # for p, gen in zip(group_players, gens): # p.session_gen = gen # for gen in range(1,C.num_gen+1): # gen_players = [player for player in group_players if player.session_gen == gen] # random.shuffle(gen_players) # sides = [True, False] # for p, side in zip(gen_players, sides): # p.side = side # p.session_end = (p.session_gen == C.num_gen) # for p in group_players: # p.participant.vars['r_advice']='' # p.participant.vars['interprets'] = [] # p.participant.vars['g_advice'] = '' # p.participant.vars['asurvey'] = [] # p.participant.vars['match_history'] = {} # p.participant.vars['done'] = False # p.participant.vars['rfirst'] = (p.session_gen > 1) # # NEW FIELD TO CORRECT WAITING # p.released_to_endwait = False # if group_gen > 0: # print(ancestor_players) # ancestor_options = [ancestor for ancestor in ancestor_players if (ancestor.dynasty == group.dynasty and ancestor.gen == group_gen)] # for p in group_players: # if p.session_gen == 1: # print("Group dynasty:"+str(group.dynasty)) # ancestor = random.choice(ancestor_options) # ancestor_options.remove(ancestor) # p.gen = ancestor.gen + 1 # p.side = ancestor.side # get_tag(p) # p.ancestor_participant_id = ancestor.participant_id # if ancestor.g_advice == '': # ValueError("Advice not passed") # p.participant.vars['asurvey'] = string_to_bool(ancestor.g_survey) # if p.participant.vars['asurvey'] == []: # ValueError("asurvey empty") # p.participant.vars['r_advice'] = ancestor.g_advice # else: # first group in dynasty # for p in group_players: # if p.session_gen == 1: # p.participant.vars['rfirst'] = False # p.gen = p.session_gen # get_tag(p) # p.participant.vars['asurvey'] = [] # p.participant.vars['r_advice'] = '' # for p in players: # identify later generations # p.stage = 0 # if p.session_gen > 1: # p.stage = -1 # p.gen = get_predecessor(p).gen + 1 # get_tag(p) # # continue advice/ increment player attributes # subsession.num_questions = len(C.history) # subsession.payoff_round = nround # if subsession.period_number != 2 and nround >= 3: # roll = dice_rolls[nround - 1] # roll1 = -1 # if subsession.period_number == 3: # roll1 = subsession.in_round(nround -2).dice_roll # if roll1 > delta or roll > delta: # subsession.last_period = True # if roll1 > delta: # subsession.payoff_round = nround - 2 # if nround > 1: # subsession.group_like_round(1) # for g in subsession.get_groups(): # g.dynasty = g.in_round(nround - 1).dynasty # g.number = g.in_round(nround - 1).number # # increment session generation attributes # if subsession.in_round(nround - 1).last_period: # new generation # gen = subsession.in_round(nround - 1).current_gen + 1 # subsession.first_period = True # else: # same generation # gen = subsession.in_round(nround - 1).current_gen # subsession.first_period = False # subsession.current_gen = gen # for p in players: # if p.session_end and p.session.config['gen_end']: # p.last_gen = True # p.side = p.in_round(nround - 1).side # p.gen = p.in_round(nround - 1).gen # get_tag(p) # p.session_gen = p.in_round(nround - 1).session_gen # p.session_end = (p.session_gen == C.num_gen) # #active_players = [player for player in players if player.session_gen == subsession.current_gen] # p.participant.vars['wait'] = False # if p.session_gen == subsession.current_gen: # Pass advice in later generations (inheritance already random from role) # p.stage = 0 # if p.session_gen < p.subsession.current_gen: # if retired, recall advice, survey generations, increment stage # p.stage = p.in_round(p.round_number - 1).stage + 1 # if p.stage <= p.subsession.num_questions: # p.r_survey = p.participant.vars['rfirst'] # else: # p.r_survey = not p.participant.vars['rfirst'] # if p.session_gen > p.subsession.current_gen: # p.stage = -1 # p.participant.vars['wait'] = True # subsession.delta = delta # subsession.dice_roll = roll # def get_tag(player: Player): # identify opponent # side =player.side # tag = str(player.gen) # if side: # tag += 'A' # else: # tag += 'B' # player.participant.vars['tag'] = tag # def successor_tag(player: Player): # identify opponent # side =player.side # tag = str(player.gen + 1) # if side: # tag += 'A' # else: # tag += 'B' # return(tag) # def predecessor_tag(player: Player): # identify opponent # side =player.side # tag = str(player.gen - 1) # if side: # tag += 'A' # else: # tag += 'B' # return(tag) # def get_opponent(player: Player): # identify opponent # for j in player.get_others_in_group(): # if player.session_gen == j.session_gen: # return j # def get_predecessor(player: Player): # identify predecessor # for j in player.get_others_in_group(): # if player.session_gen == j.session_gen + 1 and player.side == j.side: # return j # def get_successor(player: Player): # identify successor # for j in player.get_others_in_group(): # if player.session_gen == j.session_gen - 1 and player.side == j.side: # return j # def bool_to_string(bool_list): # converts boolean lists to strings to pass between players # string_list = [str(int(elem)) for elem in bool_list] # return ','.join(string_list) # def string_to_bool(comma_string): # converts comma strings to boolean list # return [bool(int(elem)) for elem in comma_string.split(',')] # def sort_gresponse(player: Player): # N = player.subsession.num_questions # if player.session_gen == 1: # return player.participant.vars['interprets'][0: N] # if player.participant.vars['rfirst']: # return player.participant.vars['interprets'][N:2 * N] # else: # return player.participant.vars['interprets'][0: N] # def sort_rresponse(player: Player): # N = player.subsession.num_questions # if player.session_gen == 1: # ValueError("No received advice") # if player.last_gen: # return player.participant.vars['interprets'][0: N] # if player.participant.vars['rfirst']: # return player.participant.vars['interprets'][0: N] # else: # return player.participant.vars['interprets'][N:2 * N] # def r_advice_score(player: Player): # score points for received advice # predecessor_resp = player.participant.vars['asurvey'] # r_responses = sort_rresponse(player) # num_correct = len([i for i in range(0,len(r_responses)) if r_responses[i] == predecessor_resp [i]]) # count matching interpretations # return num_correct*C.PAYOFF_I # # def set_payoffs(group: Group): # # for p in group.get_players(): # # if p.stage == 0: # # j = get_opponent(p) # # payoff_matrix = { # # (False, True): C.PAYOFF_DC, # # (True, True): C.PAYOFF_CC, # # (False, False): C.PAYOFF_DD, # # (True, False): C.PAYOFF_CD, # # } # # p.payoff = payoff_matrix[(p.cooperate,j.cooperate)] # # if p.stage > 0 and not p.participant.vars['done']: # # p.payoff = 0 # # TO COMPUTE PAYOFFS FROM THE LAST ROUND OF THE PD # def set_payoffs(group: Group): # for p in group.get_players(): # if p.stage == 0: # if p.subsession.last_period: # j = get_opponent(p) # payoff_matrix = { # (False, True): C.PAYOFF_DC, # (True, True): C.PAYOFF_CC, # (False, False): C.PAYOFF_DD, # (True, False): C.PAYOFF_CD, # } # p.payoff = payoff_matrix[(p.cooperate,j.cooperate)] # else: # p.payoff = 0 # if p.stage > 0 and not p.participant.vars['done']: # p.payoff = 0 # def total_pd_earnings_so_far(player: Player): # return sum(r.payoff for r in player.in_all_rounds() if r.stage == 0) # #p.participant.vars['pd_points'] += p.points # #p.participant.payoff = round(p.participant.vars['pd_points'] * group.session.config['pd_conversion'], 2) # #p.participant.vars['pd_dollars'] = p.participant.payoff # # p.save() # # PAGES # #if p.session_gen > 1: # # ancestor = get_predecessor(p) # # p.ancestor_session_id = ancestor.session_id # # p.ancestor_participant_id = ancestor.participant_id # #if p.stage == 0: # # p.participant.vars['r_advice'] = ancestor.participant.vars['g_advice'] # #if p.stage > 0: # # p.participant.vars['asurvey'] = ancestor.g_responses # class Introduction(Page): # # @staticmethod # # def is_displayed(player: Player): # # N = player.subsession.num_questions # # return (player.subsession.first_period and player.stage == 0) or player.stage == 1 or (player.stage == N+1 and not player.participant.vars['wait']) # @staticmethod # def is_displayed(player: Player): # N = player.subsession.num_questions # # Always show at the very start # if player.subsession.first_period and player.stage == 0: # return True # # First intro to survey (everyone) # if player.stage == 1: # return True # # Second intro (ONLY for generations > 1) # if player.session_gen > 1: # return player.stage == N + 1 and not player.participant.vars['wait'] # return False # @staticmethod # def vars_for_template(player: Player): # if player.session_gen > 1: # pred = get_predecessor(player) # player.participant.vars['r_advice'] = pred.participant.vars['g_advice'] # player.ancestor_participant_id = pred.participant_id # # ATTEMPTING TO FIX THE ISSUE OF THE FIRST GENERATION BEING ASKED TO INTERPRET NON-EXISTENT RECEIVED ADVICE # if player.session_gen == 1: # player.r_survey = False # try: # if player.r_survey: # advice = player.participant.vars['r_advice'] # else: # advice = player.participant.vars['g_advice'] # except: # advice = '' # return { # 'first_period': player.subsession.first_period, # 'wait': player.participant.vars['wait'], # 'r_advice': player.participant.vars['r_advice'], # 'rsurvey':player.r_survey, # 'survey_instr': not (player.stage == 0), # 'gam_gen': player.subsession.current_gen, # 'gen': player.session_gen, # 'first_gen': player.session_gen==1, # 'delta':player.subsession.delta, # 'pred_tag': predecessor_tag(player), # 'advice':advice, # 'tag': player.participant.vars['tag'], # 'opp_tag': get_opponent(player).participant.vars['tag'], # 'succ_tag': successor_tag(player), # 'succ_opp_tag':successor_tag(get_opponent(player)), # 'stage':player.stage, # 'round': player.subsession.round_number, # 'per': player.subsession.round, # 'last_gen':C.num_gen, # 'end2':(player.session_gen == C.num_gen), # 'end':player.session_end, # 'payI': C.PAYOFF_I, # } # class React(Page): # form_model = 'player' # form_fields = ['react'] # @staticmethod # def is_displayed(player: Player): # return player.stage == 0 and (player.subsession.period_number == 2 or player.subsession.period_number == 3) # @staticmethod # def vars_for_template(player: Player): # n = player.subsession.round_number # scenario = player.subsession.period_number - 1 # if scenario == 1: # p_cooperate = player.in_round(n-1).cooperate # opp_cooperate = True # #history = {'P1': {'period': '1', 'cooperate':p_cooperate, 'name_action': player.in_round(n-1).action, # #'opp_cooperate':opp_cooperate,'name_opp_action': 1}} # else: # p_cooperate = player.in_round(n-2).cooperate # opp_cooperate = False # #history = {'P1': {'period': '1', 'cooperate':p_cooperate, 'name_action': player.in_round(n-1).action, # #'opp_cooperate':opp_cooperate,'name_opp_action': 2}} # return { # 'round_number': player.subsession.round_number, # 'history_Ccolor': "style=\"background-color:"+C.history_color[True]+"\"", # 'history_Dcolor': "style=\"background-color:"+C.history_color[False]+"\"", # 'Dbutton_color': C.button_color[False], # 'Cbutton_color': C.button_color[True], # 'Dbutton_hover': C.hover_color[False], # 'Cbutton_hover': C.hover_color[True], # 'session_end':player.session_end, # 'group': player.group, # 'version':scenario, # 'my_decision':p_cooperate, # 'opp_cooperate':opp_cooperate, # 'my_color':"style=\"background:"+C.inactive_color[p_cooperate]+";\"", # 'opp_color':"style=\"background:"+C.inactive_color[opp_cooperate]+";\"", # 'outcome_color':"style=\"background:"+C.outcome_color[opp_cooperate]+";\"", # 'period': player.subsession.round, # 'interprets': player.participant.vars['interprets'], # 'asurvey': player.participant.vars['asurvey'], # 'first_gen': player.session_gen == 1, # 'first_period': player.subsession.first_period, # 'history': [], # 'delta':player.subsession.delta, # 'r_advice': player.participant.vars['r_advice'], # 'gam_gen': player.subsession.current_gen, # 'CTAG':C.C_TAG, # 'DTAG':C.D_TAG, # 'gen': player.session_gen, # 'pred_tag': predecessor_tag(player), # 'tag': player.participant.vars['tag'], # 'opp_tag':get_opponent(player).participant.vars['tag'], # 'round': player.subsession.round_number, # 'session':player.session_id, # } # class Decision(Page): # form_model = 'player' # form_fields = ['cooperate'] # @staticmethod # def is_displayed(player: Player): # return player.stage == 0 and (player.subsession.period_number != 2 and player.subsession.period_number != 3) # @staticmethod # def vars_for_template(player: Player): # return { # 'round_number': player.subsession.round_number, # 'history_Ccolor': "style=\"background-color:"+C.history_color[True]+"\"", # 'history_Dcolor': "style=\"background-color:"+C.history_color[False]+"\"", # 'Dbutton_color': C.button_color[False], # 'Cbutton_color': C.button_color[True], # 'Dbutton_hover': C.hover_color[False], # 'Cbutton_hover': C.hover_color[True], # 'period': player.subsession.round, # 'interprets': player.participant.vars['interprets'], # 'asurvey': player.participant.vars['asurvey'], # 'first_gen': player.session_gen == 1, # 'first_period': player.subsession.first_period, # 'history': player.participant.vars['match_history'], # 'delta':player.subsession.delta, # 'r_advice': player.participant.vars['r_advice'], # 'CTAG':C.C_TAG, # 'DTAG':C.D_TAG, # 'pred_tag': predecessor_tag(player), # 'tag': player.participant.vars['tag'], # 'opp_tag':get_opponent(player).participant.vars['tag'], # 'session':player.session_id, # } # class Survey(Page): # form_model = 'player' # form_fields = ['interpret','clear'] # @staticmethod # def is_displayed(player: Player): # # Only show Survey while the player is in the interpretation stages. # N = player.subsession.num_questions # if player.session_gen == 1 or (player.session.config['gen_end'] and player.session_end): # num_q = N # else: # num_q = 2 * N # return 0 < player.stage <= num_q # @staticmethod # def vars_for_template(player: Player): # history = C.history # N = player.subsession.num_questions # question = (player.stage-1) % N # r_survey = player.r_survey # if player.session_gen == 1: # r_survey = False # player.r_survey = False # if r_survey: # advice = player.participant.vars['r_advice'] # r_advice survey # active_tag = player.participant.vars['tag'] # opp_tag = get_opponent(player).participant.vars['tag'] # else: # advice = player.participant.vars['g_advice'] # g_advice survey # active_tag = successor_tag(player) # opp_tag = successor_tag(get_opponent(player)) # if player.session_gen == 1 or (player.session.config['gen_end'] and player.session_end): # num_q = N # else: # num_q =2*N # if player.stage == num_q: # player.participant.vars['wait'] = True # historyq = history[question] # player.g_advice = player.participant.vars['g_advice'] # return { # 'history_Ccolor': "style=\"background-color:"+C.history_color[True]+"\"", # 'history_Dcolor': "style=\"background-color:"+C.history_color[False]+"\"", # 'Dbutton_color': C.button_color[False], # 'Cbutton_color': C.button_color[True], # 'Dbutton_hover': C.hover_color[False], # 'Cbutton_hover': C.hover_color[True], # 'advice': advice, # 'tag':player.participant.vars['tag'], # 'active_tag':active_tag, # 'active_opp_tag':opp_tag, # 'pred_tag': predecessor_tag(player), # 'succ_tag': successor_tag(player), # 'first_gen': player.session_gen == 1, # 'gadvice': player.g_advice, # 'r': r_survey, # 'round': len(historyq)+1, # 'asurvey': player.participant.vars['asurvey'], # 'rfirst': player.participant.vars['rfirst'], # 'history':historyq, # 'first':historyq == {}, # 'delta':player.subsession.delta, # 'CTAG':C.C_TAG, # 'DTAG':C.D_TAG, # 'stage':player.stage, # 'q':question, # 'num_q':num_q # } # # @staticmethod # # def before_next_page(player, timeout_happened): # # player.participant.vars['interprets'].append(player.interpret) # # NEW CODE TO FIX WAITING ISSUE # @staticmethod # def before_next_page(player, timeout_happened): # player.participant.vars['interprets'].append(player.interpret) # N = player.subsession.num_questions # # Release gen1 to EndWait once gen2 finishes interpreting received advice # if player.session_gen > 1: # finished_received = ( # (player.participant.vars['rfirst'] and player.stage == N) or # ((not player.participant.vars['rfirst']) and player.stage == 2 * N) # ) # if finished_received: # predecessor = get_predecessor(player) # if predecessor is not None: # predecessor.released_to_endwait = True # # Send gen2 to EndOfGame once gen2 is fully done # if player.session_end: # num_q = N if (player.session_gen == 1 or (player.session.config['gen_end'] and player.session_end)) else 2 * N # if player.stage == num_q: # player.final_period = True # class Results1WaitPage(WaitPage): # @staticmethod # def is_displayed(subsession: Subsession): # return subsession.period_number == 3 # @staticmethod # def after_all_players_arrive(subsession: Subsession): # n = subsession.round_number # for group in subsession.get_groups(): # for p in group.get_players(): # opp = get_opponent(p) # p.cooperate = p.react # if opp.in_round(n-2).cooperate: # p.cooperate = p.in_round(n-1).react # class ResultsWaitPage(WaitPage): # wait_for_all_groups = True # template_name = 'GPD/ResultsWaitPage.html' # @staticmethod # def is_displayed(player: Player): # return player.stage == 0 and player.subsession.period_number != 2 # @staticmethod # def after_all_players_arrive(subsession: Subsession): # for group in subsession.get_groups(): # n = subsession.round_number # if group.subsession.period_number == 3: # for p in group.get_players(): # opp = get_opponent(p) # p.cooperate = p.react # if opp.in_round(n - 2).cooperate: # p.cooperate = p.in_round(n - 1).react # set_payoffs(group) # round = str(group.subsession.round) # N = group.subsession.num_questions # for p in group.get_players(): # if p.participant.vars['done']: # continue # if p.stage < 0: # continue # if p.stage == 0: # active players # opp = get_opponent(p) # if p.cooperate: # p.action = C.C_TAG # if opp.cooperate: # opp.action = C.C_TAG # if p.subsession.round_number <= p.subsession.payoff_round: # p.participant.vars['match_history']['P' + round] = { # 'period': round, # 'cooperate':p.cooperate, # 'name_action': p.action, # 'opp_cooperate':opp.cooperate, # 'name_opp_action': opp.action # } # if p.subsession.last_period and p.session_gen>1: # predecessor = get_predecessor(p) # predecessor.payoff += p.payoff # continue # # SURVEY CALCULATIONS # # calculate Gdone = predecssor done given advice survey # if p.session_gen > 1: # num_question = 2*N # predecessor = get_predecessor(p) # if predecessor.participant.vars['rfirst']: # Gdone = (predecessor.stage >= 2*N) # else: # Gdone = (predecessor.stage >= N) # else: # session_gen == 1 # Gdone = True # if p.session_gen == 1: # num_question = N # p.participant.vars['rpoints'] = 0 # if p.session_gen != 1: # # has receiver advice # # calculate Rdone, if current player finished received advice survey # if p.participant.vars['rfirst']: # Rdone = (p.stage >= N) # else: # Rdone = (p.stage >= 2*N) # # if Rdone and Gdone: # # if p.session_gen > 1: # # p.participant.vars['asurvey'] = sort_gresponse(predecessor) # # # full responses to both surveys, calculate # # p.participant.vars['rpoints'] = r_advice_score(p) # # if p.session_gen > 1: # # predecessor.participant.vars['gpoints'] = p.participant.vars['rpoints'] # # predecessor.final_period = predecessor.participant.vars['wait'] # # NEW CODE TO FIX WAITING ISSUE # if Rdone and Gdone: # if p.session_gen > 1: # p.participant.vars['asurvey'] = sort_gresponse(predecessor) # p.participant.vars['rpoints'] = r_advice_score(p) # if p.session_gen > 1: # predecessor.participant.vars['gpoints'] = p.participant.vars['rpoints'] # if p.session_end: # p.participant.vars['gpoints'] = 0 # if p.session.config['gen_end']: # num_question = N # p.g_responses = '' # if p.stage >= num_question:# last gen done when survey done # p.final_period = True # p.subsession.stop_session = True # for p in group.get_players(): # if p.subsession.stop_session: # p.payoff += p.participant.vars['gpoints'] + p.participant.vars['rpoints'] # payoff from interpreting # @staticmethod # def vars_for_template(player: Player): # advice = player.participant.vars['r_advice'] # opp = get_opponent(player) # if player.stage == player.subsession.num_questions: # player.r_survey = not player.r_survey # if player.r_survey: # advice = player.participant.vars['r_advice'] # else: # advice = player.participant.vars['g_advice'] # return { # 'history_Ccolor': "style=\"background-color:"+C.history_color[True]+"\"", # 'history_Dcolor': "style=\"background-color:"+C.history_color[False]+"\"", # 'Dbutton_color': C.active_color[False], # 'Cbutton_color': C.active_color[True], # 'my_color':"style=\"background:"+C.inactive_color[player.cooperate]+";\"", # 'my_decision':player.cooperate, # 'first_gen': player.session_gen == 1, # 'asurvey':player.participant.vars['asurvey'], # 'survey':player.participant.vars['interprets'], # 'rsurvey':player.r_survey, # 'survey_instr': (player.stage == 0 or player.stage == player.subsession.num_questions), # 'advice':advice, # 'period': player.subsession.round, # 'final': player.final_period, # 'stage': player.stage, # 'end': player.session_end, # 'history': player.participant.vars['match_history'], # 'first_period': player.subsession.period_number==1, # 'r_advice': advice, # 'current_match': str(player.session_gen), # 'pred_tag': predecessor_tag(player), # 'tag': player.participant.vars['tag'], # 'opp_tag': opp.participant.vars['tag'], # 'succ_tag': successor_tag(player), # 'survey_instr': player.stage == player.subsession.num_questions and player.session_gen != 1, # 'succ_opp_tag': successor_tag(opp), # } # class Results1(Page): # @staticmethod # def is_displayed(player: Player): # return player.stage == 0 and player.subsession.period_number == 3 # @staticmethod # def vars_for_template(player: Player): # opponent = get_opponent(player) # n = player.subsession.round_number-2 # first round # return dict( # payoff_round = player.subsession.payoff_round, # round_number = player.subsession.round_number, # r2_decision=player.cooperate, # opponent=opponent, # same_choice=player.in_round(n).cooperate == opponent.in_round(n).cooperate, # period = player.subsession.round, # my_decision=player.in_round(n).cooperate, # opp_decision=opponent.in_round(n).cooperate, # roll = player.subsession.in_round(n).dice_roll, # history = player.participant.vars['match_history'], # history_Ccolor = "style=\"background-color:"+C.history_color[True]+"\"", # history_Dcolor = "style=\"background-color:"+C.history_color[False]+"\"", # Dbutton_color= C.active_color[False], # Cbutton_color= C.active_color[True], # my_color="style=\"background:"+C.inactive_color[player.in_round(n).cooperate]+";\"", # opp_color="style=\"background:"+C.inactive_color[opponent.in_round(n).cooperate]+";\"", # outcome_color="style=\"background:"+C.outcome_color[opponent.in_round(n).cooperate]+";\"", # tag = player.participant.vars['tag'], # opp_tag = get_opponent(player).participant.vars['tag'], # pred_tag = predecessor_tag(player), # first_gen= player.session_gen == 1, # last_per=player.subsession.last_period, # delta=player.subsession.delta, # payoff = player.in_round(n).payoff, # first_period = False, # r_advice = player.participant.vars['r_advice'], # g_advice=player.participant.vars['g_advice'], # per= player.subsession.round, # opp = get_opponent(player), # stage = player.stage,) # class Results(Page): # @staticmethod # def is_displayed(player: Player): # return player.stage == 0 and player.subsession.period_number >= 3 and player.subsession.payoff_round != player.subsession.round_number - 2 # @staticmethod # def vars_for_template(player: Player): # opponent = get_opponent(player) # p_cooperate = player.cooperate # opp_cooperate = opponent.cooperate # return dict( # opponent=opponent, # total_so_far=total_pd_earnings_so_far(player), # same_choice=p_cooperate == opp_cooperate, # period = player.subsession.round, # my_decision=p_cooperate, # opp_decision=opp_cooperate, # roll = player.subsession.dice_roll, # history = player.participant.vars['match_history'], # history_Ccolor = "style=\"background-color:"+C.history_color[True]+"\"", # history_Dcolor = "style=\"background-color:"+C.history_color[False]+"\"", # Dbutton_color= C.active_color[False], # Cbutton_color= C.active_color[True], # my_color="style=\"background:"+C.inactive_color[player.cooperate]+";\"", # opp_color="style=\"background:"+C.inactive_color[opponent.cooperate]+";\"", # outcome_color="style=\"background:"+C.outcome_color[opponent.cooperate]+";\"", # tag = player.participant.vars['tag'], # opp_tag = get_opponent(player).participant.vars['tag'], # pred_tag = predecessor_tag(player), # first_gen= player.session_gen == 1, # last_per=player.subsession.last_period, # delta=player.subsession.delta, # first_period = False, # r_advice = player.participant.vars['r_advice'], # g_advice=player.participant.vars['g_advice'], # opp = get_opponent(player), # stage = player.stage,) # # give advice # class EndOfMatch(Page): # form_model = 'player' # form_fields = ['g_advice'] # @staticmethod # def is_displayed(player: Player): # return (player.subsession.last_period and player.stage == 0 and not player.session.config['gen_end']) # @staticmethod # def vars_for_template(player: Player): # opponent = get_opponent(player) # #player.in_all_rounds().g_advice = player.g_advice # player.participant.vars['last_round'] = player.subsession.round_number # return dict( # roll=player.subsession.dice_roll, # round = player.subsession.round_number, # history_Ccolor = "style=\"background-color:"+C.history_color[True]+"\"", # history_Dcolor = "style=\"background-color:"+C.history_color[False]+"\"", # Dbutton_color= C.active_color[False], # Cbutton_color= C.active_color[True], # opponent=opponent, # tag = player.participant.vars['tag'], # opp_tag = get_opponent(player).participant.vars['tag'], # succ_tag= successor_tag(player), # succ_opp_tag= successor_tag(get_opponent(player)), # pred_tag = predecessor_tag(player), # opp_succ_tag= successor_tag(get_opponent(player)), # sessionid=player.session.id, # same_choice=player.cooperate == opponent.cooperate, # my_decision=player.field_display('cooperate'), # opponent_decision=opponent.field_display('cooperate'), # first_period = False, # history = player.participant.vars['match_history'], # delta=player.subsession.delta, # r_advice=player.participant.vars['r_advice'], # first_gen= player.session_gen == 1, # per= player.subsession.round,) # @staticmethod # def before_next_page(player, timeout_happened): # player.participant.vars['g_advice'] = player.g_advice # class SaveLocal(WaitPage): # template_name = 'GPD/PreWait.html' # @staticmethod # def is_displayed(player: Player): # N = player.subsession.num_questions # return (player.subsession.last_period and not player.session.config['gen_end'] and player.stage <= 0) or\ # player.stage == player.subsession.num_questions # @staticmethod # def vars_for_template(player: Player): # opp = get_opponent(player) # player.r_survey = player.participant.vars['rfirst'] # if player.stage == player.subsession.num_questions: # player.r_survey = not player.r_survey # if player.r_survey: # advice = player.participant.vars['r_advice'] # else: # advice = player.participant.vars['g_advice'] # return { # 'inactive':player.stage<0, # 'r_advice': player.participant.vars['r_advice'], # 'rsurvey':player.r_survey, # 'survey_instr': (player.stage == 0 or player.stage == player.subsession.num_questions), # 'stage':player.stage, # 'pred_tag': predecessor_tag(player), # 'pred_opp_tag': predecessor_tag(opp), # 'advice': advice, # 'tag': player.participant.vars['tag'], # 'opp_tag': opp.participant.vars['tag'], # 'succ_tag': successor_tag(player), # 'succ_opp_tag': successor_tag(opp), # } # class SaveSession(WaitPage): # @staticmethod # def is_displayed(player: Player): # return player.final_period and player.session_end # @staticmethod # def app_after_this_page(player: Player, upcoming_apps): # player.participant.vars['rsurvey'] = sort_rresponse(player) # player.participant.vars['gsurvey'] = sort_gresponse(player) # player.g_advice = player.participant.vars['g_advice'] # player.g_responses = bool_to_string(sort_gresponse(player)) # add_player_history(player) # class EndOfGame(Page): # #timeout_seconds = 30 # @staticmethod # def is_displayed(player: Player): # return player.final_period and player.session_end # @staticmethod # def vars_for_template(player: Player): # opponent = get_opponent(player) # player.participant.vars['done'] = True # # points for interpreting received advice # return dict( # roll=player.subsession.dice_roll, # round = player.subsession.round_number, # asurvey =player.participant.vars['asurvey'], # opp_tag = get_opponent(player).participant.vars['tag'], # tag = player.participant.vars['tag'], # pred_tag = predecessor_tag(player), # succ_tag= successor_tag(player), # opp_succ_tag= successor_tag(get_opponent(player)), # asurvey2 =player.participant.vars['interprets'], # opponent=opponent, # same_choice=player.cooperate == opponent.cooperate, # my_decision=player.field_display('cooperate'), # opponent_decision=opponent.field_display('cooperate'), # r_advice=player.participant.vars['r_advice'], # payoff=player.participant.payoff, # money_payoff = player.participant.payoff_plus_participation_fee(), # end=player.session_end, # final = player.final_period, # gen=player.session_gen, # session_continue = not player.subsession.stop_session, # current_gen=player.subsession.current_gen, # gpoints= player.participant.vars['gpoints'], # rpoints= player.participant.vars['rpoints'], # dynasty = player.group.dynasty, # last = (player.session_end and not player.session.config['gen_end']), # per=player.subsession.round, # session=player.session_id, # id = player.session.id, # ) # class EndWait(WaitPage): # template_name = 'GPD/EndWait.html' # #timeout_seconds = 30 # @staticmethod # def is_displayed(player: Player): # # return player.final_period and not player.session_end # # NEW CODE TO FIX WAITING ISSUE # return player.released_to_endwait and not player.session_end # @staticmethod # def vars_for_template(player: Player): # opponent = get_opponent(player) # player.participant.vars['done'] = True # # points for interpreting received advice # return dict( # asurvey =player.participant.vars['asurvey'], # opp_tag = get_opponent(player).participant.vars['tag'], # tag = player.participant.vars['tag'], # pred_tag = predecessor_tag(player), # succ_tag= successor_tag(player), # opp_succ_tag= successor_tag(get_opponent(player)), # asurvey2 =player.participant.vars['interprets'], # opponent=opponent, # same_choice=player.cooperate == opponent.cooperate, # my_decision=player.field_display('cooperate'), # opponent_decision=opponent.field_display('cooperate'), # roll=player.subsession.dice_roll, # r_advice=player.participant.vars['r_advice'], # payoff=player.participant.payoff, # money_payoff = player.participant.payoff_plus_participation_fee(), # end=player.session_end, # final = player.final_period, # gen=player.session_gen, # session_continue = not player.subsession.stop_session, # current_gen=player.subsession.current_gen, # gpoints= player.participant.vars['gpoints'], # rpoints= player.participant.vars['rpoints'], # dynasty = player.group.dynasty, # last = (player.session_end and not player.session.config['gen_end']), # per=player.subsession.round, # session=player.session_id, # id=str(player.participant.id)+str(player.side), # ) # # NEW CLASS TO FORCE GEN 1 TO WAIT FOR GEN 2 TO FINISH INTERPRETING RECEIVING RESULTS BEFORE SEEING FINAL PAYMENT PAGE # # class WaitForGen2(WaitPage): # # @staticmethod # # def is_displayed(player: Player): # # return player.session_gen == 1 and player.participant.vars.get('wait', False) and not player.final_period # page_sequence = [Introduction, # Decision, React, # Survey, # # WaitForGen2, # ResultsWaitPage, Results1, # Results, EndOfMatch, # SaveLocal, SaveSession, EndOfGame, EndWait] # #page_sequence = [Introduction, Decision, ResultsWaitPage, ResultsPage, WaitGroup, Results] # TESTING THE OLD VERSION OF THE CODE (THIS WORKS) from otree.api import * import numpy as np import random import GPD from db.database import create_database_tables from db.crud import get_ancestor_players, add_player_history # THIS IS THE NEW CODE doc = """ This is an intergenerational "Prisoner's Dilemma". Two players are asked separately whether they want to cooperate or defect. Their choices and the choices of their successors directly determine the payoffs. """ ## Random seed # delta # survey class C(BaseConstants): NAME_IN_URL = 'GPD' INSTRUCTIONS_TEMPLATE = 'GPD/instructions.html' INSTRUCTIONS_SURVEY = 'GPD/instructions-survey.html' PAYOFF_CC = 65 PAYOFF_CD = 10 PAYOFF_DC = 100 PAYOFF_DD = 35 PAYOFF_I = 5 # interpretation payoff (should be changed to five points) NUM_ROUNDS = 50 C_TAG = '1' # label for cooperation D_TAG = '2' # label for defection num_gen = 2 num_dynasty = 5 PLAYERS_PER_GROUP = num_gen*2 delta = 50 gamma = 1 inactive_color = ["#FAE5CB", "#CBE6FA"] active_color = ["SandyBrown","LightSkyBlue"] history_color = active_color outcome_color = ["Orange","DeepSkyBlue"] button_color = outcome_color hover_color = ["#FE9900","#00C4FE"] genfile = 'gen' groupfile = 'advice' history = [{}, {'P1': {'period': '1', 'name_opp_action': C_TAG, 'opp_cooperate': True}}, {'P1': {'period': '1', 'name_opp_action': D_TAG, 'opp_cooperate': False}} ] # questions for advice survey class Subsession(BaseSubsession): dice_roll = models.IntegerField(initial=-10) gen_number = models.IntegerField(initial=-10) # which generation this round corresponds to first_period = models.BooleanField(initial=True) # True if it is the first period of a match last_period = models.BooleanField(initial=False) # True if it is the last period of a match period_number = models.IntegerField(initial=1) current_gen = models.IntegerField(initial=1) num_questions = models.IntegerField(initial = 0) delta = models.IntegerField(initial = C.delta) stop_session = models.BooleanField(initial = False) dynasty_session = models.IntegerField(initial = -1) payoff_round = models.IntegerField(initial = -1) round = models.IntegerField(initial = -1) class Group(BaseGroup): number = models.IntegerField() dynasty = models.IntegerField(initial = -1) class Player(BasePlayer): # Game fields final_period = models.BooleanField(initial = False) # ready to receive payoff, leave experiment action = models.StringField(initial=C.D_TAG) cooperate = models.BooleanField( choices=[[True, C.C_TAG], [False, C.D_TAG]], doc="""This player's decision""", widget=widgets.RadioSelect, initial= False, ) react = models.BooleanField( choices=[[True, C.C_TAG], [False, C.D_TAG]], doc="""This player's decision""", widget=widgets.RadioSelect, initial= False,) session_gen = models.IntegerField(initial = 1) gen = models.IntegerField(initial = 1) # advice ancestor_advice = models.LongStringField(label="Advice to you", default="") ancestor_participant_id = models.IntegerField(default=0) g_advice = models.LongStringField(initial = '',label="Advice:") # ID fields session_end = models.BooleanField(initial = False) last_gen = models.BooleanField(initial = False) side = models.BooleanField(initial = False) stage = models.IntegerField(initial=-1) # Survey fields r_survey = models.BooleanField(initial = True) # interpreting received advice interpret = models.BooleanField() clear = models.BooleanField(label="Does the advice clearly indicate what to do in this scenario?") g_responses = models.StringField(initial = '') # FUNCTIONS def creating_session(subsession: Subsession): if len(subsession.get_groups())>C.num_dynasty: ValueError("Too many groups") nround = subsession.round_number # current round ## ROLL Round incrementing if subsession.session.config['gen_end']: delta = 1-(1-C.delta)/(1+C.gamma) else: delta = C.delta # draw random number for each round seed = random.seed(a=None, version=2) random.seed(a=seed, version=2) extra_rounds = C.num_dynasty*2+len(C.history) # accounts for survey question rounds dice_rolls = np.random.randint(1, 101, C.NUM_ROUNDS+1).tolist() while sum(i > delta for i in dice_rolls[0:(C.NUM_ROUNDS-len(C.history)-extra_rounds)]) < C.num_gen: dice_rolls = np.random.randint(1, 101, C.NUM_ROUNDS+1).tolist() subsession.session.vars['dice_rolls'] = dice_rolls roll = -1 if nround == 1: subsession.period_number = 1 subsession.round = 1 roll = dice_rolls[1] else: if subsession.in_round(nround-1).last_period: subsession.period_number = 1 subsession.round = 1 else: subsession.period_number = subsession.in_round(nround-1).period_number + 1 subsession.round = subsession.in_round(nround-1).round + 1 if subsession.period_number == 3: subsession.round = subsession.round - 1 ## player advice/incrementing # initialize roles and draw advice players = subsession.get_players() subsession.dynasty_session = subsession.session.config['dynasty_session'] if nround == 1: subsession.group_randomly() subsession.period_number = 1 subsession.current_gen = 1 # try: # ancestors = get_ancestor_players(subsession.dynasty_session) # except: # ancestors = [] # print('No Ancestors') # finally: # dynasties = list(range(0, C.num_dynasty)) # dynasty_ages = list(range(0, C.num_dynasty)) # num_groups = len(subsession.get_groups()) # print('Dynasty') # for dynasty in dynasties: # dynasty_ancestors = [ancestor for ancestor in ancestors if ancestor.dynasty == dynasty] # try: # age = max([ancestor.gen for ancestor in dynasty_ancestors]) # generation of dynasty # except: # age = 0 # dynasty_ages[dynasty] = age # for n in range(num_groups,C.num_dynasty): # long_dynasties = [i for i in range(0,len(dynasties)) if dynasty_ages[i] == max(dynasty_ages)] # maximum length dynasties # excess = max(long_dynasties) # dynasties to remove # dynasties.remove(dynasties[excess]) # remove first dynasty reaching this value # dynasty_ages.remove(dynasty_ages[excess]) # ancestor_players = [ancestor for ancestor in ancestors if ancestor.dynasty in dynasties] # THIS CODE ATTEMPTS TO FIX THE ISSUE OF STARTING AT A LATER GENERATION AND PULLING EARLIER, NON-EXISTENT DATA dynasties = list(range(0, C.num_dynasty)) dynasty_ages = [0] * C.num_dynasty num_groups = len(subsession.get_groups()) dynasties = dynasties[:num_groups] ancestor_players = [] create_database_tables() #subsession.group_randomly() # randomly assign groups, generations, dynasty num = 0 for group in subsession.get_groups(): gens = [] group.number = num group.dynasty = dynasties[num] group_gen = dynasty_ages[num] for i in range(1,C.num_gen+1): gens = gens + [i, i] random.shuffle(gens) num += 1 group_players = group.get_players() for p, gen in zip(group_players, gens): p.session_gen = gen for gen in range(1,C.num_gen+1): gen_players = [player for player in group_players if player.session_gen == gen] random.shuffle(gen_players) sides = [True, False] for p, side in zip(gen_players, sides): p.side = side p.session_end = (p.session_gen == C.num_gen) for p in group_players: p.participant.vars['r_advice']='' p.participant.vars['interprets'] = [] p.participant.vars['g_advice'] = '' p.participant.vars['asurvey'] = [] p.participant.vars['match_history'] = {} p.participant.vars['done'] = False p.participant.vars['rfirst'] = (p.session_gen > 1) # NEW CODE AS OF 04-04-2026 (5:29 PM) --- attempting to fix the error of no final payment page appearing p.participant.vars['gpoints'] = 0 p.participant.vars['rpoints'] = 0 if group_gen > 0: print(ancestor_players) ancestor_options = [ancestor for ancestor in ancestor_players if (ancestor.dynasty == group.dynasty and ancestor.gen == group_gen)] for p in group_players: if p.session_gen == 1: print("Group dynasty:"+str(group.dynasty)) ancestor = random.choice(ancestor_options) ancestor_options.remove(ancestor) p.gen = ancestor.gen + 1 p.side = ancestor.side get_tag(p) p.ancestor_participant_id = ancestor.participant_id if ancestor.g_advice == '': ValueError("Advice not passed") p.participant.vars['asurvey'] = string_to_bool(ancestor.g_survey) if p.participant.vars['asurvey'] == []: ValueError("asurvey empty") p.participant.vars['r_advice'] = ancestor.g_advice else: # first group in dynasty for p in group_players: if p.session_gen == 1: p.participant.vars['rfirst'] = False p.gen = p.session_gen get_tag(p) p.participant.vars['asurvey'] = [] p.participant.vars['r_advice'] = '' for p in players: # identify later generations p.stage = 0 if p.session_gen > 1: p.stage = -1 p.gen = get_predecessor(p).gen + 1 get_tag(p) # continue advice/ increment player attributes subsession.num_questions = len(C.history) subsession.payoff_round = nround if subsession.period_number != 2 and nround >= 3: roll = dice_rolls[nround - 1] roll1 = -1 if subsession.period_number == 3: roll1 = subsession.in_round(nround -2).dice_roll if roll1 > delta or roll > delta: subsession.last_period = True if roll1 > delta: subsession.payoff_round = nround - 2 if nround > 1: subsession.group_like_round(1) for g in subsession.get_groups(): g.dynasty = g.in_round(nround - 1).dynasty g.number = g.in_round(nround - 1).number # increment session generation attributes if subsession.in_round(nround - 1).last_period: # new generation gen = subsession.in_round(nround - 1).current_gen + 1 subsession.first_period = True else: # same generation gen = subsession.in_round(nround - 1).current_gen subsession.first_period = False subsession.current_gen = gen for p in players: if p.session_end and p.session.config['gen_end']: p.last_gen = True p.side = p.in_round(nround - 1).side p.gen = p.in_round(nround - 1).gen get_tag(p) p.session_gen = p.in_round(nround - 1).session_gen p.session_end = (p.session_gen == C.num_gen) #active_players = [player for player in players if player.session_gen == subsession.current_gen] p.participant.vars['wait'] = False if p.session_gen == subsession.current_gen: # Pass advice in later generations (inheritance already random from role) p.stage = 0 if p.session_gen < p.subsession.current_gen: # if retired, recall advice, survey generations, increment stage p.stage = p.in_round(p.round_number - 1).stage + 1 if p.stage <= p.subsession.num_questions: p.r_survey = p.participant.vars['rfirst'] else: p.r_survey = not p.participant.vars['rfirst'] if p.session_gen > p.subsession.current_gen: p.stage = -1 p.participant.vars['wait'] = True subsession.delta = delta subsession.dice_roll = roll def get_tag(player: Player): # identify opponent side =player.side tag = str(player.gen) if side: tag += 'A' else: tag += 'B' player.participant.vars['tag'] = tag def successor_tag(player: Player): # identify opponent side =player.side tag = str(player.gen + 1) if side: tag += 'A' else: tag += 'B' return(tag) def predecessor_tag(player: Player): # identify opponent side =player.side tag = str(player.gen - 1) if side: tag += 'A' else: tag += 'B' return(tag) def get_opponent(player: Player): # identify opponent for j in player.get_others_in_group(): if player.session_gen == j.session_gen: return j def get_predecessor(player: Player): # identify predecessor for j in player.get_others_in_group(): if player.session_gen == j.session_gen + 1 and player.side == j.side: return j def get_successor(player: Player): # identify successor for j in player.get_others_in_group(): if player.session_gen == j.session_gen - 1 and player.side == j.side: return j def bool_to_string(bool_list): # converts boolean lists to strings to pass between players string_list = [str(int(elem)) for elem in bool_list] return ','.join(string_list) def string_to_bool(comma_string): # converts comma strings to boolean list return [bool(int(elem)) for elem in comma_string.split(',')] def sort_gresponse(player: Player): N = player.subsession.num_questions if player.session_gen == 1: return player.participant.vars['interprets'][0: N] if player.participant.vars['rfirst']: return player.participant.vars['interprets'][N:2 * N] else: return player.participant.vars['interprets'][0: N] def sort_rresponse(player: Player): N = player.subsession.num_questions if player.session_gen == 1: ValueError("No received advice") if player.last_gen: return player.participant.vars['interprets'][0: N] if player.participant.vars['rfirst']: return player.participant.vars['interprets'][0: N] else: return player.participant.vars['interprets'][N:2 * N] def r_advice_score(player: Player): # score points for received advice predecessor_resp = player.participant.vars['asurvey'] r_responses = sort_rresponse(player) num_correct = len([i for i in range(0,len(r_responses)) if r_responses[i] == predecessor_resp [i]]) # count matching interpretations return num_correct*C.PAYOFF_I # INCORRECTLY COMPUTES PAYOFFS AS A FUNCTION OF ALL EARNINGS NOT JUST THE LAST ROUND # def set_payoffs(group: Group): # for p in group.get_players(): # if p.stage == 0: # j = get_opponent(p) # payoff_matrix = { # (False, True): C.PAYOFF_DC, # (True, True): C.PAYOFF_CC, # (False, False): C.PAYOFF_DD, # (True, False): C.PAYOFF_CD, # } # p.payoff = payoff_matrix[(p.cooperate,j.cooperate)] # if p.stage > 0 and not p.participant.vars['done']: # p.payoff = 0 # CORRECTLY COMPUTES PAYOFFS AS A FUNCTION OF LAST ROUND EARNINGS ONLY def set_payoffs(group: Group): for p in group.get_players(): if p.stage == 0: if p.subsession.last_period: j = get_opponent(p) payoff_matrix = { (False, True): C.PAYOFF_DC, (True, True): C.PAYOFF_CC, (False, False): C.PAYOFF_DD, (True, False): C.PAYOFF_CD, } p.payoff = payoff_matrix[(p.cooperate,j.cooperate)] else: p.payoff = 0 if p.stage > 0 and not p.participant.vars['done']: p.payoff = 0 def total_pd_earnings_so_far(player: Player): return sum(r.payoff for r in player.in_all_rounds() if r.stage == 0) #p.participant.vars['pd_points'] += p.points #p.participant.payoff = round(p.participant.vars['pd_points'] * group.session.config['pd_conversion'], 2) #p.participant.vars['pd_dollars'] = p.participant.payoff # p.save() # PAGES #if p.session_gen > 1: # ancestor = get_predecessor(p) # p.ancestor_session_id = ancestor.session_id # p.ancestor_participant_id = ancestor.participant_id #if p.stage == 0: # p.participant.vars['r_advice'] = ancestor.participant.vars['g_advice'] #if p.stage > 0: # p.participant.vars['asurvey'] = ancestor.g_responses class Introduction(Page): @staticmethod def is_displayed(player: Player): N = player.subsession.num_questions return (player.subsession.first_period and player.stage == 0) or player.stage == 1 or (player.stage == N+1 and not player.participant.vars['wait']) @staticmethod def vars_for_template(player: Player): if player.session_gen > 1: pred = get_predecessor(player) player.participant.vars['r_advice'] = pred.participant.vars['g_advice'] player.ancestor_participant_id = pred.participant_id # NEW CODE AS OF 04-04-2026 (2:47 PM) --- attempting to fix the error of being asked to interpret received advice as the first generation if player.session_gen == 1: player.r_survey = False try: if player.r_survey: advice = player.participant.vars['r_advice'] else: advice = player.participant.vars['g_advice'] except: advice = '' return { 'first_period': player.subsession.first_period, 'wait': player.participant.vars['wait'], 'r_advice': player.participant.vars['r_advice'], 'rsurvey':player.r_survey, 'survey_instr': not (player.stage == 0), 'gam_gen': player.subsession.current_gen, 'gen': player.session_gen, 'first_gen': player.session_gen==1, 'delta':player.subsession.delta, 'pred_tag': predecessor_tag(player), 'advice':advice, 'tag': player.participant.vars['tag'], 'opp_tag': get_opponent(player).participant.vars['tag'], 'succ_tag': successor_tag(player), 'succ_opp_tag':successor_tag(get_opponent(player)), 'stage':player.stage, 'round': player.subsession.round_number, 'per': player.subsession.round, 'last_gen':C.num_gen, 'end2':(player.session_gen == C.num_gen), 'end':player.session_end, 'payI': C.PAYOFF_I, } class React(Page): form_model = 'player' form_fields = ['react'] @staticmethod def is_displayed(player: Player): return player.stage == 0 and (player.subsession.period_number == 2 or player.subsession.period_number == 3) @staticmethod def vars_for_template(player: Player): n = player.subsession.round_number scenario = player.subsession.period_number - 1 if scenario == 1: p_cooperate = player.in_round(n-1).cooperate opp_cooperate = True #history = {'P1': {'period': '1', 'cooperate':p_cooperate, 'name_action': player.in_round(n-1).action, #'opp_cooperate':opp_cooperate,'name_opp_action': 1}} else: p_cooperate = player.in_round(n-2).cooperate opp_cooperate = False #history = {'P1': {'period': '1', 'cooperate':p_cooperate, 'name_action': player.in_round(n-1).action, #'opp_cooperate':opp_cooperate,'name_opp_action': 2}} return { 'round_number': player.subsession.round_number, 'history_Ccolor': "style=\"background-color:"+C.history_color[True]+"\"", 'history_Dcolor': "style=\"background-color:"+C.history_color[False]+"\"", 'Dbutton_color': C.button_color[False], 'Cbutton_color': C.button_color[True], 'Dbutton_hover': C.hover_color[False], 'Cbutton_hover': C.hover_color[True], 'session_end':player.session_end, 'group': player.group, 'version':scenario, 'my_decision':p_cooperate, 'opp_cooperate':opp_cooperate, 'my_color':"style=\"background:"+C.inactive_color[p_cooperate]+";\"", 'opp_color':"style=\"background:"+C.inactive_color[opp_cooperate]+";\"", 'outcome_color':"style=\"background:"+C.outcome_color[opp_cooperate]+";\"", 'period': player.subsession.round, 'interprets': player.participant.vars['interprets'], 'asurvey': player.participant.vars['asurvey'], 'first_gen': player.session_gen == 1, 'first_period': player.subsession.first_period, 'history': [], 'delta':player.subsession.delta, 'r_advice': player.participant.vars['r_advice'], 'gam_gen': player.subsession.current_gen, 'CTAG':C.C_TAG, 'DTAG':C.D_TAG, 'gen': player.session_gen, 'pred_tag': predecessor_tag(player), 'tag': player.participant.vars['tag'], 'opp_tag':get_opponent(player).participant.vars['tag'], 'round': player.subsession.round_number, 'session':player.session_id, } class Decision(Page): form_model = 'player' form_fields = ['cooperate'] @staticmethod def is_displayed(player: Player): return player.stage == 0 and (player.subsession.period_number != 2 and player.subsession.period_number != 3) @staticmethod def vars_for_template(player: Player): return { 'round_number': player.subsession.round_number, 'history_Ccolor': "style=\"background-color:"+C.history_color[True]+"\"", 'history_Dcolor': "style=\"background-color:"+C.history_color[False]+"\"", 'Dbutton_color': C.button_color[False], 'Cbutton_color': C.button_color[True], 'Dbutton_hover': C.hover_color[False], 'Cbutton_hover': C.hover_color[True], 'period': player.subsession.round, 'interprets': player.participant.vars['interprets'], 'asurvey': player.participant.vars['asurvey'], 'first_gen': player.session_gen == 1, 'first_period': player.subsession.first_period, 'history': player.participant.vars['match_history'], 'delta':player.subsession.delta, 'r_advice': player.participant.vars['r_advice'], 'CTAG':C.C_TAG, 'DTAG':C.D_TAG, 'pred_tag': predecessor_tag(player), 'tag': player.participant.vars['tag'], 'opp_tag':get_opponent(player).participant.vars['tag'], 'session':player.session_id, } class Survey(Page): form_model = 'player' form_fields = ['interpret','clear'] @staticmethod def is_displayed(player: Player): # Only show Survey while the player is in the interpretation stages. N = player.subsession.num_questions if player.session_gen == 1 or (player.session.config['gen_end'] and player.session_end): num_q = N else: num_q = 2 * N return 0 < player.stage <= num_q @staticmethod def vars_for_template(player: Player): history = C.history N = player.subsession.num_questions question = (player.stage-1) % N r_survey = player.r_survey if player.session_gen == 1: r_survey = False player.r_survey = False if r_survey: advice = player.participant.vars['r_advice'] # r_advice survey active_tag = player.participant.vars['tag'] opp_tag = get_opponent(player).participant.vars['tag'] else: advice = player.participant.vars['g_advice'] # g_advice survey active_tag = successor_tag(player) opp_tag = successor_tag(get_opponent(player)) if player.session_gen == 1 or (player.session.config['gen_end'] and player.session_end): num_q = N else: num_q =2*N # if player.stage == num_q: # player.participant.vars['wait'] = True historyq = history[question] player.g_advice = player.participant.vars['g_advice'] return { 'history_Ccolor': "style=\"background-color:"+C.history_color[True]+"\"", 'history_Dcolor': "style=\"background-color:"+C.history_color[False]+"\"", 'Dbutton_color': C.button_color[False], 'Cbutton_color': C.button_color[True], 'Dbutton_hover': C.hover_color[False], 'Cbutton_hover': C.hover_color[True], 'advice': advice, 'tag':player.participant.vars['tag'], 'active_tag':active_tag, 'active_opp_tag':opp_tag, 'pred_tag': predecessor_tag(player), 'succ_tag': successor_tag(player), 'first_gen': player.session_gen == 1, 'gadvice': player.g_advice, 'r': r_survey, 'round': len(historyq)+1, 'asurvey': player.participant.vars['asurvey'], 'rfirst': player.participant.vars['rfirst'], 'history':historyq, 'first':historyq == {}, 'delta':player.subsession.delta, 'CTAG':C.C_TAG, 'DTAG':C.D_TAG, 'stage':player.stage, 'q':question, 'num_q':num_q } #@staticmethod #def before_next_page(player, timeout_happened): #player.participant.vars['interprets'].append(player.interpret) @staticmethod def before_next_page(player, timeout_happened): player.participant.vars['interprets'].append(player.interpret) N = player.subsession.num_questions # determine how many survey questions this player has if player.session_gen == 1 or (player.session.config['gen_end'] and player.session_end): num_q = N else: num_q = 2 * N # if this is the last survey question if player.stage == num_q: player.participant.vars['wait'] = True if player.session_end: # gen2 finished — compute rpoints, set gpoints for gen1, release both predecessor = get_predecessor(player) player.participant.vars['asurvey'] = sort_gresponse(predecessor) player.participant.vars['rpoints'] = r_advice_score(player) player.participant.vars['gpoints'] = 0 if predecessor is not None: predecessor.participant.vars['gpoints'] = player.participant.vars['rpoints'] predecessor.payoff += predecessor.participant.vars['gpoints'] + predecessor.participant.vars['rpoints'] predecessor.final_period = True player.payoff += player.participant.vars['gpoints'] + player.participant.vars['rpoints'] player.final_period = True player.subsession.stop_session = True elif player.session_gen == 1: # gen1 finished their surveys — just wait, final_period stays False until gen2 done pass class Results1WaitPage(WaitPage): @staticmethod def is_displayed(subsession: Subsession): return subsession.period_number == 3 @staticmethod def after_all_players_arrive(subsession: Subsession): n = subsession.round_number for group in subsession.get_groups(): for p in group.get_players(): opp = get_opponent(p) p.cooperate = p.react if opp.in_round(n-2).cooperate: p.cooperate = p.in_round(n-1).react class ResultsWaitPage(WaitPage): wait_for_all_groups = True template_name = 'GPD/ResultsWaitPage.html' @staticmethod def is_displayed(player: Player): return player.stage == 0 and player.subsession.period_number != 2 @staticmethod def after_all_players_arrive(subsession: Subsession): for group in subsession.get_groups(): n = subsession.round_number if group.subsession.period_number == 3: for p in group.get_players(): opp = get_opponent(p) p.cooperate = p.react if opp.in_round(n - 2).cooperate: p.cooperate = p.in_round(n - 1).react set_payoffs(group) round = str(group.subsession.round) N = group.subsession.num_questions for p in group.get_players(): if p.participant.vars['done']: continue if p.stage < 0: continue if p.stage == 0: # active players opp = get_opponent(p) if p.cooperate: p.action = C.C_TAG if opp.cooperate: opp.action = C.C_TAG if p.subsession.round_number <= p.subsession.payoff_round: p.participant.vars['match_history']['P' + round] = { 'period': round, 'cooperate':p.cooperate, 'name_action': p.action, 'opp_cooperate':opp.cooperate, 'name_opp_action': opp.action } if p.subsession.last_period and p.session_gen>1: predecessor = get_predecessor(p) predecessor.payoff += p.payoff # # FIX 1: set final_period for last gen (session_end) players # if p.session_end and p.subsession.last_period: # p.participant.vars['gpoints'] = 0 # p.final_period = True # p.subsession.stop_session = True # # FIX 2: set final_period for gen1 (predecessor) when last gen's game ends # if p.subsession.last_period and p.session_gen > 1: # predecessor = get_predecessor(p) # if predecessor.participant.vars.get('wait', False): # predecessor.final_period = True continue # SURVEY CALCULATIONS # calculate Gdone = predecssor done given advice survey if p.session_gen > 1: num_question = 2*N predecessor = get_predecessor(p) if predecessor.participant.vars['rfirst']: Gdone = (predecessor.stage >= 2*N) else: Gdone = (predecessor.stage >= N) else: # session_gen == 1 Gdone = True if p.session_gen == 1: num_question = N p.participant.vars['rpoints'] = 0 if p.session_gen != 1: # has receiver advice # calculate Rdone, if current player finished received advice survey if p.participant.vars['rfirst']: Rdone = (p.stage >= N) else: Rdone = (p.stage >= 2*N) if Rdone and Gdone: if p.session_gen > 1: p.participant.vars['asurvey'] = sort_gresponse(predecessor) # full responses to both surveys, calculate p.participant.vars['rpoints'] = r_advice_score(p) if p.session_gen > 1: predecessor.participant.vars['gpoints'] = p.participant.vars['rpoints'] # NEW CODE AS OF 04-04-2026 (8:01 PM) --- attempting to fix the error of no final payment page appearing #predecessor.final_period = True # OLD CODE AS OF 04-04-2026 (8:01 PM) --- attempting to fix the error of no final payment page appearing #predecessor.final_period = predecessor.participant.vars['wait'] # JUST TOLD ME TO COMMENT THIS OUT MAYBE SHOULD GO BACK? 04-04-2026 (11:49 PM) if p.session_end: p.participant.vars['gpoints'] = 0 if p.session.config['gen_end']: num_question = N p.g_responses = '' # NEW CODE AS OF 04-04-2026 (8:00 PM) --- attempting to fix the error of no final payment page appearing #if p.subsession.last_period: # OLD CODE AS OF 04-04-2026 (8:00 PM) --- attempting to fix the error of no final payment page appearing if p.stage >= num_question:# last gen done when survey done p.final_period = True p.subsession.stop_session = True # # NEW CODE AS OF 04-04-2026 (6:14 PM) --- attempting to fix the error of no final payment page appearing (did not work) # if p.session_end and p.final_period: # predecessor = get_predecessor(p) # if predecessor is not None and not predecessor.final_period: # predecessor.final_period = True # for p in group.get_players(): # if p.subsession.stop_session: # p.payoff += p.participant.vars['gpoints'] + p.participant.vars['rpoints'] # payoff from interpreting # JUST TOLD ME TO COMMENT THIS OUT MAYBE SHOULD COMMENT BACK? 04-04-2026 (11:49 PM) @staticmethod def vars_for_template(player: Player): advice = player.participant.vars['r_advice'] opp = get_opponent(player) if player.stage == player.subsession.num_questions: player.r_survey = not player.r_survey if player.r_survey: advice = player.participant.vars['r_advice'] else: advice = player.participant.vars['g_advice'] return { 'history_Ccolor': "style=\"background-color:"+C.history_color[True]+"\"", 'history_Dcolor': "style=\"background-color:"+C.history_color[False]+"\"", 'Dbutton_color': C.active_color[False], 'Cbutton_color': C.active_color[True], 'my_color':"style=\"background:"+C.inactive_color[player.cooperate]+";\"", 'my_decision':player.cooperate, 'first_gen': player.session_gen == 1, 'asurvey':player.participant.vars['asurvey'], 'survey':player.participant.vars['interprets'], 'rsurvey':player.r_survey, #'survey_instr': (player.stage == 0 or player.stage == player.subsession.num_questions), (DUPLICATE) 'advice':advice, 'period': player.subsession.round, 'final': player.final_period, 'stage': player.stage, 'end': player.session_end, 'history': player.participant.vars['match_history'], 'first_period': player.subsession.period_number==1, 'r_advice': advice, 'current_match': str(player.session_gen), 'pred_tag': predecessor_tag(player), 'tag': player.participant.vars['tag'], 'opp_tag': opp.participant.vars['tag'], 'succ_tag': successor_tag(player), 'survey_instr': player.stage == player.subsession.num_questions and player.session_gen != 1, 'succ_opp_tag': successor_tag(opp), } class Results1(Page): @staticmethod def is_displayed(player: Player): return player.stage == 0 and player.subsession.period_number == 3 @staticmethod def vars_for_template(player: Player): opponent = get_opponent(player) n = player.subsession.round_number-2 # first round return dict( payoff_round = player.subsession.payoff_round, round_number = player.subsession.round_number, r2_decision=player.cooperate, opponent=opponent, same_choice=player.in_round(n).cooperate == opponent.in_round(n).cooperate, period = player.subsession.round, my_decision=player.in_round(n).cooperate, opp_decision=opponent.in_round(n).cooperate, roll = player.subsession.in_round(n).dice_roll, history = player.participant.vars['match_history'], history_Ccolor = "style=\"background-color:"+C.history_color[True]+"\"", history_Dcolor = "style=\"background-color:"+C.history_color[False]+"\"", Dbutton_color= C.active_color[False], Cbutton_color= C.active_color[True], my_color="style=\"background:"+C.inactive_color[player.in_round(n).cooperate]+";\"", opp_color="style=\"background:"+C.inactive_color[opponent.in_round(n).cooperate]+";\"", outcome_color="style=\"background:"+C.outcome_color[opponent.in_round(n).cooperate]+";\"", tag = player.participant.vars['tag'], opp_tag = get_opponent(player).participant.vars['tag'], pred_tag = predecessor_tag(player), first_gen= player.session_gen == 1, last_per=player.subsession.last_period, delta=player.subsession.delta, payoff = player.in_round(n).payoff, first_period = False, r_advice = player.participant.vars['r_advice'], g_advice=player.participant.vars['g_advice'], per= player.subsession.round, opp = get_opponent(player), stage = player.stage,) class Results(Page): @staticmethod def is_displayed(player: Player): return player.stage == 0 and player.subsession.period_number >= 3 and player.subsession.payoff_round != player.subsession.round_number - 2 @staticmethod def vars_for_template(player: Player): opponent = get_opponent(player) p_cooperate = player.cooperate opp_cooperate = opponent.cooperate return dict( opponent=opponent, total_so_far=total_pd_earnings_so_far(player), same_choice=p_cooperate == opp_cooperate, period = player.subsession.round, my_decision=p_cooperate, opp_decision=opp_cooperate, roll = player.subsession.dice_roll, history = player.participant.vars['match_history'], history_Ccolor = "style=\"background-color:"+C.history_color[True]+"\"", history_Dcolor = "style=\"background-color:"+C.history_color[False]+"\"", Dbutton_color= C.active_color[False], Cbutton_color= C.active_color[True], my_color="style=\"background:"+C.inactive_color[player.cooperate]+";\"", opp_color="style=\"background:"+C.inactive_color[opponent.cooperate]+";\"", outcome_color="style=\"background:"+C.outcome_color[opponent.cooperate]+";\"", tag = player.participant.vars['tag'], opp_tag = get_opponent(player).participant.vars['tag'], pred_tag = predecessor_tag(player), first_gen= player.session_gen == 1, last_per=player.subsession.last_period, delta=player.subsession.delta, first_period = False, r_advice = player.participant.vars['r_advice'], g_advice=player.participant.vars['g_advice'], opp = get_opponent(player), stage = player.stage,) # give advice class EndOfMatch(Page): form_model = 'player' form_fields = ['g_advice'] @staticmethod def is_displayed(player: Player): return (player.subsession.last_period and player.stage == 0 and not player.session.config['gen_end']) @staticmethod def vars_for_template(player: Player): opponent = get_opponent(player) #player.in_all_rounds().g_advice = player.g_advice player.participant.vars['last_round'] = player.subsession.round_number return dict( roll=player.subsession.dice_roll, round = player.subsession.round_number, history_Ccolor = "style=\"background-color:"+C.history_color[True]+"\"", history_Dcolor = "style=\"background-color:"+C.history_color[False]+"\"", Dbutton_color= C.active_color[False], Cbutton_color= C.active_color[True], opponent=opponent, tag = player.participant.vars['tag'], opp_tag = get_opponent(player).participant.vars['tag'], succ_tag= successor_tag(player), succ_opp_tag= successor_tag(get_opponent(player)), pred_tag = predecessor_tag(player), opp_succ_tag= successor_tag(get_opponent(player)), sessionid=player.session.id, same_choice=player.cooperate == opponent.cooperate, my_decision=player.field_display('cooperate'), opponent_decision=opponent.field_display('cooperate'), first_period = False, history = player.participant.vars['match_history'], delta=player.subsession.delta, r_advice=player.participant.vars['r_advice'], first_gen= player.session_gen == 1, per= player.subsession.round,) @staticmethod def before_next_page(player, timeout_happened): player.participant.vars['g_advice'] = player.g_advice class SaveLocal(WaitPage): template_name = 'GPD/PreWait.html' @staticmethod def is_displayed(player: Player): N = player.subsession.num_questions # NEW CODE AS OF 04-04-2026 (3:08 PM) --- attempting to fix the error of being asked to interpret received advice as the first generation return (player.subsession.last_period and not player.session.config['gen_end'] and player.stage <= 0) or\ (player.stage == player.subsession.num_questions and player.session_gen > 1) # OLD CODE AS OF 04-04-2026 (3:08 PM) --- attempting to fix the error of being asked to interpret received advice as the first generation #return (player.subsession.last_period and not player.session.config['gen_end'] and player.stage <= 0) or\ # player.stage == player.subsession.num_questions @staticmethod def vars_for_template(player: Player): opp = get_opponent(player) player.r_survey = player.participant.vars['rfirst'] if player.stage == player.subsession.num_questions: player.r_survey = not player.r_survey if player.r_survey: advice = player.participant.vars['r_advice'] else: advice = player.participant.vars['g_advice'] return { 'inactive':player.stage<0, 'r_advice': player.participant.vars['r_advice'], 'rsurvey':player.r_survey, 'survey_instr': (player.stage == 0 or player.stage == player.subsession.num_questions), 'stage':player.stage, 'pred_tag': predecessor_tag(player), 'pred_opp_tag': predecessor_tag(opp), 'advice': advice, 'tag': player.participant.vars['tag'], 'opp_tag': opp.participant.vars['tag'], 'succ_tag': successor_tag(player), 'succ_opp_tag': successor_tag(opp), } class SaveSession(WaitPage): @staticmethod def is_displayed(player: Player): return player.final_period and player.session_end @staticmethod def app_after_this_page(player: Player, upcoming_apps): player.participant.vars['rsurvey'] = sort_rresponse(player) player.participant.vars['gsurvey'] = sort_gresponse(player) player.g_advice = player.participant.vars['g_advice'] player.g_responses = bool_to_string(sort_gresponse(player)) add_player_history(player) class EndOfGame(Page): #timeout_seconds = 30 @staticmethod def is_displayed(player: Player): return player.final_period and player.session_end @staticmethod def vars_for_template(player: Player): opponent = get_opponent(player) player.participant.vars['done'] = True # points for interpreting received advice return dict( roll=player.subsession.dice_roll, round = player.subsession.round_number, asurvey =player.participant.vars['asurvey'], opp_tag = get_opponent(player).participant.vars['tag'], tag = player.participant.vars['tag'], pred_tag = predecessor_tag(player), succ_tag= successor_tag(player), opp_succ_tag= successor_tag(get_opponent(player)), asurvey2 =player.participant.vars['interprets'], opponent=opponent, same_choice=player.cooperate == opponent.cooperate, my_decision=player.field_display('cooperate'), opponent_decision=opponent.field_display('cooperate'), r_advice=player.participant.vars['r_advice'], payoff=player.participant.payoff, money_payoff = player.participant.payoff_plus_participation_fee(), end=player.session_end, final = player.final_period, gen=player.session_gen, session_continue = not player.subsession.stop_session, current_gen=player.subsession.current_gen, gpoints= player.participant.vars['gpoints'], rpoints= player.participant.vars['rpoints'], dynasty = player.group.dynasty, last = (player.session_end and not player.session.config['gen_end']), per=player.subsession.round, session=player.session_id, #id = player.session.id, id = player.participant.code # NEW CODE SO THAT IDs ARE DIFFERENT ACROSS PARTICIPANTS ) class EndWait(WaitPage): template_name = 'GPD/EndWait.html' #timeout_seconds = 30 @staticmethod def is_displayed(player: Player): return player.final_period and not player.session_end @staticmethod def vars_for_template(player: Player): opponent = get_opponent(player) player.participant.vars['done'] = True # points for interpreting received advice return dict( asurvey =player.participant.vars['asurvey'], opp_tag = get_opponent(player).participant.vars['tag'], tag = player.participant.vars['tag'], pred_tag = predecessor_tag(player), succ_tag= successor_tag(player), opp_succ_tag= successor_tag(get_opponent(player)), asurvey2 =player.participant.vars['interprets'], opponent=opponent, same_choice=player.cooperate == opponent.cooperate, my_decision=player.field_display('cooperate'), opponent_decision=opponent.field_display('cooperate'), roll=player.subsession.dice_roll, r_advice=player.participant.vars['r_advice'], payoff=player.participant.payoff, money_payoff = player.participant.payoff_plus_participation_fee(), end=player.session_end, final = player.final_period, gen=player.session_gen, session_continue = not player.subsession.stop_session, current_gen=player.subsession.current_gen, gpoints= player.participant.vars['gpoints'], rpoints= player.participant.vars['rpoints'], dynasty = player.group.dynasty, last = (player.session_end and not player.session.config['gen_end']), per=player.subsession.round, session=player.session_id, id=str(player.participant.id)+str(player.side), ) class WaitForGen2(WaitPage): @staticmethod def is_displayed(player: Player): return player.session_gen == 1 and player.participant.vars.get('wait', False) and not player.final_period # page_sequence = [Introduction, # Decision, React, # Survey, # ResultsWaitPage, Results1, # Results, EndOfMatch, # SaveLocal, SaveSession, EndOfGame, EndWait] page_sequence = [Introduction, Decision, React, Survey, WaitForGen2, ResultsWaitPage, Results1, Results, EndOfMatch, SaveLocal, SaveSession, EndOfGame, EndWait] # page_sequence = [Introduction, Decision, ResultsWaitPage, ResultsPage, WaitGroup, Results] # END OF FILE ==============================================================================================================