from otree.api import * from django.core.validators import MaxValueValidator, MinValueValidator import os import pandas as pd import random doc = """ Your app description """ class Group(BaseGroup): pass class C(BaseConstants): NAME_IN_URL = 'hiringFlexible' PLAYERS_PER_GROUP = None NUM_ROUNDS = 4 def get_candidate(): data_people = pd.read_csv("/Users/max/Documents/GitHub/Experiment/survey_2/data/clean_randomise.csv") candidate = data_people[data_people["Group"] == random.randint(1, 100)] cons_cols = ["participantlabel","survey1playerage","majority","reservation wage","profile_name","quartile","Set","Group"] selected_columns = ["score1","score2","score3"] cons_cols.extend(random.sample(selected_columns,2)) candidate = candidate[cons_cols] if ('score3' in candidate.columns.tolist()) & ('score1' in candidate.columns.tolist()): candidate.rename(columns={"score3":"score2"},inplace=True) elif ('score3' in candidate.columns.tolist()) & ('score2' in candidate.columns.tolist()): candidate.rename(columns={"score3":"score1"},inplace=True) candidate = candidate.sort_values(by="majority") candidate.reset_index(inplace=True,drop=True) return candidate candidate = get_candidate() class Player(BasePlayer): question3_answer = models.BooleanField( label='3. If you decide to hire candidate 1 and candidate 2, which following pairs of wages you can offer respectively?', choices=((False, 'A. 17, 18'), (False, "B. 20, 20"), (False,"C. 1, 2"), (False, "D. 4, 4"), (True, "E. A, B")) ) pass competition5_answer = models.BooleanField( label="""5. If you decide to hire none of the candidates or fail to hire any of the candidates successfully, how much you can earn (in points)? """, choices=( (False,"A. 22 points"), (False,"B. 21 points"), (True,"C. 7 points"), (False,"D. 10 points") ) ) competition6_answer = models.BooleanField( label="""6. If you successfully hire candidate 2 and you offer a wage of 10 points, how much you can earn in total?""", choices=( (True,"A. 22 points"), (False,"B. 21 points"), (False,"C. 7 points"), (False,"D. 10 points") ) ) competition7_answer = models.BooleanField( label="""7. If you want to hire candidate 2 and offer a wage of 11, and y our competitor offer a wage of 15. Can you successfully hire candidate 2?""", choices=( (True,"""A. No. Because my competitor offers a higher wage, and both of our wage offers are greater than the reservation wage of candidate 2"""), (False,"""B. Yes. Because my wage offer is greater than the reservation wage of candidate 2"""), (False,"C. Not sure"), (False,"""D. Yes. Because we can both successfully hire candidate 2 as our wage offer is greater than our assigned reservation wage. """) ) ) noncompetition5_answer = models.BooleanField( label="""5. If you decide to hire none of the candidates or fail to hire any of the candidates successfully, how many points you did have in total? """, choices=( (False,"""A. 0 point"""), (False,"""B. 5 points"""), (True,"C. 15 points"), (False,"""D. 10 points""") ) ) noncompetition6_answer = models.BooleanField( label="""6. If you successfully hire candidate 2 and you offer a wage of 10 points, how many points did you earn in total (assume candidate 2 is the only candidate you successfully hire)""", choices=( (True,"""A. 22 points"""), (False,"""B. 21 points"""), (False,"C. 7 points"), (False,"""D. 10 points""") ) ) prac_hiring_1 = models.CharField(label="", choices= ("Yes","NO") ) prac_wage_1 = models.IntegerField( default=0, label="", validators=[ MaxValueValidator(25), MinValueValidator(5) ] ) prac_hiring_2 = models.CharField(label="", choices= ("Yes","NO") ) prac_wage_2 = models.IntegerField( default=0, label="", validators=[ MaxValueValidator(25), MinValueValidator(5) ] ) prac_hiring_3 = models.CharField(label="", choices= ("Yes","NO") ) prac_wage_3 = models.IntegerField( default=0, label="", validators=[ MaxValueValidator(25), MinValueValidator(5) ] ) prac_hiring_4 = models.CharField(label="", choices= ("Yes","NO") ) prac_wage_4 = models.IntegerField( default=0, label="", validators=[ MaxValueValidator(25), MinValueValidator(5) ] ) estimate_performance_1 = models.CurrencyField(initial=0) estimate_performance_2 = models.CurrencyField(initial=0) estimate_performance_3 = models.CurrencyField(initial=0) estimate_performance_4 = models.CurrencyField(initial=0) set_number = models.StringField() treatment = models.StringField() def estimate_score(self): return class Subsession(BaseSubsession): pass # PAGES class FirstRoundPage(Page): def is_displayed(self): return self.round_number == 1 class TestingQuestion3(FirstRoundPage): form_model = 'player' form_fields = ["question3_answer"] def before_next_page(self,timeout_happened): self.treatment = self.session.config["name"] # def error_message(player,values): def error_message(self, values=Player): error_dict = {"Flexible":"""
  • You can choose different wages for different candidates you want to hire. The candidate will only accept your wage offer only if it is greater than the reservation wage you face, which ranges from 5 to 25.
  • """, "Fix":"""
  • You can only choose an identical wage for different candidates you want to hire. The candidate will only accept your wage offer only if it is greater than the reservation wage you face, which ranges from 5 to 25
  • """} if values["question3_answer"] != True: if "Flexible" in self.session.config["name"]: return error_dict["Flexible"] else: return error_dict["Fix"] else: pass pass class TestingQuestionCompetition(FirstRoundPage): form_model = 'player' form_fields = ["competition5_answer","competition6_answer","competition7_answer"] def is_displayed(self): return ("Comp" in self.session.config["name"]) & (self.round_number == 1) def error_message(player, values): hints= { "competition5_answer": """Your total payment will consist of 15 initial points and the additional points you earn from the manager task.""", "competition6_answer": """You will receive 1 point for each score of the Employment Performance of your successfully hired candidate, minus the wage you decided to offer as additional points. Your total payment will consist of 15 initial points and the additional points you earn from the manager task.""", "competition7_answer": """Candidate will only accept your wage offer only if 1) it is greater than or equal to the reservation wage of the candidate 2) it is higher than your competing employer’s wage offer after deducting the reservation wage.""" } error_messages = dict() for key, item in values.items(): if item != True: if key == "competition5_answer": error_messages["competition5_answer"] = hints[key] elif key == "competition6_answer": error_messages["competition6_answer"] = hints[key] elif key == "competition7_answer": error_messages["competition7_answer"] = hints[key] return error_messages class TestingQuestionNonCompetition(FirstRoundPage): form_model = 'player' form_fields = ["noncompetition5_answer","noncompetition6_answer"] def is_displayed(self): return ("NonCom" in self.session.config["name"]) & (self.round_number == 1) def error_message(player, values): hints= { "noncompetition5_answer": """ Your total payment will consist of 15 initial points and the additional points you earn from the manager task. """, "noncompetition6_answer": """ You will receive 1 point for each score of the Employment Performance of your successfully hired candidate, minus the wage you decided to offer as additional points. Your total payment will consist of 15 initial points and the additional points you earn from the manager task. """ } error_messages = dict() for key, item in values.items(): if item != True: if key == "competition5_answer": error_messages["noncompetition5_answer"] = hints[key] else: error_messages["noncompetition6_answer"] = hints[key] return error_messages class DynamicPage(Page): def get_proper_page_name(self): return self.__class__.__name__.lower() def vars_for_template(self): candidates = C.candidate roundNum = self.round_number self.set_number = str(candidates["Group"].unique()[0]) if self.round_number == 1: est_payment = self.estimate_performance_1 elif self.round_number == 2: est_payment = self.estimate_performance_2 elif self.round_number == 3: est_payment = self.estimate_performance_3 elif self.round_number == 4: est_payment = self.estimate_performance_4 # if "feedback" in self.get_proper_page_name(): # # add estimation to each candidate # candidates["assigned_estimation"] = candidates["identity"].apply( # lambda row: self.player.get_score_estimation_as_dict()[row] # ) return { "round1":"hiringFlexible/hiringTask_{roundNum}".format( roundNum = self.round_number ), 'candidates': candidates[candidates["quartile"] == self.round_number], 'roundNumber':roundNum, 'estimate':est_payment } class HiringPage(DynamicPage): form_model = 'player' form_fields = ["prac_hiring_1",'prac_wage_1',"prac_hiring_2",'prac_wage_2', "prac_hiring_3",'prac_wage_3',"prac_hiring_4",'prac_wage_4'] def before_next_page(self,timeout_happened): payment = 0 data = C.candidate data = data[data["quartile"] == self.round_number] index = data[data["quartile"] == self.round_number].index if self.prac_hiring_1 == "Yes": if self.prac_wage_1 >= data.at[data.index[0],"reservation wage"]: payment = payment + data.at[data.index[0],"score2"] - self.prac_wage_1 else: payment = payment if self.prac_hiring_2 == "Yes": if self.prac_wage_2 >= data.at[data.index[1],"reservation wage"]: payment = payment + data.at[data.index[1],"score2"] - self.prac_wage_2 else: payment = payment if self.prac_hiring_3 == "Yes": if self.prac_wage_3 >= data.at[data.index[2],"reservation wage"]: payment = payment + data.at[data.index[2],"score2"] - self.prac_wage_3 else: payment = payment if self.prac_hiring_4 == "Yes": if self.prac_wage_4 >= data.at[data.index[3],"reservation wage"]: payment = payment + data.at[data.index[3],"score2"] - self.prac_wage_4 else: payment = payment payment = (15+ payment)*0.1 print(payment) if self.round_number == 1: self.estimate_performance_1 = float(payment) elif self.round_number == 2: self.estimate_performance_2 = float(payment) elif self.round_number == 3: self.estimate_performance_3 = float(payment) elif self.round_number == 4: self.estimate_performance_4 = float(payment) pass class Estimation(DynamicPage): form_model = 'player' page_sequence = [ TestingQuestion3, TestingQuestionCompetition, TestingQuestionNonCompetition, HiringPage, Estimation ]