]> git.immae.eu Git - perso/Denise/oms.git/commitdiff
changelog à jour (pour mise en prod) beta master
authorDenise sur ardoise <denise@ardoise>
Sun, 7 Aug 2022 12:26:25 +0000 (14:26 +0200)
committerDenise sur ardoise <denise@ardoise>
Sun, 7 Aug 2022 12:26:25 +0000 (14:26 +0200)
15 files changed:
app.py
calculs_extrapole.py
configuration.py
data/FAQ_data.txt
data/changelog_data.txt
faq.py
gestion_donnees.py
static/outilspage.js
static/requetes.js
static/style.css
templates/apropos.html
templates/contact.html
templates/faq.html
templates/index.html
trace_courbe.py

diff --git a/app.py b/app.py
index 84e2ff111f4610848c480ad56391f5d56510e9a3..f60d3e2ec9d76f0fcbf98003a6378dc70a284295 100644 (file)
--- a/app.py
+++ b/app.py
@@ -59,7 +59,7 @@ def courbe_image(ext):
 
     # récupérer les données du formulaire proprement
     config,listes_jours,listes_donnees = donnees.web_vers_python(data,liste_err)
-    debug(" * On a récupéré et traité les données du formulaire web",liste_err)
+    debug(" * On a récupéré et traité les données du formulaire web, "+str(listes_jours)+str(listes_donnees),liste_err)
 
     # Gérer les enfants additionnels
     enfants_add = donnees.gere_enfants_additionnels(data, flask.request.files, liste_err)
@@ -71,6 +71,11 @@ def courbe_image(ext):
     
     # noter le nom de l'enfant pour l'export
     nomenfant = donnees.simplifie_nom(config['nom'])
+    # Les noms des autres enfants c'est sympa
+    nomsenfantsplus = ""
+    for dicoenfant in enfants_add:
+        nomsenfantsplus += "_"+donnees.simplifie_nom(dicoenfant["poids"][0]["nom"])
+
     existe_courbe = False
     # créer les figures
     try:
@@ -101,7 +106,8 @@ def courbe_image(ext):
     if ext == "b64":
         reponse = { "result":result, 
             "export_txt": texte,
-            "nomenfant": nomenfant}
+            "nomenfant": nomenfant,
+            "nomsenfantsplus": nomsenfantsplus}
         if result == "success":
             reponse["messages"] = liste_err[0]+liste_err[1]
             reponse["calculextra"] = liste_extracalculs
@@ -132,9 +138,9 @@ def faq():
     beta=initialise_mode_beta()
     
     table_faq = f.lire_fichier_csv_simple(f.fichier_FAQ)
-    l_categ,table_qr = f.extraire_tables_par_cat(table_faq)
+    l_categ, l_categsimple, table_qr = f.extraire_tables_par_cat(table_faq)
 
-    return flask.render_template("faq.html",lcateg=l_categ,tableqr=table_qr,err=[], beta=beta)
+    return flask.render_template("faq.html",lcateg=l_categ,lcategsimple= l_categsimple, tableqr=table_qr,err=[], beta=beta)
 
 @app.route("/changelog")
 def changelog():
index fdd4c680830cc2315b5bb513673ae9ff512efde6..c84960d6b703d9ba5e75b7c60b80aaf3efd46c27 100644 (file)
@@ -130,15 +130,18 @@ def joliechaine_age(age):
     #print(retour)
     return retour[:-2]
 
-def formate_resultat_donnee(age, donnee, typedonnee, extra, liste_err):
+def formate_resultat_donnee(age, date, donnee, typedonnee, extra, liste_err):
     """ Formate le tout en une zolie phrase
-    age et donnee sont les données,
+    age date et donnee sont les données. date peut être None (sinon donnée de date)
     typedonnee est le type de donnée (poids, etc)
     extra est un truc additionnel à mettre entre parenthèses"""
 
     donnee_arrondie = u.arrondit_donnee(donnee, typedonnee)
     chaine = "À "+joliechaine_age(convertit_age_vers_texte(age))
 
+    if date != None:
+        chaine += ", le "+date.strftime("%d/%m/%Y")
+
     if typedonnee == "poids":
         chaine+= ", l'enfant pèsera "+str(donnee_arrondie)+" kg"
     elif typedonnee == "taille":
@@ -154,9 +157,9 @@ def formate_resultat_donnee(age, donnee, typedonnee, extra, liste_err):
     chaine+=ajout+"."
     return chaine
 
-def formate_resultat_age(age, donnee, typedonnee, extra, liste_err):
+def formate_resultat_age(age, date, donnee, typedonnee, extra, liste_err):
     """ formate les données en une zolie phrase
-    age et donnee sont les données
+    age, date et donnee sont les données. date est une donnée de date qui peut être vide.
     typedonnee est le type de donnée (poids, etc)
     extra est un truc additionnel à mettre entre parenthèses"""
     age_joli = joliechaine_age(convertit_age_vers_texte(age))
@@ -167,6 +170,9 @@ def formate_resultat_age(age, donnee, typedonnee, extra, liste_err):
     else:# phrase générique
         chaine= "L'enfant atteindra la donnée "+typedonnee+" "+str(donnee)+" à l'âge de "+age_joli
     
+    if date != None:
+        chaine += ", le "+date.strftime("%d/%m/%Y")
+    
     if extra!="":
         ajout=" ("+extra+")"
     else:
index b22c6e3fbd788141534217d62fbd113ec1387316..7b1d7c584459c8fc72361688c00ba3a907b24c2c 100644 (file)
@@ -5,7 +5,7 @@
 CONFIG = {}
 
 ### La version de l'app
-CONFIG["version"] = 2.5
+CONFIG["version"] = 2.6
 # Nombre de versions anciennes dans le changelog
 CONFIG["nb_lignes_changelog"] = 4
 
@@ -47,6 +47,7 @@ CONFIG["fichiersOMS"]["taille"] = {
         "z_mixte": "lhfa_mix_z_exp.txt",
         }
 
+CONFIG["voyelles"] = ["a", "e", "i", "o", "u", "y"]
 
 # ajouter le chemin
 for typed in CONFIG["liste_typedonnees"]:
index cbc3a56440783763afe4a6127b9080686d59e501..605ca7f85a2ec240f0a3e0e728adff5eee210c73 100644 (file)
@@ -12,12 +12,12 @@ Si vous manquez de lignes, vous pouvez cliquer sur ""Ajouter des lignes"" pour a
 "Utilisation - préférences du graphique","Pourquoi tracer des courbes vides ?","Cela peut servir à tracer une courbe de référence à imprimer pour tracer la courbe à la main. Cette option est désactivée par défaut."
 
 "Utilisation - préférences du graphique","C'est quoi la différence entre la courbe percentiles et moyenne/écarts-types ?","Ce sont deux manières de comparer son enfant à la «&nbsp;référence&nbsp;». Si vous ne savez pas la différence entre une moyenne et une médiane, retenez juste que ce sont des calculs un peu différents, mais cela ne change pas l'allure de la courbe, si votre enfant «&nbsp;suit&nbsp;» un couloir sur un type de courbe ce sera pareil sur l'autre. Vous pouvez au pire choisir celle que vous préférez. ;)
