#Income Dynamics, Income Sources and Preferences for Redistribution: Otree #University of Guelph, F.A.R.E Laboratory #Faculty Supervisors: Tongzhe Li and Bradley Ruffle #Programmers: Mitchell Ubene, Mark Patton, Zhelong Chen from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random import itertools import time doc = """ This is the 3rd round of an income dynamics game game with 24 players. The round consists of 2 periods. """ class Constants(BaseConstants): name_in_url = 'Dynamic_Income3' players_per_group = 3 num_rounds = 2 initial_incomes_list = ((50), (80), (110)) initial_incomes_list_low = (c(80), c(110)) initial_incomes_list_medium = '$50', '$110' initial_incomes_list_high = "$50", "$80" high_income = 110 medium_income = 80 low_income = 50 class Subsession(BaseSubsession): #creates setup for Period 3, Periods 1 and 2 def creating_session(self): import itertools import random if self.round_number ==2: for p in self.get_players(): p.score = 0 #Reassigns initial incomes to players to start round 3. #Gives them the last option that they haven't started with yet. if self.round_number ==1: self.group_randomly() for p in self.get_players(): p.last_income = p.participant.vars['initial_incomes2'] if p.last_income == 50: p.initial_income = 80 elif p.last_income == 80: p.initial_income = 110 elif p.last_income == 110: p.initial_income = 50 #Regroups all participants randomly while giving each group players with 3 different income levels. def do_shuffle(self): import random import itertools players = self.get_players() num_players = int(len(players)) num_groups = int(num_players/Constants.players_per_group) low_players = [p for p in players if p.initial_income == 50] med_players = [p for p in players if p.initial_income == 80] high_players = [p for p in players if p.initial_income == 110] low_players_random = random.sample(low_players, num_groups) med_players_random = random.sample(med_players, num_groups) high_players_random = random.sample(high_players, num_groups) group_matrix = [] # pop elements from M_players until it's empty while low_players_random: new_group = [ low_players_random.pop(), med_players_random.pop(), high_players_random.pop(), ] group_matrix.append(new_group) self.set_group_matrix(group_matrix) class Group(BaseGroup): collected_income_tax = models.PositiveIntegerField() average_collected_income_tax = models.PositiveIntegerField() median_income_tax = models.PositiveIntegerField() median_for_page = models.IntegerField() #Function for Income Tax Procedure def income_tax_median(self): import statistics for p in self.get_players(): p1 = self.get_player_by_id(1) p2 = self.get_player_by_id(2) p3 = self.get_player_by_id(3) income_tax_list = (p1.income_tax, p2.income_tax, p3.income_tax) self.median_income_tax = (statistics.median(income_tax_list))/100 self.median_for_page = int(self.median_income_tax*100) for p in self.get_players(): if self.round_number ==1: p.amount_subtracted = p.initial_income * self.median_income_tax p.subtracted_income = p.initial_income - p.amount_subtracted elif self.round_number ==2: p.amount_subtracted = p.new_income * self.median_income_tax p.subtracted_income = p.new_income - p.amount_subtracted self.collected_income_tax = sum([p.amount_subtracted for p in self.get_players()]) self.average_collected_income_tax = self.collected_income_tax/Constants.players_per_group for p in self.get_players(): p.redistributed_income = p.subtracted_income + self.average_collected_income_tax #Function for redistributing initial incomes during 2nd period as a result of the math game scores. def redistribute_incomes(self): for p in self.get_players(): p1 = self.get_player_by_id(1) p2 = self.get_player_by_id(2) p3 = self.get_player_by_id(3) if p1.score > p2.score and p1.score > p3.score and p2.score > p3.score: p1.new_income = Constants.high_income #p1.placing = '1st' p2.new_income = Constants.medium_income #p2.placing = '2nd' p3.new_income = Constants.low_income #p3.placing = '3rd' elif p1.score > p2.score and p1.score > p3.score and p2.score < p3.score: p1.new_income = Constants.high_income #p1.placing = '1st' p3.new_income = Constants.medium_income #p3.placing = '2nd' p2.new_income = Constants.low_income #p2.placing = '3rd' elif p1.score == p2.score and p1.score > p3.score: p1.new_income = Constants.high_income p2.new_income = Constants.medium_income p3.new_income = Constants.low_income elif p1.score == p3.score and p1.score > p2.score: p1.new_income = Constants.high_income p3.new_income = Constants.medium_income p2.new_income = Constants.low_income elif p1.score ==p2.score and p1.score < p3.score: p1.new_income = Constants.medium_income p2.new_income = Constants.low_income p3.new_income = Constants.high_income elif p1.score == p3.score and p1.score < p2.score: p1.new_income = Constants.medium_income p2.new_income = Constants.high_income p3.new_income = Constants.low_income elif p1.score == p3.score and p1.score == p2.score: p1.new_income = random.choice(Constants.initial_incomes_list) y = True while y: p2.new_income = random.choice(Constants.initial_incomes_list) if p2.new_income != p1.new_income: y = False x = True while x: p3.new_income = random.choice(Constants.initial_incomes_list) if p3.new_income != p1.new_income and p3.new_income != p2.new_income: x = False elif p2.score == p3.score and p2.score > p1.score: p2.new_income = Constants.high_income p3.new_income = Constants.medium_income p1.new_income = Constants.low_income elif p2.score == p3.score and p2.score < p1.score: p1.new_income = Constants.high_income p2.new_income = Constants.medium_income p3.new_income = Constants.low_income elif p2.score > p1.score and p2.score > p3.score and p1.score > p3.score: p2.new_income = Constants.high_income #p2.placing = '1st' p1.new_income = Constants.medium_income #p1.placing = '2nd' p3.new_income = Constants.low_income #p3.placing = '3rd' elif p2.score > p1.score and p2.score > p3.score and p3.score > p1.score: p2.new_income = Constants.high_income #p2.placing = '1st' p3.new_income = Constants.medium_income #p3.placing = '2nd' p1.new_income = Constants.low_income #p1.placing = '3rd' elif p3.score > p1.score and p3.score > p2.score and p1.score > p2.score: p3.new_income = Constants.high_income #p3.placing = '1st' p1.new_income = Constants.medium_income #p1.placing = '2nd' p2.new_income = Constants.low_income #p2.placing = '3rd' elif p3.score > p1.score and p3.score > p2.score and p2.score > p1.score: p3.new_income = Constants.high_income #p3.placing = '1st' p2.new_income = Constants.medium_income #p2.placing = '2nd' p1.new_income = Constants.low_income #p1.placing = '3rd' for p in self.get_players(): if p.id_in_group ==1: p.new_income = p1.new_income elif p.id_in_group ==2: p.new_income = p2.new_income elif p.id_in_group ==3: p.new_income = p3.new_income class Player(BasePlayer): Hscore = models.PositiveIntegerField(initial = 0) total = models.PositiveIntegerField(initial = 0) round3_payoff = models.PositiveIntegerField(initial = 0) round3_stage = models.PositiveIntegerField(initial = 0) placing = models.StringField() score = models.PositiveIntegerField(initial = 0) initial_income = models.PositiveIntegerField() redistributed_income = models.PositiveIntegerField() subtracted_income = models.PositiveIntegerField() amount_subtracted = models.PositiveIntegerField() new_income = models.PositiveIntegerField(initial = 0) last_income = models.PositiveIntegerField() income_tax = models.PositiveIntegerField( choices = [[0,'0%'], [10,'10%'], [20,'20%'], [30,'30%'], [40,'40%'], [50,'50%'], [60,'60%'], [70,'70%'], [80,'80%'], [90,'90%'], [100,'100%'], ], widget = widgets.RadioSelectHorizontal()) same_income = models.BooleanField() #question data for Round 3 Period 2 Q1 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 4+5+6+7", choices = [[1, '22'], [2, '24'], [3, '20'], [4, '10'] ], widget = widgets.RadioSelect ()) Q2 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 10+8-2-3", choices = [[1, '9'], [2, '14'], [3, '13'], [4, '20'] ], widget = widgets.RadioSelect ()) Q3 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 11+12+11-1", choices = [[1, '33'], [2, '21'], [3, '30'], [4, '32'] ], widget = widgets.RadioSelect ()) Q4 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 3+4+1-0", choices = [[1, '12'], [2, '0'], [3, '3'], [4, '8'] ], widget = widgets.RadioSelect ()) Q5 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 9+6-10+2", choices = [[1, '6'], [2, '2'], [3, '7'], [4, '5'] ], widget = widgets.RadioSelect ()) Q6 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 12+3+2+7", choices = [[1, '29'], [2, '15'], [3, '36'], [4, '24'] ], widget = widgets.RadioSelect ()) Q7 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 18-3+10-7", choices = [[1, '19'], [2, '18'], [3, '9'], [4, '17'] ], widget = widgets.RadioSelect ()) Q8 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 15+7-6", choices = [[1, '15'], [2, '12'], [3, '22'], [4, '16'] ], widget = widgets.RadioSelect ()) Q9 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 10+4-6-7", choices = [[1, '14'], [2, '2'], [3, '1'], [4, '4'] ], widget = widgets.RadioSelect ()) Q10 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 21-7-8+4", choices = [[1, '10'], [2, '1'], [3, '7'], [4, '12'] ], widget = widgets.RadioSelect ()) Q11 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 4+5+10+5", choices = [[1, '26'], [2, '17'], [3, '15'], [4, '24'] ], widget = widgets.RadioSelect ()) Q12 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 24-4+5-10", choices = [[1, '11'], [2, '15'], [3, '13'], [4, '14'] ], widget = widgets.RadioSelect ()) Q13 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 8-4+5+10", choices = [[1, '16'], [2, '19'], [3, '15'], [4, '20'] ], widget = widgets.RadioSelect ()) Q14 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 20-3+10-7", choices = [[1, '20'], [2, '16'], [3, '28'], [4, '23'] ], widget = widgets.RadioSelect ()) Q15 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 2+2+10-4", choices = [[1, '10'], [2, '11'], [3, '15'], [4, '12'] ], widget = widgets.RadioSelect ()) Q16 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 2+9+2-6", choices = [[1, '14'], [2, '13'], [3, '7'], [4, '12'] ], widget = widgets.RadioSelect ()) Q17 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 16+8-2+10", choices = [[1, '32'], [2, '35'], [3, '34'], [4, '25'] ], widget = widgets.RadioSelect ()) Q18 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 3+6-8+4", choices = [[1, '10'], [2, '5'], [3, '8'], [4, '9'] ], widget = widgets.RadioSelect ()) Q19 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 7+5-6+11", choices = [[1, '13'], [2, '12'], [3, '13'], [4, '17'] ], widget = widgets.RadioSelect ()) Q20 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 2+2+2+3", choices = [[1, '2'], [2, '14'], [3, '9'], [4, '5'] ], widget = widgets.RadioSelect ()) Q21 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 10+12-1-3+5", choices = [[1, '23'], [2, '15'], [3, '22'], [4, '16'] ], widget = widgets.RadioSelect ()) Q22 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" "1+10-2+3-2", choices = [[1, '3'], [2, '7'], [3, '10'], [4, '14'] ], widget = widgets.RadioSelect ()) Q23 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 12+10+3-10-8", choices = [[1, '6'], [2, '7'], [3, '9'], [4, '5'] ], widget = widgets.RadioSelect ()) Q24 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 2+8-3-2+16", choices = [[1, '25'], [2, '30'], [3, '21'], [4, '24'] ], widget = widgets.RadioSelect ()) Q25 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 10+7-2+5+5", choices = [[1, '25'], [2, '27'], [3, '22'], [4, '23'] ], widget = widgets.RadioSelect ()) Q26 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 10-4+18-2-10", choices = [[1, '16'], [2, '17'], [3, '12'], [4, '17'] ], widget = widgets.RadioSelect ()) Q27 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 11+13-2+7-1", choices = [[1, '29'], [2, '17'], [3, '28'], [4, '20'] ], widget = widgets.RadioSelect ()) Q28 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 16-1+3+3+2", choices = [[1, '23'], [2, '18'], [3, '22'], [4, '16'] ], widget = widgets.RadioSelect ()) Q29 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 10+3-1+14+12", choices = [[1, '13'], [2, '38'], [3, '34'], [4, '31'] ], widget = widgets.RadioSelect ()) Q30 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 13+25-15-1+3", choices = [[1, '29'], [2, '27'], [3, '25'], [4, '27'] ], widget = widgets.RadioSelect ())