from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random import itertools import statistics doc = """ Ultimatum game with two treatments: direct response and strategy method. In the former, one player makes an offer and the other either accepts or rejects. It comes in two flavors, with and without hypothetical questions about the second player's response to offers other than the one that is made. In the latter treatment, the second player is given a list of all possible offers, and is asked which ones to accept or reject. """ class Constants(BaseConstants): name_in_url = 'ultimatum' players_per_group = 2 num_rounds = 6 instructions_template = 'ultimatum/Instructions.html' endowment = c(100) payoff_if_rejected = c(0) offer_increment = c(10) # outgroup_rounds = [3, 4, 2] #ingroup_rounds = [5, 1, 6] outgroup_rounds = [2,5,6] ingroup_rounds = [1,3,4] offer_choices = currency_range(0, endowment, offer_increment) offer_choices_count = len(offer_choices) keep_give_amounts = [] for offer in offer_choices: keep_give_amounts.append((offer, endowment - offer)) class Subsession(BaseSubsession): def creating_session(self): assert len(self.get_players()) % 6 == 0, 'The number of players should a multiple of 6' if self.round_number == 1: self.session.vars['offer_treatment'] = [c(0)] self.session.vars['offer_control'] = [c(0)] self.session.vars['accepted_offer_values_treatment_outgroup'] = [c(0)] self.session.vars['accepted_offer_values_treatment_ingroup'] = [c(0)] self.session.vars['offer_ingroup'] = [c(0)] self.session.vars['offer_outgroup'] = [c(0)] self.session.vars['accepted_offer_values_control'] = [c(0)] self.session.vars['accepted_offer_values_treatment'] = [c(0)] self.session.vars['rejected_offer_values_control'] = [c(0)] self.session.vars['rejected_offer_values_treatment'] = [c(0)] # randomize to treatments for g in self.get_groups(): if 'use_strategy_method' in self.session.config: g.use_strategy_method = self.session.config['use_strategy_method'] else: g.use_strategy_method = random.choice([False]) def do_my_shuffle(self): if self.round_number in Constants.outgroup_rounds: players = self.get_players() white_players = [p for p in players if p.participant.vars['colour'] == 'white'] green_players = [p for p in players if p.participant.vars['colour'] == 'green'] saffron_players = [p for p in players if p.participant.vars['colour'] == 'saffron'] random.shuffle(white_players) random.shuffle(green_players) random.shuffle(saffron_players) print('shuffled whites', white_players) print('shuffled greens', green_players) print('shuffled saffrons', saffron_players) group_matrix = [] # pop elements from M_players until it's empty while green_players: new_group = [ green_players.pop(), saffron_players.pop(), ] group_matrix.append(new_group) while white_players: new_group = [ white_players.pop(), white_players.pop(), ] group_matrix.append(new_group) self.set_group_matrix(group_matrix) print('Group Matrix for this', self.round_number, 'round is', group_matrix) elif self.round_number in Constants.ingroup_rounds: players = self.get_players() white_players = [p for p in players if p.participant.vars['colour'] == 'white'] green_players = [p for p in players if p.participant.vars['colour'] == 'green'] saffron_players = [p for p in players if p.participant.vars['colour'] == 'saffron'] random.shuffle(white_players) random.shuffle(green_players) random.shuffle(saffron_players) print('shuffled whites', white_players) print('shuffled greens', green_players) print('shuffled saffrons', saffron_players) group_matrix = [] # pop elements from M_players until it's empty while green_players: new_group = [ green_players.pop(), green_players.pop(), ] group_matrix.append(new_group) while saffron_players: new_group = [ saffron_players.pop(), saffron_players.pop(), ] group_matrix.append(new_group) while white_players: new_group = [ white_players.pop(), white_players.pop(), ] group_matrix.append(new_group) self.set_group_matrix(group_matrix) print('Group Matrix for this', self.round_number, 'round is', group_matrix) def collate_offers(self): for gp in self.get_groups(): players = self.get_players() for p in players: while p.participant.vars['treatment_indicator'] == 'no_treatment': if gp.offer_accepted == 1: self.session.vars['accepted_offer_values_control'].append(gp.amount_offered) print('accepted offers in control',self.session.vars['accepted_offer_values_control']) elif gp.offer_accepted == 0: self.session.vars['rejected_offer_values_control'].append(gp.amount_offered) print('rejected offers in control', self.session.vars['rejected_offer_values_control']) while p.participant.vars['treatment_indicator'] == 'group_treatment': if gp.offer_accepted == 1: self.session.vars['accepted_offer_values_treatment'].append(gp.amount_offered) print('accepted offers in treatment',self.session.vars['accepted_offer_values_treatment']) elif gp.offer_accepted == 0: self.session.vars['rejected_offer_values'].append(gp.amount_offered) print('rejected offers in treatment', self.session.vars['rejected_offer_values_treatment']) def make_field(amount): return models.BooleanField( widget=widgets.RadioSelectHorizontal, label='Would you accept an offer of {}?'.format(c(amount))) class Group(BaseGroup): use_strategy_method = models.BooleanField( doc="""Whether this group uses strategy method""" ) amount_offered = models.CurrencyField(choices=Constants.offer_choices) offer_accepted = models.BooleanField( doc="if offered amount is accepted (direct response method)" ) # for strategy method, see the make_field function above response_0 = make_field(0) response_10 = make_field(10) response_20 = make_field(20) response_30 = make_field(30) response_40 = make_field(40) response_50 = make_field(50) response_60 = make_field(60) response_70 = make_field(70) response_80 = make_field(80) response_90 = make_field(90) response_100 = make_field(100) def set_payoffs(self): p1, p2 = self.get_players() if self.use_strategy_method: self.offer_accepted = getattr(self, 'response_{}'.format( int(self.amount_offered))) if self.offer_accepted: p1.player_amount_sent = self.amount_offered p1.payoff = Constants.endowment - self.amount_offered p2.payoff = self.amount_offered if p1.participant.vars['treatment_indicator'] == 'no_treatment': self.session.vars['accepted_offer_values_control'].append(self.amount_offered) print('accepted offers in control', self.session.vars['accepted_offer_values_control']) self.session.vars['offer_control'].append(self.amount_offered) print('offers in control', self.session.vars['offer_control']) elif p1.participant.vars['treatment_indicator'] == 'group_treatment': self.session.vars['accepted_offer_values_treatment'].append(self.amount_offered) print('accepted offers in treatment', self.session.vars['accepted_offer_values_treatment']) self.session.vars['offer_treatment'].append(self.amount_offered) print('offers in treatment', self.session.vars['offer_treatment']) if self.round_number in Constants.outgroup_rounds: self.session.vars['accepted_offer_values_treatment_outgroup'].append(self.amount_offered) print('accepted offers in treatment', self.session.vars['accepted_offer_values_treatment_outgroup']) self.session.vars['offer_outgroup'].append(self.amount_offered) print('offers in outgroup rounds', self.session.vars['offer_outgroup']) elif self.round_number in Constants.ingroup_rounds: self.session.vars['accepted_offer_values_treatment_ingroup'].append(self.amount_offered) print('accepted offers in treatment', self.session.vars['accepted_offer_values_treatment_ingroup']) self.session.vars['offer_ingroup'].append(self.amount_offered) print('offers in ingroup rounds', self.session.vars['offer_ingroup']) else: p1.player_amount_sent = self.amount_offered p1.payoff = Constants.payoff_if_rejected p2.payoff = Constants.payoff_if_rejected if p1.participant.vars['treatment_indicator'] == 'no_treatment': self.session.vars['rejected_offer_values_control'].append(self.amount_offered) print('rejected offers in control', self.session.vars['rejected_offer_values_control']) self.session.vars['offer_control'].append(self.amount_offered) print('offers in control', self.session.vars['offer_control']) elif p1.participant.vars['treatment_indicator'] == 'group_treatment': self.session.vars['rejected_offer_values_treatment'].append(self.amount_offered) print('rejected offers in treatment', self.session.vars['rejected_offer_values_treatment']) self.session.vars['offer_treatment'].append(self.amount_offered) print('offers in treatment', self.session.vars['offer_treatment']) if self.round_number in Constants.outgroup_rounds: self.session.vars['offer_outgroup'].append(self.amount_offered) print('offers in outgroup rounds', self.session.vars['offer_outgroup']) elif self.round_number in Constants.ingroup_rounds: self.session.vars['offer_ingroup'].append(self.amount_offered) print('offers in ingroup rounds', self.session.vars['offer_ingroup']) class Player(BasePlayer): player_amount_sent = models.CurrencyField() session_vars_dump = models.StringField() def vars_dump(self): self.session_vars_dump = str(self.session.vars) def get_partner(self): return self.get_others_in_group()[0]