-<br>Pour les curieuses et les curieux :
+<br>Pour les curieuses et les curieux :</p>
 <ul>
 <li>Médiane et percentiles : si votre enfant est (par exemple) au 30e percentile, cela signifie qu'il est dans la 30e «&nbsp;tranche&nbsp;» sur 100 tranches. Autrement dit 29% des enfants sont plus légers que lui, et 70% sont plus lourds. Cela donne une idée de où il se situe par rapport aux autres. <a href=""https://fr.wikipedia.org/wiki/Centile"">Plus d'infos (maths)</a></li>
 <li>Moyenne et écart-types : la moyenne est obtenue en faisant la somme et en divisant par le nombre d'enfants. L'écart-type (noté &sigma;) est une sorte d'«&nbsp;écart moyen&nbsp;» à la moyenne. On regarde donc généralement la moyenne, la moyenne + 1&sigma;, moyenne +2&sigma;, moyenne -1 &sigma;, etc. <a href=""https://fr.wikipedia.org/wiki/%C3%89cart_type"">Plus d'infos (maths)</a></li>
 </ul>
-Si la répartition des données est «&nbsp;bonne&nbsp;» (on parle de gaussienne entre matheuses et matheux), alors la moyenne correspond à la médiane, la moyenne + 1&sigma; correspond environ au 84e percentile, la moyenne -1&sigma; correspond au 16e percentile. Pour ces données, il semble que ce soit assez proche d'une gaussienne."
+<p>Si la répartition des données est «&nbsp;bonne&nbsp;» (on parle de gaussienne entre matheuses et matheux), alors la moyenne correspond à la médiane, la moyenne + 1&sigma; correspond environ au 84e percentile, la moyenne -1&sigma; correspond au 16e percentile. Pour ces données, il semble que ce soit assez proche d'une gaussienne."
 
 "Utilisation - préférences du graphique","Que signifie même échelle d'âge sur tous les graphiques&nbsp;?","Si, par exemple, vous avez des données de poids qui vont jusqu'à 2 ans et des données de taille qui vont jusqu'à 6 mois, alors chaque graphique (taille et poids) aura son échelle différente. Mais si vous cochez la case, alors tous seront sur une échelle similaire (c'est-à-dire jusqu'à 2 ans et un peu plus). Si vous saisissez un âge maximum du graphique, c'est cette limite maximum qui sera appliquée sur tous les graphiques."
 
@@ -39,6 +39,7 @@ S'il y a plusieurs données, alors on cherche dans quel intervalle de courbes el
 
 "Utilisation - courbes multiples","C'est quoi les courbes multiples&nbsp;?","Vous pouvez souhaiter tracer sur une même courbe de poids (par exemple) l'évolution du poids de deux (ou plus) enfants, du même âge ou d'âges différents. Pour cela, il faut avoir déjà sous forme de fichier les données des enfants additionnels. Seuls le nom de l'enfant et ses données sont extraites, les paramètres du graphiques seront ceux définis plus haut (donc pour l'enfant «&nbsp;principal&nbsp;»). C'est pourquoi vous pouvez choisir un symbole et une couleur pour chacun des graphiques additionnels. Par contre ces paramètres ne sont pas sauvegardés (seuls ceux de l'enfant «&nbsp;principal&nbsp;» le sont)."
 
+"Utilisation - courbes multiples","C'est quoi l'alias&nbsp;?","Vous avez enregistré un fichier de données d'un autre enfant, à son vrai nom, et vous voulez tracer des courbes multiples mais avec un surnom car vous avez l'intention de rendre cette courbe publique&nbsp;: vous pouvez mettre le surnom ici. Si vous laissez ce champ vide, le nom de l'enfant enregistré dans le fichier sera utilisé. Si vous n'avez pas très bien compris, essayez et vous verrez&nbsp;!"
 
 "Courbe","À quoi sert ce site ?","Il sert à tracer les courbes de croissance des bébés et jeunes enfants en fonction de leur âge, comme sur le carnet de santé, et la compare aux courbes de références de l'Organisation Mondiale de la Santé. Ces courbes sont a priori prévues pour des enfants nés à terme en bonne santé. Pour un enfant prématuré ou à situation particulière, référez vous à un.e professionnel.le de santé."
 
@@ -70,6 +71,8 @@ Vous trouverez <a href=""static/courbe_oms_gf_1an.png"">ici</a> et <a href=""sta
 
 "Technique","Quelle est la technologie utilisée derrière ?","Il s'agit de <a href=""https://flask.palletsprojects.com/en/1.1.x/"">flask</a>, un petit framework de développement web en <a href=""https://www.python.org/"">python</a>. Il y a une petite dose de <a href=""https://developer.mozilla.org/fr/docs/Web/JavaScript"">JavaScript</a> pour assaisonner le tout, et voilà."
 
+"Technique","Quand je clique sur ""Je veux les courbes"" je reste sur le message ""Calcul en cours"" mais rien ne se passe...","C'est un vilain bug, voir ci-dessous pour la marche à suivre !"
+
 "Technique","J'ai trouvé un affreux bug !","N'hésitez pas à me contacter avec le plus de détails possibles à ce sujet. Par exemple quelles données, quelles manipulations vous ont amené.e à ce bug. Vous pouvez aussi préciser votre navigateur. Plus vous me fournissez d'informations, plus j'ai de chances de résoudre le bug !"
 
 "Technique","J'ai envie d'aider à trouver les bugs !","Il y a la version bêta du site <a href=""https://beta.oms.syanni.eu"">ici</a>. Si la bêta est en avance sur le site de production, c'est qu'il y a des choses à tester et des bugs à chasser (vérifier le changelog pour comparer les versions)."
