from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) from prev2.config import * import random import numpy as np import ast author = 'Vincent Lenglin' doc = """ Prevention 2 - main task reste à faire : coder le front les choix paiement questionnaire de compréhension questionnaire socio demo prudence ATTENTION DANS LES PERTES, BIEN VERIFFIER LES PROBA ET LEUR ASSOCIATIONS AUX CONSEQUENCES (attention aux inversions) """ class Subsession(BaseSubsession): def creating_session(self): dict2 = Constants.c_dict2 if self.round_number == 1: for p in self.get_players(): p.WINNER_BIG_PRIZE = random.choices([0, 1], weights=[29, 1], k=1)[0] p.participant.vars['CHOIX_VECTEUR'] = [] # CONDITIONS EXPERIMENTALES # ------------------------------------------------ p.GAIN = Constants.c_GAIN # si GAIN == 1 : domaine des gains; si GAIN == 0 alors domaine des pertes p.RISK = Constants.c_RISK # si RISK == 1 : domaine du risque; si RISK == 0 alors domaine de l'ambiguité p.CROISSANT = Constants.c_CROISSANT # si croissant == 1 : alors MPL croissant; si croissant == 0 alors MPL décroissant if p.GAIN == 1 and p.RISK == 1: p.CONDITION = "RISK_GAIN" elif p.GAIN == 0 and p.RISK == 1: p.CONDITION = "RISK_LOSS" elif p.GAIN == 1 and p.RISK == 0: p.CONDITION = "AMBIGUITY_GAIN" elif p.GAIN == 0 and p.RISK == 0: p.CONDITION = "AMBIGUITY_LOSS" for s in range(1, Constants.num_rounds + 1): p.in_round(s).CONDITION = p.CONDITION p.in_round(s).GAIN = p.GAIN p.in_round(s).RISK = p.RISK p.in_round(s).CROISSANT = p.CROISSANT p.in_round(s).WINNER_BIG_PRIZE = p.WINNER_BIG_PRIZE ## CREATIONS DES LOTERIES A ET B + MPL croissant ou décroissant # -------------------------------------------------------------------------- # Création des loteries B à partir des loteries A # Tout d'abord on s'occupe des conditions perte et gain car 15€ dans les gains correspond à X1 qui est le meilleur outcome. # Si on rend négatif 15 donc -15, X1 devient le plus petit alors qu'on veut que X1 reste le meilleur outcome. # Il faut donc utiliser un petit tour de pass passe pour réorganiser. if p.GAIN == 0: # Loss domain for cle in dict2: dict2[cle]["X1_loss"] = -dict2[cle]["X2"] dict2[cle]["X2_loss"] = -dict2[cle]["X1"] dict2[cle]["X1"] = dict2[cle]["X1_loss"] dict2[cle]["X2"] = dict2[cle]["X2_loss"] # On ajoute des éléments importants aux différents dictionnaires for key in dict2: dict2[key]["P2"] = 100 - dict2[key]["P1"] dict2[key]["X1_B_list"] = np.round(np.arange(dict2[key]["X1"] - dict2[key]["MAX_COST"], dict2[key]["X1"] + dict2[key]["PAS"] , dict2[key]["PAS"]), decimals=2).tolist() dict2[key]["X2_B_list"] = np.round(np.arange(dict2[key]["X2"] - dict2[key]["MAX_COST"], dict2[key]["X2"] + dict2[key]["PAS"] , dict2[key]["PAS"]), decimals=2).tolist() dict2[key]["P1_B"] = dict2[key]["P1"] + 10 dict2[key]["P2_B"] = 100 - dict2[key]["P1_B"] # Determine si le MPL est croissant ou décroissant croissant = "croissant" # création de la clé "croissant" valeur_croissant = p.CROISSANT # si croissant == 1 : alors MPL croissant; si croissant == 0 alors MPL décroissant for cle in dict2: dict2[cle][croissant] = valeur_croissant # On stock la valeur de croissant dans le dico # Afficher le dictionnaire mis à jour : soit on reste en décroissant soit en croissant if p.CROISSANT == 0: for key in dict2: dict2[key]["X1_B_list"].sort(reverse=True) # type: ignore dict2[key]["X2_B_list"].sort(reverse=True) # type: ignore # On stock le gros dictionnaire dans une variable participant pour pouvoir jouer avec ensuite dans la section PLAYER p.participant.vars['dico'] = dict2 class Group(BaseGroup): pass class Player(BasePlayer): # propriétés CONDITION = models.StringField() RISK = models.IntegerField() GAIN = models.IntegerField() CROISSANT = models.IntegerField() PAS = models.FloatField() MAX_COST = models.IntegerField() ORDRE_LOTERIE = models.LongStringField() ID_LOT = models.StringField() HIGH = models.IntegerField() # éléments des loteries # loterie A X1 = models.IntegerField() X2 = models.IntegerField() P1 = models.IntegerField() P2 = models.IntegerField() # loterie B X1_B = models.LongStringField() X2_B = models.LongStringField() P1_B = models.IntegerField() P2_B = models.IntegerField() # CHOIX NUM_CHOICE = models.IntegerField() for j in range(1, Constants.num_choices + 1): locals()['CHOIX' + str(j)] = models.StringField() del j # PAIEMENT WINNER_BIG_PRIZE = models.IntegerField() ROUND_SELECTED = models.IntegerField() X1_B_VECTEUR_SELECTED = models.StringField() X2_B_VECTEUR_SELECTED = models.StringField() X1_SELECTED = models.IntegerField() X2_SELECTED = models.IntegerField() P1_SELECTED = models.IntegerField() P2_SELECTED = models.IntegerField() X1_B_SELECTED = models.FloatField() X2_B_SELECTED = models.FloatField() P1_B_SELECTED = models.IntegerField() P2_B_SELECTED = models.IntegerField() CHOIX_VECTEUR_SELECTED = models.StringField() INDICE_CHOICE_SELECTED = models.IntegerField() CHOIX_SELECTED = models.StringField() PAIEMENT_PREV = models.FloatField() # QUESTIONNAIRE COMPREHENSION Q1 = models.IntegerField(blank = False, label="", widget=widgets.RadioSelect, choices=[[1,'reponse 1'], [2, 'reponse 2'], [3, 'reponse 3'], [4, 'reponse 4']]) Q2 = models.IntegerField(blank = False, label="", widget=widgets.RadioSelect, choices=[[1,'reponse 1'], [2, 'reponse 2'], [3, 'reponse 3'], [4, 'reponse 4']]) Q3 = models.IntegerField(blank = False, label="", widget=widgets.RadioSelect, choices=[[1,'reponse 1'], [2, 'reponse 2'], [3, 'reponse 3'], [4, 'reponse 4']]) Q4 = models.IntegerField(blank = False, label="", widget=widgets.RadioSelect, choices=[[1,'reponse 1'], [2, 'reponse 2'], [3, 'reponse 3'], [4, 'reponse 4']]) FAUX_Q1 = models.IntegerField() FAUX_Q2 = models.IntegerField() FAUX_Q3 = models.IntegerField() FAUX_Q4 = models.IntegerField() ### RANDOMISATION DES LOTERIES ### # ----------------------------------------------------- # On randomise l'ordre d'apparition des loteries def random_cle(self): keys = list(self.participant.vars['dico'].keys()) # on récupère la liste des clés random.shuffle(keys) # On randomise l'ordre self.participant.vars['dico'] = {key: self.participant.vars['dico'][key] for key in keys} # on réorganise l'ordre des clés dans le dico self.participant.vars['key_list'] = list(self.participant.vars['dico'].keys()) # on stock les clés avec le nouvel ordre dans une variable self.ORDRE_LOTERIE = str(self.participant.vars['key_list']) # on enregistre l'ordre des loteries dans la base de données ### ENREGRISTREMENT DES DATAS ### # -------------------------------------------------- # On enregistre les propriétés et éléments des loteries A et B dans la base de données à chaque round def record_valeur(self): variables = ['HIGH', 'PAS', 'MAX_COST', 'X1', 'X2', 'P1', 'P2', 'P1_B', 'P2_B'] for variable in variables: setattr(self, variable, self.participant.vars['dico'][self.participant.vars['key_list'][self.round_number - 1]][variable]) self.ID_LOT = self.participant.vars['key_list'][self.round_number - 1] self.X1_B = str(self.participant.vars['dico'][self.participant.vars['key_list'][self.round_number - 1]]["X1_B_list"]) self.X2_B = str(self.participant.vars['dico'][self.participant.vars['key_list'][self.round_number - 1]]["X2_B_list"]) # On zip plusieurs éléments afin de pouvoir utiliser les for loop dans django/html self.participant.vars['X1_B_list'] = self.participant.vars['dico'][self.participant.vars['key_list'][self.round_number - 1]]["X1_B_list"] self.participant.vars['X2_B_list'] = self.participant.vars['dico'][self.participant.vars['key_list'][self.round_number - 1]]["X2_B_list"] self.participant.vars['nb_choix'] = [i for i in range(1, len(self.participant.vars['X1_B_list']) + 1)] # On crée un vecteur des noms des choix possibles self.NUM_CHOICE = len(self.participant.vars['X1_B_list']) self.participant.vars['n_choix'] = ['CHOIX' + str(k) for k in range(1, len(self.participant.vars['X1_B_list']) + 1)] # On crée un ZIP de plusieurs variables changeantes dans le MPL afin d'utiliser le for loop dans django pour créer les tableaux MPL self.participant.vars['ZIP_LOT'] = zip(self.participant.vars['X1_B_list'], self.participant.vars['X2_B_list'], self.participant.vars['nb_choix'], self.participant.vars['n_choix']) ############################################################ # PAIEMENT ############################################################ # récupération des rounds impliquant les high stakes et les small stakes def recuperation_index_cle_high(self): self.participant.vars['INDICE_HIGH'] = [] self.participant.vars['INDICE_SMALL'] = [] for index, (key, value) in enumerate(self.participant.vars['dico'].items()): if 'HIGH' in value and value['HIGH'] == 1: self.participant.vars['INDICE_HIGH'].append(index) elif 'HIGH' in value and value['HIGH'] == 0: self.participant.vars['INDICE_SMALL'].append(index) # Selection d'un seul round pour paiement en fonction de si l'individu doit être récompensé # sur un high stake ou un low stake if self.WINNER_BIG_PRIZE == 1: self.participant.vars['ROUND_SELECTED'] = random.choices(self.participant.vars['INDICE_HIGH'])[0] elif self.WINNER_BIG_PRIZE == 0: self.participant.vars['ROUND_SELECTED'] = random.choices(self.participant.vars['INDICE_SMALL'])[0] self.ROUND_SELECTED = self.participant.vars['ROUND_SELECTED'] self.in_round(Constants.num_rounds).ROUND_SELECTED = self.participant.vars['ROUND_SELECTED'] # On enregistre tous les vecteurs de choix réalisé par l'individu sous le format # choix_vecteur = [ [choix1, choix2, ...], [choix1, choix2, ...], ..., [choix1, choix2, ...]] def recuperation_des_donnees(self): self.participant.vars['CHOIX_VECTEUR'] = self.participant.vars['CHOIX_VECTEUR'] + [[ self.CHOIX1, self.CHOIX2, self.CHOIX3, self.CHOIX4, self.CHOIX5, self.CHOIX6, self.CHOIX7, self.CHOIX8, self.CHOIX9, self.CHOIX10, self.CHOIX11, ]] def paiement_prev(self): self.participant.vars['CHOIX_VECTEUR_SELECTED'] = self.participant.vars['CHOIX_VECTEUR'][self.participant.vars['ROUND_SELECTED']] self.participant.vars['CHOIX_VECTEUR_SELECTED'] = list(filter(None, self.participant.vars['CHOIX_VECTEUR_SELECTED'])) # enregistrement des caracteristiques des loteries A et B sélectionnées précédemment sur la base du round gagnant self.CHOIX_VECTEUR_SELECTED = str(self.participant.vars["CHOIX_VECTEUR_SELECTED"]) self.X1_B_VECTEUR_SELECTED = str(self.in_round(self.participant.vars['ROUND_SELECTED'] + 1).X1_B) self.X2_B_VECTEUR_SELECTED = str(self.in_round(self.participant.vars['ROUND_SELECTED'] + 1).X2_B) variables = ['X1', 'X2', 'P1', 'P2', 'P1_B', 'P2_B'] selected_round = self.participant.vars['ROUND_SELECTED'] + 1 for variable in variables: setattr(self, variable + '_SELECTED', getattr(self.in_round(selected_round), variable)) # Enregistrement du choix sélectionné au hasard pour le round sélectionné précédemment self.participant.vars["LEN_CHOIX_VECTEUR_SELECTED"] = len(self.participant.vars['CHOIX_VECTEUR_SELECTED']) self.participant.vars["INDICE_CHOICE_SELECTED"] = random.choices([i for i in range(0, self.participant.vars["LEN_CHOIX_VECTEUR_SELECTED"] + 1)])[0] self.INDICE_CHOICE_SELECTED = self.participant.vars["INDICE_CHOICE_SELECTED"] self.participant.vars['CHOIX_SELECTED'] = self.participant.vars['CHOIX_VECTEUR_SELECTED'][self.participant.vars["INDICE_CHOICE_SELECTED"]] self.CHOIX_SELECTED = self.participant.vars['CHOIX_SELECTED'] # Enregistrement de X1_B et X2_B sélectionné au hasard pour le round sélectionné précédemment* self.participant.vars['X1_B_SELECTED'] = ast.literal_eval(self.X1_B_VECTEUR_SELECTED) # permet de convertir str en list de numerique self.participant.vars['X2_B_SELECTED'] = ast.literal_eval(self.X2_B_VECTEUR_SELECTED) self.participant.vars['X1_B_SELECTED'] = self.participant.vars['X1_B_SELECTED'][self.participant.vars["INDICE_CHOICE_SELECTED"]] self.participant.vars['X2_B_SELECTED'] = self.participant.vars['X2_B_SELECTED'][self.participant.vars["INDICE_CHOICE_SELECTED"]] self.X1_B_SELECTED = self.participant.vars['X1_B_SELECTED'] self.X2_B_SELECTED = self.participant.vars['X2_B_SELECTED'] # PAIEMENT SUR L'APP PREV2 if self.CHOIX_SELECTED == 'A': self.PAIEMENT_PREV = random.choices([self.X1_SELECTED, self.X2_SELECTED], [self.P1_SELECTED, self.P2_SELECTED])[0] elif self.CHOIX_SELECTED == 'B': self.PAIEMENT_PREV = random.choices([self.X1_B_SELECTED, self.X2_B_SELECTED], [self.P1_B_SELECTED, self.P2_B_SELECTED])[0] self.participant.vars['PAIEMENT_PREV'] = self.PAIEMENT_PREV