#!/usr/bin/env python3
# -*- coding: utf-8 -*-
-from configuration import *
-from gestion_erreurs import *
+from configuration import CONFIG,DEFAUT
+from gestion_erreurs import debug, warning, erreur, initialise_erreurs
+from gestion_couleurs import rgb_vers_tuple, tuple_vers_rgb
+from gestion_unites import choix_unite
import datetime
import json
import unidecode
+import copy
+### Les données "tournent" selon :
+### python -> json -> (export/import) -> formulaire HTML -> données POST -> python etc
############ Fonctions de conversion
Si un des caractères n'est ni un nombre, ni une lettre "autorisée" ni une espace,
on affiche un warning et on ignore ce caractère
"""
+# debug("conversion de "+chaine+" vers un nb de jours",liste_err)
chainenombre = ""
agejours = 0.
for lettre in chaine:
else:
if lettre == 'a' or lettre == 'A':
# On a trouvé l'année, on ajoute tout ce qui est trouvé jusque là
- agejours += int(chainenombre)*jours_dans_annee
+ agejours += int(chainenombre)*CONFIG["jours_dans_annee"]
chainenombre = ""
elif lettre == 'm' or lettre == 'M':
# On a trouvé le mois
- agejours += int(chainenombre)*jours_dans_mois
+ agejours += int(chainenombre)*CONFIG["jours_dans_mois"]
chainenombre = ""
elif lettre == 's' or lettre == 'S':
# la semaine
- agejours += int(chainenombre)*jours_dans_semaine
+ agejours += int(chainenombre)*CONFIG["jours_dans_semaine"]
chainenombre = ""
elif lettre == 'j' or lettre == 'J':
# On a trouvé le jour
if agejours<0:
warning("L'âge est négatif !",liste_err)
agejours = 0
+# debug("On a convertit ! Résultat : "+str(agejours),liste_err)
return agejours
+# python -> json
def convertit_age_vers_texte(nombre):
""" convertit un nombre de jours en un truc plus lisible en mois, années, jours
et renvoie une chaîne sous la forme 3a2m1j par exemple"""
- annees = int(nombre / jours_dans_annee)
- restant = nombre - annees*jours_dans_annee
- mois = int(restant/jours_dans_mois)
- jours= round(nombre - mois*jours_dans_mois - annees*jours_dans_annee)
+ annees = int(nombre / CONFIG["jours_dans_annee"])
+ restant = nombre - annees*CONFIG["jours_dans_annee"]
+ mois = int(restant/CONFIG["jours_dans_mois"])
+ jours= round(nombre - mois*CONFIG["jours_dans_mois"] - annees*CONFIG["jours_dans_annee"])
chaine = ""
if annees >0:
if jours>0 or nombre ==0: # si c'est la naissance, faut beien écrire 0j quand même
chaine += str(jours)+"j"
return chaine
+
##########################
+# fonction qui calcule "auto" le maxi du graphique en fonction du max
+def calcule_max_graphique(l_jours):
+ """ calcule l'age maxi sur le graphique"""
+ if l_jours == []:
+ return CONFIG["jours_defaut_donneesvides"]
+ else:
+ jour_maxi = max(l_jours)# pas la peine d'aller très au delà du jour max
+ jour_maxi = int(jour_maxi* 1.2)+3 # on rajoute un peu
+ return jour_maxi
+
def simplifie_nom(chaine):
""" simplifie le nom chaine afin d'en faire une extension
chaine2 = unidecode.unidecode(chaine2)
return chaine2[:15]
-def convertit_poids_vers_python(chaine,liste_err):
- """ convertit une chaine vers un float qui est le poids.
- On gère notamment la virgule, et on enlève les espaces
- Un poids invalide -> on renvoie 0 avec un warning"""
+def convertit_donnee_vers_python(chaine,typedonnee,liste_err):
+ """ convertit une chaine vers un float qui est le type donnee voulu.
+ La virgule peut être . ou , et on vire d'éventuels espaces.
+ Taille invalide : on renvoie 0 avec un warning.
+ Si la chaine est en fait déjà au format float, on laisse tel quel"""
+ if type(chaine) == float:
+ return chaine
chaine2 = chaine.replace(",",".")
chaine2 = chaine2.replace(" ","")
+
try:
- poids = float(chaine2)
+ donnee = float(chaine2)
except:
- warning("Poids impossible à lire : "+chaine,liste_err)
- poids = 0
- if not( 0<=poids<poids_maxi):
- warning("Poids incohérent : "+str(poids),liste_err)
- poids = 0
- return poids
+ warning(typedonnee+" impossible à lire : "+chaine,liste_err)
+ donnee = 0
+
+ # Pour le poids, un cas particulier
+ if typedonnee == "poids" and donnee > CONFIG["poids_maxi_conversion"]:
+ donnee = donnee/1000 # conversion en grammes
+ if not( 0<=donnee<CONFIG[typedonnee+"_maxi"]):
+ warning(typedonnee+" incohérent(e) : "+str(donnee),liste_err)
+ donnee = 0
+ return donnee
-#def convertit_poids_vers_texte(poids):
-# """ convertit un poids vers du texte. Rien à dire là pour l'instant """
-# return str(poids)
#########################
+# web -> python
def convertit_date_vers_python(chaine,liste_err):
""" prend une chaine comme renvoyée par un champ de formulaire date
aaaa-mm-jj et en fait une date python
warning("La date : "+chaine+" est invalide !",liste_err)
return ""
else:
+ 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,liste_err)
+ warning("Impossible de lire la date "+chaine+". Format accepté : aaaa-mm-jj",liste_err)
return date
-
+
+# python -> json
def convertit_date_vers_texte(date):
""" convertit une date python en format texte aaaa-mm-jj"""
if date == "":
d = date1 - datenaissance
jours = d.days
if jours<0:
- erreur_continue("La différence entre les dates est négative... :/")
+ warning("La différence entre les dates est négative... :/")
return -1
return jours
-########### Fonctions qui gèretn les données
+################### On regroupe tout ce qui gère les données en une fonction
+
+def web_vers_python(data,liste_err, court=False):
+ """ prend en argument le dictionnaire de requête et renvoie la config, et les
+ tableaux de donnée
+ court : si True est précisé, on ne met que le nom dans la config (enfant
+ additionnel)"""
+
+ # Régler la configuration
+ config = gere_configuration(data,liste_err, court)
+
+ # récupérer les données
+ listes_jours = {}
+ listes_donnees = {}
+ for typed in CONFIG["liste_typedonnees"]:
+ listes_jours[typed],listes_donnees[typed] = gere_donnees(data,config["naissance"],typed,liste_err)
+ # Si on veut extrapoler au-delà du jour maxi, on adapte
+
+ # Si on a choisi la même échelle de données
+ if config.get("memechelle") == "oui":
+ config["non_sauve"]["maxi"] = calcule_max_graphique([j for lj in listes_jours.values() for j in lj])
+ # En cas d'extrapolation, on prend le maxi
+ if config["non_sauve"]["calculextradata_type"] !="" and config["non_sauve"]["calculextradata_age"]>config["non_sauve"]["maxi"]:
+ config["non_sauve"]["maxi"] = int(config["non_sauve"]["calculextradata_age"]) +1
+ config["non_sauve"]["unite"] = choix_unite(config["non_sauve"]["maxi"])
+
+ return (config,listes_jours,listes_donnees)
-def gere_configuration(data,liste_err):
+
+
+########### Fonctions qui gèretn les données web vers python
+
+def gere_checkbox(chaine):
+ """ prend en arg une chaine, et renvoie "oui" si c'est "on" (sortie de la checkbox)
+ et chaîne vide si n'importe quoi d'autre"""
+ if chaine == "on":
+ return "oui"
+ else:
+ return ""
+
+def gere_symbole(chaine):
+ """ prend en arg une chaîne genre "o", ">" et vérifie si c'est un symbole valide.
+ Renvoie ce symbole-là ou le défaut"""
+ if chaine in CONFIG["liste_symboles"]:
+ return chaine
+ else:
+ return DEFAUT["symbole"]
+
+def gere_configuration(data,liste_err, court=False):
""" prend en argument le dictionnaire de requête (configuration imparfaite), et
construit le dictionnaire de configuration qui va bien.
- Vérifie que chaque entrée est cohérente évidemment."""
- configuration = {}
+ Vérifie que chaque entrée est cohérente évidemment.
+ court : si mis à True, on ne met que le nom dans la configuraion,
+ ainsi que la date de naissance et le sexe"""
+ # Initialisation
+ configuration = {"non_sauve": {}}
# Pour le nom, osef qu'il soit vide
nom = data.get("nom","")
# Par contre s'il est trop long on le tronque
- configuration["nom"] = nom[:longueur_max_nom_bebe]
-
+ configuration["nom"] = nom[:CONFIG["longueur_max_nom_bebe"]]
+
+ naissance = data.get("naissance","")
+ if naissance !="":
+ naissance = convertit_date_vers_python(naissance,liste_err)
+ configuration["naissance"] = naissance
+
sexe = data.get("sexe","")
if not (sexe in ["F","M","N"]):
warning("Le sexe de l'enfant est invalide ! "+sexe,liste_err)
sexe = "N"
configuration["sexe"] = sexe
+
+ if not(court):
+
+ prematurite = data.get("prematurite","")
+ j = convertit_jours_vers_python(prematurite,liste_err)
+ configuration["prematurite"] = convertit_age_vers_texte(j)
+
+ configuration["agecorrige"] = gere_checkbox(data.get("agecorrige",""))
+
+ # Type de courbe. Au pire on met P
+ tyc = data.get("typecourbe","")
+ if not (tyc in ["P","Z"]):
+ tyc = "P"
+ configuration["typecourbe"] = tyc
+
+ # unité
+ unite = data.get("unite","")
+ if not (unite in CONFIG["liste_unites"]):
+ unite = ""
+ #warning("L'unité "+unite+" n'est pas reconnue !",liste_err)
+ configuration["unite"] = unite
- naissance = data.get("naissance","")
- if naissance !="":
- naissance = convertit_date_vers_python(naissance,liste_err)
- configuration["naissance"] = naissance
-
- # Type de courbe. Au pire on met P
- tyc = data.get("typecourbe","")
- if not (tyc in ["P","Z"]):
- tyc = "P"
- configuration["typecourbe"] = tyc
+ # grille
+ configuration["grille"] = gere_checkbox(data.get("grille",""))
- # unité
- unite = data.get("unite","")
- if not (unite in liste_unites_valides):
- unite = ""
- #warning("L'unité "+unite+" n'est pas reconnue !",liste_err)
- configuration["unite"] = unite
+ # tracer ou non les courbes vides
+ configuration["tracevide"] = gere_checkbox(data.get("tracevide",""))
+
+ # Même échelle sur tous les graphiques
+ configuration["memechelle"] = gere_checkbox(data.get("memechelle",""))
- # grille
- grille = data.get("grille","")
- if grille != "on":
- configuration["grille"] = ""
- else:
- configuration["grille"] = "oui"
- # maxi. 0 signifie qu'on veut pas de maxi
- maxi = data.get("maxi","")
- if maxi == "":
- configuration["maxi"] = 0
- else:
- configuration["maxi"] = convertit_jours_vers_python(maxi,liste_err)
+ # maxi. 0 signifie qu'on veut pas de maxi
+ maxi = data.get("maxi","")
+ if maxi == "":
+ configuration["maxi"] = 0
+ else:
+ configuration["maxi"] = int(convertit_jours_vers_python(maxi,liste_err))
+
+ # dimensions du graphique
+ largeur = data.get("largeur","")
+ if largeur == "":
+ largeur = DEFAUT["largeur_graphique"]
+ else:
+ try:
+ largeur = int(largeur)
+ except:
+ warning("La largeur "+largeur+"est invalide !",liste_err)
+ largeur = DEFAUT["largeur_graphique"]
+ if largeur > CONFIG["largeur_graphique_max"]:
+ largeur = CONFIG["largeur_graphique_max"]
+ warning("Largeur du graphique trop grande !",liste_err)
+ elif largeur < CONFIG["largeur_graphique_min"]:
+ largeur = CONFIG["largeur_graphique_min"]
+ warning("Largeur du graphique trop petite !",liste_err)
+ configuration["largeur"] = largeur
+
+ hauteur = data.get("hauteur","")
+ if hauteur == "":
+ hauteur = DEFAUT["hauteur_graphique"]
+ else:
+ try:
+ hauteur = int(hauteur)
+ except:
+ warning("La hauteur "+hauteur+"est invalide !",liste_err)
+ hauteur = DEFAUT["hauteur_graphique"]
+ if hauteur > CONFIG["hauteur_graphique_max"]:
+ hauteur = CONFIG["hauteur_graphique_max"]
+ warning("Hauteur du graphique trop grande !",liste_err)
+ elif hauteur < CONFIG["hauteur_graphique_min"]:
+ hauteur = CONFIG["hauteur_graphique_min"]
+ warning("Hauteur du graphique trop petite !",liste_err)
+ configuration["hauteur"] = hauteur
+
+ # existence et position de la légende
+ configuration["legende"] = gere_checkbox(data.get("legende",""))
+
+ positionlegende = data.get("positionlegende","")
+ if not(positionlegende in ['upper left','upper right','lower left','lower right']):
+ positionlegende = "upper left"
+ configuration["positionlegende"] = positionlegende
+
+ configuration["couleurs"] = {}
+ # gérer les couleurs
+ for clecouleur in DEFAUT["couleurs"]:
+ coul = rgb_vers_tuple(data.get("couleur_"+clecouleur,""),CONFIG["couleurs"][clecouleur],liste_err)
+ configuration["couleurs"][clecouleur] = coul
+
+ # symbole
+ configuration["symbole"] = gere_symbole( data.get("symbole", ""))
- # dimensions du graphique
- largeur = data.get("largeur","")
- if largeur == "":
- largeur = largeur_graphique
- else:
- try:
- largeur = int(largeur)
- except:
- warning("La largeur "+largeur+"est invalide !",liste_err)
- largeur = largeur_graphique
- if largeur > largeur_graphique_max:
- largeur = largeur_graphique_max
- warning("Largeur trop grande !",liste_err)
- elif largeur < largeur_graphique_min:
- largeur = largeur_graphique_min
- warning("Largeur trop petite !",liste_err)
- configuration["largeur"] = largeur
+ configuration["non_sauve"]["grilleamelio"] = gere_checkbox(data.get("grilleamelio",""))
- hauteur = data.get("hauteur","")
- if hauteur == "":
- hauteur = hauteur_graphique
- else:
- try:
- hauteur = int(hauteur)
- except:
- warning("La hauteur "+hauteur+"est invalide !",liste_err)
- hauteur = hauteur_graphique
- if hauteur > hauteur_graphique_max:
- hauteur = hauteur_graphique_max
- warning("Hauteur trop grande !",liste_err)
- elif hauteur < hauteur_graphique_min:
- hauteur = hauteur_graphique_min
- warning("Hauteur trop petite !",liste_err)
- configuration["hauteur"] = hauteur
- # existence et position de la légende
- legende = data.get("legende","")
- if legende =="":
- legende = "non"
- elif legende=="on":
- legende = "oui"
- else:
- legende = "oui"
- configuration["legende"] = legende
+ #### La partie extrapolation n'a pas besoin d'être sauvée
+ configuration["non_sauve"]["prolongercourbes"] = gere_checkbox(data.get("prolongercourbes",""))
- positionlegende = data.get("positionlegende","")
- if not(positionlegende in ['upper left','upper right','lower left','lower right']):
- positionlegende = "upper left"
- configuration["positionlegende"] = positionlegende
+ # Valeur par défaut : 1
+ debug(data.get("nbextradata", "aaargh"), liste_err)
+ nbextradata = data.get("nbextradata",1)
+ try:
+ nbextradata = int(nbextradata)
+ except:
+ warning("Le nombre de données sur lequel on extrapole est invalide : "+nbextradata, liste_err)
+ nbextradata = 1
+ configuration["non_sauve"]["nbextradata"] = nbextradata
+
+ if data.get("calculextradata_type","") in CONFIG["liste_typedonnees"]:
+ 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)
+ else:
+ configuration["non_sauve"]["calculextradata_type"] = ""
+ # On ne met rien dans l'âge, pas la peine
+
+ ctyped = data.get("calculextratemps_type","")
+ if ctyped in CONFIG["liste_typedonnees"]:
+ configuration["non_sauve"]["calculextratemps_type"] = ctyped
+ configuration["non_sauve"]["calculextratemps_val"] = convertit_donnee_vers_python(data.get("calculextratemps_val",""), ctyped, liste_err)
+ else:
+ configuration["non_sauve"]["calculextratemps_type"] = ""
+
+ # Tracer les calculs sur la grille
+ configuration["non_sauve"]["calculextradata_trace"] = gere_checkbox(data.get("calculextradata_trace"))
+ configuration["non_sauve"]["calculextratemps_trace"] = gere_checkbox(data.get("calculextratemps_trace"))
+
return configuration
-
-#def configuration_vers_texte(config):
-# """ exporte le texte associé à une configuration
-# on dumpe simplement sauf pour maxi """
-# texte = "# Section configuration\n"
-# for (cle,val) in config.items():
-# if cle != "maxi":
-# texte+= cle + "=" + str(val) + "\n"
-# else:
-# texte+= cle + "=" + convertit_age_vers_texte(val)+"\n"
-# texte +="\n"
-# return texte
-
-def gere_donneespoids(data,naissance,liste_err):
- """ prend en argument le dictionnaire de requête, et la date de naissance
- (éventuellement vide) et construit les deux listes l_jours et l_poids"""
- # On construit la liste des couples
+
+## web vers python : données
+def gere_donnees(data,naissance,typedonnee,liste_err):
+ """ prend en argument le dictionnaire de requête, et la date de
+ naissance (éventuellement vide), et construit deux listes :
+ l_jours et l_data correspondantes.
+ Il faut donner en argument le type de données : voir
+ CONFIG["liste_typedonnees"]"""
+ if typedonnee not in CONFIG["liste_typedonnees"]:
+ warning("gere_donnees : le type de données : "+typedonnee+" est invalide !! Types acceptés : "+str(CONFIG["liste_typedonnees"]),liste_err)
+ return ([],[])
+
+ # On construit une liste de couples d'abord
liste_donnees = []
i = 0
- # On va chercher si y'a des données à poids_i
- while "poids_"+str(i) in data.keys():
- if data["poids_"+str(i)] != "":
- poids = convertit_poids_vers_python(data["poids_"+str(i)],liste_err)
+ # On va chercher si y'a des données à donnee_i
+ while typedonnee+"_"+str(i) in data.keys():
+ if data[typedonnee+"_"+str(i)] != "":
+ 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,poids))
+ liste_donnees.append((age,donnee))
else:
date = data.get("date_"+str(i),"")
datep = convertit_date_vers_python(date,liste_err)
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,poids))
+ liste_donnees.append((age,donnee))
i+=1
# Trier la liste
# splitter la liste
l_jours = [x[0] for x in liste_donnees]
- l_poids = [x[1] for x in liste_donnees]
-
- return (l_jours,l_poids)
+ l_donnee = [x[1] for x in liste_donnees]
-
-#def donnees_poids_vers_texte(l_jours,l_poids):
-# """ retourne le texte correspondant aux données de poids """
-# texte = "# Section données\n"
-#
-# for i in range(len(l_poids)):
-# texte +=convertit_age_vers_texte(l_jours[i])+","+convertit_poids_vers_texte(l_poids[i])+"\n"
-#
-# texte+="\n"
-# return texte
-
+ return (l_jours,l_donnee)
+# python vers Json
+#### export vers json
-
-def donnees_vers_json(l_jours,l_poids,config):
+def donnees_vers_json(l_jours,l_poids,l_jourst,l_taille,config):
""" retourne le json à renvoyer"""
- gros_dico = config.copy()
+ gros_dico = copy.deepcopy(config)
l_jours2 = [convertit_age_vers_texte(d) for d in l_jours]
+ l_jourst2 = [convertit_age_vers_texte(d) for d in l_jourst]
gros_dico["data_j"] = l_jours2
gros_dico["data_p"] = l_poids
+ gros_dico["data_jours_taille"] = l_jourst2
+ gros_dico["data_taille"] = l_taille
# gérer la date de naissance
if gros_dico.get("naissance","") != "":
gros_dico["naissance"] = convertit_date_vers_texte(gros_dico["naissance"])
# gérer l'age maxi
gros_dico["maxi"] = convertit_age_vers_texte(gros_dico["maxi"])
+ # gérer les couleurs
+ for clecouleur in DEFAUT["couleurs"]:
+ gros_dico["couleurs"][clecouleur] = tuple_vers_rgb(gros_dico["couleurs"][clecouleur])
+
+ # Enlever ce qui ne se sauvegarde pas si y'a
+ if "non_sauve" in gros_dico:
+ del gros_dico["non_sauve"]
return json.dumps(gros_dico, indent=2,ensure_ascii=False )
-#def fichier_texte_vers_configdonnees(fichier,liste_err):
-# """ prend le texte importé et l'exporte vers configuration et données
-# sous forme de valeurs du formulaire """
-#
-# valform = {}
-# indice_formulaire = 0 # l'indice du formulaire pour les données : age_1, date_1, poids_1 etc
-# num_ligne = 0
-# lignes = fichier.readlines()
-# for ligne in lignes:
-# num_ligne +=1
-# ligne = str(ligne,"utf8")
-# ligne = ligne.rstrip("\n")
-# if ligne != "" and ligne[0] != "#" and not(ligne.isspace()): # les lignes commençant par # sont des commentaires
-# # On essaie de partitionner pour voir
-# (var,egal,val) = ligne.partition("=")
-# if egal == "=": # c'est une ligne de config
-# valform[var] = val
-# else:
-# (age,virgule,poids) = ligne.partition(",") # On partitionne avec ,
-# if virgule == ",":
-# # c'est une ligne de data
-# valform["age_"+str(indice_formulaire)] = age
-# valform["poids_"+str(indice_formulaire)] = poids
-# indice_formulaire +=1
-#
-# else:
-# warning("La ligne "+str(num_ligne)+" n'est pas reconnue et sera ignorée : <"+ligne+">",liste_err)
-#
-# #le nb max du formulaire
-# valform["nb_data"] = max(indice_formulaire +2,nombre_lignes_form)
-#
-# return valform
-
-def fichier_json_vers_configdonnees(fichier,liste_err):
- """ prend le json importé et l'exporte vers les valeurs du formulaire """
- chaine = fichier.read()
- valform = json.loads(chaine)
+def fusionne_donnees(listes_jours,listes_donnees):
+ """ prend en argument deux dicos de listes. Chaque liste de jours est associée à une liste
+ 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
+ ("age":truc, "donnee1":truc, "donnee2":truc, ...) triée par ordre de jours. Si jamais une des données est vide,
+ le champ du dictionnaire n'est pas rempli"""
+
+ def fini(lj):
+ """ teste si les listes sont toutes vides """
+ for l in lj.values():
+ if l!=[]:
+ return False
+ return True
+
+ def mini(lj):
+ """ renvoie la clé de la liste où il y a le min """
+ cle_mini = CONFIG["liste_typedonnees"][0]
+ for (cle,liste) in lj.items():
+ if lj[cle_mini]== []:
+ cle_mini = cle
+ elif lj[cle] != []:
+ if convertit_jours_vers_python(lj[cle][0],initialise_erreurs())<convertit_jours_vers_python(lj[cle_mini][0],initialise_erreurs()):
+ cle_mini = cle
+ return cle_mini
+
+ liste_f = []
+ while not(fini(listes_jours)):
+ typedonnee = mini(listes_jours)
+ # On extrait les données dans les deux listes (jours et données)
+ jour = listes_jours[typedonnee].pop(0)
+ donnee = listes_donnees[typedonnee].pop(0)
+ if liste_f == [] or jour != liste_f[-1]["age"]: # Si le jour est un "nouveau" jour
+ liste_f.append({"age":jour})
+ # On met à jour l'élément
+ liste_f[-1][typedonnee] = donnee
+
+ return liste_f
+
+
+### COnversion json vers formulaire
+# Json -> formulaire HTML
+def fichier_json_vers_configdonnees(chaine,liste_err):
+ """ prend le json importé (chaine) et l'exporte vers les valeurs du formulaire
+ Renvoyé sous forme de dictionnaire (mais adapté au formulaire web)"""
+ debug("json vers config : Prêt à interpréter le json",liste_err)
+ try:
+ valform = json.loads(chaine)
+ except :
+ erreur("Impossible de lire le fichier json !",liste_err)
+ return {}
# Il faut maintenant récupérer les l_jours et l_poids puis les remettre
# sous forme de age_i et poids_i
- l_jours= valform.get("data_j",[])
- l_poids=valform.get("data_p",[])
- if len(l_poids) != len(l_jours):
- warning("Lecture du json : les données sont incohérentes (listes de taille différentes et/ou pb de lecture")
- long = min(len(l_jours),len(l_poids))
- else:
- long = len(l_jours)
- for i in range(long):
- valform["age_"+str(i)] = l_jours[i]
- valform["poids_"+str(i)] = l_poids[i]
+
+ listes_jours = {}
+ listes_donnees = {}
+ for typed in CONFIG["liste_typedonnees"]:
+ if typed == "poids": # pour la rétrocompatibilité
+ listes_jours[typed] = valform.get("data_j",[])
+ listes_donnees[typed] = valform.get("data_p",[])
+ else:
+ listes_jours[typed] = valform.get("data_jours_"+typed,[])
+ listes_donnees[typed] = valform.get("data_"+typed,[])
+
+ debug("Avant fusion : listes jours "+str(listes_jours),liste_err)
+ liste_donnees = fusionne_donnees(listes_jours,listes_donnees)
+ debug("Fusion de listes ok. Liste moche : "+str(liste_donnees),liste_err)
+ for i in range(len(liste_donnees)):
+ for (cle,val) in liste_donnees[i].items():
+ valform[cle+"_"+str(i)] = val
- valform["nb_data"] = max(long +2,nombre_lignes_form)
+ valform["nb_data"] = max(len(liste_donnees) +2,DEFAUT["nb_data"])
return valform
-
\ No newline at end of file
+
+#### Pour l'insertion d'une 2e (ou plus) courbe sur le graphique, ue fonction qui sépare tout ça
+def eclate_donnees_additionnelles(conf, ljours, ldonnees, symb):
+ """ conf est la config (on ne garde que le nom) pour un enfant additionnel,
+ ljours et ldonnees les dictionnaires de listes contenant les données.
+ symb est le symbole choisi pour cette courbe additionnelle (déjà vérifié)
+ On fabrique un joli dictionnaire typed -> (conf lj, ldonnee) avec le nom de l'enfant,
+ et les données pour chaque typed"""
+
+ retour = {}
+ conf["symbole"] = symb # On ajoute le symbole additionnel
+ for typed in CONFIG["liste_typedonnees"]:
+ retour[typed] = (conf, ljours[typed], ldonnees[typed])
+
+ return retour
\ No newline at end of file