index 37a46d042d31290b212ecd38d4c15597a98a7e51..50443dfbb7a3a927a14d333d4869f638e2c46186 100644 (file)
@@ -1,4 +1,19 @@
-"Version 2.5","29/06/2021","<p>Plus de courbes ! Et d'autres choses...</p>
+"Version 2.6","7/08/2022","<p>Des petites nouveautés :</p>
+<ul>
+       <li>Les dates sont désormais prioritaires sur les âges pour éviter les soucis d'arrondis.</li>
+       <li>Il est également possible de mettre une date sur un repère (et de repérer une date précise).</li>
+       <li>On peut également utiliser les dates pour les extrapolations (telle date l'enfant pèsera tant...)</li>
+       <li>Un bug corrigé : si on demande une taille de graphique supérieure à l'âge max des données OMS (5 ans), ça ne fait pas planter l'extrapolation (le tracé d'extrapolation s'arrêtera juste à 5 ans).</li>
+
+       <li>On peut choisir un ""alias"" pour les noms des enfants pour les courbes d'autres enfants. Pratique quand on a le fichier enregistré à un nom et qu'on veut poster la courbe sur un forum public (sans le nom).</li>
+       <li>Petite amélioration sur le titre des courbes et des fichiers quand on a plusieurs enfants.</li>
+    <li>Un bug corrigé sur les courbes pour prématurés.</li>
+       <li>Un peu de ménage par-ci, par-là...</li>
+</ul>"
+
+"Version 2.501","14/05/2022","<p>Petit bug mineur corrigé : si on met une donnée avec une date inférieure à la date de naissance, elle est ignorée et un petit message s'affiche.</p>"
+
+"Version 2.5","29/07/2021","<p>Plus de courbes ! Et d'autres choses...</p>
 <ul>
 <li>Un petit coup de peinture général à divers endroits.</li>
 <li>Une icône, enfin (il était temps...)</li>
diff --git a/faq.py b/faq.py
index 09cd9f385ce3367a83c0b49b1b7bd846f6323bb6..45f28d6f8fb3f7b1869b38bca9b5d317b7fbe9ba 100644 (file)
--- a/faq.py
+++ b/faq.py
@@ -8,7 +8,7 @@ chemin_data = "data/"
 
 fichier_FAQ = chemin_data+"FAQ_data.txt"
 fichier_changelog = chemin_data+"changelog_data.txt"
-
+from gestion_donnees import simplifie_nom
 
 
 def lire_fichier_csv_simple(fichier):
@@ -31,9 +31,10 @@ def extraire_categories(table):
     return liste_cat
 
 def extraire_tables_par_cat(table):
-    """ construit deux tables : une de catégories, une de tables de (q,r)
-     categ[i] va correspondre à tableqr[i] en terme de catégorie"""
+    """ construit trois tables : une de catégories, une de tables de (q,r), une de catégories simplifées
+     categ[i] et categsimple[i] vont correspondre à tableqr[i] en terme de catégorie"""
     categ = extraire_categories(table)
+    categsimple = [ simplifie_nom(cat) for cat in categ ]
     tableqr = [ [] for i in range(len(categ)) ]
     
     for ligne in table:
@@ -45,4 +46,4 @@ def extraire_tables_par_cat(table):
         except:
             print("Impossible de lire la ligne : "+str(ligne))
             
-    return (categ,tableqr)
+    return (categ, categsimple, tableqr)
index 6911320ecbc1309072bff8883ae282e4a9bb5da7..b508706334e3a7c7797293368b0bf3dfcdd77232 100644 (file)
@@ -63,6 +63,7 @@ def convertit_age_vers_texte(nombre):
     annees = int(nombre / CONFIG["jours_dans_annee"])
     restant = nombre - annees*CONFIG["jours_dans_annee"]
     mois = int(restant/CONFIG["jours_dans_mois"])
+    #print("mois : ",mois, ", restant : ",nombre - mois*CONFIG["jours_dans_mois"])
     jours= round(nombre - mois*CONFIG["jours_dans_mois"] - annees*CONFIG["jours_dans_annee"])
     
     chaine = ""
@@ -70,7 +71,7 @@ def convertit_age_vers_texte(nombre):
         chaine += str(annees)+"a"
     if mois >0:
         chaine += str(mois)+"m"
-    if jours>0 or  nombre ==0: # si c'est la naissance, faut beien écrire 0j quand même
+    if jours>0 or  nombre ==0: # si c'est la naissance, faut bien écrire 0j quand même
         chaine += str(jours)+"j"
     return chaine
 
@@ -89,7 +90,7 @@ def calcule_max_graphique(l_jours):
 
 def simplifie_nom(chaine):
     """ simplifie le nom chaine afin d'en faire une extension
-    pour le nom du fichier. Met tout en minuscules et vire les caractères spéciaux
+    pour le nom du fichier. Vire les caractères spéciaux
     et max 15 caractères"""
     chaine2 = ""
     for l in chaine:
@@ -140,12 +141,14 @@ def convertit_date_vers_python(chaine,liste_err):
         warning("La date : "+chaine+" est invalide !",liste_err)
         return ""
     else:
+        print(liste_err)
+
         debug("Conversion de la date "+chaine+". Découpage : "+str(liste),liste_err)
         try:
             date = datetime.date(int(liste[0]),int(liste[1]),int(liste[2]))
         except:
             date = ""
-            warning("Impossible de lire la date "+chaine+". Format accepté : aaaa-mm-jj",liste_err)
+            warning("Impossible de lire la date "+chaine+". Format accepté : aaaa-mm-jj ou aaaa/mm/jj",liste_err)
         return date
   
 # python -> json
@@ -157,13 +160,15 @@ def convertit_date_vers_texte(date):
         #return (str(date.year)+"-"+str(date.month)+"-"+str(date.day))
         return str(date)
 
-def delta_date(date1,datenaissance):
+def delta_date(date1,datenaissance, liste_err):
     """ renvoie le nombre de jours (entier) entre date1 et datenaissance format "datetime"
     datenaissance est supposée antérieure. Erreur sinon."""
+    if type(date1) != datetime.date or type(datenaissance) != datetime.date:
+        return -1
     d = date1 - datenaissance
     jours = d.days
     if jours<0:
-        warning("La différence entre les dates est négative... :/")
+        warning("Une des dates saisies ("+str(date1)+") est inférieure à la date de naissance (la donnée est donc ignorée)", liste_err)
         return -1
     return jours
 
@@ -349,12 +354,25 @@ def gere_configuration(data,liste_err, court=False):
             nbextradata = 1
         configuration["non_sauve"]["nbextradata"] = nbextradata
         
-        if data.get("calculextradata_type","") in CONFIG["liste_typedonnees"]:
+        if data.get("calculextradata_type","") in CONFIG["liste_typedonnees"]: # Si on a choisi un type de données à calculer
+            
             configuration["non_sauve"]["calculextradata_type"] = data.get("calculextradata_type","")
-            configuration["non_sauve"]["calculextradata_age"] = convertit_jours_vers_python(data.get("calculextradata_age","0j"),liste_err)
+            age = convertit_jours_vers_python(data.get("calculextradata_age","0j"),liste_err)
+            date = convertit_date_vers_python(data.get("calculextradata_date", ""), liste_err)
+            agecalcule = delta_date(date, configuration["naissance"], liste_err)
+            if configuration["naissance"] != "" and agecalcule != -1: # On garde plutôt la date
+                configuration["non_sauve"]["calculextradata_age"] = agecalcule
+                configuration["non_sauve"]["calculextradata_date"] = date
+            else: # On garde l'âge
+                configuration["non_sauve"]["calculextradata_age"] = age
+                if type(configuration["naissance"]) == datetime.date:
+#                    print(configuration["naissance"], type(configuration["naissance"]))
+                    configuration["non_sauve"]["calculextradata_date"] = configuration["naissance"] + datetime.timedelta(days=round(age))
+                else:
+                    configuration["non_sauve"]["calculextradata_date"] = None
         else:
             configuration["non_sauve"]["calculextradata_type"] = ""
-            # On ne met rien dans l'âge, pas la peine
+            # On ne met rien dans les autres données, pas la peine
         
         ctyped = data.get("calculextratemps_type","")
         if ctyped in CONFIG["liste_typedonnees"]:
@@ -373,12 +391,26 @@ def gere_configuration(data,liste_err, court=False):
         i=0
         while "repere_texte_"+str(i) in data: # Tant qu'il y a des trucs définis
             debug("Repère trouvé", liste_err)
+            jegardecerepere = False # On va passer à True uniquementsi tout va bien
+
             age=data.get("repere_age_"+str(i), "")
+            date=data.get("repere_date_"+str(i), "")
             trace=gere_checkbox(data.get("repere_trace_"+str(i), ""))
-            if age !="":
-                agec=convertit_jours_vers_python(age, liste_err)
+            affichedate=gere_checkbox(data.get("repere_affichedate_"+str(i), ""))
+
+            if date!="" and configuration['naissance'] != "": # Si on a saisi une date (et qu'il y a la date de naissance)
+                datepython = convertit_date_vers_python(date,liste_err)
+                if datepython !="": # Si la conversion s'est bien passée
+                    nbjours = delta_date(datepython, configuration['naissance'], liste_err)
+                    if nbjours != -1: # Si tout va bien jusque là
+                        jegardecerepere=True
+            elif age !="":
+                nbjours=convertit_jours_vers_python(age, liste_err)
+                jegardecerepere=True
+
+            if jegardecerepere:
                 texte = data.get("repere_texte_"+str(i), "") # Même si le texte est vide, osef
-                configuration["liste_reperes"].append({"typed": "age", "donnee": agec, "texte": texte, "trace": trace})
+                configuration["liste_reperes"].append({"typed": "age", "donnee": nbjours, "date": date, "texte": texte, "trace": trace, "affichedate":affichedate})
             i+=1
     
     return configuration   
@@ -404,19 +436,25 @@ def gere_donnees(data,naissance,typedonnee,liste_err):
     while "age_"+str(i) in data.keys():
         if data.get(typedonnee+"_"+str(i), "") != "": # si la donne de ce type existe
             donnee = convertit_donnee_vers_python(data[typedonnee+"_"+str(i)],typedonnee,liste_err)
-            age = data.get("age_"+str(i),"")
-            if age !="":
-                age = convertit_jours_vers_python(age,liste_err)
-                liste_donnees.append((age,donnee))
-            else: 
-                date = data.get("date_"+str(i),"")
+
+            ## Si une date est saisie, on la prend en priorité car c'est des entiers et les entiers c'est BIEN
+            date = data.get("date_"+str(i),"")
+            if date != "":
                 datep = convertit_date_vers_python(date,liste_err)
-                # on vérifie la date
-                if naissance == "":
-                    warning("La date de naissance n'a pas été précisée. Du coup on ne peut pas calculer l'âge de l'enfant le "+date,liste_err)
-                elif datep != "":  # la date est valide et on a une date de naissance
-                    age = delta_date(datep,naissance)
-                    liste_donnees.append((age,donnee))
+            else:
+                datep = ""
+            
+            if naissance != "" and datep != "": # On ne peut pas calculer l'âge si on n'a pas ces deux données      
+                age = delta_date(datep,naissance, liste_err)
+                if age != -1: # -1 signifie une erreur donc on ne garde pas la donnée
+                        liste_donnees.append((age,donnee))
+            else: # Sinon, on regarde si on a saisi l'âge
+                age = data.get("age_"+str(i),"")
+                if age == "":
+                    warning("gere_donnees : ni l'âge ni la date ne sont saisies... donnée ignorée", liste_err)
+                else:
+                    age = convertit_jours_vers_python(age,liste_err)
+                    liste_donnees.append((age,donnee))                    
         i+=1
         
     # Trier la liste
@@ -457,6 +495,11 @@ def gere_enfants_additionnels(data, files, liste_err):
                     # Le symbole et la couleur
                     symb2 = gere_symbole(data.get("symbole_donnees_"+str(i)))
                     coul2 = rgb_vers_tuple(data.get("couleur_donnees_"+str(i),""),CONFIG["couleurs"]["cadretxt"],liste_err)
+                    alias = data.get("alias_"+str(i), "")
+                    if alias != "": # Si l'alias n'est pas vide, il remplace le prénom
+                        print(conf2)
+                        conf2["nom"] = alias
+                    
                     enfant2 = eclate_donnees_additionnelles(conf2, ljours2, listes_donnees2, symb2, coul2)
                     enfants_add.append(enfant2)
         i+=1
@@ -484,8 +527,8 @@ def donnees_vers_json(l_jours,l_poids,l_jourst,l_taille,config):
     if gros_dico.get("naissance","") != "":
         gros_dico["naissance"] = convertit_date_vers_texte(gros_dico["naissance"])
         # Calcul de toutes les dates de données
-        l_dates_poids = [convertit_date_vers_texte( config["naissance"] + datetime.timedelta(days=jours) ) for jours in l_jours]
-        l_dates_taille = [convertit_date_vers_texte( config["naissance"] + datetime.timedelta(days=jours) ) for jours in l_jourst]
+        l_dates_poids = [convertit_date_vers_texte( config["naissance"] + datetime.timedelta(days=round(jours)) ) for jours in l_jours]
+        l_dates_taille = [convertit_date_vers_texte( config["naissance"] + datetime.timedelta(days=round(jours)) ) for jours in l_jourst]
         gros_dico["data_dates_poids"]= l_dates_poids
         gros_dico["data_dates_taille"] = l_dates_taille
             
index dac70bff4ec7867ceb2f2f83fceb57f3ac652863..b0b3a1d81b4eeab31fdf62519882f33330f2e646 100644 (file)
@@ -205,7 +205,11 @@ function ajoute_reperes()
        for(var i=nblignes; i<nblignes+nb_additionnel ; i++) 
        {
                var elt = document.createElement("li") ;
-               elt.innerHTML = 'Âge&nbsp;: <input class="data" type="text" name="repere_age_'+i+'" value=""> Texte associé&nbsp;: <input class="texte" type="text" name="repere_texte_'+i+'" value=""> Tracer&nbsp;: <input type="checkbox" name="repere_trace_'+i+'">' ;
+               elt.innerHTML = 'Âge&nbsp;: <input class="data" type="text" name="repere_age_'+i+'" value=""> \
+               ou date&nbsp;: <input type="date" name="repere_date_{{ i }}" value=""> \
+               Texte associé&nbsp;: <input class="texte" type="text" name="repere_texte_'+i+'" value=""> \
+               Tracer&nbsp;: <input type="checkbox" name="repere_trace_'+i+'">\
+               Afficher la date&nbsp;: <input type="checkbox" name="repere_affichedate_{{ i }}">' ;
                eltul.appendChild(elt) ;
        }
        
index 465366c5dd1e4f0a3556e3098fbd9b0ac301ed1d..faa8706941dd7bdfa197bb5e329bf7bf230df54e 100644 (file)
@@ -21,6 +21,7 @@ function appelle_image()
                        var liste_warnings = this.response.messages
                        var texte = this.response.export_txt;
                        var nomenfant = this.response.nomenfant ;
+                       var nomsenfantsplus = this.response.nomsenfantsplus ;
                        var calculextra = this.response.calculextra ;
 
                        // on affiche l'export des données
@@ -39,8 +40,9 @@ function appelle_image()
                                        document.getElementById('sectioncourbe').style.display = "block";
                                        document.getElementById('section_courbe_poids').style.display = "block" ;
                                        document.getElementById('courbe_poids').src = 'data:image/png;base64,'+(image_poids);
+                                       document.getElementById('courbe_poids').alt = 'Courbe de poids de '+nomenfant ;                                 
                                        boutondl = document.getElementById("courbe_dl_poids") ;
-                                       boutondl.setAttribute('onclick',"download_file('courbe_poids_"+nomenfant+".png', 'image/png;base64','"+image_poids +"')")
+                                       boutondl.setAttribute('onclick',"download_file('courbe_poids_"+nomenfant+nomsenfantsplus+".png', 'image/png;base64','"+image_poids +"')")
                                }
                                else {
                                        document.getElementById('section_courbe_poids').style.display = "none" ;
@@ -50,6 +52,7 @@ function appelle_image()
                                        document.getElementById('sectioncourbe').style.display = "block";
                                        document.getElementById('section_courbe_taille').style.display = "block" ;
                                        document.getElementById('courbe_taille').src = 'data:image/png;base64,'+(image_taille);
+                                       document.getElementById('courbe_taille').alt = 'Courbe de taille de '+nomenfant ;               
                                        boutondl = document.getElementById("courbe_dl_taille") ;
                                        boutondl.setAttribute('onclick',"download_file('courbe_taille_"+nomenfant+".png', 'image/png;base64','"+image_taille +"')")
                            }
