from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import numpy as np import random import csv author = 'William Brown' doc = """ Game used to test subject's strategic reasoning in various voting systems using a "level-k" framework" """ class Constants(BaseConstants): name_in_url = 'strategic_voting' players_per_group = 3 num_rounds = 40 num_sessions = 5 # treatment 1 is plurality, treatment 2 is STAR, treatment 3 is IR treatment = 1 preferences = [2, 4, 1, 0, 3] file = open("strategic_voting/preferences_pl.csv", 'r') data = csv.reader(file, delimiter=',') payouts_pl = [] for x in range(num_sessions): payouts_pl.append(list()) for _ in range(5): payouts_pl[x].append(data.__next__()) file.close() file = open("strategic_voting/preferences_ir.csv", 'r') data = csv.reader(file, delimiter=',') payouts_ir = [] for x in range(num_sessions): payouts_ir.append(list()) for _ in range(5): payouts_ir[x].append(data.__next__()) file.close() file = open("strategic_voting/preferences_star.csv", 'r') data = csv.reader(file, delimiter=',') payouts_star = [] for x in range(num_sessions): payouts_star.append(list()) for _ in range(5): payouts_star[x].append(data.__next__()) file.close() class Subsession(BaseSubsession): def creating_session(self): self.group_randomly() players = self.get_players() groups = self.get_groups() for g in groups: g.preferences = Constants.preferences[(self.round_number-1)//8] for p in players: if self.round_number == 1: p.set_round = 0 else: p.set_round = self.round_number % 9 class Group(BaseGroup): preferences = models.IntegerField() total_A = models.IntegerField(initial=0, min=0) total_B = models.IntegerField(initial=0, min=0) total_C = models.IntegerField(initial=0, min=0) total_D = models.IntegerField(initial=0, min=0) r_1_A = models.IntegerField(initial=0, min=0) r_1_B = models.IntegerField(initial=0, min=0) r_1_C = models.IntegerField(initial=0, min=0) r_1_D = models.IntegerField(initial=0, min=0) r_2_A = models.IntegerField(initial=0, min=0) r_2_B = models.IntegerField(initial=0, min=0) r_2_C = models.IntegerField(initial=0, min=0) r_2_D = models.IntegerField(initial=0, min=0) p1_vote_A = models.IntegerField(initial=0) p1_vote_B = models.IntegerField(initial=0) p1_vote_C = models.IntegerField(initial=0) p1_vote_D = models.IntegerField(initial=0) p2_vote_A = models.IntegerField(initial=0) p2_vote_B = models.IntegerField(initial=0) p2_vote_C = models.IntegerField(initial=0) p2_vote_D = models.IntegerField(initial=0) p3_vote_A = models.IntegerField(initial=0) p3_vote_B = models.IntegerField(initial=0) p3_vote_C = models.IntegerField(initial=0) p3_vote_D = models.IntegerField(initial=0) p1_score_A = models.IntegerField(initial=0) p1_score_B = models.IntegerField(initial=0) p1_score_C = models.IntegerField(initial=0) p1_score_D = models.IntegerField(initial=0) p2_score_A = models.IntegerField(initial=0) p2_score_B = models.IntegerField(initial=0) p2_score_C = models.IntegerField(initial=0) p2_score_D = models.IntegerField(initial=0) p3_score_A = models.IntegerField(initial=0) p3_score_B = models.IntegerField(initial=0) p3_score_C = models.IntegerField(initial=0) p3_score_D = models.IntegerField(initial=0) winner = models.StringField() winner_num = models.IntegerField() majority = models.FloatField(initial=0) average_A = models.FloatField(initial=0, min=0, max=4) average_B = models.FloatField(initial=0, min=0, max=4) average_C = models.FloatField(initial=0, min=0, max=4) average_D = models.FloatField(initial=0, min=0, max=4) runoff_total_1 = models.IntegerField(initial=0, min=0) runoff_total_2 = models.IntegerField(initial=0, min=0) runoff_cand_1 = models.StringField() runoff_cand_2 = models.StringField() def vote_A(self): self.total_A = 0 for p in self.get_players(): if p.pl_vote == 'A': self.total_A += p.votes return self.total_A def vote_B(self): self.total_B = 0 for p in self.get_players(): if p.pl_vote == 'B': self.total_B += p.votes return self.total_B def vote_C(self): self.total_C = 0 for p in self.get_players(): if p.pl_vote == 'C': self.total_C += p.votes return self.total_C def vote_D(self): self.total_D = 0 for p in self.get_players(): if p.pl_vote == 'D': self.total_D += p.votes return self.total_D def vote_winner(self): sys_random = random.SystemRandom() self.vote_A() self.vote_B() self.vote_C() self.vote_D() candidates = { "A": self.total_A, "B": self.total_B, "C": self.total_C, "D": self.total_D, } winning_candidate = [] maximum = 0 for name, votes in candidates.items(): if votes == maximum: winning_candidate.append(name) if votes > maximum: winning_candidate = [] winning_candidate.append(name) maximum = votes self.winner = sys_random.choice(winning_candidate) self.winner_num = 0 if self.winner == "A": self.winner_num = 0 elif self.winner == "B": self.winner_num = 1 elif self.winner == "C": self.winner_num = 2 else: self.winner_num = 3 players = self.get_players() for p in players: if p.id_in_group == 1: if p.pl_vote == "A": self.p1_vote_A += p.votes if p.pl_vote == "B": self.p1_vote_B += p.votes if p.pl_vote == "C": self.p1_vote_C += p.votes if p.pl_vote == "D": self.p1_vote_D += p.votes if p.id_in_group == 2: if p.pl_vote == "A": self.p2_vote_A += p.votes if p.pl_vote == "B": self.p2_vote_B += p.votes if p.pl_vote == "C": self.p2_vote_C += p.votes if p.pl_vote == "D": self.p2_vote_D += p.votes if p.id_in_group == 3: if p.pl_vote == "A": self.p3_vote_A += p.votes if p.pl_vote == "B": self.p3_vote_B += p.votes if p.pl_vote == "C": self.p3_vote_C += p.votes if p.pl_vote == "D": self.p3_vote_D += p.votes def get_runoff(self): sys_random = random.SystemRandom() a_ratings = [] b_ratings = [] c_ratings = [] d_ratings = [] runoff_cand = [] players = self.get_players() for p in players: a_ratings.append(p.STAR_A*p.votes) b_ratings.append(p.STAR_B*p.votes) c_ratings.append(p.STAR_C*p.votes) d_ratings.append(p.STAR_D*p.votes) for p in players: if p.id_in_group == 1: self.p1_score_A += p.STAR_A*p.votes self.p1_score_B += p.STAR_B*p.votes self.p1_score_C += p.STAR_C*p.votes self.p1_score_D += p.STAR_D*p.votes if p.id_in_group == 2: self.p2_score_A += p.STAR_A * p.votes self.p2_score_B += p.STAR_B * p.votes self.p2_score_C += p.STAR_C * p.votes self.p2_score_D += p.STAR_D * p.votes if p.id_in_group == 3: self.p3_score_A += p.STAR_A * p.votes self.p3_score_B += p.STAR_B * p.votes self.p3_score_C += p.STAR_C * p.votes self.p3_score_D += p.STAR_D * p.votes cand_avg = { "A": sum(a_ratings), "B": sum(b_ratings), "C": sum(c_ratings), "D": sum(d_ratings), } self.average_A = cand_avg["A"] self.average_B = cand_avg["B"] self.average_C = cand_avg["C"] self.average_D = cand_avg["D"] for name, votes in cand_avg.items(): runoff_cand.append((name,votes)) def takeSecond(elem): return elem[1] sys_random.shuffle(runoff_cand) runoff_cand.sort(key=takeSecond, reverse=True) del runoff_cand[2:4] return [item[0] for item in runoff_cand] def get_star_winner(self, runoff_cands): sys_random = random.SystemRandom() players = self.get_players() self.runoff_cand_1 = runoff_cands[0] self.runoff_cand_2 = runoff_cands[1] candidate_votes = { } for c in runoff_cands: candidate_votes[c] = 0 for p in players: vote_choices = { "A": p.STAR_A, "B": p.STAR_B, "C": p.STAR_C, "D": p.STAR_D, } player_vote = [] maximum = 0 for c in runoff_cands: if vote_choices[c] == maximum: player_vote.append(c) if vote_choices[c] > maximum: player_vote = [] player_vote.append(c) maximum = vote_choices[c] if len(player_vote) > 1: pass else: player_vote = "".join(player_vote) candidate_votes[player_vote] += p.votes if p.id_in_group == 1: if player_vote == "A": self.p1_vote_A += p.votes if player_vote == "B": self.p1_vote_B += p.votes if player_vote == "C": self.p1_vote_C += p.votes if player_vote == "D": self.p1_vote_D += p.votes if p.id_in_group == 2: if player_vote == "A": self.p2_vote_A += p.votes if player_vote == "B": self.p2_vote_B += p.votes if player_vote == "C": self.p2_vote_C += p.votes if player_vote == "D": self.p2_vote_D += p.votes if p.id_in_group == 3: if player_vote == "A": self.p3_vote_A += p.votes if player_vote == "B": self.p3_vote_B += p.votes if player_vote == "C": self.p3_vote_C += p.votes if player_vote == "D": self.p3_vote_D += p.votes self.runoff_total_1 = candidate_votes[runoff_cands[0]] self.runoff_total_2 = candidate_votes[runoff_cands[1]] winning_candidate = [] maximum = 0 for name, votes in candidate_votes.items(): if votes == maximum: winning_candidate.append(name) if votes > maximum: winning_candidate = [] winning_candidate.append(name) maximum = votes self.winner = sys_random.choice(winning_candidate) self.winner_num = 0 if self.winner == "A": self.winner_num = 0 elif self.winner == "B": self.winner_num = 1 elif self.winner == "C": self.winner_num = 2 else: self.winner_num = 3 def get_ir_winner(self): votes_A = 0 votes_B = 0 votes_C = 0 votes_D = 0 players = self.get_players() total_votes = 0 for p in players: total_votes += p.votes for p in players: vote_choices = { "A": p.IR_A, "B": p.IR_B, "C": p.IR_C, "D": p.IR_D, } vote = min(vote_choices, key=vote_choices.get) if vote == "A": votes_A += p.votes elif vote == "B": votes_B += p.votes elif vote == "C": votes_C += p.votes elif vote == "D": votes_D += p.votes candidates = { "A": votes_A, "B": votes_B, "C": votes_C, "D": votes_D, } self.majority = total_votes/2 self.total_A += candidates["A"] self.total_B += candidates["B"] self.total_C += candidates["C"] self.total_D += candidates["D"] if max(candidates.values()) > total_votes/2: self.winner = max(candidates, key=candidates.get) else: cands = ["A", "B", "C", "D"] count = 0 while max(candidates.values()) < total_votes/2: count += 1 bottom_cand = min(candidates, key=candidates.get) cands.remove(bottom_cand) new_candidates = { } for ca in cands: new_candidates[ca] = 0 for p in players: vote_choices_new = { "A": p.IR_A, "B": p.IR_B, "C": p.IR_C, "D": p.IR_D, } vote_choices_new_2 = { "A": p.IR_A, "B": p.IR_B, "C": p.IR_C, "D": p.IR_D, } for v in vote_choices_new: if v not in cands: del vote_choices_new_2[v] else: pass vote_choices_new = vote_choices_new_2 vote = min(vote_choices_new, key=vote_choices_new.get) if vote == "A": new_candidates["A"] += p.votes elif vote == "B": new_candidates["B"] += p.votes elif vote == "C": new_candidates["C"] += p.votes elif vote == "D": new_candidates["D"] += p.votes candidates = new_candidates cand_votes = { } old_cands = ["A", "B", "C", "D"] for c in old_cands: cand_votes[c] = 0 for ca in candidates: if ca in old_cands: cand_votes[ca] = candidates[ca] if count == 1: self.r_1_A += cand_votes["A"] self.r_1_B += cand_votes["B"] self.r_1_C += cand_votes["C"] self.r_1_D += cand_votes["D"] elif count == 2: self.r_2_A += cand_votes["A"] self.r_2_B += cand_votes["B"] self.r_2_C += cand_votes["C"] self.r_2_D += cand_votes["D"] else: pass self.winner = max(candidates, key=candidates.get) self.winner_num = 0 if self.winner == "A": self.winner_num = 0 elif self.winner == "B": self.winner_num = 1 elif self.winner == "C": self.winner_num = 2 else: self.winner_num = 3 def get_payoffs_PL(self): players = self.get_players() for p in players: p.payoff += int(Constants.payouts_pl[Constants.preferences[(self.round_number-1)//8]][self.winner_num+1][p.id_in_group-1]) def get_payoffs_IR(self): players = self.get_players() for p in players: p.payoff += int(Constants.payouts_ir[Constants.preferences[(self.round_number-1)//8]][self.winner_num+1][p.id_in_group-1]) def get_payoffs_STAR(self): players = self.get_players() for p in players: p.payoff += int(Constants.payouts_star[Constants.preferences[(self.round_number-1)//8]][self.winner_num+1][p.id_in_group-1]) class Player(BasePlayer): votes = models.IntegerField() player_payoff = models.StringField() other_pl_vote1 = models.StringField() other_pl_vote2 = models.StringField() other_action_11 = models.IntegerField() other_action_12 = models.IntegerField() other_action_13 = models.IntegerField() other_action_14 = models.IntegerField() other_action_21 = models.IntegerField() other_action_22 = models.IntegerField() other_action_23 = models.IntegerField() other_action_24 = models.IntegerField() other_player_1 = models.IntegerField() other_player_2 = models.IntegerField() set_round = models.IntegerField() def player_payoff_1_pl(self): self.player_payoff = Constants.payouts_pl[Constants.preferences[(self.round_number-1)//8]][1][self.id_in_group - 1] return self.player_payoff def player_payoff_2_pl(self): self.player_payoff = Constants.payouts_pl[Constants.preferences[(self.round_number-1)//8]][2][self.id_in_group - 1] return self.player_payoff def player_payoff_3_pl(self): self.player_payoff = Constants.payouts_pl[Constants.preferences[(self.round_number-1)//8]][3][self.id_in_group - 1] return self.player_payoff def player_payoff_4_pl(self): self.player_payoff = Constants.payouts_pl[Constants.preferences[(self.round_number-1)//8]][4][self.id_in_group - 1] return self.player_payoff def player_payoff_1_ir(self): self.player_payoff = Constants.payouts_ir[Constants.preferences[(self.round_number-1)//8]][1][self.id_in_group - 1] return self.player_payoff def player_payoff_2_ir(self): self.player_payoff = Constants.payouts_ir[Constants.preferences[(self.round_number-1)//8]][2][self.id_in_group - 1] return self.player_payoff def player_payoff_3_ir(self): self.player_payoff = Constants.payouts_ir[Constants.preferences[(self.round_number-1)//8]][3][self.id_in_group - 1] return self.player_payoff def player_payoff_4_ir(self): self.player_payoff = Constants.payouts_ir[Constants.preferences[(self.round_number-1)//8]][4][self.id_in_group - 1] return self.player_payoff def player_payoff_1_star(self): self.player_payoff = Constants.payouts_star[Constants.preferences[(self.round_number-1)//8]][1][self.id_in_group - 1] return self.player_payoff def player_payoff_2_star(self): self.player_payoff = Constants.payouts_star[Constants.preferences[(self.round_number-1)//8]][2][self.id_in_group - 1] return self.player_payoff def player_payoff_3_star(self): self.player_payoff = Constants.payouts_star[Constants.preferences[(self.round_number-1)//8]][3][self.id_in_group - 1] return self.player_payoff def player_payoff_4_star(self): self.player_payoff = Constants.payouts_star[Constants.preferences[(self.round_number-1)//8]][4][self.id_in_group - 1] return self.player_payoff pl_vote = models.StringField( choices=['A', 'B', 'C', 'D'], widget=widgets.RadioSelectHorizontal, doc="Plurality vote choice" ) STAR_A = models.IntegerField( choices=[1, 2, 3, 4], doc="STAR votes for A" ) STAR_B = models.IntegerField( choices=[1, 2, 3, 4], doc="STAR votes for B" ) STAR_C = models.IntegerField( choices=[1, 2, 3, 4], doc="STAR votes for C" ) STAR_D = models.IntegerField( choices=[1, 2, 3, 4], doc="STAR votes for D" ) IR_A = models.IntegerField( choices=[1, 2, 3, 4], doc="IR votes for A" ) IR_B = models.IntegerField( choices=[1, 2, 3, 4], doc="IR votes for B" ) IR_C = models.IntegerField( choices=[1, 2, 3, 4], doc="IR votes for C" ) IR_D = models.IntegerField( choices=[1, 2, 3, 4], doc="IR votes for D" ) pl_vote_test = models.StringField( choices=['A', 'B', 'C', 'D'], doc="Plurality vote choice test" ) STAR_A_pr = models.IntegerField( choices=[1, 2, 3, 4], doc="STAR votes for A" ) STAR_B_pr = models.IntegerField( choices=[1, 2, 3, 4], doc="STAR votes for B" ) STAR_C_pr = models.IntegerField( choices=[1, 2, 3, 4], doc="STAR votes for C" ) STAR_D_pr = models.IntegerField( choices=[1, 2, 3, 4], doc="STAR votes for D" ) IR_A_pr = models.IntegerField( choices=[1, 2, 3, 4], doc="IR votes for A" ) IR_B_pr = models.IntegerField( choices=[1, 2, 3, 4], doc="IR votes for B" ) IR_C_pr = models.IntegerField( choices=[1, 2, 3, 4], doc="IR votes for C" ) IR_D_pr = models.IntegerField( choices=[1, 2, 3, 4], doc="IR votes for D" )