#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 1st round of an income dynamics game game with 24 players. The round consists of 2 periods. """ class Constants(BaseConstants): name_in_url = 'Dynamic_Income1' 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 round 1, period 1 and 2 def creating_session(self): import itertools import random #3 initial income choices are $50, $80, $110 #initial_incomes_random randomly chooses the three variables to put in a random order without repeating #initial_incomes_iterator stores values in a way that allows them to be assigned to players in group through initial_incomes_list = ((50), (80), (110)) initial_incomes_random = random.sample(initial_incomes_list, 3) initial_incomes_iterator = itertools.cycle(initial_incomes_random) #round 1, period 1: assigns random initial_incomes to players in all groups if self.round_number ==1: for p in self.get_players(): p.initial_income = next(initial_incomes_iterator) p.participant.vars['initial_incomes'] = p.initial_income if self.round_number ==2: for p in self.get_players(): p.score = 0 ### #This is another way to assign the random initial values to players within each group ### # for p in self.get_players(): # if p.id_in_group ==1: # p.initial_income = random.choice(initial_incomes) # p1 = p.initial_income # elif p.id_in_group ==2: # x = True # while x: # p.initial_income = random.choice(initial_incomes) # p2 = p.initial_income # if p2 != p1: # x = False # elif p.id_in_group ==3: # x = True # while x: # p.initial_income = random.choice(initial_incomes) # p3 = p.initial_income # if p3 != p2 and p3 != p1: # x = False # p.initial_income = next(initial_incomes) #p.payoff = p.participant.vars['payoff'] class Group(BaseGroup): collected_income_tax = models.PositiveIntegerField() average_collected_income_tax = models.PositiveIntegerField() median_income_tax = models.PositiveIntegerField() median_for_page = models.PositiveIntegerField() #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 def Define_Payoff(self): for p in self.get_players(): p.participant.vars['round1_payoffs'] = p.player.in_round(2).round1_payoff class Player(BasePlayer): Hscore = models.PositiveIntegerField(initial = 0) round1_stage = models.PositiveIntegerField(initial = 0) round1_payoff = models.PositiveIntegerField(initial = 0) placing = models.StringField() score = models.PositiveIntegerField(initial = 0) initial_income = models.IntegerField() redistributed_income = models.PositiveIntegerField() subtracted_income = models.PositiveIntegerField() amount_subtracted = models.PositiveIntegerField() new_income = models.PositiveIntegerField(initial = 0) 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 1 Period 2 Q1 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 8-6+13+3-10", choices = [[1, '5'], [2, '6'], [3, '8'], [4, '10'] ], widget = widgets.RadioSelect ()) Q2 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 7+6-(-4)+2-9", choices = [[1, '10'], [2, '2'], [3, '9'], [4, '12'] ], widget = widgets.RadioSelect ()) Q3 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 2+2+3-(-3)+4", choices = [[1, '14'], [2, '13'], [3, '8'], [4, '11'] ], widget = widgets.RadioSelect ()) Q4 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 5+6-4+5", choices = [[1, '10'], [2, '13'], [3, '12'], [4, '14'] ], widget = widgets.RadioSelect ()) Q5 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 3+3+9-13", choices = [[1, '4'], [2, '2'], [3, '5'], [4, '3'] ], widget = widgets.RadioSelect ()) Q6 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 13+14-5-1", choices = [[1, '20'], [2, '21'], [3, '19'], [4, '18'] ], widget = widgets.RadioSelect ()) Q7 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 7-(-6)-8+1+3", choices = [[1, '7'], [2, '11'], [3, '9'], [4, '10'] ], widget = widgets.RadioSelect ()) Q8 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 13-14+5+2-3", choices = [[1, '3'], [2, '0'], [3, '-1'], [4, '2'] ], widget = widgets.RadioSelect ()) Q9 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 5-7-6+4+2", choices = [[1, '1'], [2, '-1'], [3, '2'], [4, '-2'] ], widget = widgets.RadioSelect ()) Q10 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 2+4+0-8+7", choices = [[1, '7'], [2, '6'], [3, '4'], [4, '5'] ], widget = widgets.RadioSelect ()) Q11 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 11+13-12-9", choices = [[1, '3'], [2, '1'], [3, '5'], [4, '2'] ], widget = widgets.RadioSelect ()) Q12 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 6+3+8-(-8)+2", choices = [[1, '28'], [2, '25'], [3, '24'], [4, '27'] ], widget = widgets.RadioSelect ()) Q13 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 1+1-1+13-6", choices = [[1, '6'], [2, '8'], [3, '7'], [4, '9'] ], widget = widgets.RadioSelect ()) Q14 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 9+9+8+7+6", choices = [[1, '38'], [2, '40'], [3, '39'], [4, '36'] ], widget = widgets.RadioSelect ()) Q15 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 5-8-2-6+2", choices = [[1, '-8'], [2, '-9'], [3, '-6'], [4, '-10'] ], widget = widgets.RadioSelect ()) Q16 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 3+3+1+4-6", choices = [[1, '3'], [2, '5'], [3, '7'], [4, '9'] ], widget = widgets.RadioSelect ()) Q17 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 2-1+6+2-4", choices = [[1, '3'], [2, '6'], [3, '2'], [4, '5'] ], widget = widgets.RadioSelect ()) Q18 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 10+7+6-11", choices = [[1, '12'], [2, '11'], [3, '13'], [4, '10'] ], widget = widgets.RadioSelect ()) Q19 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 16-5-9+3+4", choices = [[1, '10'], [2, '9'], [3, '8'], [4, '7'] ], widget = widgets.RadioSelect ()) Q20 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 15+15+15-6", choices = [[1, '40'], [2, '41'], [3, '38'], [4, '39'] ], widget = widgets.RadioSelect ()) Q21 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 10-8+4-10+5", choices = [[1, '3'], [2, '5'], [3, '12'], [4, '1'] ], widget = widgets.RadioSelect ()) Q22 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 1+1+8+9-3", choices = [[1, '16'], [2, '7'], [3, '12'], [4, '19'] ], widget = widgets.RadioSelect ()) Q23 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 19-9+5+11-1", choices = [[1, '26'], [2, '27'], [3, '12'], [4, '25'] ], widget = widgets.RadioSelect ()) Q24 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 15+6-8+1-9", choices = [[1, '5'], [2, '7'], [3, '12'], [4, '11'] ], widget = widgets.RadioSelect ()) Q25 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 25-7+2-3+5", choices = [[1, '16'], [2, '27'], [3, '22'], [4, '10'] ], widget = widgets.RadioSelect ()) Q26 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 17-2+8-5-1", choices = [[1, '16'], [2, '7'], [3, '13'], [4, '17'] ], widget = widgets.RadioSelect ()) Q27 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 1+10-10+8+2", choices = [[1, '11'], [2, '7'], [3, '12'], [4, '10'] ], widget = widgets.RadioSelect ()) Q28 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 16+4-9+3+2", choices = [[1, '20'], [2, '18'], [3, '12'], [4, '16'] ], widget = widgets.RadioSelect ()) Q29 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 2+3+8-10+1", choices = [[1, '3'], [2, '7'], [3, '4'], [4, '11'] ], widget = widgets.RadioSelect ()) Q30 = models.IntegerField (initial = 0, verbose_name = "What is the answer to this question" " 20+5+5-10-1", choices = [[1, '19'], [2, '7'], [3, '13'], [4, '17'] ], widget = widgets.RadioSelect ())