index f72a5462fd8376eb6a1fb9d0f6eb3ae5c6dc1dfd..d25b5eb33b415e840b90b170fa0d31f2eb0fa89c 100644 (file)
@@ -124,6 +124,13 @@ nav {
        width:7em
 }
 
+/* Réponses dans la page liste */
+.reponses {
+       font-size: 0.9em ;
+       display: none;
+
+}
+
 /* Page changelog */
 #suite_changelog {
        display: none;
index 0f86ebe42e027d2fc87e5ac55bd51360b7b356b6..6dd3d00ec9693ea6747a34c0c5ec048c0df9185a 100644 (file)
@@ -2,11 +2,11 @@
 {% block contenu %}
 
 <p>Cet outil utilise les données de l'Organisation Mondiale de la Santé qu'on peut trouver
-<a href="https://www.who.int/childgrowth/standards/fr/">ici</a>.</p>
+<a href="https://www.who.int/tools/child-growth-standards" target="_blank">ici</a>.</p>
 
-<p>Ces données, ainsi que les images générées, sont sous licence <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/igo/">CC BY-NC-SA 3.0 IGO</a></p>
+<p>Ces données, ainsi que les images générées, sont sous licence <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/igo/" target="_blank">CC BY-NC-SA 3.0 IGO</a></p>
 
 
-<p>Cet outil, hors données de l'OMS est sous <a href="https://fr.wikipedia.org/wiki/Licence_MIT">licence MIT (licence X11)</a>. Le code source est disponible <a href="https://git.immae.eu/?p=perso/Denise/oms.git">là</a>.</p>
+<p>Cet outil, hors données de l'OMS est sous <a href="https://fr.wikipedia.org/wiki/Licence_MIT" target="_blank">licence MIT (licence X11)</a>. Le code source est disponible <a href="https://git.immae.eu/?p=perso/Denise/oms.git" target="_blank">là</a>.</p>
 
 {% endblock %}
