class Group(BaseGroup): two_third_guesses = models.FloatField() best_guess = models.FloatField() tie = models.BooleanField(initial=False) def set_payoffs(self): players = self.get_players() self.two_third_guesses = ((2 / 3) * sum(p.guess_value for p in players) / len(players)) candidates = [] smallest_difference_so_far = Constants.guess_max + 1 # initialize to largest possible difference tie = False for p in self.get_players(): p.payoff = 0 p.is_winner = False # initialize to false difference = abs(p.guess_value - self.two_third_guesses) if difference < smallest_difference_so_far: tie = False candidates = [p] smallest_difference_so_far = difference elif difference == smallest_difference_so_far: tie = True candidates.append(p) self.tie = tie winners = candidates winners_cnt = len(winners) for p in winners: p.is_winner = True p.payoff = (Constants.winner_payoff / winners_cnt if tie else Constants.winner_payoff) self.best_guess = winners[0].guess_value
class Subsession(otree.models.BaseSubsession): name_in_url = 'exp1' min_value = models.FloatField( default=None, choices=CHOICES, doc="minimum of all decisions") def minimum(self): self.min_value = min([p.decision for p in self.get_players()]) def set_payoffs(self): print 'self.min_value', self.min_value for p in self.get_players(): print 'p.decision', p.decision assert p.decision is not None assert self.min_value is not None p.payoff = self.a + self.b * self.min_value - self.c * p.decision a = models.FloatField(default=200.0,doc="a+b*(minimum of all)-c*(own choice)") b = models.FloatField(default=400.0,doc="a+b*(minimum of all)-c*(own choice)") c = models.FloatField(default=200.0,doc="a+b*(minimum of all)-c*(own choice)")
class Player(BasePlayer): # form showing whether a player approves government's reforms approval_choices = ((1, "Одобряю"),(0, "Не одобряю")) approval = models.FloatField(widget=widgets.RadioSelect, choices=approval_choices) approval_final = models.FloatField(widget=widgets.RadioSelect, choices=approval_choices) # form showing how much a player is spending on trying to overthrow the system vote_to_overthrow = models.FloatField(widget=widgets.SliderInput(attrs={'step': '1'}), min=0, max=Constants.max_overthrow_vote_for_player, default=3) # form showing how much reforms a player desires after the overthrow reforms_votes = models.FloatField(widget=widgets.SliderInput(attrs={'step': '1'}), min=0, max=Constants.max_reforms, default=3)
class Treatment(otree.models.BaseTreatment): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> a = models.FloatField(default=200.0, doc="a+b*(minimum of all)-c*(own choice)") b = models.FloatField(default=400.0, doc="a+b*(minimum of all)-c*(own choice)") c = models.FloatField(default=200.0, doc="a+b*(minimum of all)-c*(own choice)")
class Group(otree.models.BaseGroup): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> players_per_group = 5 two_third_guesses = models.FloatField() def set_payoffs(self): self.two_third_guesses = (2 / 3) * sum( [p.guess_value for p in self.get_players()]) / len(self.get_players()) winner_so_far = None smallest_difference_so_far = 1000 # arbitrary big number for p in self.get_players(): difference = abs(p.guess_value - self.two_third_guesses) if difference < smallest_difference_so_far: winner_so_far = p smallest_difference_so_far = difference winner_so_far.is_winner = True for p in self.get_players(): if p.is_winner: p.payoff = Constants.winner_payoff else: p.payoff = 0
class Group(otree.models.BaseGroup): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> total_return = models.CurrencyField( doc="""Total return from agent's effort = [Return for single unit of agent's work effort] * [Agent's work effort]""") agent_fixed_pay = models.CurrencyField( doc="""Amount offered as fixed pay to agent""", min=Constants.min_fixed_payment, max=Constants.max_fixed_payment, verbose_name='Fixed Payment (from %i to %i)' % (Constants.min_fixed_payment, Constants.max_fixed_payment)) agent_return_share = models.FloatField( choices=Constants.agent_return_share_choices, doc="""Agent's share of total return""", verbose_name='Return Share', widget=widgets.RadioSelectHorizontal()) agent_work_effort = models.PositiveIntegerField( choices=range(1, 10 + 1), doc="""Agent's work effort, [1, 10]""", widget=widgets.RadioSelectHorizontal(), ) agent_work_cost = models.CurrencyField( doc="""Agent's cost of work effort""") contract_accepted = models.BooleanField( doc="""Whether agent accepts proposal""", widget=widgets.RadioSelect(), choices=( (True, 'Accept'), (False, 'Reject'), )) def set_payoffs(self): principal = self.get_player_by_role('principal') agent = self.get_player_by_role('agent') if not self.contract_accepted: principal.payoff = Constants.reject_principal_pay agent.payoff = Constants.reject_agent_pay else: self.agent_work_cost = cost_from_effort(self.agent_work_effort) self.total_return = return_from_effort(self.agent_work_effort) money_to_agent = self.agent_return_share * \ self.total_return + self.agent_fixed_pay agent.payoff = money_to_agent - self.agent_work_cost principal.payoff = self.total_return - money_to_agent principal.payoff += Constants.bonus agent.payoff += Constants.bonus def return_share_as_percentage(self): return utils.float_as_percentage(self.agent_return_share)
class FormFieldModel(otree.models.BaseGroup): null_boolean = models.BooleanField() big_integer = models.BigIntegerField() boolean = models.BooleanField(default=False) char = models.CharField() comma_separated_integer = models.CommaSeparatedIntegerField(max_length=100) date = models.DateField() date_time = models.DateTimeField() alt_date_time = models.DateTimeField( widget=otree.forms.SplitDateTimeWidget) decimal = models.DecimalField(max_digits=5, decimal_places=2) email = models.EmailField() file = models.FileField(upload_to='_tmp/uploads') file_path = models.FilePathField() float = models.FloatField() integer = models.IntegerField() generic_ip_address = models.GenericIPAddressField() positive_integer = models.PositiveIntegerField() positive_small_integer = models.PositiveSmallIntegerField() slug = models.SlugField() small_integer = models.SmallIntegerField() text = models.TextField() alt_text = models.TextField(widget=otree.forms.TextInput) time = models.TimeField() url = models.URLField() many_to_many = models.ManyToManyField('SimpleModel', related_name='+') one_to_one = models.OneToOneField('SimpleModel', related_name='+') currency = models.CurrencyField() currency_choice = models.CurrencyField(choices=[('0.01', '0.01'), ('1.20', '1.20')]) sent_amount = models.CurrencyField(choices=currency_range(0, 0.75, 0.05)) slider_widget = models.IntegerField(widget=widgets.SliderInput())
class Player(BasePlayer): def score_round(self): # update player payoffs if self.solution == self.user_total: self.is_correct = True self.payoff_score = 1 else: self.is_correct = False self.payoff_score = c(0) def set_task_score(self): op_scores = [] for op in self.get_others_in_group(): op_scores.append(int(op.participant.vars['task_2_score'])) self.participant.vars['task_2_op_scores'] = op_scores task_timer = models.PositiveIntegerField( doc="""The length of the real effort task timer.""") solution = models.PositiveIntegerField( doc="this round's correct summation") user_total = models.PositiveIntegerField( min=1, max=9999, doc="user's summation", widget=widgets.TextInput(attrs={'autocomplete': 'off'})) is_correct = models.BooleanField(doc="did the user get the task correct?") payoff_score = models.FloatField(doc='''score in this task''')
class Group(otree.models.BaseGroup): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> players_per_group = 2 total_return = models.MoneyField( doc="""Total return from agent's effort = [Return for single unit of agent's work effort] * [Agent's work effort]""" ) agent_fixed_pay = models.MoneyField( doc="""Amount offered as fixed pay to agent""" ) agent_return_share = models.FloatField( doc="""Agent's share of total return""", ) agent_work_effort = models.PositiveIntegerField( doc="""Agent's work effort, [1, 10]""", ) agent_work_cost = models.MoneyField( doc="""Agent's cost of work effort""" ) contract_accepted = models.NullBooleanField( doc="""Whether agent accepts proposal""", widget=widgets.RadioSelect(), ) # choices def agent_fixed_pay_choices(self): return money_range(-Constants.max_fixed_payment, Constants.max_fixed_payment, 0.50) def agent_work_effort_choices(self): return range(1, 10+1) def agent_return_share_choices(self): return Constants.agent_return_share_choices def set_payoffs(self): principal = self.get_player_by_role('principal') agent = self.get_player_by_role('agent') if not self.contract_accepted: principal.payoff = Constants.reject_principal_pay agent.payoff = Constants.reject_agent_pay else: self.agent_work_cost = cost_from_effort(self.agent_work_effort) self.total_return = return_from_effort(self.agent_work_effort) money_to_agent = self.agent_return_share*self.total_return + self.agent_fixed_pay agent.payoff = money_to_agent - self.agent_work_cost principal.payoff = self.total_return - money_to_agent
class Group(otree.models.BaseGroup): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> def set_payoffs(self): for p in self.get_players(): p.payoff = 50 in_all_groups_wait_page = models.FloatField(initial=0)
class Subsession(otree.models.BaseSubsession): name_in_url = 'exp3' endowment = models.MoneyField( default=20.00, doc="payoff = p(endowment-contribution)+a/N*sum(contribution)") a = models.FloatField( default=2.0, doc="payoff = p(endowment-contribution)+a/N*sum(contribution)")
class Subsession(otree.models.BaseSubsession): name_in_url = 'public_goods' endowment = models.PositiveIntegerField( default=100, doc="""Amount allocated to each player""") efficiency_factor = models.FloatField( default=1.8, doc="""The multiplication factor in group contribution""") question_correct = 92
class Player(otree.models.BasePlayer): # <built-in> group = models.ForeignKey(Group, null = True) subsession = models.ForeignKey(Subsession) # </built-in> decision = models.FloatField( default=None, choices=CHOICES, doc="degree to which capital requirement is accomodated", widget = widgets.RadioSelect() )
class Player(otree.models.BasePlayer): # <built-in> match = models.ForeignKey(Match, null=True) treatment = models.ForeignKey(Treatment, null=True) subsession = models.ForeignKey(Subsession) # </built-in> decision = models.FloatField( default=None, choices=[(1, '100 %'), (0.8, '80 %'), (0.6, '60 %'), (0.4, '40 %'), (0.2, '20 %'), (0, '0 %')], doc="degree to which capital requirement is accomodated")
class Treatment(otree.models.BaseTreatment): # <built-in> subsession = models.ForeignKey(Subsession) # </built-in> endowment = models.MoneyField( default=20.00, doc="payoff = p(endowment-contribution)+a/N*sum(contribution)") a = models.FloatField( default=2.0, doc="payoff = p(endowment-contribution)+a/N*sum(contribution)") def contribution_choices(self): return money_range(0, self.endowment, 1.00)
class Player(otree.models.BasePlayer): def other_player(self): """Returns other player in group. Only valid for 2-player groups.""" return self.get_others_in_group()[0] from_other_player = models.PositiveIntegerField() is_winner = models.BooleanField(initial=False) in_all_groups_wait_page = models.FloatField(initial=0) group_id_before_p1_switch = models.PositiveIntegerField() def role(self): # you can make this depend of self.id_in_group return ''
class Subsession(otree.models.BaseSubsession): name_in_url = 'exp1' min_value = models.FloatField(default=None, choices=[(1, '100 %'), (0.8, '80 %'), (0.6, '60 %'), (0.4, '40 %'), (0.2, '20 %'), (0, '0 %')], doc="minimum of all decisions") def minimum(self): self.min_value = min(p.decision for p in self.players) def set_payoffs(self): for p in self.players: p.payoff = p.treatment.a + p.treatment.b * p.subsession.min_value - p.treatment.c * p.decision
class Player(otree.models.BasePlayer): # <built-in> group = models.ForeignKey(Group, null=True) subsession = models.ForeignKey(Subsession) # </built-in> training_my_profit = models.CurrencyField( verbose_name='My profit would be') price = models.CurrencyField( min=0, max=Constants.maximum_price, doc="""Price player chooses to sell product for""") quality = models.CurrencyField( min=0, max=Constants.maximum_price, doc="""Price player chooses to produce with quality equal to""") share = models.FloatField(min=0, max=1)
class Player(otree.models.BasePlayer): # <built-in> group = models.ForeignKey(Group, null=True) subsession = models.ForeignKey(Subsession) # </built-in> fw = models.CurrencyField(min=0) bet = models.PositiveIntegerField(min=0, max=100, widget=widgets.SliderInput()) rt = models.FloatField() is_winner = models.BooleanField() def feedback_time(self): round_number = self.subsession.round_number if self.group.subgroup_type in (Constants.sg1, Constants.sg3): return True return round_number % 3 == 0 def decide_time(self): if self.group.subgroup_type in (Constants.sg3, Constants.sg2): return self.subsession.round_number in (1, 4, 7) return True def gadd_payoff(self, winner, pw): X = Constants.gadd_endowment alpha_t = self.bet / 100. rtp = (Constants.win_perc if winner else Constants.loose_perc) / 100. self.payoff = float(X * (alpha_t * rtp)) increment = X * (alpha_t * (1 + rtp) + (1 - alpha_t)) self.fw = pw + increment def gmul_payoff(self, winner, pw): alpha_t = self.bet / 100. rtp = (Constants.win_perc if winner else Constants.loose_perc) / 100. self.payoff = float(pw * alpha_t * rtp) self.fw = pw * (alpha_t * (1 + rtp) + (1 - alpha_t)) def set_payoff(self): # retrieve the last whealt fw = self.last_fw() # check if is winner self.is_winner = (random.randint(0, 99) <= Constants.win_chance) # payoff ccompute if self.group.group_type == Constants.gadd: self.gadd_payoff(self.is_winner, fw) else: self.gmul_payoff(self.is_winner, fw) def last_fw(self): previous = self.in_previous_rounds() first = not previous if first and self.group.group_type == Constants.gadd: return 0 elif first and self.group.group_type == Constants.gmul: return Constants.gmul_endowment return previous[-1].fw def current_wealth(self): if self.group.subgroup_type == Constants.sg1: cw = self.last_fw() else: round_idx = self.subsession.round_number - 1 if round_idx in (0, 3, 6): cw = self.last_fw() elif round_idx in (1, 2): players = self.in_previous_rounds() cw = players[0].last_fw() elif round_idx in (4, 5): players = self.in_previous_rounds() cw = players[3].last_fw() elif round_idx in (7, 8): players = self.in_previous_rounds() cw = players[6].last_fw() if self.group.group_type == Constants.gadd: cw += Constants.gadd_endowment return cw def previous_bet(self): if self.subsession.round_number == 1: return None return self.in_previous_rounds()[-1].bet
class Session(models.OTreeModel): class Meta: app_label = "otree" # if i don't set this, it could be in an unpredictable order ordering = ['pk'] _ft = FieldTrackerWithVarsSupport() vars: dict = models._PickleField(default=dict) config: dict = models._PickleField(default=dict, null=True) # label of this session instance label = models.CharField(max_length=300, null=True, blank=True, help_text='For internal record-keeping') code = models.CharField( default=random_chars_8, max_length=16, null=False, unique=True, doc="Randomly generated unique identifier for the session.", ) mturk_HITId = models.CharField( max_length=300, null=True, blank=True, help_text='Hit id for this session on MTurk', ) mturk_HITGroupId = models.CharField( max_length=300, null=True, blank=True, help_text='Hit id for this session on MTurk', ) is_mturk = models.BooleanField(default=False) def mturk_num_workers(self): assert self.is_mturk return int(self.num_participants / settings.MTURK_NUM_PARTICIPANTS_MULTIPLE) mturk_use_sandbox = models.BooleanField( default=True, help_text="Should this session be created in mturk sandbox?") # use Float instead of DateTime because DateTime # is a pain to work with (e.g. naive vs aware datetime objects) # and there is no need here for DateTime mturk_expiration = models.FloatField(null=True) mturk_qual_id = models.CharField(default='', max_length=50) archived = models.BooleanField( default=False, db_index=True, doc=("If set to True the session won't be visible on the " "main ViewList for sessions"), ) comment = models.TextField(blank=True) _anonymous_code = models.CharField(default=random_chars_10, max_length=10, null=False, db_index=True) is_demo = models.BooleanField(default=False) _admin_report_app_names = models.TextField(default='') _admin_report_num_rounds = models.CharField(default='', max_length=255) num_participants = models.PositiveIntegerField() def __unicode__(self): return self.code @property def participation_fee(self): '''This method is deprecated from public API, but still useful internally (like data export)''' return self.config['participation_fee'] @property def real_world_currency_per_point(self): '''This method is deprecated from public API, but still useful internally (like data export)''' return self.config['real_world_currency_per_point'] @property def use_browser_bots(self): return self.config.get('use_browser_bots', False) def mock_exogenous_data(self): ''' It's for any exogenous data: - participant labels (which are not passed in through REST API) - participant vars - session vars (if we enable that) ''' if self.config.get('mock_exogenous_data'): import shared_out as user_utils with otree.db.idmap.use_cache(): user_utils.mock_exogenous_data(self) otree.db.idmap.save_objects() # need to save self because it's not in the idmap cache self.save() def get_subsessions(self): lst = [] app_sequence = self.config['app_sequence'] for app in app_sequence: models_module = otree.common.get_models_module(app) subsessions = models_module.Subsession.objects.filter( session=self).order_by('round_number') lst.extend(list(subsessions)) return lst def get_participants(self): return list(self.participant_set.order_by('id_in_session')) def mturk_worker_url(self): # different HITs # get the same preview page, because they are lumped into the same # "hit group". This is not documented, but it seems HITs are lumped # if a certain subset of properties are the same: # https://forums.aws.amazon.com/message.jspa?messageID=597622#597622 # this seems like the correct design; the only case where this will # not work is if the HIT was deleted from the server, but in that case, # the HIT itself should be canceled. # 2018-06-04: # the format seems to have changed to this: # https://worker.mturk.com/projects/{group_id}/tasks?ref=w_pl_prvw # but the old format still works. # it seems I can't replace groupId by hitID, which i would like to do # because it's more precise. subdomain = "workersandbox" if self.mturk_use_sandbox else 'www' return "https://{}.mturk.com/mturk/preview?groupId={}".format( subdomain, self.mturk_HITGroupId) def mturk_is_expired(self): # self.mturk_expiration is offset-aware, so therefore we must compare # it against an offset-aware value. return self.mturk_expiration and self.mturk_expiration < time.time() def mturk_is_active(self): return self.mturk_HITId and not self.mturk_is_expired() def advance_last_place_participants(self): # django.test takes 0.5 sec to import, # if this is done globally then it adds to each startup # it's only used here, and often isn't used at all. # so best to do it only here # it gets cached import django.test client = django.test.Client() participants = self.get_participants() # in case some participants haven't started unvisited_participants = [] for p in participants: if p._index_in_pages == 0: unvisited_participants.append(p) client.get(p._start_url(), follow=True) if unvisited_participants: # that's it -- just visit the start URL, advancing by 1 return last_place_page_index = min([p._index_in_pages for p in participants]) last_place_participants = [ p for p in participants if p._index_in_pages == last_place_page_index ] for p in last_place_participants: try: current_form_page_url = p._current_form_page_url if current_form_page_url: resp = client.post( current_form_page_url, data={ otree.constants.timeout_happened: True, otree.constants.admin_secret_code: ADMIN_SECRET_CODE, }, follow=True, ) # not sure why, but many users are getting HttpResponseNotFound if resp.status_code >= 400: msg = ('Submitting page {} failed, ' 'returned HTTP status code {}.'.format( current_form_page_url, resp.status_code)) content = resp.content if len(content) < 600: msg += ' response content: {}'.format(content) raise AssertionError(msg) else: # it's possible that the slowest user is on a wait page, # especially if their browser is closed. # because they were waiting for another user who then # advanced past the wait page, but they were never # advanced themselves. start_url = p._start_url() resp = client.get(start_url, follow=True) except: logging.exception("Failed to advance participants.") raise # do the auto-advancing here, # rather than in increment_index_in_pages, # because it's only needed here. otree.channels.utils.sync_group_send_wrapper( type='auto_advanced', group=auto_advance_group(p.code), event={}) def get_room(self): from otree.room import ROOM_DICT try: room_name = RoomToSession.objects.get(session=self).room_name return ROOM_DICT[room_name] except RoomToSession.DoesNotExist: return None def _get_payoff_plus_participation_fee(self, payoff): '''For a participant who has the given payoff, return their payoff_plus_participation_fee Useful to define it here, for data export ''' return self.config[ 'participation_fee'] + payoff.to_real_world_currency(self) def _set_admin_report_app_names(self): admin_report_app_names = [] num_rounds_list = [] for app_name in self.config['app_sequence']: models_module = otree.common.get_models_module(app_name) app_label = get_app_label_from_name(app_name) try: select_template([ f'{app_label}/admin_report.html', f'{app_label}/AdminReport.html' ]) except TemplateDoesNotExist: pass else: admin_report_app_names.append(app_name) num_rounds_list.append(models_module.Constants.num_rounds) self._admin_report_app_names = ';'.join(admin_report_app_names) self._admin_report_num_rounds = ';'.join( str(n) for n in num_rounds_list) def _admin_report_apps(self): return self._admin_report_app_names.split(';') def _admin_report_num_rounds_list(self): return [int(num) for num in self._admin_report_num_rounds.split(';')] def has_admin_report(self): return bool(self._admin_report_app_names)
class Group(otree.models.BaseGroup): def set_payoffs(self): for p in self.get_players(): p.payoff = 50 in_all_groups_wait_page = models.FloatField(initial=0)
class BasePlayer(models.Model): """ Base class for all players. """ class Meta: abstract = True index_together = ['participant', 'round_number'] ordering = ['pk'] id_in_group = models.PositiveIntegerField( null=True, db_index=True, doc=("Index starting from 1. In multiplayer games, " "indicates whether this is player 1, player 2, etc.")) # don't modify this directly! Set player.payoff instead _payoff = models.CurrencyField( null=True, doc="""The payoff the player made in this subsession""", default=0) participant = models.ForeignKey('otree.Participant', related_name='%(app_label)s_%(class)s') session = models.ForeignKey('otree.Session', related_name='%(app_label)s_%(class)s') round_number = models.PositiveIntegerField(db_index=True) _group_by_arrival_time_arrived = models.BooleanField(default=False) _group_by_arrival_time_grouped = models.BooleanField(default=False) _group_by_arrival_time_timestamp = models.FloatField(default=None, null=True) def __getattribute__(self, name): try: return super(BasePlayer, self).__getattribute__(name) except AttributeError: raise AttributeError( ATTRIBUTE_ERROR_MESSAGE.format(name)) from None # it's _name instead of name because people might define # their own name field def _name(self): return self.participant.__unicode__() @property def payoff(self): return self._payoff @payoff.setter def payoff(self, value): if value is None: value = 0 delta = value - self._payoff self._payoff += delta self.participant.payoff += delta # should save it because it may not be obvious that modifying # player.payoff also changes a field on a different model self.participant.save() @property def id_in_subsession(self): return self.participant.id_in_session def __repr__(self): id_in_subsession = self.id_in_subsession if id_in_subsession < 10: # 2 spaces so that it lines up if printing a matrix fmt_string = '<Player {}>' else: fmt_string = '<Player {}>' return fmt_string.format(id_in_subsession) def role(self): # you can make this depend of self.id_in_group return '' def in_round(self, round_number): return in_round(type(self), round_number, participant=self.participant) def in_rounds(self, first, last): return in_rounds(type(self), first, last, participant=self.participant) def in_previous_rounds(self): return self.in_rounds(1, self.round_number - 1) def in_all_rounds(self): '''i do it this way because it doesn't rely on idmap''' return self.in_previous_rounds() + [self] def get_others_in_group(self): return [p for p in self.group.get_players() if p != self] def get_others_in_subsession(self): return [p for p in self.subsession.get_players() if p != self] def __unicode__(self): return self._name() def _GroupClass(self): return self._meta.get_field('group').rel.to @property def _Constants(self): return get_models_module(self._meta.app_config.name).Constants @classmethod def _ensure_required_fields(cls): """ Every ``Player`` model requires a foreign key to the ``Subsession`` and ``Group`` model of the same app. """ subsession_model = '{app_label}.Subsession'.format( app_label=cls._meta.app_label) subsession_field = models.ForeignKey(subsession_model) ensure_field(cls, 'subsession', subsession_field) group_model = '{app_label}.Group'.format(app_label=cls._meta.app_label) group_field = models.ForeignKey(group_model, null=True) ensure_field(cls, 'group', group_field)
class Player(otree.models.BasePlayer): # <built-in> group = models.ForeignKey(Group, null=True) subsession = models.ForeignKey(Subsession) # </built-in> player_name = models.CharField(max_length=255) avatar = models.CharField(max_length=255) genero = models.CharField( max_length=30, widget=widgets.RadioSelectHorizontal(), choices=[Constants.hombre, Constants.mujer], verbose_name="Seleccióne su género") # bloque 1 block_1_last_question_clicked = models.IntegerField(default=0, widget=widgets.HiddenInput()) satisfecho_con_la_vida = models.PositiveIntegerField( verbose_name=( "En una escala del 1 al 10, donde 1 es nada satisfecho y 10 " "totalmente satisfecho, en general ¿qué tan satisfecha(o) se " "encuentra usted con su vida? Usted puede escoger cualquier " "número entre 1 y 10."), choices=range(1,11), widget=widgets.RadioSelectHorizontal(), default=1) cuartos_en_el_hogar = models.PositiveIntegerField( widget=widgets.SliderInput(), max=20, verbose_name=("¿Cuántos cuartos hay en su hogar sin contar pasillos, ni baños?"), min=1, default=1) cuantos_cuartos_se_usan_para_dormir = models.PositiveIntegerField( widget=widgets.SliderInput(), max=20, verbose_name=("Y de esos cuartos, ¿cuántos usan para dormir?"), min=1, default=1) habitantes = models.PositiveIntegerField( widget=widgets.SliderInput(), max=20, verbose_name=("¿Cuántas personas viven en su hogar contando ancianos y niños?"), min=1, default=1) focos = models.PositiveIntegerField( widget=widgets.SliderInput(), max=50, verbose_name=( "Contando todos los focos que utiliza para iluminar su hogar, " "incluyendo los de techos, paredes y lámparas de buró o piso, " "dígame, ¿Cuántos focos tiene en su vivienda?"), min=1, default=1) con_quien_vive = models.CharField( verbose_name=("¿Con quién vive actualmente?"), max_length=255, default="---", choices=["---", "Solo", "Con una pareja", "Con amigos", "Con esposo(a)", "Con familia", "Otro"]) cuenta_con_automovil = models.BooleanField( verbose_name=("Automóvil propio excluyendo taxis"), widget=widgets.RadioSelectHorizontal(), default=False) cuantos_automovil = models.PositiveIntegerField(default=0) cuenta_con_televisor = models.BooleanField( verbose_name=("Televisor"), widget=widgets.RadioSelectHorizontal(), default=False) cuantos_televisor = models.PositiveIntegerField(default=0) cuenta_con_celular = models.BooleanField( verbose_name=("Teléfono Celular"), widget=widgets.RadioSelectHorizontal(), default=False) cuantos_celular = models.PositiveIntegerField(default=0) cuenta_con_computadora = models.BooleanField( verbose_name=("Computadora de escritorio o portátil"), widget=widgets.RadioSelectHorizontal(), default=False) cuantos_computadora = models.PositiveIntegerField(default=0) cuenta_con_bano = models.BooleanField( verbose_name=("Baño completo con regadera y excusado para uso exclusivo del hogar"), widget=widgets.RadioSelectHorizontal(), default=False) cuantos_bano = models.PositiveIntegerField(default=0) cuenta_con_servidumbre = models.BooleanField( verbose_name=("Personas de servicio doméstico como limpieza, jardinero o chofer"), widget=widgets.RadioSelectHorizontal(), default=False) cuantos_servidumbre = models.PositiveIntegerField(default=0) tarjeta_de_credito = models.BooleanField( verbose_name=("Cuenta usted con tarjeta de crédito"), widget=widgets.RadioSelectHorizontal(), default=False) altura = models.FloatField( verbose_name=("Aproximadamente, ¿qué estatura tiene usted? (en metros)"), min=0, widget=widgets.SliderInput(attrs={'step': '0.01', 'max': '2.5'}), default=0) peso = models.PositiveIntegerField( verbose_name=("Aproximadamente, ¿qué peso tiene usted? (en kilogramos)"), min=0, max=200, widget=widgets.SliderInput(), default=0) ejercicio_fisico = models.BooleanField( verbose_name=("Durante las últimas dos semanas, ¿ha realizado usted ejercicio físico fuera del trabajo?"), widget=widgets.RadioSelectHorizontal(), default=False) cigarrillo = models.BooleanField( verbose_name=("Durante las últimas dos semanas, ¿ha fumado algún cigarrillo o puro?"), widget=widgets.RadioSelectHorizontal(), default=False) vive_con_padre = models.BooleanField( widget=widgets.RadioSelectHorizontal(), default=False) vive_con_madre = models.BooleanField( widget=widgets.RadioSelectHorizontal(), default=False) edad_padre = models.PositiveIntegerField( choices=range(30, 101), default=30) edad_madre = models.PositiveIntegerField( choices=range(30, 101), default=30) padre_habla_dialecto_indigena = models.BooleanField( widget=widgets.RadioSelectHorizontal(), default=False) madre_habla_dialecto_indigena = models.BooleanField( widget=widgets.RadioSelectHorizontal(), default=False) padre_habla_lengua_extranjera = models.BooleanField( widget=widgets.RadioSelectHorizontal(), default=False) madre_habla_lengua_extranjera = models.BooleanField( widget=widgets.RadioSelectHorizontal(), default=False) nivel_educacion_padre = models.CharField( choices=["---", "Primaria", "Secundaria", "Preparatoria", "Universitario"], max_length=50, default="---") nivel_educacion_madre = models.CharField( choices=["---", "Primaria", "Secundaria", "Preparatoria", "Universitario"], max_length=50, default="---") # bloque 2 block_2_last_question_clicked = models.IntegerField(default=0, widget=widgets.HiddenInput()) riqueza_hogar_14_anios = models.PositiveIntegerField( widget=widgets.RadioSelectHorizontal(), verbose_name=( "Comparando el hogar donde vivía a los 14 años con todos los " "hogares actuales de México y usando una escala de 1 a 10, en la " "que 1 son los hogares más pobres y 10 son los más ricos, ¿dónde " "pondría usted su hogar de ese entonces?"), choices=range(1, 11), default=1) TRABAJOS = ("---", "Patrón o empleador ", "Trabajador por cuenta propia ", "Empleado u obrero del sector público", "Empleado u obrero del sector privado", "Servicio Doméstico (por pago)", "Quehaceres del hogar (sin pago) ", "Trabajador sin pago ", "Fuerzas armadas y del orden") padre_trabajaba_14_anios = models.BooleanField(widget=widgets.RadioSelectHorizontal(), default=False) madre_trabajaba_14_anios = models.BooleanField(widget=widgets.RadioSelectHorizontal(), default=False) padre_ocupacion_14_anios = models.CharField(max_length=255, choices=TRABAJOS, default=TRABAJOS[0]) madre_ocupacion_14_anios = models.CharField(max_length=255, choices=TRABAJOS, default=TRABAJOS[0]) padre_trabajo_servicios_medicos_14_anios = models.BooleanField(widget=widgets.RadioSelectHorizontal(), default=False) madre_trabajo_servicios_medicos_14_anios = models.BooleanField(widget=widgets.RadioSelectHorizontal(), default=False) CON_QUIEN_VIVIA = ( "---", "Solo con el padre", "Solo con la madre", "Con ambos, padre y madre", "Con otra familia", "Otra persona") con_quien_vivia_14_anios = models.CharField( verbose_name=("Cuando usted tenía alrededor de 14 años ¿con quién vivía?"), choices=CON_QUIEN_VIVIA, default=CON_QUIEN_VIVIA[0], max_length=255) MUCHO_REGULAR_POCO_NADA = ["---", "Mucho", "Regular", "Poco", "Nada"] padre_emocionalmente_cerano_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) madre_emocionalmente_cerano_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) padre_entendia_problemas_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) madre_entendia_problemas_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) padre_actividades_escolares_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) madre_actividades_escolares_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) padre_actividades_tiempo_libre_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) madre_actividades_tiempo_libre_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) padre_reglas_claras_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) madre_reglas_claras_14_anios = models.CharField( max_length=20, choices=MUCHO_REGULAR_POCO_NADA, default=MUCHO_REGULAR_POCO_NADA[0]) relacion_padres_14_anios = models.CharField( verbose_name=("¿La relación entre sus padres generalmente era: excelente, buena, regular, mala o muy mala?"), max_length=20, default="---", choices=["---", "Excelente", "Buena", "Regular", "Mala", "Muy mala"]) FAMILIA_FRECUENCIA = ("Siempre", "Frecuentemente", "Pocas veces", "Nunca", "Omitir") familia_frecuencia_insultos_14_anios = models.CharField( verbose_name=("¿Con qué frecuencia ocurrían INSULTOS, GRITOS o AMENAZAS en su familia?"), max_length=20, choices=FAMILIA_FRECUENCIA, default=FAMILIA_FRECUENCIA[-1]) familia_frecuencia_cercania_14_anios = models.CharField( verbose_name=("¿Con qué frecuencia los miembros de su familia se sentían muy cercanos los unos de los otros?"), max_length=20, choices=FAMILIA_FRECUENCIA, default=FAMILIA_FRECUENCIA[-1]) frequencia_miedos_14_anios = models.CharField( verbose_name=("¿Con qué frecuencia la/lo molestaban miedos o preocupaciones?"), max_length=20, choices=FAMILIA_FRECUENCIA, default=FAMILIA_FRECUENCIA[-1]) madre_trabajo_por_ingreso_desde_que_nacio = models.BooleanField( verbose_name=("¿Su madre trabajo por un ingreso en algún momento desde que usted nació hasta el día de hoy?"), widget=widgets.RadioSelectHorizontal(), default=False) madre_trabajo_periodos_de_su_vida_0_4_anios = models.BooleanField( verbose_name=("0 a 4 años de edad"), widget=widgets.RadioSelectHorizontal(), default=False) madre_trabajo_periodos_de_su_vida_5_9_anios = models.BooleanField( verbose_name=("5 a 9 años de edad"), widget=widgets.RadioSelectHorizontal(), default=False) madre_trabajo_periodos_de_su_vida_10_14_anios = models.BooleanField( verbose_name=("10 a 14 años de edad"), widget=widgets.RadioSelectHorizontal(), default=False) madre_trabajo_periodos_de_su_vida_15_19_anios = models.BooleanField( verbose_name=("15 a 19 años de edad"), widget=widgets.RadioSelectHorizontal(), default=False) tiene_hermanos = models.BooleanField( verbose_name=("¿Tiene usted hermanos o hermanas?"), widget=widgets.RadioSelectHorizontal(), default=False) numero_de_hermano_que_es_usted = models.PositiveIntegerField( verbose_name=( "Ahora piense en sus hermanos ordenándolos del mayor al menor " "aunque hayan fallecido y dígame qué número de hermano es usted."), choices=range(1, 11), default=1, widget=widgets.RadioSelectHorizontal()) HERMANOS_1_10 = ["---"] + [str(i) for i in range(1, 11)] hermanos_que_son = models.CharField(choices=HERMANOS_1_10, max_length=10, default=HERMANOS_1_10[0]) hermanas_que_son = models.CharField(choices=HERMANOS_1_10, max_length=10, default=HERMANOS_1_10[0]) hermanos_viven_con_usted_actualmente = models.CharField(choices=HERMANOS_1_10, max_length=10, default=HERMANOS_1_10[0]) hermanas_viven_con_usted_actualmente = models.CharField(choices=HERMANOS_1_10, max_length=10, default=HERMANOS_1_10[0]) hermanos_trabajan_por_pago_actualmente = models.CharField(choices=HERMANOS_1_10, max_length=10, default=HERMANOS_1_10[0]) hermanas_trabajan_por_pago_actualmente = models.CharField(choices=HERMANOS_1_10, max_length=10, default=HERMANOS_1_10[0]) espera_trabajar_remonerado_mayor_parte_de_su_vida = models.BooleanField( widget=widgets.RadioSelectHorizontal(), verbose_name=("¿Espera usted trabajar de forma remunerada la mayor parte de su vida?"), default=False) TRABAJO_FUTURO = [ "---", "Asalariado", "Auto-empleado", "Dueño de negocio", "Dueño de empresa", "Ninguna de las anteriores"] de_que_manera_espera_trabajar = models.CharField( verbose_name="¿De qué manera espera trabajar?", choices=TRABAJO_FUTURO, max_length=100, default=TRABAJO_FUTURO[0]) cuanto_cree_que_ganaria_en_30_anios = models.PositiveIntegerField( widget=widgets.SliderInput(), max=100000, verbose_name=( "Imagine que usted tiene 30 años el día de hoy y está trabajando " "de forma remunerada. ¿Cuánto cree que ganaría al mes por su trabajo?"), default=0) cree_que_tendra_hijo = models.CharField( verbose_name="Cree que usted tenga un hijo en algún momento de la vida?", choices=["---", "Si", "No", "Ya lo tuvo"], max_length=100, default="---") edad_de_primer_hijo = models.PositiveIntegerField( verbose_name=("¿A qué edad espera tener su primer hijo?"), choices=range(1, 100), default=0) edad_tuvo_primer_hijo = models.PositiveIntegerField( verbose_name=("¿A qué edad tuvo a su primer hijo?"), choices=range(1, 100), default=0) # BLOQUE 3 block_3_last_question_clicked = models.IntegerField(default=0, widget=widgets.HiddenInput()) RANGO_1_10 = range(1, 11) hogar_actual_vs_mexico = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Comparando su hogar actual con todos los hogares actuales de México y usando una escala de 1 a 10, en la que 1 son los hogares más pobres y 10 son los más ricos, ¿dónde pondría usted su hogar actual?")) cuanto_depende_de_usted_que_le_vaya_bien = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("En una escala del 1 al 10, donde 1 es “nada depende de usted” y 10 es “todo depende de usted”, ¿qué tanto depende de usted misma(o) que le vaya bien en este año y el próximo?")) gobierno_o_sociedad_pobreza = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Pobreza")) gobierno_o_sociedad_delincuencia = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Delincuencia")) gobierno_o_sociedad_narcotrafico = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Narcotráfico")) gobierno_o_sociedad_corrupcion = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Corrupción")) gobierno_o_sociedad_educacion = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Mala o Poca Educación")) gobierno_o_sociedad_discriminacion = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Discriminación")) gobierno_o_sociedad_adicciones_y_enfermedades = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Atención de adicciones y enfermedades")) dispuesto_a_tomar_riesgos = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("En una escala del 1 al 10, donde 1 es nada dispuesto y 10 totalmente dispuesto, ¿qué tan dispuesto está a tomar riesgos?")) describe_como_persona_abstengo_hacer_cosas_hoy = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Me abstengo de cosas hoy para poder tener más mañana")) describe_como_persona_retrazo_cosas = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Tiendo a retrasar cosas aun cuando sería mejor hacerlas de una vez")) describe_como_persona_asumo_gente_tiene_mejores_intenciones = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Mientras no esté convencido de lo contrario, siempre asumo que la gente tiene las mejores intenciones")) describe_como_persona_no_entiendo_pelea_no_le_beneficia = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("No entiendo por qué alguna gente dedica su vida a pelear por una causa que no les beneficia directamente")) describe_como_persona_ayudo_al_que_me_ayudo = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Realizo un gran esfuerzo para ayudar a alguien que me ha ayudado antes")) describe_como_persona_me_vengo = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Si alguien me hace algo malo a propósito, trataré de regresárselo")) que_tan_impulsivo_se_considera = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("En una escala del 1 al 10, donde 1 es totalmente y 10 es nada, ¿qué tan impulsivo se considera?")) dispuesto_a_confiar = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Confiar en otras personas")) dispuesto_a_compartir = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Compartir algo con otras personas sin nada a cambio")) dispuesto_a_regresar_favor = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Regresar un favor a un extraño")) dispuesto_a_castigar = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Castigar a alguien debido a una conducta injusta aun cuando es costoso. Ej. Decirle a una persona que no tire basura en la calle aun cuando esa persona se puede enojar y decirle algo.")) que_tan_paciente_se_considera = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("En una escala del 1 al 10, donde 1 es muy paciente y 10 es muy impaciente, ¿qué tan paciente o impaciente se considera? Usted puede escoger cualquier número entre 1 y 10.")) acuerdo_con_educacion_genera_ingreso = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("El nivel educativo determina el nivel de ingreso de una persona")) acuerdo_con_hombres_mas_trabajo_que_mujeres = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Cuando no hay mucho trabajo, los hombres deberían de tener preferencia a un trabajo antes que las mujeres")) acuerdo_con_esposa_que_gana_mas_genera_dinero = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("La esposa que gana más dinero que el esposo genera problemas")) acuerdo_con_no_se_puede_confiar_en_nadie = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Hoy en día, no se puede confiar en nadie más")) acuerdo_con_camino_de_mi_vida = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("El camino de mi vida depende de mí")) acuerdo_con_he_logrado_lo_que_merezco = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("En comparación con otros, no he logrado lo que merezco")) acuerdo_con_logros_suerte = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Lo que se logra en la vida es principalmente una cuestión de destino o suerte")) acuerdo_con_otros_deciden_por_mi = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Frecuentemente tengo la sensación de que otros toman decisiones sobre mi vida")) acuerdo_con_puedo_influir_en_condicion_social = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Si uno es social o políticamente activo, se puede influir en las condiciones sociales")) acuerdo_con_trabajar_duro_exito = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Hay que trabajar duro para alcanzar el éxito")) acuerdo_con_dudo_de_mi_mismo = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Si enfrento dificultades en la vida, frecuentemente dudo de mí mismo")) acuerdo_con_oportunidades_dadas_por_condiciones_sociales = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Las oportunidades que tengo en la vida están determinadas por las condiciones sociales")) acuerdo_con_habilidades_mas_que_esfuerzo = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Las habilidades con las que nací son más importantes que todo el esfuerzo que yo pueda hacer")) acuerdo_con_poco_control_de_la_vida = models.PositiveIntegerField( choices=RANGO_1_10, default=RANGO_1_10[0], widget=widgets.RadioSelectHorizontal(), verbose_name=("Tengo poco control sobre las cosas que suceden en mi vida")) TOTALMENTE_MUCHO_REGULAR_POCO_NADA = ("---", "Totalmente", "Mucho", "Regular", "Poco", "Nada") que_tanto_es_es_reservado = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Es reservado(a)")) que_tanto_es_confiable = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Es generalmente confiable")) que_tanto_es_flojo = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Tiende a ser flojo(a)")) que_tanto_es_relajado = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Es relajado(a) o maneja bien el estrés")) que_tanto_es_artista = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Tiene intereses artísticos")) que_tanto_es_sociable = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Es extrovertido(a) o sociable")) que_tanto_es_falla_en_los_demas = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Tiende a encontrar fallas en los demás")) que_tanto_es_nervioso = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Se pone nervioso(a) fácilmente")) que_tanto_es_imaginador = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Tiene una imaginación activa")) que_tanto_lo_describe_ideas_me_distraen = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Algunas veces nuevas ideas y proyectos me distraen de mis proyectos e ideas anteriores")) que_tanto_lo_describe_contratiempos_desanima = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Los contratiempos no me desaniman")) que_tanto_lo_describe_persona_trabajadora = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Soy una persona muy trabajadora")) que_tanto_lo_describe_pierdo_interes = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Me obsesiono con ideas o proyectos por un tiempo, pero pierdo el interés rápidamente.")) que_tanto_lo_describe_persigo_diferentes_metas = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Frecuentemente me pongo una meta pero más tarde persigo una diferente.")) que_tanto_lo_describe_dificultades_para_concentracion = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Tengo dificultades para mantener mi concentración en proyectos que toman más de unos cuantos meses en completarse.")) que_tanto_lo_describe_termino_lo_que_comienzo = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Termino todo lo que comienzo")) que_tanto_lo_describe_efuerzo_en_mi_trabajo = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Pongo mucho esfuerzo en los trabajos que realizo")) que_tanto_lo_describe_malos_habitos = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Me cuesta romper malos hábitos")) que_tanto_lo_describe_cosas_inapropiadas = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Frecuentemente digo cosas inapropiadas")) que_tanto_lo_describe_resisto_tentaciones = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Soy muy bueno para resistir tentaciones")) que_tanto_lo_describe_me_arrepiento = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Hago cosas que se sienten bien en el momento pero después me arrepiento de ellas")) que_tanto_lo_describe_hago_cosas_sin_pensar = models.CharField( choices=TOTALMENTE_MUCHO_REGULAR_POCO_NADA, default=TOTALMENTE_MUCHO_REGULAR_POCO_NADA[0], max_length=30, verbose_name=("Frecuentemente hago cosas sin pensar en todas las opciones")) apuesta_loteria_1000 = models.PositiveIntegerField( verbose_name=("Imagine un juego de lotería con diez boletos numerados del 1 al 10, cuyo premio al número ganador es de $1,000. ¿Cuánto estaría dispuesto a pagar por un boleto para participar en ella?"), min=0, max=1000, widget=widgets.SliderInput(), default=0) donar_1000 = models.PositiveIntegerField( verbose_name=("Imagine la siguiente situación: El día de hoy usted recibe inesperadamente $1,000. ¿Cuánto consideraría donar a una buena causa?"), min=0, max=1000, widget=widgets.SliderInput(), default=0) pagan_100_esperar_3_meses = models.PositiveIntegerField( min=1000, max=50000, widget=widgets.SliderInput(), verbose_name=("¿Cuánto le tendrían que pagar dentro de tres meses para que pueda esperar este tiempo?"), default=0) que_tanto_lo_describe_1_anio = models.PositiveIntegerField( min=1000, max=50000, widget=widgets.SliderInput(), verbose_name=("Y ahora, ¿cuánto le tendrían que pagar dentro de un año para que pueda esperar ese tiempo?"), default=0) # bloque 4 block_4_last_question_clicked = models.IntegerField(default=0, widget=widgets.HiddenInput()) # MUJERES mestruando = models.BooleanField( verbose_name="¿Se encuentra usted menstruando el día de hoy?", default=False, widget=widgets.RadioSelectHorizontal()) fecha_ultima_regla = models.DateField( default=lambda: timezone.now().date(), verbose_name="Fecha de comienzo de última regla (si no recuerda con precisión, favor de indicar la fecha más próxima).") fecha_siguiente_regla = models.DateField( default=lambda: timezone.now().date(), verbose_name="Fecha esperada de comienzo de siguiente regla (si no puede calcular con precisión, favor de indicar la fecha más próxima independientemente de si usted es regular o irregular)") anticonceptivos = models.BooleanField( verbose_name="¿Utiliza pastillas anticonceptivas?", default=False, widget=widgets.RadioSelectHorizontal()) duracion_del_sangrado = models.PositiveIntegerField( verbose_name=("¿Normalmente, cuántos días dura el sangrado?"), widget=widgets.SliderInput(), default=5, min=1, max=10) # HOMBRES trabaja_empresa_dependencia_publica = models.BooleanField( verbose_name="Actualmente se encuentra trabajando en alguna empresa o dependencia pública?", default=False, widget=widgets.RadioSelectHorizontal()) fecha_busqueda_empleo = models.DateField( default=lambda: timezone.now().date(), verbose_name="Aproximadamente, cuando fue la última fecha en que buscó empleo?.") fecha_fin_de_estudios = models.DateField( default=lambda: timezone.now().date(), verbose_name="Fecha en la que dio por terminados sus estudios?") discriminacion_laboral = models.BooleanField( verbose_name="Desde su perspectiva, alguna vez ha sido victima de discriminación laboral?", default=False, widget=widgets.RadioSelectHorizontal()) que_tanto_presencio_discriminacion = models.PositiveIntegerField( verbose_name=("En una escala del 1 al 10, que tanto ha presenciado discriminación, para usted o algún compañero, en el campo laboral?"), widget=widgets.SliderInput(), default=5, min=1, max=10) # Bloque 5 FIGURE_CHOICES_6 = ['---', '1', '2', '3', '4', '5', '6'] fig1 = models.CharField( verbose_name="fig1.jpg", max_length=10, choices=FIGURE_CHOICES_6, default=FIGURE_CHOICES_6[0]) fig2 = models.CharField( verbose_name="fig2.jpg", max_length=10, choices=FIGURE_CHOICES_6, default=FIGURE_CHOICES_6[0]) fig3 = models.CharField( verbose_name="fig3.jpg", max_length=10, choices=FIGURE_CHOICES_6, default=FIGURE_CHOICES_6[0]) fig4 = models.CharField( verbose_name="fig4.jpg", max_length=10, choices=FIGURE_CHOICES_6, default=FIGURE_CHOICES_6[0]) FIGURE_CHOICES_8 = ['---', '1', '2', '3', '4', '5', '6', '7', '8'] fig5 = models.CharField( verbose_name="fig5.jpg", max_length=10, choices=FIGURE_CHOICES_8, default=FIGURE_CHOICES_8[0]) fig6 = models.CharField( verbose_name="fig6.jpg", max_length=10, choices=FIGURE_CHOICES_8, default=FIGURE_CHOICES_8[0]) fig7 = models.CharField( verbose_name="fig7.jpg", max_length=10, choices=FIGURE_CHOICES_8, default=FIGURE_CHOICES_8[0]) fig8 = models.CharField( verbose_name="fig8.jpg", max_length=10, choices=FIGURE_CHOICES_8, default=FIGURE_CHOICES_8[0]) fig9 = models.CharField( verbose_name="fig9.jpg", max_length=10, choices=FIGURE_CHOICES_8, default=FIGURE_CHOICES_8[0]) fig10 = models.CharField( verbose_name="fig10.jpg", max_length=10, choices=FIGURE_CHOICES_8, default=FIGURE_CHOICES_8[0])
class Participant(models.OTreeModel, models.VarsMixin, ParticipantIDMapMixin): class Meta: ordering = ['pk'] app_label = "otree" index_together = ['session', 'mturk_worker_id', 'mturk_assignment_id'] session = djmodels.ForeignKey('otree.Session', on_delete=models.CASCADE) vars: dict = models._PickleField(default=dict) label = models.CharField( max_length=50, null=True, doc=( "Label assigned by the experimenter. Can be assigned by passing a " "GET param called 'participant_label' to the participant's start " "URL" ), ) id_in_session = models.PositiveIntegerField(null=True) payoff = models.CurrencyField(default=0) time_started = djmodels.DateTimeField(null=True) mturk_assignment_id = models.CharField(max_length=50, null=True) mturk_worker_id = models.CharField(max_length=50, null=True) _index_in_pages = models.PositiveIntegerField(default=0, db_index=True) def _numeric_label(self): """the human-readable version.""" return 'P{}'.format(self.id_in_session) _monitor_note = models.CharField(null=True, max_length=300) code = models.CharField( default=random_chars_8, max_length=16, # set non-nullable, until we make our CharField non-nullable null=False, # unique implies DB index unique=True, ) # useful when we don't want to load the whole session just to get the code _session_code = djmodels.CharField(max_length=16) visited = models.BooleanField( default=False, db_index=True, doc="""Whether this user's start URL was opened""" ) # stores when the page was first visited _last_page_timestamp = models.PositiveIntegerField(null=True) _last_request_timestamp = models.PositiveIntegerField(null=True) is_on_wait_page = models.BooleanField(default=False) # these are both for the admin # In the changelist, simply call these "page" and "app" _current_page_name = models.CharField( max_length=200, null=True, verbose_name='page' ) _current_app_name = models.CharField(max_length=200, null=True, verbose_name='app') # only to be displayed in the admin participants changelist _round_number = models.PositiveIntegerField(null=True) _current_form_page_url = djmodels.URLField() _max_page_index = models.PositiveIntegerField() _is_bot = models.BooleanField(default=False) # can't start with an underscore because used in template # can't end with underscore because it's a django field (fields.E001) is_browser_bot = models.BooleanField(default=False) _timeout_expiration_time = models.FloatField() _timeout_page_index = models.PositiveIntegerField() _gbat_is_waiting = models.BooleanField(default=False) _gbat_page_index = models.PositiveIntegerField() _gbat_grouped = models.BooleanField() def _current_page(self): # don't put 'pages' because that causes wrapping which takes more space # since it's longer than the header return f'{self._index_in_pages}/{self._max_page_index}' # because variables used in templates can't start with an underscore def current_page_(self): return self._current_page() def get_players(self): """Used to calculate payoffs""" lst = [] app_sequence = self.session.config['app_sequence'] for app in app_sequence: models_module = otree.common.get_models_module(app) players = models_module.Player.objects.filter(participant=self).order_by( 'round_number' ) lst.extend(list(players)) return lst def _url_i_should_be_on(self): if not self.visited: return self._start_url() if self._index_in_pages <= self._max_page_index: return url_i_should_be_on( self.code, self._session_code, self._index_in_pages ) return reverse('OutOfRangeNotification', args=[self.code]) def _start_url(self): return otree.common.participant_start_url(self.code) def payoff_in_real_world_currency(self): return self.payoff.to_real_world_currency(self.session) def payoff_plus_participation_fee(self): return self.session._get_payoff_plus_participation_fee(self.payoff) def _get_current_player(self): lookup = get_page_lookup(self._session_code, self._index_in_pages) models_module = otree.common.get_models_module(lookup.app_name) PlayerClass = getattr(models_module, 'Player') return PlayerClass.objects.get( participant=self, round_number=lookup.round_number )