from otree.api import * import random # # add attention tasks # add practice tasks # Add treatment 3 and 4 in which there are some helping options: # this can be done by adding one option to no_donation field being: # I donate x to all, a randomly selected charity # repeating the field results in replacing the value of the field. # Amount of donation changes to tokens # Add pictures for tokens # Letting them know that they are navigating to the next page: changing the background , or the title # use a picture for tokens // number of tokens. in two pages. # documentation that directs subjects to the Prolific # Payment: atomatic approval or manual approval # Otree adds few more pages and collects the prolofic ID. # Say minimum 5 pounds per prolific // 7.5 recomanded. # to Return their submission - # Attention tasks - internal biases for donation doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'charity_survey' PLAYERS_PER_GROUP = None NUM_ROUNDS = 28 # there will be 4 repetition total_rounds = 25 # total number of rounds: number of pages*number of repetition # Initial amount allocated to the player TOKEN = 100 # For convenience of working with fields NUMBERS1 = [11, 12, 15, 110, 120] NUMBERS2 = list(range(1, 40)) # Treatment 1: choose one; Treatment 2: choose as many TREATMENTS = [1, 2] # Ascending or descending order of options or randomised # 'OneMany', 'ManyOne', 'Rand' TASKS = [1, 1] # Endowment if they complete the experiment ENDOWMENT_TOTAL = NUM_ROUNDS * len(NUMBERS1) * 100 # conversion_rate = 500 flat_rate_pounds = 6 # 6 pounds flat_rate_token = flat_rate_pounds * conversion_rate # Add that the charity list comes from the execl file # charity_list is used for treatment 1 charity_list = [ 'I will donate to support Breast Cancer UK in their education, research and campaigning work to prevent ' 'more cases of breast cancer.', 'I will donate to support Breast Cancer UK’s research into the effect of bisphenols ' '(chemicals used in certain everyday plastics) on breast cancer development.', 'I will donate to support The Citizens Foundation (UK) to fund high quality, life changing education for ' 'underprivileged children in Pakistan.', 'I will donate to support The Citizens Foundation (UK) in covering the operating expenses of a school unit.', 'I will donate to support The Citizens Foundation (UK) with their Female Empowerment Fund to educate and ' 'empower women in the community.', 'I will donate to support The Citizens Foundation (UK) with their Alumni Scholarship Fund to provide higher ' 'education scholarships to promising TCF graduates.', 'I will donate to support ARHC to fund care and support for their patients and their families.', 'I will donate to support ARHC in meeting the daily cost of home-cooked meals for patients.', 'I will donate to support ARHC to cover the costs of clinical uniforms for their frontline teams.', 'I will donate to support ARHC to help someone who has been bereaved, by organising a counselling session.', 'I will donate to support Ovacome to cover the cost of sending information booklets to someone who has just ' 'been diagnosed with ovarian cancer.', 'I will donate to support Ovacome with providing an hour of 1-1 specialist support for someone affected ' 'by ovarian cancer.', 'I will donate to support Ovacome to pay for a live webinar with a leading clinician in the field of ovarian ' 'cancer.', 'I will donate to support Ovacome in providing support and information to anyone affected by ovarian cancer.', 'I will donate to support Chichester Festival Theatre with their Ageless Campaign for access to the ' 'theatre and live art for people who may not find it easy to get involved in theatre, including older ' 'people at risk of isolation.', 'I will donate to support Chichester Festival Theatre to buy art materials for ' 'their intergenerational workshops.', 'I will donate to support Chichester Festival Theatre to buy musical instruments for their dementia friendly ' 'singing groups.', 'I will donate to support Chichester Festival Theatre to buy cast lists in braille for use by their visually ' 'impaired customers.', 'I will donate to support Chichester Festival Theatre to appoint a specialist practitioner to run a creative ' 'workshop in a local care home.', 'I will donate to support Inspire North with their work in offering services and accredited training in' ' mental health, wellbeing, housing and domestic abuse to the community.', 'I will donate to support Inspire North to help someone experiencing homelessness or domestic abuse.', 'I will donate to support Inspire North to provide a wide range of life-changing mental health and wellbeing ' 'services.', ] # charity_list_dic is used for treatment 2. # name is used to creat fields and labels to display it on html file. charity_list_dic = [ dict(name='charity_0', label="I will donate to support Breast Cancer UK in their education, research and campaigning work to " "prevent more cases of breast cancer."), dict(name='charity_1', label="I will donate to support Breast Cancer UK’s research into the effect of bisphenols (chemicals used in " "certain everyday plastics) on breast cancer development."), dict(name='charity_2', label="I will donate to support The Citizens Foundation (UK) to fund high quality, life changing education for " "underprivileged children in Pakistan."), dict(name='charity_3', label="I will donate to support The Citizens Foundation (UK) in covering the operating expenses of a school " "unit."), dict(name='charity_4', label="I will donate to support The Citizens Foundation (UK) with their Female Empowerment Fund to educate and " "empower women in the community."), dict(name='charity_5', label="I will donate to support I will donate to support The Citizens Foundation (UK) with their " "Alumni Scholarship Fund to provide " "higher education scholarships to promising TCF graduates."), dict(name='charity_6', label="I will donate to support ARHC to fund care and support for their patients and their " "families."), dict(name='charity_7', label="I will donate to support ARHC in meeting the daily cost of home-cooked meals for " "patients."), dict(name='charity_8', label="I will donate to support ARHC to cover the costs of clinical uniforms for their frontline " "teams."), dict(name='charity_9', label="I will donate to ARHC help someone who has been bereaved, by organising a counselling session."), dict(name='charity_10', label="I will donate to support Ovacome to cover the cost of sending information booklets to " "someone who has just " "been diagnosed with ovarian cancer."), dict(name='charity_11', label="I will donate to support Ovacome with providing an hour of 1-1 specialist support for " "someone affected " "by ovarian cancer."), dict(name='charity_12', label="I will donate to support Ovacome to pay for a live webinar with a leading clinician " "in the field of ovarian " "cancer."), dict(name='charity_13', label="I will donate to support Ovacome in providing support and information to anyone affected " "by ovarian cancer."), dict(name='charity_14', label="I will donate to support Chichester Festival Theatre with their Ageless Campaign for access to the" " theatre and live art for people who may not find it easy to get involved in theatre," " including older people at risk of isolation."), dict(name='charity_15', label="I will donate to support Chichester Festival Theatre to buy art materials for their intergenerational " "workshops."), dict(name='charity_16', label="I will donate to support Chichester Festival Theatre to buy musical instruments for their dementia " "friendly singing groups."), dict(name='charity_17', label="I will donate to support Chichester Festival Theatre to buy cast lists in braille for use by their " "visually impaired customers."), dict(name='charity_18', label="I will donate to support Chichester Festival Theatre to appoint a specialist practitioner to run a " "creative workshop in a local care home."), dict(name='charity_19', label="I will donate to support Inspire North with their work in offering services and accredited " "training in " "mental health, wellbeing, housing and domestic abuse to the community."), dict(name='charity_20', label="I will donate to support Inspire North to help someone experiencing homelessness or domestic abuse."), dict(name='charity_21', label="I will donate to support Inspire North to provide a wide range of life-changing mental health and " "wellbeing services."), ] total_charity = len(charity_list) # Treatment 1 one_in_one = 1 one_in_two = 2 one_in_five = 5 one_in_ten = 10 one_in_twenty = 20 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): # dropout detection, From otree-snippets is_dropout = models.BooleanField(initial=False) # players are randomly assigned to be in treatment 1 or 2 assigned_treatment = models.IntegerField() assigned_order = models.IntegerField() # this field record happiness f_int1 = models.IntegerField(blank=False, min=0, default=0) f_int2 = models.IntegerField(blank=False, min=0, default=0) f_int3 = models.IntegerField(blank=False, min=0, default=0) f_int4 = models.IntegerField(blank=False, min=0, default=0) f_int5 = models.IntegerField(blank=False, min=0, default=0) f_int6 = models.IntegerField(blank=False, min=0, default=0) f_int7 = models.IntegerField(blank=False, min=0, default=0) f_int8 = models.IntegerField(blank=False, min=0, default=0) f_int9 = models.IntegerField(blank=False, min=0, default=0) f_int10 = models.IntegerField(blank=False, min=0, default=0) # the following fields collects the random number generated in creating_session. # Format of the names options_one_in_two // options_two_in_two etc. options11 = models.PositiveIntegerField() options12 = models.PositiveIntegerField() options22 = models.PositiveIntegerField() options15 = models.PositiveIntegerField() options25 = models.PositiveIntegerField() options35 = models.PositiveIntegerField() options45 = models.PositiveIntegerField() options55 = models.PositiveIntegerField() options110 = models.PositiveIntegerField() options210 = models.PositiveIntegerField() options310 = models.PositiveIntegerField() options410 = models.PositiveIntegerField() options510 = models.PositiveIntegerField() options610 = models.PositiveIntegerField() options710 = models.PositiveIntegerField() options810 = models.PositiveIntegerField() options910 = models.PositiveIntegerField() options1010 = models.PositiveIntegerField() options120 = models.PositiveIntegerField() options220 = models.PositiveIntegerField() options320 = models.PositiveIntegerField() options420 = models.PositiveIntegerField() options520 = models.PositiveIntegerField() options620 = models.PositiveIntegerField() options720 = models.PositiveIntegerField() options820 = models.PositiveIntegerField() options920 = models.PositiveIntegerField() options1020 = models.PositiveIntegerField() options1120 = models.PositiveIntegerField() options1220 = models.PositiveIntegerField() options1320 = models.PositiveIntegerField() options1420 = models.PositiveIntegerField() options1520 = models.PositiveIntegerField() options1620 = models.PositiveIntegerField() options1720 = models.PositiveIntegerField() options1820 = models.PositiveIntegerField() options1920 = models.PositiveIntegerField() options2020 = models.PositiveIntegerField() # these fields record the selected charity in treatment 1 choice11 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") choice12 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") choice15 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") choice110 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") choice120 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") # these fields record the selected charity in treatment 2 # in a hidden field. their number shows the rank of display choice2_11 = models.BooleanField(blank=True) choice2_12 = models.BooleanField(blank=True) choice2_22 = models.BooleanField(blank=True) choice2_15 = models.BooleanField(blank=True) choice2_25 = models.BooleanField(blank=True) choice2_35 = models.BooleanField(blank=True) choice2_45 = models.BooleanField(blank=True) choice2_55 = models.BooleanField(blank=True) choice2_110 = models.BooleanField(blank=True) choice2_210 = models.BooleanField(blank=True) choice2_310 = models.BooleanField(blank=True) choice2_410 = models.BooleanField(blank=True) choice2_510 = models.BooleanField(blank=True) choice2_610 = models.BooleanField(blank=True) choice2_710 = models.BooleanField(blank=True) choice2_810 = models.BooleanField(blank=True) choice2_910 = models.BooleanField(blank=True) choice2_1010 = models.BooleanField(blank=True) choice2_120 = models.BooleanField(blank=True) choice2_220 = models.BooleanField(blank=True) choice2_320 = models.BooleanField(blank=True) choice2_420 = models.BooleanField(blank=True) choice2_520 = models.BooleanField(blank=True) choice2_620 = models.BooleanField(blank=True) choice2_720 = models.BooleanField(blank=True) choice2_820 = models.BooleanField(blank=True) choice2_920 = models.BooleanField(blank=True) choice2_1020 = models.BooleanField(blank=True) choice2_1120 = models.BooleanField(blank=True) choice2_1220 = models.BooleanField(blank=True) choice2_1320 = models.BooleanField(blank=True) choice2_1420 = models.BooleanField(blank=True) choice2_1520 = models.BooleanField(blank=True) choice2_1620 = models.BooleanField(blank=True) choice2_1720 = models.BooleanField(blank=True) choice2_1820 = models.BooleanField(blank=True) choice2_1920 = models.BooleanField(blank=True) choice2_2020 = models.BooleanField(blank=True) # these fields collect the amount of donation, entered by the subjects: # in treatment 1 # in treatment 2 amount1_11 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount1_12 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount1_15 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount1_110 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount1_120 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") # in treatment 2 no_donation2_1 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") no_donation2_2 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") no_donation2_5 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") no_donation2_10 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") no_donation2_20 = models.StringField(blank=False, widget=widgets.RadioSelect, label=" ") # each page with the listed charities needs its own field. # page 1: 1 listed, page 2: 2 listed, ... 1 + 2 + 5 + 10 + 20=38 amount2_11 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_21 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_22 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_15 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_25 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_35 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_45 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_55 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_110 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_210 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_310 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_410 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_510 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_610 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_710 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_810 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_910 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1010 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_120 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_220 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_320 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_420 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_520 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_620 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_720 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_820 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_920 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1020 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1120 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1220 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1320 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1420 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1520 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1620 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1720 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1820 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_1920 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") amount2_2020 = models.PositiveIntegerField(blank=True, min=0, max=C.TOKEN, default=0, label="Amount of tokens") # FUNCTIONS # with this function, each player gets a randomised charity list # the list is the same across treatments 1 and treatment 2 # this way we can collect the order of options on the screen. # some of the options might be repeated among: # one_in_one, one_in_two, one_in_five, one_in_ten and for sure in one_in_twenty def creating_session(subsession: Subsession): # Experimental pre checks: # browser checks, screen checks, audio checks, attention pledges # author: erkalkohxu # TBC # for player in subsession.get_players(): # player.participant.is_dropout = False # print('set player.participant.is_dropout', player.participant.is_dropout) # import time # player.participant.expiry = time.time() + player.session.config['task_round_timeout_seconds'] # print('set player.participant.expiry', player.participant.expiry) current_round = subsession.round_number if subsession.round_number == 1: # random_numbertest=random.sample(range(1, C.total_charity), C.three_in_five) for p in subsession.get_players(): participant = p.participant participant.vars['assigned_treatment'] = random.choice(C.TREATMENTS) participant.vars['assigned_order'] = random.choice(C.TASKS) p.assigned_treatment = participant.vars['assigned_treatment'] p.assigned_order = participant.vars['assigned_order'] participant.vars['kept'] = [] participant.vars['donate'] = [] # print('Treatment is', participant.vars['assigned_treatment'], # 'and task is', participant.vars['assigned_order']) # it's needed to generate a random number for all 25 rounds. # just check how we can recover charities name etc. from that for p in subsession.get_players(): participant = p.participant # p.participant.random_number11 = {} # participant.vars['random_number11'] = [] # generates random numbers for number of players*number of rounds participant.random_number11 = random.sample(range(1, C.total_charity), C.one_in_one) p.options11 = participant.random_number11[0] # print('subsession.round_number', subsession.round_number, 'participant', participant, # participant.random_number11) # participant.random_number12 = random.sample(range(1, C.total_charity), C.one_in_two) p.options12 = participant.random_number12[0] p.options22 = participant.random_number12[1] # participant.random_number15 = random.sample(range(1, C.total_charity), C.one_in_five) p.options15 = participant.random_number15[0] p.options25 = participant.random_number15[1] p.options35 = participant.random_number15[2] p.options45 = participant.random_number15[3] p.options55 = participant.random_number15[4] # participant.random_number110 = random.sample(range(1, C.total_charity), C.one_in_ten) p.options110 = participant.random_number110[0] p.options210 = participant.random_number110[1] p.options310 = participant.random_number110[2] p.options410 = participant.random_number110[3] p.options510 = participant.random_number110[4] p.options610 = participant.random_number110[5] p.options710 = participant.random_number110[6] p.options810 = participant.random_number110[7] p.options910 = participant.random_number110[8] p.options1010 = participant.random_number110[9] # participant.random_number120 = random.sample(range(1, C.total_charity), C.one_in_twenty) p.options120 = participant.random_number120[0] p.options220 = participant.random_number120[1] p.options320 = participant.random_number120[2] p.options420 = participant.random_number120[3] p.options520 = participant.random_number120[4] p.options620 = participant.random_number120[5] p.options720 = participant.random_number120[6] p.options820 = participant.random_number120[7] p.options920 = participant.random_number120[8] p.options1020 = participant.random_number120[9] p.options1120 = participant.random_number120[10] p.options1220 = participant.random_number120[11] p.options1320 = participant.random_number120[12] p.options1420 = participant.random_number120[13] p.options1520 = participant.random_number120[14] p.options1620 = participant.random_number120[15] p.options1720 = participant.random_number120[16] p.options1820 = participant.random_number120[17] p.options1920 = participant.random_number120[18] p.options2020 = participant.random_number120[19] def set_payoffs(player: Player): import math total_payoff_t = sum(player.participant.vars['kept']) total_donate_t = sum(player.participant.vars['donate']) total_payoff_tc = total_payoff_t / C.conversion_rate total_donate_tc = total_donate_t / C.conversion_rate total_payoff_p = round(total_payoff_tc, 2) total_donate_p = round(total_donate_tc, 2) # player.payoff = total_payoff_p # print('Partcipant', player.participant, 'amount', player.participant.vars['kept']) # these are functions to specify options def no_donation2_1_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['Y', 'I will donate to the following charity/charities: '] ] def no_donation2_2_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['Y', 'I will donate to the following charity/charities: '] ] def no_donation2_5_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['Y', 'I will donate to the following charity/charities:'] ] def no_donation2_10_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['Y', 'I will donate to the following charity/charities: '] ] def no_donation2_20_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['Y', 'I will donate to the following charity/charities: '] ] def choice11_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['0', C.charity_list[player.options11]], ] def choice12_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['0', C.charity_list[player.options12]], ['1', C.charity_list[player.options22]], ] def choice15_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['0', C.charity_list[player.options15]], ['1', C.charity_list[player.options25]], ['2', C.charity_list[player.options35]], ['3', C.charity_list[player.options45]], ['4', C.charity_list[player.options55]], ] def choice110_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['0', C.charity_list[player.options110]], ['1', C.charity_list[player.options210]], ['2', C.charity_list[player.options310]], ['3', C.charity_list[player.options410]], ['4', C.charity_list[player.options510]], ['5', C.charity_list[player.options610]], ['6', C.charity_list[player.options710]], ['7', C.charity_list[player.options810]], ['8', C.charity_list[player.options910]], ['9', C.charity_list[player.options1010]], ] # MustCopyError: Cannot modify a list that originated in your constants class. # First, you must make a copy of it, # e.g. mylist.copy() This is to prevent accidentally modifying the original list. def choice120_choices(player: Player): return [ ['N', 'I will not donate on this occasion.'], ['0', C.charity_list[player.options120]], ['1', C.charity_list[player.options220]], ['2', C.charity_list[player.options320]], ['3', C.charity_list[player.options420]], ['4', C.charity_list[player.options520]], ['5', C.charity_list[player.options620]], ['6', C.charity_list[player.options720]], ['7', C.charity_list[player.options820]], ['8', C.charity_list[player.options920]], ['9', C.charity_list[player.options1020]], ['10', C.charity_list[player.options1120]], ['11', C.charity_list[player.options1220]], ['12', C.charity_list[player.options1320]], ['13', C.charity_list[player.options1420]], ['14', C.charity_list[player.options1520]], ['15', C.charity_list[player.options1620]], ['16', C.charity_list[player.options1720]], ['17', C.charity_list[player.options1820]], ['18', C.charity_list[player.options1920]], ['19', C.charity_list[player.options2020]], ] # ------------------------------------------------------------------------- # PAGES # ------------------------------------------------------------------------- class Instruction(Page): pass class CharityInfo(Page): pass # one page for them to read. # making a hyperlink, to remind them. needed? class Checkpoints(Page): pass # 20 tasks, maybe an attention check after task 12/15 # ------------------------------------------------------------------------- # OneIn: Ascending order and descending order # ------------------------------------------------------------------------- class MyPageOneInOne(Page): form_model = 'player' form_fields = [ 'choice11', 'amount1_11'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number < 5 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return 20 < player.round_number < 25 @staticmethod def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append(player.amount1_11) participant.vars['kept'].append(100 - player.amount1_11) @staticmethod def error_message(player: Player, values): if values['amount1_11'] is None: return 'Amount of tokens in the box cannot be empty. ' \ 'Put 0 if you do not want to donate.' # alternatively, you could make quiz1_error_message, quiz2_error_message, etc. # but if you have many similar fields, this is more efficient. solutions = dict(choice11='N') # error_message can return a dict whose keys are field names and whose # values are error messages errors = {f: 'You have selected: I will not want to donate. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount1_11'] != 0: return errors if errors_d and \ values['amount1_11'] == 0: return errors_d class MyPageOneInOnefint1(Page): form_model = 'player' form_fields = ['f_int1'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 5 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 25 class MyPageOneInTwo(Page): form_model = 'player' form_fields = ['choice12', 'amount1_12'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return 5 < player.round_number < 10 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return 15 < player.round_number < 20 def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append(player.amount1_12) participant.vars['kept'].append(100 - player.amount1_12) # player.payoff = C.ENDOWMENT_TOTAL - sum(participant.vars['donate']) @staticmethod def error_message(player: Player, values): if values['amount1_12'] is None: return 'Amount of tokens in the box cannot be empty. ' \ 'Put 0 if you do not want to donate.' solutions = dict(choice12='N') # error_message can return a dict whose keys are field names and whose # values are error messages errors = { f: 'You have selected: I will not donate on this occasion. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount1_12'] != 0: return errors if errors_d and \ values['amount1_12'] == 0: return errors_d class MyPageOneInTwofint2(Page): form_model = 'player' form_fields = ['f_int2'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 10 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 20 class MyPageOneInFive(Page): form_model = 'player' form_fields = ['choice15', 'amount1_15'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return 10 < player.round_number < 15 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return 10 < player.round_number < 15 def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append(player.amount1_15) participant.vars['kept'].append(100 - player.amount1_15) player.payoff = C.ENDOWMENT_TOTAL - sum(participant.vars['donate']) @staticmethod def error_message(player: Player, values): if values['amount1_15'] is None: return 'Amount of tokens in the box cannot be empty. ' \ 'Put 0 if you do not want to donate.' solutions = dict(choice15='N') # error_message can return a dict whose keys are field names and whose # values are error messages errors = { f: 'You have selected: I will not donate on this occasion. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount1_15'] != 0: return errors if errors_d and \ values['amount1_15'] == 0: return errors_d class MyPageOneInFivefint3(Page): form_model = 'player' form_fields = ['f_int3'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 15 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 15 class MyPageOneInTen(Page): form_model = 'player' form_fields = ['choice110', 'amount1_110'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return 15 < player.round_number < 20 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return 5 < player.round_number < 10 def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append(player.amount1_110) participant.vars['kept'].append(100 - player.amount1_110) # player.payoff = C.ENDOWMENT_TOTAL - sum(participant.vars['donate']) @staticmethod def error_message(player: Player, values): if values['amount1_110'] is None: return 'Amount of tokens in the box cannot be empty. ' \ 'Put 0 if you do not want to donate.' solutions = dict(choice110='N') # error_message can return a dict whose keys are field names and whose # values are error messages errors = { f: 'You have selected: I will not donate on this occasion. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount1_110'] != 0: return errors if errors_d and \ values['amount1_110'] == 0: return errors_d class MyPageOneInTenfint4(Page): form_model = 'player' form_fields = ['f_int4'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 20 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 10 class MyPageOneInTwenty(Page): form_model = 'player' form_fields = ['choice120', 'amount1_120'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return 20 < player.round_number < 25 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number < 5 def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append(player.amount1_120) participant.vars['kept'].append(100 - player.amount1_120) # player.payoff = C.ENDOWMENT_TOTAL - sum(participant.vars['donate']) @staticmethod def error_message(player: Player, values): if values['amount1_120'] is None: return 'Amount of tokens in the box cannot be empty. ' \ 'Put 0 if you do not want to donate.' solutions = dict(choice120='N') # error_message can return a dict whose keys are field names and whose # values are error messages errors = { f: 'You have selected: I will not donate on this occasion. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount1_120'] != 0: return errors if errors_d and \ values['amount1_120'] == 0: return errors_d class MyPageOneInTwentyfint5(Page): form_model = 'player' form_fields = ['f_int5'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 25 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 1: return player.round_number == 5 # ------------------------------------------------------------------------- # Many In # ------------------------------------------------------------------------- # the following pages are for treatment 2 class MyPageManyInOne(Page): form_model = 'player' form_fields = ['amount2_11', 'choice2_11', 'no_donation2_1'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number < 5 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return 20 < player.round_number < 25 # form_fields = ['amount2_{}'.format(n) for n in range(1, C.NUMBERS2[1])] # to collect labels @staticmethod def vars_for_template(player: Player): participant = player.participant return {'CharityOptions11': C.charity_list_dic[player.options11] } def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append(player.amount2_11) participant.vars['kept'].append(100 - player.amount2_11) @staticmethod def error_message(player: Player, values): if values['amount2_11'] is None: return 'Amount of tokens in the box cannot be empty. If you do not want to donate, put 0 in donation boxes.' solutions = dict(no_donation2_1='N') # error_message can return a dict whose keys are field names and whose # values are error messages errors = { f: 'You have selected: I will not donate on this occasion. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount2_11'] != 0: return errors if errors_d and \ values['amount2_11'] == 0: return errors_d class MyPageManyInOnefint6(Page): form_model = 'player' form_fields = ['f_int6'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 5 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 25 class MyPageManyInTwo(Page): form_model = 'player' # form_fields=['amount2_{}'.format(n) for n in range(C.NUMBERS2[1], C.NUMBERS2[3])] form_fields = ['amount2_21', 'amount2_22', 'choice2_12', 'choice2_22', 'no_donation2_2'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return 5 < player.round_number < 10 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return 15 < player.round_number < 20 # to collect labels # now i need to calculate payoffs. try for fields in form-fields @staticmethod def vars_for_template(player: Player): participant = player.participant return {'CharityOptions12': C.charity_list_dic[player.options12], 'CharityOptions22': C.charity_list_dic[player.options22] } @staticmethod def error_message(player: Player, values): if values['amount2_21'] is None or values['amount2_22'] is None: return 'Amount of tokens in the box cannot be empty. If you do not want to donate, put 0 in donation boxes.' if values['amount2_21'] + values['amount2_22'] > 100: return 'Total Amount of tokens cannot be larger than 100 tokens.' solutions = dict(no_donation2_2='N') errors = { f: 'You have selected: I will not donate on this occasion. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity/charities to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount2_21'] + values['amount2_22'] != 0: return errors if errors_d and \ values['amount2_21'] + values['amount2_22'] == 0: return errors_d # @staticmethod # def error_message(player, values): # # print('values is', values) # # validate the total sum # if values['amount2_21'] is None or values['amount2_22'] is None: # return 'Please enter amount of tokens.' # if values['amount2_21'] + values['amount2_22'] > 100: # return 'Total Amount of tokens cannot be larger than 100 tokens.' def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append(sum((player.amount2_21, player.amount2_22))) participant.vars['kept'].append( 100 - sum((player.amount2_21, player.amount2_22))) class MyPageManyInTwofint7(Page): form_model = 'player' form_fields = ['f_int7'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 10 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 20 class MyPageManyInFive(Page): form_model = 'player' # form_fields = ['amount2_{}'.format(n) for n in range(C.NUMBERS2[3], C.NUMBERS2[8])] form_fields = ['amount2_15', 'amount2_25', 'amount2_35', 'amount2_45', 'amount2_55', 'choice2_15', 'choice2_25', 'choice2_35', 'choice2_45', 'choice2_55', 'no_donation2_5'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return 10 < player.round_number < 15 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return 10 < player.round_number < 15 # to collect labels @staticmethod def vars_for_template(player: Player): participant = player.participant return {'CharityOptions15': C.charity_list_dic[player.options15], 'CharityOptions25': C.charity_list_dic[player.options25], 'CharityOptions35': C.charity_list_dic[player.options35], 'CharityOptions45': C.charity_list_dic[player.options45], 'CharityOptions55': C.charity_list_dic[player.options55], } @staticmethod def error_message(player: Player, values): if values['amount2_15'] is None or values['amount2_25'] is None or \ values['amount2_35'] is None or values['amount2_45'] is None or \ values['amount2_55'] is None: return 'Amount of tokens in the box cannot be empty.' if values['amount2_15'] + values['amount2_25'] + \ values['amount2_35'] + values['amount2_45'] + \ values['amount2_55'] > 100: return 'Total Amount of tokens cannot be larger than 100 tokens.' solutions = dict(no_donation2_5='N') errors = { f: 'You have selected: I will not donate on this occasion. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity/charities to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount2_15'] + values['amount2_25'] + \ values['amount2_35'] + values['amount2_45'] + \ values['amount2_55'] != 0: return errors if errors_d and \ values['amount2_15'] + values['amount2_25'] + \ values['amount2_35'] + values['amount2_45'] + \ values['amount2_55'] == 0: return errors_d def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append( sum((player.amount2_15, player.amount2_25, player.amount2_35, player.amount2_45, player.amount2_55))) participant.vars['kept'].append( 100 - sum((player.amount2_15, player.amount2_25, player.amount2_35, player.amount2_45, player.amount2_55))) class MyPageManyInFivefint8(Page): form_model = 'player' form_fields = ['f_int8'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 15 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 15 class MyPageManyInTen(Page): form_model = 'player' # form_fields = ['amount2_{}'.format(n) for n in range(C.NUMBERS2[8], C.NUMBERS2[18])] form_fields = ['amount2_110', 'amount2_210', 'amount2_310', 'amount2_410', 'amount2_510', 'amount2_610', 'amount2_710', 'amount2_810', 'amount2_910', 'amount2_1010', 'choice2_110', 'choice2_210', 'choice2_310', 'choice2_410', 'choice2_510', 'choice2_610', 'choice2_710', 'choice2_810', 'choice2_910', 'choice2_1010', 'no_donation2_10'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return 15 < player.round_number < 20 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return 5 < player.round_number < 10 # to collect labels @staticmethod def vars_for_template(player: Player): participant = player.participant return {'CharityOptions110': C.charity_list_dic[player.options110], 'CharityOptions210': C.charity_list_dic[player.options210], 'CharityOptions310': C.charity_list_dic[player.options310], 'CharityOptions410': C.charity_list_dic[player.options410], 'CharityOptions510': C.charity_list_dic[player.options510], 'CharityOptions610': C.charity_list_dic[player.options610], 'CharityOptions710': C.charity_list_dic[player.options710], 'CharityOptions810': C.charity_list_dic[player.options810], 'CharityOptions910': C.charity_list_dic[player.options910], 'CharityOptions1010': C.charity_list_dic[player.options1010], } @staticmethod def error_message(player: Player, values): if values['amount2_110'] is None or values['amount2_210'] is None or \ values['amount2_310'] is None or values['amount2_410'] is None or \ values['amount2_510'] is None or values['amount2_610'] is None or \ values['amount2_710'] is None or values['amount2_810'] is None or \ values['amount2_910'] is None or values['amount2_1010'] is None: return 'Amount of tokens in the box cannot be empty. If you do not want to donate, put 0 in donation boxes.' if values['amount2_110'] + values['amount2_210'] + \ values['amount2_310'] + values['amount2_410'] + \ values['amount2_510'] + values['amount2_610'] + \ values['amount2_710'] + values['amount2_810'] + \ values['amount2_910'] + values['amount2_1010'] > 100: return 'Total Amount of tokens cannot be larger than 100 tokens.' solutions = dict(no_donation2_10='N') errors = { f: 'You have selected: I will not donate on this occasion. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity/charities to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount2_110'] + values['amount2_210'] + \ values['amount2_310'] + values['amount2_410'] + \ values['amount2_510'] + values['amount2_610'] + \ values['amount2_710'] + values['amount2_810'] + \ values['amount2_910'] + values['amount2_1010'] != 0: return errors if errors_d and \ values['amount2_110'] + values['amount2_210'] + \ values['amount2_310'] + values['amount2_410'] + \ values['amount2_510'] + values['amount2_610'] + \ values['amount2_710'] + values['amount2_810'] + \ values['amount2_910'] + values['amount2_1010'] == 0: return errors_d def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append(sum((player.amount2_110, player.amount2_210, player.amount2_310, player.amount2_410, player.amount2_410, player.amount2_610, player.amount2_510, player.amount2_810, player.amount2_610, player.amount2_1010))) participant.vars['kept'].append(100 - sum((player.amount2_110, player.amount2_210, player.amount2_310, player.amount2_410, player.amount2_410, player.amount2_610, player.amount2_510, player.amount2_810, player.amount2_610, player.amount2_1010 ))) class MyPageManyInTenfint9(Page): form_model = 'player' form_fields = ['f_int9'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 20 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 10 class MyPageManyInTwenty(Page): form_model = 'player' # form_fields = ['amount2_{}'.format(n) for n in range(C.NUMBERS2[18], C.NUMBERS2[38])] form_fields = ['amount2_120', 'amount2_220', 'amount2_320', 'amount2_420', 'amount2_520', 'amount2_620', 'amount2_720', 'amount2_820', 'amount2_920', 'amount2_1020', 'amount2_1120', 'amount2_1220', 'amount2_1320', 'amount2_1420', 'amount2_1520', 'amount2_1620', 'amount2_1720', 'amount2_1820', 'amount2_1920', 'amount2_2020', 'choice2_120', 'choice2_220', 'choice2_320', 'choice2_420', 'choice2_520', 'choice2_620', 'choice2_720', 'choice2_820', 'choice2_920', 'choice2_1020', 'choice2_1120', 'choice2_1220', 'choice2_1320', 'choice2_1420', 'choice2_1520', 'choice2_1620', 'choice2_1720', 'choice2_1820', 'choice2_1920', 'choice2_2020', 'no_donation2_20'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return 20 < player.round_number < 25 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number < 5 # to collect labels @staticmethod def vars_for_template(player: Player): participant = player.participant return {'CharityOptions120': C.charity_list_dic[player.options120], 'CharityOptions220': C.charity_list_dic[player.options220], 'CharityOptions320': C.charity_list_dic[player.options320], 'CharityOptions420': C.charity_list_dic[player.options420], 'CharityOptions520': C.charity_list_dic[player.options520], 'CharityOptions620': C.charity_list_dic[player.options620], 'CharityOptions720': C.charity_list_dic[player.options720], 'CharityOptions820': C.charity_list_dic[player.options820], 'CharityOptions920': C.charity_list_dic[player.options920], 'CharityOptions1020': C.charity_list_dic[player.options1020], 'CharityOptions1120': C.charity_list_dic[player.options1120], 'CharityOptions1220': C.charity_list_dic[player.options1220], 'CharityOptions1320': C.charity_list_dic[player.options1320], 'CharityOptions1420': C.charity_list_dic[player.options1420], 'CharityOptions1520': C.charity_list_dic[player.options1520], 'CharityOptions1620': C.charity_list_dic[player.options1620], 'CharityOptions1720': C.charity_list_dic[player.options1720], 'CharityOptions1820': C.charity_list_dic[player.options1820], 'CharityOptions1920': C.charity_list_dic[player.options1920], 'CharityOptions2020': C.charity_list_dic[player.options2020], } @staticmethod def error_message(player: Player, values): if values['amount2_120'] is None or values['amount2_220'] is None or \ values['amount2_320'] is None or values['amount2_420'] is None or \ values['amount2_520'] is None or values['amount2_620'] is None or \ values['amount2_720'] is None or values['amount2_820'] is None or \ values['amount2_920'] is None or values['amount2_1020'] is None or \ values['amount2_1120'] is None or values['amount2_1220'] is None or \ values['amount2_1320'] is None or values['amount2_1420'] is None or \ values['amount2_1520'] is None or values['amount2_1620'] is None or \ values['amount2_1720'] is None or values['amount2_1820'] is None or \ values['amount2_1920'] is None or values['amount2_2020'] is None: return 'Amount of tokens in the box cannot be empty. If you do not want to donate, put 0 in donation boxes.' if values['amount2_120'] + values['amount2_220'] + \ values['amount2_320'] + values['amount2_420'] + \ values['amount2_520'] + values['amount2_620'] + \ values['amount2_720'] + values['amount2_820'] + \ values['amount2_920'] + values['amount2_1020'] + \ values['amount2_1120'] + values['amount2_1220'] + \ values['amount2_1320'] + values['amount2_1420'] + \ values['amount2_1520'] + values['amount2_1620'] + \ values['amount2_1720'] + values['amount2_1820'] + \ values['amount2_1920'] + values['amount2_2020'] > 100: return 'Total Amount of tokens cannot be larger than 100 tokens.' solutions = dict(no_donation2_20='N') errors = { f: 'You have selected: I will not donate on this occasion. But you have put a number in the donation box.' for f in solutions if values[f] == solutions[f]} errors_d = {f: 'You selected a charity/charities to donate, but you put 0 in the donation box.' for f in solutions if values[f] != solutions[f]} if errors and \ values['amount2_120'] + values['amount2_220'] + \ values['amount2_320'] + values['amount2_420'] + \ values['amount2_520'] + values['amount2_620'] + \ values['amount2_720'] + values['amount2_820'] + \ values['amount2_920'] + values['amount2_1020'] + \ values['amount2_1120'] + values['amount2_1220'] + \ values['amount2_1320'] + values['amount2_1420'] + \ values['amount2_1520'] + values['amount2_1620'] + \ values['amount2_1720'] + values['amount2_1820'] + \ values['amount2_1920'] + values['amount2_2020'] != 0: return errors if errors_d and \ values['amount2_120'] + values['amount2_220'] + \ values['amount2_320'] + values['amount2_420'] + \ values['amount2_520'] + values['amount2_620'] + \ values['amount2_720'] + values['amount2_820'] + \ values['amount2_920'] + values['amount2_1020'] + \ values['amount2_1120'] + values['amount2_1220'] + \ values['amount2_1320'] + values['amount2_1420'] + \ values['amount2_1520'] + values['amount2_1620'] + \ values['amount2_1720'] + values['amount2_1820'] + \ values['amount2_1920'] + values['amount2_2020'] == 0: return errors_d def before_next_page(player: Player, timeout_happened): participant = player.participant participant.vars['donate'].append(sum((player.amount2_120, player.amount2_220, player.amount2_320, player.amount2_420, player.amount2_420, player.amount2_620, player.amount2_520, player.amount2_820, player.amount2_620, player.amount2_1020, player.amount2_1120, player.amount2_1220, player.amount2_1320, player.amount2_1420, player.amount2_1520, player.amount2_1620, player.amount2_1720, player.amount2_1820, player.amount2_1920, player.amount2_2020,))) participant.vars['kept'].append(100 - sum((player.amount2_120, player.amount2_220, player.amount2_320, player.amount2_420, player.amount2_420, player.amount2_620, player.amount2_520, player.amount2_820, player.amount2_620, player.amount2_1020, player.amount2_1120, player.amount2_1220, player.amount2_1320, player.amount2_1420, player.amount2_1520, player.amount2_1620, player.amount2_1720, player.amount2_1820, player.amount2_1920, player.amount2_2020, ))) class MyPageManyInTwentyfint10(Page): form_model = 'player' form_fields = ['f_int10'] @staticmethod def is_displayed(player: Player): if player.participant.vars['assigned_order'] == 1 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 25 if player.participant.vars['assigned_order'] == 2 \ and player.participant.vars['assigned_treatment'] == 2: return player.round_number == 5 class App_pay(Page): @staticmethod def before_next_page(player: Player, timeout_happened): set_payoffs(player) @staticmethod def vars_for_template(player: Player): participant = player.participant participant.payoff = sum(participant.vars['kept']) return dict( # Pays = set_payoffs, total_payoff=sum(participant.vars['kept']), total_donate=sum(participant.vars['donate']), redemption_code=participant.label or participant.code ) class TimerSoft(Page): pass class Page1(Page): timeout_seconds = 10 @staticmethod def is_displayed(player: Player): return player.round_number == 26 @staticmethod def before_next_page(player: Player, timeout_happened): # note: codes come from bugfix if timeout_happened: player.is_dropout = True class ByeDropout(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 27: return player.is_dropout @staticmethod def error_message(player: Player, values): return "Cannot proceed past this page" class Page2(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 28: return player.is_dropout page_sequence = [ MyPageManyInOne, MyPageManyInOnefint6, MyPageManyInTwo, MyPageManyInTwofint7, MyPageManyInFive, MyPageManyInFivefint8, MyPageManyInTen, MyPageManyInTenfint9, MyPageManyInTwenty, MyPageManyInTwentyfint10, MyPageOneInOne, MyPageOneInOnefint1, MyPageOneInTwo, MyPageOneInTwofint2, MyPageOneInFive, MyPageOneInFivefint3, MyPageOneInTen, MyPageOneInTenfint4, MyPageOneInTwenty, MyPageOneInTwentyfint5, ]