index 6da2e96b166ec93bbb7bfb5409c9d2143b3e7105..bd791a968f28da41b35d289d146fbfd72b4be8a9 100644 (file)
@@ -1,14 +1,14 @@
 {% extends "base.html" %}
 {% block contenu %}
 <p>Si vous avez une question, un commentaire, une idée, vous pouvez me contacter à l'adresse suivante : oms arobase le nom de domaine.</p>
-<p>Vous pouvez également me retrouver sur le <a href="https://forum.lllfrance.org/">forum LLL</a>, sous le pseudo de Sekhmet.</p>
+<p>Vous pouvez également me retrouver sur le <a href="https://forum.lllfrance.org/" target="_blank">forum LLL</a>, sous le pseudo de Sekhmet.</p>
 
 <p><strong>Merci</strong> à celles et ceux qui m'ont aidée à mettre en place cet outil :
 <ul>
        <li>immae pour l'hébergement et l'aide technique,</li>
        <li>cerise pour le coup de peinture sur la façade,</li>
        <li>arcanmster pour le côté "je tape partout pour voir si ça casse",</li>
-       <li>les bêta-testeuses enthousiastes du forum LLL, entre autres MmeMarguerite, Maman-chat, bloom et Nerialka</li>
+       <li>les bêta-testeuses enthousiastes du forum LLL, entre autres MmeMarguerite, Maman-chat, bloom, Nerialka, ... et toutes les membres qui m'ont fait des retours et suggestions par la suite&nbsp;!</li>
 </ul></p>
 
 {% endblock %}
index 162f68dbb76b365f2f530ceff16fbeeb0efd698d..b382dd46b08a9d2f7675f0369802a845d4c928b5 100644 (file)
@@ -3,8 +3,8 @@
 <h2>Foire Aux Questions (FAQ)</h2>
 
 <div id="sommaire">
-<ul>{% for cat in lcateg %}
-<li><a href="#{{ cat }}">{{ cat }}</a></li>
+<ul>{% for i in range(lcateg|length) %}
+<li><a href="#{{ lcategsimple[i] }}">{{ lcateg[i] }}</a></li>
 {% endfor %}
 </ul>
 </div>
@@ -13,7 +13,7 @@
 {% for i in range(lcateg|length) %}
 {% set qr = tableqr[i] %}
 
