from otree.api import * import random import time import warnings warnings.filterwarnings('ignore') import logging logging.getLogger('websockets').setLevel(logging.CRITICAL) logging.getLogger('websockets.legacy.server').setLevel(logging.CRITICAL) doc = """ Multiplayer Gambling """ class C(BaseConstants): NAME_IN_URL = 'multiplayer_app' PLAYERS_PER_GROUP = 3 NUM_ROUNDS = 192 TRIALS_PER_BLOCK = 16 NUM_TRAINING_BLOCKS = 6 NUM_TEST_BLOCKS = 6 TRAINING_ROUNDS = 96 TEST_ROUNDS = 96 payoffFullCons = 2 payoffHalfCons = 1 payoffDiss = 0 images = ["diamond", "square", "triangle", "circle", "gear", "teardrop", "oval", "hex"] highRewPairs = { 0: [1, 2, 3], 1: [0, 2, 3], 2: [0, 1, 3], 3: [0, 1, 2] } lowRewPairs = { 4: [5, 6, 7], 5: [4, 6, 7], 6: [4, 5, 7], 7: [4, 5, 6] } class Subsession(BaseSubsession): # subsessions include pre-rating, trials, post-rating images = models.StringField() class Group(BaseGroup): # group of players. this experiment only has 1 group composed of 3 players fullConsensus = models.BooleanField(initial=False) reward_left = models.FloatField(initial=0) reward_right = models.FloatField(initial=0) reward_left_string = models.StringField(initial='') reward_right_string = models.StringField(initial='') randomDraw = models.IntegerField(initial=0) randomAttentionKey = models.IntegerField(initial=0) attentionKey = models.IntegerField(initial=0) images_left = models.StringField(initial='') images_right = models.StringField(initial='') randomDrawProbe = models.IntegerField(initial=0) rewardLev = models.IntegerField(initial=0) probeTypeCurr = models.IntegerField(initial=0) probeTrialCount = models.IntegerField(initial=0) images = models.StringField(initial='') shapesSocial = models.StringField(initial='') shapesIndividual = models.StringField(initial='') class Player(BasePlayer): chosBandit = models.StringField(initial='') fullConsensus = models.BooleanField(initial=False) socialLocation = models.StringField(initial='') placement = models.StringField(initial='') rewardWin = models.BooleanField(initial=False) condition = models.StringField(initial='') images = models.StringField(initial='') name = models.StringField() player1_name = models.StringField() player2_name = models.StringField() player3_name = models.StringField() block_type = models.StringField() # 'social', 'individual', or 'test' phase = models.StringField() # training or test original_reward_level = models.IntegerField() # 0 or 1 before reversal trial_type = models.IntegerField() left_shape_reward_level = models.StringField(blank=True) right_shape_reward_level = models.StringField(blank=True) #timing data experiment_start_time = models.FloatField(blank=True) stimulus_onset_time = models.FloatField(blank=True) response_time = models.FloatField(blank=True) selection_highlight_time = models.FloatField(blank=True) # same as response_time choice_wait_start_time = models.FloatField(blank=True) select_reveal_start_time = models.FloatField(blank=True) social_reveal_start_time = models.FloatField(blank=True) condition_reveal_start_time = models.FloatField(blank=True) reward_reveal_start_time = models.FloatField(blank=True) reaction_time = models.FloatField(blank=True) def get_current_phase(round_number): return 'training' if round_number <= 96 else 'test' def get_block_number(round_number): return ((round_number - 1) // 16) + 1 def get_block_type(player): block_num = get_block_number(player.round_number) order = player.session.vars['block_type_order'] if order == 'social_first': return 'social' if block_num % 2 == 1 else 'individual' else: return 'individual' if block_num % 2 == 1 else 'social' def set_trial_metadata(player): phase = get_current_phase(player.round_number) player.phase = phase player.block_type = get_block_type(player) trialType = player.session.vars['trialType'][player.round_number - 1] if trialType == 1: player.original_reward_level = player.session.vars['rewardLevel'][player.round_number - 1] else: player.original_reward_level = None def live_choice_timing(player, data): if 'timing_data' in data: player.stimulus_onset_time = float(data['timing_data']['stimulus_onset']) player.response_time = float(data['timing_data']['response_time']) player.selection_highlight_time = player.response_time player.reaction_time = float(data['timing_data']['reaction_time']) return {} def live_probe_choice(player, data): if 'timing_data' in data: player.stimulus_onset_time = float(data['timing_data']['stimulus_onset']) player.response_time = float(data['timing_data']['response_time']) player.selection_highlight_time = player.response_time player.reaction_time = float(data['timing_data']['reaction_time']) print(f"Received timing data: {data['timing_data']}") return {} def creating_session(subsession: Subsession): if subsession.round_number == 1: session = subsession.session session.vars['images'] = random.sample(C.images, k=len(C.images)) highIndex = [0, 1, 2, 3] lowIndex = [4, 5, 6, 7] random.shuffle(highIndex) random.shuffle(lowIndex) session.vars['socialBlockIndex'] = highIndex[:2] + lowIndex[:2] session.vars['individualBlockIndex'] = highIndex[2:] + lowIndex[2:] random.shuffle(session.vars['socialBlockIndex']) random.shuffle(session.vars['individualBlockIndex']) socialHigh = [i for i in session.vars['socialBlockIndex'] if i < 4] socialLow = [i for i in session.vars['socialBlockIndex'] if i >= 4] individualHigh = [i for i in session.vars['individualBlockIndex'] if i < 4] individualLow = [i for i in session.vars['individualBlockIndex'] if i >= 4] images = session.vars['images'] socialShapeNames = [images[i] for i in session.vars['socialBlockIndex']] individualShapeNames = [images[i] for i in session.vars['individualBlockIndex']] session.vars['shapesSocial'] = socialShapeNames session.vars['shapesIndividual'] = individualShapeNames for group in subsession.get_groups(): group.shapesSocial = ','.join(session.vars['shapesSocial']) group.shapesIndividual = ','.join(session.vars['shapesIndividual']) trialType = [] rewardLevel = [] probeType = [] for block in range(12): block_rewards = [1] * 6 + [0] * 6 random.shuffle(block_rewards) block_probes = [1, 1, 2, 2] random.shuffle(block_probes) if block < 2: # 1st block of each condition: gambling first, then probes block_trial_type = [1] * 12 + [0] * 4 block_reward_level = block_rewards + [None] * 4 block_probe_type = [None] * 12 + block_probes else: # all other blocks: interleaved block_trial_type = [1] * 12 + [0] * 4 random.shuffle(block_trial_type) block_reward_level = [] block_probe_type = [] normal_idx = 0 probe_idx = 0 for i in block_trial_type: if i == 1: block_reward_level.append(block_rewards[normal_idx]) block_probe_type.append(None) normal_idx += 1 else: block_reward_level.append(None) block_probe_type.append(block_probes[probe_idx]) probe_idx += 1 trialType.extend(block_trial_type) rewardLevel.extend(block_reward_level) probeType.extend(block_probe_type) session.vars['trialType'] = trialType session.vars['rewardLevel'] = rewardLevel session.vars['probeType'] = probeType session.vars['randomDrawHighSocial'] = random.sample(socialHigh * 50, k=96) session.vars['randomDrawLowSocial'] = random.sample(socialLow * 50, k=96) session.vars['randomDrawHighIndividual'] = random.sample(individualHigh * 50, k=96) session.vars['randomDrawLowIndividual'] = random.sample(individualLow * 50, k=96) session.vars['block_type_order'] = random.choice(['social_first', 'individual_first']) session.vars['center_positions'] = [random.randint(0, 1) for _ in range(192)] # Print structure by block for block in range(12): start = block * 16 end = start + 16 block_trials = trialType[start:end] block_rewards = rewardLevel[start:end] block_probes = probeType[start:end] normal_count = sum(1 for t in block_trials if t == 1) probe_count = sum(1 for t in block_trials if t == 0) phase = 'training' if block < 6 else 'test' block_type = 'social' if (block + 1) % 2 == 1 else 'individual' print(f"Block {block+1} ({phase}, {block_type}): {normal_count} normal, {probe_count} probes") currentRound = subsession.round_number groups = subsession.get_groups() group = groups[0] trialType = subsession.session.vars['trialType'] probeCount = 0 for roundNum in range(1, currentRound + 1): if trialType[roundNum - 1] == 0: probeCount += 1 if trialType[currentRound - 1] == 0: group.probeTrialCount = probeCount # PAGES class Instructions(Page): @staticmethod def vars_for_template(player: Player): group = player.group class PreRating(Page): @staticmethod def vars_for_template(player: Player): group = player.group class PreRatingWait(WaitPage): pass class FixationProbe(Page): form_model = 'player' timeout_seconds = 1 @staticmethod def is_displayed(player): return player.session.vars['trialType'][player.round_number-1] == 0 def vars_for_template(player: Player): group = player.group session = player.session images = session.vars['images'] phase = get_current_phase(player.round_number) blockType = get_block_type(player) probeType = session.vars['probeType'][player.round_number - 1] group.probeTypeCurr = probeType if blockType == 'social': blockIndex = session.vars['socialBlockIndex'] else: blockIndex = session.vars['individualBlockIndex'] highShapesInBlock = [i for i in blockIndex if i < 4] lowShapesInBlock = [i for i in blockIndex if i >= 4] highShapeIndex = random.choice(highShapesInBlock) lowShapeIndex = random.choice(lowShapesInBlock) if probeType == 1: group.images_left = images[highShapeIndex] group.images_right = images[lowShapeIndex] player.condition = 'high_low' player.left_shape_reward_level = 'high' player.right_shape_reward_level = 'low' else: group.images_left = images[lowShapeIndex] group.images_right = images[highShapeIndex] player.condition = 'low_high' player.left_shape_reward_level = 'low' player.right_shape_reward_level = 'high' player.trial_type = 0 print(f"\n=== FIXATION PROBE (Round {player.round_number}) ===") print(f"Phase: {phase}, BlockType: {blockType}") print(f"ProbeType: {probeType} (1=high left, 2=low left)") print(f"Left shape: {group.images_left} ({player.left_shape_reward_level})") print(f"Right shape: {group.images_right} ({player.right_shape_reward_level})") return dict( avatar = "images/person.png", imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right) ) class ProbeChoice(Page): form_model = 'player' form_fields = ['chosBandit'] live_method = 'live_probe_choice' @staticmethod def is_displayed(player): return player.session.vars['trialType'][player.round_number-1] == 0 def vars_for_template(player: Player): group = player.group session = player.session block_type = get_block_type(player) phase = get_current_phase(player.round_number) # Show avatars for social training probes show_avatars = (block_type == 'social') player1_name = '' player2_name = '' player3_name = '' if show_avatars: players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( avatar="images/person.png", imageLeft="images/{}.png".format(group.images_left), imageRight="images/{}.png".format(group.images_right), block_type=block_type, show_avatars=show_avatars, player1_name=player1_name, player2_name=player2_name, player3_name=player3_name ) def js_vars(player: Player): group = player.group session = player.session block_type = get_block_type(player) phase = get_current_phase(player.round_number) show_avatars = (block_type == 'social') center_position = 0 player1_name = '' player2_name = '' player3_name = '' if show_avatars: center_position = session.vars['center_positions'][player.round_number - 1] players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( block_type=block_type, show_avatars=show_avatars, center_position=center_position, player1_name=player1_name, player2_name=player2_name, player3_name=player3_name, playerid=player.id_in_group, ) def before_next_page(player: Player, timeout_happened): player.chosBandit = player.chosBandit player.experiment_start_time = player.participant.vars.get('experiment_start_time') set_trial_metadata(player) class ProbeChoiceWait(WaitPage): template_name = 'multiplayer_app/ProbeChoiceWait.html' @staticmethod def is_displayed(player): return player.session.vars['trialType'][player.round_number-1] == 0 def vars_for_template(player): group = player.group session = player.session block_type = get_block_type(player) phase = get_current_phase(player.round_number) show_avatars = (block_type == 'social') player1_name = '' player2_name = '' player3_name = '' if show_avatars: players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( avatar="images/person.png", imageLeft="images/{}.png".format(group.images_left), imageRight="images/{}.png".format(group.images_right), block_type=block_type, show_avatars=show_avatars, player1_name=player1_name, player2_name=player2_name, player3_name=player3_name ) def js_vars(player): group = player.group session = player.session block_type = get_block_type(player) phase = get_current_phase(player.round_number) show_avatars = (block_type == 'social') center_position = 0 player1_name = '' player2_name = '' player3_name = '' if show_avatars: center_position = session.vars['center_positions'][player.round_number - 1] players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( chosBandit=player.chosBandit, block_type=block_type, show_avatars=show_avatars, center_position=center_position, player1_name=player1_name, player2_name=player2_name, player3_name=player3_name, playerid=player.id_in_group, ) def after_all_players_arrive(group: Group): current_time = time.time() for player in group.get_players(): experiment_start = player.participant.vars.get('experiment_start_time', current_time) player.choice_wait_start_time = current_time - experiment_start # Calculate placements for social training probes player_lists = group.get_players() player1, player2, player3 = player_lists[0], player_lists[1], player_lists[2] if player1.chosBandit == "37": if player2.chosBandit == "37": if player3.chosBandit == "37": for p in player_lists: p.placement = "1" else: for p in player_lists: p.placement = "2" else: if player3.chosBandit == "37": for p in player_lists: p.placement = "3" else: for p in player_lists: p.placement = "4" else: if player2.chosBandit == "37": if player3.chosBandit == "37": for p in player_lists: p.placement = "5" else: for p in player_lists: p.placement = "6" else: if player3.chosBandit == "37": for p in player_lists: p.placement = "7" else: for p in player_lists: p.placement = "8" class ProbeSocialReveal(Page): form_model = 'player' timeout_seconds = 1.5 @staticmethod def is_displayed(player): # only show for probe trials in social blocks during training if player.session.vars['trialType'][player.round_number-1] != 0: return False block_type = get_block_type(player) phase = get_current_phase(player.round_number) return block_type == 'social' and phase == 'training' def vars_for_template(player: Player): group = player.group session = player.session image_avatar = "person" players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( imageLeft="images/{}.png".format(group.images_left), imageRight="images/{}.png".format(group.images_right), avatar="images/{}.png".format(image_avatar), player1_name=player1_name, player2_name=player2_name, player3_name=player3_name ) def js_vars(player): group = player.group session = player.session players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' center_position = session.vars['center_positions'][player.round_number - 1] return dict( chosBandit=player.chosBandit, placement=player.placement, playerid=player.id_in_group, name=player.participant.name, center_position=center_position, player1_name=player1_name, player2_name=player2_name, player3_name=player3_name ) class Fixation(Page): form_model = 'player' timeout_seconds = 1 @staticmethod def is_displayed(player): return player.session.vars['trialType'][player.round_number-1] == 1 def vars_for_template(player: Player): group = player.group session = player.session images = session.vars['images'] phase = get_current_phase(player.round_number) blockType = get_block_type(player) blockNum = get_block_number(player.round_number) rewardLevel = session.vars['rewardLevel'][player.round_number - 1] if phase == 'test': rewardLevel = 1 - rewardLevel group.rewardLev = rewardLevel if blockType == 'social': blockTypeNum = (blockNum + 1) // 2 - 1 randomDrawHigh = session.vars['randomDrawHighSocial'] randomDrawLow = session.vars['randomDrawLowSocial'] blockShapes = session.vars['socialBlockIndex'] else: blockTypeNum = blockNum // 2 - 1 randomDrawHigh = session.vars['randomDrawHighIndividual'] randomDrawLow = session.vars['randomDrawLowIndividual'] blockShapes = session.vars['individualBlockIndex'] trialInBlock = (player.round_number - 1) % 16 blockTypeTrialIndex = blockTypeNum * 16 + trialInBlock if rewardLevel == 1: group.randomDraw = randomDrawHigh[blockTypeTrialIndex] possiblePairs = [i for i in blockShapes if i < 4 and i != group.randomDraw] else: group.randomDraw = randomDrawLow[blockTypeTrialIndex] possiblePairs = [i for i in blockShapes if i >= 4 and i != group.randomDraw] group.images_left = images[group.randomDraw] pairedShape = random.choice(possiblePairs) group.images_right = images[pairedShape] player.trial_type = 1 print(f"\n=== FIXATION (Round {player.round_number}) ===") print(f"Phase: {phase}, Block: {blockNum}, BlockType: {blockType}") print(f"RewardLevel (after reversal): {rewardLevel}, Original: {session.vars['rewardLevel'][player.round_number - 1]}") print(f"Left shape: {group.images_left}, Right shape: {group.images_right}") return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right) ) class Choice(Page): form_model = 'player' form_fields = ['chosBandit'] live_method = 'live_choice_timing' @staticmethod def is_displayed(player): return player.session.vars['trialType'][player.round_number-1] == 1 def vars_for_template(player: Player): group = player.group session = player.session images = session.vars['images'] rewardLevel = session.vars['rewardLevel'] group.images = ','.join(images) images_left,images_right = group.images_left,group.images_right image_avatar = "person" phase = get_current_phase(player.round_number) block_type = get_block_type(player) # For social blocks, get player names player1_name = '' player2_name = '' player3_name = '' if block_type == 'social': center_position = session.vars['center_positions'][player.round_number - 1] players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), avatar = "images/{}.png".format(image_avatar), block_type = block_type, player1_name = player1_name, player2_name = player2_name, player3_name = player3_name ) player.chosBandit = player.chosBandit def js_vars(player: Player): group = player.group session = player.session phase = get_current_phase(player.round_number) block_type = get_block_type(player) center_position = 0 player1_name = '' player2_name = '' player3_name = '' if block_type == 'social': center_position = session.vars['center_positions'][player.round_number - 1] players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( block_type = block_type, center_position = center_position, player1_name = player1_name, player2_name = player2_name, player3_name = player3_name, playerid = player.id_in_group, ) def before_next_page(player: Player, timeout_happened): if player.round_number == 1: start_time = time.time() player.participant.vars['experiment_start_time'] = start_time player.experiment_start_time = player.participant.vars.get('experiment_start_time') set_trial_metadata(player) class ChoiceWait(WaitPage): template_name = 'multiplayer_app/ChoiceWait.html' @staticmethod def is_displayed(player): return player.session.vars['trialType'][player.round_number-1] == 1 def vars_for_template(player): group = player.group chosBandit = player.chosBandit images_left,images_right = group.images_left,group.images_right session = player.session images = session.vars['images'] rewardLevel = session.vars['rewardLevel'][player.round_number - 1] phase = get_current_phase(player.round_number) if phase == 'test': rewardLevel = 1 - rewardLevel group.rewardLev = rewardLevel image_avatar = "person" if group.rewardLev == 1: #high group.reward_left = abs(round(random.gauss(450, 100) / 100, 2)) group.reward_right = abs(round(random.gauss(450, 100) / 100, 2)) diff = abs(group.reward_left-group.reward_right) if diff <= 0.1: chose = random.choice((group.reward_left, group.reward_right)) if chose == group.reward_left: group.reward_left = group.reward_left + .2 elif chose == group.reward_right: group.reward_right = group.reward_right + .2 group.reward_left_string = str("%.2f" % group.reward_left) group.reward_right_string = str("%.2f" % group.reward_right) elif group.rewardLev == 0: group.reward_left = abs(round(random.gauss(200, 100) / 100, 2)) group.reward_right = abs(round(random.gauss(200, 100) / 100, 2)) diff = abs(group.reward_left-group.reward_right) if diff <= 0.1: chose = random.choice((group.reward_left, group.reward_right)) if chose == group.reward_left: group.reward_left = group.reward_left + .2 elif chose == group.reward_right: group.reward_right = group.reward_right + .2 group.reward_left_string = str("%.2f" % group.reward_left) group.reward_right_string = str("%.2f" % group.reward_right) phase = get_current_phase(player.round_number) block_type = get_block_type(player) print(f"\n=== CHOICE WAIT (Round {player.round_number}) ===") print(f"Phase: {phase}, BlockType: {block_type}") print(f"RewardLevel: {group.rewardLev}") print(f"Reward left: {group.reward_left}, Reward right: {group.reward_right}") # For social blocks, get player names player1_name = '' player2_name = '' player3_name = '' if block_type == 'social': center_position = session.vars['center_positions'][player.round_number - 1] players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), avatar = "images/{}.png".format(image_avatar), block_type = block_type, player1_name = player1_name, player2_name = player2_name, player3_name = player3_name ) def js_vars(player: Player): group = player.group session = player.session phase = get_current_phase(player.round_number) block_type = get_block_type(player) center_position = 0 player1_name = '' player2_name = '' player3_name = '' if block_type == 'social': center_position = session.vars['center_positions'][player.round_number - 1] players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( block_type = block_type, center_position = center_position, player1_name = player1_name, player2_name = player2_name, player3_name = player3_name, playerid = player.id_in_group, chosBandit=player.chosBandit ) def after_all_players_arrive(group: Group): player_lists = group.get_players() player1, player2, player3 = player_lists[0], player_lists[1], player_lists[2] if player1.chosBandit == "37": if player2.chosBandit == "37": if player3.chosBandit == "37": # 1,2,3 v group.fullConsensus = True for i in range (1,4): locals()[f"player{i}"].payoff = C.payoffFullCons locals()[f"player{i}"].socialLocation = "left" locals()[f"player{i}"].placement = "1" elif player3.chosBandit == "39": # 1,2 v 3 player1.payoff,player2.payoff,player3.payoff = C.payoffHalfCons,C.payoffHalfCons,C.payoffDiss player1.socialLocation,player2.socialLocation,player3.socialLocation = "left","left","right" group.fullConsensus = False for i in range (1,4): locals()[f"player{i}"].placement = "2" # LLR elif player2.chosBandit == "39": if player3.chosBandit == "37": # 1,3 v 2 player1.payoff,player2.payoff,player3.payoff = C.payoffHalfCons,C.payoffDiss,C.payoffHalfCons player1.socialLocation,player2.socialLocation,player3.socialLocation = "left","right","left" group.fullConsensus = False for i in range (1,4): locals()[f"player{i}"].placement = "3" # LRL elif player3.chosBandit == "39": # 1 v 2,3 player1.payoff,player2.payoff,player3.payoff = C.payoffDiss,C.payoffHalfCons,C.payoffHalfCons player1.socialLocation,player2.socialLocation,player3.socialLocation = "left","right","right" group.fullConsensus = False for i in range (1,4): locals()[f"player{i}"].placement = "4" # LRR elif player1.chosBandit == "39": if player2.chosBandit == "37": if player3.chosBandit == "37": # 2,3 v 1 player1.payoff,player2.payoff,player3.payoff = C.payoffDiss,C.payoffHalfCons,C.payoffHalfCons player1.socialLocation,player2.socialLocation,player3.socialLocation = "right","left","left" group.fullConsensus = False for i in range (1,4): locals()[f"player{i}"].placement = "5" # RLL elif player3.chosBandit == "39": # 2 v 1,3 player1.payoff,player2.payoff,player3.payoff = C.payoffHalfCons,C.payoffDiss,C.payoffHalfCons player1.socialLocation,player2.socialLocation,player3.socialLocation = "right","left","right" group.fullConsensus = False for i in range (1,4): locals()[f"player{i}"].placement = "6" # RLR elif player2.chosBandit == "39": if player3.chosBandit == "37": # 3 v 1,2 player1.payoff,player2.payoff,player3.payoff = C.payoffHalfCons,C.payoffHalfCons,C.payoffDiss player1.socialLocation,player2.socialLocation,player3.socialLocation = "right","right","left" group.fullConsensus = False for i in range (1,4): locals()[f"player{i}"].placement = "7" # RRL elif player3.chosBandit == "39": # v 1,2,3 for i in range (1,4): locals()[f"player{i}"].payoff = C.payoffFullCons locals()[f"player{i}"].socialLocation = "right" locals()[f"player{i}"].placement = "8" # RRR group.fullConsensus = True current_time = time.time() for player in group.get_players(): experiment_start = player.participant.vars.get('experiment_start_time', current_time) player.choice_wait_start_time = current_time - experiment_start class SelectReveal(Page): form_model = 'player' form_fields = ['chosBandit'] timeout_seconds = 1 @staticmethod def is_displayed(player): return player.session.vars['trialType'][player.round_number-1] == 1 def vars_for_template(player: Player): group = player.group chosBandit = player.chosBandit session = player.session images_left,images_right = group.images_left,group.images_right images = session.vars['images'] image_avatar = "person" if player.chosBandit == "37": if group.reward_left > group.reward_right: player.rewardWin = True elif group.reward_left < group.reward_right: player.rewardWin = False elif player.chosBandit == "39": if group.reward_left < group.reward_right: player.rewardWin = True elif group.reward_left > group.reward_right: player.rewardWin = False phase = get_current_phase(player.round_number) rewardLevel = session.vars['rewardLevel'][player.round_number - 1] if phase == 'test': rewardLevel = 1 - rewardLevel group.rewardLev = rewardLevel block_type = get_block_type(player) player1_name = '' player2_name = '' player3_name = '' if block_type == 'social': players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), avatar = "images/{}.png".format(image_avatar), block_type = block_type, player1_name = player1_name, player2_name = player2_name, player3_name = player3_name, ) def js_vars(player): group = player.group session = player.session phase = get_current_phase(player.round_number) block_type = get_block_type(player) center_position = 0 if block_type == 'social': center_position = session.vars['center_positions'][player.round_number - 1] player1_name = '' player2_name = '' player3_name = '' if block_type == 'social': players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' return dict( chosBandit=player.chosBandit, rewardWin = player.rewardWin, block_type = block_type, center_position = center_position, player1_name = player1_name, player2_name = player2_name, player3_name = player3_name, playerid = player.id_in_group, ) def before_next_page(player: Player, timeout_happened): player.chosBandit = player.chosBandit current_time = time.time() experiment_start = player.participant.vars.get('experiment_start_time', current_time) player.select_reveal_start_time = current_time - experiment_start class SocialReveal(Page): form_model = 'player' form_fields = ['chosBandit'] timeout_seconds = 1.5 @staticmethod def is_displayed(player): if player.session.vars['trialType'][player.round_number-1] != 1: return False blockType = get_block_type(player) return blockType == 'social' def vars_for_template(player: Player): group = player.group session = player.session chosBandit = player.chosBandit players,others = group.get_players(),player.get_others_in_group() images_left,images_right = group.images_left,group.images_right image_avatar = "person" player.player1_name,player.player2_name,player.player3_name = players[0].participant.name,players[1].participant.name,players[2].participant.name images = session.vars['images'] if player.rewardWin == True: if player.payoff == 0: player.condition = '3' return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), avatar = "images/{}.png".format(image_avatar) ) else: if group.fullConsensus == 1: player.condition = '1' return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), avatar = "images/{}.png".format(image_avatar) ) else: player.condition = '1_partial' return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), avatar = "images/{}.png".format(image_avatar) ) elif player.rewardWin == False: if player.payoff == 0: player.condition = '4' return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), avatar = "images/{}.png".format(image_avatar) ) else: if group.fullConsensus == 1: player.condition = '2' return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), avatar = "images/{}.png".format(image_avatar) ) else: player.condition = '2_partial' return dict( imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), avatar = "images/{}.png".format(image_avatar) ) phase = get_current_phase(player.round_number) block_type = get_block_type(player) return dict( avatar = "images/{}.png".format(image_avatar), avatar_2 = "images/{}.png".format(image_avatar), avatar_3 = "images/{}.png".format(image_avatar) ) player.chosBandit = chosBandit group.reward_left_string = str("%.2f" % group.reward_left) group.reward_right_string = str("%.2f" % group.reward_right) def js_vars(player): group = player.group players = group.get_players() player1_name = players[0].participant.name or 'Player 1' player2_name = players[1].participant.name or 'Player 2' player3_name = players[2].participant.name or 'Player 3' center_position = player.session.vars['center_positions'][player.round_number - 1] return dict( chosBandit=player.chosBandit, placement = player.placement, playerid = player.id_in_group, name = player.participant.name, condition = player.condition, rewardWin = player.rewardWin, center_position = center_position, player1_name = player1_name, player2_name = player2_name, player3_name = player3_name ) def before_next_page(player: Player, timeout_happened): player.chosBandit = player.chosBandit current_time = time.time() experiment_start = player.participant.vars.get('experiment_start_time', current_time) player.social_reveal_start_time = current_time - experiment_start class ConditionReveal(Page): form_model = 'player' form_fields = ['chosBandit'] timeout_seconds = 2 @staticmethod def is_displayed(player): return player.session.vars['trialType'][player.round_number-1] == 1 def vars_for_template(player: Player): group = player.group session = player.session reward_left,reward_right = group.reward_left,group.reward_right image_avatar = "person" players,others = group.get_players(),player.get_others_in_group() images_left,images_right = group.images_left,group.images_right player.player1_name,player.player2_name,player.player3_name = players[0].participant.name,players[1].participant.name,players[2].participant.name images = session.vars['images'] phase = get_current_phase(player.round_number) block_type = get_block_type(player) return dict( avatar = "images/{}.png".format(image_avatar), avatar_2 = "images/{}.png".format(image_avatar), avatar_3 = "images/{}.png".format(image_avatar), imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), block_type = block_type ) if player.chosBandit == "37": if group.reward_left > group.reward_right: group.reward_right = 0 elif group.reward_left < group.reward_right: group.reward_left = 0 elif player.chosBandit == "39": if group.reward_left < group.reward_right: group.reward_left = 0 elif group.reward_left > group.reward_right: group.reward_right = 0 group.reward_left_string = str("%.2f" % group.reward_left) group.reward_right_string = str("%.2f" % group.reward_right) def js_vars(player): return dict( chosBandit=player.chosBandit, placement = player.placement, playerid = player.id_in_group, name = player.participant.name, block_type = player.block_type ) def before_next_page(player: Player, timeout_happened): player.chosBandit = player.chosBandit current_time = time.time() experiment_start = player.participant.vars.get('experiment_start_time', current_time) player.condition_reveal_start_time = current_time - experiment_start class RewardReveal(Page): form_model = 'player' form_fields = ['chosBandit'] timeout_seconds = 2 @staticmethod def is_displayed(player): return player.session.vars['trialType'][player.round_number-1] == 1 def vars_for_template(player: Player): group = player.group session = player.session chosBandit = player.chosBandit image_avatar = "person" players,others = group.get_players(),player.get_others_in_group() images_left,images_right = group.images_left,group.images_right player.player1_name,player.player2_name,player.player3_name = players[0].participant.name,players[1].participant.name,players[2].participant.name images = session.vars['images'] rewardLevel = session.vars['rewardLevel'] group.reward_left_string = str("%.2f" % group.reward_left) group.reward_right_string = str("%.2f" % group.reward_right) phase = get_current_phase(player.round_number) block_type = get_block_type(player) return dict( avatar = "images/{}.png".format(image_avatar), avatar_2 = "images/{}.png".format(image_avatar), avatar_3 = "images/{}.png".format(image_avatar), imageLeft = "images/{}.png".format(group.images_left), imageRight = "images/{}.png".format(group.images_right), block_type = block_type ) def js_vars(player): block_type = player.block_type return dict( chosBandit=player.chosBandit, placement = player.placement, playerid = player.id_in_group, name = player.participant.name, block_type = block_type ) def before_next_page(player: Player, timeout_happened): player.chosBandit = player.chosBandit current_time = time.time() experiment_start = player.participant.vars.get('experiment_start_time', current_time) player.reward_reveal_start_time = current_time - experiment_start class PostRating(Page): form_model = 'player' form_fields = ['chosBandit'] @staticmethod def vars_for_template(player: Player): group = player.group class PostRatingWait(WaitPage): pass class Debrief(Page): pass class ThankYou(Page): pass page_sequence = [ FixationProbe, ProbeChoice, ProbeChoiceWait, ProbeSocialReveal, Fixation, Choice, ChoiceWait, SelectReveal, SocialReveal, ConditionReveal, RewardReveal ] def custom_export(players): yield ['participantSessionId', 'participantNum', 'roundNum', 'payoffCons', 'choice', 'groupFullCons', 'rewardWin', 'condition','rewardLeft', 'rewardRight', 'imageLeft', 'imageRight', 'rewardLevel', 'ProbeType', "shapes", "shapesSocial", "shapesIndividual", 'phase', 'block_type', 'trial_type', 'original_reward_level', 'left_shape_reward_level', 'right_shape_reward_level'] for p in players: participant = p.participant session = p.session subsession = p.subsession group = p.group yield [participant.id_in_session, participant.code, subsession.round_number, p.payoff, p.chosBandit, group.fullConsensus, p.rewardWin, p.condition, group.reward_left, group.reward_right, group.images_left, group.images_right, group.rewardLev, group.probeTypeCurr, session.vars['images'], session.vars['shapesSocial'], session.vars['shapesIndividual'], p.phase, p.block_type, p.trial_type, p.original_reward_level, p.left_shape_reward_level, p.right_shape_reward_level]