from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, ) import random import json author = 'Monika Leszczynska' doc = """ Checking 'd' and 'b' letters """ class Constants(BaseConstants): name_in_url = 'matrices_second' players_per_group = None task_timer = 120 num_rounds = 15 d_total = 20 b_total = 60 total_letters = 80 fixed_payoff = c(2.00) bonus_payoff = c(0.20) class Subsession(BaseSubsession): def creating_session(self): n = Constants.total_letters for p in self.get_players(): indices = list(range(1, n + 1)) d_list = ['d'] * Constants.d_total b_list = ['b'] * Constants.b_total letters_list = d_list + b_list random.shuffle(letters_list) form_fields = ['choice_' + str(k) for k in indices] zipped = list(zip(indices, form_fields, letters_list)) # Save the full set of choices into the player's field (as JSON string) p.letter_choices_data = json.dumps({ 'fields': form_fields, 'letters': letters_list, 'responses': [None] * n }) p.endgame = 0 class Group(BaseGroup): pass class Player(BasePlayer): # ----- existing fields ------------------------------------------------- letter_choices_data = models.LongStringField() consent = models.BooleanField(blank=True) submit_noConsent = models.BooleanField(blank=True, initial=False) gender = models.StringField() gender_others = models.StringField(blank=True) age = models.IntegerField(min=18, max=100) birth_month = models.CharField(max_length=20) task_timer = models.IntegerField(initial=Constants.task_timer) d_crossed = models.IntegerField(initial=0) b_crossed = models.IntegerField(initial=0) total_correct = models.IntegerField(initial=0) correct = models.IntegerField(initial=0) is_correct = models.BooleanField(initial=False) endgame = models.IntegerField(initial=0) # ----- NEW: 100 checkbox fields --------------------------------------- # They will be called choice_1, choice_2, …, choice_100 (or to _80 if you # keep Constants.total_letters = 80). Blank=True so unchecked boxes post # an empty string, which won’t fail validation. for i in range(1, Constants.total_letters + 1): locals()[f"choice_{i}"] = models.StringField(blank=True) del i # ---------------------------------------------------------------------- # ------------ helper methods (unchanged) ------------------------------ def count_effort(self): data = json.loads(self.letter_choices_data) responses = data.get('responses', []) self.d_crossed = responses.count('d') self.b_crossed = responses.count('b') def check_correctness(self): data = json.loads(self.letter_choices_data) responses = data.get('responses', []) self.correct = int( responses.count('d') == Constants.d_total and responses.count('b') == 0 ) self.is_correct = bool(self.correct) def update_endgame(self): self.endgame = 1 print("Endgame set to:", self.endgame) def consent_error_message(self, value): if value is None: return "Please check the box if you agree!"