-<h3 id="{{ lcateg[i] }}">{{ lcateg[i] }}</h3>
+<h3 id="{{ lcategsimple[i] }}">{{ lcateg[i] }}</h3>
 <ul>
        {% for (q,r) in qr %}
        <li><p><strong>Q : </strong>{{ q|safe }}</p>
index bbe381142e9497fb35743456dda7cf67aee39e85..93a95afa41160edf32b20c7d6ffd862b19da0540 100644 (file)
 
 
   <label for="fichier_donnees" class="icon_button">
-       <img src="static/icons/import.png">
+       <img src="static/icons/import.png" alt="Importer">
        <span class="icon_legend">Importer un fichier</span>
   </label>
   <input type="file" name="fichier_donnees" id="fichier_donnees" oninput="upload_file('form_import_donnees')">
 </form> 
 
 {% if "fichier_importe" in valform %}
+<p>Version du fichier de sauvegarde : 
 {% if "version" in valform %}
-<p>Version du fichier de sauvegarde : {{ valform.version }}.</p>{% endif %}
+{{ valform.version }}
+{% else %}
+Inférieure à 2.5{% endif %}
+</p>
 {% if "version" not in valform or valform.version < CONFIG.version %}
-<p class="petit">Note : La version du fichier de sauvegarde est inférieure à la version du site ({{ CONFIG.version}}), mais cela ne devrait pas générer de bug (normalement).
+<p class="petit">Note&nbsp;: La version du fichier de sauvegarde est inférieure à la version du site ({{ CONFIG.version}}), mais cela ne devrait pas générer de bug (normalement). <br>
+Si vous voulez mettre à jour votre fichier de sauvegarde, il suffit de ré-enregistrer les données une fois les courbes générées.
 </p>{% elif valform.version > CONFIG.version %}
-<p class="petit">Note : la version du fichier de sauvegarde ({{ valform.version }}) est <b>supérieure</b> à la version du site ({{ CONFIG.version}}). Vous avez probablement avez testé un fichier de sauvegarde de la version bêta sur la version normale du site. Sinon c'est que vous avez voyagé dans le temps, trifouillé le fichier de sauvegarde, ou... je ne sais pas. Il se peut qu'il y ait des bugs. Ou pas.</p>
+<p class="petit">Note&nbsp;: la version du fichier de sauvegarde ({{ valform.version }}) est <b>supérieure</b> à la version du site ({{ CONFIG.version}}). Vous avez probablement avez testé un fichier de sauvegarde de la version bêta sur la version normale du site. Sinon c'est que vous avez voyagé dans le temps, trifouillé le fichier de sauvegarde, ou... je ne sais pas. Il se peut qu'il y ait des bugs. Ou pas.</p>
 {% endif %}
 {% endif %}
 
@@ -37,7 +42,7 @@
 <h3>Informations sur l'enfant</h3>
 <div>
        <label for="reset_donnees" class="icon_button">
-               <img src="static/icons/trash.png">
+               <img src="static/icons/trash.png" alt="Effacer">
                <span class="icon_legend">Effacer les données du formulaire</span>
        </label>         
        <input type="reset" id="reset_donnees" value="Effacer les données du formulaire">      
@@ -49,7 +54,8 @@
 <li><label>Date de naissance&nbsp;: </label> <input type="date" name="naissance" value="{{ valform.naissance }}">
        <p id="changemode" class="petit"><span onclick="change_mode_dates('text')" class="bouton">Cliquer ici</span> pour saisir les dates comme du texte.</p> </li>
 <li>Prématuré ? <span class="petit">(expérimental)</span> <span class="bouton" onclick="affiche_cache('prema',this)">Afficher</span>
-<div id="prema"><p class="petit">Si l'enfant est né prématuré (avant 37 semaines d'aménorrhée), indiquer de « combien » en durée (même syntaxe que pour les âges, voir plus bas). Sinon, laisser 0j.</p>
+<div id="prema"><p class="petit">Si l'enfant est né prématuré (avant 37 semaines d'aménorrhée), indiquer de « combien » en durée (même syntaxe que pour les âges, voir plus bas). Sinon, laisser 0j. 
+<br>Remarque&nbsp;: les courbes OMS ne se prolongent pas pour la période prématurée, mais permettent de suivre la croissance de l'enfant une fois le terme atteint.</p>
 <label>Prématurité</label> <input type="text" class="data" name="prematurite" value="{{ valform.prematurite }}"> <input type="checkbox" name="agecorrige"{% if valform.agecorrige == "oui"%} checked{%endif%}> Afficher l'âge corrigé sur la courbe (plutôt que l'âge réel).
 </div></li>
 
@@ -64,7 +70,7 @@
 <p>Syntaxe pour l'âge&nbsp;: utiliser j, s, m, a comme des "unités" (jours, semaines, mois, années). Vous pouvez mixer les unités, par exemple "3a2m5j" pour 3 ans, 2 mois et 5 jours. Les espaces sont ignorées, et il faut saisir des nombres entiers.</p>
 <p>Saisir le poids en kilogrammes (par exemple "2.62" ou "2,62" pour 2 kilogrammes et 620 grammes), ou en grammes ("2620" par exemple).</p>
 <p class="donneesplus">Saisir la taille en centimètres. Note : il y a généralement un centimètre de moins quand on mesure l'enfant debout par rapport à allongé. On peut voir sur la courbe de référence une "cassure" à deux ans qui correspond au changement du type de mesure.</p>
-<p>Il faut saisir la date ou l'âge. Si les deux sont saisis, seul l'âge comptera.</p>
+<p>Il faut saisir la date ou l'âge. La date a priorité sur l'âge (si la date de naissance est saisie).</p>
 
 <p class="donneesplus">Si vous ne saisissez que des données de poids par exemple, la courbe de taille ne sera pas tracée (par défaut, voir préférences du graphique).</p>
 
                <ul id="ajoutereperecourbe">
                        {% for i in range(valform.liste_reperes | length) %}
                        <li>Âge&nbsp;: <input class="data" type="text" name="repere_age_{{ i }}" value="{{ valform.liste_reperes[i].donnee }}"> 
+                       ou date&nbsp;: <input type="date" name="repere_date_{{ i }}" value="{{ valform.liste_reperes[i].date }}">
                         Texte associé&nbsp;: <input class="texte" type="text" name="repere_texte_{{ i }}" value="{{ valform.liste_reperes[i].texte }}">
-                        Tracer&nbsp;: <input type="checkbox" name="repere_trace_{{ i }}" {% if valform.liste_reperes[i].trace %} checked {% endif %}></li>
+                        Tracer&nbsp;: <input type="checkbox" name="repere_trace_{{ i }}" {% if valform.liste_reperes[i].trace %} checked {% endif %}>
+                        Afficher la date&nbsp;: <input type="checkbox" name="repere_affichedate_{{ i }}" {% if valform.liste_reperes[i].affichedate %} checked {% endif %}>
+                        </li>
                        {% endfor %}
                        {% for j in range(valform.liste_reperes | length, valform.nb_reperes_mini) %}
                        <li>Âge&nbsp;: <input class="data" type="text" name="repere_age_{{ j }}" value=""> 
