import random from otree.api import * class C(BaseConstants): NAME_IN_URL = 'combined_survey' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 REWARD_CORRECT_ANSWERS = cu(300) # Вопрос 1: GPT - средний взнос (ИСПРАВЛЕНО: "выше" вместо "ниже") question_text_gpt = 'Мы провели 1000 независимых игр «Общественное благо» с моделью GPT в соответствии с правилами выше. Как вы думаете, сколько в среднем (в долларах) она вносила в общий фонд?' correct_answer_gpt = 3 # Вопрос 2: Разброс между моделями question_text_variance = 'Укажите среднее отклонение среднего взноса среди ответов восьми моделей (в долларах), то есть, простыми словами, насколько в среднем взносы разных моделей в игре общественное благо отличаются друг от друга:' correct_answer_variance = 'B' # 16-30 долларов # Список моделей для отображения MODELS_LIST = "arcee_free, gpr_os, grok_4_1, llama_3, llama_3_2, gpt_2, deepseek_V3_2, L3_linarius" TOLERANCE = 2 # Допустимое отклонение для вопроса 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): player_id = models.StringField() # Какой вопрос был выбран компьютером (1 или 2) selected_question = models.IntegerField() # =================================================================== # ПРОВЕРКА ПОНИМАНИЯ ПРАВИЛ ИГРЫ # =================================================================== comprehension_q1 = models.StringField( choices=[ ['A', 'A) 50'], ['B', 'B) 75'], ['C', 'C) 100'], ['D', 'D) 150'], ], label='Если каждый из 10 игроков вкладывает по 50 из 100 долларов в общий фонд, каков будет выигрыш каждого?', widget=widgets.RadioSelect ) comprehension_q2 = models.StringField( choices=[ ['A', 'A) 50'], ['B', 'B) 100'], ['C', 'C) 180'], ['D', 'D) 280'], ], label='Каков будет ваш выигрыш, если вы вкладываете 0 в общий фонд, а все остальные 9 игроков вкладывают по 100 из 100 долларов?', widget=widgets.RadioSelect ) # =================================================================== # ДЕМОГРАФИЧЕСКИЕ ВОПРОСЫ # =================================================================== age = models.IntegerField( label='Укажите год своего рождения:', min=1920 ) gender = models.StringField( choices=[['female', 'Женщина'], ['male', 'Мужчина'], ['other', 'Другое']], label='Ваш пол:', widget=widgets.RadioSelect ) education = models.StringField( choices=[ ['Среднее', 'Среднее'], ['Высшее (бакалавриат)', 'Высшее (бакалавриат)'], ['Высшее (магистратура)', 'Высшее (магистратура)'], ['Высшее (аспирантура/PhD)', 'Высшее (аспирантура/PhD)'], ], label='Ваше образование:', widget=widgets.RadioSelect ) # НОВОЕ: Какой моделью ИИ пользуетесь ai_model_used = models.StringField( choices=[ ['ChatGPT', 'ChatGPT (OpenAI)'], ['Claude', 'Claude (Anthropic)'], ['Gemini', 'Gemini (Google)'], ['DeepSeek', 'DeepSeek'], ['Copilot', 'Copilot (Microsoft)'], ['None', 'Не пользуюсь ИИ'], ['Other', 'Другое'], ], label='Какой моделью ИИ вы пользуетесь чаще всего?', widget=widgets.RadioSelect ) ai_familiarity = models.IntegerField( label='Насколько вы знакомы с ИИ-инструментами, такими как ChatGPT, Claude, DeepSeek и другими аналогичными системами?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) general_trust = models.IntegerField( label='Как вы считаете, можно ли в целом доверять большинству людей?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) risk_attitude = models.IntegerField( label='Насколько вы в целом готовы идти на риск?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) life_satisfaction = models.IntegerField( label='Насколько вы в целом удовлетворены своей жизнью в настоящее время?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) # =================================================================== # ОТВЕТЫ НА ВОПРОСЫ ОБ ИИ # =================================================================== question1_gpt = models.IntegerField( label='Ваш ответ (в долларах):', min=0, max=100, ) # ИЗМЕНЕНО: Теперь выбор из диапазонов question2_variance = models.StringField( choices=[ ['A', '0-15 долларов (почти одинаковое поведение)'], ['B', '16-30 долларов (небольшие различия)'], ['C', '31-45 долларов (средние различия)'], ['D', '46-60 долларов (большие различия)'], ['E', '61-75 долларов (очень большие различия)'], ['F', '76-100 долларов (огромные различия)'], ], label='', widget=widgets.RadioSelect ) # Поля для отслеживания правильности is_correct = models.BooleanField(initial=False) # =================================================================== # ОПРОСНИК ОБ ВОСПРИЯТИИ ИИ # =================================================================== attn_1 = models.IntegerField( label='Чтобы подтвердить, что вы внимательно читаете вопросы, выберите число 7.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) het_1 = models.IntegerField( label='Различные модели ИИ могут давать систематически разные ответы на один и тот же вопрос.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) het_2 = models.IntegerField( label='Важно знать, какая именно модель ИИ используется, прежде чем решать, доверять ли её советам.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) het_3 = models.IntegerField( label='Если два ИИ обучены на разных типах данных, я ожидаю, что они будут по-разному вести себя в экономических играх.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) use_1 = models.IntegerField( label='Как часто вы используете ИИ-инструменты (например, ChatGPT или аналогичные) в повседневной жизни?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) use_2 = models.IntegerField( label='Насколько вы считаете себя компетентным(ой) в использовании ИИ-инструментов?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) use_3 = models.IntegerField( label='В целом, насколько полезными для вас были ИИ-инструменты, когда вы их использовали?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) def_1 = models.IntegerField( label='Насколько вы готовы изменить свое первоначальное решение после получения рекомендации от ИИ?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) def_2 = models.IntegerField( label='Если рекомендация ИИ противоречит вашей интуиции, насколько вероятно, что вы все равно последуете ей?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) def_3 = models.IntegerField( label='В задаче, требующей стратегического решения, насколько вероятно, что вы будете полагаться на рекомендации ИИ?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) ver_1 = models.IntegerField( label='Как часто вы проверяете ответы ИИ с помощью других источников?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) ver_2 = models.IntegerField( label='Если ответ ИИ звучит уверенно и правдоподобно, как часто вы пропускаете проверку, потому что он «звучит правильно»?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) ver_3 = models.IntegerField( label='Насколько вы в целом скептически относитесь к ответам, сгенерированным ИИ?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) acc_1 = models.IntegerField( label='Когда ИИ дает ответ, я, как правило, считаю его правильным.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) acc_2 = models.IntegerField( label='Рекомендации ИИ надежны в задачах, требующих стратегического мышления (а не только фактических знаний).', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) acc_3 = models.IntegerField( label='В целом я считаю рекомендации, сгенерированные ИИ, заслуживающими доверия.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) mm_1 = models.IntegerField( label='Я уверен(а) в своей способности предсказать, как ИИ будет вести себя в экономической игре.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) mm_2 = models.IntegerField( label='Если вы сыграете в одну и ту же игру один раз с человеком, а другой раз с ИИ, чье поведение вам будет легче предсказать?', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) mm_3 = models.IntegerField( label='По сравнению с типичным человеком, я ожидаю, что ИИ будет вести себя более рационально в экономических играх.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) mm_4 = models.IntegerField( label='По сравнению с типичным человеком, я ожидаю, что ИИ будет вести себя более справедливо в экономических играх.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) mm_5 = models.IntegerField( label='По сравнению с типичным человеком, я ожидаю, что ИИ будет вести себя более стратегически в экономических играх.', widget=widgets.RadioSelectHorizontal, choices=[[i, str(i)] for i in range(1, 11)] ) def creating_session(subsession): for player in subsession.get_players(): player.player_id = f'player_{player.id_in_group}' # Случайно выбираем вопрос 1 или 2 player.selected_question = random.choice([1, 2]) def check_answers_and_reward(player: Player): """Проверяем только выбранный вопрос""" if player.selected_question == 1: # Проверка вопроса 1 (GPT) answer = player.question1_gpt correct = C.correct_answer_gpt is_correct = abs(answer - correct) <= C.TOLERANCE answer_display = f"{answer} долларов" correct_display = f"{correct} долларов (±{C.TOLERANCE})" else: # Проверка вопроса 2 (дисперсия) answer = player.question2_variance correct = C.correct_answer_variance is_correct = (answer == correct) # Для отображения variance_choices = { 'A': '0-15 долларов', 'B': '16-30 долларов', 'C': '31-45 долларов', 'D': '46-60 долларов', 'E': '61-75 долларов', 'F': '76-100 долларов', } answer_display = variance_choices.get(answer, answer) correct_display = variance_choices.get(correct, correct) player.is_correct = is_correct if is_correct: player.payoff = C.REWARD_CORRECT_ANSWERS else: player.payoff = cu(0) # Сохраняем результат player.participant.vars['result_data'] = { 'selected_question': player.selected_question, 'answer': answer_display, 'correct_answer': correct_display, 'is_correct': is_correct, 'reward': player.payoff, } # ========================================================================= # PAGES # ========================================================================= class YourType(Page): form_model = 'player' form_fields = ['player_id'] @staticmethod def is_displayed(player): return player.round_number == 1 class IntroPage(Page): @staticmethod def is_displayed(player): return player.round_number == 1 class Survey(Page): form_model = 'player' form_fields = [ 'age', 'gender', 'education', 'ai_model_used', 'ai_familiarity', 'general_trust', 'risk_attitude', 'life_satisfaction', ] @staticmethod def is_displayed(player): return player.round_number == 1 class GameRulesPage(Page): form_model = 'player' form_fields = ['comprehension_q1', 'comprehension_q2'] @staticmethod def is_displayed(player): return player.round_number == 1 @staticmethod def error_message(player, values): if values['comprehension_q1'] != 'D': return 'Вопрос 1: Вопрос 1: Неверно. Подумайте еще раз: каждый игрок вносит 50 в общий фонд и оставляет себе 50. Всего в фонде 500, умножается на 2 = 1000, делится на 10 = по 100 каждому из фонда. Итого: 50 (осталось) + 100 (из фонда) = 150.' if values['comprehension_q2'] != 'D': return 'Вопрос 2: Неверно. Подумайте: 9 игроков × 100 = 900, умножается на 2 = 1800, делится на 10 = 180 каждому. Вы не вложили ничего, значит 100 + 180 = 280.' class Survey1(Page): form_model = 'player' form_fields = ['question1_gpt', 'question2_variance'] @staticmethod def is_displayed(player): return player.round_number == 1 @staticmethod def before_next_page(player, timeout_happened): check_answers_and_reward(player) class CorrectAnswersPage(Page): @staticmethod def is_displayed(player): return player.round_number == 1 @staticmethod def vars_for_template(player): data = player.participant.vars.get('result_data', {}) return dict( selected_question=player.selected_question, answer=data.get('answer', ''), correct_answer=data.get('correct_answer', ''), is_correct=data.get('is_correct', False), reward=data.get('reward', 0), question_text_1=C.question_text_gpt, question_text_2=C.question_text_variance, ) # НОВАЯ СТРАНИЦА: Информация о бонусе перед опросом class BonusInfoPage(Page): @staticmethod def is_displayed(player): return player.round_number == 1 class AISurveyPage1(Page): form_model = 'player' form_fields = [ 'attn_1', 'het_1', 'het_2', 'het_3', 'use_1', 'use_2', 'use_3', ] @staticmethod def is_displayed(player): return player.round_number == 1 @staticmethod def error_message(player, values): if values.get('attn_1') != 7: player.participant.vars['attn_1_failed'] = True return "Чтобы подтвердить, что вы внимательно читаете вопросы, пожалуйста, выберите число 7." else: player.participant.vars['attn_1_failed'] = False return None class AISurveyPage2(Page): form_model = 'player' form_fields = [ 'def_1', 'def_2', 'def_3', 'ver_1', 'ver_2', 'ver_3', ] @staticmethod def is_displayed(player): return player.round_number == 1 class AISurveyPage3(Page): form_model = 'player' form_fields = [ 'acc_1', 'acc_2', 'acc_3', 'mm_1', 'mm_2', 'mm_3', 'mm_4', 'mm_5', ] @staticmethod def is_displayed(player): return player.round_number == 1 class EndPage(Page): @staticmethod def is_displayed(player): return player.round_number == 1 @staticmethod def vars_for_template(player): attn_1_failed = player.participant.vars.get('attn_1_failed', False) return { 'attn_failed': attn_1_failed, 'attn_1_failed': attn_1_failed, } # ОБНОВЛЕННАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ СТРАНИЦ (добавлена BonusInfoPage) page_sequence = [ YourType, IntroPage, Survey, GameRulesPage, Survey1, BonusInfoPage, # ← СНАЧАЛА бонус инфо AISurveyPage1, # ← ПОТОМ опрос AISurveyPage2, AISurveyPage3, CorrectAnswersPage, # ← ПОТОМ результаты EndPage, ]