from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import logging import random author = 'Dr. Barthel, Dr. Hoffman and Walker Chesley' doc = """ Your app description """ logger = logging.getLogger(__name__) class Constants(BaseConstants): name_in_url = 'Parking_game' num_rounds = 6 faculty_role = 'Faculty' student_1_role = 'Student 1' student_2_role = 'Student 2' student_3_role = 'Student 3' players_per_group = None class Subsession(BaseSubsession): def creating_session(self): pass def vars_for_admin_report(self): pass class Group(BaseGroup): # Group variables: lot_A_count = models.IntegerField( doc='Count of number of cars parked in faculty lot', default = 0, ) lot_A_max = models.IntegerField( doc='Maximum number of spots availalbe in the lot', ) lot_A_value = models.IntegerField( doc='Cost of parking in this lot', ) lot_B_count = models.IntegerField( doc='Count of number of cars parked in faculty lot', default = 0, ) lot_B_max = models.IntegerField( doc='Maximum number of spots availalbe in the lot', ) lot_B_value = models.IntegerField( doc='Cost of parking in this lot', ) lot_C_count = models.IntegerField( doc='Count of number of cars parked in faculty lot', default = 0, ) lot_C_max = models.IntegerField( doc='Maximum number of spots availalbe in the lot', ) lot_C_value = models.IntegerField( doc='Cost of parking in this lot', ) lot_D_count = models.IntegerField( doc='Count of number of cars parked in faculty lot', default = 0, ) lot_D_value = models.IntegerField( doc='Value of parking in this lot', ) home_count = models.IntegerField( doc='Number of players who chose not lot, or were not able to find a lot', default=0 ) home_cost = models.IntegerField( doc='Cost of staying home', ) # Group Methods: def add_to_lot(self): for p in self.get_players(): if p.in_round(self.round_number).available_lots == 'Lot A': self.lot_A_count += 1 elif p.available_lots == 'Lot B': self.lot_B_count += 1 elif p.available_lots == 'Lot C': self.lot_C_count += 1 elif p.available_lots == 'Lot D': self.lot_D_count += 1 elif p.available_lots == 'Stay Home': self.no_lot_count += 1 def check_if_full_lot(self): lot_A_parked = [] lot_A_difference = 0 lot_B_parked = [] lot_B_difference = 0 lot_C_parked = [] lot_C_difference = 0 # Players who have to park again: the_chosen = [] # List all players parked in lots A, B and C for p in self.get_players(): if p.available_lots == 'Lot A': lot_A_parked.append(p) if p.available_lots == 'Lot B': lot_B_parked.append(p) if p.available_lots == 'Lot C': lot_C_parked.append(p) if self.lot_A_count > self.lot_A_max: lot_A_difference = self.lot_A_count - self.lot_A_max lot_A_removed = self.random_remove_from_lot(lot_A_parked, lot_A_difference) the_chosen.append(lot_A_removed) if self.lot_B_count > self.lot_B_max: lot_B_difference = self.lot_B_count - self.lot_B_max lot_B_removed = self.random_remove_from_lot(lot_B_parked, lot_B_difference) the_chosen.append(lot_B_removed) if self.lot_C_count > self.lot_C_max: lot_C_difference = self.lot_C_count - self.lot_C_max lot_C_removed = self.random_remove_from_lot(lot_C_parked, lot_C_difference) the_chosen.append(lot_C_removed) return the_chosen def set_payoff(self): penalty = self.session.config['penalty'] permit_value = self.session.config['parking_permit_value'] for p in self.get_players(): if p.available_lots == 'Lot A': p.parking_value = self.lot_A_value - permit_value if p.available_lots == 'Lot B': p.parking_value = self.lot_B_value - permit_value if p.available_lots == 'Lot C': p.parking_value = self.lot_C_value - permit_value if p.available_lots == 'Lot D': p.parking_value = self.lot_D_value - permit_value if p.available_lots == 'Stay Home': p.parking_value = self.home_cost if p.failed_parking == True: p.parking_value = p.parking_value - (penalty * p.failed_parking_attempts) def set_base_lot_value(self): lot_max = len(self.get_players()) / 4 self.lot_A_max = lot_max self.lot_B_max = lot_max self.lot_C_max = lot_max self.lot_A_value = self.session.config['lot_A_value'] self.lot_B_value = self.session.config['lot_B_value'] self.lot_C_value = self.session.config['lot_C_value'] self.lot_D_value = self.session.config['lot_D_value'] self.home_cost = self.session.config['home_value'] def lot_value_adjustment(self, lot): pass def set_random_lot(self): lots = [ 'Lot A', 'Lot B', 'Lot C', 'Lot D', 'Stay Home' ] return random.choice(lots) def random_remove_from_lot(self, players, difference): the_chosen = [] while difference != 0: random.shuffle(players) chosen = players.pop() chosen.failed_parking = True chosen.failed_parking_attempts += 1 the_chosen.append(chosen) difference -= 1 return the_chosen class Player(BasePlayer): # Player variables: commuter_type = models.StringField( doc='Players Commuter Type', choices=[ 'Faculty', 'Student 1', 'Student 2', 'Student 3' ] ) lot_choosen = models.StringField( doc='Final parking place chosen by player' ) failed_parking = models.BooleanField( doc='True if parking lot chosen was full and player must reselect their parking location. False by default.', default=False, ) failed_parking_attempts = models.IntegerField( doc='Count of failed parking attempts', default=0 ) parking_value = models.IntegerField( doc='Value of the lot chosen minus permit price' ) available_lots = models.StringField( doc='All lots available to park in', choices = [ 'Lot A', 'Lot B', 'Lot C', 'Lot D', 'Stay Home', ], )