+                       ou date&nbsp;: <input type="date" name="repere_date_{{ i }}" value="">
                         Texte associé&nbsp;: <input class="texte" type="text" name="repere_texte_{{ j }}" value="">
-                        Tracer&nbsp;: <input type="checkbox" name="repere_trace_{{ j }}"></li>
+                        Tracer&nbsp;: <input type="checkbox" name="repere_trace_{{ j }}">
+                        Afficher la date&nbsp;: <input type="checkbox" name="repere_affichedate_{{ i }}"></li>
+
                        {% endfor %}
                </ul>
                
        {% for val in CONFIG.liste_typedonnees %}
        <option value="{{val}}">{{val}}</option>
        {% endfor %}
-       </select> à l'âge <input type="text" class="data" name="calculextradata_age" value="6m">
+       </select> à l'âge <input type="text" class="data" name="calculextradata_age">
+       ou à la date <input type="date" name="calculextradata_date">
        <input type="checkbox" name="calculextradata_trace"> ... et le voir sur le graphique.</li>
        
        <li>Calculer l'âge auquel l'enfant aura <input type="text" class="data" name="calculextratemps_val">
        <option value="{{ symb }}" {% if numero_enfant == loop.index  %} selected{% endif %}>{{ CONFIG.liste_symboles[symb] | safe}}</option>
        {% endfor %}
   </select> | 
-  Couleur&nbsp;: <input type="color" name="couleur_donnees_{{ numero_enfant }}" value="{{ valform.couleurs.cadretxt }}"></li>{% endfor %}
+  Couleur&nbsp;: <input type="color" name="couleur_donnees_{{ numero_enfant }}" value="{{ valform.couleurs.cadretxt }}"> | 
+  Alias <span class="petit">(remplace le prénom)</span>&nbsp;: <input type="text" name="alias_{{ numero_enfant }}"></li>{% endfor %}
   </ul>
   <p class="bouton" onclick="ajoute_enfants()" id="reveleenfants">Plus d'enfants O_o</p>
+  
 </div>
 
 
 <!--- Le grobouton -->
 <div>
        <span onclick="appelle_image()" class="icon_button">
-       <img src="static/icons/courbe.png">
+       <img src="static/icons/courbe.png" alt="Tracer les courbes">
        <span class="icon_legend">Je veux les courbes !</span></span>
        <span id="statut_courbes"></span>
 </div>
 
        <h2>Courbes</h2>
        <div id="section_courbe_poids">
-       <img id="courbe_poids">
+       <img id="courbe_poids" src="" alt="">
 
        <div id="courbe_dl_poids" class="icon_button">
-               <img src="static/icons/export.png">
+               <img src="static/icons/export.png" alt="Exporter la courbe de poids">
                <span class="icon_legend">Télécharger la courbe de poids</span>
        </div>
        </div>
 
        <div id="section_courbe_taille">
-       <img id="courbe_taille">
+       <img id="courbe_taille" src="" alt="">
        
        <div id="courbe_dl_taille" class="icon_button">
-               <img src="static/icons/export.png">
+               <img src="static/icons/export.png" alt="Exporter la courbe de taille">
                <span class="icon_legend">Télécharger la courbe de taille</span>
        </div>
        </div>
        <p>Vous pouvez télécharger les données afin de ne pas avoir à les re-saisir la prochaine fois.</p>
 
        <div id="export_dl" class="icon_button">
-               <img src="static/icons/export.png">
+               <img src="static/icons/export.png" alt="Exporter les données">
                <span class="icon_legend">Télécharger les données</span>
        </div>
-       <p>Si vous n'arrivez pas à télécharger les données, <a href='#export' onclick="affiche_export()">cliquez ici</a> pour les voir en texte clair&nbsp: il vous suffira de les copier/coller dans un fichier texte.</p>
+       <p>Si vous n'arrivez pas à télécharger les données, <a href='#export' onclick="affiche_export()">cliquez ici</a> pour les voir en texte clair&nbsp;: il vous suffira de les copier/coller dans un fichier texte.</p>
        <div id="export">
        <textarea readonly id="export_texte">
        </textarea>
index c39f2657b9c15217cd5cc167407b4639ca7e3ca0..ed5f980b584e26e47b20c9f491bfeb6961ef5183 100644 (file)
@@ -3,9 +3,10 @@
 from configuration import CONFIG
 import gestionOMS as oms
 import gestion_unites as u
-from gestion_donnees import calcule_max_graphique, convertit_jours_vers_python
+from gestion_donnees import calcule_max_graphique, convertit_jours_vers_python, simplifie_nom
 from gestion_erreurs import debug, erreur, warning
 from calculs_extrapole import calcule_donnee_extrapolee, calcule_age_extrapole, interpole_lineaire, interpole_lineaire_ordonnee, formate_resultat_donnee, formate_resultat_age, formate_interpole, formate_extrapole
+import datetime
 
 from numpy import arange
 
@@ -45,7 +46,7 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, e
             jour_maxi = conf["non_sauve"]["maxi"]+1
     else:
         jour_maxi = conf["maxi"]+1
-    
+        
     # Si on cherche à extrapoler au-delà
     if conf["non_sauve"]["calculextradata_type"] == typedonnee and conf["non_sauve"]["calculextradata_age"]>jour_maxi:
         jour_maxi =  int(conf["non_sauve"]["calculextradata_age"]) +1
@@ -73,7 +74,8 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, e
     debug("Prématurité : "+str(prema)+" age corrigé : "+conf["agecorrige"],liste_err)           
     if prema>0 and conf["agecorrige"] == "oui":
         l_jours = [j-prema for j in l_jours]
-        jour_maxi = jour_maxi - prema
+        jour_maxi = max(jour_maxi - prema, 2)
+        ## Si le jour maxi est <0 on met minimum 1 jour quand même !
 
 
     ###################### Conversion des unités ###########################""
@@ -173,6 +175,8 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, e
             if lj != []: # pas la peine de tracer si y'a rien à tracer
                 # Ajouter le nom de cet enfant-là
                 listenoms.append(conf_add["nom"])
+                # Le mot "courbe" doit être au pluriel du coup !
+                titre = titre.replace("Courbe ", "Courbes ")
                 lj_conv = u.convertit_tableau(lj,unite,liste_err)
                 debug("Tracé de la courbe additionnelle de "+conf_add["nom"]+" config : "+str(conf_add), liste_err)
                 ax.plot(lj_conv, ld, label=conf_add["nom"], color=conf_add["couleurcourbe"],marker=conf_add["symbole"])
