from otree.api import * import random from pprint import pprint import json from ast import literal_eval doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'questions' PLAYERS_PER_GROUP = None NUM_ROUNDS = 57 ## this will have to be 57 OBJECTS = { "Measuring Tape": {"info1": "1.5m long", "info2": "cm and inches", "info3": "Retractable and flexible", "name": "Measuring Tape", "img": "objects/Measuring-Tape.jpg", }, "Cutlery": {"info1": "Plastic", "info2": "Reusable", "info3": "Case dimensions: 21 x 6 x 2.5 cm", "name": "Cutlery", "img": "objects/Cutlery.jpg", }, "Bottle": {"info1": "BPA-free", "info2": "Flexible silicone", "info3": "21 oz capacity", "name": "Bottle", "img": "objects/Bottle.jpg", }, "Notebook": {"info1": "320 lined pages", "info2": "Vegan leather", "info3": "14.6 x 21 cm", "name": "Notebook", "img": "objects/Notebook.jpg", }, "Battery": {"info1": "10,000 mAh (2.25 charges for iPhone 12, 1.6 charges for Galaxy S20)", "info2": "Overcharge protection", "info3": "Temperature control", "name": "Battery", "img": "objects/Battery.jpg", }, "Blender": {"info1": "1.9L capacity", "info2": "450W", "info3": "16.4D x 19.2W x 27.7H cm", "name": "Blender", "img": "objects/Blender.jpg", }, "Speaker": {"info1": "Bluetooth speaker", "info2": "66ft range", "info3": "24h battery life", "name": "Speaker", "img": "objects/Speaker.jpg", }, "Air Frier": {"info1": "4.3L capacity", "info2": "1500W", "info3": "29D x 36.5W x 32.5H cm", "name": "Air Frier", "img": "objects/Air-Frier.jpg", }, "Forty": {"info1": "", "info2": "", "info3": "", "name": "£40 in cash", "img": "objects/Forty.jpg", }, "Thirty": {"info1": "", "info2": "", "info3": "", "name": "£30 in cash", "img": "objects/Thirty.jpg", }, "Nothing": {"info1": "", "info2": "", "info3": "", "name": "nothing", "img": "objects/Nothing.jpg", }, } #Participants will be split into two groups, which will each see a combination of object pairs ## Group A will see (1,2) (4,6) (5,8) and (3,7) ## Group B will see (7,8) (3,5) (1,4) and (2,6) # The first object in the pair will be the L(eft object), and the second, the R(ight object). ## Although left/right order will be randomised later on. ## And the final data will be uniformly coded. # For Group A: ## Best_a and Worst_a object in the pair #Ba = [1,4,5,3] #Wa = [2,6,8,7] # For Group B: #Bb = [7,3,1,2] #Wb = [8,5,4,6] ## FOR EACH PAIR, 48 lotteries # + 4 binary choice pair # + 2 CRE (£30,£40 - obj 10,9 - SU+SD) # + 3 dominance, where the first, fifth, and eight items on the ranking at 100, 50 and 25% prob respectively are put vs 100% nothing # object nr 11 is NOTHING Ba_obj = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1,4,5,3, 9,9, 1,5,8,] Wa_obj = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2,6,8,7, 10,10, 11,11,11,] Bb_obj = [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7,3,1,2, 9,9, 1,5,8,] Wb_obj = [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8,5,4,6, 10,10, 11,11,11,] B_obj_prob = [90, 80, 70, 36, 18, 9, 32, 16, 8, 28, 14, 7, 90, 80, 70, 36, 18, 9, 32, 16, 8, 28, 14, 7, 90, 80, 70, 36, 18, 9, 32, 16, 8, 28, 14, 7, 90, 80, 70, 36, 18, 9, 32, 16, 8, 28, 14, 7, 100, 100, 100, 100, 80, 20, 100, 50, 25,] W_obj_prob = [100, 100, 100, 40, 20, 10, 40, 20, 10, 40, 20, 10,100, 100, 100, 40, 20, 10, 40, 20, 10, 40, 20, 10, 100, 100, 100, 40, 20, 10, 40, 20, 10, 40, 20, 10,100, 100, 100, 40, 20, 10, 40, 20, 10, 40, 20, 10, 100, 100, 100, 100, 100,25, 0, 0, 0,] class Subsession(BaseSubsession): pass def creating_session(subsession): for p in subsession.get_players(): ## IF I NEEDED ANYTHING FROM SESSION.CONFIG, THIS WOULD BE THE PLACE TO PUT IT. #p.minimal_design = p.session.config['minimal_design'] #pprint("minimal design is:") #pprint(p.minimal_design) if p.round_number == 1: #pair_order = [1,2,3,4] pair_order = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33, 34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, 49,50,51,52, 53,54, 55,56,57] random.shuffle(pair_order) p.participant.vars['pair_order'] = str(pair_order) p.ranked9 = "Forty" p.ranked10 = "Thirty" p.ranked11 = "Nothing" p.participant.vars['ranked9'] = p.ranked9 p.participant.vars['ranked10'] = p.ranked10 p.participant.vars['ranked11'] = p.ranked11 group_a = random.randint(0,1) p.group_a = group_a #reverse_side = random.randint(0,1) #p.reverse_side = reverse_side p.current_round = 1 for q in p.in_rounds(1, C.NUM_ROUNDS): pair_drawn = int(pair_order[q.round_number - 1]) q.pair_order = str(pair_order) q.pair_drawn = pair_drawn ##q.increasing_order = increasing_order q.group_a = group_a reverse_side = random.randint(0,1) q.reverse_side = reverse_side if group_a == 1: q.b_object = C.Ba_obj[pair_drawn - 1] q.w_object = C.Wa_obj[pair_drawn - 1] # need the -1 because question order starts from 1, but lists index from 0 if group_a == 0: q.b_object = C.Bb_obj[pair_drawn - 1] q.w_object = C.Wb_obj[pair_drawn - 1] q.w_obj_prob = C.W_obj_prob[pair_drawn - 1] q.b_obj_prob = C.B_obj_prob[pair_drawn - 1] q.w_other_prob = 100 - q.w_obj_prob q.b_other_prob = 100 - q.b_obj_prob q.prob_w_obj_img = "/static/probs/" + str(q.w_obj_prob) + ".JPG" q.prob_b_obj_img = "/static/probs/" + str(q.b_obj_prob) + ".JPG" ##### THIS WILL ONLY BE USED IF THE BLOCK BELOW IS USED (IE IF MORE VARIABLES ARE INDEXED) # SO I'LL ADD AN EXTRA "#" FOR NOW. #pair_order = json.loads(p.pair_order) #pair_drawn = int(pair_order[subsession.round_number - 1]) #pprint(pair_drawn) p.current_round = subsession.round_number ##EXAMPLE OF OTHER VARIABLES THAT COME FROM CONSTANTS AND NEED TO BE DRAWN BY ROUND TOO. ##p.external = Constants.external_amount[question_drawn] ##p.income = Constants.income_amount[question_drawn] ##p.policy = Constants.policy_amount[question_drawn] class Group(BaseGroup): pass class Player(BasePlayer): current_round = models.IntegerField() pair_order = models.StringField() pair_drawn = models.IntegerField() ranked9 = models.StringField() ranked10 = models.StringField() ranked11 = models.StringField() group_a = models.IntegerField() reverse_side = models.IntegerField() w_object = models.IntegerField() b_object = models.IntegerField() w_obj_prob = models.IntegerField() b_obj_prob = models.IntegerField() w_other_prob = models.IntegerField() b_other_prob = models.IntegerField() prob_w_obj_img = models.StringField() prob_b_obj_img = models.StringField() riskychoice = models.IntegerField( widget=widgets.RadioSelectHorizontal, label='Which option do you prefer?' ) #def save_questions(player): # player.participant.vars["b_object"] = player.b_object.in_all_rounds() def riskychoice_choices(player): if player.reverse_side == 0: choices = [ [0, "Option 1"], [1, "Option 2"],] if player.reverse_side == 1: choices = [ [1, "Option 1"], [0, "Option 2"],] return choices # PAGES class infoquestions(Page): pass class question(Page): form_model = 'player' form_fields = [ 'riskychoice', ] @staticmethod def vars_for_template(self): return { # I THINK I MAY NOT NEED ALL THESE RANKED #'ranked1': self.participant.vars['ranked1'], #'ranked2': self.participant.vars['ranked2'], #'ranked3': self.participant.vars['ranked3'], #'ranked4': self.participant.vars['ranked4'], #'ranked5': self.participant.vars['ranked5'], #'ranked6': self.participant.vars['ranked6'], #'ranked7': self.participant.vars['ranked7'], #'ranked8': self.participant.vars['ranked8'], 'worstobj': self.w_object, 'bestobj': self.b_object, #'leftobj_dict': C.OBJECTS[self.participant.vars["ranked"+str(self.l_object)]], 'worstobj_dict': C.OBJECTS[self.participant.vars.get("ranked"+str(self.w_object))], #this one is more error tolerant #'rightobj_dict': C.OBJECTS[self.participant.vars["ranked"+str(self.r_object)]], 'bestobj_dict': C.OBJECTS[self.participant.vars.get("ranked"+str(self.b_object))], # this one is more error tolerant 'w_obj_prob': self.w_obj_prob, 'b_obj_prob': self.b_obj_prob, 'w_other_prob': self.w_other_prob, 'b_other_prob': self.b_other_prob, 'prob_w_obj_img': self.prob_w_obj_img, 'prob_b_obj_img': self.prob_b_obj_img, 'reverse_side': self.reverse_side, } def before_next_page(player, timeout_happened): # pass relevant variables to payment app try: best_objects = literal_eval(player.participant.vars['best_objects']) except KeyError: best_objects = [-99 for x in range(0, 57)] best_objects[player.round_number - 1] = player.b_object player.participant.vars['best_objects'] = str(best_objects) try: worst_objects = literal_eval(player.participant.vars['worst_objects']) except KeyError: worst_objects = [-99 for x in range(0, 57)] worst_objects[player.round_number - 1] = player.w_object player.participant.vars['worst_objects'] = str(worst_objects) try: best_objects_p = literal_eval(player.participant.vars['best_objects_p']) except KeyError: best_objects_p = [-99 for x in range(0, 57)] best_objects_p[player.round_number - 1] = player.b_obj_prob player.participant.vars['best_objects_p'] = str(best_objects_p) try: worst_objects_p = literal_eval(player.participant.vars['worst_objects_p']) except KeyError: worst_objects_p = [-99 for x in range(0, 57)] worst_objects_p[player.round_number - 1] = player.w_obj_prob player.participant.vars['worst_objects_p'] = str(worst_objects_p) try: riskychoices = literal_eval(player.participant.vars['riskychoices']) except KeyError: riskychoices = [-99 for x in range(0, 57)] riskychoices[player.round_number - 1] = player.riskychoice player.participant.vars['riskychoices'] = str(riskychoices) #FOR TESTING #pprint(player.participant.vars['best_objects']) #pprint(player.participant.vars['worst_objects']) #pprint(player.participant.vars['best_objects_p']) #pprint(player.participant.vars['worst_objects_p']) #pprint(player.participant.vars['riskychoices']) page_sequence = [question]