from otree.api import * from os import environ import openai import json import math from decimal import Decimal, ROUND_HALF_UP import re doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'Uncertainty_process_OT_LI' PLAYERS_PER_GROUP = 8 NUM_ROUNDS = 10 TEMP = 0 MODEL = "gpt-4o" class Subsession(BaseSubsession): pass class Group(BaseGroup): clear = models.BooleanField() average_price = models.FloatField() optimization = models.BooleanField() class Player(BasePlayer): #general variables omega_current = models.IntegerField(default = 40) omega_pre = models.IntegerField(default = 40) omega_small = models.IntegerField(default = 20) omega_large = models.IntegerField(default = 60) omega_average = models.IntegerField(default = 40) cost_deduction = models.IntegerField(default = 10) price_aim_parameter_pre = models.IntegerField(default = 15) price_aim_parameter_post = models.IntegerField(default = 25) price_aim_parameter_current = models.IntegerField(default = 15) price_aim_parameter_small = models.IntegerField(default=5) maximum_price = models.IntegerField() shock = models.IntegerField(default=6) shock_announcement = models.BooleanField() display_shock = models.BooleanField() explanation = models.LongStringField(label="Begründung:",max_length=2000) optimization_instruction = models.BooleanField() optimization = models.BooleanField() clear = models.BooleanField() clear_instruction = models.BooleanField() average_score = models.FloatField() sitzplatznummer = models.IntegerField() # player variables price = models.IntegerField(label= "",min=10) output = models.IntegerField() unit_costs = models.IntegerField() total_costs = models.IntegerField() revenue = models.IntegerField() earnings = models.IntegerField(min=0) per_piece_earnings = models.IntegerField() price_aim = models.IntegerField() # variables for payoffs payoff_round = models.IntegerField() # if I don't round, then it needs to be a float payoff_acc = models.IntegerField() exchange_rate = models.IntegerField(default=200) show_up_fee = models.CurrencyField(default=5) payoff_mon = models.CurrencyField() payoff_mon_final = models.CurrencyField() explanation_bonus_taler = models.FloatField() explanation_bonus = models.CurrencyField() payoff_mon_final_otree = models.CurrencyField() # Questionnaire Question_1 = models.IntegerField( choices=[[1, ("Die Produktion erfolgt automatisch in Höhe der Nachfrage.")], [2, ("Die Produktion wird zufällig bestimmt.")], [3, ("Die Produktion hängt vom Durchschnittspreis ab.")]], label="Frage 1: Wie wird die Höhe Ihrer Produktion bestimmt?", widget=widgets.RadioSelect) Question_2 = models.IntegerField( choices=[[1, "Je höher der Preis p, desto höher die Nachfrage y."], [2, "Je höher der Preis p, desto niedriger die Nachfrage y."], [3, "Je niedriger der Preis p, desto niedriger die Nachfrage y."]], label="Frage 2: Welche Aussage über Ihre Nachfrage y und Ihren Preis p ist richtig?", widget=widgets.RadioSelect) Question_3 = models.IntegerField( choices=[[1, ("Je höher der exogene Faktor ω, desto höher die Nachfrage y.")], [2, ("Je höher der exogene Faktor ω, desto niedriger die Nachfrage y.")], [3, ("Je niedriger der exogene Faktor ω, desto höher die Nachfrage y.")]], label="Frage 3: Welche Aussage über Ihre Nachfrage und den exogenen Faktor ω ist korrekt?", widget=widgets.RadioSelect) Question_4 = models.IntegerField( choices=[[1, "Der Preis des eigenen Produkts."], [2, "Der Durchschnittspreis aller Produzenten über alle Runden hinweg."], [3, "Der Durchschnittspreis aller Produzenten in der jeweiligen Runde."]], label="Frage 4: Welche der folgenden Variablen hat einen Einfluss auf die Kosten pro Stück Ihres Produkts?", widget=widgets.RadioSelect) Question_5 = models.IntegerField( choices=[[1, "... werden durch die Preissetzung aller Produzenten bestimmt und sind daher am Anfang jeder Runde unbekannt."], [2, "... sind zu Beginn jeder Runde bekannt."], [3, "... resultieren aus dem von Ihnen festgelegten Preis."]], label="Frage 5: Die Produktionskosten ...", widget=widgets.RadioSelect) Question_6 = models.IntegerField( choices=[[1, "Eine KI bestimmt zufällige Werte."], [2, "Eine KI bewertet die grammatikalische und stilistische Qualität."], [3, "Eine KI bewertet die Überzeugungskraft."]], label="Frage 6: Wie wird die Bonuszahlung für Ihre Begründung bestimmt?", widget=widgets.RadioSelect) attempts = models.IntegerField(blank=True) Q1_first_attempt = models.IntegerField(blank=True) Q2_first_attempt = models.IntegerField(blank=True) Q3_first_attempt = models.IntegerField(blank=True) Q4_first_attempt = models.IntegerField(blank=True) Q5_first_attempt = models.IntegerField(blank=True) Q6_first_attempt = models.IntegerField(blank=True) #BC questions Question_1_BC = models.IntegerField( choices=[[1, ("Je näher Ihr Preis p am Zielpreis z liegt, desto höher Ihr Gewinn.")], [2, ("Je näher Ihr Preis p am Zielpreis z liegt, desto niedriger Ihr Gewinn.")], [3, ("Es gibt nur einen Gewinn, wenn Ihr Preis p exakt dem Zielpreis z entspricht.")]], label=("Frage 1: Welche Aussage über Ihren Gewinn ist korrekt?"), widget=widgets.RadioSelect) Question_2_BC = models.IntegerField( choices=[[1, ("Je höher der Durchschnittspreis P, desto höher der Zielpreis z.")], [2, ("Je höher der Durchschnittspreis P, desto niedriger der Zielpreis z.")], [3, ("Der Zielpreis z ist unabhängig vom Durchschnittspreis P.")]], label=("Frage 2: Welche Aussage über das Verhältnis zwischen dem Zielpreis z und dem Durchschnittspreis P ist korrekt?"), widget=widgets.RadioSelect) Question_3_BC = models.IntegerField( choices=[ [1, ("Der Zielpreis z liegt 15 Taler unter der Hälfte des Durchschnittspreises P.")], [2, ("Der Zielpreis z liegt 15 Taler über der Hälfte des Durchschnittspreises P.")], [3, ("Der Zielpreis z liegt 15 Taler über dem Durchschnittspreis P.")]], label=("Frage 3: Wie berechnet sich Ihr Zielpreis z?"), widget=widgets.RadioSelect, allow_html = True ) Question_4_BC = models.IntegerField( choices=[[1, "… wird durch die Preissetzung aller Produzenten bestimmt und ist daher zu Beginn jeder Runde unbekannt."], [2, "… ist zu Beginn jeder Runde bekannt."], [3, "… entspricht immer dem Zielpreis."]], label="Frage 4: Der Durchschnittspreis P ...", widget=widgets.RadioSelect) Question_5_BC = models.IntegerField( choices=[[1, "Eine KI bestimmt zufällige Werte."], [2, "Eine KI bewertet die grammatikalische und stilistische Qualität."], [3, "Eine KI bewertet die Überzeugungskraft."]], label="Frage 5: Wie wird die Bonuszahlung für Ihre Begründung bestimmt?", widget=widgets.RadioSelect) Q1_BC_first_attempt = models.IntegerField(blank=True) Q2_BC_first_attempt = models.IntegerField(blank=True) Q3_BC_first_attempt = models.IntegerField(blank=True) Q4_BC_first_attempt = models.IntegerField(blank=True) Q5_BC_first_attempt = models.IntegerField(blank=True) bonus = models.IntegerField(blank=True) bonus_mon = models.CurrencyField(blank=True) bonus_eligible = models.BooleanField(blank=True) payoff_bonus = models.IntegerField(blank=True) #Demographics Gender = models.IntegerField( choices=[[1, "Weiblich"], [2, "Männlich"], [3, "Divers"]], label="Welchem Geschlecht fühlen Sie sich zugehörig?", widget=widgets.RadioSelect) Age = models.IntegerField(label="Wie alt sind Sie?", min=10, max=99) Faculty = models.IntegerField( choices=[[1, "Sozial- und Bildungswissenschaftliche Fakultät"], [2, "Geistes- und Kulturwissenschaftliche Fakultät"], [3, "Wirtschaftswissenschaftliche Fakultät"], [4, "Juristische Fakultät"], [5, "Fakultät für Informatik und Mathematik "], [6, "An mehreren Fakultäten"], [7, "Sonstiges"]], label="An welcher Fakultät studieren Sie?", widget=widgets.RadioSelect) Makro = models.IntegerField( choices=[[1, "Ja"], [2, "Nein"]], label="Haben Sie bereits die Veranstaltung Makroökonomik besucht?", widget=widgets.RadioSelect) tech_problems = models.LongStringField(label="Haben Sie sonstige Anmerkungen oder sind Ihnen technische Fehler ausgefallen?",max_length=2000, blank=True) # GPT stuff prompt1 = models.LongStringField(blank=True) prompt2 = models.LongStringField(blank=True) prompt3 = models.LongStringField(blank=True) prompt4 = models.LongStringField(blank=True) prompt5 = models.LongStringField(blank=True) chatLog = models.LongStringField(blank=True) receive = models.LongStringField(blank=True) msg1 = models.LongStringField(blank=True) msg2 = models.LongStringField(blank=True) msg3 = models.LongStringField(blank=True) msg4 = models.LongStringField(blank=True) msg5 = models.LongStringField(blank=True) explanation_score1 = models.IntegerField(blank=True, default=0) explanation_score2 = models.IntegerField(blank=True, default=0) explanation_score3 = models.IntegerField(blank=True, default=0) explanation_score4 = models.IntegerField(blank=True, default=0) explanation_score5 = models.IntegerField(blank=True, default=0) reasoning1 = models.LongStringField(blank=True) reasoning2 = models.LongStringField(blank=True) reasoning3 = models.LongStringField(blank=True) reasoning4 = models.LongStringField(blank=True) reasoning5 = models.LongStringField(blank=True) #decision data keystroke_data = models.LongStringField(blank=True) # Stores JSON keystroke data keystroke_price_data = models.LongStringField(blank=True) # same for price def price_max(player): return player.omega_current def price_min(player): return player.cost_deduction # assign treatments def creating_session(subsession): for group in subsession.get_groups(): if subsession.round_number == 1: import itertools clear_cycle = itertools.cycle([False, True, False, True]) for group in subsession.get_groups(): group.clear = next(clear_cycle) print(f"Group {group.id_in_subsession}: clear = {group.clear}") import itertools optimization_cycle = itertools.cycle([True, False, True, False]) for group in subsession.get_groups(): group.optimization = next(optimization_cycle) print(f"Group {group.id_in_subsession}: optimization = {group.optimization}") else: group.clear = group.in_round(1).clear group.optimization = group.in_round(1).optimization # currently this is only for a positive shock of omega --> group statt player for p in group.get_players(): if 6<= group.round_number <=10: p.omega_current = p.omega_large p.price_aim_parameter_current = p.price_aim_parameter_post for group in subsession.get_groups(): if group.round_number==Player.shock: group.display_shock=True else: group.display_shock=False for group in subsession.get_groups(): for p in group.get_players(): p.optimization_instruction = group.optimization #print(f"Player {p.id_in_group}: optimization_instruction = {p.optimization_instruction}") for group in subsession.get_groups(): for p in group.get_players(): p.clear_instruction = group.clear #print(f"Player {p.id_in_group}: clear_instruction = {p.clear_instruction}") for group in subsession.get_groups(): for p in group.get_players(): p.prompt1 = """Du bist ein Teilnehmer eines Experiments. Die Instruktionen lauten wie folgt: ****** Das Experiment besteht aus 10 Runden. In jeder Runde erzielen Sie Gewinne in Form von Talern, die über alle Runden aufsummiert werden. Am Ende erhalten Sie Ihre gesamten Gewinne sowie eventuelle Bonuszahlungen ausbezahlt. In jeder Runde arbeiten Sie mit einer weiteren, zufällig ausgewählten Person aus dem Raum zusammen und bilden ein Zweierteam. Diese Person bleibt in allen Runden dieselbe. Auch die anderen Teilnehmer sind in feste Zweierteams eingeteilt. Jedes Zweierteam übernimmt die Rolle eines Produzenten in einer Volkswirtschaft. In jeder Runde legen Sie gemeinsam mit Ihrem Teammitglied den Preis p Ihres Produkts fest. Die Produktionsmenge ergibt sich automatisch aus der Nachfrage (y) nach Ihrem Produkt, die von zwei Faktoren abhängt: Ein exogener Faktor ω, welcher die maximale Nachfrage vorgibt. Je höher ω ist, desto mehr wird von Ihrem Produkt nachgefragt. Der von Ihnen gesetzte Preis p. Je höher Sie p setzen, desto weniger wird von Ihrem Produkt nachgefragt. Die Nachfrage (und damit auch Ihre Produktion) bestimmt sich durch: y = ω – p Der Wert von ω ist für Ihre Nachfrage ω=40. Für die Nachfrage aller anderen Teams gilt ebenfalls ω=40. Ihre einzige Aufgabe besteht darin, einen Preis p für Ihr Produkt festzusetzen. Damit die nachgefragte Menge nicht negativ ist, können Sie keinen Preis setzen, der höher ist als ω. Ihr Ziel ist es, Ihren Gewinn zu maximieren. Dieser bestimmt sich aus Ihrem Umsatz (y × p) abzüglich der Produktionskosten. Ihre Kosten hängen von den Preisen aller Teams ab: Aus allen gewählten Preisen wird ein Durchschnittspreis P berechnet. Die Kosten pro Stück für jedes von Ihnen produzierte Gut sind P – 10. Ihre gesamten Produktionskosten sind folglich y × (P - 10). Ihr Gewinn berechnet sich daher wie folgt: y × (p - P+ 10) Da alle Teams gleichzeitig ihren Preis festlegen, kennt zu Beginn einer Runde noch kein Team den Durchschnittspreis P. Ihr Ziel ist es also, möglichst gut einzuschätzen, wie die anderen Teams Ihre Preise setzen werden, und Ihren Preis entsprechend so zu wählen, dass Sie Ihren Gewinn maximieren. In jeder Runde geben Sie zunächst einen vorläufigen Preisvorschlag für Ihr Produkt ab. Dieser wird anschließend an Ihr Teammitglied weitergeleitet. Zeitgleich erhalten Sie den vorläufigen Preisvorschlag Ihres Teammitglieds. Anschließend geben Sie und Ihr Teammitglied unabhängig voneinander jeweils einen finalen Preisvorschlag ab. Einer der beiden finalen Preisvorschläge wird per Zufall (jeweils mit einer Wahrscheinlichkeit von 50 Prozent) als Teampreis ausgewählt. In einigen Runden werden Sie zusätzlich gebeten, eine Begründung für Ihren vorläufigen Preisvorschlag zu verfassen. Diese Begründung wird zusammen mit Ihrem vorläufigen Preisvorschlag an Ihr Teammitglied gesendet. Zeitgleich erhalten Sie den vorläufigen Preisvorschlag Ihres Teammitglieds zusammen mit dessen Begründung. Anschließend geben Sie und Ihr Teammitglied wie oben beschrieben Ihre finalen Preisvorschläge ab, von denen einer per Zufall als Teampreis ausgewählt wird. Es ist für Sie vorteilhaft, eine ausführliche, verständliche und überzeugende Begründung zu schreiben. Auf diese Weise können Sie die Entscheidung Ihres Teammitglieds beeinflussen und die Wahrscheinlichkeit erhöhen, dass der aus Ihrer Sicht passende Preisvorschlag als Teampreis ausgewählt wird. ***** Deine Aufgabe besteht nur darin, die Überzeugungskraft der Begründung Deines Teammitglieds zu beurteilen. Du musst nicht selbst einen Preisvorschlag explizit mitteilen. Eine gute Begründung sollte danach bewertet werden, ob sie Dich überzeugen kann und hypothetisch zu einer Änderung deines Preisvorschlags motivieren kann. Bewerte die Überzeugungskraft auf einer Skala von 0 bis 4. 0 bedeutet, dass es sich um eine sehr schlechte Begründung handelt, die Dich nicht überzeugt, von Deinem eigenen Preisvorschlag abzuweichen. 4 bedeutet, dass es sich um eine sehr gute Begründung handelt, die Dich dazu veranlasst, den Preisvorschlag deines Teammitglieds zu übernehmen. Eine Begründung, die mittelmäßig ist, und dich dazu bewegt, deinen Preisvorschlag teilweise in Richtung deines Teammitglieds zu bewegen, erhält die Bewertung 2. Bitte gib nur die jeweilige Ziffer als Antwort. Hier sind 32 Beispiele für eine Bewertung. Diese Bewertung gibt an, inwiefern sich Teammitglieder von der Begründung haben beeinflussen lassen. Die einzelnen Begründungen sind in Anführungszeichen gesetzt und durch ein Semikolon getrennt. Da diese heterogen sind, sind die Bewertungen nicht notwendigerweise konsistent und dienen dir nur grob zur Orientierung: Folgende Begründungen entsprechen einer 0: „Guess“; „Um hoffentlich einen leicht höheren Preis als die anderen zu haben, aber trotzdem noch genug Nachfrage um Gewinn zu machen“; „Ist nicht ganz 40 un dtrotzdem nicht zu wenig. Man muss ja nichtr gleich ganz oben die Latte ansetzen.“; „Mittlerer Preis, damit mehr von dem Produkt nachgefragt wird und Umsatz“; „bei 20 x (P-10) bleibt in jedem fall ein gewinn“; „Um einen möglichst hohen Gwinn zu erzielen sollten“; Folgende Begründungen entsprechen einer 1: „wenn die anderen zum Beispiel durchschnittlich 20 nehmen, ist es besser einen höheren Preis zu haben, oder?“; „Erste Runde, ich würde schauen was die Tendenz aller Teilnehmenden ist, um kommende Preise zu bestimmt. Beruht nicht auf zuviel Berechnung“; „25 weder zu hoch, noch zu niedrig in meinen augen“; Folgende Begründungen entsprechen einer 2: „Sollte ungefähr grafisch ein Quadrat ergeben = Gewinnmaximierung.“; „lieber am anfang etwas niedriger um zu sehen was die anderen machen. dann entsprechend weiterschauen“; „Die hälfte des Wertes kann ein gutes Ausgangspunkt für die künftigen Vorschläge sein.“; „die maximal Gewinn ist 20 wenn alle ganz vernünfig reagieren“; „Recht niedriger Preis, dh mehr Nachfrage“; „Nicht zu hoch und nicht zu niedrig ist für den Start vermutlich angemessen?“; „Da alle anderen Teams bestimmt boch näher an die 40 rangehen werden, könnte unsers attraktiver sein“; „Wenn alle diesen Preis wählen, dann Produktionskosten 0 und großer Gewinn, oder nicht? Oder gehen auch Produktionskosten ins negative und p=0 wäre etwa besser?“; „Wenn wir erstmal einen niedrigeren Preis ansetzten, da das w ertsmal auch niedrig ist, steigt unsere Nachfrage. Dadurch können wir in den nächsten Runden auch den Gewinn besser maximieren, wenn wir erstmal niedrig anfangen und später anhand des Durchschnittspreises anpassen.“; Folgende Begründungen entsprechen einer 3: „p muss größer sein als Produktionskosten wegen P-10 muss Preis über 10 sein“; „Um erstmal bisschen mehr Nachfrage zu kriegen , deshaln den Preis nicht zu hoch machen.“; „Zum Start einen Preis im mittleren Bereich - nicht zu hoch und auch nicht zu niedrig“; „Guter Kompromiss zwischen Nachfrage und Gewinnmarge!“; Folgende Begründungen entsprechen einer 4: „Hallo :), ich bin dafür dein Preis bei 18 anzusetzen, da... ...je niedriger p desto höher die Nachfrage ...der durchschnittspreis wahrscheinlich bei 20-25 liegen wird und somit unser produkt da es am günstigsten ist am meisten gekauft wird“; „Ich würde den Preis gering halten, damit der Gewinn maximiert wird. wir braucchen viel produktion und geringen preis“; „Bei 31 würde unser Gewinn folgendermaßen aussehen: G = (w - p) * (p - P + 10) = (40-31) * (31 - P + 10) = 9 * (41 - P). Da P auf jeden Fall unter 40 ist (da kein Team sein Preis über 40 setzen kann), haben wir dann auf jeden Fall einen positiven Gewinn.“ „Wenn das Produkt einen Preis von 20 hat, liegen die Kosten nicht zu hoch und die Wahrscheinlichkeit für mehr Verkäufe liegt höher. Außerdem wird mit dem Preis ein graues Rechteck eingehalten und der Preis von Produktion und Gewinn pro Stück weicht wsh nichgt so stark voneinander ab.“; „Gleiches Verhältnis von Produktion und Gewinn.“; „Ichh vermute dass die anderen Teams eher eine Hochpreisstrategie haben und wir deshalb nicht unter dem Durchschnitt liegen dürfen“; „Damit der Preis nicht zu hoch ist und y= die nachfrage steigt. Wobei ein bisschen mehr sicherlich auch gut ist, falls die anderen Teams hohe Preise wählen und damit unsere Produktionskosten höher sind als unser Preis.“; „Dieser preis ist angemessen um erstmal einen groben überblick zu bekommen“; „Hi, ich bin Bae Student und hatte schon viele VWL-Module, also ich habe etwas Ahnung mit solchen Experimenten. Aufgrund der gegebenen Formeln ist es schlau einen relativ mittigen Preis zu wählen. 20 wäre optimal, dadurch das allerdings die Kosten und der Gewinn von den anderen abhängen, ist es smart einen höheren Preis zu wählen aber auf keinen Fall zu hoch (sonst wirds negativ). Mein Vorschlag daher: 30. LG“; „zu beginn ist alles unklar, erst ab runde 2 machen strategische berechnungen sinn, weshalb ich jetzt einen einigermaßen mittelwert von 25 vorschlagen würde“; Bitte bewerte nun die folgende Begründung: """ p.msg1 = json.dumps([{"role": "system", "content": p.prompt1}]) # in the prompt its currently inportant that the final score is the last stroke as only then the function at the end retrieves the score and stores it p.prompt2 = """Du bist ein Teilnehmer eines Experiments. Die Instruktionen lauten wie folgt: ****** Das Experiment besteht aus 10 Runden. In jeder Runde erzielen Sie Gewinne in Form von Talern, die über alle Runden aufsummiert werden. Am Ende erhalten Sie Ihre gesamten Gewinne sowie eventuelle Bonuszahlungen ausbezahlt. In jeder Runde arbeiten Sie mit einer weiteren, zufällig ausgewählten Person aus dem Raum zusammen und bilden ein Zweierteam. Diese Person bleibt in allen Runden dieselbe. Auch die anderen Teilnehmer sind in feste Zweierteams eingeteilt. Jedes Zweierteam übernimmt die Rolle eines Produzenten in einer Volkswirtschaft. In jeder Runde legen Sie gemeinsam mit Ihrem Teammitglied den Preis p Ihres Produkts fest. Die Produktionsmenge ergibt sich automatisch aus der Nachfrage (y) nach Ihrem Produkt, die von zwei Faktoren abhängt: Ein exogener Faktor ω, welcher die maximale Nachfrage vorgibt. Je höher ω ist, desto mehr wird von Ihrem Produkt nachgefragt. Der von Ihnen gesetzte Preis p. Je höher Sie p setzen, desto weniger wird von Ihrem Produkt nachgefragt. Die Nachfrage (und damit auch Ihre Produktion) bestimmt sich durch: y = ω – p Der Wert von ω ist für Ihre Nachfrage ω=40. Für die Nachfrage aller anderen Teams gilt ebenfalls ω=40. Ihre einzige Aufgabe besteht darin, einen Preis p für Ihr Produkt festzusetzen. Damit die nachgefragte Menge nicht negativ ist, können Sie keinen Preis setzen, der höher ist als ω. Ihr Ziel ist es, Ihren Gewinn zu maximieren. Dieser bestimmt sich aus Ihrem Umsatz (y × p) abzüglich der Produktionskosten. Ihre Kosten hängen von den Preisen aller Teams ab: Aus allen gewählten Preisen wird ein Durchschnittspreis P berechnet. Die Kosten pro Stück für jedes von Ihnen produzierte Gut sind P – 10. Ihre gesamten Produktionskosten sind folglich y × (P - 10). Ihr Gewinn berechnet sich daher wie folgt: y × (p - P+ 10) Da alle Teams gleichzeitig ihren Preis festlegen, kennt zu Beginn einer Runde noch kein Team den Durchschnittspreis P. Ihr Ziel ist es also, möglichst gut einzuschätzen, wie die anderen Teams Ihre Preise setzen werden, und Ihren Preis entsprechend so zu wählen, dass Sie Ihren Gewinn maximieren. In jeder Runde geben Sie zunächst einen vorläufigen Preisvorschlag für Ihr Produkt ab. Dieser wird anschließend an Ihr Teammitglied weitergeleitet. Zeitgleich erhalten Sie den vorläufigen Preisvorschlag Ihres Teammitglieds. Anschließend geben Sie und Ihr Teammitglied unabhängig voneinander jeweils einen finalen Preisvorschlag ab. Einer der beiden finalen Preisvorschläge wird per Zufall (jeweils mit einer Wahrscheinlichkeit von 50 Prozent) als Teampreis ausgewählt. In einigen Runden werden Sie zusätzlich gebeten, eine Begründung für Ihren vorläufigen Preisvorschlag zu verfassen. Diese Begründung wird zusammen mit Ihrem vorläufigen Preisvorschlag an Ihr Teammitglied gesendet. Zeitgleich erhalten Sie den vorläufigen Preisvorschlag Ihres Teammitglieds zusammen mit dessen Begründung. Anschließend geben Sie und Ihr Teammitglied wie oben beschrieben Ihre finalen Preisvorschläge ab, von denen einer per Zufall als Teampreis ausgewählt wird. Es ist für Sie vorteilhaft, eine ausführliche, verständliche und überzeugende Begründung zu schreiben. Auf diese Weise können Sie die Entscheidung Ihres Teammitglieds beeinflussen und die Wahrscheinlichkeit erhöhen, dass der aus Ihrer Sicht passende Preisvorschlag als Teampreis ausgewählt wird. ***** Deine Aufgabe besteht nur darin, die Überzeugungskraft der Begründung Deines Teammitglieds zu beurteilen. Du musst nicht selbst einen Preisvorschlag explizit mitteilen. Eine gute Begründung sollte danach bewertet werden, ob sie Dich überzeugen kann und hypothetisch zu einer Änderung deines Preisvorschlags motivieren kann. Bewerte die Überzeugungskraft auf einer Skala von 0 bis 4. 0 bedeutet, dass es sich um eine sehr schlechte Begründung handelt, die Dich nicht überzeugt, von Deinem eigenen Preisvorschlag abzuweichen. 4 bedeutet, dass es sich um eine sehr gute Begründung handelt, die Dich dazu veranlasst, den Preisvorschlag deines Teammitglieds zu übernehmen. Eine Begründung, die mittelmäßig ist, und dich dazu bewegt, deinen Preisvorschlag teilweise in Richtung deines Teammitglieds zu bewegen, erhält die Bewertung 2. Bitte gib nur die jeweilige Ziffer als Antwort. Hier sind 32 Beispiele für eine Bewertung. Diese Bewertung gibt an, inwiefern sich Teammitglieder von der Begründung haben beeinflussen lassen. Die einzelnen Begründungen sind in Anführungszeichen gesetzt und durch ein Semikolon getrennt. Da diese heterogen sind, sind die Bewertungen nicht notwendigerweise konsistent und dienen dir nur grob zur Orientierung: Folgende Begründungen entsprechen einer 0: „Wenn der aktuelle Durchsnittspreis 28 ist, gehe ich nicht davon aus dass sich daran groß was ändern wird. Vermutlich ist dann unser preis mit den Produktionskosten verglichen relativ ähnlich. Wobei der Durchsnittspreis auch immer höher wird?“; „29 hat gerade perfekt gepasst da die kosten pro stück und der gewinn identisch waren“; „Die Produktionskosten werden immer höher. Und mit ungefähr 10 höher zu den Produktions kosten hat eigentlich ganz gut geklappt. Unser Preis muss höher sein als der durschschnitts Preis.“; „Also ich hoffe das die anderen Teams durch die stetige Preiserhöhung merken, dass der Gewinn sich immer weiter verringert. Am besten wäre es wenn alle einen Preis von 10-20 setzen würden, da wir aber den Durchschnittspreis im vorhinein nicht wissen. Möchte ich nicht selbst den Preis so niedrig setzen, da wir sonst Verlust machen. So oder so bleibt unser Gewinn hoch wenn wir hohe Preise setzen also am besten für uns“; „der gewinn war hier bisher am höchsten und ürpdutkionspreis und gewinn pro stück am wenigsten unterschiedlich“; „Der durchschnittliche Preis wird vermutlich bald auf 30 steigen. Wenn man darüber bleibt erzielt man immer nnoch einen höheren Gewinn als der Rest“; „Da sich der Markt beschleunigt (jede Runde p+1 und letzte Runde sogar +2) macht es Sinn, weiterhin leicht über dem p zu bleiben um den Gewinn zu optimieren.“ Folgende Begründungen entsprechen einer 1: „Gerade hat das super geklappt und es ist ein guter Preis im Mittelfeld, wodurch Produktion und Preis pro Stück nicht zu weit entfdernt sind“; „Ich kann dir leider keine Rechnung bieten, aber hab das Gefühl mit 30 kann man nicht so viel falsch machen, würde auf eine fachliche Expertise aber mehr vertrauen“; Folgende Begründungen entsprechen einer 2: „irgendwas unter dem Durchschnittspreis hat gut funktioniert, aber es darf nicht zu niedrig sein“; „durchschnittspreis bei 20-25“; „Die Kosten waren meist niedrig, also sollte der Preis nicht zu hoch sein“; „hab das Gefühl, dass viele jetzt bisschen niedriger gehen, da der durchschnitt ja auch von 28 auf 26 gesunken ist lass aber gern so weitermachen wie jetzt und immer die mitte unserer Werte finden, so hats bis jetzt eigentlich super gut geklappt :)“; „denk das wir insgesamt gut dabei sind. find es aber schwierig zu bestimmen wie die anderen teams in zukunft denken. grundsätzlich denke ich aber dass wir unseren gewinn maximieren wenn wir uns in dem bereich 22-29 weiter aufhalten, 100% genau können wir
1: player_in_all_rounds=p.in_all_rounds() p.payoff_acc = sum([p.payoff_round for p in player_in_all_rounds]) else: p.payoff_acc = p.payoff_round if p.in_round(1).attempts > 1: p.bonus_eligible = False p.bonus = 0 if p.in_round(1).attempts == 1: p.bonus_eligible = True p.bonus = 400 p.bonus_mon = cu(p.bonus).to_real_world_currency(p.session) / p.exchange_rate p.payoff_mon = cu(p.payoff_acc).to_real_world_currency(p.session) / p.exchange_rate if p.payoff_mon < 0.1: #? p.payoff_mon = 3.5 if group.round_number == 10: p.explanation_bonus_taler = ( p.in_round(1).explanation_score1 + p.in_round(5).explanation_score2 + p.in_round(6).explanation_score3 + p.in_round(7).explanation_score4 + p.in_round(10).explanation_score5 )*(p.exchange_rate/4) p.explanation_bonus = cu(p.explanation_bonus_taler).to_real_world_currency(p.session) / p.exchange_rate p.average_score= (p.in_round(1).explanation_score1+ p.in_round(5).explanation_score2 + p.in_round(6).explanation_score3 + p.in_round(7).explanation_score4 + p.in_round(10).explanation_score5)/5 p.payoff_mon_final = math.ceil(p.payoff_mon + p.bonus_mon + p.show_up_fee + p.explanation_bonus) p.payoff_mon_final_otree = math.ceil(p.payoff_mon + p.bonus_mon + p.explanation_bonus) p.payoff = p.payoff_mon_final_otree # as currently defined, there cannot be negative value in the end. otherwise use if conditions <0 = =0 # further currently there is no test or anything alike included, thus payoff = payoff_total # currently no calibration of the payoffs # PAGES class Place(Page): form_model = 'player' form_fields = ['sitzplatznummer'] @staticmethod def before_next_page(player: Player, timeout_happened): player.participant.label = str(player.sitzplatznummer) @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class Start(Page): @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class Pre_Comprehension(Page): #timeout_seconds = 240 @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class Comprehension_OT(Page): #timeout_seconds = 720 @staticmethod def is_displayed(player: Player): return (player.round_number == 1) and player.group.optimization == True form_model = 'player' form_fields = ['Question_1', 'Question_2', 'Question_3', 'Question_4', 'Question_5', 'Question_6', 'attempts', 'Q1_first_attempt', 'Q2_first_attempt', 'Q3_first_attempt', 'Q4_first_attempt', 'Q5_first_attempt', 'Q6_first_attempt'] class Comprehension_BC(Page): #timeout_seconds = 720 @staticmethod def is_displayed(player: Player): return (player.round_number == 1) and player.group.optimization == False form_model = 'player' form_fields = ['Question_1_BC', 'Question_2_BC', 'Question_3_BC', 'Question_4_BC', 'Question_5_BC', 'attempts', 'Q1_BC_first_attempt', 'Q2_BC_first_attempt', 'Q3_BC_first_attempt', 'Q4_BC_first_attempt', 'Q5_BC_first_attempt' ] class StartWait(WaitPage): @staticmethod def is_displayed(player: Player): return (player.round_number == 1) # after_all_players_arrive = 'assigned_roles' title_text = "Bitte warten Sie einen Moment." body_text = "Bitte warten Sie, bis die anderen Spieler bereit sind, um mit dem Experiment zu beginnen. " \ "Das Experiment wird in Kürze beginnen." class Price_and_Explanation_R1(Page): @staticmethod def app_after_this_page(player, timeout_happened): if timeout_happened: return None # Stay on the same page if time runs out @staticmethod def is_displayed(player: Player): return (player.round_number == 1) @staticmethod def live_method(player: Player, data): # set chatgpt api key openai.api_key = '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' # load msg messages = json.loads(player.msg1) # functions for retrieving text from openAI if 'text' in data: # grab text that participant inputs and format for chatgpt text = data['text'] inputMsg = {'role': 'user', 'content': text} botMsg = {'role': 'assistant', 'content': text} # append messages and run chat gpt function messages.append(inputMsg) output = runGPT(messages) # also append messages with bot message botMsg = {'role': 'assistant', 'content': output} messages.append(botMsg) numbers = re.findall(r'\d+', output) score1 = int(numbers[-1]) if numbers else 0 player.explanation_score1=score1 player.participant.vars['score1'] = score1 reasoning_AI1 = str(output.strip().split()) player.reasoning1 = reasoning_AI1 return {player.id_in_group: output} else: pass form_model = 'player' form_fields = ['price', 'keystroke_data', 'keystroke_price_data', 'chatLog', 'receive'] class Price_and_Explanation_R2(Page): @staticmethod def app_after_this_page(player, timeout_happened): if timeout_happened: return None # Stay on the same page if time runs out @staticmethod def is_displayed(player: Player): return (player.round_number == 5) @staticmethod def live_method(player: Player, data): # set chatgpt api key openai.api_key = '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' # load msg messages = json.loads(player.msg2) # functions for retrieving text from openAI if 'text' in data: # grab text that participant inputs and format for chatgpt text = data['text'] inputMsg = {'role': 'user', 'content': text} botMsg = {'role': 'assistant', 'content': text} # append messages and run chat gpt function messages.append(inputMsg) output = runGPT(messages) # also append messages with bot message botMsg = {'role': 'assistant', 'content': output} messages.append(botMsg) numbers = re.findall(r'\d+', output) score2 = int(numbers[-1]) if numbers else 0 player.explanation_score2=score2 player.participant.vars['score2'] = score2 reasoning_AI2 = str(output.strip().split()) player.reasoning2 = reasoning_AI2 return {player.id_in_group: output} else: pass form_model = 'player' form_fields = ['price', 'keystroke_data', 'keystroke_price_data', 'chatLog', 'receive'] class Price_and_Explanation_R3(Page): @staticmethod def app_after_this_page(player, timeout_happened): if timeout_happened: return None # Stay on the same page if time runs out @staticmethod def is_displayed(player: Player): return (player.round_number == 6) @staticmethod def live_method(player: Player, data): # set chatgpt api key openai.api_key = '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' # load msg messages = json.loads(player.msg3) # functions for retrieving text from openAI if 'text' in data: # grab text that participant inputs and format for chatgpt text = data['text'] inputMsg = {'role': 'user', 'content': text} botMsg = {'role': 'assistant', 'content': text} # append messages and run chat gpt function messages.append(inputMsg) output = runGPT(messages) # also append messages with bot message botMsg = {'role': 'assistant', 'content': output} messages.append(botMsg) numbers = re.findall(r'\d+', output) score3 = int(numbers[-1]) if numbers else 0 player.explanation_score3=score3 player.participant.vars['score3'] = score3 reasoning_AI3 = str(output.strip().split()) player.reasoning3 = reasoning_AI3 return {player.id_in_group: output} else: pass form_model = 'player' form_fields = ['price', 'keystroke_data', 'keystroke_price_data', 'chatLog', 'receive'] class Price_and_Explanation_R4(Page): @staticmethod def app_after_this_page(player, timeout_happened): if timeout_happened: return None # Stay on the same page if time runs out @staticmethod def is_displayed(player: Player): return (player.round_number == 7) @staticmethod def live_method(player: Player, data): # set chatgpt api key openai.api_key = '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' # load msg messages = json.loads(player.msg4) # functions for retrieving text from openAI if 'text' in data: # grab text that participant inputs and format for chatgpt text = data['text'] inputMsg = {'role': 'user', 'content': text} botMsg = {'role': 'assistant', 'content': text} # append messages and run chat gpt function messages.append(inputMsg) output = runGPT(messages) # also append messages with bot message botMsg = {'role': 'assistant', 'content': output} messages.append(botMsg) numbers = re.findall(r'\d+', output) score4 = int(numbers[-1]) if numbers else 0 player.explanation_score4=score4 player.participant.vars['score4'] = score4 reasoning_AI4 = str(output.strip().split()) player.reasoning4 = reasoning_AI4 return {player.id_in_group: output} else: pass form_model = 'player' form_fields = ['price', 'keystroke_data', 'keystroke_price_data', 'chatLog', 'receive'] class Price_and_Explanation_R5(Page): @staticmethod def app_after_this_page(player, timeout_happened): if timeout_happened: return None # Stay on the same page if time runs out @staticmethod def is_displayed(player: Player): return (player.round_number == 10) @staticmethod def live_method(player: Player, data): # set chatgpt api key openai.api_key = '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' # load msg messages = json.loads(player.msg5) # functions for retrieving text from openAI if 'text' in data: # grab text that participant inputs and format for chatgpt text = data['text'] inputMsg = {'role': 'user', 'content': text} botMsg = {'role': 'assistant', 'content': text} # append messages and run chat gpt function messages.append(inputMsg) output = runGPT(messages) # also append messages with bot message botMsg = {'role': 'assistant', 'content': output} messages.append(botMsg) numbers = re.findall(r'\d+', output) score5 = int(numbers[-1]) if numbers else 0 player.explanation_score5=score5 player.participant.vars['score5'] = score5 reasoning_AI5 = str(output.strip().split()) player.reasoning5 = reasoning_AI5 return {player.id_in_group: output} else: pass form_model = 'player' form_fields = ['price', 'keystroke_data', 'keystroke_price_data', 'chatLog', 'receive'] class PriceSetting(Page): @staticmethod def is_displayed(player: Player): return player.round_number in [2, 3, 4, 8, 9] form_model = 'player' form_fields = ['price'] class ResultsWait(WaitPage): after_all_players_arrive='round_results' title_text = "Bitte warten Sie einen Moment." body_text = "Bitte warten Sie kurz bis alle Teilnehmenden eine Entscheidung getroffen haben. " \ "Es geht in Kürze weiter." class ResultsFeedback(Page): pass class ShockAnnouncement(Page): @staticmethod def is_displayed(player: Player): return (player.round_number == player.shock) class FinalResults(Page): @staticmethod def is_displayed(player: Player): return (player.round_number == 10) class Demographics(Page): @staticmethod def is_displayed(player: Player): return (player.round_number == 10) form_model = 'player' form_fields = ['Gender', 'Age', 'Faculty', 'Makro', 'tech_problems'] class FinalPage(Page): @staticmethod def is_displayed(player: Player): return (player.round_number == 10) page_sequence = [ Place, Start, Pre_Comprehension, Comprehension_OT, Comprehension_BC, StartWait, ShockAnnouncement, Price_and_Explanation_R1, Price_and_Explanation_R2, Price_and_Explanation_R3, Price_and_Explanation_R4, Price_and_Explanation_R5, PriceSetting, ResultsWait, ResultsFeedback, FinalResults, Demographics, FinalPage]