@@ -181,9 +185,22 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, e
                     warning("Attention, tous les enfants n'ont pas le même sexe. La courbe de référence est celle de "+conf["nom"]+" et ne sera pas forcément pertinente pour les autres. Vous pouvez éventuellement essayer la courbe neutre. Remarque : cette alerte s'affichera quand même.", liste_err)
 
 
-        # Si y'a un nom on met "courbe de machin"
-        if listenoms != []:
-            titre += " de " +", ".join(listenoms)
+        # Si y'a un nom on met "courbe de machin, de bidule, d'alala, de truc"
+        for i in range(len(listenoms)):
+            # Mot de liaison : , ou et ?
+            if i>0 and i!=len(listenoms)-1:
+                titre += ", "
+            elif i>0 and i == len(listenoms) -1:
+                titre+= " et " 
+            else:
+                titre += " "
+            # Est-ce que la première lettre est une voyelle ?
+            lettre = simplifie_nom(listenoms[i]).lower()[0] 
+            if lettre in CONFIG["voyelles"]:
+                titre += "d'" 
+            else:
+                titre += "de "
+            titre += listenoms[i]
 
         if prema>0:
             titre+= ", préma de "+conf["prematurite"]
@@ -227,7 +244,11 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, e
                     # On va prendre les extrapolations de la dernière donnée jusqu'à l fin du graphe
                     debut_extr = int(l_jours[-conf["non_sauve"]["nbextradata"]])
                     i_debut_extr = dates_extrapole.index(debut_extr)
-                    i_fin_extr = dates_extrapole.index(jour_maxi)
+                    if jour_maxi >= dates_extrapole[-1]:
+                        i_fin_extr = len(dates_extrapole) -1
+                    else:
+                        i_fin_extr = dates_extrapole.index(jour_maxi)
+                    print("bla", i_debut_extr, i_fin_extr)
                     # Voilà ce qu'on veut tracer
                     dates_extrapole_trace = dates_extrapole[i_debut_extr:i_fin_extr+1]
                     donnees_extrapole_trace = donnees_extrapole[i_debut_extr:i_fin_extr+1]                
@@ -248,11 +269,11 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, e
                     else:
                         message=formate_interpole()
                     
-                    texte = formate_resultat_donnee(conf["non_sauve"]["calculextradata_age"], r, typedonnee, message, liste_err)
+                    texte = formate_resultat_donnee(conf["non_sauve"]["calculextradata_age"], conf["non_sauve"]["calculextradata_date"], r, typedonnee, message, liste_err)
                     debug("calcul de la donnée extrapolée : "+texte, liste_err)
                     if texte!="":
                         liste_extracalculs.append(texte)
-                        print(liste_extracalculs)
+                        #print(liste_extracalculs)
                         # Ajouter le trait ?
                         if conf["non_sauve"]["calculextradata_trace"] == "oui":
                             dessine_guides(conf["non_sauve"]["calculextradata_age"], r, conf["couleurs"]["cadretxt"], unite, ax, liste_err)
@@ -261,14 +282,23 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, e
                 if conf["non_sauve"]["calculextratemps_type"] == typedonnee:
                     # interpolation
                     r = interpole_lineaire_ordonnee(l_jours,l_poids,conf["non_sauve"]["calculextratemps_val"], liste_err)
+                    if type(conf["naissance"]) == datetime.date:
+                        rdate = conf["naissance"] + datetime.timedelta(days=r)
+                    else:
+                        rdate = None
+                    
                     if r==-1:
                         # ça sera donc une extrapolation
-                        r = calcule_age_extrapole(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextratemps_val"], liste_err)          
+                        r = calcule_age_extrapole(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextratemps_val"], liste_err)
+                        if type(conf["naissance"]) == datetime.date:
+                            rdate = conf["naissance"] + datetime.timedelta(days=round(r))
+                        else:
+                            rdate = None
                         message=formate_extrapole(conf["non_sauve"]["nbextradata"])
                     else:
                         message=formate_interpole()
-                    
-                    texte = formate_resultat_age(r, conf["non_sauve"]["calculextratemps_val"], typedonnee, message, liste_err)
+                    print(r, rdate)
+                    texte = formate_resultat_age(r, rdate, conf["non_sauve"]["calculextratemps_val"], typedonnee, message, liste_err)
                     
                     #r = calcule_age_extrapole(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextratemps_val"], typedonnee, liste_err)
                     if texte!="":
@@ -309,16 +339,23 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, e
     poids_max = poids_max * 1.05
        
 
+
     ### Repères additionnels éventuels.
     #reperes est une liste qui contient des dictionnaires avec "typed" (type de donnée : âge, etc), "donnee" :
     #la donnée (en jours pour l'âge), et "texte": le texte à mettre sur le repère en question.
     #Pour tracer des repères verticaux (horizontaux plus tard) sur la courbe.
+
+    debug("Échelle ok. Voir s'il y a des repères supplémentaires : "+str(conf["liste_reperes"]), liste_err)
+    
     for rep in conf["liste_reperes"]:
         if rep.get("trace", "") == "oui": # SI on veut tracer
             agec = u.convertitunite(rep["donnee"], unite, liste_err)
             # Tracé de la ligne verticale
             ax.vlines(agec, poids_min, poids_max, linestyles="dashed", color=conf["couleurs"]["cadretxt"])
-            # Tracé éventuel du texte
+            # date à afficher ?
+            if rep["affichedate"] == "oui" and rep["date"] != "":
+                ax.text(agec, poids_min,rep["date"]+" ", rotation=90, verticalalignment='top', horizontalalignment='center', color=conf["couleurs"]["cadretxt"], fontstyle="italic")
+            # Si y'a un texte à afficher
             if rep["texte"] != "":
                 ax.text(agec, poids_min, " "+rep["texte"], rotation=90, verticalalignment='bottom', horizontalalignment='right', color=conf["couleurs"]["cadretxt"])
 
@@ -343,14 +380,19 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, e
         
         ax.set_yticks(echellemajeure, minor=False)
         ax.set_yticks(echellemineure, minor=True)
-    
         # échelle en temps
-        pas=u.choix_echelle_temps(unite, age_maxi)
+        
+        # Le jour minimum n'est pas forcément zéro !
+        age_mini = min(l_jours[0], 0)
+        
+        pas=u.choix_echelle_temps(unite, age_maxi - age_mini)
         debug("pas choisis pour l'échelle en x : "+str(pas), liste_err)    
+        
+
     
-        echellemajeure = arange(0,age_maxi, pas[0])
+        echellemajeure = arange(age_mini,age_maxi, pas[0])
         if pas[1] >0:
-            echellemineure = arange(0,age_maxi, pas[1])
+            echellemineure = arange(age_mini,age_maxi, pas[1])
         else:
             echellemineure = []
         ax.set_xticks(echellemajeure, minor=False)