from otree.api import * import random import pickle from datetime import datetime import pandas as pd c = cu doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'risk_attitude' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 NUM_TRIES = 2 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): decision_round_one = models.IntegerField(min=1, max=100, label="Für welche Option entscheiden Sie sich? Bitte geben Sie die Nummer der Lotterie an.") decision_round_two = models.IntegerField(min=1, max=100, label="Für welche Option entscheiden Sie sich? Bitte geben Sie die Nummer der Lotterie an.") risk_level_revealed = models.IntegerField() risk_prediction_full = models.IntegerField(min=0, max=3) risk_prediction_decfs = models.IntegerField(min=0, max=3) unfold_list_tracker = models.BooleanField() #lottery_selected = models.IntegerField() #lottery_red = models.BooleanField() #lottery_understanding = models.IntegerField(min=0) consent = models.BooleanField() treatment = models.StringField() tries_left = models.IntegerField(initial=C.NUM_TRIES) quiz1 = models.IntegerField(label='Mit wie vielen anderen realen Personen können Sie Ihre Punkte teilen?', choices=[1,2,3]) quiz2 = models.IntegerField(label='Welchen Zweck erfüllt das KI-System?', choices=[[1,"Vorhersage der Reaktion von Teilnehmer 2"],[2,'Vorhersage Ihrer Risikobereitschaft'],[3,'Vorhersage der Entscheidung von Teilnehmer 1']]) BDM = models.IntegerField(min=0, max=1000, label="Bitte geben Sie an, wie viele Punkte Sie für die Nutzung des KI-Systems ausgeben würden") BDM_result = models.BooleanField() ## Prediction variables todo # Participants' descriptives # Alter age = models.IntegerField(label="Ihr Alter:", min=18, max=99, blank=False) sex = models.IntegerField(choices=[[1, "Weiblich"], [0, "Männlich"]],widget=widgets.RadioSelect, label="Ihr Geschlecht:", blank=False) germborn = models.IntegerField(choices=[[0, 'Nicht in Deutschland geboren'], [1, 'In Deutschland geboren']], label="Sind Sie in Deutschland geboren?", widget=widgets.RadioSelect) income = models.IntegerField(choices=[[0, '< 1000 €'],[1, '1001 - 1500 €'],[2, '1501 - 2000 €'], [3, '2001 - 2500 €'],[4, '2501 - 3000 €'],[5, '3001 - 3500 €'], [6, '3501 - 4000 €'],[7, '4001 - 4500 €'],[8, '4501 - 5000 €'], [9, '> 5000 €']], label="Ihr monatliches Bruttoeinkommen in Euro:", blank=False) education = models.IntegerField(label="Die Gesamtdauer Ihrer Ausbildung in Jahre (Beginn ab der 1. Schulklasse)" "
Beispiel 1: Sie haben für 13 Jahre die Schule besucht und anschließend 5 Jahre studiert: Gesamtdauer = 18 Jahre" "
Beispiel 2: Sie haben für 8 Jahre die Schule besucht und anschließend eine 3 jährige Ausbildung absolviert: Gesamtdauer = 11 Jahre", blank=False) sat_socialLife = models.IntegerField(choices=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], label="Ihren Freunden und Bekannten?", widget=widgets.RadioSelectHorizontal, blank=False) sat_health = models.IntegerField(choices=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], label="Ihrer Gesundheit?", widget=widgets.RadioSelectHorizontal, blank=False) importance_religion = models.IntegerField(choices=[[4, "Ganz unwichtig"], [3, "Weniger wichtig"], [2, "Wichtig"], [1,"Sehr wichtig"]], label="Glaube und Religion", widget=widgets.RadioSelectHorizontal, blank=False) importance_involvement = models.IntegerField(choices=[[4, 'ganz unwichtig'], [3, 'Weniger wichtig'], [2, 'Wichtig'], [1,'Sehr wichtig']], label="Politisch und gesellschaftlich engagiert sein", widget=widgets.RadioSelectHorizontal, blank=False) check_account = models.IntegerField(choices= [[5, "Nie"], [4, "Seltener als 1 mal pro Monat"], [3, "Mindestens 1 mal pro Monat"], [2, "Mindestens 1 mal pro Woche"], [1, "Täglich"]], label="Häufigkeit der Überprüfung des Kontostands:", widget=widgets.RadioSelectHorizontal, blank=False) alcohol = models.IntegerField(choices=[[6, "Nie"], [5, "Einmal im Monat oder seltener"], [4, "An zwei bis vier Tagen im Monat"], [3, "An zwei bis drei Tagen in der Woche"], [2, "An vier bis sechs Tagen in der Woche"], [1, "Täglich"]], label="Häufigkeit des Verzehrs alkoholischer Getränke", widget=widgets.RadioSelect, blank=False) smoke = models.IntegerField(choices=[[1, "Ja"], [0, "Nein"]],widget=widgets.RadioSelect, label="Rauchen Sie derzeit, egal ob Zigaretten, Pfeifen oder Zigarren?", blank=False) # - - - - - - - - - - - - - - - - - - - - - - # Dummy variables age_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'],[1, 'Zurückhalten']], label="Alter", widget=widgets.RadioSelect, blank=True)### sex_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'],[1, 'Zurückhalten']], label="Geschlecht", widget=widgets.RadioSelect, blank=False)### germborn_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'],[1, 'Zurückhalten']], label="In Deutschland geboren", widget=widgets.RadioSelect, blank=False)### income_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'],[1, 'Zurückhalten']], label="Monats-Bruttoeinkommen", widget=widgets.RadioSelect, blank=False)### education_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'],[1, 'Zurückhalten']], label="Ausbildungs-Jahre", widget=widgets.RadioSelect, blank=False)### sat_socialLife_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'],[1, 'Zurückhalten']], label="Zufriedenheit mit Freunden und Bekannten", widget=widgets.RadioSelect, blank=False)### sat_health_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'],[1, 'Zurückhalten']], label="Zufriedenheit mit Ihrer Gesundheit", widget=widgets.RadioSelect, blank=False) importance_religion_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'], [1, 'Zurückhalten']],label="Wichtigkeit der Religion / des Glaubens", widget=widgets.RadioSelect, blank=False)### importance_involvement_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'], [1, 'Zurückhalten']],label="Wichtigkeit politisch/gesellschaftlich engagiert zu sein", widget=widgets.RadioSelect, blank=False) check_account_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'], [1, 'Zurückhalten']],label="Prüfung des Kontos",widget=widgets.RadioSelect, blank=False)### alcohol_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'], [1, 'Zurückhalten']],label="Verzehr alkoholischer Getränke", widget=widgets.RadioSelect, blank=False)### smoke_dummy = models.IntegerField(choices=[[0, 'Bereitstellen'], [1, 'Zurückhalten']],label="Rauchen", widget=widgets.RadioSelect, blank=False) # Functions ml_model = pickle.load(open('risk_model.sav', 'rb')) def predict_risk_full(player: Player): # Predict the fairness/reciprocity of dictator based on all attributes # Initialize each dummy with 0; extent the number and names of dummies according to the used features # Create the input for the ML model; consists of (1) questionnaire attr. and (2) dummies=0 input_obs_dict = pd.DataFrame({"age": player.age, "education": player.education, "sex": player.sex, "germborn": player.germborn, "smoke": player.smoke, "sat_health": player.sat_health, "sat_socialLife": player.sat_socialLife, "importance_religion": player.importance_religion, "check_account": player.check_account, "alcohol": player.alcohol, "importance_involvement": player.importance_involvement, "income": player.income, # ----- Dummies -------- "age_dummy": 0, "education_dummy": 0, "sex_dummy": 0, "germborn_dummy": 0, "smoke_dummy": 0, "sat_health_dummy": 0, "sat_socialLife_dummy": 0, "importance_religion_dummy": 0, "check_account_dummy": 0, "alcohol_dummy": 0, "importance_involvement_dummy":0, "income_dummy": 0 }, index=[0]) input_obs = pd.DataFrame(input_obs_dict) # Convert dict to DataFrame (only 1 row since we look at each single participant) player.risk_prediction_full = int(ml_model.predict(input_obs)) # Perform the prediction def predict_risk_decfs(player: Player): dummies = [player.age_dummy, player.sex_dummy, player.germborn_dummy, player.income_dummy, player.education_dummy, player.sat_socialLife_dummy, player.sat_health_dummy, player.importance_religion_dummy, player.importance_involvement_dummy, player.check_account_dummy, player.alcohol_dummy, player.smoke_dummy] player_vars = [player.age, player.sex, player.germborn, player.income, player.education, player.sat_socialLife, player.sat_health, player.importance_religion, player.importance_involvement, player.check_account, player.alcohol, player.smoke] participant = player.participant par_fields = ["age", "sex", "germborn", "income", "education", "sat_socialLife", "sat_health", "importance_religion","importance_involvement", "check_account", "alcohol", 'smoke'] """ dict_medians = {'age': 45.0, 'bgbilzeit': 11.5, 'labgro16': 2200.0, 'sex': 0.0, 'germborn': 1.0, 'bgp0108': 8.0, 'bgp0106': 7.0, 'bgp0112': 6.0, 'bgp05': 5.0, 'bgp0111': 8.0, 'bgp0610': 2.0, 'bgp0702': 3.0, 'bgp115': 5.0} """ for dummy, var, par_field in zip(dummies, player_vars, par_fields): if dummy == 1: participant.vars[par_field] = -1 else: participant.vars[par_field] = var input_obs_dict = pd.DataFrame({"age": participant.age, "education": participant.education, "sex": participant.sex, "germborn": participant.germborn, "smoke": participant.smoke, "sat_health": participant.sat_health, "sat_socialLife": participant.sat_socialLife, "importance_religion": participant.importance_religion, "check_account": participant.check_account, "alcohol": participant.alcohol, "importance_involvement": participant.importance_involvement, "income": participant.income, # ----- Dummies -------- "age_dummy": player.age_dummy, "education_dummy": player.education_dummy, "sex_dummy": player.sex_dummy, "germborn_dummy": player.germborn_dummy, "smoke_dummy": player.smoke_dummy, "sat_health_dummy": player.sat_health_dummy, "sat_socialLife_dummy": player.sat_socialLife_dummy, "importance_religion_dummy": player.importance_religion_dummy, "check_account_dummy": player.check_account_dummy, "alcohol_dummy": player.alcohol_dummy, "importance_involvement_dummy":player.importance_involvement_dummy, "income_dummy": player.income_dummy }, index=[0]) input_obs = pd.DataFrame(input_obs_dict) player.risk_prediction_decfs = int(ml_model.predict(input_obs)) def creating_session(subsession): # Assigns the experimental groups; itertools.cycle ensures that we have 50/50 distribution of treatment groups import itertools treatments = itertools.cycle(['baseline', 'treatment']) x = 1 for player in subsession.get_players(): player.treatment=next(treatments) print('player', x, 'is in condition:', player.treatment) x += 1 subsession.group_randomly() def start_timestamp(player: Player): participant = player.participant participant.vars['start_time'] = datetime.now() def end_timestamp(player: Player): participant = player.participant participant.vars['end_time'] = datetime.now() completion_time = participant.vars['end_time'] - participant.vars['start_time'] participant.vars['completion_time'] = completion_time.seconds def create_lottery(p1, v1, v2): parameter_list = [p1, v1, v2] expected_value = p1 * v1 + (1 - p1) * v2 if (v1 != 1) and (v2 != 1): lottery = f"Mit einer Wahrscheinlichkeit von {p1 * 100}% erhalten Sie {v1} Punkte. Mit einer Wahrscheinlichkeit von {(1 - p1) * 100}% erhalten Sie {v2} Punkte." elif (v1 == 1) and (v2 != 1): lottery = f"Mit einer Wahrscheinlichkeit von {p1 * 100}% erhalten Sie {v1} Punkt. Mit einer Wahrscheinlichkeit von {(1 - p1) * 100}% erhalten Sie {v2} Punkte." elif (v1 != 1) and (v2 == 1): lottery = f"Mit einer Wahrscheinlichkeit von {p1 * 100}% erhalten Sie {v1} Punkte. Mit einer Wahrscheinlichkeit von {(1 - p1) * 100}% erhalten Sie {v2} Punkt." return lottery, parameter_list, expected_value def create_lotteries_random(n): random.seed(10) lottery_list = [] for i in range(1, n): p1_rand = round(random.random(), 1) v1_rand = random.randint(0, 50) v2_rand = random.randint(0, 50) risk_level_rand = random.randint(0,3) lottery_creation_results = create_lottery(p1_rand, v1_rand, v2_rand) lottery_dict = dict(ID=i, text=lottery_creation_results[0], parameter=lottery_creation_results[1], exp_value=lottery_creation_results[2], risk_level=risk_level_rand, ) lottery_list.append(lottery_dict) return lottery_list def personalize_lotteries_risk(player: Player, n): lottery_list = create_lotteries_random(n) personalised_lotteries = [] for lottery in lottery_list: if lottery['risk_level'] == player.risk_prediction_full: personalised_lotteries.append(lottery) return personalised_lotteries def extract_risk_level(player: Player, n): lottery_list = create_lotteries_random(n) player.risk_level_revealed = lottery_list[player.decision_round_two-1]["risk_level"] def BDM_decision(player: Player): random_threshold = random.randint(0,1000) player.BDM_result = 1 if player.BDM >= random_threshold else 0 def lottery_understanding_error_message(player: Player, value): if value != C.PAYOFF_WHITE_A: return f"Actually, you would earn {cu(C.PAYOFF_WHITE_A)}. For lottery A you had 3 chances out of 10 to earn {cu(C.PAYOFF_RED_A)} (if a red ball was extracted) and 7 chances out of 10 to earn {cu(C.PAYOFF_WHITE_A)} (if a white ball was extracted). Since a white ball was extracted, you earn {cu(C.PAYOFF_WHITE_A)}." def consent_error_message(player: Player, value): if not value: return "You must consent in order to take part, otherwise please close this tab." # PAGES class Introduction(Page): def before_next_page(player: Player, timeout_happened): start_timestamp(player) class questionnaire(Page): form_model = 'player' form_fields = ["age", "education", "sex", "germborn", "smoke", "sat_health","sat_socialLife","importance_religion", "check_account","alcohol","importance_involvement","income"] @staticmethod def before_next_page(player: Player, timeout_happened): predict_risk_full(player) player.unfold_list_tracker = 0 @staticmethod def vars_for_template(player: Player): descriptives = ["age", "sex", "germborn", "income", "education"] Likert_vars_10 = ["sat_socialLife","sat_health"] importances = ["importance_religion","importance_involvement"] miscellaneous = ["smoke","alcohol","check_account"] return dict(descriptives=descriptives, Likert_vars_10=Likert_vars_10) class Explanation_of_experiment(Page): pass class Lottery_example(Page): pass class Lotteries_round_two(Page): form_model = "player" form_fields = ["decision_round_two"] def vars_for_template(player: Player): lotteries = create_lotteries_random(11) return {"lotteries": lotteries} @staticmethod def before_next_page(player: Player, timeout_happened): extract_risk_level(player, 11) class Lotteries_round_two_result(Page): form_model = "player" def vars_for_template(player: Player): lotteries = create_lotteries_random(11) lottery_two_selected = lotteries[player.decision_round_two-1]['text'] return {"lottery_two_selected": lottery_two_selected} class Lotteries_round_one_presentation(Page): form_model = "player" #form_fields = ["decision_round_one"] def vars_for_template(player: Player): lotteries = create_lotteries_random(101) return {"lotteries": lotteries} class Explanation_of_AI(Page): pass class Decentralized_feature_selection(Page): form_model = 'player' form_fields = ["age_dummy", "sex_dummy", "germborn_dummy", "income_dummy", "education_dummy", "sat_socialLife_dummy", "sat_health_dummy", "importance_religion_dummy","importance_involvement_dummy", "check_account_dummy", "alcohol_dummy", 'smoke_dummy'] #todo: Bei neuen features anpassen! @staticmethod def is_displayed(player: Player): return (player.treatment == 'treatment') @staticmethod def before_next_page(player: Player, timeout_happened): predict_risk_decfs(player) class BDM(Page): form_model = 'player' form_fields= ['BDM'] @staticmethod def before_next_page(player: Player, timeout_happened): BDM_decision(player) class BDM_result(Page): form_model = 'player' class Lotteries_round_one_with_AI(Page): form_model = "player" form_fields = ["decision_round_one", "unfold_list_tracker"] def vars_for_template(player: Player): lotteries_one_personalized = personalize_lotteries_risk(player, 101) lotteries_one_full = create_lotteries_random(101) return {"lotteries_one_personalized":lotteries_one_personalized[0:10], "lotteries_one_full":lotteries_one_full} @staticmethod def is_displayed(player: Player): return (player.BDM_result == 1) class Lotteries_round_one_without_AI(Page): form_model = "player" form_fields = ["decision_round_one"] def vars_for_template(player: Player): lotteries = create_lotteries_random(101) return {"lotteries": lotteries} @staticmethod def is_displayed(player: Player): return (player.BDM_result == 0) class Lotteries_round_one_result(Page): form_model = "player" def vars_for_template(player: Player): lotteries = create_lotteries_random(101) lottery_one_selected = lotteries[player.decision_round_one-1]['text'] return {"lottery_one_selected": lottery_one_selected} class Lotteries_round_two_result(Page): form_model = "player" def vars_for_template(player: Player): lotteries = create_lotteries_random(101) lottery_two_selected = lotteries[player.decision_round_two-1]['text'] return {"lottery_two_selected": lottery_two_selected} class Results(Page): pass page_sequence = [Introduction, questionnaire, Explanation_of_experiment, Lotteries_round_one_presentation, Explanation_of_AI, # attention check Decentralized_feature_selection, BDM, BDM_result, #todo Seiteninhalt Lotteries_round_one_without_AI, Lotteries_round_one_with_AI, Lotteries_round_one_result, Lotteries_round_two, Lotteries_round_two_result, #secondaries ]