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' PLAYERS_PER_GROUP = 2 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() # 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=100) show_up_fee = models.CurrencyField(default=5) payoff_mon = models.CurrencyField() payoff_mon_final = models.CurrencyField() 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 Teams bestimmt und sind daher am Anfang jeder Runde unbekannt."], [2, "... sind zu Beginn jeder Runde bekannt."], [3, "... resultieren aus dem von meinem Team festgelegten Preis."]], label="Frage 5: Die Produktionskosten ...", widget=widgets.RadioSelect) Question_6 = models.IntegerField( choices=[[1, "An alle Teilnehmenden."], [2, "An mein Teammitglied."], [3, "An ein zufällig ausgewähltes anderes Team."]], label="Frage 6: An wen wird Ihr vorläufiger Preisvorschlag weitergeleitet?", widget=widgets.RadioSelect) Question_7 = models.IntegerField( choices=[[1, "Mein finaler Preisvorschlag ist der Preis für das Produkt."], [2, "Der Preis wird zufällig zwischen den vorläufigen Preisvorschlägen ausgewählt, die zwischen den Teammitgliedern ausgetauscht wurden."], [3, "Der Preis wird zufällig aus den finalen Preisvorschlägen ausgewählt, die beide Teammitglieder nach dem Austausch der vorläufigen Preisvorschläge abgegeben haben."]], label="Frage 7: Wie wird der Preis für Ihr Produkt in jeder Runde festgelegt?", 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) Q7_first_attempt = models.IntegerField(blank=True) #BC questions Question_1_BC = models.IntegerField( choices=[[1, ("Je näher der Teampreis p am Zielpreis z liegt, desto höher der Gewinn.")], [2, ("Je näher der Teampreis p am Zielpreis z liegt, desto niedriger der Gewinn.")], [3, ("Es gibt nur einen Gewinn, wenn der Teampreis 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 Teams 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, "An alle Teilnehmenden."], [2, "An mein Teammitglied."], [3, "An ein zufällig ausgewähltes anderes Team."]], label="Frage 5: An wen wird Ihr vorläufiger Preisvorschlag weitergeleitet?", widget=widgets.RadioSelect) Question_6_BC = models.IntegerField( choices=[[1, "Mein finaler Preisvorschlag ist der Preis für das Produkt."], [2, "Der Preis wird zufällig zwischen den vorläufigen Preisvorschlägen ausgewählt, die zwischen den Teammitgliedern ausgetauscht wurden."], [3, "Der Preis wird zufällig aus den finalen Preisvorschlägen ausgewählt, die beide Teammitglieder nach dem Austausch der vorläufigen Preisvorschläge abgegeben haben."]], label="Frage 6: Wie wird der Preis für das Produkt Ihres Teams in jeder Runde festgelegt?", 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) Q6_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) explanation_score2 = models.IntegerField(blank=True) explanation_score3 = models.IntegerField(blank=True) explanation_score4 = models.IntegerField(blank=True) explanation_score5 = models.IntegerField(blank=True) 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([True, False, 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 = """Sie sind der Gutachter für die Erklärungen der Teilnehmenden an einem Preisspiel. Bewerten Sie anhand der folgenden Punkte: Zentrale Bewertungsaspekte: - Wurden die Preise der anderen Teilnehmenden erwähnt? Wenn ja, geben Sie 1 Punkt. - Wurde das Reagieren auf die Preise der anderen Teilnehmer erwähnt? Wenn ja, geben Sie 1 Punkt. - Haben sie die Nachfrage nach ihrer Ware erwähnt? Wenn ja, geben Sie 1 Punkt. Erläutern Sie zunächst kurz Ihre Bewertung zu den drei Punkten. Geben Sie dann am Ende der Antwort auf einer neuen Zeile ausschließlich die Gesamtpunktzahl als ganze Zahl (0-3) an, ohne weitere Erläuterung oder Text. Wenn die Eingabe nur eine sinnlose Aneinanderreihung von Buchstaben ist, schreiben Sie 0. Explanation: """ 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 = """Bitte geben Sie die gegenteilige Erklärung zu derjenigen ab, die Sie vom Teilnehmenden erhalten haben. Danach druck "4". Explanation: """ p.msg2 = json.dumps([{"role": "system", "content": p.prompt2}]) p.prompt3 = """Jetzt hat ein Schock für die Gewinnfunktion der Teilnehmenden stattgefunden. Falls die Teilnehmenden diesen erwähnt haben, gib einen Punkt. - Erläutern Sie zunächst, wie Sie zu den einzelnen Punkten gekommen sind, und geben Sie dann eine einzelne ganze Zahl (0-3) an, die die Gesamtpunktzahl darstellt. Falls Sie nur eine sinnlose Aneinanderreihung von Buchstaben erhalten, geben Sie 0. Explanation: """ p.msg3 = json.dumps([{"role": "system", "content": p.prompt3}]) p.prompt4 = """Hier sollten die Teilnehmenden nun erkennen, dass es sich um einen aggregierten Schock handelt, also alle gleichermaßen betroffen sind. Falls der Schock beschrieben wurde, gib 1 Punkt. Falls nicht, gib 0 Punkte. Erläutern Sie zunächst, wie Sie zu den einzelnen Punkten gekommen sind, und geben Sie dann eine einzelne ganze Zahl (0-1) an, die die Gesamtpunktzahl darstellt. Falls Sie nur eine sinnlose Aneinanderreihung von Buchstaben erhalten, geben Sie 0. Explanation: """ p.msg4 = json.dumps([{"role": "system", "content": p.prompt4}]) p.prompt5 = """Stimme der Antwort der Teilnehmenden einfach nur zu. Danach druck "10" Explanation: """ p.msg5 = json.dumps([{"role": "system", "content": p.prompt5}]) def runGPT(inputMessage): completion = openai.ChatCompletion.create( model=C.MODEL, messages=inputMessage, temperature=C.TEMP ) return completion["choices"][0]["message"]["content"] def average_price(group): group.average_price = 0 for player in group.get_players(): group.average_price += player.price group.average_price /= C.PLAYERS_PER_GROUP def explanation(player): return player.explanation # calculating the earnings def round_results(group): players = group.get_players() for p in players: if p.price < 10: p.price = 10 players = group.get_players() group.average_price = 0 for player in group.get_players(): group.average_price += player.price group.average_price /= C.PLAYERS_PER_GROUP group.average_price = int(Decimal(group.average_price).to_integral_value(rounding=ROUND_HALF_UP)) for p in players: p.output = (p.omega_current - p.price) p.revenue = p.output * p.price p.unit_costs = group.average_price - p.cost_deduction p.total_costs = p.unit_costs * p.output p.earnings = (p.price - p.unit_costs) * p.output p.per_piece_earnings = p.price - p.unit_costs # if in BC p.price_aim = round((p.omega_current + group.average_price - p.cost_deduction) / 2) for p in players: if p.output < 0: p.output =0 if p.earnings < 0: p.earnings = 0 players = group.get_players() for p in players: p.payoff_round = p.earnings if group.round_number>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 = 200 p.bonus_mon = cu(p.bonus).to_real_world_currency(p.session) / p.exchange_rate p.payoff_mon = math.ceil(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 = cu( 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.payoff_mon_final = p.payoff_mon + p.bonus_mon + p.show_up_fee + p.explanation_bonus p.payoff_mon_final_otree = 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 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', 'Question_7', 'attempts', 'Q1_first_attempt', 'Q2_first_attempt', 'Q3_first_attempt', 'Q4_first_attempt', 'Q5_first_attempt', 'Q6_first_attempt', 'Q7_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','Question_6_BC', 'attempts', 'Q1_BC_first_attempt', 'Q2_BC_first_attempt', 'Q3_BC_first_attempt', 'Q4_BC_first_attempt', 'Q5_BC_first_attempt','Q6_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 = [ 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]