from otree.api import * doc = """ This is a one-shot "Prisoner's Dilemma". Two players are asked separately whether they want to cooperate or defect. Their choices directly determine the payoffs. """ class C(BaseConstants): NAME_IN_URL = 'prisonerZ' PLAYERS_PER_GROUP = 2 NUM_ROUNDS = 15 PAYOFF_A = cu(18) PAYOFF_B = cu(12) PAYOFF_C = cu(6) PAYOFF_D = cu(0) RESPONSE_SCALE_1= [ (1, 'Überhaupt nicht'), (2, 'Ein bisschen'), (3, 'Weder ein bisschen noch viel'), (4, 'Viel'), (5, 'Völlig'), ] RESPONSE_SCALE_2 = [ (1, 'Stimme überhaupt nicht zu'), (2, 'Stimme nicht zu'), (3, 'Stimme eher nicht zu'), (4, 'Neutral'), (5, 'Stimme eher zu'), (6, 'Stimme völlig zu'), (7, 'Stimme zu'), ] POSITION_CHOICES = [ ("Professur W3, C4, o.ä.", "Professur W3, C4, o.ä."), ("Professur W2, C3, o.ä.", "Professur W2, C3, o.ä."), ("Professur C2, o.ä.", "Professur C2, o.ä."), ("Juniorprofessur", "Juniorprofessur"), ("Andere Hochschullehrposition", "Andere Hochschullehrposition"), ("Andere Wissenschaftlerposition EG14 TVL/TVöD und höher", "Andere Wissenschaftlerposition EG14 TVL/TVöD und höher"), ("Andere Wissenschaftlerposition EG13 TVL/TVöD und darunter", "Andere Wissenschaftlerposition EG13 TVL/TVöD und darunter"), ("Keine Angabe", "Keine Angabe"), ] DISCIPLINE_CHOICES = [ ("Pädagogik, Lehramt und Erziehungswissenschaften", "Pädagogik, Lehramt und Erziehungswissenschaften"), ("Geisteswissenschaften und Künste", "Geisteswissenschaften und Künste"), ("Sozialwissenschaften und Psychologie", "Sozialwissenschaften und Psychologie"), ("Wirtschaftswissenschaften", "Wirtschaftswissenschaften"), ("Rechtswissenschaften", "Rechtswissenschaften"), ("Lebenswissenschaften", "Lebenswissenschaften"), ("Physik und Mathematik", "Physik und Mathematik"), ("Chemie", "Chemie"), ("Informatik", "Informatik"), ("Ingenieurwesen", "Ingenieurwesen"), ("Agrarwissenschaft und Forstwissenschaft", "Agrarwissenschaft und Forstwissenschaft"), ("Medizin, Pharmazie und Gesundheitswesen", "Medizin, Pharmazie und Gesundheitswesen"), ("Soziale Arbeit und Sozialwesen", "Soziale Arbeit und Sozialwesen"), ("Andere (bitte angeben)", "Andere (bitte angeben)"), ] EMPLOYMENT_CHOICES = [ ("Vollzeit", "Vollzeit"), ("Teilzeit", "Teilzeit"), ] EMPLOYMENT_DURATION_CHOICES = [ ("Unbefristet beamtet", "Unbefristet beamtet"), ("Unbefristet angestellt", "Unbefristet angestellt"), ("Befristet mit Aussicht auf unbefristeten Vertrag", "Befristet mit Aussicht auf unbefristeten Vertrag"), ("Befristet ohne Aussicht auf unbefristeten Vertrag", "Befristet ohne Aussicht auf unbefristeten Vertrag"), ("Bezahlung nach Stunden, Werkvertrag, o.ä.", "Bezahlung nach Stunden, Werkvertrag, o.ä."), ("Andere (bitte angeben)", "Andere (bitte angeben)"), ] TRAUM = [ ("Ja", "Ja"), ("Nein", "Nein"), ("Zum Teil", "Zum Teil"), ] #randomizes particpants in the first round and #keeps the matching constant over all following rounds: class Subsession(BaseSubsession): pass #def creating_session(self): # import random #if self.round_number == 1: # self.group_randomly(fixed_id_in_group=True) # print(self.get_group_matrix()) #else: # self.group_like_round(1) #def creating_session(self): #if self.round_number == 1: #self.group_randomly() #else: # Explicitly set groups to match previous round #for player in self.get_players(): # player.group = player.in_round(self.round_number - 1).group # Alternatively, you can use: player.group_like_round(self.round_number - 1) #def creating_session(self): #self.group_randomly() #if self.round_number == 1: #self.group_randomly() #else: #self.group_like_round(1) class Group(BaseGroup): #second_chat = models.IntegerField() group_color = models.StringField() #treatment = models.BooleanField() class Player(BasePlayer): #secondchat = models.IntegerField() #group_color = models.StringField() def make_q(label): return models.IntegerField(label=label, choices=[1, 2, 3, 4, 5], widget=widgets.RadioSelect) def make_c(label): return models.IntegerField(label=label, choices=[1, 2, 3, 4, 5, 6, 7], widget=widgets.RadioSelect) q1 = make_q('Ich bin eher zurückhaltend, reserviert.') q2 = make_q('Ich schenke anderen leicht Vertrauen, glaube an das Gute im Menschen.') q3 = make_q('Ich bin bequem, neige zur Faulheit.') q4 = make_q('Ich bin entspannt, lasse mich durch Stress nicht aus der Ruhe bringen.') q5 = make_q('Ich habe nur wenig künstlerisches Interesse.') q6 = make_q('Ich gehe aus mir heraus, bin gesellig.') q7 = make_q('Ich neige dazu, andere zu kritisieren.') q8 = make_q('Ich erledige Aufgaben gründlich.') q9 = make_q('Ich werde leicht nervös und unsicher') q10 = make_q('Ich habe eine aktive Vorstellungskraft, bin fantasievoll.') c15 = make_c('Zusammenarbeit ist für jede Organisation, die Wachstum, Innovation und Produktivität erreichen möchte, von entscheidender Bedeutung') c16 = make_c('Ich bin „gut“ darin, Konflikte oder Meinungsverschiedenheiten mit Kolleginnen und Kollegen oder Teammitgliedern zu lösen') c17 = make_c('In meiner aktuellen Position ist es oft erforderlich, dass ich mit anderen zusammenarbeite.') c18 = make_c('Wenn es Begriffe gibt, die ich nicht verstehe, mache ich mir normalerweise nicht die Mühe zu fragen, was sie bedeuten') c19 = make_c('Ich verhandle mit anderen, wenn ich denke, dass es nötig ist') c20 = make_c('Oft erkunde ich keine alternativen Lösungen') c21 = make_c('Ich übernehme die Verantwortung, wenn Entscheidungen getroffen werden müssen') c22 = make_c('Es macht mir Spaß, mich an Entscheidungen zu beteiligen') c23 = make_c('Wenn widersprüchliche Ansichten (im Team) existieren, vertrete ich meinen Standpunkt oft nicht') c24 = make_c('Ich frage nicht nach alternativen Lösungen') c25 = make_c('Ich neige dazu, keine Vorschläge für Handlungs- oder Entscheidungsoptionen zu unterbreiten, wenn man mich nicht gezielt dazu auffordert') c26 = make_c('Meistens gehöre ich zu den Personen im Team, die Vorschläge machen/unterbreiten. Ich übernehme eine aktive Rolle im Team, anstatt darauf zu warten, dass andere Vorschläge machen') c27 = make_c('Normalerweise spreche ich offen darüber, wie ich mich fühle') c28 = make_c('Wenn ich nicht alle Optionen verstehe, schweige ich') c29 = make_c('Ich schaue anderen in die Augen, wenn ich anderer Meinung bin') gender_b = models.StringField(label="Bitte wählen Sie Ihr Geschlecht aus:", choices=["Männlich", "Weiblich", "Divers"]) birthd_b = models.IntegerField(label="Bitte tragen Sie Ihr Geburtsjahr ein:") email_b = models.StringField(label="Bitte tragen Sie Ihre E-Mail-Adresse ein*") state_b = models.StringField(label="In welchem Bundesland arbeiten Sie?") traum_role = models.StringField(label="Bitte geben Sie an, welche Rolle/Position Sie im T!Raum-Projekt innehaben") from otree.api import ( models, widgets ) hprofed_b = models.StringField( label="Welchen höchsten beruflichen Ausbildungs- oder (Fach-)Hochschulabschluss haben Sie?", choices=[ 'Noch in beruflicher Ausbildung (Berufsvorbereitungsjahr, Auszubildende/-r, Praktikant/-in, Student/-in)', 'Schüler/-in und besuche eine berufsorientierte Aufbau-, Fachschule o. ä.', 'Keinen beruflichen Abschluss und bin nicht in beruflicher Ausbildung', 'Beruflich-betriebliche Berufsausbildung (Lehre) abgeschlossen', 'Beruflich-schulische Ausbildung (Berufsfachschule, Handelsschule, Vorbereitungsdienst für den mittleren Dienst in der öffentlichen Verwaltung) abgeschlossen', 'Ausbildung an einer Fachschule der DDR abgeschlossen Ausbildung an einer Fach-, Meister-, Technikerschule, Berufs- oder Fachakademie abgeschlossen', 'Bachelor an (Fach-)Hochschule abgeschlossen', 'Fachhochschulabschluss (z. B. Diplom, Master)', 'Universitätsabschluss (z. B. Diplom, Magister, Staatsexamen, Master)', 'Promotion' ], widget=widgets.RadioSelect ) other_hprofed_b = models.StringField( label="Ein anderer beruflicher Abschluss, und zwar", blank=True ) salc_b = models.StringField( label="Was ist Ihre heutige Position bzw. Gehaltskategorie?", choices=C.POSITION_CHOICES, widget=widgets.RadioSelect, blank=True ) salc_b_other_position = models.StringField( label="Andere (bitte angeben):", blank=True ) arear_b = models.StringField( label="Bitte nennen Sie Ihre Disziplin bzw. Fachrichtungsgruppe, der Sie Ihre wissenschaftliche Tätigkeit zurechnen. (Bitte nur eine Angabe)", choices=C.DISCIPLINE_CHOICES, widget=widgets.RadioSelect, ) other_arear_b = models.StringField( label="", blank=True ) Traum_b = models.StringField( label="Verfügen Sie im Rahmen der T!Raum-Inititative über einen Arbeitsvertrag?", choices= C.TRAUM, widget=widgets.RadioSelect ) scopee_b = models.StringField( label="In Welchem Umfang sind Sie derzeitig in Ihrer T!Raum-Inititative beschäftigt?", choices=C.EMPLOYMENT_CHOICES, widget=widgets.RadioSelect, blank=True ) part_time_description = models.StringField( label="Bitte geben Sie Ihren genauen Teilzeitumfang an:", blank=True ) other_employment = models.StringField( label="Andere: Bitte geben Sie Ihre genaue Beschäftigung an:", blank=True ) duratione_b = models.StringField( label="Welche Beschäftigungsdauer ist bei Ihrem Beschäftigungsvertrag vorgesehen? (Bitte nur eine Angabe)", choices=C.EMPLOYMENT_DURATION_CHOICES, widget=widgets.RadioSelect, ) other_duratione_b = models.StringField( label="", blank=True ) consent = models.BooleanField( label='Ich habe die Informationen nach Art. 13 DSGVO anlässlich der Datenerhebung bei der Teilnahme und Durchführung des Lab-in-the-field Experiments im Rahmen der T!Raum Begleitforschung des International Center for Higher Education Research (INCHER) der Universität Kassel gelesen und ich willige in die Teilnahme am Forschungsprojekt und die damit verbundene Datenverarbeitung ein. Sofern ich besondere Kategorien von personenbezogenen Daten angebe bzw. angegeben habe, sind diese von der Einwilligungserklärung umfasst. Mir ist bewusst, dass die Einwilligung/en freiwillig ist/sind und ohne Nachteile (auch einzeln) verweigert oder jederzeit auch ohne Angaben von Gründen widerrufen werden können. Ich weiß, dass im Falle eines Widerrufs die Rechtmäßigkeit der aufgrund der Einwilligung bis zum Widerruf erfolgten Verarbeitung nicht berührt wird. Ich habe verstanden, dass ich mich für einen Widerruf einfach an Herrn Prof. Dr. Guido Bünstorf, E-Mail: buenstorf@uni-kassel.de, Telefon +49 561 804 2961, wenden kann und dass aus der Verweigerung der Einwilligung oder ihrem Widerruf keine Nachteile entstehen', widget=widgets.CheckboxInput, ) essay_b = models.LongStringField( label="", blank=True ) essay_c = models.StringField( label="", blank=True ) quiz1 = models.IntegerField(label="Füllen Sie die Lücke aus: Wenn Sie und die andere Person beide A wählen, erhalten Sie beide", choices = [0, 12, 6, 18], ) quiz2 = models.IntegerField(label="Füllen Sie die Lücke aus: Wenn Sie B wählen und die andere Person A wählt, erhalten Sie 18 und die andere Person erhält", choices = [0,12,6,18], ) quiz3 = models.StringField( label="Ihr Gegenüber im Spiel ist über alle Runden", choices = ['identisch', 'unterschiedlich'], ) cooperate = models.BooleanField( choices=[[True, 'A'], [False, 'B']], doc="""This player's decision""", widget=widgets.RadioSelect, ) # FUNCTIONS #def creating_session(subsession): #import random #if subsession.round_number == 1: #subsession.group_randomly(fixed_id_in_group=True) #else: # subsession.group_like_round(1) #print("Initial Group Matrix:") # print(group_matrix) def set_payoffs(group: Group): for p in group.get_players(): set_payoff(p) def other_player(player: Player): return player.get_others_in_group()[0] def set_payoff(player: Player): payoff_matrix = { (False, True): C.PAYOFF_A, (True, True): C.PAYOFF_B, (False, False): C.PAYOFF_C, (True, False): C.PAYOFF_D, } other = other_player(player) player.payoff = payoff_matrix[(player.cooperate, other.cooperate)] #Subsessions def creating_session(self): if self.round_number == 1: import random # Initial random group assignment self.group_randomly(fixed_id_in_group=True) group_matrix = self.get_group_matrix() print("Initial Group Matrix:") print(group_matrix) # Color assignment # Create a dictionary to store the mapping of group IDs to colors group_color_mapping = {} # Create a counter to keep track of the number of groups assigned to each color color_counter = {'blue': 0, 'red': 0} for group in self.get_groups(): # Determine the color for the group based on the counter group_color = 'blue' if color_counter['blue'] <= color_counter['red'] else 'red' color_counter[group_color] += 1 # Store the color in the mapping group_color_mapping[group.id_in_subsession] = group_color for player in group.get_players(): player.participant.vars['group_color'] = group_color # Store the initial group matrix and mapping in session.vars self.session.vars['initial_group_matrix'] = group_matrix self.session.vars['group_color_mapping'] = group_color_mapping else: # If it's not the first round, retrieve the initial group matrix and mapping from session.vars initial_group_matrix = self.session.vars.get('initial_group_matrix', []) group_color_mapping = self.session.vars.get('group_color_mapping', {}) # Apply the initial group matrix self.set_group_matrix(initial_group_matrix) # Display group colors print("Group Colors:") for group_id, color in group_color_mapping.items(): print(f"Group {group_id}: {color}") # Assign colors based on the stored mapping for group in self.get_groups(): group_id = group.id_in_subsession group_color = group_color_mapping.get(group_id, 'blue') for player in group.get_players(): player.participant.vars['group_color'] = group_color #def creating_session(subsession): #import random #if subsession.round_number == 1: #subsession.group_randomly(fixed_id_in_group=True) #print(subsession.get_group_matrix()) #else: #subsession.group_like_round(1) #import itertools #import random #if subsession.round_number == 1: #subsession.group_randomly(fixed_id_in_group=True) #print(subsession.get_group_matrix()) #else: #subsession.group_like_round(1) #if subsession.round_number == 1: #for group in subsession.get_groups(): # participant = group.participant #participant.secondchat = random.choice([True, False]) #if subsession.round_number == 1: #treatments = itertools.cycle([1, 2, 3]) #for player in subsession.get_players(): # player.participant.secondchat = next(treatments) # Original logic for round 1 #subsession.group_randomly(fixed_id_in_group=True) # import random #if subsession.round_number == 1: #subsession.group_randomly(fixed_id_in_group=True) #print(subsession.get_group_matrix()) #else: #subsession.group_like_round(1) # print(subsession.get_group_matrix()) # treatment = itertools.cycle([1, 2]) # for group in subsession.get_groups(): #group.second_chat = next(treatment) #for player in subsession.get_player(): #player.secondchat = next(treatment) #neuer #neu #def creating_session(self): # import itertools #import random #if self.round_number == 1: #for group in self.get_groups(): # Assign a color to each participant in the group #for player in group.get_players(): # player.participant.vars['group_color'] = random.choice(['blue', 'red']) # PAGES class Introduction(Page): timeout_seconds = 180 def is_displayed(player: Player): return player.round_number == 1 class Consent(Page): form_model = 'player' form_fields = ['consent'] def is_displayed(player: Player): return player.round_number == 1 class Survey1(Page): form_model = 'player' form_fields = ['gender_b', 'email_b','state_b', 'traum_role','hprofed_b','other_hprofed_b', 'salc_b', 'salc_b_other_position','arear_b','other_arear_b','Traum_b','scopee_b','part_time_description','other_employment', 'duratione_b','other_duratione_b'] def is_displayed(self): return self.round_number == 1 class Survey2(Page): form_model = 'player' form_fields = ['q1', 'q2', 'q3', 'q4', 'q5', 'q6', 'q7', 'q8', 'q9', 'q10'] def is_displayed(player: Player): return player.round_number == 1 class Survey3(Page): form_model = 'player' form_fields = ['c15', 'c16', 'c17', 'c18', 'c19', 'c20', 'c21', 'c22', 'c23', 'c24', 'c25', 'c26', 'c27', 'c28', 'c29'] def is_displayed(player: Player): return player.round_number == 1 class Info(Page): timeout_seconds = 50 def is_displayed(player: Player): return player.round_number == 1 class Instruction(Page): timeout_seconds = 360 def is_displayed(player: Player): return player.round_number == 1 class Testfragen(Page): form_model = 'player' form_fields = ['quiz1', 'quiz2', 'quiz3'] def is_displayed(player: Player): return player.round_number == 1 @staticmethod def error_message(player: Player, values): solutions = dict(quiz1=12, quiz2=0, quiz3='identisch') if values != solutions: return "Eine oder mehrere Antworten waren falsch, versuchen Sie es noch einmal." #class MatchingWaitPage(WaitPage): #def is_displayed(player: Player): #return player.round_number == 1 #def after_all_players_arrive(subsession: Subsession): #for group in self.subsession.get_groups(): #print(f"Round {self.round_number} - Group {group.id_in_subsession}: {[(p.id_in_group, p.group_id) for p in group.get_players()]}") # Execute creating_session after all players have arrived #subsession.creating_session() class Decision(Page): form_model = 'player' form_fields = ['cooperate'] class ResultsWaitPage(WaitPage): after_all_players_arrive = set_payoffs class Results(Page): @staticmethod def vars_for_template(player: Player): opponent = other_player(player) return dict( opponent=opponent, same_choice=player.cooperate == opponent.cooperate, my_decision=player.field_display('cooperate'), opponent_decision=opponent.field_display('cooperate'), ) #class GBATWaitPage(WaitPage): #import itertools #treatment = itertools.cycle([1, 2]) #for group in subsession.get_groups(): #group.second_chat = next(treatment) #@staticmethod #def after_all_players_arrive(group: Group): #import random #group.treatment = random.choice([True, False]) class Chat1_C_C(Page): timeout_seconds = 300 #def is_displayed(self): #return ( # self.round_number == 2 #and self.session.vars.get('group_color') == 'blue' #) #def vars_for_template(self): # Pass group_color to the template context #return {} #p1 = self.group.get_player_by_id(1) #color = p1.participant.vars['group_color'] def is_displayed(self): # Retrieve the participant's group color group_color_mapping = self.session.vars.get('group_color_mapping', {}) participant_group_color = group_color_mapping.get(self.group.id_in_subsession) # Check if round number is 2 and participant's group color is 'blue' return self.round_number == 5 and participant_group_color == 'blue' class Chat1_C_E(Page): timeout_seconds = 300 #def is_displayed(self): #return ( #self.round_number == 2 #and self.participant.vars.get('group_color') == 'red' #) #def vars_for_template(self): # Pass group_color to the template context #return {} def is_displayed(self): # Retrieve the participant's group color group_color_mapping = self.session.vars.get('group_color_mapping', {}) participant_group_color = group_color_mapping.get(self.group.id_in_subsession) # Check if round number is 2 and participant's group color is 'blue' return self.round_number == 5 and participant_group_color == 'red' class Chat2(Page): timeout_seconds = 300 #def is_displayed(self): #return ( # self.round_number == 3 #and self.participant.vars.get('group_color') == 'blue' #) def is_displayed(self): # Retrieve the participant's group color group_color_mapping = self.session.vars.get('group_color_mapping', {}) participant_group_color = group_color_mapping.get(self.group.id_in_subsession) # Check if round number is 2 and participant's group color is 'blue' return self.round_number == 10 and participant_group_color == 'blue' class Essay(Page): form_model = 'player' form_fields = ['essay_b'] timeout_seconds = 300 #def is_displayed(self): #return ( #self.round_number == 3 #and self.participant.vars.get('group_color') == 'red' # ) # def vars_for_template(self): # Pass group_color to the template context #return {} def is_displayed(self): # Retrieve the participant's group color group_color_mapping = self.session.vars.get('group_color_mapping', {}) participant_group_color = group_color_mapping.get(self.group.id_in_subsession) # Check if round number is 2 and participant's group color is 'blue' return self.round_number == 10 and participant_group_color == 'red' class End(Page): timeout_seconds = 60 def is_displayed(player: Player): return player.round_number == 15 page_sequence = [Introduction, Consent, Survey1, Survey2, Survey3, Info, Instruction, Testfragen, Decision, ResultsWaitPage, Results, Chat1_C_C, Chat1_C_E, Chat2, Essay, End] #Introduction, Consent, Survey1, Survey2, Survey3, Info, Instruction, Testfragen #Introduction, Consent, Survey1, Survey2, Survey3, Info, Instruction, Testfragen, #Introduction, Consent, Survey1, Survey2, Survey3, Info, Instruction, Testfragen,