from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants import re #from captcha.fields import ReCaptchaField class Consent(Page): def vars_for_template(self): return {'participation_fee': Constants.participation_fee, 'max_bonus': self.session.config['max_bonus'], 'redemption_code': self.participant.code } class Captcha(Page): _allow_custom_attributes = True form_model = 'player' form_fields = [] # captcha does not get in here #def get_form(self, data=None, files=None, **kwargs): # frm = super().get_form(data, files, **kwargs) # frm.fields['captcha'] = ReCaptchaField() # return frm class Demographics(Page): form_model = 'player' form_fields = ['year_of_birth', 'gender', 'income', 'hhincome', 'marital_status', 'children', 'education', 'height', 'weight', 'health', 'race', 'westernized', 'country', 'zip', 'loan', 'loan_hypothetical', 'loan_hypothetical_why'] def vars_for_template(self): image = Constants.sil_pic return {'image': image} def before_next_page(self): p = self.player p.qualified = True p.age = 2019 - p.year_of_birth if getattr(p, "year_of_birth") > 1990: p.qualified = False class Warning(Page): pass class Round1(Page): def is_displayed(self): return self.player.qualified is True def vars_for_template(self): if self.player.cp_error: return {'message': 'You made a mistake! Please, re-read the instructions.', 'endowment': Constants.endowment} else: return {'endowment': Constants.endowment} class UQ_s(Page): def is_displayed(self): return self.player.qualified is True """Comprehension Question""" form_model = 'player' form_fields = ['uq1', 'uq2', 'uq3'] # Function to redirect to instructions page if the comprehension answers are wrong: def before_next_page(self): p = self.player p.cp_error = False for k, v in Constants.correct_answers.items(): if getattr(p, k) != v and p.error1 is not True: p.cp_error = True p.error1 = True break elif getattr(p, k) != v and p.error1 is True: p.cp_error = False p.error2 = True p.flagged = True break if self.player.cp_error: for f in self.form_fields: setattr(p, f, None) self._is_frozen = False self._index_in_pages -= 2 self.participant._index_in_pages -= 2 class SignalingCredit(Page): def is_displayed(self): return self.player.qualified is True and self.player.flagged is not True """Player chooses whether to signal to show creditworthiness""" form_model = 'player' form_fields = ['signal_credit', 'unit_update_credit_age', 'unit_update_credit_weight', 'unit_update_credit_height'] def vars_for_template(self): if self.player.update_error: return {'message': 'Careful, you selected a characteristic but forgot to update it!', 'gender': self.player.gender, 'age': self.player.age, 'weight': self.player.weight, 'height': self.player.height, 'income': round(self.player.income)} else: return { 'gender': self.player.gender, 'age': self.player.age, 'weight': self.player.weight, 'height': self.player.height, 'income': round(self.player.income)} def before_next_page(self): p = self.player p.update_error = False if self.player.signal_credit == 1: self.player.unit_update_credit_weight = 0 self.player.unit_update_credit_height = 0 if getattr(p, 'unit_update_credit_age') == 0: p.update_error = True elif self.player.signal_credit == 2: self.player.unit_update_credit_age = 0 self.player.unit_update_credit_height = 0 if getattr(p, 'unit_update_credit_weight') == 0: p.update_error = True elif self.player.signal_credit == 3: self.player.unit_update_credit_age = 0 self.player.unit_update_credit_weight = 0 if getattr(p, 'unit_update_credit_height') == 0: p.update_error = True elif self.player.signal_credit is 0: self.player.unit_update_credit_age = 0 self.player.unit_update_credit_weight = 0 self.player.unit_update_credit_height = 0 # Update unless the participant did not move the slider: if self.player.update_error: self._is_frozen = False self._index_in_pages -= 1 self.participant._index_in_pages -= 1 else: self.player.update_credit_age = self.player.age + self.player.unit_update_credit_age self.player.update_credit_weight = self.player.weight + self.player.unit_update_credit_weight self.player.update_credit_height = self.player.height + self.player.unit_update_credit_height class Warning2(Page): pass class Round2(Page): def is_displayed(self): return self.player.qualified is True def vars_for_template(self): if self.player.cp_error_d: return {'message': 'You made a mistake! Please, re-read the instructions.'} class UQ_s_dating(Page): def is_displayed(self): return self.player.qualified is True """Comprehension Question""" form_model = 'player' form_fields = ['uq1_d', 'uq2_d'] # Function to redirect to instructions page if the comprehension answers are wrong: def before_next_page(self): p = self.player p.flagged_d = False for k, v in Constants.correct_answers_d.items(): if getattr(p, k) != v and p.error1d is not True: p.cp_error_d = True p.error1d = True break elif getattr(p, k) != v and p.error1d is True: p.cp_error_d = False p.error2d = True p.flagged_d = True break if self.player.cp_error_d: for f in self.form_fields: setattr(p, f, None) self._is_frozen = False self._index_in_pages -= 2 self.participant._index_in_pages -= 2 class SignalingDating(Page): def is_displayed(self): return self.player.qualified is True """Player chooses whether to signal to show dating potential """ form_model = 'player' form_fields = ['signal_dating', 'unit_update_dating_age', 'unit_update_dating_weight', 'unit_update_dating_height'] def vars_for_template(self): if self.player.update_error: return {'message': 'Careful, you selected a ' 'characteristic but forgot to update it!', 'gender': self.player.gender, 'age': self.player.age, 'weight': self.player.weight, 'height': self.player.height, 'income': round(self.player.income)} else: return {'gender': self.player.gender, 'age': self.player.age, 'weight': self.player.weight, 'height': self.player.height, 'income': round(self.player.income)} def before_next_page(self): p = self.player p.update_error = False if self.player.signal_dating == 1: self.player.unit_update_dating_weight = 0 self.player.unit_update_dating_height = 0 if getattr(p, 'unit_update_dating_age') == 0: p.update_error = True elif self.player.signal_dating == 2: self.player.unit_update_dating_age = 0 self.player.unit_update_dating_height = 0 if getattr(p, 'unit_update_dating_weight') == 0: p.update_error = True elif self.player.signal_dating == 3: self.player.unit_update_dating_age = 0 self.player.unit_update_dating_weight = 0 if getattr(p, 'unit_update_dating_height') == 0: p.update_error = True elif self.player.signal_dating is 0: self.player.unit_update_dating_age = 0 self.player.unit_update_dating_weight = 0 self.player.unit_update_dating_height = 0 if self.player.update_error: self._is_frozen = False self._index_in_pages -= 1 self.participant._index_in_pages -= 1 else: self.player.update_dating_age = self.player.age + \ self.player.unit_update_dating_age self.player.update_dating_weight = self.player.weight + \ self.player.unit_update_dating_weight self.player.update_dating_height = self.player.height + \ self.player.unit_update_dating_height class Issues(Page): def is_displayed(self): return self.player.qualified is True form_model = 'player' form_fields = ['issues', 'comments'] def before_next_page(self): self.player.set_payoffs() class ResultsUganda(Page): form_model = 'player' form_fields = ['phone_number', 'payment_method'] def is_displayed(self): return self.player.qualified is True def vars_for_template(self): if self.player.phone_error: return {"msg": "Invalid mobile phone number!", "participation_fee": Constants.participation_fee, "max_bonus": Constants.maxbonus, "payoff_round1": self.participant.vars["payoff_round1"], "payoff_round2": self.participant.vars["payoff_round2"], "total_payoff": self.participant.payoff_plus_participation_fee() } else: return {"participation_fee": Constants.participation_fee, "max_bonus": Constants.maxbonus, "payoff_round1": self.participant.vars["payoff_round1"], "payoff_round2": self.participant.vars["payoff_round2"], "total_payoff": self.participant.payoff_plus_participation_fee() } def before_next_page(self): """ Raise a ValidationError if the value looks like a mobile telephone number. """ rule = re.compile(r'^(?:\+?256)?[07]\d{9,13}$') if not rule.search(self.player.phone_number): self.player.phone_error = True else: self.player.phone_error = False if self.player.phone_error: self._is_frozen = False self._index_in_pages -= 1 self.participant._index_in_pages -= 1 class Excluded(Page): form_model = 'player' form_fields = ['phone_number', 'payment_method'] def is_displayed(self): return self.player.qualified is False def vars_for_template(self): if self.player.phone_error: return{"msg": "Invalid mobile phone number!", "thank_you_bonus": Constants.thank_you_bonus } else: return {"thank_you_bonus": Constants.thank_you_bonus } def before_next_page(self): """ Raise a ValidationError if the value looks like a mobile telephone number. """ rule = re.compile(r'^(?:\+?256)?[07]\d{9,13}$') if not rule.search(self.player.phone_number): self.player.phone_error = True else: self.player.phone_error = False if self.player.phone_error: self._is_frozen = False self._index_in_pages -= 1 self.participant._index_in_pages -= 1 page_sequence = [ Consent, #Captcha, Demographics, Warning, Round1, UQ_s, SignalingCredit, Warning2, Round2, UQ_s_dating, SignalingDating, Issues, ResultsUganda, Excluded ]