from otree.api import ( models, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, widgets ) import time from settings import MY_DEFAULT_TIMER import random from random import randrange doc = '' class Constants(BaseConstants): name_in_url = 'dobble_practice' players_per_group = None num_rounds = 9 base_image_dimensions_mapping = { 4: 140, 6: 100, 8: 90 } cloud_images = 'https://storage.googleapis.com/sorting-game/icons/' class Group(BaseGroup): pass def creating_sequence(self, items_number): if self.round_number == 1: self.session.cards[items_number] = create_dobble_cards(items_number) random.shuffle(self.session.cards[items_number]) self.session.round_cards[items_number] = {} card_1 = self.session.cards[items_number][(self.round_number - 1) % len(self.session.cards[items_number])] card_2 = self.session.cards[items_number][self.round_number % len(self.session.cards[items_number])] # Only one item should exist correct_answer = list(set(card_1) & set(card_2))[0] random.shuffle(card_1) random.shuffle(card_2) base_image_dimension = Constants.base_image_dimensions_mapping[items_number] card_1 = list(map((lambda x: {"number": x, "rotation": randrange(360), "width": int(randrange(80, 120) * base_image_dimension / 100)}), card_1)) card_2 = list(map((lambda x: {"number": x, "rotation": randrange(360), "width": int(randrange(80, 120) * base_image_dimension / 100)}), card_2)) self.session.round_cards[items_number][self.round_number] = { "card_1": card_1, "card_2": card_2, "correct_answer": correct_answer } class Subsession(BaseSubsession): subsession_round_number = models.IntegerField() def creating_session(self): self.subsession_round_number = self.session.config['practice_rounds'] * 3 if self.round_number == 1: self.session.round_cards = {} self.session.cards = {} creating_sequence(self, self.session.config['card_items_number']) class Player(BasePlayer): def waiting_too_long(self): if not hasattr(self.participant, 'wait_page_arrival'): self.participant.wait_page_arrival = time.time() return time.time() - self.participant.wait_page_arrival > MY_DEFAULT_TIMER dobble_answer = models.IntegerField(initial=-1) correct_answer = models.BooleanField() round_score = models.IntegerField() answer_time = models.IntegerField() selection = models.StringField( choices=['Animal', 'Food', 'Summer'], widget=widgets.RadioSelect, label='Select the theme you want to play' ) timeout_happened = models.BooleanField(initial=False) error_answers_count = models.IntegerField(initial=0) correct_answers_count = models.IntegerField(initial=0) def calculate_answer(self, round_cards): self.correct_answer = self.dobble_answer == round_cards['correct_answer'] self.round_score = 0 if not self.correct_answer else self.answer_time if self.correct_answer: self.participant.correct_answers_count += 1 else: self.participant.error_answers_count += 1 self.correct_answers_count = self.participant.correct_answers_count self.error_answers_count = self.participant.error_answers_count def new_period(self): self.participant.correct_answers_count = 0 self.participant.error_answers_count = 0 # n-1 must be prime def create_dobble_cards(n): cards = [] # first card and first category for crd in range(0, n): symbols = [0] for sym in range(1, n): symbols.append(crd * (n-1) + sym) cards.append(symbols.copy()) # other categories for cat in range(1, n): for crd in range(0, n-1): symbols = [cat] for sym in range(1, n): symbols.append(1 + sym * (n-1) + ((cat-1) * (sym-1) + crd) % (n-1)) cards.append(symbols.copy()) return cards class DobbleCard: items = []