from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) from django.db import models as django_models from otree.models import Participant from django.db.models.signals import post_save from django.dispatch import receiver from random import randint import time class Constants(BaseConstants): name_in_url = "karma" players_per_group = 28 PLAYERS_PER_GROUP = players_per_group NUM_MAIN_ROUNDS = 50 NUM_TEST_ROUNDS = 5 NUM_ROUNDS = NUM_MAIN_ROUNDS + NUM_TEST_ROUNDS num_rounds = NUM_ROUNDS NAME_IN_URL = 'karma' URGENCY_VALUES_1 = [1, 5] URGENCY_PROBABILITIES_1 = [0.5, 0.5] URGENCY_VALUES_2 = [1, 9] URGENCY_PROBABILITIES_2 = [0.75, 0.25] INITIAL_KARMA = 9 MAX_KARMA = 18 TIME_GROUPING = 10 * 60 TIME_INTRODUCTION = 4 * 60 TIME_INSTRUCTION = 3 * 60 TIME_TEST_ROUND = 20 TIME_TEST_RESULT = 20 TIME_TEST_END = 30 TIME_ROUND = 10 TIME_RESULT = 5 DROPOUT_COUNT = 6 TIME_DROPOUT = 1 TIME_DROPOUT_PAGE = 5 BASE_PAYMENT = 1.5 BONUS_PAYMENT_RANDOM = 1.0 BONUS_PAYMENT_AVERAGE = 10.0 BONUS_PAYMENT_MAX = 20.0 RANDOM_EFFICIENCY = 1.5 MAX_EFFICIENCY_1 = 2 MAX_EFFICIENCY_2 = 2.25 RANDOM_SCORE = 0.5 * RANDOM_EFFICIENCY * NUM_MAIN_ROUNDS AVERAGE_SCORE_1 = 0.9 * MAX_EFFICIENCY_1 * NUM_MAIN_ROUNDS AVERAGE_SCORE_2 = 0.9 * MAX_EFFICIENCY_2 * NUM_MAIN_ROUNDS class Subsession(BaseSubsession): counter = models.IntegerField(initial=1) def creating_session(self): self.counter = 1 players = self.get_players() if self.round_number == 1: for p in players: p.participant.vars['timeout_count'] = 0 p.participant.vars['is_dropout'] = False def group_by_arrival_time_method(self, waiting_players): if len(waiting_players) >= Constants.players_per_group: return waiting_players[:Constants.players_per_group] else: for p in waiting_players: p.participant.vars['connected'] = len(waiting_players) for p in waiting_players: if p.waiting_too_long(): # [p] means a single-player group. p.participant.vars['grouping_timeout'] = True return [p] class Group(BaseGroup): treatment_id = models.IntegerField() group_counter = models.IntegerField() total_payment = models.IntegerField() redistribution = models.FloatField() class Player(BasePlayer): karma_input = models.IntegerField( min=0, label="Please enter your bid:",initial=0, ) # karma_input = models.IntegerField( # label="Please choose how you want to proceed:", # choices=[ # [0, 'Gain'], # [1, 'Maintain'], # [4, 'Spend'], # ], # widget=widgets.RadioSelect # ) urgency = models.IntegerField() is_winner = models.BooleanField(initial=False) is_tied = models.BooleanField(initial=False) is_tied_win = models.BooleanField(initial=False) is_tied_lose = models.BooleanField(initial=False) partner_id = models.IntegerField() role_id = models.IntegerField() treatment_id = models.IntegerField() group_counter = models.IntegerField() group_redistribution = models.FloatField() dropout = models.BooleanField(initial=False) karma = models.FloatField() karma_int = models.IntegerField() k_pre_redist = models.FloatField() redistribution = models.FloatField() total_bonus = models.FloatField() # Grouping def waiting_too_long(self): return time.time() - self.participant.vars['wait_page_arrival'] > Constants.TIME_GROUPING