from otree.api import * doc = """ XAI Experiment with real estate agents """ conf_label = "Wie sicher sind Sie sich mit dieser Entscheidung?\nAngabe von 1 (unsicher) bis 5 (sicher)." surp_label = "Wie überrascht sind Sie von der Vorhersage der KI?\nAngabe von 1 (nicht überrascht) bis 5 (überrascht)." conf_choices = [[1, ""], [2, ""], [3, ""], [4, ""], [5, ""]] price_label = "Ihre Preisschätzung in EUR/qm:" likert_7_scale = [ [1, "Stimme überhaupt nicht zu"], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, "Stimme voll zu"] ] def creating_session(subsession): for player in subsession.get_players(): import random import pandas as pd participant = player.participant # shuffle of stages 1, 2, 3 my_indices = list(pd.read_csv("xai_experiment/immobilien_pred_prices.csv", index_col=0).index) random.shuffle(my_indices) participant.immoSampleOrderS1 = my_indices[:4] participant.immoSampleOrderS2 = my_indices[4:12] # shuffle of stage 4 stage_4_prop = [[0, 1], [0, 2], [0, 3], [1, 1], [1, 2], [1, 3]] participant.outMarketProp = random.choice(stage_4_prop) participant.inMarketProp = random.choice(stage_4_prop) participant.treatment = random.choice(["none", "ai", "xai_local"]) # treat_nr = int(player.participant.id_in_session) % 3 # participant.treatment = ["none", "ai", "xai_local"][treat_nr] # "xai_global" class C(BaseConstants): NAME_IN_URL = 'xai_experiment' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): # Ich möchte an dieser Studie teilnehmen is_mobile = models.BooleanField() consent = models.BooleanField(choices=["Ich möchte an der Studie teilnehmen."], label="Durch das Ankreuzen des Kästchens erkläre ich mich mit der Teilnahme an der Studie einverstanden.") # # # STAGE 1 # # priorLocation1 = models.FloatField() priorBalcony1 = models.FloatField() priorGreen1 = models.FloatField() priorPrice1 = models.FloatField() priorConfLocation1 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfBalcony1 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfGreen1 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfPrice1 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorLocation2 = models.FloatField() priorBalcony2 = models.FloatField() priorGreen2 = models.FloatField() priorPrice2 = models.FloatField() priorConfLocation2 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfBalcony2 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfGreen2 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfPrice2 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorLocation3 = models.FloatField() priorBalcony3 = models.FloatField() priorGreen3 = models.FloatField() priorPrice3 = models.FloatField() priorConfLocation3 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfBalcony3 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfGreen3 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfPrice3 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorLocation4 = models.FloatField() priorBalcony4 = models.FloatField() priorGreen4 = models.FloatField() priorPrice4 = models.FloatField() priorConfLocation4 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfBalcony4 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfGreen4 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorConfPrice4 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) priorImpLocation = models.IntegerField( label="Wichtigkeit der Eigenschaft \nStadt (innerhalb der Kategorie \"A-Stadt\") für den Preis:", min=0, max=100, initial=0) priorImpBalcony = models.IntegerField(label="Wichtigkeit der Eigenschaft Balkon/Terasse für den Preis:", min=0, max=100, initial=0) priorImpGreen = models.IntegerField( label="Wichtigkeit der Eigenschaft Anteil Grünenwähler im Stadtteil für den Preis:", min=0, max=100, initial=0) # # # STAGE 2 # # treatmentPrice1 = models.FloatField(label=price_label, min=0) treatmentConfPrice1 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentSurprise1 = models.IntegerField(label=surp_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentPrice2 = models.FloatField(label=price_label, min=0) treatmentConfPrice2 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentSurprise2 = models.IntegerField(label=surp_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentPrice3 = models.FloatField(label=price_label, min=0) treatmentConfPrice3 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentSurprise3 = models.IntegerField(label=surp_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentPrice4 = models.FloatField(label=price_label, min=0) treatmentConfPrice4 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentSurprise4 = models.IntegerField(label=surp_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentPrice5 = models.FloatField(label=price_label, min=0) treatmentConfPrice5 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentSurprise5 = models.IntegerField(label=surp_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentPrice6 = models.FloatField(label=price_label, min=0) treatmentConfPrice6 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentSurprise6 = models.IntegerField(label=surp_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentPrice7 = models.FloatField(label=price_label, min=0) treatmentConfPrice7 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentSurprise7 = models.IntegerField(label=surp_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentPrice8 = models.FloatField(label=price_label, min=0) treatmentConfPrice8 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) treatmentSurprise8 = models.IntegerField(label=surp_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) # ---> AI aiTakeAdvice = models.IntegerField( label='Ich beziehe den Rat der KI in meine Bewertung des Quadratmeterpreises ein.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) aiPercAccuracy = models.IntegerField( label='Auf einer Skala von 0 bis 100%: Für wie präzise halten Sie die Preisprognosen der KI?', choices=[[i, str(i) + '%'] for i in range(0, 101)]) aiCogTrustComp1 = models.IntegerField( label='Die KI ist kompetent und effektiv bei der Vorhersage der angebotenen Quadratmeterpreises.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) aiCogTrustComp2 = models.IntegerField( label='Die KI erfüllt Ihre Aufgabe, den angebotenen Quadratmeterpreis vorherzusagen, sehr gut.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) aiCogTrustComp3 = models.IntegerField( label='Insgesamt ist die KI eine kompetente Hilfe für meine Bewertung des Quadratmeterpreises.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) aiCogTrustInteg1 = models.IntegerField(label='Die KI gibt unvoreingenommene Bewertungen ab.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], ) aiCogTrustInteg2 = models.IntegerField(label='Die KI ist ehrlich.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], ) aiCogTrustInteg3 = models.IntegerField(label='Ich halte diese KI für integer.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], ) aiEmoTrust1 = models.IntegerField( label='Ich fühle mich sicher, wenn ich mich bei meiner Entscheidung auf die KI verlasse.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) aiEmoTrust2 = models.IntegerField( label='Ich fühle mich wohl, wenn ich mich bei meiner Entscheidung auf die KI verlasse.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) aiEmoTrust3 = models.IntegerField( label='Ich fühle mich zufrieden, wenn ich mich bei meiner Entscheidung auf die KI verlasse.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) # aiPerUsefulness1 = models.IntegerField( # label='Die Verwendung dieser KI bei meiner Arbeit würde meine Produktivität erhöhen.', # widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) # aiPerUsefulness2 = models.IntegerField(label='Die Verwendung dieser KI würde meine Effektivität erhöhen.', # widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], # ) # aiPerUsefulness3 = models.IntegerField(label='Ich würde diese KI für meine Arbeit nützlich finden.', # widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], # ) # ---> XAI explTakeAdvice = models.IntegerField( label='Ich beziehe die Erklärungen in meine Bewertung des Quadratmeterpreises ein.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) explPercAccuracy = models.IntegerField( label='Auf einer Skala von 0 bis 100%: Für wie präzise halten Sie die Erklärungen der KI?', choices=[[i, str(i) + '%'] for i in range(0, 101)]) explCogTrustComp1 = models.IntegerField( label='Die Erklärungen sind kompetent und effektiv darin die Logik der KI zu vermitteln.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) explCogTrustComp2 = models.IntegerField( label='Die Erklärungen erfüllen Ihre Aufgabe, die Logik der KI zu vermitteln, sehr gut.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) explCogTrustComp3 = models.IntegerField( label='Insgesamt sind die Erklärungen eine kompetente Hilfe um die Logik der KI zu verstehen.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) explCogTrustInteg1 = models.IntegerField(label='Die Erklärungen sind unvoreingenommen.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], ) explCogTrustInteg2 = models.IntegerField(label='Die Erklärungen sind ehrlich.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], ) explCogTrustInteg3 = models.IntegerField(label='Ich halte die Erklärungen für integer.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], ) explEmoTrust1 = models.IntegerField( label='Ich fühle mich sicher, wenn ich mich bei meiner Entscheidung auf die Erklärungen verlasse.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) explEmoTrust2 = models.IntegerField( label='Ich fühle mich wohl, wenn ich mich bei meiner Entscheidung auf die Erklärungen verlasse.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) explEmoTrust3 = models.IntegerField( label='Ich fühle mich zufrieden, wenn ich mich bei meiner Entscheidung auf die Erklärungen verlasse.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) # explPerUsefulness1 = models.IntegerField( # label="Die Verwendung dieser Erklärungen bei meiner Arbeit würde meine Produktivität erhöhen.", # widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) # explPerUsefulness2 = models.IntegerField( # label="Die Verwendung dieser Erklärungen würde meine Effektivität erhöhen.", # widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], # ) # explPerUsefulness3 = models.IntegerField(label="Ich würde diese Erklärungen für meine Arbeit nützlich finden.", # widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7], # ) # # # STAGE 3 # # postLocation1 = models.FloatField() postBalcony1 = models.FloatField() postGreen1 = models.FloatField() postPrice1 = models.FloatField() postConfLocation1 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfBalcony1 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfGreen1 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfPrice1 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postLocation2 = models.FloatField() postBalcony2 = models.FloatField() postGreen2 = models.FloatField() postPrice2 = models.FloatField() postConfLocation2 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfBalcony2 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfGreen2 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfPrice2 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postLocation3 = models.FloatField() postBalcony3 = models.FloatField() postGreen3 = models.FloatField() postPrice3 = models.FloatField() postConfLocation3 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfBalcony3 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfGreen3 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfPrice3 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postLocation4 = models.FloatField() postBalcony4 = models.FloatField() postGreen4 = models.FloatField() postPrice4 = models.FloatField() postConfLocation4 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfBalcony4 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfGreen4 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postConfPrice4 = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) postImpLocation = models.IntegerField( label="Wichtigkeit der Eigenschaft \nStadt (innerhalb der Kategorie \"A-Stadt\") für den Preis:", min=0, max=100, initial=0) postImpBalcony = models.IntegerField(label="Wichtigkeit der Eigenschaft Balkon/Terasse für den Preis:", min=0, max=100, initial=0) postImpGreen = models.IntegerField( label="Wichtigkeit der Eigenschaft Anteil Grünenwähler im Stadtteil für den Preis:", min=0, max=100, initial=0) # # # STAGE 4 # # inMarket_Price = models.FloatField(label=price_label, min=0) inMarket_ConfPrice = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) outMarket_Price = models.FloatField(label=price_label, min=0) outMarket_ConfPrice = models.IntegerField(label=conf_label, widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5]) # # # FINAL QUESTIONNAIRE # # age = models.IntegerField(label="Wie alt sind Sie?", choices=range(16, 100)) gender = models.StringField(label="Was ist Ihr Geschlecht?", widget=widgets.RadioSelectHorizontal, choices=["Weiblich", "Männlich", "Divers"]) degree = models.StringField(label="Was ist ihr höchster akademischer Abschluss?", choices=["Hauptschulabschluss", "Realschulabschluss", "Abitur", "Bachelor", "Master", "Doktor", "anderer Abschluss"]) experience_industry = models.IntegerField( label="Wie viele Jahre Berufserfahrung in der Immobilienbranche besitzen Sie?", choices=range(0, 100)) experience_task = models.IntegerField(label="Über wie viel " "Erfahrung in der Bewertung von Wohnungen haben Sie?", widget=widgets.RadioSelectHorizontal, choices=range(0, 11)) overconfidence1 = models.IntegerField(label="Ich denke, dass ich besser darin bin, Immobilienobjekte akkurat zu " "bewerten als der durchschnittliche Immobilienunternehmer in Deutschland.", widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) overconfidence2 = models.IntegerField(label="Ich denke, dass ich schlauer bin als der durchschnittliche Deutsche.", widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7]) risk_aversion = models.IntegerField(label="Im Allgemeinen, wie bereit sind Sie, Risiken einzugehen?", widget=widgets.RadioSelectHorizontal, choices=range(0, 11)) ai_familiarity = models.IntegerField(label="Ich bin mit Vorhersagesoftware vertraut, die Informationen " "bereitstellt, um menschliche Entscheidungen zu unterstützen.", widget=widgets.RadioSelectHorizontal, choices=range(0, 11)) email = models.StringField(label="Ihre E-Mail Adresse:", blank=True) # PAGES class InstructionsPage(Page): form_model = 'player' form_fields = ['is_mobile', 'consent'] @staticmethod def vars_for_template(player): new_version = False try: if player.participant.label[0] in ["k", "x"]: new_version = True except: pass return dict( new_version=new_version ) class Stage1(Page): form_model = "player" form_fields = ["priorLocation1", "priorBalcony1", "priorGreen1", "priorPrice1", "priorConfLocation1", "priorConfBalcony1", "priorConfGreen1", "priorConfPrice1", "priorLocation2", "priorBalcony2", "priorGreen2", "priorPrice2", "priorConfLocation2", "priorConfBalcony2", "priorConfGreen2", "priorConfPrice2", "priorLocation3", "priorBalcony3", "priorGreen3", "priorPrice3", "priorConfLocation3", "priorConfBalcony3", "priorConfGreen3", "priorConfPrice3", "priorLocation4", "priorBalcony4", "priorGreen4", "priorPrice4", "priorConfLocation4", "priorConfBalcony4", "priorConfGreen4", "priorConfPrice4", "priorImpLocation", "priorImpBalcony", "priorImpGreen"] @staticmethod def vars_for_template(player): import pandas as pd # prepare houses dictionary (for each player individually because of random order) houses = pd.read_csv("xai_experiment/immobilien_features.csv", index_col=0)[ ['Frankfurt', "balcony", "Anteil Gruenenwaehler"]] houses = houses.rename(columns={'Frankfurt': 'cit', 'balcony': 'bal', 'Anteil Gruenenwaehler': 'gre'}) houses["cit"] = ["Frankfurt am Main" if f == 1 else "Köln" for f in houses["cit"]] houses["bal"] = ["Ja" if b == 1 else "Nein" for b in houses["bal"]] houses["gre"] = ["Unterdurch­schnittlich" if g == 1 else "Durch­schnittlich" if g == 2 else "Überdurch­schnittlich" for g in houses["gre"]] indices_to_show = player.participant.immoSampleOrderS1 houses_in_order = [] ord = 0 for i in indices_to_show: ord += 1 focal_dic = houses[houses.index == i].to_dict('records') focal_dic[0]["ind"] = i focal_dic[0]["ord"] = ord focal_dic[0]["confLocation"] = "priorConfLocation" + str(ord) focal_dic[0]["confBalcony"] = "priorConfBalcony" + str(ord) focal_dic[0]["confGreen"] = "priorConfGreen" + str(ord) focal_dic[0]["confPrice"] = "priorConfPrice" + str(ord) houses_in_order.append(focal_dic) return dict( houses_in_order=houses_in_order ) @staticmethod def js_vars(player): import pandas as pd # prepare price to be displayed for only fixed features prices = pd.read_csv("xai_experiment/immobilien_cat_A_sim_prices.csv", index_col=0) pred_price_fixed = round(sum(prices.pred_price) / len(prices) / 50) * 50 return dict( pred_price_fixed=pred_price_fixed ) @staticmethod def error_message(player, values): print('values is', values) if values['priorImpLocation'] + values['priorImpBalcony'] + values['priorImpGreen'] != 100: return f"Bitte überprüfen Sie Ihre Angaben zur Wichtigkeit der variablen Eigenschaften. Die Summe der " \ f"von Ihnen vergebenen Sterne muss 100 ergeben. Aktuell ergibt sie " \ f"{values['priorImpLocation']} + {values['priorImpBalcony']} + {values['priorImpGreen']} = " \ f"{values['priorImpLocation'] + values['priorImpBalcony'] + values['priorImpGreen']}." class Stage2(Page): form_model = "player" @staticmethod def get_form_fields(player): form_fields = ["treatmentPrice1", "treatmentPrice2", "treatmentPrice3", "treatmentPrice4", "treatmentPrice5", "treatmentPrice6", "treatmentPrice7", "treatmentPrice8", "treatmentConfPrice1", "treatmentConfPrice2", "treatmentConfPrice3", "treatmentConfPrice4", "treatmentConfPrice5", "treatmentConfPrice6", "treatmentConfPrice7", "treatmentConfPrice8"] if player.participant.treatment != "none": form_fields.extend(["treatmentSurprise1", "treatmentSurprise2", "treatmentSurprise3", "treatmentSurprise4", "treatmentSurprise5", "treatmentSurprise6", "treatmentSurprise7", "treatmentSurprise8"]) return form_fields @staticmethod def vars_for_template(player): import pandas as pd # prepare houses dictionary (for each player individually because of random order) houses = pd.read_csv("xai_experiment/immobilien_features.csv", index_col=0)[ ['Frankfurt', "balcony", "Anteil Gruenenwaehler"]] houses = houses.rename(columns={'Frankfurt': 'cit', 'balcony': 'bal', 'Anteil Gruenenwaehler': 'gre'}) houses["cit"] = ["Frankfurt am Main" if f == 1 else "Köln" for f in houses["cit"]] houses["bal"] = ["Ja" if b == 1 else "Nein" for b in houses["bal"]] houses["gre"] = ["Unterdurchschnittlich" if g == 1 else "Durchschnittlich" if g == 2 else "Überdurchschnittlich" for g in houses["gre"]] indices_to_show = player.participant.immoSampleOrderS2 houses_in_order = [] # prepare predicted prices for treatments ai, xai local, xai global prices = pd.read_csv("xai_experiment/immobilien_pred_prices.csv", index_col=0) # prepare SHAP val for treatments xai local shap_val = pd.read_csv("xai_experiment/immobilien_shap.csv", index_col=0) shap_val = shap_val[['Stadt', 'balcony', 'Anteil Gruenenwaehler']] shap_val = shap_val.rename(columns={'Stadt': 'cit', 'balcony': 'bal', 'Anteil Gruenenwaehler': 'gre'}) shap_val = shap_val.applymap( lambda x: "+" + '{:,}'.format(round(x / 50) * 50).replace(",", "X").replace(".", ",").replace("X", ".") + " EUR/qm" if round(x / 50) * 50 > 0 else '{:,}'.format(round(x / 50) * 50).replace(",", "X").replace(".", ",").replace("X", ".") + " EUR/qm") ord = 0 for i in indices_to_show: ord += 1 focal_dic = houses[houses.index == i].to_dict('records') focal_dic[0]["pred_price"] = '{:,}'.format(round(prices[prices.index == i]["predicted"].item() / 50) * 50) \ .replace(",", "X").replace(".", ",").replace("X", ".") + " EUR/qm" focal_dic[0]["shap"] = shap_val[shap_val.index == i].to_dict('records') focal_dic[0]["ind"] = i focal_dic[0]["ord"] = ord focal_dic[0]["Price"] = "treatmentPrice" + str(ord) focal_dic[0]["ConfPrice"] = "treatmentConfPrice" + str(ord) focal_dic[0]["Surprise"] = "treatmentSurprise" + str(ord) houses_in_order.append(focal_dic) # prepare price to be displayed for only fixed features prices = pd.read_csv("xai_experiment/immobilien_cat_A_sim_prices.csv", index_col=0) pred_price_fixed = '{:,}'.format(round(sum(prices.pred_price) / len(prices) / 50) * 50) \ .replace(",", "X").replace(".", ",").replace("X", ".") + " EUR/qm" return dict( avg_price=pred_price_fixed, houses_in_order=houses_in_order ) @staticmethod def js_vars(player): import pandas as pd # prepare price to be displayed for only fixed features prices = pd.read_csv("xai_experiment/immobilien_cat_A_sim_prices.csv", index_col=0) pred_price_fixed = '{:,}'.format(round(sum(prices.pred_price) / len(prices) / 50) * 50) \ .replace(",", "X").replace(".", ",").replace("X", ".") + " EUR/qm" return dict( pred_price_fixed=pred_price_fixed ) class Stage2Questions(Page): form_model = "player" @staticmethod def is_displayed(player): return not player.participant.treatment == "none" @staticmethod def get_form_fields(player): form_fields = [] if player.participant.treatment != "none": form_fields = ["aiTakeAdvice", "aiPercAccuracy", "aiCogTrustComp1", "aiCogTrustComp2", "aiCogTrustComp3", "aiCogTrustInteg1", "aiCogTrustInteg2", "aiCogTrustInteg3", "aiEmoTrust1", "aiEmoTrust2", "aiEmoTrust3"] # "aiPerUsefulness1", "aiPerUsefulness2", "aiPerUsefulness3" if player.participant.treatment in ["xai_local", "xai_global"]: form_fields.extend(["explTakeAdvice", "explPercAccuracy", "explCogTrustComp1", "explCogTrustComp2", "explCogTrustComp3", "explCogTrustInteg1", "explCogTrustInteg2", "explCogTrustInteg3", "explEmoTrust1", "explEmoTrust2", "explEmoTrust3"]) # "explPerUsefulness1", "explPerUsefulness2", "explPerUsefulness3" return form_fields class Stage3(Page): form_model = "player" form_fields = ["postLocation1", "postBalcony1", "postGreen1", "postPrice1", "postConfLocation1", "postConfBalcony1", "postConfGreen1", "postConfPrice1", "postLocation2", "postBalcony2", "postGreen2", "postPrice2", "postConfLocation2", "postConfBalcony2", "postConfGreen2", "postConfPrice2", "postLocation3", "postBalcony3", "postGreen3", "postPrice3", "postConfLocation3", "postConfBalcony3", "postConfGreen3", "postConfPrice3", "postLocation4", "postBalcony4", "postGreen4", "postPrice4", "postConfLocation4", "postConfBalcony4", "postConfGreen4", "postConfPrice4", "postImpLocation", "postImpBalcony", "postImpGreen"] @staticmethod def vars_for_template(player): import pandas as pd # prepare houses dictionary (for each player individually because of random order) houses = pd.read_csv("xai_experiment/immobilien_features.csv", index_col=0)[ ['Frankfurt', "balcony", "Anteil Gruenenwaehler"]] houses = houses.rename(columns={'Frankfurt': 'cit', 'balcony': 'bal', 'Anteil Gruenenwaehler': 'gre'}) houses["cit"] = ["Frankfurt am Main" if f == 1 else "Köln" for f in houses["cit"]] houses["bal"] = ["Ja" if b == 1 else "Nein" for b in houses["bal"]] houses["gre"] = ["Unterdurch­schnittlich" if g == 1 else "Durch­schnittlich" if g == 2 else "Überdurch­schnittlich" for g in houses["gre"]] indices_to_show = player.participant.immoSampleOrderS1 houses_in_order = [] ord = 0 for i in indices_to_show: ord += 1 focal_dic = houses[houses.index == i].to_dict('records') focal_dic[0]["ind"] = i focal_dic[0]["ord"] = ord focal_dic[0]["confLocation"] = "postConfLocation" + str(ord) focal_dic[0]["confBalcony"] = "postConfBalcony" + str(ord) focal_dic[0]["confGreen"] = "postConfGreen" + str(ord) focal_dic[0]["confPrice"] = "postConfPrice" + str(ord) houses_in_order.append(focal_dic) return dict( houses_in_order=houses_in_order ) @staticmethod def js_vars(player): import pandas as pd # prepare price to be displayed for only fixed features prices = pd.read_csv("xai_experiment/immobilien_cat_A_sim_prices.csv", index_col=0) pred_price_fixed = round(sum(prices.pred_price) / len(prices) / 50) * 50 return dict( pred_price_fixed=pred_price_fixed ) @staticmethod def error_message(player, values): print('values is', values) if values['postImpLocation'] + values['postImpBalcony'] + values['postImpGreen'] != 100: return f"Bitte überprüfen Sie Ihre Angaben zur Wichtigkeit der variablen Eigenschaften. Die Summe der" \ f"von Ihnen vergebenen Sterne muss 100 ergeben. Aktuell ergibt sie " \ f"{values['postImpLocation']} + {values['postImpBalcony']} + {values['postImpGreen']} = " \ f"{values['postImpLocation'] + values['postImpBalcony'] + values['postImpGreen']}." class Stage4(Page): form_model = "player" form_fields = ["inMarket_Price", "inMarket_ConfPrice", "outMarket_Price", "outMarket_ConfPrice"] @staticmethod def vars_for_template(player): balconyDict = {0: "Nein", 1: "Ja"} greenDict = {1: "Unterdurchschnittlich", 2: "Durchschnittlich", 3: "Überdurchschnittlich"} return dict( immo_val={ "outMarket": { "Balcony": balconyDict[player.participant.outMarketProp[0]], "Green": greenDict[player.participant.outMarketProp[1]], }, "inMarket": { "Balcony": balconyDict[player.participant.inMarketProp[0]], "Green": greenDict[player.participant.inMarketProp[1]], } } ) class LastPage(Page): form_model = "player" form_fields = ["age", "gender", "degree", "experience_industry", "experience_task", "overconfidence1", "overconfidence2", "risk_aversion", "ai_familiarity", "email"] @staticmethod def vars_for_template(player): new_version = False try: if player.participant.label[0] in ["k", "x"]: new_version = True except: pass return dict( new_version=new_version ) class ThankYouPage(Page): pass page_sequence = [InstructionsPage, Stage1, Stage2, Stage2Questions, Stage3, Stage4, LastPage, ThankYouPage] #