2 # -*- coding: utf-8 -*-
4 from configuration
import CONFIG
,DEFAUT
5 from gestion_erreurs
import debug
, warning
, erreur
, initialise_erreurs
6 from gestion_couleurs
import rgb_vers_tuple
, tuple_vers_rgb
7 from gestion_unites
import choix_unite
13 ### Les données "tournent" selon :
14 ### python -> json -> (export/import) -> formulaire HTML -> données POST -> python etc
16 ############ Fonctions de conversion
18 def convertit_jours_vers_python(chaine
,liste_err
):
19 """ convertit une chaine de type 1a 3m 1s 10j en jours
20 Renvoie un nombre de jours en float
21 Si un des caractères n'est ni un nombre, ni une lettre "autorisée" ni une espace,
22 on affiche un warning et on ignore ce caractère
24 # debug("conversion de "+chaine+" vers un nb de jours",liste_err)
29 chainenombre
+= lettre
31 if lettre
== 'a' or lettre
== 'A':
32 # On a trouvé l'année, on ajoute tout ce qui est trouvé jusque là
33 agejours
+= int(chainenombre
)*CONFIG
["jours_dans_annee"]
35 elif lettre
== 'm' or lettre
== 'M':
37 agejours
+= int(chainenombre
)*CONFIG
["jours_dans_mois"]
39 elif lettre
== 's' or lettre
== 'S':
41 agejours
+= int(chainenombre
)*CONFIG
["jours_dans_semaine"]
43 elif lettre
== 'j' or lettre
== 'J':
45 agejours
+= int(chainenombre
)
48 # autre caractère : bizarre ?
49 warning("problème à la conversion de "+chaine
+". Caractère invalide : "+lettre
,liste_err
)
50 # à la fin s'il reste qqch on le garde dans les jours
51 if chainenombre
!= "":
52 agejours
+= int(chainenombre
)
54 warning("L'âge est négatif !",liste_err
)
56 # debug("On a convertit ! Résultat : "+str(agejours),liste_err)
60 def convertit_age_vers_texte(nombre
):
61 """ convertit un nombre de jours en un truc plus lisible en mois, années, jours
62 et renvoie une chaîne sous la forme 3a2m1j par exemple"""
63 annees
= int(nombre
/ CONFIG
["jours_dans_annee"])
64 restant
= nombre
- annees
*CONFIG
["jours_dans_annee"]
65 mois
= int(restant
/CONFIG
["jours_dans_mois"])
66 #print("mois : ",mois, ", restant : ",nombre - mois*CONFIG["jours_dans_mois"])
67 jours
= round(nombre
- mois
*CONFIG
["jours_dans_mois"] - annees
*CONFIG
["jours_dans_annee"])
71 chaine
+= str(annees
)+"a"
73 chaine
+= str(mois
)+"m"
74 if jours
>0 or nombre
==0: # si c'est la naissance, faut bien écrire 0j quand même
75 chaine
+= str(jours
)+"j"
78 ##########################
80 # fonction qui calcule "auto" le maxi du graphique en fonction du max
81 def calcule_max_graphique(l_jours
):
82 """ calcule l'age maxi sur le graphique"""
84 return CONFIG
["jours_defaut_donneesvides"]
86 jour_maxi
= max(l_jours
)# pas la peine d'aller très au delà du jour max
87 jour_maxi
= int(jour_maxi
* 1.2)+3 # on rajoute un peu
91 def simplifie_nom(chaine
):
92 """ simplifie le nom chaine afin d'en faire une extension
93 pour le nom du fichier. Met tout en minuscules et vire les caractères spéciaux
94 et max 15 caractères"""
99 chaine2
= unidecode
.unidecode(chaine2
)
102 def convertit_donnee_vers_python(chaine
,typedonnee
,liste_err
):
103 """ convertit une chaine vers un float qui est le type donnee voulu.
104 La virgule peut être . ou , et on vire d'éventuels espaces.
105 Taille invalide : on renvoie 0 avec un warning.
106 Si la chaine est en fait déjà au format float, on laisse tel quel"""
107 if type(chaine
) == float:
109 chaine2
= chaine
.replace(",",".")
110 chaine2
= chaine2
.replace(" ","")
114 donnee
= float(chaine2
)
116 warning(typedonnee
+" impossible à lire : "+chaine
,liste_err
)
119 # Pour le poids, un cas particulier
120 if typedonnee
== "poids" and donnee
> CONFIG
["poids_maxi_conversion"]:
121 donnee
= donnee
/1000 # conversion en grammes
122 if not( 0<=donnee
<CONFIG
[typedonnee
+"_maxi"]):
123 warning(typedonnee
+" incohérent(e) : "+str(donnee
),liste_err
)
128 #########################
131 def convertit_date_vers_python(chaine
,liste_err
):
132 """ prend une chaine comme renvoyée par un champ de formulaire date
133 aaaa-mm-jj et en fait une date python
134 renvoie "" si ne marche pas.
135 Si jamais la date est au format avec des / ça devrait passer aussi."""
137 liste
= chaine
.split("/")
139 liste
= chaine
.split("-")
141 warning("La date : "+chaine
+" est invalide !",liste_err
)
144 debug("Conversion de la date "+chaine
+". Découpage : "+str(liste
),liste_err
)
146 date
= datetime
.date(int(liste
[0]),int(liste
[1]),int(liste
[2]))
149 warning("Impossible de lire la date "+chaine
+". Format accepté : aaaa-mm-jj",liste_err
)
153 def convertit_date_vers_texte(date
):
154 """ convertit une date python en format texte aaaa-mm-jj"""
158 #return (str(date.year)+"-"+str(date.month)+"-"+str(date.day))
161 def delta_date(date1
,datenaissance
, liste_err
):
162 """ renvoie le nombre de jours (entier) entre date1 et datenaissance format "datetime"
163 datenaissance est supposée antérieure. Erreur sinon."""
164 if type(date1
) != datetime
.date
or type(datenaissance
) != datetime
.date
:
166 d
= date1
- datenaissance
169 warning("Une des dates saisies ("+str(date1
)+") est inférieure à la date de naissance (la donnée est donc ignorée)", liste_err
)
175 ################### On regroupe tout ce qui gère les données en une fonction
177 def web_vers_python(data
,liste_err
, court
=False):
178 """ prend en argument le dictionnaire de requête et renvoie la config, et les
180 court : si True est précisé, on ne met que le nom dans la config (enfant
183 # Régler la configuration
184 config
= gere_configuration(data
,liste_err
, court
)
186 # récupérer les données
189 for typed
in CONFIG
["liste_typedonnees"]:
190 listes_jours
[typed
],listes_donnees
[typed
] = gere_donnees(data
,config
["naissance"],typed
,liste_err
)
192 # Si on veut extrapoler au-delà du jour maxi, on adapte
194 # Si on a choisi la même échelle de données
195 if config
.get("memechelle") == "oui":
196 config
["non_sauve"]["maxi"] = calcule_max_graphique([j
for lj
in listes_jours
.values() for j
in lj
])
197 # En cas d'extrapolation, on prend le maxi
198 if config
["non_sauve"]["calculextradata_type"] !="" and config
["non_sauve"]["calculextradata_age"]>config
["non_sauve"]["maxi"]:
199 config
["non_sauve"]["maxi"] = int(config
["non_sauve"]["calculextradata_age"]) +1
200 config
["non_sauve"]["unite"] = choix_unite(config
["non_sauve"]["maxi"])
202 return (config
,listes_jours
,listes_donnees
)
206 ########### Fonctions qui gèretn les données web vers python
208 def gere_checkbox(chaine
):
209 """ prend en arg une chaine, et renvoie "oui" si c'est "on" (sortie de la checkbox)
210 et chaîne vide si n'importe quoi d'autre"""
216 def gere_symbole(chaine
):
217 """ prend en arg une chaîne genre "o", ">" et vérifie si c'est un symbole valide.
218 Renvoie ce symbole-là ou le défaut"""
219 if chaine
in CONFIG
["liste_symboles"]:
222 return DEFAUT
["symbole"]
224 def gere_configuration(data
,liste_err
, court
=False):
225 """ prend en argument le dictionnaire de requête (configuration imparfaite), et
226 construit le dictionnaire de configuration qui va bien.
227 Vérifie que chaque entrée est cohérente évidemment.
228 court : si mis à True, on ne met que le nom dans la configuraion,
229 ainsi que la date de naissance et le sexe"""
231 configuration
= {"non_sauve": {}
}
233 # Pour le nom, osef qu'il soit vide
234 nom
= data
.get("nom","")
235 # Par contre s'il est trop long on le tronque
236 configuration
["nom"] = nom
[:CONFIG
["longueur_max_nom_bebe"]]
238 naissance
= data
.get("naissance","")
240 naissance
= convertit_date_vers_python(naissance
,liste_err
)
241 configuration
["naissance"] = naissance
243 sexe
= data
.get("sexe","")
244 if not (sexe
in ["F","M","N"]):
245 warning("Le sexe de l'enfant est invalide. "+sexe
,liste_err
)
247 configuration
["sexe"] = sexe
251 prematurite
= data
.get("prematurite","")
252 j
= convertit_jours_vers_python(prematurite
,liste_err
)
253 configuration
["prematurite"] = convertit_age_vers_texte(j
)
255 configuration
["agecorrige"] = gere_checkbox(data
.get("agecorrige",""))
257 # Type de courbe. Au pire on met P
258 tyc
= data
.get("typecourbe","")
259 if not (tyc
in ["P","Z"]):
261 configuration
["typecourbe"] = tyc
264 unite
= data
.get("unite","")
265 if not (unite
in CONFIG
["liste_unites"]):
267 #warning("L'unité "+unite+" n'est pas reconnue !",liste_err)
268 configuration
["unite"] = unite
271 configuration
["grille"] = gere_checkbox(data
.get("grille",""))
273 # tracer ou non les courbes vides
274 configuration
["tracevide"] = gere_checkbox(data
.get("tracevide",""))
276 # Même échelle sur tous les graphiques
277 configuration
["memechelle"] = gere_checkbox(data
.get("memechelle",""))
280 # maxi. 0 signifie qu'on veut pas de maxi
281 maxi
= data
.get("maxi","")
283 configuration
["maxi"] = 0
285 configuration
["maxi"] = int(convertit_jours_vers_python(maxi
,liste_err
))
287 # dimensions du graphique
288 largeur
= data
.get("largeur","")
290 largeur
= DEFAUT
["largeur_graphique"]
293 largeur
= int(largeur
)
295 warning("La largeur "+largeur
+"est invalide !",liste_err
)
296 largeur
= DEFAUT
["largeur_graphique"]
297 if largeur
> CONFIG
["largeur_graphique_max"]:
298 largeur
= CONFIG
["largeur_graphique_max"]
299 warning("Largeur du graphique trop grande !",liste_err
)
300 elif largeur
< CONFIG
["largeur_graphique_min"]:
301 largeur
= CONFIG
["largeur_graphique_min"]
302 warning("Largeur du graphique trop petite !",liste_err
)
303 configuration
["largeur"] = largeur
305 hauteur
= data
.get("hauteur","")
307 hauteur
= DEFAUT
["hauteur_graphique"]
310 hauteur
= int(hauteur
)
312 warning("La hauteur "+hauteur
+"est invalide !",liste_err
)
313 hauteur
= DEFAUT
["hauteur_graphique"]
314 if hauteur
> CONFIG
["hauteur_graphique_max"]:
315 hauteur
= CONFIG
["hauteur_graphique_max"]
316 warning("Hauteur du graphique trop grande !",liste_err
)
317 elif hauteur
< CONFIG
["hauteur_graphique_min"]:
318 hauteur
= CONFIG
["hauteur_graphique_min"]
319 warning("Hauteur du graphique trop petite !",liste_err
)
320 configuration
["hauteur"] = hauteur
322 # existence et position de la légende
323 configuration
["legende"] = gere_checkbox(data
.get("legende",""))
325 positionlegende
= data
.get("positionlegende","")
326 if not(positionlegende
in ['upper left','upper right','lower left','lower right']):
327 positionlegende
= "upper left"
328 configuration
["positionlegende"] = positionlegende
330 configuration
["couleurs"] = {}
332 for clecouleur
in DEFAUT
["couleurs"]:
333 coul
= rgb_vers_tuple(data
.get("couleur_"+clecouleur
,""),DEFAUT
["couleurs"].get(clecouleur
, ""),liste_err
)
334 configuration
["couleurs"][clecouleur
] = coul
337 configuration
["symbole"] = gere_symbole( data
.get("symbole", ""))
339 configuration
["non_sauve"]["grilleamelio"] = gere_checkbox(data
.get("grilleamelio",""))
342 #### La partie extrapolation n'a pas besoin d'être sauvée
343 configuration
["non_sauve"]["prolongercourbes"] = gere_checkbox(data
.get("prolongercourbes",""))
345 # Valeur par défaut : 1
346 debug(data
.get("nbextradata", "aaargh"), liste_err
)
347 nbextradata
= data
.get("nbextradata",1)
349 nbextradata
= int(nbextradata
)
351 warning("Le nombre de données sur lequel on extrapole est invalide : "+nbextradata
, liste_err
)
353 configuration
["non_sauve"]["nbextradata"] = nbextradata
355 if data
.get("calculextradata_type","") in CONFIG
["liste_typedonnees"]: # Si on a choisi un type de données à calculer
357 configuration
["non_sauve"]["calculextradata_type"] = data
.get("calculextradata_type","")
358 age
= convertit_jours_vers_python(data
.get("calculextradata_age","0j"),liste_err
)
359 date
= convertit_date_vers_python(data
.get("calculextradata_date", ""), [[],[]])
360 agecalcule
= delta_date(date
, configuration
["naissance"], liste_err
)
361 if configuration
["naissance"] != "" and agecalcule
!= -1: # On garde plutôt la date
362 configuration
["non_sauve"]["calculextradata_age"] = agecalcule
363 configuration
["non_sauve"]["calculextradata_date"] = date
364 else: # On garde l'âge
365 configuration
["non_sauve"]["calculextradata_age"] = age
366 if type(configuration
["naissance"]) == datetime
.date
:
367 # print(configuration["naissance"], type(configuration["naissance"]))
368 configuration
["non_sauve"]["calculextradata_date"] = configuration
["naissance"] + datetime
.timedelta(days
=round(age
))
370 configuration
["non_sauve"]["calculextradata_date"] = None
372 configuration
["non_sauve"]["calculextradata_type"] = ""
373 # On ne met rien dans les autres données, pas la peine
375 ctyped
= data
.get("calculextratemps_type","")
376 if ctyped
in CONFIG
["liste_typedonnees"]:
377 configuration
["non_sauve"]["calculextratemps_type"] = ctyped
378 configuration
["non_sauve"]["calculextratemps_val"] = convertit_donnee_vers_python(data
.get("calculextratemps_val",""), ctyped
, liste_err
)
380 configuration
["non_sauve"]["calculextratemps_type"] = ""
382 # Tracer les calculs sur la grille
383 configuration
["non_sauve"]["calculextradata_trace"] = gere_checkbox(data
.get("calculextradata_trace"))
384 configuration
["non_sauve"]["calculextratemps_trace"] = gere_checkbox(data
.get("calculextratemps_trace"))
387 ### Gestion des repères additionnels
388 configuration
["liste_reperes"] = []
390 while "repere_texte_"+str(i
) in data
: # Tant qu'il y a des trucs définis
391 debug("Repère trouvé", liste_err
)
392 jegardecerepere
= False # On va passer à True uniquementsi tout va bien
394 age
=data
.get("repere_age_"+str(i
), "")
395 date
=data
.get("repere_date_"+str(i
), "")
396 trace
=gere_checkbox(data
.get("repere_trace_"+str(i
), ""))
397 affichedate
=gere_checkbox(data
.get("repere_affichedate_"+str(i
), ""))
399 if date
!="" and configuration
['naissance'] != "": # Si on a saisi une date (et qu'il y a la date de naissance)
400 datepython
= convertit_date_vers_python(date
,liste_err
)
401 if datepython
!="": # Si la conversion s'est bien passée
402 nbjours
= delta_date(datepython
, configuration
['naissance'], liste_err
)
403 if nbjours
!= -1: # Si tout va bien jusque là
406 nbjours
=convertit_jours_vers_python(age
, liste_err
)
410 texte
= data
.get("repere_texte_"+str(i
), "") # Même si le texte est vide, osef
411 configuration
["liste_reperes"].append({"typed": "age", "donnee": nbjours, "date": date, "texte": texte, "trace": trace, "affichedate":affichedate}
)
418 ## web vers python : données
419 def gere_donnees(data
,naissance
,typedonnee
,liste_err
):
420 """ prend en argument le dictionnaire de requête, et la date de
421 naissance (éventuellement vide), et construit deux listes :
422 l_jours et l_data correspondantes.
423 Il faut donner en argument le type de données : voir
424 CONFIG["liste_typedonnees"]"""
425 if typedonnee
not in CONFIG
["liste_typedonnees"]:
426 warning("gere_donnees : le type de données : "+typedonnee
+" est invalide !! Types acceptés : "+str(CONFIG
["liste_typedonnees"]),liste_err
)
429 # On construit une liste de couples d'abord
433 # On va chercher si y'a des données à donnee_i
434 while "age_"+str(i
) in data
.keys():
435 if data
.get(typedonnee
+"_"+str(i
), "") != "": # si la donne de ce type existe
436 donnee
= convertit_donnee_vers_python(data
[typedonnee
+"_"+str(i
)],typedonnee
,liste_err
)
438 ## Si une date est saisie, on la prend en priorité car c'est des entiers et les entiers c'est BIEN
439 date
= data
.get("date_"+str(i
),"")
440 datep
= convertit_date_vers_python(date
,liste_err
)
442 if naissance
!= "" and datep
!= "": # On ne peut pas calculer l'âge si on n'a pas ces deux données
443 age
= delta_date(datep
,naissance
, liste_err
)
444 if age
!= -1: # -1 signifie une erreur donc on ne garde pas la donnée
445 liste_donnees
.append((age
,donnee
))
446 else: # Sinon, on regarde si on a saisi l'âge
447 age
= data
.get("age_"+str(i
),"")
449 warning("gere_donnees : ni l'âge ni la date ne sont saisies... donnée ignorée", liste_err
)
451 age
= convertit_jours_vers_python(age
,liste_err
)
452 liste_donnees
.append((age
,donnee
))
456 liste_donnees
.sort(key
=lambda x
: x
[0])
459 l_jours
= [x
[0] for x
in liste_donnees
]
460 l_donnee
= [x
[1] for x
in liste_donnees
]
462 return (l_jours
,l_donnee
)
464 # web vers python : enfants additionnels
465 def gere_enfants_additionnels(data
, files
, liste_err
):
466 """ data est le dictionnaire de requête.
467 files est le dictionnaire des fichiers (flask.request.files).
468 Renvoie les enfants additionnels sous forme de liste de dictionnaires :
469 {typed: (conf, lj, ldonnees)}
470 Dans conf y'a les infos qu'il faut pour tracer la courbe additionnelle voulue.
473 enfants_add
= [] # Enfants additionnels
474 # Les enfants additionnels commencent à 2 (puis 3, 4, etc)
476 while "couleur_donnees_"+str(i
) in data
: # Tant qu'il y a des données de ce type
477 if 'fichier_donnees_'+str(i
) in files
: # Un enfant à ajouter
478 fichier
= files
["fichier_donnees_"+str(i
)]
479 chaine
= fichier
.read() # On récupère la chaîne
480 if len(chaine
)>=5: # Si elle a une longueur à peu près raisonnable
481 debug("Un fichier de données additionnel trouvé", liste_err
)
482 formulaire_2
= fichier_json_vers_configdonnees(chaine
, liste_err
)
483 if formulaire_2
=={}:
484 warning("Le fichier de données additionnel est vide ou mal formaté", liste_err
)
486 debug("Form 2 : "+str(formulaire_2
), liste_err
)
487 # Récupérer sous forme python
488 conf2
, ljours2
, listes_donnees2
= web_vers_python(formulaire_2
,liste_err
, court
=True)
489 debug("Form 2 données travaillées "+str(ljours2
)+str(listes_donnees2
), liste_err
)
490 # Le symbole et la couleur
491 symb2
= gere_symbole(data
.get("symbole_donnees_"+str(i
)))
492 coul2
= rgb_vers_tuple(data
.get("couleur_donnees_"+str(i
),""),CONFIG
["couleurs"]["cadretxt"],liste_err
)
493 enfant2
= eclate_donnees_additionnelles(conf2
, ljours2
, listes_donnees2
, symb2
, coul2
)
494 enfants_add
.append(enfant2
)
504 #### export vers json
506 def donnees_vers_json(l_jours
,l_poids
,l_jourst
,l_taille
,config
):
507 """ retourne le json à renvoyer"""
508 gros_dico
= copy
.deepcopy(config
)
509 gros_dico
["version"] = CONFIG
["version"]
510 l_jours2
= [convertit_age_vers_texte(d
) for d
in l_jours
]
511 l_jourst2
= [convertit_age_vers_texte(d
) for d
in l_jourst
]
512 gros_dico
["data_j"] = l_jours2
513 gros_dico
["data_p"] = l_poids
514 gros_dico
["data_jours_taille"] = l_jourst2
515 gros_dico
["data_taille"] = l_taille
516 # gérer la date de naissance
517 if gros_dico
.get("naissance","") != "":
518 gros_dico
["naissance"] = convertit_date_vers_texte(gros_dico
["naissance"])
519 # Calcul de toutes les dates de données
520 l_dates_poids
= [convertit_date_vers_texte( config
["naissance"] + datetime
.timedelta(days
=round(jours
)) ) for jours
in l_jours
]
521 l_dates_taille
= [convertit_date_vers_texte( config
["naissance"] + datetime
.timedelta(days
=round(jours
)) ) for jours
in l_jourst
]
522 gros_dico
["data_dates_poids"]= l_dates_poids
523 gros_dico
["data_dates_taille"] = l_dates_taille
527 gros_dico
["maxi"] = convertit_age_vers_texte(gros_dico
["maxi"])
529 for i
in range(len(gros_dico
["liste_reperes"])):
530 gros_dico
["liste_reperes"][i
]["donnee"] = convertit_age_vers_texte(gros_dico
["liste_reperes"][i
]["donnee"])
532 for clecouleur
in DEFAUT
["couleurs"]:
533 gros_dico
["couleurs"][clecouleur
] = tuple_vers_rgb(gros_dico
["couleurs"][clecouleur
])
535 # Enlever ce qui ne se sauvegarde pas si y'a
536 if "non_sauve" in gros_dico
:
537 del gros_dico
["non_sauve"]
539 return json
.dumps(gros_dico
, indent
=2,ensure_ascii
=False )
541 def fusionne_donnees(listes_jours
,listes_donnees
, listes_dates
):
542 """ prend en argument deux dicos de listes. Chaque liste de jours est associée à une liste
543 de données (par la même clé de type de données). Il faut les fusionner pour avoir une liste de dictionnaires, de type
544 {"age":truc, "donnee1":truc, "donnee2":truc, ...} triée par ordre de jours. Si jamais une des données est vide,
545 le champ du dictionnaire n'est pas rempli
546 Le troisième paquet de listes (les dates) peut être vide ou bien simiaire : même clés."""
549 """ teste si les listes sont toutes vides """
550 for l
in lj
.values():
556 """ renvoie la clé de la liste où il y a le min """
557 cle_mini
= CONFIG
["liste_typedonnees"][0]
558 for (cle
,liste
) in lj
.items():
559 if lj
[cle_mini
]== []:
562 if convertit_jours_vers_python(lj
[cle
][0],initialise_erreurs())<convertit_jours_vers_python(lj
[cle_mini
][0],initialise_erreurs()):
567 while not(fini(listes_jours
)):
568 typedonnee
= mini(listes_jours
)
569 # On extrait les données dans les deux listes (jours et données)
570 jour
= listes_jours
[typedonnee
].pop(0)
571 donnee
= listes_donnees
[typedonnee
].pop(0)
573 if liste_f
== [] or jour
!= liste_f
[-1]["age"]: # Si le jour est un "nouveau" jour
574 liste_f
.append({"age":jour}
)
575 # On met à jour l'élément (ou on l'ajoute)
576 liste_f
[-1][typedonnee
] = donnee
578 # Si il y a une date associée, on la met !
579 if listes_dates
[typedonnee
] != []:
580 date
= listes_dates
[typedonnee
].pop(0)
581 liste_f
[-1]["date"] = convertit_date_vers_texte(date
)
587 ### COnversion json vers formulaire
588 # Json -> formulaire HTML
589 def fichier_json_vers_configdonnees(chaine
,liste_err
):
590 """ prend le json importé (chaine) et l'exporte vers les valeurs du formulaire
591 Renvoyé sous forme de dictionnaire (mais adapté au formulaire web)"""
592 debug("json vers config : Prêt à interpréter le json",liste_err
)
594 valform
= json
.loads(chaine
)
596 erreur("Impossible de lire le fichier json !",liste_err
)
598 # Il faut maintenant récupérer les l_jours et l_poids puis les remettre
599 # sous forme de age_i et poids_i
604 for typed
in CONFIG
["liste_typedonnees"]:
605 if typed
== "poids": # pour la rétrocompatibilité
606 listes_jours
[typed
] = valform
.get("data_j",[])
607 listes_donnees
[typed
] = valform
.get("data_p",[])
608 listes_dates
[typed
] = valform
.get("data_dates_"+typed
,[])
610 listes_jours
[typed
] = valform
.get("data_jours_"+typed
,[])
611 listes_donnees
[typed
] = valform
.get("data_"+typed
,[])
612 listes_dates
[typed
] = valform
.get("data_dates_"+typed
,[])
615 debug("Avant fusion : listes jours "+str(listes_jours
),liste_err
)
616 liste_donnees
= fusionne_donnees(listes_jours
,listes_donnees
, listes_dates
)
617 debug("Fusion de listes ok. Liste moche : "+str(liste_donnees
),liste_err
)
618 for i
in range(len(liste_donnees
)):
619 for (cle
,val
) in liste_donnees
[i
].items():
620 valform
[cle
+"_"+str(i
)] = val
622 valform
["nb_data"] = max(len(liste_donnees
) +2,DEFAUT
["nb_data"])
628 #### Pour l'insertion d'une 2e (ou plus) courbe sur le graphique, ue fonction qui sépare tout ça
629 def eclate_donnees_additionnelles(conf
, ljours
, ldonnees
, symb
, couleur
):
630 """ conf est la config (on ne garde que le nom) pour un enfant additionnel,
631 ljours et ldonnees les dictionnaires de listes contenant les données.
632 symb est le symbole choisi pour cette courbe additionnelle (déjà vérifié)
633 On fabrique un joli dictionnaire typed -> (conf, lj, ldonnee) avec le nom de l'enfant,
634 et les données pour chaque typed"""
635 #print("test conf avant "+str(ldonnees)+str(ljours))
638 conf
["symbole"] = symb
# On ajoute le symbole additionnel
639 conf
["couleurcourbe"] = couleur
# la couleur
640 for typed
in CONFIG
["liste_typedonnees"]:
641 retour
[typed
] = (conf
, ljours
[typed
], ldonnees
[typed
])
643 #print("test "+str(retour))